From 1971ba88d8458af1ac5c4711ac9655103a3329b7 Mon Sep 17 00:00:00 2001 From: Valentin Radu Date: Fri, 24 Dec 2021 15:43:53 +0200 Subject: [PATCH] Restoring default settings only asks for elevation if required --- CHANGELOG.md | 1 + ExplorerPatcher/GUI.c | 169 ++++++++++++++++++++++++++++++++++++++---- version.h | 6 +- 3 files changed, 157 insertions(+), 19 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8e826d5..80be9c1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -46,6 +46,7 @@ Tested on OS build 22000.376. * The clock flyouts now display correctly when using this taskbar * Fixed a bug that displayed wrong window previews when the combine taskbar buttons option was set to never combine (#564) (.17) * Possibility to set position on screen (top/bottom) from the Properties UI +* Restoring default settings only asks for elevation if required (for the moment, only if you have registered the application as shell extension) (.18) #### Simple Window Switcher diff --git a/ExplorerPatcher/GUI.c b/ExplorerPatcher/GUI.c index b4e5ab3..753923f 100644 --- a/ExplorerPatcher/GUI.c +++ b/ExplorerPatcher/GUI.c @@ -8,6 +8,36 @@ static void(*RefreshImmersiveColorPolicyState)() = NULL; static BOOL(*ShouldAppsUseDarkMode)() = NULL; DWORD dwTaskbarPosition = 3; BOOL gui_bOldTaskbar = TRUE; + +NTSTATUS NTAPI hookRtlQueryElevationFlags(DWORD* pFlags) +{ + *pFlags = 0; + return 0; +} + +PVOID pvRtlQueryElevationFlags; + +LONG NTAPI OnVex(PEXCEPTION_POINTERS ExceptionInfo) +{ + if (ExceptionInfo->ExceptionRecord->ExceptionCode == STATUS_SINGLE_STEP && + ExceptionInfo->ExceptionRecord->ExceptionAddress == pvRtlQueryElevationFlags) + { + ExceptionInfo->ContextRecord-> +#if defined(_X86_) + Eip +#elif defined (_AMD64_) + Rip +#else +#error not implemented +#endif + = (ULONG_PTR)hookRtlQueryElevationFlags; + + return EXCEPTION_CONTINUE_EXECUTION; + } + + return EXCEPTION_CONTINUE_SEARCH; +} + BOOL IsHighContrast() { HIGHCONTRASTW highContrast; @@ -1006,10 +1036,40 @@ static BOOL GUI_Build(HDC hDC, HWND hwnd, POINT pt) ); if (hFile) { + void* buffer = NULL; + HKEY hKey = NULL; + RegOpenKeyExW( + HKEY_LOCAL_MACHINE, + L"Software\\Classes\\CLSID\\" _T(EP_CLSID) L"\\InprocServer32", + REG_OPTION_NON_VOLATILE, + KEY_READ | KEY_WOW64_64KEY, + &hKey + ); + if (hKey == NULL || hKey == INVALID_HANDLE_VALUE) + { + buffer = malloc(cbRscr); + if (buffer) + { + memcpy(buffer, pRscr, cbRscr); + char* p1 = strstr(buffer, "[-HKEY_LOCAL_MACHINE\\Software\\Classes\\CLSID\\" EP_CLSID "\\InprocServer32]"); + if (p1) p1[0] = ';'; + char* p2 = strstr(buffer, ";d Register as shell extension"); + if (p2) memcpy(p2, ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;", 70); + } + else + { + RegCloseKey(hKey); + hKey = NULL; + } + } + if (!buffer) + { + buffer = pRscr; + } DWORD dwNumberOfBytesWritten = 0; if (WriteFile( hFile, - pRscr, + buffer, cbRscr, &dwNumberOfBytesWritten, NULL @@ -1017,25 +1077,102 @@ static BOOL GUI_Build(HDC hDC, HWND hwnd, POINT pt) { CloseHandle(hFile); - SHELLEXECUTEINFO ShExecInfo = { 0 }; - ShExecInfo.cbSize = sizeof(SHELLEXECUTEINFO); - ShExecInfo.fMask = SEE_MASK_NOCLOSEPROCESS; - ShExecInfo.hwnd = NULL; - ShExecInfo.lpVerb = NULL; - ShExecInfo.lpFile = wszPath; - ShExecInfo.lpParameters = L""; - ShExecInfo.lpDirectory = NULL; - ShExecInfo.nShow = SW_SHOW; - ShExecInfo.hInstApp = NULL; - ShellExecuteEx(&ShExecInfo); - WaitForSingleObject(ShExecInfo.hProcess, INFINITE); - DWORD dwExitCode = 0; - GetExitCodeProcess(ShExecInfo.hProcess, &dwExitCode); + DWORD dwError = 1; + if (hKey == NULL || hKey == INVALID_HANDLE_VALUE) + { + dwError = 0; + // https://stackoverflow.com/questions/50298722/win32-launching-a-highestavailable-child-process-as-a-normal-user-process + if (pvRtlQueryElevationFlags = GetProcAddress(GetModuleHandleW(L"ntdll"), "RtlQueryElevationFlags")) + { + PVOID pv; + if (pv = AddVectoredExceptionHandler(TRUE, OnVex)) + { + CONTEXT ctx; + ZeroMemory(&ctx, sizeof(CONTEXT)); + ctx.ContextFlags = CONTEXT_DEBUG_REGISTERS; + ctx.Dr7 = 0x404; + ctx.Dr1 = (ULONG_PTR)pvRtlQueryElevationFlags; + + if (SetThreadContext(GetCurrentThread(), &ctx)) + { + WCHAR wszExec[MAX_PATH * 2]; + ZeroMemory(wszExec, MAX_PATH * 2 * sizeof(WCHAR)); + wszExec[0] = L'"'; + GetWindowsDirectoryW(wszExec + 1, MAX_PATH); + wcscat_s(wszExec, MAX_PATH * 2, L"\\regedit.exe\" \""); + wcscat_s(wszExec, MAX_PATH * 2, wszPath); + wcscat_s(wszExec, MAX_PATH * 2, L"\""); + STARTUPINFO si; + ZeroMemory(&si, sizeof(STARTUPINFO)); + si.cb = sizeof(STARTUPINFO); + PROCESS_INFORMATION pi; + ZeroMemory(&pi, sizeof(PROCESS_INFORMATION)); + wprintf(L"%s\n", wszExec); + if (CreateProcessW(NULL, wszExec, 0, 0, 0, 0, 0, 0, &si, &pi)) + { + CloseHandle(pi.hThread); + //CloseHandle(pi.hProcess); + } + else + { + dwError = GetLastError(); + } + + ctx.Dr7 = 0x400; + ctx.Dr1 = 0; + SetThreadContext(GetCurrentThread(), &ctx); + + if (pi.hProcess) + { + WaitForSingleObject(pi.hProcess, INFINITE); + DWORD dwExitCode = 0; + GetExitCodeProcess(pi.hProcess, &dwExitCode); + CloseHandle(pi.hProcess); + } + } + else + { + dwError = GetLastError(); + } + RemoveVectoredExceptionHandler(pv); + } + else + { + dwError = GetLastError(); + } + } + else + { + dwError = GetLastError(); + } + } + if (dwError) + { + SHELLEXECUTEINFO ShExecInfo = { 0 }; + ShExecInfo.cbSize = sizeof(SHELLEXECUTEINFO); + ShExecInfo.fMask = SEE_MASK_NOCLOSEPROCESS; + ShExecInfo.hwnd = NULL; + ShExecInfo.lpVerb = NULL; + ShExecInfo.lpFile = wszPath; + ShExecInfo.lpParameters = L""; + ShExecInfo.lpDirectory = NULL; + ShExecInfo.nShow = SW_SHOW; + ShExecInfo.hInstApp = NULL; + ShellExecuteExW(&ShExecInfo); + WaitForSingleObject(ShExecInfo.hProcess, INFINITE); + DWORD dwExitCode = 0; + GetExitCodeProcess(ShExecInfo.hProcess, &dwExitCode); + CloseHandle(ShExecInfo.hProcess); + } _this->tabOrder = 0; InvalidateRect(hwnd, NULL, FALSE); - CloseHandle(ShExecInfo.hProcess); DeleteFileW(wszPath); } + if (hKey == NULL || hKey == INVALID_HANDLE_VALUE) + { + RegCloseKey(hKey); + free(buffer); + } } } else if (!strncmp(line + 1, "about", 5)) diff --git a/version.h b/version.h index 0682a1f..be8c43e 100644 --- a/version.h +++ b/version.h @@ -1,7 +1,7 @@ #define VER_MAJOR 22000 #define VER_MINOR 376 #define VER_BUILD_HI 40 -#define VER_BUILD_LO 17 +#define VER_BUILD_LO 18 #define VER_FLAGS VS_FF_PRERELEASE @@ -12,5 +12,5 @@ #define VER_STR(arg) #arg // The String form of the version numbers -#define VER_FILE_STRING VALUE "FileVersion", "22000.376.40.17" -#define VER_PRODUCT_STRING VALUE "ProductVersion", "22000.376.40.17" +#define VER_FILE_STRING VALUE "FileVersion", "22000.376.40.18" +#define VER_PRODUCT_STRING VALUE "ProductVersion", "22000.376.40.18"