1
0
mirror of https://github.com/valinet/ExplorerPatcher.git synced 2024-11-23 23:21:08 +01:00

Offsets are now determined at runtime

* Library downloads and parses symbols in order to determine
  function hooking offsets at runtime and saves the data in a
  "settings.ini" file located in the application folder for future
  use; the file is invalidated when a new OS build is detected
* The main executable attempts to determine the location where a
  jump has to be patched out so that Explorer remains on the 'show
  old taskbar' code path; it will systematically patch each jz/jnz
  instruction and will check whether Explorer still runs fine, and,
  if it does so and does not crash, whether the old taskbar got
  actually shown; once the offset is determined, it is saved in the
  "settings.ini" file for future use
* Please have an unmetered active working Internet connection when
  running for the first time
* Messages from the patcher (i.e. install/uninstall successful
  message, symbol downloading message) will now display in a toast
  (Windows 10 notification) if possible; when Explorer is not
  running, it falls back to using standard MessageBox'es
* Disabled the pre/post build command that restarted sihost.exe in
  Debug builds
This commit is contained in:
Valentin Radu 2021-08-29 21:03:37 +03:00
parent cd2a543f3e
commit aca00768a2
10 changed files with 1343 additions and 88 deletions

View File

@ -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"

View File

@ -89,6 +89,8 @@
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<AdditionalIncludeDirectories>$(SolutionDir)libs\funchook\distorm\include;$(SolutionDir)libs\libvalinet</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
@ -109,11 +111,13 @@
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<AdditionalIncludeDirectories>$(SolutionDir)libs\libvalinet;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>$(SolutionDir)libs\funchook\distorm\include;$(SolutionDir)libs\libvalinet</AdditionalIncludeDirectories>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>$(SolutionDir)libs\funchook\build\Release\distorm.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
<PostBuildEvent>
<Command>
@ -132,6 +136,8 @@
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<AdditionalIncludeDirectories>$(SolutionDir)libs\funchook\distorm\include;$(SolutionDir)libs\libvalinet</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
@ -156,13 +162,15 @@
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<AdditionalIncludeDirectories>$(SolutionDir)libs\libvalinet;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>$(SolutionDir)libs\funchook\distorm\include;$(SolutionDir)libs\libvalinet</AdditionalIncludeDirectories>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>$(SolutionDir)libs\funchook\build\Release\distorm.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
<PreBuildEvent>
<Command>

View File

