Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Restart explorer the "official" graceful way #2326

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
97 changes: 73 additions & 24 deletions SystemInformer/actions.c
Original file line number Diff line number Diff line change
Expand Up @@ -2281,6 +2281,7 @@ BOOLEAN PhUiRestartProcess(
BOOLEAN environmentAllocated = FALSE;
PVOID environmentBuffer = NULL;
ULONG environmentLength;
BOOLEAN processTerminated = FALSE;

if (PhGetIntegerSetting(L"EnableWarnings"))
{
Expand All @@ -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)))
Expand Down Expand Up @@ -2370,6 +2348,74 @@ 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;

if (NT_SUCCESS(PhGetWindowClientId(shellWindow = PhGetShellWindow(), &shellClientId)) &&
Process->ProcessId == shellClientId.UniqueProcess)
{
if (NT_SUCCESS(PhOpenProcess(
&processHandle,
SYNCHRONIZE,
Process->ProcessId
)))
{
BOOLEAN postToTaskbar = WindowsVersion >= WINDOWS_VISTA;

if (postToTaskbar)
{
HWND taskbarWindow = NULL;
CLIENT_ID taskbarClientId;
WCHAR windowClassName[MAX_PATH] = L"";

while (taskbarWindow = FindWindowEx(NULL, taskbarWindow, NULL, NULL))
{
if (NT_SUCCESS(PhGetWindowClientId(taskbarWindow, &taskbarClientId)) &&
taskbarClientId.UniqueProcess == shellClientId.UniqueProcess)
{
GetClassName(taskbarWindow, windowClassName, RTL_NUMBER_OF(windowClassName));
if (PhEqualStringZ(windowClassName, L"Shell_TrayWnd", FALSE))
{
postToTaskbar = !PostMessage(taskbarWindow, WM_USER + 0x1B4, 0, 0); // exit Explorer official way (Dart Vanya)
break;
}
}
}
}

if (postToTaskbar)
{
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)
Expand Down Expand Up @@ -2541,7 +2587,10 @@ BOOLEAN PhUiRestartProcess(

// Terminate the existing process.

PhTerminateProcess(processHandle, STATUS_SUCCESS);
if (!processTerminated)
{
status = PhTerminateProcess(processHandle, STATUS_SUCCESS);
}

// Update the console foreground.

Expand Down
15 changes: 15 additions & 0 deletions SystemInformer/mwpgproc.c
Original file line number Diff line number Diff line change
Expand Up @@ -851,6 +851,21 @@ VOID PhMwpInitializeProcessMenu(
item->Flags |= PH_EMENU_DISABLED;
}
}

// Special case for the current shell process
if (item = PhFindEMenuItem(Menu, 0, 0, ID_PROCESS_RESTART))
{
if (NumberOfProcesses == 1)
{
CLIENT_ID shellClientId;

if (NT_SUCCESS(PhGetWindowClientId(PhGetShellWindow(), &shellClientId)) &&
Processes[0]->ProcessId == shellClientId.UniqueProcess)
{
item->Text = L"Res&tart shell";
}
}
}
}

PPH_EMENU PhpCreateProcessMenu(
Expand Down
Loading