From 30e58ac08b6ee122de3130f3f02d6a855130ae51 Mon Sep 17 00:00:00 2001 From: Jan Date: Sun, 18 Feb 2024 22:11:09 +0100 Subject: Clean up wsock proxy code and move wsock build system logic (#671) - moves `WSockProxy` to `wsockproxy/CmakeLists` - remove exepath stuff from dllmain + its still done in loader.cpp because its used when reporting failure - Disabled any Thread Library calls + we don't need to know about threads at all in the proxy - yoink `wsock32.asm` into outer space + turns out, we can just call the function in a void shim since that wont touch the registers - stop copying `wsock32.dll` to the game directory + this should improve the state of things when using the EA App --- primedev/CMakeLists.txt | 2 +- primedev/WSockProxy.cmake | 49 ------------ primedev/wsockproxy/CMakeLists.txt | 48 ++++++++++++ primedev/wsockproxy/dllmain.cpp | 153 ++++++------------------------------- primedev/wsockproxy/loader.cpp | 38 +++++++-- primedev/wsockproxy/wsock32.asm | 7 -- 6 files changed, 102 insertions(+), 195 deletions(-) delete mode 100644 primedev/WSockProxy.cmake create mode 100644 primedev/wsockproxy/CMakeLists.txt delete mode 100644 primedev/wsockproxy/wsock32.asm diff --git a/primedev/CMakeLists.txt b/primedev/CMakeLists.txt index 03f2628e..31dda4b2 100644 --- a/primedev/CMakeLists.txt +++ b/primedev/CMakeLists.txt @@ -1,3 +1,3 @@ include(Northstar.cmake) include(Launcher.cmake) -include(WSockProxy.cmake) +add_subdirectory(wsockproxy) diff --git a/primedev/WSockProxy.cmake b/primedev/WSockProxy.cmake deleted file mode 100644 index 017e358a..00000000 --- a/primedev/WSockProxy.cmake +++ /dev/null @@ -1,49 +0,0 @@ -# loader_wsock32_proxy - -find_package(minhook REQUIRED) - -add_library( - loader_wsock32_proxy SHARED - "wsockproxy/dllmain.cpp" - "wsockproxy/loader.cpp" - "wsockproxy/loader.h" - "wsockproxy/wsock32.asm" - "wsockproxy/wsock32.def" - ) - -target_link_libraries( - loader_wsock32_proxy - PRIVATE minhook - mswsock.lib - ws2_32.lib - ShLwApi.lib - imagehlp.lib - dbghelp.lib - kernel32.lib - user32.lib - gdi32.lib - winspool.lib - comdlg32.lib - advapi32.lib - shell32.lib - ole32.lib - oleaut32.lib - uuid.lib - odbc32.lib - odbccp32.lib - ) - -target_precompile_headers( - loader_wsock32_proxy - PRIVATE - wsockproxy/pch.h - ) - -target_compile_definitions(loader_wsock32_proxy PRIVATE UNICODE _UNICODE) - -set_target_properties( - loader_wsock32_proxy - PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${NS_BINARY_DIR}/bin/x64_retail - OUTPUT_NAME wsock32 - LINK_FLAGS "/MANIFEST:NO /DEBUG" - ) diff --git a/primedev/wsockproxy/CMakeLists.txt b/primedev/wsockproxy/CMakeLists.txt new file mode 100644 index 00000000..0dbac745 --- /dev/null +++ b/primedev/wsockproxy/CMakeLists.txt @@ -0,0 +1,48 @@ +# loader_wsock32_proxy + +find_package(minhook REQUIRED) + +add_library( + loader_wsock32_proxy SHARED + "dllmain.cpp" + "loader.cpp" + "loader.h" + "wsock32.def" + ) + +target_link_libraries( + loader_wsock32_proxy + PRIVATE minhook + mswsock.lib + ws2_32.lib + ShLwApi.lib + imagehlp.lib + dbghelp.lib + kernel32.lib + user32.lib + gdi32.lib + winspool.lib + comdlg32.lib + advapi32.lib + shell32.lib + ole32.lib + oleaut32.lib + uuid.lib + odbc32.lib + odbccp32.lib + ) + +target_precompile_headers( + loader_wsock32_proxy + PRIVATE + pch.h + ) + +target_compile_definitions(loader_wsock32_proxy PRIVATE UNICODE _UNICODE) + +set_target_properties( + loader_wsock32_proxy + PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${NS_BINARY_DIR}/bin/x64_retail + OUTPUT_NAME wsock32 + LINK_FLAGS "/MANIFEST:NO /DEBUG" + ) diff --git a/primedev/wsockproxy/dllmain.cpp b/primedev/wsockproxy/dllmain.cpp index 4cc4f26e..5a606e45 100644 --- a/primedev/wsockproxy/dllmain.cpp +++ b/primedev/wsockproxy/dllmain.cpp @@ -1,90 +1,29 @@ #include "loader.h" -#include #include -HINSTANCE hLThis = 0; -FARPROC p[857]; -HINSTANCE hL = 0; +FARPROC p[73]; +HMODULE hL = 0; -bool GetExePathWide(wchar_t* dest, DWORD destSize) -{ - if (!dest) - return NULL; - if (destSize < MAX_PATH) - return NULL; - - DWORD length = GetModuleFileNameW(NULL, dest, destSize); - return length && PathRemoveFileSpecW(dest); -} - -wchar_t exePath[4096]; -wchar_t buffer1[8192]; -wchar_t buffer2[12288]; +static wchar_t wsockPath[4096]; BOOL WINAPI DllMain(HINSTANCE hInst, DWORD reason, LPVOID) { if (reason == DLL_PROCESS_ATTACH) { - hLThis = hInst; - - if (!GetExePathWide(exePath, 4096)) - { - MessageBoxA( - GetForegroundWindow(), - "Failed getting game directory.\nThe game cannot continue and has to exit.", - "Northstar Wsock32 Proxy Error", - 0); - return true; - } - - SetCurrentDirectoryW(exePath); + // Tell the OS we don't need to know about threads + DisableThreadLibraryCalls(hInst); if (!ProvisionNorthstar()) // does not call InitialiseNorthstar yet, will do it on LauncherMain hook return true; - // copy the original library for system to our local directory, with changed name so that we can load it - swprintf_s(buffer1, L"%s\\bin\\x64_retail\\wsock32.org.dll", exePath); - GetSystemDirectoryW(buffer2, 4096); - swprintf_s(buffer2, L"%s\\wsock32.dll", buffer2); - try - { - std::filesystem::copy_file(buffer2, buffer1); - } - catch (const std::exception& e1) - { - if (!std::filesystem::exists(buffer1)) - { - // fallback by copying to temp dir... - // because apparently games installed by EA Desktop app don't have write permissions in their directories - auto temp_dir = std::filesystem::temp_directory_path() / L"wsock32.org.dll"; - try - { - std::filesystem::copy_file(buffer2, temp_dir); - } - catch (const std::exception& e2) - { - if (!std::filesystem::exists(temp_dir)) - { - swprintf_s( - buffer2, - L"Failed copying wsock32.dll from system32 to \"%s\"\n\n%S\n\nFurthermore, we failed copying wsock32.dll into " - L"temporary directory at \"%s\"\n\n%S", - buffer1, - e1.what(), - temp_dir.c_str(), - e2.what()); - MessageBoxW(GetForegroundWindow(), buffer2, L"Northstar Wsock32 Proxy Error", 0); - return false; - } - } - swprintf_s(buffer1, L"%s", temp_dir.c_str()); - } - } - hL = LoadLibraryExW(buffer1, 0, LOAD_WITH_ALTERED_SEARCH_PATH); + GetSystemDirectoryW(wsockPath, 4096); + swprintf_s(wsockPath, 4096, L"%s\\wsock32.dll", wsockPath); + + hL = LoadLibraryExW(wsockPath, 0, LOAD_WITH_ALTERED_SEARCH_PATH); if (!hL) { - LibraryLoadError(GetLastError(), L"wsock32.org.dll", buffer1); + LibraryLoadError(GetLastError(), L"wsock32.dll", wsockPath); return false; } @@ -119,64 +58,16 @@ extern "C" FARPROC PA = NULL; int RunASM(); - void PROXY_EnumProtocolsA() - { - PA = p[1]; - RunASM(); - } - void PROXY_EnumProtocolsW() - { - PA = p[2]; - RunASM(); - } - void PROXY_GetAddressByNameA() - { - PA = p[4]; - RunASM(); - } - void PROXY_GetAddressByNameW() - { - PA = p[5]; - RunASM(); - } - void PROXY_WEP() - { - PA = p[17]; - RunASM(); - } - void PROXY_WSARecvEx() - { - PA = p[30]; - RunASM(); - } - void PROXY___WSAFDIsSet() - { - PA = p[36]; - RunASM(); - } - void PROXY_getnetbyname() - { - PA = p[45]; - RunASM(); - } - void PROXY_getsockopt() - { - PA = p[52]; - RunASM(); - } - void PROXY_inet_network() - { - PA = p[56]; - RunASM(); - } - void PROXY_s_perror() - { - PA = p[67]; - RunASM(); - } - void PROXY_setsockopt() - { - PA = p[72]; - RunASM(); - } + void PROXY_EnumProtocolsA() { p[1](); } + void PROXY_EnumProtocolsW() { p[2](); } + void PROXY_GetAddressByNameA() { p[4](); } + void PROXY_GetAddressByNameW() { p[5](); } + void PROXY_WEP() { p[17](); } + void PROXY_WSARecvEx() { p[30](); } + void PROXY___WSAFDIsSet() { p[36](); } + void PROXY_getnetbyname() { p[45](); } + void PROXY_getsockopt() { p[52](); } + void PROXY_inet_network() { p[56](); } + void PROXY_s_perror() { p[67](); } + void PROXY_setsockopt() { p[72](); } } diff --git a/primedev/wsockproxy/loader.cpp b/primedev/wsockproxy/loader.cpp index 0a299ba8..a3abf11c 100644 --- a/primedev/wsockproxy/loader.cpp +++ b/primedev/wsockproxy/loader.cpp @@ -1,4 +1,5 @@ #include "loader.h" +#include #include #include #include @@ -8,6 +9,21 @@ namespace fs = std::filesystem; +static wchar_t northstarPath[8192]; +static wchar_t exePath[4096]; + +bool GetExePathWide(wchar_t* dest, DWORD destSize) +{ + if (!dest) + return NULL; + if (destSize < MAX_PATH) + return NULL; + + DWORD length = GetModuleFileNameW(NULL, dest, destSize); + return length && PathRemoveFileSpecW(dest); +} + + void LibraryLoadError(DWORD dwMessageId, const wchar_t* libName, const wchar_t* location) { char text[4096]; @@ -75,22 +91,30 @@ bool LoadNorthstar() strProfile = "R2Northstar"; } - wchar_t buffer[8192]; + if (!GetExePathWide(exePath, 4096)) + { + MessageBoxA( + GetForegroundWindow(), + "Failed getting game directory.\nThe game cannot continue and has to exit.", + "Northstar Wsock32 Proxy Error", + 0); + return true; + } // Check if "Northstar.dll" exists in profile directory, if it doesnt fall back to root - swprintf_s(buffer, L"%s\\%s\\Northstar.dll", exePath, std::wstring(strProfile.begin(), strProfile.end()).c_str()); + swprintf_s(northstarPath, L"%s\\%s\\Northstar.dll", exePath, std::wstring(strProfile.begin(), strProfile.end()).c_str()); - if (!fs::exists(fs::path(buffer))) - swprintf_s(buffer, L"%s\\Northstar.dll", exePath); + if (!fs::exists(fs::path(northstarPath))) + swprintf_s(northstarPath, L"%s\\Northstar.dll", exePath); - std::wcout << L"[*] Using: " << buffer << std::endl; + std::wcout << L"[*] Using: " << northstarPath << std::endl; - HMODULE hHookModule = LoadLibraryExW(buffer, 0, 8u); + HMODULE hHookModule = LoadLibraryExW(northstarPath, 0, 8u); if (hHookModule) Hook_Init = GetProcAddress(hHookModule, "InitialiseNorthstar"); if (!hHookModule || Hook_Init == nullptr) { - LibraryLoadError(GetLastError(), L"Northstar.dll", buffer); + LibraryLoadError(GetLastError(), L"Northstar.dll", northstarPath); return false; } } diff --git a/primedev/wsockproxy/wsock32.asm b/primedev/wsockproxy/wsock32.asm deleted file mode 100644 index 22a9c384..00000000 --- a/primedev/wsockproxy/wsock32.asm +++ /dev/null @@ -1,7 +0,0 @@ -.data -extern PA : qword -.code -RunASM proc -jmp qword ptr [PA] -RunASM endp -end -- cgit v1.2.3