Author: hbelusca
Date: Mon Apr 21 01:22:17 2014
New Revision: 62847
URL:
http://svn.reactos.org/svn/reactos?rev=62847&view=rev
Log:
[KERNEL32][CONSRV]
Implement (undocumented) SetLastConsoleEventActive API.
Patch by Alexander Andrejevic, with a minor modification by me concerning the addition of
a NotifiedLastCloseProcess member to the CONSOLE structure and a check that makes sure
that only the app that asked for the notification, receives it (and so that we don't
call the console control dispatcher for nothing).
This API is used by ntvdm to be sure that it gets killed when all other console apps
attached to the ntvdm's console are away.
CORE-7250
Modified:
trunk/reactos/dll/win32/kernel32/client/console/console.c
trunk/reactos/include/psdk/wincon.h
trunk/reactos/include/reactos/subsys/win/conmsg.h
trunk/reactos/win32ss/user/winsrv/consrv/condrv/console.c
trunk/reactos/win32ss/user/winsrv/consrv/console.c
trunk/reactos/win32ss/user/winsrv/consrv/handle.c
trunk/reactos/win32ss/user/winsrv/consrv/include/conio.h
Modified: trunk/reactos/dll/win32/kernel32/client/console/console.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/kernel32/client/…
==============================================================================
--- trunk/reactos/dll/win32/kernel32/client/console/console.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/kernel32/client/console/console.c [iso-8859-1] Mon Apr 21
01:22:17 2014
@@ -30,6 +30,7 @@
PHANDLER_ROUTINE* CtrlHandlers;
ULONG NrCtrlHandlers;
ULONG NrAllocatedHandlers;
+BOOL LastCloseNotify = FALSE;
HANDLE InputWaitHandle = INVALID_HANDLE_VALUE;
@@ -129,8 +130,14 @@
case CTRL_SHUTDOWN_EVENT:
break;
- case 3:
- ExitThread(0);
+ case CTRL_LAST_CLOSE_EVENT:
+ /*
+ * In case the console app hasn't register for last close notification,
+ * just kill this console handler thread. We don't want that such apps
+ * get killed for unexpected reasons. On the contrary apps that registered
+ * can be killed because they expect to be.
+ */
+ if (!LastCloseNotify) ExitThread(0);
break;
case 4:
@@ -2595,14 +2602,26 @@
}
/*
- * @unimplemented
- */
-BOOL
+ * @implemented
+ */
+DWORD
WINAPI
SetLastConsoleEventActive(VOID)
{
- STUB;
- return FALSE;
+ CONSOLE_API_MESSAGE ApiMessage;
+ PCONSOLE_NOTIFYLASTCLOSE NotifyLastCloseRequest =
&ApiMessage.Data.NotifyLastCloseRequest;
+
+ /* Set the flag used by the console control dispatcher */
+ LastCloseNotify = TRUE;
+
+ /* Set up the input arguments */
+ NotifyLastCloseRequest->ConsoleHandle =
NtCurrentPeb()->ProcessParameters->ConsoleHandle;
+
+ /* Call CSRSS; just return the NTSTATUS cast to DWORD */
+ return CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
+ NULL,
+ CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX,
ConsolepNotifyLastClose),
+ sizeof(*NotifyLastCloseRequest));
}
/* EOF */
Modified: trunk/reactos/include/psdk/wincon.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/include/psdk/wincon.h?rev=…
==============================================================================
--- trunk/reactos/include/psdk/wincon.h [iso-8859-1] (original)
+++ trunk/reactos/include/psdk/wincon.h [iso-8859-1] Mon Apr 21 01:22:17 2014
@@ -65,11 +65,12 @@
/*
* Control handler codes
*/
-#define CTRL_C_EVENT 0
-#define CTRL_BREAK_EVENT 1
-#define CTRL_CLOSE_EVENT 2
-#define CTRL_LOGOFF_EVENT 5
-#define CTRL_SHUTDOWN_EVENT 6
+#define CTRL_C_EVENT 0
+#define CTRL_BREAK_EVENT 1
+#define CTRL_CLOSE_EVENT 2
+#define CTRL_LAST_CLOSE_EVENT 3 /* Undocumented */
+#define CTRL_LOGOFF_EVENT 5
+#define CTRL_SHUTDOWN_EVENT 6
/*
* Input mode flags
Modified: trunk/reactos/include/reactos/subsys/win/conmsg.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/include/reactos/subsys/win…
==============================================================================
--- trunk/reactos/include/reactos/subsys/win/conmsg.h [iso-8859-1] (original)
+++ trunk/reactos/include/reactos/subsys/win/conmsg.h [iso-8859-1] Mon Apr 21 01:22:17
2014
@@ -204,6 +204,20 @@
typedef struct
{
+ HANDLE ConsoleHandle;
+ DWORD CtrlEvent;
+ DWORD ProcessGroupId;
+} CONSOLE_GENERATECTRLEVENT, *PCONSOLE_GENERATECTRLEVENT;
+
+typedef struct
+{
+ HANDLE ConsoleHandle;
+} CONSOLE_NOTIFYLASTCLOSE, *PCONSOLE_NOTIFYLASTCLOSE;
+
+
+
+typedef struct
+{
HANDLE OutputHandle;
BOOL Unicode;
@@ -347,6 +361,7 @@
DWORD Flags;
DWORD State;
} CONSOLE_GETSETHWSTATE, *PCONSOLE_GETSETHWSTATE;
+
typedef struct
@@ -529,6 +544,15 @@
typedef struct
{
HANDLE ConsoleHandle;
+ HANDLE InputHandle;
+ DWORD NumberOfEvents;
+} CONSOLE_GETNUMINPUTEVENTS, *PCONSOLE_GETNUMINPUTEVENTS;
+
+
+
+typedef struct
+{
+ HANDLE ConsoleHandle;
HANDLE Handle;
} CONSOLE_CLOSEHANDLE, *PCONSOLE_CLOSEHANDLE;
@@ -584,6 +608,7 @@
} CONSOLE_OPENCONSOLE, *PCONSOLE_OPENCONSOLE;
+
typedef struct
{
HANDLE ConsoleHandle;
@@ -699,20 +724,6 @@
} CONSOLE_GETSETHISTORYINFO, *PCONSOLE_GETSETHISTORYINFO;
-
-typedef struct
-{
- HANDLE ConsoleHandle;
- DWORD CtrlEvent;
- DWORD ProcessGroupId;
-} CONSOLE_GENERATECTRLEVENT, *PCONSOLE_GENERATECTRLEVENT;
-
-typedef struct
-{
- HANDLE ConsoleHandle;
- HANDLE InputHandle;
- DWORD NumberOfEvents;
-} CONSOLE_GETNUMINPUTEVENTS, *PCONSOLE_GETNUMINPUTEVENTS;
typedef struct
{
@@ -757,8 +768,10 @@
CONSOLE_ATTACHCONSOLE AttachConsoleRequest;
CONSOLE_FREECONSOLE FreeConsoleRequest;
- /* Process list */
+ /* Processes */
CONSOLE_GETPROCESSLIST GetProcessListRequest;
+ CONSOLE_GENERATECTRLEVENT GenerateCtrlEventRequest;
+ CONSOLE_NOTIFYLASTCLOSE NotifyLastCloseRequest;
/* Handles */
CONSOLE_OPENCONSOLE OpenConsoleRequest;
@@ -806,6 +819,7 @@
CONSOLE_GETINPUT GetInputRequest; // SrvGetConsoleInput /
PeekConsoleInput & ReadConsoleInput
CONSOLE_READOUTPUT ReadOutputRequest; // SrvReadConsoleOutput /
ReadConsoleOutput
CONSOLE_READOUTPUTCODE ReadOutputCodeRequest; // SrvReadConsoleOutputString /
ReadConsoleOutputAttribute & ReadConsoleOutputCharacter
+ CONSOLE_GETNUMINPUTEVENTS GetNumInputEventsRequest;
/* Write */
CONSOLE_WRITECONSOLE WriteConsoleRequest; // SrvWriteConsole /
WriteConsole
@@ -830,9 +844,6 @@
CONSOLE_SETHISTORYNUMBERCOMMANDS SetHistoryNumberCommandsRequest;
CONSOLE_GETSETHISTORYINFO HistoryInfoRequest;
- CONSOLE_GENERATECTRLEVENT GenerateCtrlEventRequest;
- CONSOLE_GETNUMINPUTEVENTS GetNumInputEventsRequest;
-
/* Input and Output Code Pages */
CONSOLE_GETINPUTOUTPUTCP GetConsoleCPRequest;
CONSOLE_SETINPUTOUTPUTCP SetConsoleCPRequest;
Modified: trunk/reactos/win32ss/user/winsrv/consrv/condrv/console.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/win32ss/user/winsrv/consrv…
==============================================================================
--- trunk/reactos/win32ss/user/winsrv/consrv/condrv/console.c [iso-8859-1] (original)
+++ trunk/reactos/win32ss/user/winsrv/consrv/condrv/console.c [iso-8859-1] Mon Apr 21
01:22:17 2014
@@ -244,7 +244,7 @@
return Status;
}
-static NTSTATUS
+NTSTATUS
ConDrvConsoleCtrlEvent(IN ULONG CtrlEvent,
IN PCONSOLE_PROCESS_DATA ProcessData)
{
@@ -535,6 +535,8 @@
Console->ReferenceCount = 0;
InitializeCriticalSection(&Console->Lock);
InitializeListHead(&Console->ProcessList);
+ Console->NotifiedLastCloseProcess = NULL;
+ Console->NotifyLastClose = FALSE;
/* Initialize the frontend interface */
ResetFrontEnd(Console);
Modified: trunk/reactos/win32ss/user/winsrv/consrv/console.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/win32ss/user/winsrv/consrv…
==============================================================================
--- trunk/reactos/win32ss/user/winsrv/consrv/console.c [iso-8859-1] (original)
+++ trunk/reactos/win32ss/user/winsrv/consrv/console.c [iso-8859-1] Mon Apr 21 01:22:17
2014
@@ -641,8 +641,27 @@
CSR_API(SrvConsoleNotifyLastClose)
{
- DPRINT1("%s not yet implemented\n", __FUNCTION__);
- return STATUS_NOT_IMPLEMENTED;
+ NTSTATUS Status;
+ PCONSOLE_PROCESS_DATA ProcessData =
ConsoleGetPerProcessData(CsrGetClientThread()->Process);
+ PCONSOLE Console;
+
+ Status = ConSrvGetConsole(ProcessData, &Console, TRUE);
+ if (!NT_SUCCESS(Status)) return Status;
+
+ /* Only one process is allowed to be registered for last close notification */
+ if (!Console->NotifyLastClose)
+ {
+ Console->NotifiedLastCloseProcess = ProcessData;
+ Console->NotifyLastClose = TRUE;
+ Status = STATUS_SUCCESS;
+ }
+ else
+ {
+ Status = STATUS_ACCESS_DENIED;
+ }
+
+ ConSrvReleaseConsole(Console, TRUE);
+ return Status;
}
Modified: trunk/reactos/win32ss/user/winsrv/consrv/handle.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/win32ss/user/winsrv/consrv…
==============================================================================
--- trunk/reactos/win32ss/user/winsrv/consrv/handle.c [iso-8859-1] (original)
+++ trunk/reactos/win32ss/user/winsrv/consrv/handle.c [iso-8859-1] Mon Apr 21 01:22:17
2014
@@ -633,6 +633,10 @@
return Status;
}
+NTSTATUS
+ConDrvConsoleCtrlEvent(IN ULONG CtrlEvent,
+ IN PCONSOLE_PROCESS_DATA ProcessData);
+
VOID
FASTCALL
ConSrvRemoveConsole(PCONSOLE_PROCESS_DATA ProcessData)
@@ -661,6 +665,30 @@
/* 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);
Modified: trunk/reactos/win32ss/user/winsrv/consrv/include/conio.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/win32ss/user/winsrv/consrv…
==============================================================================
--- trunk/reactos/win32ss/user/winsrv/consrv/include/conio.h [iso-8859-1] (original)
+++ trunk/reactos/win32ss/user/winsrv/consrv/include/conio.h [iso-8859-1] Mon Apr 21
01:22:17 2014
@@ -282,6 +282,8 @@
CONSOLE_STATE State; /* State of the console */
LIST_ENTRY ProcessList; /* List of processes owning the console. The
first one is the so-called "Console Leader Process" */
+ PCONSOLE_PROCESS_DATA NotifiedLastCloseProcess; /* Pointer to the unique process that
needs to be notified when all the other processes have been detached from the console */
+ BOOLEAN NotifyLastClose; /* TRUE if the console should send a control
event to the last attached process after all the others detached, if it wanted to be
notified */
FRONTEND TermIFace; /* Frontend-specific interface */