diff --git a/reactos/win32ss/user/winsrv/consrv/condrv/console.c b/reactos/win32ss/user/winsrv/consrv/condrv/console.c index 3ec35f220af..c19754da56e 100644 --- a/reactos/win32ss/user/winsrv/consrv/condrv/console.c +++ b/reactos/win32ss/user/winsrv/consrv/condrv/console.c @@ -1091,6 +1091,16 @@ ConDrvSetConsoleCP(IN PCONSOLE Console, return STATUS_SUCCESS; } +PCONSOLE_PROCESS_DATA NTAPI +ConDrvGetConsoleLeaderProcess(IN PCONSOLE Console) +{ + if (Console == NULL) return NULL; + + return CONTAINING_RECORD(Console->ProcessList.Blink, + CONSOLE_PROCESS_DATA, + ConsoleLink); +} + NTSTATUS NTAPI ConDrvGetConsoleProcessList(IN PCONSOLE Console, IN OUT PULONG ProcessIdsList, diff --git a/reactos/win32ss/user/winsrv/consrv/frontends/gui/conwnd.c b/reactos/win32ss/user/winsrv/consrv/frontends/gui/conwnd.c index 6e8adfb6231..da3a0f11614 100644 --- a/reactos/win32ss/user/winsrv/consrv/frontends/gui/conwnd.c +++ b/reactos/win32ss/user/winsrv/consrv/frontends/gui/conwnd.c @@ -48,9 +48,7 @@ SetConWndConsoleLeaderCID(IN PGUI_CONSOLE_DATA GuiData) PCONSOLE_PROCESS_DATA ProcessData; CLIENT_ID ConsoleLeaderCID; - ProcessData = CONTAINING_RECORD(GuiData->Console->ProcessList.Blink, - CONSOLE_PROCESS_DATA, - ConsoleLink); + ProcessData = ConDrvGetConsoleLeaderProcess(GuiData->Console); ConsoleLeaderCID = ProcessData->Process->ClientId; SetWindowLongPtrW(GuiData->hWindow, GWLP_CONSOLE_LEADER_PID, (LONG_PTR)(ConsoleLeaderCID.UniqueProcess)); diff --git a/reactos/win32ss/user/winsrv/consrv/frontends/gui/guisettings.c b/reactos/win32ss/user/winsrv/consrv/frontends/gui/guisettings.c index 0d64f83e604..fadfc79aeba 100644 --- a/reactos/win32ss/user/winsrv/consrv/frontends/gui/guisettings.c +++ b/reactos/win32ss/user/winsrv/consrv/frontends/gui/guisettings.c @@ -356,9 +356,7 @@ GuiConsoleShowConsoleProperties(PGUI_CONSOLE_DATA GuiData, NtUnmapViewOfSection(NtCurrentProcess(), pSharedInfo); /* Get the console leader process, our client */ - ProcessData = CONTAINING_RECORD(Console->ProcessList.Blink, - CONSOLE_PROCESS_DATA, - ConsoleLink); + ProcessData = ConDrvGetConsoleLeaderProcess(Console); /* Duplicate the section handle for the client */ Status = NtDuplicateObject(NtCurrentProcess(), @@ -430,9 +428,7 @@ GuiApplyUserSettings(PGUI_CONSOLE_DATA GuiData, PGUI_CONSOLE_INFO GuiInfo = NULL; /* Get the console leader process, our client */ - ProcessData = CONTAINING_RECORD(Console->ProcessList.Blink, - CONSOLE_PROCESS_DATA, - ConsoleLink); + ProcessData = ConDrvGetConsoleLeaderProcess(Console); /* Duplicate the section handle for ourselves */ Status = NtDuplicateObject(ProcessData->Process->ProcessHandle, diff --git a/reactos/win32ss/user/winsrv/consrv/handle.c b/reactos/win32ss/user/winsrv/consrv/handle.c index 81fa41d2dce..98b7ff0c0db 100644 --- a/reactos/win32ss/user/winsrv/consrv/handle.c +++ b/reactos/win32ss/user/winsrv/consrv/handle.c @@ -633,10 +633,6 @@ Quit: return Status; } -NTSTATUS -ConDrvConsoleCtrlEvent(IN ULONG CtrlEvent, - IN PCONSOLE_PROCESS_DATA ProcessData); - VOID FASTCALL ConSrvRemoveConsole(PCONSOLE_PROCESS_DATA ProcessData) @@ -652,6 +648,9 @@ ConSrvRemoveConsole(PCONSOLE_PROCESS_DATA ProcessData) ProcessData->ConsoleHandle, CONSOLE_RUNNING, TRUE)) { + /* Retrieve the console leader process */ + PCONSOLE_PROCESS_DATA ConsoleLeaderProcess = ConDrvGetConsoleLeaderProcess(Console); + DPRINT("ConSrvRemoveConsole - Locking OK\n"); /* Close all console handles and free the handles table */ @@ -660,36 +659,41 @@ ConSrvRemoveConsole(PCONSOLE_PROCESS_DATA ProcessData) /* Detach the process from the console */ ProcessData->ConsoleHandle = NULL; - /* Remove ourselves from the console's list of processes */ + /* Remove the process from the console's list of processes */ RemoveEntryList(&ProcessData->ConsoleLink); + /* Check whether the console should send a last close notification */ + if (Console->NotifyLastClose) + { + /* If we are removing the process which wants the last close notification... */ + if (ProcessData == Console->NotifiedLastCloseProcess) + { + /* ... just reset the flag and the pointer... */ + Console->NotifyLastClose = FALSE; + Console->NotifiedLastCloseProcess = NULL; + } + /* + * ... otherwise, if we are removing the console leader process + * (that cannot be the process wanting the notification, because + * the previous case already dealt with it)... + */ + else if (ProcessData == ConsoleLeaderProcess) + { + /* + * ... reset the flag first (so that we avoid multiple notifications) + * and then send the last close notification. + */ + Console->NotifyLastClose = FALSE; + ConDrvConsoleCtrlEvent(CTRL_LAST_CLOSE_EVENT, Console->NotifiedLastCloseProcess); + + /* Only now, reset the pointer */ + Console->NotifiedLastCloseProcess = NULL; + } + } + /* Update the internal info of the terminal */ TermRefreshInternalInfo(Console); - /* - * Check if there is only one process still attached to the console, - * and that the console should send a control event in this case. - */ - if ((Console->ProcessList.Flink != &Console->ProcessList) && - (Console->ProcessList.Flink->Flink == &Console->ProcessList) && - // (Console->ProcessList.Flink == Console->ProcessList.Blink) && - Console->NotifyLastClose) - { - PCONSOLE_PROCESS_DATA LastProcess = CONTAINING_RECORD(Console->ProcessList.Flink, - CONSOLE_PROCESS_DATA, - ConsoleLink); - /* If the remaining process is the one that wanted the notification... */ - if (LastProcess == Console->NotifiedLastCloseProcess) - { - /* ... notify it that it's the only one remaining on the console */ - ConDrvConsoleCtrlEvent(CTRL_LAST_CLOSE_EVENT, LastProcess); - } - - /* In any case reset the pointer and the flag */ - Console->NotifiedLastCloseProcess = NULL; - Console->NotifyLastClose = FALSE; - } - /* Release the console */ DPRINT("ConSrvRemoveConsole - Decrement Console->ReferenceCount = %lu\n", Console->ReferenceCount); ConDrvReleaseConsole(Console, TRUE); diff --git a/reactos/win32ss/user/winsrv/consrv/include/conio.h b/reactos/win32ss/user/winsrv/consrv/include/conio.h index 6dda15759fe..631eebd3f01 100644 --- a/reactos/win32ss/user/winsrv/consrv/include/conio.h +++ b/reactos/win32ss/user/winsrv/consrv/include/conio.h @@ -343,6 +343,11 @@ typedef struct _CONSOLE VOID FASTCALL ConioPause(PCONSOLE Console, UINT Flags); VOID FASTCALL ConioUnpause(PCONSOLE Console, UINT Flags); +PCONSOLE_PROCESS_DATA NTAPI +ConDrvGetConsoleLeaderProcess(IN PCONSOLE Console); +NTSTATUS +ConDrvConsoleCtrlEvent(IN ULONG CtrlEvent, + IN PCONSOLE_PROCESS_DATA ProcessData); NTSTATUS NTAPI ConDrvConsoleProcessCtrlEvent(IN PCONSOLE Console, IN ULONG ProcessGroupId,