diff --git a/SystemInformer/actions.c b/SystemInformer/actions.c index f9f81c8043b8..153566f900c3 100644 --- a/SystemInformer/actions.c +++ b/SystemInformer/actions.c @@ -2281,6 +2281,7 @@ BOOLEAN PhUiRestartProcess( BOOLEAN environmentAllocated = FALSE; PVOID environmentBuffer = NULL; ULONG environmentLength; + BOOLEAN processTerminated = FALSE; if (PhGetIntegerSetting(L"EnableWarnings")) { @@ -2306,29 +2307,6 @@ BOOLEAN PhUiRestartProcess( if (Process->ProcessId == NtCurrentProcessId()) return FALSE; - // Special handling for the current shell process. (dmex) - { - CLIENT_ID shellClientId; - - if (NT_SUCCESS(PhGetWindowClientId(PhGetShellWindow(), &shellClientId))) - { - if (Process->ProcessId == shellClientId.UniqueProcess) - { - status = PhOpenProcess( - &processHandle, - PROCESS_TERMINATE, - Process->ProcessId - ); - - if (NT_SUCCESS(status)) - { - PhTerminateProcess(processHandle, STATUS_SUCCESS); - NtClose(processHandle); - } - } - } - } - fileNameWin32 = Process->FileName ? PhGetFileName(Process->FileName) : NULL; if (PhIsNullOrEmptyString(fileNameWin32) || !PhDoesFileExistWin32(PhGetString(fileNameWin32))) @@ -2370,6 +2348,73 @@ BOOLEAN PhUiRestartProcess( NtClose(processHandle); processHandle = NULL; + // Special handling for the current shell process. (dmex) + // Handling shell process only after VM_READ routines above have completed, because we cannot properly read memory of exited process (Dart Vanya) + { + CLIENT_ID shellClientId; + HWND shellWindow = NULL; + + if (NT_SUCCESS(PhGetWindowClientId(shellWindow = PhGetShellWindow(), &shellClientId)) && + Process->ProcessId == shellClientId.UniqueProcess) + { + if (NT_SUCCESS(PhOpenProcess( + &processHandle, + SYNCHRONIZE, + Process->ProcessId + ))) + { + if (WindowsVersion >= WINDOWS_VISTA) + { + CLIENT_ID taskbarClientId; + WCHAR windowClassName[MAX_PATH] = L""; + shellWindow = NULL; + + while (shellWindow = FindWindowEx(NULL, shellWindow, NULL, NULL)) + { + if (NT_SUCCESS(PhGetWindowClientId(shellWindow, &taskbarClientId)) && + taskbarClientId.UniqueProcess == shellClientId.UniqueProcess) + { + GetClassName(WindowHandle, windowClassName, RTL_NUMBER_OF(windowClassName)); + + if (PhEqualStringZ(windowClassName, L"Shell_TrayWnd", FALSE)) + { + PostMessage(shellWindow, WM_USER + 0x1B4, 0, 0); // exit Explorer official way (Dart Vanya) + break; + } + } + } + } + else + { + PostMessage(shellWindow, WM_QUIT, 0, 0); + } + + // Wait for a reasonably timeout (maybe a setting like ExplorerShellRestartTimeout?) + status = PhWaitForMultipleObjectsAndPump(NULL, 1, &processHandle, 2500, QS_ALLINPUT); + processTerminated = status == STATUS_WAIT_0; + + NtClose(processHandle); + processHandle = NULL; + } + + if (!processTerminated) + { + status = PhOpenProcess( + &processHandle, + PROCESS_TERMINATE, + Process->ProcessId + ); + + if (NT_SUCCESS(status)) + { + processTerminated = NT_SUCCESS(PhTerminateProcess(processHandle, STATUS_SUCCESS)); + NtClose(processHandle); + processHandle = NULL; + } + } + } + } + // Start the process. // // Use the existing process as the parent, and restarting the process will inherit most of the process configuration from itself (dmex) @@ -2541,7 +2586,10 @@ BOOLEAN PhUiRestartProcess( // Terminate the existing process. - PhTerminateProcess(processHandle, STATUS_SUCCESS); + if (!processTerminated) + { + status = PhTerminateProcess(processHandle, STATUS_SUCCESS); + } // Update the console foreground.