From 021093545962c14403a4d0cb4dba5eb703348697 Mon Sep 17 00:00:00 2001 From: Valentin Radu Date: Mon, 25 Oct 2021 05:42:03 +0300 Subject: [PATCH] File Explorer is restarted using Windows Restart Manager --- ExplorerPatcher/GUI.c | 28 ++----- ExplorerPatcher/utility.c | 18 ++--- ExplorerPatcher/utility.h | 162 +++++++++++++++++++++++++++++++++++++- 3 files changed, 173 insertions(+), 35 deletions(-) diff --git a/ExplorerPatcher/GUI.c b/ExplorerPatcher/GUI.c index b8e3d84..0d1894b 100644 --- a/ExplorerPatcher/GUI.c +++ b/ExplorerPatcher/GUI.c @@ -510,30 +510,14 @@ static BOOL GUI_Build(HDC hDC, HWND hwnd, POINT pt) if (p) *p = 0; if (!strncmp(line + 1, "restart", 7)) { - PROCESSENTRY32 pe32 = { 0 }; - pe32.dwSize = sizeof(PROCESSENTRY32); - HANDLE hSnapshot = CreateToolhelp32Snapshot( - TH32CS_SNAPPROCESS, - 0 - ); - if (Process32First(hSnapshot, &pe32) == TRUE) + if (FindWindowW(L"Shell_TrayWnd", NULL)) { - do - { - if (!wcscmp(pe32.szExeFile, TEXT("sihost.exe"))) - { - HANDLE hSihost = OpenProcess( - PROCESS_TERMINATE, - FALSE, - pe32.th32ProcessID - ); - TerminateProcess(hSihost, 0); - CloseHandle(hSihost); - return TRUE; - } - } while (Process32Next(hSnapshot, &pe32) == TRUE); + ZZRestartExplorer(); + } + else + { + StartExplorer(); } - CloseHandle(hSnapshot); } else if (!strncmp(line + 1, "reset", 5)) { diff --git a/ExplorerPatcher/utility.c b/ExplorerPatcher/utility.c index 358340c..301046d 100644 --- a/ExplorerPatcher/utility.c +++ b/ExplorerPatcher/utility.c @@ -99,18 +99,6 @@ const IActivationFactoryAA XamlExtensionsFactory = { }; #pragma endregion -int FileExistsW(wchar_t* file) -{ - WIN32_FIND_DATAW FindFileData; - HANDLE handle = FindFirstFileW(file, &FindFileData); - int found = handle != INVALID_HANDLE_VALUE; - if (found) - { - FindClose(handle); - } - return found; -} - void printf_guid(GUID guid) { printf("Guid = {%08lX-%04hX-%04hX-%02hhX%02hhX-%02hhX%02hhX%02hhX%02hhX%02hhX%02hhX}\n", @@ -276,6 +264,12 @@ __declspec(dllexport) CALLBACK ZZLaunchExplorerDelayed(HWND hWnd, HINSTANCE hIns ZZLaunchExplorer(hWnd, hInstance, lpszCmdLine, nCmdShow); } +__declspec(dllexport) CALLBACK ZZRestartExplorer(HWND hWnd, HINSTANCE hInstance, LPSTR lpszCmdLine, int nCmdShow) +{ + BeginExplorerRestart(); + FinishExplorerRestart(); +} + POINT GetDefaultWinXPosition(BOOL bUseRcWork, BOOL* lpBottom, BOOL* lpRight, BOOL bAdjust) { if (lpBottom) *lpBottom = FALSE; diff --git a/ExplorerPatcher/utility.h b/ExplorerPatcher/utility.h index bf68254..0758ef7 100644 --- a/ExplorerPatcher/utility.h +++ b/ExplorerPatcher/utility.h @@ -10,6 +10,8 @@ #include #include #include +#include +#pragma comment(lib, "Rstrtmgr.lib") #define _LIBVALINET_INCLUDE_UNIVERSAL #include @@ -75,7 +77,17 @@ typedef struct _IActivationFactoryAA extern const IActivationFactoryAA XamlExtensionsFactory; #pragma endregion -int FileExistsW(wchar_t* file); +inline int FileExistsW(wchar_t* file) +{ + WIN32_FIND_DATAW FindFileData; + HANDLE handle = FindFirstFileW(file, &FindFileData); + int found = handle != INVALID_HANDLE_VALUE; + if (found) + { + FindClose(handle); + } + return found; +} // https://stackoverflow.com/questions/1672677/print-a-guid-variable void printf_guid(GUID guid); @@ -258,4 +270,152 @@ Cleanup: return fIsRunAsAdmin; } + +inline BOOL IsDesktopWindowAlreadyPresent() +{ + return (FindWindowExW(NULL, NULL, L"Progman", NULL) || FindWindowExW(NULL, NULL, L"Proxy Desktop", NULL)); +} + +// https://jiangsheng.net/2013/01/22/how-to-restart-windows-explorer-programmatically-using-restart-manager/ +inline RM_UNIQUE_PROCESS GetExplorerApplication() +{ + HWND hwnd = FindWindow(L"Shell_TrayWnd", NULL); + DWORD pid = 0; + GetWindowThreadProcessId(hwnd, &pid); + + RM_UNIQUE_PROCESS out = { 0, { -1, -1 } }; + DWORD bytesReturned; + WCHAR imageName[MAX_PATH]; // process image name buffer + DWORD processIds[2048]; // max 2048 processes (more than enough) + + // enumerate all running processes (usually around 60-70) + EnumProcesses(processIds, sizeof(processIds), &bytesReturned); + int count = bytesReturned / sizeof(DWORD); // number of processIds returned + + for (int i = 0; i < count; ++i) + { + DWORD processId = processIds[i]; + HANDLE hProc; + if (processId == pid && (hProc = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, processId))) + { + GetProcessImageFileNameW(hProc, imageName, MAX_PATH); + FILETIME ftStart, ftExit, ftKernel, ftUser; + GetProcessTimes(hProc, &ftStart, &ftExit, &ftKernel, &ftUser); + + if (ftStart.dwLowDateTime < out.ProcessStartTime.dwLowDateTime) + { + out.dwProcessId = processId; + out.ProcessStartTime = ftStart; + } + CloseHandle(hProc); + } + } + return out; // return count in pResults +} + +static DWORD RmSession = -1; +static wchar_t RmSessionKey[CCH_RM_SESSION_KEY + 1]; + +// shuts down the explorer and is ready for explorer restart +inline void BeginExplorerRestart() +{ + if (RmStartSession(&RmSession, 0, RmSessionKey) == ERROR_SUCCESS) + { + RM_UNIQUE_PROCESS rgApplications[] = { GetExplorerApplication() }; + RmRegisterResources(RmSession, 0, 0, 1, rgApplications, 0, 0); + + DWORD rebootReason; + UINT nProcInfoNeeded, nProcInfo = 16; + RM_PROCESS_INFO affectedApps[16]; + RmGetList(RmSession, &nProcInfoNeeded, &nProcInfo, affectedApps, &rebootReason); + + if (rebootReason == RmRebootReasonNone) // no need for reboot? + { + // shutdown explorer + RmShutdown(RmSession, RmForceShutdown, 0); + } + } +} +// restarts the explorer +inline void FinishExplorerRestart() +{ + DWORD dwError; + if (dwError = RmRestart(RmSession, 0, NULL)) + printf("\n RmRestart error: %d\n\n", dwError); + + RmEndSession(RmSession); + RmSession = -1; + RmSessionKey[0] = 0; +} + +// https://stackoverflow.com/questions/5689904/gracefully-exit-explorer-programmatically +inline BOOL ExitExplorer() +{ + HWND hWndTray = FindWindowW(L"Shell_TrayWnd", NULL); + return PostMessageW(hWndTray, 0x5B4, 0, 0); +} + +inline void StartExplorer() +{ + + /*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"))) + { + HANDLE hSihost = OpenProcess( + PROCESS_TERMINATE, + FALSE, + pe32.th32ProcessID + ); + TerminateProcess(hSihost, 1); + CloseHandle(hSihost); + } + } while (Process32Next(hSnapshot, &pe32) == TRUE); + } + CloseHandle(hSnapshot); + */ + wchar_t wszPath[MAX_PATH]; + ZeroMemory( + wszPath, + (MAX_PATH) * sizeof(wchar_t) + ); + GetWindowsDirectoryW( + wszPath, + MAX_PATH + ); + wcscat_s( + wszPath, + MAX_PATH, + L"\\explorer.exe" + ); + STARTUPINFO si; + ZeroMemory(&si, sizeof(STARTUPINFO)); + si.cb = sizeof(si); + PROCESS_INFORMATION pi; + ZeroMemory(&pi, sizeof(PROCESS_INFORMATION)); + if (CreateProcessW( + NULL, + wszPath, + NULL, + NULL, + TRUE, + CREATE_UNICODE_ENVIRONMENT, + NULL, + NULL, + &si, + &pi + )) + { + CloseHandle(pi.hThread); + CloseHandle(pi.hProcess); + } +} #endif \ No newline at end of file