diff --git a/ExplorerPatcher/ExplorerPatcher.rc b/ExplorerPatcher/ExplorerPatcher.rc index f52434f..c8d4524 100644 --- a/ExplorerPatcher/ExplorerPatcher.rc +++ b/ExplorerPatcher/ExplorerPatcher.rc @@ -51,8 +51,8 @@ END // VS_VERSION_INFO VERSIONINFO - FILEVERSION 22000,1,0,4 - PRODUCTVERSION 22000,1,0,4 + FILEVERSION 22000,1,0,5 + PRODUCTVERSION 22000,1,0,5 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -69,12 +69,12 @@ BEGIN BEGIN VALUE "CompanyName", "VALINET Solutions SRL" VALUE "FileDescription", "ExplorerPatcher Daemon" - VALUE "FileVersion", "22000.1.0.4" + VALUE "FileVersion", "22000.1.0.5" VALUE "InternalName", "ExplorerPatcher.exe" VALUE "LegalCopyright", "Copyright (C) 2006-2021 VALINET Solutions SRL. All rights reserved." VALUE "OriginalFilename", "ExplorerPatcher.exe" VALUE "ProductName", "ExplorerPatcher" - VALUE "ProductVersion", "22000.1.0.4" + VALUE "ProductVersion", "22000.1.0.5" END END BLOCK "VarFileInfo" diff --git a/ExplorerPatcher/ExplorerPatcher.vcxproj b/ExplorerPatcher/ExplorerPatcher.vcxproj index 8628e32..ef41f22 100644 --- a/ExplorerPatcher/ExplorerPatcher.vcxproj +++ b/ExplorerPatcher/ExplorerPatcher.vcxproj @@ -89,6 +89,8 @@ true _DEBUG;_CONSOLE;%(PreprocessorDefinitions) true + MultiThreadedDebug + $(SolutionDir)libs\funchook\distorm\include;$(SolutionDir)libs\libvalinet Console @@ -109,11 +111,13 @@ true _DEBUG;_CONSOLE;%(PreprocessorDefinitions) true - $(SolutionDir)libs\libvalinet;%(AdditionalIncludeDirectories) + $(SolutionDir)libs\funchook\distorm\include;$(SolutionDir)libs\libvalinet + MultiThreadedDebug Windows true + $(SolutionDir)libs\funchook\build\Release\distorm.lib;%(AdditionalDependencies) @@ -132,6 +136,8 @@ true NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true + MultiThreaded + $(SolutionDir)libs\funchook\distorm\include;$(SolutionDir)libs\libvalinet Console @@ -156,13 +162,15 @@ true NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true - $(SolutionDir)libs\libvalinet;%(AdditionalIncludeDirectories) + $(SolutionDir)libs\funchook\distorm\include;$(SolutionDir)libs\libvalinet + MultiThreaded Windows true true true + $(SolutionDir)libs\funchook\build\Release\distorm.lib;%(AdditionalDependencies) diff --git a/ExplorerPatcher/main.c b/ExplorerPatcher/main.c index 8df9a31..f91c9bd 100644 --- a/ExplorerPatcher/main.c +++ b/ExplorerPatcher/main.c @@ -9,13 +9,90 @@ processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"") #include #pragma comment(lib, "Shlwapi.lib") +#include +#include +#define _LIBVALINET_INCLUDE_UNIVERSAL +#include + +#include +#define BYTES_TO_DISASSEMBLE 1000 +#define APPID L"Microsoft.Windows.Explorer" +#define SYMBOLS_RELATIVE_PATH "\\settings.ini" +#define EXPLORER_SB_NAME "explorer" +#define EXPLORER_SB_0 "CTray::Init" +#define EXPLORER_SB_CNT 1 +#define EXPLORER_PATCH_OFFSET "Offset" +#define EXPLORER_PATCH_OFFSET_OK "OffsetOK" +#define EXPLORER_PATCH_OFFSET_STRAT "OffsetStrat" +const char* explorer_SN[EXPLORER_SB_CNT] = { + EXPLORER_SB_0 +}; +#pragma pack(push, 1) +typedef struct symbols_addr +{ + DWORD explorer_PTRS[EXPLORER_SB_CNT]; +} symbols_addr; +#pragma pack(pop) + +wchar_t InstallOK[] = +L"\r\n" +L" \r\n" +L" \r\n" +L" \r\n" +L" \r\n" +L" \r\n" +L" \r\n" +L" \r\n" +L" \r\n"; + +wchar_t UninstallOK[] = +L"\r\n" +L" \r\n" +L" \r\n" +L" \r\n" +L" \r\n" +L" \r\n" +L" \r\n" +L" \r\n" +L" \r\n"; + +typedef LONG NTSTATUS, * PNTSTATUS; +#define STATUS_SUCCESS (0x00000000) + +typedef NTSTATUS(WINAPI* RtlGetVersionPtr)(PRTL_OSVERSIONINFOW); + +BOOL GetOSVersion(PRTL_OSVERSIONINFOW lpRovi) +{ + HMODULE hMod = GetModuleHandleW(L"ntdll.dll"); + if (hMod != NULL) + { + RtlGetVersionPtr fxPtr = (RtlGetVersionPtr)GetProcAddress( + hMod, + "RtlGetVersion" + ); + if (fxPtr != NULL) + { + lpRovi->dwOSVersionInfoSize = sizeof(RTL_OSVERSIONINFOW); + if (STATUS_SUCCESS == fxPtr(lpRovi)) + { + return TRUE; + } + } + } + return FALSE; +} + #define DEBUG #undef DEBUG #define CLASS_NAME TEXT("ExplorerPatcher") #define APP_NAME TEXT("Windows Explorer") #define NOP 0x90 -#define PATCH_OFFSET 0x8cb33 +#define PATCH_OFFSET 0 //0x8cb33 #define DELAY 5000 HANDLE hProcess = NULL; @@ -118,12 +195,58 @@ int install_uninstall() { goto error_setup; } - MessageBox( - 0, - TEXT("Uninstall successful."), - APP_NAME, - MB_ICONINFORMATION + BOOL canShowToast = FALSE; + PROCESSENTRY32 pe32 = { 0 }; + pe32.dwSize = sizeof(PROCESSENTRY32); + HANDLE hSnapshot = CreateToolhelp32Snapshot( + TH32CS_SNAPPROCESS, + 0 ); + if (Process32First(hSnapshot, &pe32) == TRUE) + { + do + { + if (!wcscmp(pe32.szExeFile, TEXT("explorer.exe"))) + { + canShowToast = TRUE; + break; + } + } while (Process32Next(hSnapshot, &pe32) == TRUE); + } + CloseHandle(hSnapshot); + if (!canShowToast) + { + MessageBox( + 0, + TEXT("Uninstall successful."), + APP_NAME, + MB_ICONINFORMATION + ); + } + else + { + __x_ABI_CWindows_CData_CXml_CDom_CIXmlDocument* inputXml2 = NULL; + HRESULT hr = String2IXMLDocument( + UninstallOK, + wcslen(UninstallOK), + &inputXml2, +#ifdef DEBUG + stdout +#else + NULL +#endif + ); + hr = ShowToastMessage( + inputXml2, + APPID, + sizeof(APPID) / sizeof(TCHAR) - 1, +#ifdef DEBUG + stdout +#else + NULL +#endif + ); + } } else { @@ -143,11 +266,88 @@ int install_uninstall() { goto error_setup; } - MessageBox( - 0, - TEXT("Successfully installed Taskman registry key."), - APP_NAME, - MB_ICONINFORMATION + BOOL canShowToast = FALSE; + PROCESSENTRY32 pe32 = { 0 }; + pe32.dwSize = sizeof(PROCESSENTRY32); + HANDLE hSnapshot = CreateToolhelp32Snapshot( + TH32CS_SNAPPROCESS, + 0 + ); + if (Process32First(hSnapshot, &pe32) == TRUE) + { + do + { + if (!wcscmp(pe32.szExeFile, TEXT("explorer.exe"))) + { + canShowToast = TRUE; + break; + } + } while (Process32Next(hSnapshot, &pe32) == TRUE); + } + CloseHandle(hSnapshot); + if (!canShowToast) + { + MessageBox( + 0, + TEXT("Installation was successful. Please sign out or restart") + TEXT("the computer for the changes to take effect."), + APP_NAME, + MB_ICONINFORMATION + ); + } + else + { + __x_ABI_CWindows_CData_CXml_CDom_CIXmlDocument* inputXml2 = NULL; + HRESULT hr = String2IXMLDocument( + InstallOK, + wcslen(InstallOK), + &inputXml2, +#ifdef DEBUG + stdout +#else + NULL +#endif + ); + hr = ShowToastMessage( + inputXml2, + APPID, + sizeof(APPID) / sizeof(TCHAR) - 1, +#ifdef DEBUG + stdout +#else + NULL +#endif + ); + Sleep(10000); + } + hSnapshot = CreateToolhelp32Snapshot( + TH32CS_SNAPPROCESS, + 0 + ); + if (Process32First(hSnapshot, &pe32) == TRUE) + { + do + { + if (!wcscmp(pe32.szExeFile, TEXT("sihost.exe"))) + { + HANDLE hSihost = OpenProcess( + PROCESS_TERMINATE, + FALSE, + pe32.th32ProcessID + ); + TerminateProcess(hSihost, 0); + CloseHandle(hSihost); + } + } while (Process32Next(hSnapshot, &pe32) == TRUE); + } + CloseHandle(hSnapshot); + TerminateProcess( + OpenProcess( + PROCESS_TERMINATE, + FALSE, + GetCurrentProcessId() + ), + 0 ); } RegCloseKey(hKey); @@ -185,7 +385,8 @@ int WINAPI wWinMain( DWORD dwExplorerPID = 0, dwOldValue; SIZE_T dwNumberOfBytes; uintptr_t dwInjectedAddr = 0; - const char szPayload[6] = { NOP, NOP, NOP, NOP, NOP, NOP }; + const char szPayload0[6] = { NOP, NOP, NOP, NOP, NOP, NOP }; + const char szPayload1[2] = { NOP, 0xE9 }; PROCESSENTRY32 pe32 = { 0 }; MODULEENTRY32 me32 = { 0 }; THREADENTRY32 th32 = { 0 }; @@ -216,6 +417,25 @@ int WINAPI wWinMain( 0 ); if (Process32First(hSnapshot, &pe32) == TRUE) + { + do + { + if (pe32.th32ProcessID != GetCurrentProcessId() && + !wcscmp(pe32.szExeFile, TEXT("ExplorerPatcher.exe"))) + { + HANDLE hOwn = OpenProcess( + SYNCHRONIZE, + FALSE, + pe32.th32ProcessID + ); + WaitForSingleObject( + hOwn, + INFINITE + ); + } + } while (Process32Next(hSnapshot, &pe32) == TRUE); + } + if (Process32First(hSnapshot, &pe32) == TRUE) { do { @@ -233,6 +453,186 @@ int WINAPI wWinMain( break; } + DWORD dwRet = 0; + char szSettingsPath[MAX_PATH]; + ZeroMemory( + szSettingsPath, + (MAX_PATH) * sizeof(char) + ); + TCHAR wszSettingsPath[MAX_PATH]; + ZeroMemory( + wszSettingsPath, + (MAX_PATH) * sizeof(TCHAR) + ); + GetModuleFileNameA( + hInstance, + szSettingsPath, + MAX_PATH + ); + PathRemoveFileSpecA(szSettingsPath); + strcat_s( + szSettingsPath, + MAX_PATH, + SYMBOLS_RELATIVE_PATH + ); + mbstowcs_s( + &dwRet, + wszSettingsPath, + MAX_PATH, + szSettingsPath, + MAX_PATH + ); + + symbols_addr symbols_PTRS; + ZeroMemory( + &symbols_PTRS, + sizeof(symbols_addr) + ); + symbols_PTRS.explorer_PTRS[0] = VnGetUInt( + TEXT(EXPLORER_SB_NAME), + TEXT(EXPLORER_SB_0), + 0, + wszSettingsPath + ); + + BOOL bNeedToDownload = FALSE; + for (UINT i = 0; i < sizeof(symbols_addr) / sizeof(DWORD); ++i) + { + if (!((DWORD*)&symbols_PTRS)[i]) + { + bNeedToDownload = TRUE; + } + } + // https://stackoverflow.com/questions/36543301/detecting-windows-10-version/36543774#36543774 + RTL_OSVERSIONINFOW rovi; + if (!GetOSVersion(&rovi)) + { + DebugActiveProcessStop(dwExplorerPID); + return 1; + } + // https://stackoverflow.com/questions/47926094/detecting-windows-10-os-build-minor-version + DWORD32 ubr = 0, ubr_size = sizeof(DWORD32); + HKEY hKey; + LONG lRes = RegOpenKeyExW( + HKEY_LOCAL_MACHINE, + wcschr( + wcschr( + wcschr( + UNIFIEDBUILDREVISION_KEY, + '\\' + ) + 1, + '\\' + ) + 1, + '\\' + ) + 1, + 0, + KEY_READ, + &hKey + ); + if (lRes == ERROR_SUCCESS) + { + RegQueryValueExW( + hKey, + UNIFIEDBUILDREVISION_VALUE, + 0, + NULL, + &ubr, + &ubr_size + ); + } + TCHAR szReportedVersion[MAX_PATH]; + ZeroMemory( + szReportedVersion, + (MAX_PATH) * sizeof(TCHAR) + ); + TCHAR szStoredVersion[MAX_PATH]; + ZeroMemory( + szStoredVersion, + (MAX_PATH) * sizeof(TCHAR) + ); + wsprintf( + szReportedVersion, + L"%d.%d.%d.%d", + rovi.dwMajorVersion, + rovi.dwMinorVersion, + rovi.dwBuildNumber, + ubr + ); + VnGetString( + TEXT("OS"), + TEXT("Build"), + szStoredVersion, + MAX_PATH, + MAX_PATH, + NULL, + wszSettingsPath + ); + if (!bNeedToDownload) + { + bNeedToDownload = wcscmp(szReportedVersion, szStoredVersion); + } + + if (bNeedToDownload) + { + char explorer_sb_dll[MAX_PATH]; + ZeroMemory( + explorer_sb_dll, + (MAX_PATH) * sizeof(char) + ); + GetWindowsDirectoryA( + explorer_sb_dll, + MAX_PATH + ); + strcat_s( + explorer_sb_dll, + MAX_PATH, + "\\" + ); + strcat_s( + explorer_sb_dll, + MAX_PATH, + EXPLORER_SB_NAME + ); + strcat_s( + explorer_sb_dll, + MAX_PATH, + ".exe" + ); + if (VnDownloadSymbols( + NULL, + explorer_sb_dll, + szSettingsPath, + MAX_PATH + )) + { + DebugActiveProcessStop(dwExplorerPID); + return 2; + } + if (VnGetSymbols( + szSettingsPath, + symbols_PTRS.explorer_PTRS, + explorer_SN, + EXPLORER_SB_CNT + )) + { + DebugActiveProcessStop(dwExplorerPID); + return 3; + } + VnWriteUInt( + TEXT(EXPLORER_SB_NAME), + TEXT(EXPLORER_SB_0), + symbols_PTRS.explorer_PTRS[0], + wszSettingsPath + ); + + VnWriteString( + TEXT("OS"), + TEXT("Build"), + szReportedVersion, + wszSettingsPath + ); + } + if ((hExplorer = OpenProcess( PROCESS_VM_READ | PROCESS_VM_WRITE | @@ -267,42 +667,315 @@ int WINAPI wWinMain( } CloseHandle(hSnapshot); - if (dwInjectedAddr) + uintptr_t start = VnGetUInt( + TEXT(EXPLORER_SB_NAME), + TEXT(EXPLORER_PATCH_OFFSET), + 0, + wszSettingsPath + ); + uintptr_t ok = VnGetUInt( + TEXT(EXPLORER_SB_NAME), + TEXT(EXPLORER_PATCH_OFFSET_OK), + 0, + wszSettingsPath + ); + uintptr_t strat = VnGetUInt( + TEXT(EXPLORER_SB_NAME), + TEXT(EXPLORER_PATCH_OFFSET_STRAT), + 0, + wszSettingsPath + ); + uintptr_t end = 0; + if (!ok) { + uintptr_t CTray_Init = dwInjectedAddr + (uintptr_t)symbols_PTRS.explorer_PTRS[0]; + char m[BYTES_TO_DISASSEMBLE]; VirtualProtectEx( hExplorer, - (LPVOID)dwInjectedAddr, - sizeof(szPayload), + (LPVOID)CTray_Init, + BYTES_TO_DISASSEMBLE, + PAGE_EXECUTE_READWRITE, + &dwOldValue + ); + ReadProcessMemory( + hExplorer, + (LPVOID)CTray_Init, + m, + BYTES_TO_DISASSEMBLE, + &dwNumberOfBytes + ); + VirtualProtectEx( + hExplorer, + (LPVOID)CTray_Init, + BYTES_TO_DISASSEMBLE, + dwOldValue, + (PDWORD)(&dwNumberOfBytes) + ); + _DecodedInst decodedInstructions[1000]; + UINT decodedInstructionsCount = 0; + _DecodeResult res = distorm_decode( + 0, + (const unsigned char*)m, + BYTES_TO_DISASSEMBLE, + Decode64Bits, + decodedInstructions, + 1000, + &decodedInstructionsCount + ); + BOOL found = FALSE; + for (UINT i = 0; i < decodedInstructionsCount; ++i) + { + if ((!strcmp(decodedInstructions[i].mnemonic.p, "JZ") || + !strcmp(decodedInstructions[i].mnemonic.p, "JNZ")) && + decodedInstructions[i].offset > start) + { + found = TRUE; + start = decodedInstructions[i].offset; + if (strat == 0) + { + memcpy( + m + start, + szPayload0, + sizeof(szPayload0) + ); + } + else if (strat == 1) + { + memcpy( + m + start, + szPayload1, + sizeof(szPayload1) + ); + } + break; + } + } + if (!found) + { + start = 0; + strat++; + } +#ifdef DEBUG + res = distorm_decode( + 0, + (const unsigned char*)m, + BYTES_TO_DISASSEMBLE, + Decode64Bits, + decodedInstructions, + 1000, + &decodedInstructionsCount + ); + for (UINT i = 0; i < decodedInstructionsCount; ++i) + { + printf( + "0x%p\t%s\t%s\n", + decodedInstructions[i].offset, + decodedInstructions[i].mnemonic.p, + decodedInstructions[i].instructionHex.p + ); + } +#endif + VirtualProtectEx( + hExplorer, + (LPVOID)CTray_Init, + BYTES_TO_DISASSEMBLE, PAGE_EXECUTE_READWRITE, &dwOldValue ); WriteProcessMemory( hExplorer, - (LPVOID)dwInjectedAddr, - szPayload, - sizeof(szPayload), + (LPVOID)CTray_Init, + m, + BYTES_TO_DISASSEMBLE, &dwNumberOfBytes ); VirtualProtectEx( hExplorer, - (LPVOID)dwInjectedAddr, - sizeof(szPayload), + (LPVOID)CTray_Init, + BYTES_TO_DISASSEMBLE, dwOldValue, (PDWORD)(&dwNumberOfBytes) ); DebugActiveProcessStop(dwExplorerPID); - /* - WaitForSingleObject( - hExplorer, - INFINITE + Sleep(3000); + HWND hWnd = FindWindowEx( + NULL, + NULL, + L"Shell_TrayWnd", + NULL ); - */ + if (hWnd) + { + hWnd = FindWindowEx( + hWnd, + NULL, + L"Start", + NULL + ); + if (hWnd) + { + if (IsWindowVisible(hWnd)) + { + ok = 1; + } + } + } + VnWriteUInt( + TEXT(EXPLORER_SB_NAME), + TEXT(EXPLORER_PATCH_OFFSET), + start, + wszSettingsPath + ); + VnWriteUInt( + TEXT(EXPLORER_SB_NAME), + TEXT(EXPLORER_PATCH_OFFSET_OK), + ok, + wszSettingsPath + ); + VnWriteUInt( + TEXT(EXPLORER_SB_NAME), + TEXT(EXPLORER_PATCH_OFFSET_STRAT), + strat, + wszSettingsPath + ); +#ifdef DEBUG + printf("start: %d ok %d\n", start, ok); +#endif + if (!ok) + { + hSnapshot = CreateToolhelp32Snapshot( + TH32CS_SNAPPROCESS, + 0 + ); + if (Process32First(hSnapshot, &pe32) == TRUE) + { + do + { + if (!wcscmp(pe32.szExeFile, TEXT("explorer.exe"))) + { + HANDLE hExpl = OpenProcess( + PROCESS_TERMINATE, + FALSE, + pe32.th32ProcessID + ); + TerminateProcess(hExpl, 1); + CloseHandle(hExpl); + } + } while (Process32Next(hSnapshot, &pe32) == TRUE); + } + if (Process32First(hSnapshot, &pe32) == TRUE) + { + do + { + if (!wcscmp(pe32.szExeFile, TEXT("sihost.exe"))) + { + HANDLE hSihost = OpenProcess( + PROCESS_TERMINATE, + FALSE, + pe32.th32ProcessID + ); + TerminateProcess(hSihost, 1); + CloseHandle(hSihost); + Sleep(500); + STARTUPINFO info = {sizeof(info)}; + PROCESS_INFORMATION processInfo; + BOOL b = CreateProcess( + NULL, + pe32.szExeFile, + NULL, + NULL, + TRUE, + CREATE_UNICODE_ENVIRONMENT, + NULL, + NULL, + &info, + &processInfo + ); + break; + } + } while (Process32Next(hSnapshot, &pe32) == TRUE); + } + CloseHandle(hSnapshot); + TerminateProcess( + OpenProcess( + PROCESS_TERMINATE, + FALSE, + GetCurrentProcessId() + ), + 0 + ); + } + } + else + { + dwInjectedAddr += (uintptr_t)symbols_PTRS.explorer_PTRS[0] + start; + if (strat == 0) + { + VirtualProtectEx( + hExplorer, + (LPVOID)dwInjectedAddr, + sizeof(szPayload0), + PAGE_EXECUTE_READWRITE, + &dwOldValue + ); + WriteProcessMemory( + hExplorer, + (LPVOID)dwInjectedAddr, + szPayload0, + sizeof(szPayload0), + &dwNumberOfBytes + ); + VirtualProtectEx( + hExplorer, + (LPVOID)dwInjectedAddr, + sizeof(szPayload0), + dwOldValue, + (PDWORD)(&dwNumberOfBytes) + ); + } + else if (strat == 1) + { + VirtualProtectEx( + hExplorer, + (LPVOID)dwInjectedAddr, + sizeof(szPayload1), + PAGE_EXECUTE_READWRITE, + &dwOldValue + ); + WriteProcessMemory( + hExplorer, + (LPVOID)dwInjectedAddr, + szPayload1, + sizeof(szPayload1), + &dwNumberOfBytes + ); + VirtualProtectEx( + hExplorer, + (LPVOID)dwInjectedAddr, + sizeof(szPayload1), + dwOldValue, + (PDWORD)(&dwNumberOfBytes) + ); + } + DebugActiveProcessStop(dwExplorerPID); + // WaitForSingleObject( + // hExplorer, + // INFINITE + // ); } CloseHandle(hExplorer); } else { DebugActiveProcessStop(dwExplorerPID); + TerminateProcess( + OpenProcess( + PROCESS_TERMINATE, + FALSE, + GetCurrentProcessId() + ), + 0 + ); } GetModuleFileName( diff --git a/ExplorerPatcherLibrary/ExplorerPatcherLibrary.rc b/ExplorerPatcherLibrary/ExplorerPatcherLibrary.rc index 0e26f3f..128e4db 100644 --- a/ExplorerPatcherLibrary/ExplorerPatcherLibrary.rc +++ b/ExplorerPatcherLibrary/ExplorerPatcherLibrary.rc @@ -51,8 +51,8 @@ END // VS_VERSION_INFO VERSIONINFO - FILEVERSION 22000,1,0,4 - PRODUCTVERSION 22000,1,0,4 + FILEVERSION 22000,1,0,5 + PRODUCTVERSION 22000,1,0,5 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -69,12 +69,12 @@ BEGIN BEGIN VALUE "CompanyName", "VALINET Solutions SRL" VALUE "FileDescription", "ExplorerPatcher Library" - VALUE "FileVersion", "22000.1.0.4" + VALUE "FileVersion", "22000.1.0.5" VALUE "InternalName", "ExplorerPatcherLibrary.dll" VALUE "LegalCopyright", "Copyright (C) 2006-2021 VALINET Solutions SRL. All rights reserved." VALUE "OriginalFilename", "ExplorerPatcherLibrary.dll" VALUE "ProductName", "WinOverview" - VALUE "ProductVersion", "22000.1.0.4" + VALUE "ProductVersion", "22000.1.0.5" END END BLOCK "VarFileInfo" diff --git a/ExplorerPatcherLibrary/ExplorerPatcherLibrary.vcxproj b/ExplorerPatcherLibrary/ExplorerPatcherLibrary.vcxproj index 326a8f7..942a7ff 100644 --- a/ExplorerPatcherLibrary/ExplorerPatcherLibrary.vcxproj +++ b/ExplorerPatcherLibrary/ExplorerPatcherLibrary.vcxproj @@ -92,6 +92,7 @@ NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true $(SolutionDir)libs\funchook\include;$(SolutionDir)libs\libvalinet;%(AdditionalIncludeDirectories) + MultiThreaded Console @@ -116,6 +117,7 @@ true _DEBUG;_CONSOLE;%(PreprocessorDefinitions) true + MultiThreadedDebug Console @@ -137,6 +139,7 @@ _DEBUG;_CONSOLE;%(PreprocessorDefinitions) true $(SolutionDir)libs\funchook\include;$(SolutionDir)libs\libvalinet;%(AdditionalIncludeDirectories) + MultiThreadedDebug Console @@ -161,6 +164,7 @@ true NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true + MultiThreaded Console diff --git a/ExplorerPatcherLibrary/dllmain.c b/ExplorerPatcherLibrary/dllmain.c index 1e07380..2fe3562 100644 --- a/ExplorerPatcherLibrary/dllmain.c +++ b/ExplorerPatcherLibrary/dllmain.c @@ -9,6 +9,81 @@ #include #include #pragma comment(lib, "UxTheme.lib") +#include +#include +#define _LIBVALINET_INCLUDE_UNIVERSAL +#include + +#define APPID L"Microsoft.Windows.Explorer" +#define SYMBOLS_RELATIVE_PATH "\\settings.ini" +#define EXPLORER_SB_NAME "explorer" +#define EXPLORER_SB_0 "CTray::_HandleGlobalHotkey" +#define EXPLORER_SB_CNT 1 +#define TWINUI_PCSHELL_SB_NAME "twinui.pcshell" +#define TWINUI_PCSHELL_SB_0 "CImmersiveContextMenuOwnerDrawHelper::s_ContextMenuWndProc" +#define TWINUI_PCSHELL_SB_1 "CLauncherTipContextMenu::GetMenuItemsAsync" +#define TWINUI_PCSHELL_SB_2 "ImmersiveContextMenuHelper::ApplyOwnerDrawToMenu" +#define TWINUI_PCSHELL_SB_3 "ImmersiveContextMenuHelper::RemoveOwnerDrawFromMenu" +#define TWINUI_PCSHELL_SB_4 "CLauncherTipContextMenu::_ExecuteShutdownCommand" +#define TWINUI_PCSHELL_SB_5 "CLauncherTipContextMenu::_ExecuteCommand" +#define TWINUI_PCSHELL_SB_6 "CLauncherTipContextMenu::ShowLauncherTipContextMenu" +#define TWINUI_PCSHELL_SB_CNT 7 +#define TWINUI_SB_NAME "twinui" +#define TWINUI_SB_0 "CImmersiveHotkeyNotification::_GetMonitorForHotkeyNotification" +#define TWINUI_SB_1 "IsDesktopInputContext" +#define TWINUI_SB_2 "CImmersiveHotkeyNotification::OnMessage" +#define TWINUI_SB_CNT 3 +const char* explorer_SN[EXPLORER_SB_CNT] = { + EXPLORER_SB_0 +}; +const char* twinui_pcshell_SN[TWINUI_PCSHELL_SB_CNT] = { + TWINUI_PCSHELL_SB_0, + TWINUI_PCSHELL_SB_1, + TWINUI_PCSHELL_SB_2, + TWINUI_PCSHELL_SB_3, + TWINUI_PCSHELL_SB_4, + TWINUI_PCSHELL_SB_5, + TWINUI_PCSHELL_SB_6 +}; +const char* twinui_SN[TWINUI_SB_CNT] = { + TWINUI_SB_0, + TWINUI_SB_1, + TWINUI_SB_2 +}; +#pragma pack(push, 1) +typedef struct symbols_addr +{ + DWORD explorer_PTRS[EXPLORER_SB_CNT]; + DWORD twinui_pcshell_PTRS[TWINUI_PCSHELL_SB_CNT]; + DWORD twinui_PTRS[TWINUI_SB_CNT]; +} symbols_addr; +#pragma pack(pop) + +wchar_t DownloadSymbolsXML[] = +L"\r\n" +L" \r\n" +L" \r\n" +L" \r\n" +L" \r\n" +L" \r\n" +L" \r\n" +L" \r\n" +L" \r\n"; + +wchar_t DownloadOKXML[] = +L"\r\n" +L" \r\n" +L" \r\n" +L" \r\n" +L" \r\n" +L" \r\n" +L" \r\n" +L" \r\n" +L" \r\n"; #define DEBUG #undef DEBUG @@ -19,6 +94,32 @@ HWND messageWindow = NULL; HANDLE hIsWinXShown = NULL; INT64 lockEnsureWinXHotkeyOnlyOnce; +typedef LONG NTSTATUS, * PNTSTATUS; +#define STATUS_SUCCESS (0x00000000) + +typedef NTSTATUS(WINAPI* RtlGetVersionPtr)(PRTL_OSVERSIONINFOW); + +BOOL GetOSVersion(PRTL_OSVERSIONINFOW lpRovi) +{ + HMODULE hMod = GetModuleHandleW(L"ntdll.dll"); + if (hMod != NULL) + { + RtlGetVersionPtr fxPtr = (RtlGetVersionPtr)GetProcAddress( + hMod, + "RtlGetVersion" + ); + if (fxPtr != NULL) + { + lpRovi->dwOSVersionInfoSize = sizeof(RTL_OSVERSIONINFOW); + if (STATUS_SUCCESS == fxPtr(lpRovi)) + { + return TRUE; + } + } + } + return FALSE; +} + static HWND(WINAPI* CreateWindowInBand)( _In_ DWORD dwExStyle, _In_opt_ ATOM atom, @@ -42,22 +143,17 @@ static INT64(*CLauncherTipContextMenu_ShowLauncherTipContextMenuFunc)( POINT* pt ); -static void(*CLauncherTipContextMenu_ExecuteCommand)( +static void(*CLauncherTipContextMenu_ExecuteCommandFunc)( void* _this, int a2 ); -static void(*CLauncherTipContextMenu_ExecuteShutdownCommand)( +static void(*CLauncherTipContextMenu_ExecuteShutdownCommandFunc)( void* _this, void* a2 ); -static INT64(*InternalAddRef)( - void* a1, - INT64 a2 - ); - -static INT64(*ImmersiveContextMenuHelper_ApplyOwnerDrawToMenu)( +static INT64(*ImmersiveContextMenuHelper_ApplyOwnerDrawToMenuFunc)( HMENU h1, HMENU h2, HWND a3, @@ -65,19 +161,19 @@ static INT64(*ImmersiveContextMenuHelper_ApplyOwnerDrawToMenu)( void* data ); -static void(*ImmersiveContextMenuHelper_RemoveOwnerDrawFromMenu)( +static void(*ImmersiveContextMenuHelper_RemoveOwnerDrawFromMenuFunc)( HMENU _this, HMENU hWnd, HWND a3 ); -static INT64(*CLauncherTipContextMenu_GetMenuItemsAsync)( +static INT64(*CLauncherTipContextMenu_GetMenuItemsAsyncFunc)( void* _this, void* rect, void** iunk ); -static INT64(*CImmersiveContextMenuOwnerDrawHelper_s_ContextMenuWndProc)( +static INT64(*CImmersiveContextMenuOwnerDrawHelper_s_ContextMenuWndProcFunc)( HWND hWnd, int a2, HWND a3, @@ -296,7 +392,7 @@ LRESULT CALLBACK CLauncherTipContextMenu_WndProc( { BOOL v12 = FALSE; if ((uMsg == WM_DRAWITEM || uMsg == WM_MEASUREITEM) && - CImmersiveContextMenuOwnerDrawHelper_s_ContextMenuWndProc( + CImmersiveContextMenuOwnerDrawHelper_s_ContextMenuWndProcFunc( hWnd, uMsg, wParam, @@ -386,7 +482,7 @@ DWORD ShowLauncherTipContextMenu( } INT64* unknown_array = calloc(4, sizeof(INT64)); - ImmersiveContextMenuHelper_ApplyOwnerDrawToMenu( + ImmersiveContextMenuHelper_ApplyOwnerDrawToMenuFunc( *((HMENU*)((char*)params->_this + 0xe8)), hWnd, &(params->point), @@ -404,7 +500,7 @@ DWORD ShowLauncherTipContextMenu( 0 ); - ImmersiveContextMenuHelper_RemoveOwnerDrawFromMenu( + ImmersiveContextMenuHelper_RemoveOwnerDrawFromMenuFunc( *((HMENU*)((char*)params->_this + 0xe8)), hWnd, &(params->point) @@ -416,7 +512,7 @@ DWORD ShowLauncherTipContextMenu( if (res < 4000) { INT64 info = *(INT64*)((char*)(*(INT64*)((char*)params->_this + 0xa8 - 0x58)) + (INT64)res * 8 - 8); - CLauncherTipContextMenu_ExecuteCommand( + CLauncherTipContextMenu_ExecuteCommandFunc( (char*)params->_this - 0x58, &info ); @@ -424,7 +520,7 @@ DWORD ShowLauncherTipContextMenu( else { INT64 info = *(INT64*)((char*)(*(INT64*)((char*)params->_this + 0xc8 - 0x58)) + ((INT64)res - 4000) * 8); - CLauncherTipContextMenu_ExecuteShutdownCommand( + CLauncherTipContextMenu_ExecuteShutdownCommandFunc( (char*)params->_this - 0x58, &info ); @@ -503,7 +599,7 @@ INT64 CLauncherTipContextMenu_ShowLauncherTipContextMenuHook( } IUnknown* iunk; - INT64 r = CLauncherTipContextMenu_GetMenuItemsAsync( + INT64 r = CLauncherTipContextMenu_GetMenuItemsAsyncFunc( _this, &point, &iunk @@ -853,6 +949,7 @@ __declspec(dllexport) DWORD WINAPI main( messageWindow = (HWND)lpParameter; + funchook = funchook_create(); @@ -867,9 +964,480 @@ __declspec(dllexport) DWORD WINAPI main( ); + + DWORD dwRet = 0; + char szSettingsPath[MAX_PATH]; + ZeroMemory( + szSettingsPath, + (MAX_PATH) * sizeof(char) + ); + TCHAR wszSettingsPath[MAX_PATH]; + ZeroMemory( + wszSettingsPath, + (MAX_PATH) * sizeof(TCHAR) + ); + GetModuleFileNameA( + hModule, + szSettingsPath, + MAX_PATH + ); + PathRemoveFileSpecA(szSettingsPath); + strcat_s( + szSettingsPath, + MAX_PATH, + SYMBOLS_RELATIVE_PATH + ); + mbstowcs_s( + &dwRet, + wszSettingsPath, + MAX_PATH, + szSettingsPath, + MAX_PATH + ); + + symbols_addr symbols_PTRS; + ZeroMemory( + &symbols_PTRS, + sizeof(symbols_addr) + ); + symbols_PTRS.explorer_PTRS[0] = VnGetUInt( + TEXT(EXPLORER_SB_NAME), + TEXT(EXPLORER_SB_0), + 0, + wszSettingsPath + ); + + symbols_PTRS.twinui_pcshell_PTRS[0] = VnGetUInt( + TEXT(TWINUI_PCSHELL_SB_NAME), + TEXT(TWINUI_PCSHELL_SB_0), + 0, + wszSettingsPath + ); + symbols_PTRS.twinui_pcshell_PTRS[1] = VnGetUInt( + TEXT(TWINUI_PCSHELL_SB_NAME), + TEXT(TWINUI_PCSHELL_SB_1), + 0, + wszSettingsPath + ); + symbols_PTRS.twinui_pcshell_PTRS[2] = VnGetUInt( + TEXT(TWINUI_PCSHELL_SB_NAME), + TEXT(TWINUI_PCSHELL_SB_2), + 0, + wszSettingsPath + ); + symbols_PTRS.twinui_pcshell_PTRS[3] = VnGetUInt( + TEXT(TWINUI_PCSHELL_SB_NAME), + TEXT(TWINUI_PCSHELL_SB_3), + 0, + wszSettingsPath + ); + symbols_PTRS.twinui_pcshell_PTRS[4] = VnGetUInt( + TEXT(TWINUI_PCSHELL_SB_NAME), + TEXT(TWINUI_PCSHELL_SB_4), + 0, + wszSettingsPath + ); + symbols_PTRS.twinui_pcshell_PTRS[5] = VnGetUInt( + TEXT(TWINUI_PCSHELL_SB_NAME), + TEXT(TWINUI_PCSHELL_SB_5), + 0, + wszSettingsPath + ); + symbols_PTRS.twinui_pcshell_PTRS[6] = VnGetUInt( + TEXT(TWINUI_PCSHELL_SB_NAME), + TEXT(TWINUI_PCSHELL_SB_6), + 0, + wszSettingsPath + ); + + symbols_PTRS.twinui_PTRS[0] = VnGetUInt( + TEXT(TWINUI_SB_NAME), + TEXT(TWINUI_SB_0), + 0, + wszSettingsPath + ); + symbols_PTRS.twinui_PTRS[1] = VnGetUInt( + TEXT(TWINUI_SB_NAME), + TEXT(TWINUI_SB_1), + 0, + wszSettingsPath + ); + symbols_PTRS.twinui_PTRS[2] = VnGetUInt( + TEXT(TWINUI_SB_NAME), + TEXT(TWINUI_SB_2), + 0, + wszSettingsPath + ); + + BOOL bNeedToDownload = FALSE; + for (UINT i = 0; i < sizeof(symbols_addr) / sizeof(DWORD); ++i) + { + if (!((DWORD*)&symbols_PTRS)[i]) + { + bNeedToDownload = TRUE; + } + } + // https://stackoverflow.com/questions/36543301/detecting-windows-10-version/36543774#36543774 + RTL_OSVERSIONINFOW rovi; + if (!GetOSVersion(&rovi)) + { + FreeLibraryAndExitThread( + hModule, + 1 + ); + return 1; + } + // https://stackoverflow.com/questions/47926094/detecting-windows-10-os-build-minor-version + DWORD32 ubr = 0, ubr_size = sizeof(DWORD32); + HKEY hKey; + LONG lRes = RegOpenKeyExW( + HKEY_LOCAL_MACHINE, + wcschr( + wcschr( + wcschr( + UNIFIEDBUILDREVISION_KEY, + '\\' + ) + 1, + '\\' + ) + 1, + '\\' + ) + 1, + 0, + KEY_READ, + &hKey + ); + if (lRes == ERROR_SUCCESS) + { + RegQueryValueExW( + hKey, + UNIFIEDBUILDREVISION_VALUE, + 0, + NULL, + &ubr, + &ubr_size + ); + } + TCHAR szReportedVersion[MAX_PATH]; + ZeroMemory( + szReportedVersion, + (MAX_PATH) * sizeof(TCHAR) + ); + TCHAR szStoredVersion[MAX_PATH]; + ZeroMemory( + szStoredVersion, + (MAX_PATH) * sizeof(TCHAR) + ); + wsprintf( + szReportedVersion, + L"%d.%d.%d.%d", + rovi.dwMajorVersion, + rovi.dwMinorVersion, + rovi.dwBuildNumber, + ubr + ); + VnGetString( + TEXT("OS"), + TEXT("Build"), + szStoredVersion, + MAX_PATH, + MAX_PATH, + NULL, + wszSettingsPath + ); + if (!bNeedToDownload) + { + bNeedToDownload = wcscmp(szReportedVersion, szStoredVersion); + } + + if (bNeedToDownload) + { + TCHAR buffer[sizeof(DownloadSymbolsXML) / sizeof(wchar_t) + 30]; + ZeroMemory( + buffer, + (sizeof(DownloadSymbolsXML) / sizeof(wchar_t) + 30) * sizeof(TCHAR) + ); + wsprintf( + buffer, + DownloadSymbolsXML, + szReportedVersion + ); + HRESULT hr = S_OK; + __x_ABI_CWindows_CData_CXml_CDom_CIXmlDocument* inputXml = NULL; + hr = String2IXMLDocument( + buffer, + wcslen(buffer), + &inputXml, +#ifdef DEBUG + stdout +#else + NULL +#endif + ); + hr = ShowToastMessage( + inputXml, + APPID, + sizeof(APPID) / sizeof(TCHAR) - 1, +#ifdef DEBUG + stdout +#else + NULL +#endif + ); + char explorer_sb_exe[MAX_PATH]; + ZeroMemory( + explorer_sb_exe, + (MAX_PATH) * sizeof(char) + ); + GetWindowsDirectoryA( + explorer_sb_exe, + MAX_PATH + ); + strcat_s( + explorer_sb_exe, + MAX_PATH, + "\\" + ); + strcat_s( + explorer_sb_exe, + MAX_PATH, + EXPLORER_SB_NAME + ); + strcat_s( + explorer_sb_exe, + MAX_PATH, + ".exe" + ); + if (VnDownloadSymbols( + NULL, + explorer_sb_exe, + szSettingsPath, + MAX_PATH + )) + { + FreeLibraryAndExitThread( + hModule, + 2 + ); + return 2; + } + if (VnGetSymbols( + szSettingsPath, + symbols_PTRS.explorer_PTRS, + explorer_SN, + EXPLORER_SB_CNT + )) + { + FreeLibraryAndExitThread( + hModule, + 3 + ); + return 3; + } + VnWriteUInt( + TEXT(EXPLORER_SB_NAME), + TEXT(EXPLORER_SB_0), + symbols_PTRS.explorer_PTRS[0], + wszSettingsPath + ); + + char twinui_pcshell_sb_dll[MAX_PATH]; + ZeroMemory( + twinui_pcshell_sb_dll, + (MAX_PATH) * sizeof(char) + ); + GetSystemDirectoryA( + twinui_pcshell_sb_dll, + MAX_PATH + ); + strcat_s( + twinui_pcshell_sb_dll, + MAX_PATH, + "\\" + ); + strcat_s( + twinui_pcshell_sb_dll, + MAX_PATH, + TWINUI_PCSHELL_SB_NAME + ); + strcat_s( + twinui_pcshell_sb_dll, + MAX_PATH, + ".dll" + ); + if (VnDownloadSymbols( + NULL, + twinui_pcshell_sb_dll, + szSettingsPath, + MAX_PATH + )) + { + FreeLibraryAndExitThread( + hModule, + 4 + ); + return 4; + } + if (VnGetSymbols( + szSettingsPath, + symbols_PTRS.twinui_pcshell_PTRS, + twinui_pcshell_SN, + TWINUI_PCSHELL_SB_CNT + )) + { + FreeLibraryAndExitThread( + hModule, + 5 + ); + return 5; + } + VnWriteUInt( + TEXT(TWINUI_PCSHELL_SB_NAME), + TEXT(TWINUI_PCSHELL_SB_0), + symbols_PTRS.twinui_pcshell_PTRS[0], + wszSettingsPath + ); + VnWriteUInt( + TEXT(TWINUI_PCSHELL_SB_NAME), + TEXT(TWINUI_PCSHELL_SB_1), + symbols_PTRS.twinui_pcshell_PTRS[1], + wszSettingsPath + ); + VnWriteUInt( + TEXT(TWINUI_PCSHELL_SB_NAME), + TEXT(TWINUI_PCSHELL_SB_2), + symbols_PTRS.twinui_pcshell_PTRS[2], + wszSettingsPath + ); + VnWriteUInt( + TEXT(TWINUI_PCSHELL_SB_NAME), + TEXT(TWINUI_PCSHELL_SB_3), + symbols_PTRS.twinui_pcshell_PTRS[3], + wszSettingsPath + ); + VnWriteUInt( + TEXT(TWINUI_PCSHELL_SB_NAME), + TEXT(TWINUI_PCSHELL_SB_4), + symbols_PTRS.twinui_pcshell_PTRS[4], + wszSettingsPath + ); + VnWriteUInt( + TEXT(TWINUI_PCSHELL_SB_NAME), + TEXT(TWINUI_PCSHELL_SB_5), + symbols_PTRS.twinui_pcshell_PTRS[5], + wszSettingsPath + ); + VnWriteUInt( + TEXT(TWINUI_PCSHELL_SB_NAME), + TEXT(TWINUI_PCSHELL_SB_6), + symbols_PTRS.twinui_pcshell_PTRS[6], + wszSettingsPath + ); + + char twinui_sb_dll[MAX_PATH]; + ZeroMemory( + twinui_sb_dll, + (MAX_PATH) * sizeof(char) + ); + GetSystemDirectoryA( + twinui_sb_dll, + MAX_PATH + ); + strcat_s( + twinui_sb_dll, + MAX_PATH, + "\\" + ); + strcat_s( + twinui_sb_dll, + MAX_PATH, + TWINUI_SB_NAME + ); + strcat_s( + twinui_sb_dll, + MAX_PATH, + ".dll" + ); + if (VnDownloadSymbols( + NULL, + twinui_sb_dll, + szSettingsPath, + MAX_PATH + )) + { + FreeLibraryAndExitThread( + hModule, + 6 + ); + return 6; + } + if (VnGetSymbols( + szSettingsPath, + symbols_PTRS.twinui_PTRS, + twinui_SN, + TWINUI_SB_CNT + )) + { + FreeLibraryAndExitThread( + hModule, + 7 + ); + return 7; + } + VnWriteUInt( + TEXT(TWINUI_SB_NAME), + TEXT(TWINUI_SB_0), + symbols_PTRS.twinui_PTRS[0], + wszSettingsPath + ); + VnWriteUInt( + TEXT(TWINUI_SB_NAME), + TEXT(TWINUI_SB_1), + symbols_PTRS.twinui_PTRS[1], + wszSettingsPath + ); + VnWriteUInt( + TEXT(TWINUI_SB_NAME), + TEXT(TWINUI_SB_2), + symbols_PTRS.twinui_PTRS[2], + wszSettingsPath + ); + + VnWriteString( + TEXT("OS"), + TEXT("Build"), + szReportedVersion, + wszSettingsPath + ); + + __x_ABI_CWindows_CData_CXml_CDom_CIXmlDocument* inputXml2 = NULL; + hr = String2IXMLDocument( + DownloadOKXML, + wcslen(DownloadOKXML), + &inputXml2, +#ifdef DEBUG + stdout +#else + NULL +#endif + ); + hr = ShowToastMessage( + inputXml2, + APPID, + sizeof(APPID) / sizeof(TCHAR) - 1, +#ifdef DEBUG + stdout +#else + NULL +#endif + ); + } + + + + HANDLE hExplorer = GetModuleHandle(NULL); CTray_HandleGlobalHotkeyFunc = (INT64(*)(void*, unsigned int, unsigned int)) - ((uintptr_t)hExplorer + 0x117F8); + ((uintptr_t)hExplorer + symbols_PTRS.explorer_PTRS[0]); rv = funchook_prepare( funchook, (void**)&CTray_HandleGlobalHotkeyFunc, @@ -890,29 +1458,26 @@ __declspec(dllexport) DWORD WINAPI main( HANDLE hTwinuiPcshell = GetModuleHandle(L"twinui.pcshell.dll"); - CImmersiveContextMenuOwnerDrawHelper_s_ContextMenuWndProc = (INT64(*)(HWND, int, HWND, int, BOOL*)) - ((uintptr_t)hTwinuiPcshell + 0xB0E12); + CImmersiveContextMenuOwnerDrawHelper_s_ContextMenuWndProcFunc = (INT64(*)(HWND, int, HWND, int, BOOL*)) + ((uintptr_t)hTwinuiPcshell + symbols_PTRS.twinui_pcshell_PTRS[0]); - InternalAddRef = (INT64(*)(void*, INT64)) - ((uintptr_t)hTwinuiPcshell + 0x46650); + CLauncherTipContextMenu_GetMenuItemsAsyncFunc = (INT64(*)(void*, void*, void**)) + ((uintptr_t)hTwinuiPcshell + symbols_PTRS.twinui_pcshell_PTRS[1]); + + ImmersiveContextMenuHelper_ApplyOwnerDrawToMenuFunc = (INT64(*)(HMENU, HMENU, HWND, unsigned int, void*)) + ((uintptr_t)hTwinuiPcshell + symbols_PTRS.twinui_pcshell_PTRS[2]); - CLauncherTipContextMenu_GetMenuItemsAsync = (INT64(*)(void*, void*, void**)) - ((uintptr_t)hTwinuiPcshell + 0x5051F0); + ImmersiveContextMenuHelper_RemoveOwnerDrawFromMenuFunc = (void(*)(HMENU, HMENU, HWND)) + ((uintptr_t)hTwinuiPcshell + symbols_PTRS.twinui_pcshell_PTRS[3]); - ImmersiveContextMenuHelper_ApplyOwnerDrawToMenu = (INT64(*)(HMENU, HMENU, HWND, unsigned int, void*)) - ((uintptr_t)hTwinuiPcshell + 0x535AF8); - - ImmersiveContextMenuHelper_RemoveOwnerDrawFromMenu = (void(*)(HMENU, HMENU, HWND)) - ((uintptr_t)hTwinuiPcshell + 0x536300); + CLauncherTipContextMenu_ExecuteShutdownCommandFunc = (void(*)(void*, void*)) + ((uintptr_t)hTwinuiPcshell + symbols_PTRS.twinui_pcshell_PTRS[4]); - CLauncherTipContextMenu_ExecuteShutdownCommand = (void(*)(void*, void*)) - ((uintptr_t)hTwinuiPcshell + 0x514714); - - CLauncherTipContextMenu_ExecuteCommand = (void(*)(void*, int)) - ((uintptr_t)hTwinuiPcshell + 0x5143D0); + CLauncherTipContextMenu_ExecuteCommandFunc = (void(*)(void*, int)) + ((uintptr_t)hTwinuiPcshell + symbols_PTRS.twinui_pcshell_PTRS[5]); CLauncherTipContextMenu_ShowLauncherTipContextMenuFunc = (INT64(*)(void*, POINT*)) - ((uintptr_t)hTwinuiPcshell + 0x506EE0); + ((uintptr_t)hTwinuiPcshell + symbols_PTRS.twinui_pcshell_PTRS[6]); rv = funchook_prepare( funchook, (void**)&CLauncherTipContextMenu_ShowLauncherTipContextMenuFunc, @@ -929,13 +1494,13 @@ __declspec(dllexport) DWORD WINAPI main( HANDLE hTwinui = GetModuleHandle(L"twinui.dll"); CImmersiveHotkeyNotification_GetMonitorForHotkeyNotificationFunc = (INT64(*)(void*, void**, HWND*)) - ((uintptr_t)hTwinui + 0x24B4A8); + ((uintptr_t)hTwinui + symbols_PTRS.twinui_PTRS[0]); IsDesktopInputContextFunc = (BOOL(*)(void*, void*)) - ((uintptr_t)hTwinui + 0x24A5C4); + ((uintptr_t)hTwinui + symbols_PTRS.twinui_PTRS[1]); CImmersiveHotkeyNotification_OnMessageFunc = (HRESULT(*)(void*, INT64, INT, INT64)) - ((uintptr_t)hTwinui + 0xB2A70); + ((uintptr_t)hTwinui + symbols_PTRS.twinui_PTRS[2]); rv = funchook_prepare( funchook, (void**)&CImmersiveHotkeyNotification_OnMessageFunc, diff --git a/PostBuildCommand/PostBuildCommand.vcxproj b/PostBuildCommand/PostBuildCommand.vcxproj index cf49a53..af2b2c4 100644 --- a/PostBuildCommand/PostBuildCommand.vcxproj +++ b/PostBuildCommand/PostBuildCommand.vcxproj @@ -69,16 +69,16 @@ taskkill /f /im:sihost.exe 2>nul &set errorlevel=0 - taskkill /f /im:sihost.exe 2>nul &set errorlevel=0 + rem taskkill /f /im:sihost.exe 2>nul &set errorlevel=0 PostBuildCommand.exe WIN32;_DEBUG;$(NMakePreprocessorDefinitions) - taskkill /f /im:sihost.exe 2>nul &set errorlevel=0 + rem taskkill /f /im:sihost.exe 2>nul &set errorlevel=0 - taskkill /f /im:sihost.exe 2>nul &set errorlevel=0 + rem taskkill /f /im:sihost.exe 2>nul &set errorlevel=0 PostBuildCommand.exe _DEBUG;$(NMakePreprocessorDefinitions) - taskkill /f /im:sihost.exe 2>nul &set errorlevel=0 + rem taskkill /f /im:sihost.exe 2>nul &set errorlevel=0 taskkill /f /im:sihost.exe 2>nul &set errorlevel=0 diff --git a/PreBuildCommand/PreBuildCommand.vcxproj b/PreBuildCommand/PreBuildCommand.vcxproj index 376eb13..465143a 100644 --- a/PreBuildCommand/PreBuildCommand.vcxproj +++ b/PreBuildCommand/PreBuildCommand.vcxproj @@ -63,22 +63,22 @@ - taskkill /f /im:explorer.exe 2>nul &set errorlevel=0 + rem taskkill /f /im:explorer.exe 2>nul &set errorlevel=0 PreBuildCommand.exe NDEBUG;$(NMakePreprocessorDefinitions) - taskkill /f /im:explorer.exe 2>nul &set errorlevel=0 + rem taskkill /f /im:explorer.exe 2>nul &set errorlevel=0 - taskkill /f /im:explorer.exe 2>nul &set errorlevel=0 + rem taskkill /f /im:explorer.exe 2>nul &set errorlevel=0 PreBuildCommand.exe WIN32;_DEBUG;$(NMakePreprocessorDefinitions) - taskkill /f /im:explorer.exe 2>nul &set errorlevel=0 + rem taskkill /f /im:explorer.exe 2>nul &set errorlevel=0 - taskkill /f /im:explorer.exe 2>nul &set errorlevel=0 + rem taskkill /f /im:explorer.exe 2>nul &set errorlevel=0 PreBuildCommand.exe _DEBUG;$(NMakePreprocessorDefinitions) - taskkill /f /im:explorer.exe 2>nul &set errorlevel=0 + rem taskkill /f /im:explorer.exe 2>nul &set errorlevel=0 taskkill /f /im:explorer.exe 2>nul &set errorlevel=0 diff --git a/README.md b/README.md index aca58f1..afe8ca6 100644 --- a/README.md +++ b/README.md @@ -5,14 +5,12 @@ Explorer Patcher is a patcher that enables various stuff in Explorer. For the mo * enables the power user menu (Win+X) when using the classic taskbar in Windows 11 * shows the Start menu on the monitor containing the cursor when invoked with the Windows key -This has been tested only on Windows 11 build 22000.1. It probably does not work on other builds due to different offsets in explorer.exe and its libraries. Once this matures, a solution will be offered for dynamically determining the necessary offsets. As it stands, the application is more in a proof of concept phase. +This has been tested only on Windows 11 build 22000.1. ~~It probably does not work on other builds due to different offsets in explorer.exe and its libraries. Once this matures, a solution will be offered for dynamically determining the necessary offsets. As it stands, the application is more in a proof of concept phase.~~ It should work on higher builds, provided that the OS components' structure has not changed too drastically. The library is able to automatically download symbols and determine the offsets for correctly hooking the functions. A detailed description of how this works is available on my web site [here](https://valinet.ro/2021/08/09/Restore-Windows-11-to-working-Windows-10-UI.html). Precompiled binaries are available in [Releases](https://github.com/valinet/ExplorerPatcher/releases). -Please help me fix the known issues described below in order to get feature parity with regular Windows 10 releases. As it stands, the application works but it is not perfect, yet. - ## Installation To install, save the executable in a safe directory, run it once as an administrator to have it register as [Taskman](https://www.geoffchappell.com/notes/windows/shell/explorer/taskman.htm) for Explorer and just restart Explorer or reboot. @@ -58,13 +56,20 @@ Steps: md build cd build cmake -G "Visual Studio 16 2019" -A x64 .. - cmake --build . --config Release ``` If "cmake" is not found as a command, type its full path, or have its folder added to PATH. Type "Win32" instead of "x64" above, if compiling for x86. The command above works for x64. + Now, in the `libs\funchook\build` folder, open the file `funchook-static.vcxproj` with any text editor, search and replace all occurences of `MultiThreadedDLL` with `MultiThreaded`. + + Once done, you can now compile funchook: + + ``` + cmake --build . --config Release + ``` + 3. Compile ExplorerPatcher * Double click the ExplorerPatcher.sln to open the solution in Visual Studio. Choose Release and your processor architecture in the toolbar. Press F6 to compile. diff --git a/libs/libvalinet b/libs/libvalinet index d345b62..b8aefad 160000 --- a/libs/libvalinet +++ b/libs/libvalinet @@ -1 +1 @@ -Subproject commit d345b62ab1062b9414a1db934c69ce777d467169 +Subproject commit b8aefade48424ff76db4509f347cc52557ca2d5e