Reputation: 1098
TL;DR
I'm trying to pass the path to a file (e.g. DLL), which contains unicode (UTF-16) characters, to a C++ function, which only supports the "A" variant, so it takes only ANSI characters.
More precisely it's DetourCreateProcessWithDllEx resp. DetourCreateProcessWithDlls from the Microsoft Detours library.
Their lpDllName
resp. *rlpDlls
parameters are of the type LPCSTR
, so no wide characters can be used. According to this issue, this seems to be because the "import table does not have a wide character version".
The issue has been locked in the meantime, so maybe someone here has an idea on how I could still pass the path with unicode characters to the function.
When looking at the withdll sample code, you probably don't even need to load the Detours library, as the point of failure is already at the LoadLibraryExA
call, which checks if the DLL has the correct exports.
Yes, using the unicode variant LoadLibraryExW
would work for this, but the point of failure is then just delayed until the DetourCreateProcessWithDllEx
call, so I guess Detours itself isn't necessary to test this. If the call to LoadLibraryExA
fails, then the Detours functions would probably fail as well.
So I'm looking for ways to make this work. I'm afraid there isn't any, but maybe somebody knows one. It does actually already work with "simple" unicode directories like "E:\test\Chäröcter Teßt" or "E:\test\Bjørn". But it fails for e.g. "E:\test\Bölükbaşı". With this it throws a "126" error for LoadLibraryExA ("The specified module could not be found") or "3" for the Detours call ("The system cannot find the path specified").
Here's some stripped down code taken from the withdll sample as a test case:
(As explained, for an even more simple test case you could probably remove the Detours part and only check with the LoadLibraryExA
call.)
#include <windows.h>
#include <detours.h>
#include <strsafe.h>
int CDECL main(int argc, char** argv)
{
LPCSTR rpszDllRaw = "detoursSimpleDll64.dll"; // Exists in the same directory, along with its 32bit counterpart
LPCSTR szExe = "HelloWorld.exe"; // Exists in the same directory
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);
}
// Here begins the Detours code
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;
}
Upvotes: 1
Views: 463