diff --git a/win/nvfbcwrp/framework.h b/win/nvfbcwrp/framework.h index 61ca0b6..152f4e8 100644 --- a/win/nvfbcwrp/framework.h +++ b/win/nvfbcwrp/framework.h @@ -3,3 +3,5 @@ #define WIN32_LEAN_AND_MEAN // Исключите редко используемые компоненты из заголовков Windows // Файлы заголовков Windows #include +#include +#include diff --git a/win/nvfbcwrp/nvfbcdefs.h b/win/nvfbcwrp/nvfbcdefs.h index 09b2dc5..eb0edf4 100644 --- a/win/nvfbcwrp/nvfbcdefs.h +++ b/win/nvfbcwrp/nvfbcdefs.h @@ -1,8 +1,5 @@ #pragma once -// Magic code which is passed as pPrivateData and enables NvFBC to work on GeForce -int magic[] = { 0x0D7BC620, 0x4C17E142, 0x5E6B5997, 0x4B5A855B }; - typedef unsigned long NvU32; /* 0 to 4294967295 */ /** diff --git a/win/nvfbcwrp/nvfbcwrp.vcxproj b/win/nvfbcwrp/nvfbcwrp.vcxproj index 1137212..2c93794 100644 --- a/win/nvfbcwrp/nvfbcwrp.vcxproj +++ b/win/nvfbcwrp/nvfbcwrp.vcxproj @@ -30,27 +30,27 @@ DynamicLibrary true v142 - MultiByte + Unicode DynamicLibrary false v142 true - MultiByte + Unicode DynamicLibrary true v142 - MultiByte + Unicode DynamicLibrary false v142 true - MultiByte + Unicode @@ -132,6 +132,7 @@ WIN32;NDEBUG;NVFBCWRP_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) true pch.h + true Windows @@ -154,6 +155,7 @@ NDEBUG;NVFBCWRP_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) true pch.h + true Windows diff --git a/win/nvfbcwrp/nvfbcwrp.vcxproj.filters b/win/nvfbcwrp/nvfbcwrp.vcxproj.filters index e6510e8..144b956 100644 --- a/win/nvfbcwrp/nvfbcwrp.vcxproj.filters +++ b/win/nvfbcwrp/nvfbcwrp.vcxproj.filters @@ -15,15 +15,15 @@ - - Файлы заголовков - Файлы заголовков Файлы заголовков + + Файлы заголовков + diff --git a/win/nvfbcwrp/nvfbcwrp_main.cpp b/win/nvfbcwrp/nvfbcwrp_main.cpp index 672f259..f699749 100644 --- a/win/nvfbcwrp/nvfbcwrp_main.cpp +++ b/win/nvfbcwrp/nvfbcwrp_main.cpp @@ -1,29 +1,117 @@ #include "pch.h" #include "nvfbcdefs.h" -#include #ifdef _WIN64 -#define LIBNAME ".\\NvFBC64_.dll" +#define LIBNAME TEXT(".\\NvFBC64_.dll") #else -#define LIBNAME ".\\NvFBC_.dll" +#define LIBNAME TEXT(".\\NvFBC_.dll") #endif -HINSTANCE hLThis = 0; +#define ENV_NVFBC_DUMPDIR TEXT("NVFBCWRP_DUMP_DIR") +#define ENV_NVFBC_PRIVDATA_FILE TEXT("NVFBCWRP_PRIVDATA_FILE") +#define NVFBC_PRIVDATA_DUMP_PREFIX TEXT("pd_") + extern "C" { FARPROC ORIG_NvFBC_Create, ORIG_NvFBC_Enable, ORIG_NvFBC_GetSDKVersion, ORIG_NvFBC_GetStatus, ORIG_NvFBC_GetStatusEx, ORIG_NvFBC_SetGlobalFlags, ORIG_NvOptimusEnablement; } NvFBC_CreateFunctionExType ORIG_NvFBC_CreateEx; -HINSTANCE hL = 0; + +// Default magic code which is passed as pPrivateData +// and enables NvFBC to work on GeForce +DWORD default_magic[] = { 0xAEF57AC5, 0x401D1A39, 0x1B856BBE, 0x9ED0CEBA }; +void* magic = default_magic; +NvU32 magic_size = sizeof(default_magic); + +TCHAR* dumpPath = NULL; + +TCHAR* getEnvVar(const TCHAR* name, DWORD size = MAX_PATH) { + TCHAR* buf = NULL; + try { + buf = new TCHAR[size]; + } + catch (std::bad_alloc&) { + return NULL; + } + DWORD ret = GetEnvironmentVariable(name, buf, size); + if (ret != 0 && size > ret) { + return buf; + } + else { + delete buf; + return NULL; + } +} + +std::tuple tryGetMagic() { + TCHAR* filename = getEnvVar(ENV_NVFBC_PRIVDATA_FILE); + if (!filename) { + return { 0, NULL }; + } + + HANDLE hFile = INVALID_HANDLE_VALUE; + hFile = CreateFile(filename, + GENERIC_READ, + FILE_SHARE_READ, + NULL, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, + NULL); + delete filename; + if (hFile == INVALID_HANDLE_VALUE) { + return { 0, NULL }; + } + + LARGE_INTEGER size; + LARGE_INTEGER zero; + zero.QuadPart = 0; + if (!SetFilePointerEx(hFile, zero, &size, FILE_END)) { + CloseHandle(hFile); + return { 0, NULL }; + } + if (size.HighPart) { + CloseHandle(hFile); + return { 0, NULL }; + } + if (!SetFilePointerEx(hFile, zero, NULL, FILE_BEGIN)) { + CloseHandle(hFile); + return { 0, NULL }; + } + + char* buf = NULL; + try { + buf = new char[size.LowPart]; + } + catch (std::bad_alloc&) + { + CloseHandle(hFile); + return { 0, NULL }; + } + DWORD bytes_read = 0; + if (ReadFile(hFile, buf, size.LowPart, &bytes_read, NULL) && + bytes_read == size.LowPart) { + CloseHandle(hFile); + return { size.LowPart, buf }; + } + else { + CloseHandle(hFile); + delete buf; + return { 0, NULL }; + } +} + BOOL WINAPI DllMain(HINSTANCE hInst,DWORD reason,LPVOID) { + HINSTANCE hL = 0; if (reason == DLL_PROCESS_ATTACH) { - //hLThis = hInst; hL = LoadLibrary(LIBNAME); if (!hL) return false; + + // DllMain calls are serialized by system on process level, so we are clear + // to set required variables. ORIG_NvFBC_Create = GetProcAddress(hL, "NvFBC_Create"); if (!ORIG_NvFBC_Create) return false; ORIG_NvFBC_CreateEx = (NvFBC_CreateFunctionExType)::GetProcAddress(hL, "NvFBC_CreateEx"); @@ -40,24 +128,69 @@ BOOL WINAPI DllMain(HINSTANCE hInst,DWORD reason,LPVOID) if (!ORIG_NvFBC_SetGlobalFlags) return false; ORIG_NvOptimusEnablement = GetProcAddress(hL, "NvOptimusEnablement"); if (!ORIG_NvOptimusEnablement) return false; + + // Check dump settings + if (TCHAR* dumpDirName = getEnvVar(ENV_NVFBC_DUMPDIR)) + { + dumpPath = dumpDirName; + } + + // Check external magic file + NvU32 new_magic_size; + void* new_magic; + std::tie(new_magic_size, new_magic) = tryGetMagic(); + if (new_magic) { + magic = new_magic; + magic_size = new_magic_size; + } } - if (reason == DLL_PROCESS_DETACH) + if (reason == DLL_PROCESS_DETACH && hL) { FreeLibrary(hL); + if (dumpPath) { + delete dumpPath; + dumpPath = NULL; + } + if (magic != default_magic) { + delete magic; + magic = NULL; + } return true; } return true; } +void tryDumpPrivateData(NvU32 size, void* data) +{ + TCHAR szTmpFilename[MAX_PATH]; + if (dumpPath && GetTempFileName(dumpPath, NVFBC_PRIVDATA_DUMP_PREFIX, 0, szTmpFilename) != 0) { + // Privdata spying enabled and tempfile created. + // Attempt to dump private data. + HANDLE hTempFile = INVALID_HANDLE_VALUE; + hTempFile = CreateFile((LPTSTR)szTmpFilename, + GENERIC_WRITE, + 0, + NULL, + CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL, + NULL); + if (hTempFile != INVALID_HANDLE_VALUE) { + // File is open, dumping data. + WriteFile(hTempFile, data, size, NULL, NULL); + CloseHandle(hTempFile); + } + } +} + NVFBCRESULT NVFBCAPI PROXY_NvFBC_CreateEx(NvFBCCreateParams* params) { if (params->dwPrivateDataSize == 0 && params->pPrivateData == NULL) { //Backup old values void* bkp_privdata = params->pPrivateData; NvU32 bkp_privdatasize = params->dwPrivateDataSize; // Inject private keys into structure - params->dwPrivateDataSize = sizeof(magic); - params->pPrivateData = &magic; + params->dwPrivateDataSize = magic_size; + params->pPrivateData = magic; // Invoke original function NVFBCRESULT res = ORIG_NvFBC_CreateEx(params); // Rollback private data changes in params structure @@ -66,6 +199,9 @@ NVFBCRESULT NVFBCAPI PROXY_NvFBC_CreateEx(NvFBCCreateParams* params) { return res; } else { + if (params->dwPrivateDataSize > 0 && params->pPrivateData != NULL) { + tryDumpPrivateData(params->dwPrivateDataSize, params->pPrivateData); + } return ORIG_NvFBC_CreateEx((void*)params); } } \ No newline at end of file