From 7c506d86c968ea27982b4b2f502616b253737f55 Mon Sep 17 00:00:00 2001 From: narzoul Date: Sun, 25 Apr 2021 16:49:02 +0200 Subject: [PATCH] Support unicode file paths --- DDrawCompat/Common/Hook.cpp | 20 ++------ DDrawCompat/Common/Log.cpp | 24 +++++----- DDrawCompat/Common/Log.h | 3 +- DDrawCompat/Common/Path.cpp | 30 ++++++++++++ DDrawCompat/Common/Path.h | 13 +++++ DDrawCompat/DDrawCompat.vcxproj | 2 + DDrawCompat/DDrawCompat.vcxproj.filters | 6 +++ DDrawCompat/Dll/DllMain.cpp | 64 +++++++------------------ 8 files changed, 87 insertions(+), 75 deletions(-) create mode 100644 DDrawCompat/Common/Path.cpp create mode 100644 DDrawCompat/Common/Path.h diff --git a/DDrawCompat/Common/Hook.cpp b/DDrawCompat/Common/Hook.cpp index 0e213ea..cd3ea88 100644 --- a/DDrawCompat/Common/Hook.cpp +++ b/DDrawCompat/Common/Hook.cpp @@ -10,11 +10,12 @@ #include #include +#include #include namespace { - IDebugClient* g_debugClient = nullptr; + IDebugClient4* g_debugClient = nullptr; IDebugControl* g_debugControl = nullptr; IDebugSymbols* g_debugSymbols = nullptr; IDebugDataSpaces4* g_debugDataSpaces = nullptr; @@ -22,7 +23,6 @@ namespace bool g_isDbgEngInitialized = false; PIMAGE_NT_HEADERS getImageNtHeaders(HMODULE module); - std::string getModulePath(HMODULE module); bool initDbgEng(); FARPROC* findProcAddressInIat(HMODULE module, const char* procName) @@ -106,13 +106,6 @@ namespace return static_cast(endOffset - g_debugBase); } - std::string getModulePath(HMODULE module) - { - char path[MAX_PATH] = {}; - GetModuleFileName(module, path, sizeof(path)); - return path; - } - void hookFunction(void*& origFuncPtr, void* newFuncPtr, const char* funcName) { BYTE* targetFunc = reinterpret_cast(origFuncPtr); @@ -216,7 +209,7 @@ namespace g_isDbgEngInitialized = true; HRESULT result = S_OK; - if (FAILED(result = DebugCreate(IID_IDebugClient, reinterpret_cast(&g_debugClient))) || + if (FAILED(result = DebugCreate(IID_IDebugClient4, reinterpret_cast(&g_debugClient))) || FAILED(result = g_debugClient->QueryInterface(IID_IDebugControl, reinterpret_cast(&g_debugControl))) || FAILED(result = g_debugClient->QueryInterface(IID_IDebugSymbols, reinterpret_cast(&g_debugSymbols))) || FAILED(result = g_debugClient->QueryInterface(IID_IDebugDataSpaces4, reinterpret_cast(&g_debugDataSpaces)))) @@ -225,10 +218,7 @@ namespace return false; } - char dllPath[MAX_PATH] = {}; - GetModuleFileName(Dll::g_currentModule, dllPath, sizeof(dllPath)); - - result = g_debugClient->OpenDumpFile(dllPath); + result = g_debugClient->OpenDumpFileWide(Compat::getModulePath(Dll::g_currentModule).c_str(), 0); if (FAILED(result)) { Compat::Log() << "ERROR: DbgEng: OpenDumpFile failed: " << Compat::hex(result); @@ -302,7 +292,7 @@ namespace Compat HMODULE module = Compat::getModuleHandleFromAddress(funcPtr); if (module) { - oss << getModulePath(module) << "+0x" << std::hex << + oss << Compat::getModulePath(module).u8string() << "+0x" << std::hex << reinterpret_cast(funcPtr) - reinterpret_cast(module); } else diff --git a/DDrawCompat/Common/Log.cpp b/DDrawCompat/Common/Log.cpp index 828ea71..4f72eb1 100644 --- a/DDrawCompat/Common/Log.cpp +++ b/DDrawCompat/Common/Log.cpp @@ -1,6 +1,5 @@ -#include - #include +#include namespace { @@ -61,8 +60,12 @@ namespace Compat GetLocalTime(&st); char header[20]; +#ifdef DEBUGLOGS sprintf_s(header, "%04hx %02hu:%02hu:%02hu.%03hu ", GetCurrentThreadId(), st.wHour, st.wMinute, st.wSecond, st.wMilliseconds); +#else + sprintf_s(header, "%02hu:%02hu:%02hu.%03hu ", st.wHour, st.wMinute, st.wSecond, st.wMilliseconds); +#endif s_logFile << header; if (0 != s_indent) @@ -76,25 +79,24 @@ namespace Compat s_logFile << std::endl; } - void Log::initLogging(const std::string& processDir, std::string processName) + void Log::initLogging(std::filesystem::path processPath) { - if (processName.length() >= 4 && - 0 == _strcmpi(processName.substr(processName.length() - 4).c_str(), ".exe")) + if (Compat::isEqual(processPath.extension(), ".exe")) { - processName.resize(processName.length() - 4); + processPath.replace_extension(); } + processPath.replace_filename(L"DDrawCompat-" + processPath.filename().native()); for (int i = 1; i < 100; ++i) { - std::ostringstream logFileName; - logFileName << processDir << '\\' << "DDrawCompat-" << processName; + auto logFilePath(processPath); if (i > 1) { - logFileName << '[' << i << ']'; + logFilePath += '[' + std::to_string(i) + ']'; } - logFileName << ".log"; + logFilePath += ".log"; - s_logFile.open(logFileName.str(), std::ios_base::out, SH_DENYWR); + s_logFile.open(logFilePath, std::ios_base::out, SH_DENYWR); if (!s_logFile.fail()) { return; diff --git a/DDrawCompat/Common/Log.h b/DDrawCompat/Common/Log.h index 60c58df..25915be 100644 --- a/DDrawCompat/Common/Log.h +++ b/DDrawCompat/Common/Log.h @@ -1,5 +1,6 @@ #pragma once +#include #include #include #include @@ -183,7 +184,7 @@ namespace Compat return *this; } - static void initLogging(const std::string& processDir, std::string processName); + static void initLogging(std::filesystem::path processPath); static bool isPointerDereferencingAllowed() { return s_isLeaveLog || 0 == s_outParamDepth; } protected: diff --git a/DDrawCompat/Common/Path.cpp b/DDrawCompat/Common/Path.cpp new file mode 100644 index 0000000..e24c284 --- /dev/null +++ b/DDrawCompat/Common/Path.cpp @@ -0,0 +1,30 @@ +#include + +namespace Compat +{ + std::filesystem::path getModulePath(HMODULE module) + { + wchar_t path[MAX_PATH]; + GetModuleFileNameW(module, path, MAX_PATH); + return path; + } + + std::filesystem::path getSystemPath() + { + wchar_t path[MAX_PATH] = {}; + GetSystemDirectoryW(path, MAX_PATH); + return path; + } + + bool isEqual(const std::filesystem::path& p1, const std::filesystem::path& p2) + { + return 0 == _wcsicmp(p1.c_str(), p2.c_str()); + } + + std::filesystem::path replaceFilename(const std::filesystem::path& path, const std::filesystem::path& filename) + { + std::filesystem::path result(path); + result.replace_filename(filename); + return result; + } +} diff --git a/DDrawCompat/Common/Path.h b/DDrawCompat/Common/Path.h new file mode 100644 index 0000000..fcad69b --- /dev/null +++ b/DDrawCompat/Common/Path.h @@ -0,0 +1,13 @@ +#pragma once + +#include + +#include + +namespace Compat +{ + std::filesystem::path getModulePath(HMODULE module); + std::filesystem::path getSystemPath(); + bool isEqual(const std::filesystem::path& p1, const std::filesystem::path& p2); + std::filesystem::path replaceFilename(const std::filesystem::path& path, const std::filesystem::path& filename); +} diff --git a/DDrawCompat/DDrawCompat.vcxproj b/DDrawCompat/DDrawCompat.vcxproj index 9877609..4dad45a 100644 --- a/DDrawCompat/DDrawCompat.vcxproj +++ b/DDrawCompat/DDrawCompat.vcxproj @@ -169,6 +169,7 @@ + @@ -268,6 +269,7 @@ + diff --git a/DDrawCompat/DDrawCompat.vcxproj.filters b/DDrawCompat/DDrawCompat.vcxproj.filters index 06566b6..7c570d1 100644 --- a/DDrawCompat/DDrawCompat.vcxproj.filters +++ b/DDrawCompat/DDrawCompat.vcxproj.filters @@ -387,6 +387,9 @@ Header Files\Common + + Header Files\Common + @@ -605,6 +608,9 @@ Source Files\Gdi + + Source Files\Common + diff --git a/DDrawCompat/Dll/DllMain.cpp b/DDrawCompat/Dll/DllMain.cpp index e27e907..5be65a7 100644 --- a/DDrawCompat/Dll/DllMain.cpp +++ b/DDrawCompat/Dll/DllMain.cpp @@ -7,6 +7,7 @@ #include #include +#include #include #include #include @@ -47,31 +48,6 @@ namespace return LOG_RESULT(reinterpret_cast(Dll::g_origProcs.*origFunc)(firstParam, params...)); } - std::string getDirName(const std::string& path) - { - return path.substr(0, path.find_last_of('\\')); - } - - std::string getFileName(const std::string& path) - { - auto lastSeparatorPos = path.find_last_of('\\'); - return std::string::npos == lastSeparatorPos ? path : path.substr(lastSeparatorPos + 1, std::string::npos); - } - - std::string getModulePath(HMODULE module) - { - char path[MAX_PATH] = {}; - GetModuleFileName(module, path, sizeof(path)); - return path; - } - - std::string getSystemDirectory() - { - char path[MAX_PATH] = {}; - GetSystemDirectory(path, sizeof(path)); - return path; - } - void installHooks() { static bool isAlreadyInstalled = false; @@ -123,20 +99,14 @@ namespace } } - bool isEqual(const std::string& p1, const std::string& p2) - { - return 0 == _stricmp(p1.c_str(), p2.c_str()); - } - bool isOtherDDrawWrapperLoaded() { - const auto currentDllPath = getModulePath(Dll::g_currentModule); - const auto currentDllDir = getDirName(currentDllPath); - const auto ddrawDllPath = currentDllDir + "\\ddraw.dll"; - const auto dciman32DllPath = currentDllDir + "\\dciman32.dll"; + const auto currentDllPath(Compat::getModulePath(Dll::g_currentModule)); + const auto ddrawDllPath(Compat::replaceFilename(currentDllPath, "ddraw.dll")); + const auto dciman32DllPath(Compat::replaceFilename(currentDllPath, "dciman32.dll")); - return (!isEqual(currentDllPath, ddrawDllPath) && GetModuleHandle(ddrawDllPath.c_str())) || - (!isEqual(currentDllPath, dciman32DllPath) && GetModuleHandle(dciman32DllPath.c_str())); + return (!Compat::isEqual(currentDllPath, ddrawDllPath) && GetModuleHandleW(ddrawDllPath.c_str())) || + (!Compat::isEqual(currentDllPath, dciman32DllPath) && GetModuleHandleW(dciman32DllPath.c_str())); } void printEnvironmentVariable(const char* var) @@ -203,26 +173,25 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) return TRUE; } - auto processPath = getModulePath(nullptr); - Compat::Log::initLogging(getDirName(processPath), getFileName(processPath)); + auto processPath(Compat::getModulePath(nullptr)); + Compat::Log::initLogging(processPath); - Compat::Log() << "Process path: " << processPath; + Compat::Log() << "Process path: " << processPath.u8string(); printEnvironmentVariable("__COMPAT_LAYER"); - auto currentDllPath = getModulePath(hinstDLL); - Compat::Log() << "Loading DDrawCompat " << (lpvReserved ? "statically" : "dynamically") << " from " << currentDllPath; + auto currentDllPath(Compat::getModulePath(hinstDLL)); + Compat::Log() << "Loading DDrawCompat " << (lpvReserved ? "statically" : "dynamically") << " from " << currentDllPath.u8string(); - auto systemDirectory = getSystemDirectory(); - if (isEqual(getDirName(currentDllPath), systemDirectory)) + auto systemPath(Compat::getSystemPath()); + if (Compat::isEqual(currentDllPath.parent_path(), systemPath)) { Compat::Log() << "DDrawCompat cannot be installed in the Windows system directory"; return FALSE; } - auto systemDDrawDllPath = systemDirectory + "\\ddraw.dll"; - Dll::g_origDDrawModule = LoadLibrary(systemDDrawDllPath.c_str()); + Dll::g_origDDrawModule = LoadLibraryW((systemPath / "ddraw.dll").c_str()); if (!Dll::g_origDDrawModule) { - Compat::Log() << "ERROR: Failed to load system ddraw.dll from " << systemDDrawDllPath; + Compat::Log() << "ERROR: Failed to load system ddraw.dll from " << systemPath.u8string(); return FALSE; } @@ -232,8 +201,7 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) HMODULE origModule = Dll::g_origDDrawModule; VISIT_DDRAW_PROCS(LOAD_ORIG_PROC); - auto systemDciman32DllPath = systemDirectory + "\\dciman32.dll"; - Dll::g_origDciman32Module = LoadLibrary(systemDciman32DllPath.c_str()); + Dll::g_origDciman32Module = LoadLibraryW((systemPath / "dciman32.dll").c_str()); if (Dll::g_origDciman32Module) { origModule = Dll::g_origDciman32Module;