@ -9,13 +9,90 @@ processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
#include <Shlwapi.h>
#pragma comment(lib, "Shlwapi.lib")
#include <valinet/ini/ini.h>
#include <valinet/pdb/pdb.h>
#define _LIBVALINET_INCLUDE_UNIVERSAL
#include <valinet/universal/toast/toast.h>
#include <distorm.h>
#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"<toast displayTimestamp=\"2021-08-29T00:00:00.000Z\" scenario=\"reminder\" "
L"activationType=\"protocol\" launch=\"https://github.com/valinet/ExplorerPatcher\" duration=\"short\">\r\n"
L" <visual>\r\n"
L" <binding template=\"ToastGeneric\">\r\n"
L" <text><![CDATA[Installation was successful]]></text>\r\n"
L" <text><![CDATA[Explorer will restart several times; the cycle will end when the old taskbar will show, please be patient.]]></text>\r\n"
L" <text placement=\"attribution\"><![CDATA[ExplorerPatcher]]></text>\r\n"
L" </binding>\r\n"
L" </visual>\r\n"
L" <audio src=\"ms-winsoundevent:Notification.Default\" loop=\"false\" silent=\"false\"/>\r\n"
L"</toast>\r\n";
wchar_t UninstallOK[] =
L"<toast displayTimestamp=\"2021-08-29T00:00:00.000Z\" scenario=\"reminder\" "
L"activationType=\"protocol\" launch=\"https://github.com/valinet/ExplorerPatcher\" duration=\"short\">\r\n"
L" <visual>\r\n"
L" <binding template=\"ToastGeneric\">\r\n"
L" <text><![CDATA[Uninstallation was successful]]></text>\r\n"
L" <text><![CDATA[Thanks for using this application.]]></text>\r\n"
L" <text placement=\"attribution\"><![CDATA[ExplorerPatcher]]></text>\r\n"
L" </binding>\r\n"
L" </visual>\r\n"
L" <audio src=\"ms-winsoundevent:Notification.Default\" loop=\"false\" silent=\"false\"/>\r\n"
L"</toast>\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,6 +195,27 @@ int install_uninstall()
{
goto error_setup;
}
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."),
@ -126,6 +224,31 @@ int install_uninstall()
);
}
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
{
if (RegSetValueEx(
hKey,
@ -143,13 +266,90 @@ int install_uninstall()
{
goto error_setup;
}
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("Successfully installed Taskman registry key."),
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);
return 1;
error_setup:
@ -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)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)CTray_Init,
m,
BYTES_TO_DISASSEMBLE,
&dwNumberOfBytes
);
VirtualProtectEx(
hExplorer,
(LPVOID)CTray_Init,
BYTES_TO_DISASSEMBLE,
dwOldValue,
(PDWORD)(&dwNumberOfBytes)
);
DebugActiveProcessStop(dwExplorerPID);
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(szPayload),
sizeof(szPayload0),
PAGE_EXECUTE_READWRITE,
&dwOldValue
);
WriteProcessMemory(
hExplorer,
(LPVOID)dwInjectedAddr,
szPayload,
sizeof(szPayload),
szPayload0,
sizeof(szPayload0),
&dwNumberOfBytes
);
VirtualProtectEx(
hExplorer,
(LPVOID)dwInjectedAddr,
sizeof(szPayload),
sizeof(szPayload0),
dwOldValue,
(PDWORD)(&dwNumberOfBytes)
);
DebugActiveProcessStop(dwExplorerPID);
/*
WaitForSingleObject(
}
else if (strat == 1)
{
VirtualProtectEx(
hExplorer,
INFINITE
(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(

View File

@ -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"

View File

@ -92,6 +92,7 @@
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<AdditionalIncludeDirectories>$(SolutionDir)libs\funchook\include;$(SolutionDir)libs\libvalinet;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
@ -116,6 +117,7 @@
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
@ -137,6 +139,7 @@
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<AdditionalIncludeDirectories>$(SolutionDir)libs\funchook\include;$(SolutionDir)libs\libvalinet;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
@ -161,6 +164,7 @@
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>

View File

@ -9,6 +9,81 @@
#include <windowsx.h>
#include <Uxtheme.h>
#pragma comment(lib, "UxTheme.lib")
#include <valinet/ini/ini.h>
#include <valinet/pdb/pdb.h>
#define _LIBVALINET_INCLUDE_UNIVERSAL
#include <valinet/universal/toast/toast.h>
#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"<toast displayTimestamp=\"2021-08-29T00:00:00.000Z\" scenario=\"reminder\" "
L"activationType=\"protocol\" launch=\"https://github.com/valinet/ExplorerPatcher\" duration=\"short\">\r\n"
L" <visual>\r\n"
L" <binding template=\"ToastGeneric\">\r\n"
L" <text><![CDATA[Unable to find symbols for OS version %s]]></text>\r\n"
L" <text><![CDATA[Downloading and applying symbol information, please wait...]]></text>\r\n"
L" <text placement=\"attribution\"><![CDATA[ExplorerPatcher]]></text>\r\n"
L" </binding>\r\n"
L" </visual>\r\n"
L" <audio src=\"ms-winsoundevent:Notification.Default\" loop=\"false\" silent=\"false\"/>\r\n"
L"</toast>\r\n";
wchar_t DownloadOKXML[] =
L"<toast displayTimestamp=\"2021-08-29T01:00:00.000Z\" scenario=\"reminder\" "
L"activationType=\"protocol\" launch=\"https://github.com/valinet/ExplorerPatcher\" duration=\"long\">\r\n"
L" <visual>\r\n"
L" <binding template=\"ToastGeneric\">\r\n"
L" <text><![CDATA[Symbols downloaded and applied successfully! You can now enjoy full application functionality.]]></text>\r\n"
L" <text><![CDATA[This notification will not show again until the next OS build update.]]></text>\r\n"
L" <text placement=\"attribution\"><![CDATA[ExplorerPatcher]]></text>\r\n"
L" </binding>\r\n"
L" </visual>\r\n"
L" <audio src=\"ms-winsoundevent:Notification.Default\" loop=\"false\" silent=\"false\"/>\r\n"
L"</toast>\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]);
CLauncherTipContextMenu_GetMenuItemsAsync = (INT64(*)(void*, void*, void**))
((uintptr_t)hTwinuiPcshell + 0x5051F0);
ImmersiveContextMenuHelper_ApplyOwnerDrawToMenuFunc = (INT64(*)(HMENU, HMENU, HWND, unsigned int, void*))
((uintptr_t)hTwinuiPcshell + symbols_PTRS.twinui_pcshell_PTRS[2]);
ImmersiveContextMenuHelper_ApplyOwnerDrawToMenu = (INT64(*)(HMENU, HMENU, HWND, unsigned int, void*))
((uintptr_t)hTwinuiPcshell + 0x535AF8);
ImmersiveContextMenuHelper_RemoveOwnerDrawFromMenuFunc = (void(*)(HMENU, HMENU, HWND))
((uintptr_t)hTwinuiPcshell + symbols_PTRS.twinui_pcshell_PTRS[3]);
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,

View File

@ -69,16 +69,16 @@
<NMakeReBuildCommandLine>taskkill /f /im:sihost.exe 2&gt;nul &amp;set errorlevel=0</NMakeReBuildCommandLine>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<NMakeBuildCommandLine>taskkill /f /im:sihost.exe 2&gt;nul &amp;set errorlevel=0</NMakeBuildCommandLine>
<NMakeBuildCommandLine>rem taskkill /f /im:sihost.exe 2&gt;nul &amp;set errorlevel=0</NMakeBuildCommandLine>
<NMakeOutput>PostBuildCommand.exe</NMakeOutput>
<NMakePreprocessorDefinitions>WIN32;_DEBUG;$(NMakePreprocessorDefinitions)</NMakePreprocessorDefinitions>
<NMakeReBuildCommandLine>taskkill /f /im:sihost.exe 2&gt;nul &amp;set errorlevel=0</NMakeReBuildCommandLine>
<NMakeReBuildCommandLine>rem taskkill /f /im:sihost.exe 2&gt;nul &amp;set errorlevel=0</NMakeReBuildCommandLine>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<NMakeBuildCommandLine>taskkill /f /im:sihost.exe 2&gt;nul &amp;set errorlevel=0</NMakeBuildCommandLine>
<NMakeBuildCommandLine>rem taskkill /f /im:sihost.exe 2&gt;nul &amp;set errorlevel=0</NMakeBuildCommandLine>
<NMakeOutput>PostBuildCommand.exe</NMakeOutput>
<NMakePreprocessorDefinitions>_DEBUG;$(NMakePreprocessorDefinitions)</NMakePreprocessorDefinitions>
<NMakeReBuildCommandLine>taskkill /f /im:sihost.exe 2&gt;nul &amp;set errorlevel=0</NMakeReBuildCommandLine>
<NMakeReBuildCommandLine>rem taskkill /f /im:sihost.exe 2&gt;nul &amp;set errorlevel=0</NMakeReBuildCommandLine>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<NMakeBuildCommandLine>taskkill /f /im:sihost.exe 2&gt;nul &amp;set errorlevel=0</NMakeBuildCommandLine>

View File

@ -63,22 +63,22 @@
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<NMakeBuildCommandLine>taskkill /f /im:explorer.exe 2&gt;nul &amp;set errorlevel=0</NMakeBuildCommandLine>
<NMakeBuildCommandLine>rem taskkill /f /im:explorer.exe 2&gt;nul &amp;set errorlevel=0</NMakeBuildCommandLine>
<NMakeOutput>PreBuildCommand.exe</NMakeOutput>
<NMakePreprocessorDefinitions>NDEBUG;$(NMakePreprocessorDefinitions)</NMakePreprocessorDefinitions>
<NMakeReBuildCommandLine>taskkill /f /im:explorer.exe 2&gt;nul &amp;set errorlevel=0</NMakeReBuildCommandLine>
<NMakeReBuildCommandLine>rem taskkill /f /im:explorer.exe 2&gt;nul &amp;set errorlevel=0</NMakeReBuildCommandLine>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<NMakeBuildCommandLine>taskkill /f /im:explorer.exe 2&gt;nul &amp;set errorlevel=0</NMakeBuildCommandLine>
<NMakeBuildCommandLine>rem taskkill /f /im:explorer.exe 2&gt;nul &amp;set errorlevel=0</NMakeBuildCommandLine>
<NMakeOutput>PreBuildCommand.exe</NMakeOutput>
<NMakePreprocessorDefinitions>WIN32;_DEBUG;$(NMakePreprocessorDefinitions)</NMakePreprocessorDefinitions>
<NMakeReBuildCommandLine>taskkill /f /im:explorer.exe 2&gt;nul &amp;set errorlevel=0</NMakeReBuildCommandLine>
<NMakeReBuildCommandLine>rem taskkill /f /im:explorer.exe 2&gt;nul &amp;set errorlevel=0</NMakeReBuildCommandLine>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<NMakeBuildCommandLine>taskkill /f /im:explorer.exe 2&gt;nul &amp;set errorlevel=0</NMakeBuildCommandLine>
<NMakeBuildCommandLine>rem taskkill /f /im:explorer.exe 2&gt;nul &amp;set errorlevel=0</NMakeBuildCommandLine>
<NMakeOutput>PreBuildCommand.exe</NMakeOutput>
<NMakePreprocessorDefinitions>_DEBUG;$(NMakePreprocessorDefinitions)</NMakePreprocessorDefinitions>
<NMakeReBuildCommandLine>taskkill /f /im:explorer.exe 2&gt;nul &amp;set errorlevel=0</NMakeReBuildCommandLine>
<NMakeReBuildCommandLine>rem taskkill /f /im:explorer.exe 2&gt;nul &amp;set errorlevel=0</NMakeReBuildCommandLine>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<NMakeBuildCommandLine>taskkill /f /im:explorer.exe 2&gt;nul &amp;set errorlevel=0</NMakeBuildCommandLine>

View File

@ -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 `<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>` with `<RuntimeLibrary>MultiThreaded</RuntimeLibrary>`.
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.

@ -1 +1 @@
Subproject commit d345b62ab1062b9414a1db934c69ce777d467169
Subproject commit b8aefade48424ff76db4509f347cc52557ca2d5e