如何向仅支持ANSI的C++函数传入含Unicode字符的文件路径?
Detours库ANSI函数处理Unicode路径的问题
摘要
尝试将包含Unicode(UTF-16)字符的DLL路径传入Detours库4.0.1版本中仅支持ANSI字符的DetourCreateProcessWithDllEx和DetourCreateProcessWithDlls函数,遇到路径兼容问题。
问题详情
这两个函数的lpDllName和*rlpDlls参数类型为LPCSTR,不支持宽字符。官方说明原因是“导入表没有宽字符版本”,相关议题已锁定,需寻找替代方案。
通过withdll示例代码测试发现,失败根源在LoadLibraryExA调用阶段——该函数会提前检查DLL导出项,若调用失败,后续Detours函数大概率也会失败。虽然LoadLibraryExW能通过检查,但失败会延迟到Detours函数调用阶段。
目前观察到部分简单Unicode路径(如E:\test\Chäröcter Teßt或E:\test\Bjørn)可正常工作,但包含复杂Unicode字符的路径(如E:\test\Bölükbaşı)会失败:LoadLibraryExA返回错误码126(“找不到指定模块”),Detours调用返回错误码3(“系统找不到指定路径”)。
测试代码
以下是从withdll示例中提取的精简测试代码(可移除Detours代码,仅通过LoadLibraryExA验证问题):
#include <windows.h> #include <detours.h> #include <strsafe.h> int CDECL main(int argc, char** argv) { LPCSTR rpszDllRaw = "detoursSimpleDll64.dll"; // 同目录下存在该文件及32位版本 LPCSTR szExe = "HelloWorld.exe"; // 同目录下存在该文件 LPCSTR rpszDllOut; CHAR szDllPath[1024]; PCHAR pszFilePart = NULL; if (!GetFullPathNameA(rpszDllRaw, ARRAYSIZE(szDllPath), szDllPath, &pszFilePart)) { printf("Error - GetFullPathNameA: %s is not a valid path name\n", rpszDllRaw); return 9002; } DWORD c = (DWORD)strlen(szDllPath) + 1; PCHAR psz = new CHAR[c]; StringCchCopyA(psz, c, szDllPath); rpszDllOut = psz; HMODULE hDll = LoadLibraryExA(rpszDllOut, NULL, DONT_RESOLVE_DLL_REFERENCES); if (hDll == NULL) { printf("Error - LoadLibraryExA: %s failed to load (error %ld).\n", rpszDllOut, GetLastError()); return 9003; } else { printf("LoadLibraryExA succeeded for %s\n", rpszDllOut); } // Detours相关代码开始 STARTUPINFOA si; PROCESS_INFORMATION pi; CHAR szCommand[2048]; CHAR szFullExe[1024] = "\0"; PCHAR pszFileExe = NULL; DWORD dwFlags = CREATE_DEFAULT_ERROR_MODE | CREATE_SUSPENDED; ZeroMemory(&si, sizeof(si)); ZeroMemory(&pi, sizeof(pi)); si.cb = sizeof(si); szCommand[0] = L'\0'; SetLastError(0); SearchPathA(NULL, szExe, ".exe", ARRAYSIZE(szFullExe), szFullExe, &pszFileExe); if (!DetourCreateProcessWithDllExA(szFullExe[0] ? szFullExe : NULL, szCommand, NULL, NULL, TRUE, dwFlags, NULL, NULL, &si, &pi, rpszDllOut, NULL)) { DWORD dwError = GetLastError(); printf("DetourCreateProcessWithDllEx failed: %ld\n", dwError); ExitProcess(9009); } printf("DetourCreateProcessWithDllEx succeeded for %s and %s\n", szFullExe, rpszDllOut); ResumeThread(pi.hThread); WaitForSingleObject(pi.hProcess, INFINITE); DWORD dwResult = 0; if (!GetExitCodeProcess(pi.hProcess, &dwResult)) { printf("GetExitCodeProcess failed: %ld\n", GetLastError()); return 9010; } dllPathFinal = NULL; delete dllPathFinal; return dwResult; }
内容的提问来源于stack exchange,提问作者sp00n
相关产品推荐
相关产品推荐

