- Fix console apps initialization.
- Add some debug output (NOTE TO MYSELF: remove them when all things work).
- Rewrite ConsoleNewProcess.
- Reorganize SrvAllocConsole and create ConsoleConnect based on SrvAllocConsole.
- Create ConsoleDisconnect which undoes what ConsoleConnect and ConsoleNewProcess did.
- Rework a little bit CsrInitConsole.

Now the console app. initialization algorithm is the following:

1- A process is created, its type (GUI or CUI) is determined (kernel32 and basesrv).
2- ConsoleNewProcess is called (consrv) and makes this new process inherit the console handles table from its parent
   (NOTE: this is done for all CUI processes, because at this point, we still don't know whether we must inherit
   the handles from the parent or not).
3- (back in kernel32) In BasepInitConsole, we determine whether or not we must create a new console window or use
   the parent's one or not using one at all. We (as a client) connect to the console server (consrv) (via CsrClientConnectToServer)
   which in turn (via CSRSS mechanism) calls ConsoleConnect. For GUI processes we do nothing. For CUI processes, we initialize
   a new console based on properties set in BasepInitConsole.
4- When a process dies, ConsoleDisconnect is called and whether it is a GUI or CUI process, we revert the actions done previously.

Part 2/2

TODO: - Debug the CSR waits.
      - Work on the console properties property-sheet.
      - See what can be done on http://jira.reactos.org/browse/CORE-122

svn path=/branches/ros-csrss/; revision=58098
This commit is contained in:
Hermès Bélusca-Maïto 2013-01-02 00:32:20 +00:00
parent e635242284
commit dd5a9c5231
6 changed files with 519 additions and 200 deletions

View file

@ -10,11 +10,6 @@
#define CSR_DEFAULT_CURSOR_SIZE 25 #define CSR_DEFAULT_CURSOR_SIZE 25
/* Object type magic numbers */
#define CONIO_CONSOLE_MAGIC 0x00000001
#define CONIO_SCREEN_BUFFER_MAGIC 0x00000002
/************************************************************************ /************************************************************************
* Screen buffer structure represents the win32 screen buffer object. * * Screen buffer structure represents the win32 screen buffer object. *
* Internally, the portion of the buffer being shown CAN loop past the * * Internally, the portion of the buffer being shown CAN loop past the *
@ -29,7 +24,7 @@
* being printed causes another line to scroll down, that the buffer IS * * being printed causes another line to scroll down, that the buffer IS *
* memcpy()'s up, and the bottom of the buffer is still displayed, but * * memcpy()'s up, and the bottom of the buffer is still displayed, but *
* internally, I just wrap back to the top of the buffer. * * internally, I just wrap back to the top of the buffer. *
***********************************************************************/ ************************************************************************/
typedef struct tagCSRSS_SCREEN_BUFFER typedef struct tagCSRSS_SCREEN_BUFFER
{ {
@ -149,7 +144,7 @@ typedef struct ConsoleInput_t
/* console.c */ /* console.c */
NTSTATUS FASTCALL ConioConsoleFromProcessData(PCONSOLE_PROCESS_DATA ProcessData, NTSTATUS FASTCALL ConioConsoleFromProcessData(PCONSOLE_PROCESS_DATA ProcessData,
PCSRSS_CONSOLE *Console); PCSRSS_CONSOLE *Console);
VOID WINAPI ConioDeleteConsole(Object_t *Object); VOID WINAPI ConioDeleteConsole(PCSRSS_CONSOLE Console);
VOID WINAPI CsrInitConsoleSupport(VOID); VOID WINAPI CsrInitConsoleSupport(VOID);
VOID FASTCALL ConioPause(PCSRSS_CONSOLE Console, UINT Flags); VOID FASTCALL ConioPause(PCSRSS_CONSOLE Console, UINT Flags);
VOID FASTCALL ConioUnpause(PCSRSS_CONSOLE Console, UINT Flags); VOID FASTCALL ConioUnpause(PCSRSS_CONSOLE Console, UINT Flags);

View file

@ -489,16 +489,17 @@ DoWriteConsole(IN PCSR_API_MESSAGE ApiMessage,
NULL, NULL,
NULL)) NULL))
{ {
/* Fail */
ConioUnlockScreenBuffer(Buff); ConioUnlockScreenBuffer(Buff);
return STATUS_NO_MEMORY; return STATUS_NO_MEMORY;
} }
} }
/* Wait until we un-pause the console */ /* Wait until we un-pause the console */
ConioUnlockScreenBuffer(Buff); Status = STATUS_PENDING;
return STATUS_PENDING;
} }
else
{
if(WriteConsoleRequest->Unicode) if(WriteConsoleRequest->Unicode)
{ {
Length = WideCharToMultiByte(Console->OutputCodePage, 0, Length = WideCharToMultiByte(Console->OutputCodePage, 0,
@ -541,6 +542,7 @@ DoWriteConsole(IN PCSR_API_MESSAGE ApiMessage,
} }
WriteConsoleRequest->NrCharactersWritten = Written; WriteConsoleRequest->NrCharactersWritten = Written;
}
ConioUnlockScreenBuffer(Buff); ConioUnlockScreenBuffer(Buff);
return Status; return Status;

View file

@ -12,7 +12,7 @@
#include "guiconsole.h" #include "guiconsole.h"
#include "tuiconsole.h" #include "tuiconsole.h"
#define NDEBUG //#define NDEBUG
#include <debug.h> #include <debug.h>
/* FUNCTIONS *****************************************************************/ /* FUNCTIONS *****************************************************************/
@ -75,6 +75,7 @@ ConioConsoleCtrlEventTimeout(DWORD Event,
return; return;
} }
DPRINT1("We succeeded at creating ProcessData->CtrlDispatcher remote thread, ProcessId = %x, Process = 0x%p\n", ProcessData->Process->ClientId.UniqueProcess, ProcessData->Process);
WaitForSingleObject(Thread, Timeout); WaitForSingleObject(Thread, Timeout);
CloseHandle(Thread); CloseHandle(Thread);
} }
@ -86,15 +87,29 @@ ConioConsoleCtrlEvent(DWORD Event, PCONSOLE_PROCESS_DATA ProcessData)
ConioConsoleCtrlEventTimeout(Event, ProcessData, 0); ConioConsoleCtrlEventTimeout(Event, ProcessData, 0);
} }
static NTSTATUS WINAPI /* static */ NTSTATUS WINAPI
CsrInitConsole(PCSRSS_CONSOLE Console, int ShowCmd) CsrInitConsole(PCSRSS_CONSOLE* NewConsole, int ShowCmd)
{ {
NTSTATUS Status; NTSTATUS Status;
SECURITY_ATTRIBUTES SecurityAttributes; SECURITY_ATTRIBUTES SecurityAttributes;
PCSRSS_CONSOLE Console;
PCSRSS_SCREEN_BUFFER NewBuffer; PCSRSS_SCREEN_BUFFER NewBuffer;
BOOL GuiMode; BOOL GuiMode;
WCHAR Title[255]; WCHAR Title[255];
if (NewConsole == NULL) return STATUS_INVALID_PARAMETER;
*NewConsole = NULL;
/* Allocate a console structure */
Console = HeapAlloc(ConSrvHeap, HEAP_ZERO_MEMORY, sizeof(CSRSS_CONSOLE));
if (NULL == Console)
{
DPRINT1("Not enough memory for console creation.\n");
return STATUS_NO_MEMORY;
}
/* Initialize the console */
Console->Title.MaximumLength = Console->Title.Length = 0; Console->Title.MaximumLength = Console->Title.Length = 0;
Console->Title.Buffer = NULL; Console->Title.Buffer = NULL;
@ -112,6 +127,7 @@ CsrInitConsole(PCSRSS_CONSOLE Console, int ShowCmd)
Console->Header.Type = CONIO_CONSOLE_MAGIC; Console->Header.Type = CONIO_CONSOLE_MAGIC;
Console->Header.Console = Console; Console->Header.Console = Console;
Console->Mode = ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT | ENABLE_PROCESSED_INPUT | ENABLE_MOUSE_INPUT; Console->Mode = ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT | ENABLE_PROCESSED_INPUT | ENABLE_MOUSE_INPUT;
InitializeListHead(&Console->ProcessList);
InitializeListHead(&Console->BufferList); InitializeListHead(&Console->BufferList);
Console->ActiveBuffer = NULL; Console->ActiveBuffer = NULL;
InitializeListHead(&Console->ReadWaitQueue); InitializeListHead(&Console->ReadWaitQueue);
@ -129,6 +145,7 @@ CsrInitConsole(PCSRSS_CONSOLE Console, int ShowCmd)
if (NULL == Console->ActiveEvent) if (NULL == Console->ActiveEvent)
{ {
RtlFreeUnicodeString(&Console->Title); RtlFreeUnicodeString(&Console->Title);
HeapFree(ConSrvHeap, 0, Console);
return STATUS_UNSUCCESSFUL; return STATUS_UNSUCCESSFUL;
} }
Console->PrivateData = NULL; Console->PrivateData = NULL;
@ -143,6 +160,7 @@ CsrInitConsole(PCSRSS_CONSOLE Console, int ShowCmd)
RtlFreeUnicodeString(&Console->Title); RtlFreeUnicodeString(&Console->Title);
DeleteCriticalSection(&Console->Lock); DeleteCriticalSection(&Console->Lock);
CloseHandle(Console->ActiveEvent); CloseHandle(Console->ActiveEvent);
HeapFree(ConSrvHeap, 0, Console);
return STATUS_INSUFFICIENT_RESOURCES; return STATUS_INSUFFICIENT_RESOURCES;
} }
/* init screen buffer with defaults */ /* init screen buffer with defaults */
@ -186,6 +204,7 @@ CsrInitConsole(PCSRSS_CONSOLE Console, int ShowCmd)
DeleteCriticalSection(&Console->Lock); DeleteCriticalSection(&Console->Lock);
CloseHandle(Console->ActiveEvent); CloseHandle(Console->ActiveEvent);
DPRINT1("GuiInitConsole: failed, Status = 0x%08lx\n", Status); DPRINT1("GuiInitConsole: failed, Status = 0x%08lx\n", Status);
HeapFree(ConSrvHeap, 0, Console);
return Status; return Status;
} }
} }
@ -199,12 +218,15 @@ CsrInitConsole(PCSRSS_CONSOLE Console, int ShowCmd)
CloseHandle(Console->ActiveEvent); CloseHandle(Console->ActiveEvent);
HeapFree(ConSrvHeap, 0, NewBuffer); HeapFree(ConSrvHeap, 0, NewBuffer);
DPRINT1("CsrInitConsoleScreenBuffer: failed\n"); DPRINT1("CsrInitConsoleScreenBuffer: failed\n");
HeapFree(ConSrvHeap, 0, Console);
return Status; return Status;
} }
/* copy buffer contents to screen */ /* Copy buffer contents to screen */
ConioDrawConsole(Console); ConioDrawConsole(Console);
*NewConsole = Console;
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }
@ -271,109 +293,116 @@ CSR_API(SrvAllocConsole)
NTSTATUS Status = STATUS_SUCCESS; NTSTATUS Status = STATUS_SUCCESS;
PCSRSS_ALLOC_CONSOLE AllocConsoleRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.AllocConsoleRequest; PCSRSS_ALLOC_CONSOLE AllocConsoleRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.AllocConsoleRequest;
PCONSOLE_PROCESS_DATA ProcessData = ConsoleGetPerProcessData(CsrGetClientThread()->Process); PCONSOLE_PROCESS_DATA ProcessData = ConsoleGetPerProcessData(CsrGetClientThread()->Process);
PCSRSS_CONSOLE Console;
BOOLEAN NewConsole = FALSE;
DPRINT("SrvAllocConsole\n"); DPRINT("SrvAllocConsole\n");
RtlEnterCriticalSection(&ProcessData->HandleTableLock); if (ProcessData->Console != NULL)
if (ProcessData->Console)
{ {
DPRINT1("Process already has a console\n"); DPRINT1("Process already has a console\n");
RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
return STATUS_INVALID_PARAMETER; return STATUS_INVALID_PARAMETER;
} }
RtlEnterCriticalSection(&ProcessData->HandleTableLock);
DPRINT1("SrvAllocConsole - Checkpoint 1\n"); DPRINT1("SrvAllocConsole - Checkpoint 1\n");
/* If we don't need a console, then get out of here */ /* Initialize a new Console */
if (!AllocConsoleRequest->ConsoleNeeded) Status = CsrInitConsole(&ProcessData->Console, AllocConsoleRequest->ShowCmd);
{
DPRINT("No console needed\n");
RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
return STATUS_SUCCESS;
}
/* If we already have one, then don't create a new one... */
if (!AllocConsoleRequest->Console ||
AllocConsoleRequest->Console != ProcessData->ParentConsole)
{
/* Allocate a console structure */
NewConsole = TRUE;
Console = HeapAlloc(ConSrvHeap, HEAP_ZERO_MEMORY, sizeof(CSRSS_CONSOLE));
if (NULL == Console)
{
DPRINT1("Not enough memory for console\n");
RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
return STATUS_NO_MEMORY;
}
/* Initialize list head */
InitializeListHead(&Console->ProcessList);
/* Insert process data required for GUI initialization */
InsertHeadList(&Console->ProcessList, &ProcessData->ConsoleLink);
/* Initialize the Console */
Status = CsrInitConsole(Console, AllocConsoleRequest->ShowCmd);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
DPRINT1("Console init failed\n"); DPRINT1("Console initialization failed\n");
HeapFree(ConSrvHeap, 0, Console);
RtlLeaveCriticalSection(&ProcessData->HandleTableLock); RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
return Status; return Status;
} }
}
else
{
/* Reuse our current console */
Console = AllocConsoleRequest->Console;
}
/* Set the Process Console */ /* Insert the process into the processes list of the console */
ProcessData->Console = Console; InsertHeadList(&ProcessData->Console->ProcessList, &ProcessData->ConsoleLink);
/* Return it to the caller */ /* Return it to the caller */
AllocConsoleRequest->Console = Console; AllocConsoleRequest->Console = ProcessData->Console;
/* Add a reference count because the process is tied to the console */ /* Add a reference count because the process is tied to the console */
_InterlockedIncrement(&Console->ReferenceCount); _InterlockedIncrement(&ProcessData->Console->ReferenceCount);
if (NewConsole || !ProcessData->bInheritHandles) #if 0000
/*
* We've just created a new console. However when ConsoleNewProcess was
* called, we didn't know that we wanted to create a new console and
* therefore, we by default inherited the handles table from our parent
* process. It's only now that we notice that in fact we do not need
* them, because we've created a new console and thus we must use it.
*
* Therefore, free our handles table and recreate a new one.
*/
ULONG i;
/* Close all console handles and free the handle table memory */
for (i = 0; i < ProcessData->HandleTableSize; i++)
{ {
/* Insert the Objects */ Win32CsrCloseHandleEntry(&ProcessData->HandleTable[i]);
}
ProcessData->HandleTableSize = 0;
RtlFreeHeap(ConSrvHeap, 0, ProcessData->HandleTable);
ProcessData->HandleTable = NULL;
#endif
/*
* Create a new handle table - Insert the IO handles
*/
/* Insert the Input handle */
Status = Win32CsrInsertObject(ProcessData, Status = Win32CsrInsertObject(ProcessData,
&AllocConsoleRequest->InputHandle, &AllocConsoleRequest->InputHandle,
&Console->Header, &ProcessData->Console->Header,
GENERIC_READ | GENERIC_WRITE, GENERIC_READ | GENERIC_WRITE,
TRUE, TRUE,
FILE_SHARE_READ | FILE_SHARE_WRITE); FILE_SHARE_READ | FILE_SHARE_WRITE);
if (! NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
DPRINT1("Failed to insert object\n"); DPRINT1("Failed to insert the input handle\n");
ConioDeleteConsole((Object_t *) Console); ConioDeleteConsole(ProcessData->Console);
ProcessData->Console = NULL; ProcessData->Console = NULL;
RtlLeaveCriticalSection(&ProcessData->HandleTableLock); RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
return Status; return Status;
} }
/* Insert the Output handle */
Status = Win32CsrInsertObject(ProcessData, Status = Win32CsrInsertObject(ProcessData,
&AllocConsoleRequest->OutputHandle, &AllocConsoleRequest->OutputHandle,
&Console->ActiveBuffer->Header, &ProcessData->Console->ActiveBuffer->Header,
GENERIC_READ | GENERIC_WRITE, GENERIC_READ | GENERIC_WRITE,
TRUE, TRUE,
FILE_SHARE_READ | FILE_SHARE_WRITE); FILE_SHARE_READ | FILE_SHARE_WRITE);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
DPRINT1("Failed to insert object\n"); DPRINT1("Failed to insert the output handle\n");
ConioDeleteConsole((Object_t *) Console); ConioDeleteConsole(ProcessData->Console);
Win32CsrReleaseObject(ProcessData, Win32CsrReleaseObject(ProcessData,
AllocConsoleRequest->InputHandle); AllocConsoleRequest->InputHandle);
ProcessData->Console = NULL; ProcessData->Console = NULL;
RtlLeaveCriticalSection(&ProcessData->HandleTableLock); RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
return Status; return Status;
} }
/* Insert the Error handle */
Status = Win32CsrInsertObject(ProcessData,
&AllocConsoleRequest->ErrorHandle,
&ProcessData->Console->ActiveBuffer->Header,
GENERIC_READ | GENERIC_WRITE,
TRUE,
FILE_SHARE_READ | FILE_SHARE_WRITE);
if (!NT_SUCCESS(Status))
{
DPRINT1("Failed to insert the error handle\n");
ConioDeleteConsole(ProcessData->Console);
Win32CsrReleaseObject(ProcessData,
AllocConsoleRequest->OutputHandle);
Win32CsrReleaseObject(ProcessData,
AllocConsoleRequest->InputHandle);
ProcessData->Console = NULL;
RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
return Status;
} }
/* Duplicate the Event */ /* Duplicate the Event */
@ -385,9 +414,11 @@ CSR_API(SrvAllocConsole)
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
DPRINT1("NtDuplicateObject() failed: %lu\n", Status); DPRINT1("NtDuplicateObject() failed: %lu\n", Status);
ConioDeleteConsole((Object_t *) Console); ConioDeleteConsole(ProcessData->Console);
if (NewConsole || !ProcessData->bInheritHandles) // if (NewConsole /* || !ProcessData->bInheritHandles */)
{ {
Win32CsrReleaseObject(ProcessData,
AllocConsoleRequest->ErrorHandle);
Win32CsrReleaseObject(ProcessData, Win32CsrReleaseObject(ProcessData,
AllocConsoleRequest->OutputHandle); AllocConsoleRequest->OutputHandle);
Win32CsrReleaseObject(ProcessData, Win32CsrReleaseObject(ProcessData,
@ -397,38 +428,31 @@ CSR_API(SrvAllocConsole)
RtlLeaveCriticalSection(&ProcessData->HandleTableLock); RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
return Status; return Status;
} }
/* Input Wait Handle */
AllocConsoleRequest->InputWaitHandle = ProcessData->ConsoleEvent;
/* Set the Ctrl Dispatcher */ /* Set the Ctrl Dispatcher */
ProcessData->CtrlDispatcher = AllocConsoleRequest->CtrlDispatcher; ProcessData->CtrlDispatcher = AllocConsoleRequest->CtrlDispatcher;
DPRINT("CSRSS:CtrlDispatcher address: %x\n", ProcessData->CtrlDispatcher); DPRINT("CSRSS:CtrlDispatcher address: %x\n", ProcessData->CtrlDispatcher);
if (!NewConsole)
{
/* Insert into the list if it has not been added */
InsertHeadList(&ProcessData->Console->ProcessList, &ProcessData->ConsoleLink);
}
RtlLeaveCriticalSection(&ProcessData->HandleTableLock); RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }
CSR_API(SrvFreeConsole) CSR_API(SrvFreeConsole)
{ {
DPRINT1("SrvFreeConsole\n");
Win32CsrReleaseConsole(CsrGetClientThread()->Process); Win32CsrReleaseConsole(CsrGetClientThread()->Process);
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }
VOID WINAPI VOID WINAPI
ConioDeleteConsole(Object_t *Object) ConioDeleteConsole(PCSRSS_CONSOLE Console)
{ {
PCSRSS_CONSOLE Console = (PCSRSS_CONSOLE) Object;
ConsoleInput *Event; ConsoleInput *Event;
DPRINT("ConioDeleteConsole\n"); DPRINT("ConioDeleteConsole\n");
/* TODO: Dereference all the waits in Console->ReadWaitQueue */
/* TODO: Dereference all the waits in Console->WriteWaitQueue */
/* Drain input event queue */ /* Drain input event queue */
while (Console->InputEvents.Flink != &Console->InputEvents) while (Console->InputEvents.Flink != &Console->InputEvents)
{ {

View file

@ -35,6 +35,9 @@ extern HANDLE ConSrvHeap;
// extern HANDLE BaseSrvSharedHeap; // extern HANDLE BaseSrvSharedHeap;
// extern PBASE_STATIC_SERVER_DATA BaseStaticServerData; // extern PBASE_STATIC_SERVER_DATA BaseStaticServerData;
/* Object type magic numbers */
#define CONIO_CONSOLE_MAGIC 0x00000001 // --> Input-type handles
#define CONIO_SCREEN_BUFFER_MAGIC 0x00000002 // --> Output-type handles
/* Common things to input/output/console objects */ /* Common things to input/output/console objects */
typedef struct Object_tt typedef struct Object_tt
@ -62,14 +65,17 @@ typedef struct _CSRSS_HANDLE
typedef struct _CONSOLE_PROCESS_DATA typedef struct _CONSOLE_PROCESS_DATA
{ {
LIST_ENTRY ConsoleLink; LIST_ENTRY ConsoleLink;
PCSR_PROCESS Process; // Parent process. PCSR_PROCESS Process; // Process owning this structure.
HANDLE ConsoleEvent; HANDLE ConsoleEvent;
/* PCSRSS_CONSOLE */ struct tagCSRSS_CONSOLE* Console; /* PCSRSS_CONSOLE */ struct tagCSRSS_CONSOLE* Console;
/* PCSRSS_CONSOLE */ struct tagCSRSS_CONSOLE* ParentConsole; /* PCSRSS_CONSOLE */ struct tagCSRSS_CONSOLE* ParentConsole;
BOOL bInheritHandles;
// BOOL bInheritHandles;
BOOL ConsoleApp; // TRUE if it is a CUI app, FALSE otherwise.
RTL_CRITICAL_SECTION HandleTableLock; RTL_CRITICAL_SECTION HandleTableLock;
ULONG HandleTableSize; ULONG HandleTableSize;
/* PCSRSS_HANDLE */ struct _CSRSS_HANDLE* HandleTable; // Is it a length-varying table or length-fixed ?? PCSRSS_HANDLE HandleTable; // Length-varying table
LPTHREAD_START_ROUTINE CtrlDispatcher; LPTHREAD_START_ROUTINE CtrlDispatcher;
} CONSOLE_PROCESS_DATA, *PCONSOLE_PROCESS_DATA; } CONSOLE_PROCESS_DATA, *PCONSOLE_PROCESS_DATA;
@ -128,11 +134,7 @@ CSR_API(SrvGetConsoleSelectionInfo);
CSR_API(SrvCloseHandle); CSR_API(SrvCloseHandle);
CSR_API(SrvVerifyConsoleIoHandle); CSR_API(SrvVerifyConsoleIoHandle);
CSR_API(SrvDuplicateHandle); CSR_API(SrvDuplicateHandle);
CSR_API(CsrGetInputWaitHandle); /// CSR_API(CsrGetInputWaitHandle);
NTSTATUS NTAPI ConsoleNewProcess(PCSR_PROCESS SourceProcess,
PCSR_PROCESS TargetProcess);
VOID NTAPI Win32CsrReleaseConsole(PCSR_PROCESS Process);
NTSTATUS FASTCALL Win32CsrInsertObject(PCONSOLE_PROCESS_DATA ProcessData, NTSTATUS FASTCALL Win32CsrInsertObject(PCONSOLE_PROCESS_DATA ProcessData,
PHANDLE Handle, PHANDLE Handle,
@ -149,6 +151,14 @@ VOID FASTCALL Win32CsrUnlockObject(Object_t *Object);
NTSTATUS FASTCALL Win32CsrReleaseObject(PCONSOLE_PROCESS_DATA ProcessData, NTSTATUS FASTCALL Win32CsrReleaseObject(PCONSOLE_PROCESS_DATA ProcessData,
HANDLE Handle); HANDLE Handle);
NTSTATUS NTAPI ConsoleNewProcess(PCSR_PROCESS SourceProcess,
PCSR_PROCESS TargetProcess);
NTSTATUS NTAPI ConsoleConnect(IN PCSR_PROCESS CsrProcess,
IN OUT PVOID ConnectionInfo,
IN OUT PULONG ConnectionInfoLength);
VOID NTAPI ConsoleDisconnect(PCSR_PROCESS Process);
VOID NTAPI Win32CsrReleaseConsole(PCSR_PROCESS Process);
/* lineinput.c */ /* lineinput.c */
CSR_API(SrvGetConsoleCommandHistoryLength); CSR_API(SrvGetConsoleCommandHistoryLength);
CSR_API(SrvGetConsoleCommandHistory); CSR_API(SrvGetConsoleCommandHistory);

View file

@ -11,7 +11,7 @@
#include "consrv.h" #include "consrv.h"
#include "conio.h" #include "conio.h"
#define NDEBUG //#define NDEBUG
#include <debug.h> #include <debug.h>
@ -21,11 +21,16 @@ static INT
AdjustHandleCounts(PCSRSS_HANDLE Entry, INT Change) AdjustHandleCounts(PCSRSS_HANDLE Entry, INT Change)
{ {
Object_t *Object = Entry->Object; Object_t *Object = Entry->Object;
DPRINT1("AdjustHandleCounts(0x%p, %d), Object = 0x%p, Object->HandleCount = %d, Object->Type = %lu\n", Entry, Change, Object, Object->HandleCount, Object->Type);
if (Entry->Access & GENERIC_READ) Object->AccessRead += Change; if (Entry->Access & GENERIC_READ) Object->AccessRead += Change;
if (Entry->Access & GENERIC_WRITE) Object->AccessWrite += Change; if (Entry->Access & GENERIC_WRITE) Object->AccessWrite += Change;
if (!(Entry->ShareMode & FILE_SHARE_READ)) Object->ExclusiveRead += Change; if (!(Entry->ShareMode & FILE_SHARE_READ)) Object->ExclusiveRead += Change;
if (!(Entry->ShareMode & FILE_SHARE_WRITE)) Object->ExclusiveWrite += Change; if (!(Entry->ShareMode & FILE_SHARE_WRITE)) Object->ExclusiveWrite += Change;
Object->HandleCount += Change; Object->HandleCount += Change;
return Object->HandleCount; return Object->HandleCount;
} }
@ -46,9 +51,11 @@ Win32CsrCloseHandleEntry(PCSRSS_HANDLE Entry)
{ {
PCSRSS_CONSOLE Console = Object->Console; PCSRSS_CONSOLE Console = Object->Console;
EnterCriticalSection(&Console->Lock); EnterCriticalSection(&Console->Lock);
/* If the last handle to a screen buffer is closed, delete it */
if (AdjustHandleCounts(Entry, -1) == 0 /* If the last handle to a screen buffer is closed, delete it... */
&& Object->Type == CONIO_SCREEN_BUFFER_MAGIC) if (AdjustHandleCounts(Entry, -1) == 0)
{
if (Object->Type == CONIO_SCREEN_BUFFER_MAGIC)
{ {
PCSRSS_SCREEN_BUFFER Buffer = (PCSRSS_SCREEN_BUFFER)Object; PCSRSS_SCREEN_BUFFER Buffer = (PCSRSS_SCREEN_BUFFER)Object;
/* ...unless it's the only buffer left. Windows allows deletion /* ...unless it's the only buffer left. Windows allows deletion
@ -57,6 +64,13 @@ Win32CsrCloseHandleEntry(PCSRSS_HANDLE Entry)
if (Buffer->ListEntry.Flink != Buffer->ListEntry.Blink) if (Buffer->ListEntry.Flink != Buffer->ListEntry.Blink)
ConioDeleteScreenBuffer(Buffer); ConioDeleteScreenBuffer(Buffer);
} }
else if (Object->Type == CONIO_CONSOLE_MAGIC)
{
/* TODO: FIXME: Destroy here the console ?? */
// ConioDeleteConsole(Console);
}
}
LeaveCriticalSection(&Console->Lock); LeaveCriticalSection(&Console->Lock);
Entry->Object = NULL; Entry->Object = NULL;
} }
@ -94,7 +108,7 @@ Win32CsrInsertObject(PCONSOLE_PROCESS_DATA ProcessData,
if (Block == NULL) if (Block == NULL)
{ {
RtlLeaveCriticalSection(&ProcessData->HandleTableLock); RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
return(STATUS_UNSUCCESSFUL); return STATUS_UNSUCCESSFUL;
} }
RtlCopyMemory(Block, RtlCopyMemory(Block,
ProcessData->HandleTable, ProcessData->HandleTable,
@ -129,6 +143,8 @@ Win32CsrReleaseObject(PCONSOLE_PROCESS_DATA ProcessData,
RtlLeaveCriticalSection(&ProcessData->HandleTableLock); RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
return STATUS_INVALID_HANDLE; return STATUS_INVALID_HANDLE;
} }
DPRINT1("Win32CsrReleaseObject - Process 0x%p, Release 0x%p\n", ProcessData->Process, &ProcessData->HandleTable[h]);
Win32CsrCloseHandleEntry(&ProcessData->HandleTable[h]); Win32CsrCloseHandleEntry(&ProcessData->HandleTable[h]);
RtlLeaveCriticalSection(&ProcessData->HandleTableLock); RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
@ -169,24 +185,43 @@ Win32CsrLockObject(PCONSOLE_PROCESS_DATA ProcessData,
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }
VOID FASTCALL
Win32CsrUnlockConsole(PCSRSS_CONSOLE Console)
{
LeaveCriticalSection(&Console->Lock);
/* Decrement reference count */
if (_InterlockedDecrement(&Console->ReferenceCount) == 0)
ConioDeleteConsole(Console);
}
VOID VOID
FASTCALL FASTCALL
Win32CsrUnlockObject(Object_t *Object) Win32CsrUnlockObject(Object_t *Object)
{ {
PCSRSS_CONSOLE Console = Object->Console; Win32CsrUnlockConsole(Object->Console);
LeaveCriticalSection(&Console->Lock);
/* dec ref count */
if (_InterlockedDecrement(&Console->ReferenceCount) == 0)
ConioDeleteConsole(&Console->Header);
} }
/** Remark: this function can be called by SrvAttachConsole (not yet implemented) **/
NTSTATUS NTSTATUS
NTAPI NTAPI
ConsoleNewProcess(PCSR_PROCESS SourceProcess, ConsoleNewProcess(PCSR_PROCESS SourceProcess,
PCSR_PROCESS TargetProcess) PCSR_PROCESS TargetProcess)
{ {
/**************************************************************************
* This function is called whenever a new process (GUI or CUI) is created.
*
* Copy the parent's handles table here if both the parent and the child
* processes are CUI. If we must actually create our proper console (and
* thus do not inherit from the console handles of the parent's), then we
* will clean this table in the next ConsoleConnect call. Why we are doing
* this? It's because here, we still don't know whether or not we must create
* a new console instead of inherit it from the parent, and, because in
* ConsoleConnect we don't have any reference to the parent process anymore.
**************************************************************************/
PCONSOLE_PROCESS_DATA SourceProcessData, TargetProcessData; PCONSOLE_PROCESS_DATA SourceProcessData, TargetProcessData;
ULONG i; ULONG i;
@ -200,9 +235,22 @@ ConsoleNewProcess(PCSR_PROCESS SourceProcess,
DPRINT1("ConsoleNewProcess - OK\n"); DPRINT1("ConsoleNewProcess - OK\n");
TargetProcessData = ConsoleGetPerProcessData(TargetProcess); TargetProcessData = ConsoleGetPerProcessData(TargetProcess);
DPRINT1("TargetProcessData = 0x%p\n", TargetProcessData);
/**** HACK !!!! ****/ RtlZeroMemory(TargetProcessData, sizeof(*TargetProcessData));
/* Initialize the new (target) process */ /* Initialize the new (target) process */
TargetProcessData->Process = TargetProcess; TargetProcessData->Process = TargetProcess;
TargetProcessData->ConsoleEvent = NULL;
TargetProcessData->Console = TargetProcessData->ParentConsole = NULL;
// TargetProcessData->bInheritHandles = FALSE;
TargetProcessData->ConsoleApp = ((TargetProcess->Flags & CsrProcessIsConsoleApp) ? TRUE : FALSE);
// Testing
TargetProcessData->HandleTableSize = 0;
TargetProcessData->HandleTable = NULL;
/* HACK */ RtlZeroMemory(&TargetProcessData->HandleTableLock, sizeof(RTL_CRITICAL_SECTION));
RtlInitializeCriticalSection(&TargetProcessData->HandleTableLock); RtlInitializeCriticalSection(&TargetProcessData->HandleTableLock);
/* Do nothing if the source process is NULL */ /* Do nothing if the source process is NULL */
@ -210,27 +258,29 @@ ConsoleNewProcess(PCSR_PROCESS SourceProcess,
return STATUS_SUCCESS; return STATUS_SUCCESS;
SourceProcessData = ConsoleGetPerProcessData(SourceProcess); SourceProcessData = ConsoleGetPerProcessData(SourceProcess);
DPRINT1("SourceProcessData = 0x%p\n", SourceProcessData);
// TODO: Check if one of the processes is really a CONSOLE.
/* /*
if (!(CreateProcessRequest->CreationFlags & (CREATE_NEW_CONSOLE | DETACHED_PROCESS))) * If both of the processes (parent and new child) are console applications,
{ * then try to inherit handles from the parent process.
// NewProcess == TargetProcess.
NewProcess->ParentConsole = Process->Console;
NewProcess->bInheritHandles = CreateProcessRequest->bInheritHandles;
}
*/ */
if ( SourceProcessData->Console != NULL && /* SourceProcessData->ConsoleApp */
/* Only inherit if the if the flag was set */ TargetProcessData->ConsoleApp )
if (!TargetProcessData->bInheritHandles) return STATUS_SUCCESS; {
/*
if (TargetProcessData->HandleTableSize) if (TargetProcessData->HandleTableSize)
{ {
return STATUS_INVALID_PARAMETER; return STATUS_INVALID_PARAMETER;
} }
*/
DPRINT1("ConsoleNewProcess - Copy the handle table (1)\n");
/* Temporary "inherit" the console from the parent */
TargetProcessData->ParentConsole = SourceProcessData->Console;
RtlEnterCriticalSection(&SourceProcessData->HandleTableLock); RtlEnterCriticalSection(&SourceProcessData->HandleTableLock);
DPRINT1("ConsoleNewProcess - Copy the handle table (2)\n");
/* Allocate a new handle table for the child process */
TargetProcessData->HandleTable = RtlAllocateHeap(ConSrvHeap, TargetProcessData->HandleTable = RtlAllocateHeap(ConSrvHeap,
HEAP_ZERO_MEMORY, HEAP_ZERO_MEMORY,
SourceProcessData->HandleTableSize SourceProcessData->HandleTableSize
@ -243,21 +293,224 @@ ConsoleNewProcess(PCSR_PROCESS SourceProcess,
TargetProcessData->HandleTableSize = SourceProcessData->HandleTableSize; TargetProcessData->HandleTableSize = SourceProcessData->HandleTableSize;
/*
* Parse the parent process' handles table and, for each handle,
* do a copy of it and reference it, if the handle is inheritable.
*/
for (i = 0; i < SourceProcessData->HandleTableSize; i++) for (i = 0; i < SourceProcessData->HandleTableSize; i++)
{ {
if (SourceProcessData->HandleTable[i].Object != NULL && if (SourceProcessData->HandleTable[i].Object != NULL &&
SourceProcessData->HandleTable[i].Inheritable) SourceProcessData->HandleTable[i].Inheritable)
{ {
/*
* Copy the handle data and increment the reference count of the
* pointed object (via the call to Win32CsrCreateHandleEntry).
*/
TargetProcessData->HandleTable[i] = SourceProcessData->HandleTable[i]; TargetProcessData->HandleTable[i] = SourceProcessData->HandleTable[i];
Win32CsrCreateHandleEntry(&TargetProcessData->HandleTable[i]); Win32CsrCreateHandleEntry(&TargetProcessData->HandleTable[i]);
} }
} }
RtlLeaveCriticalSection(&SourceProcessData->HandleTableLock); RtlLeaveCriticalSection(&SourceProcessData->HandleTableLock);
}
else
{
DPRINT1("ConsoleNewProcess - We don't launch a Console process : SourceProcessData->Console = 0x%p ; TargetProcess->Flags = %lu\n", SourceProcessData->Console, TargetProcess->Flags);
}
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }
// Temporary ; move it to a header.
NTSTATUS WINAPI CsrInitConsole(PCSRSS_CONSOLE* NewConsole, int ShowCmd);
NTSTATUS
NTAPI
ConsoleConnect(IN PCSR_PROCESS CsrProcess,
IN OUT PVOID ConnectionInfo,
IN OUT PULONG ConnectionInfoLength)
{
/**************************************************************************
* This function is called whenever a CUI new process is created.
**************************************************************************/
NTSTATUS Status = STATUS_SUCCESS;
PCONSOLE_CONNECTION_INFO ConnectInfo = (PCONSOLE_CONNECTION_INFO)ConnectionInfo;
PCONSOLE_PROCESS_DATA ProcessData = ConsoleGetPerProcessData(CsrProcess);
BOOLEAN NewConsole = FALSE;
// PCSRSS_CONSOLE Console = NULL;
DPRINT1("ConsoleConnect\n");
if ( ConnectionInfo == NULL ||
ConnectionInfoLength == NULL ||
*ConnectionInfoLength != sizeof(CONSOLE_CONNECTION_INFO) )
{
DPRINT1("CONSRV: Connection failed\n");
return STATUS_UNSUCCESSFUL;
}
/* If we don't need a console, then get out of here */
if (!ConnectInfo->ConsoleNeeded || !ProcessData->ConsoleApp) // In fact, it is for GUI apps.
{
DPRINT("ConsoleConnect - No console needed\n");
return STATUS_SUCCESS;
}
RtlEnterCriticalSection(&ProcessData->HandleTableLock);
/* If we don't have a console, then create a new one... */
if (!ConnectInfo->Console ||
ConnectInfo->Console != ProcessData->ParentConsole)
{
// PCSRSS_CONSOLE Console;
DPRINT1("ConsoleConnect - Allocate a new console\n");
/* Initialize a new Console */
NewConsole = TRUE;
Status = CsrInitConsole(&ProcessData->Console, ConnectInfo->ShowCmd);
if (!NT_SUCCESS(Status))
{
DPRINT1("Console initialization failed\n");
RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
return Status;
}
}
else /* We inherit it from the parent */
{
DPRINT1("ConsoleConnect - Reuse current (parent's) console\n");
/* Reuse our current console */
NewConsole = FALSE;
ProcessData->Console = ConnectInfo->Console;
}
/* Insert the process into the processes list of the console */
InsertHeadList(&ProcessData->Console->ProcessList, &ProcessData->ConsoleLink);
/* Return it to the caller */
ConnectInfo->Console = ProcessData->Console;
/* Add a reference count because the process is tied to the console */
_InterlockedIncrement(&ProcessData->Console->ReferenceCount);
if (NewConsole /* || !ProcessData->bInheritHandles */)
{
/*
* We've just created a new console. However when ConsoleNewProcess was
* called, we didn't know that we wanted to create a new console and
* therefore, we by default inherited the handles table from our parent
* process. It's only now that we notice that in fact we do not need
* them, because we've created a new console and thus we must use it.
*
* Therefore, free our handles table and recreate a new one.
*/
ULONG i;
/* Close all console handles and free the handle table memory */
for (i = 0; i < ProcessData->HandleTableSize; i++)
{
Win32CsrCloseHandleEntry(&ProcessData->HandleTable[i]);
}
ProcessData->HandleTableSize = 0;
RtlFreeHeap(ConSrvHeap, 0, ProcessData->HandleTable);
ProcessData->HandleTable = NULL;
/*
* Create a new handle table - Insert the IO handles
*/
/* Insert the Input handle */
Status = Win32CsrInsertObject(ProcessData,
&ConnectInfo->InputHandle,
&ProcessData->Console->Header,
GENERIC_READ | GENERIC_WRITE,
TRUE,
FILE_SHARE_READ | FILE_SHARE_WRITE);
if (!NT_SUCCESS(Status))
{
DPRINT1("Failed to insert the input handle\n");
ConioDeleteConsole(ProcessData->Console);
ProcessData->Console = NULL;
RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
return Status;
}
/* Insert the Output handle */
Status = Win32CsrInsertObject(ProcessData,
&ConnectInfo->OutputHandle,
&ProcessData->Console->ActiveBuffer->Header,
GENERIC_READ | GENERIC_WRITE,
TRUE,
FILE_SHARE_READ | FILE_SHARE_WRITE);
if (!NT_SUCCESS(Status))
{
DPRINT1("Failed to insert the output handle\n");
ConioDeleteConsole(ProcessData->Console);
Win32CsrReleaseObject(ProcessData,
ConnectInfo->InputHandle);
ProcessData->Console = NULL;
RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
return Status;
}
/* Insert the Error handle */
Status = Win32CsrInsertObject(ProcessData,
&ConnectInfo->ErrorHandle,
&ProcessData->Console->ActiveBuffer->Header,
GENERIC_READ | GENERIC_WRITE,
TRUE,
FILE_SHARE_READ | FILE_SHARE_WRITE);
if (!NT_SUCCESS(Status))
{
DPRINT1("Failed to insert the error handle\n");
ConioDeleteConsole(ProcessData->Console);
Win32CsrReleaseObject(ProcessData,
ConnectInfo->OutputHandle);
Win32CsrReleaseObject(ProcessData,
ConnectInfo->InputHandle);
ProcessData->Console = NULL;
RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
return Status;
}
}
/* Duplicate the Event */
Status = NtDuplicateObject(NtCurrentProcess(),
ProcessData->Console->ActiveEvent,
ProcessData->Process->ProcessHandle,
&ProcessData->ConsoleEvent,
EVENT_ALL_ACCESS, 0, 0);
if (!NT_SUCCESS(Status))
{
DPRINT1("NtDuplicateObject() failed: %lu\n", Status);
ConioDeleteConsole(ProcessData->Console);
if (NewConsole /* || !ProcessData->bInheritHandles */)
{
Win32CsrReleaseObject(ProcessData,
ConnectInfo->ErrorHandle);
Win32CsrReleaseObject(ProcessData,
ConnectInfo->OutputHandle);
Win32CsrReleaseObject(ProcessData,
ConnectInfo->InputHandle);
}
ProcessData->Console = NULL;
RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
return Status;
}
/* Input Wait Handle */
ConnectInfo->InputWaitHandle = ProcessData->ConsoleEvent;
/* Set the Ctrl Dispatcher */
ProcessData->CtrlDispatcher = ConnectInfo->CtrlDispatcher;
DPRINT("CSRSS:CtrlDispatcher address: %x\n", ProcessData->CtrlDispatcher);
RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
return STATUS_SUCCESS;
}
VOID VOID
WINAPI WINAPI
Win32CsrReleaseConsole(PCSR_PROCESS Process) Win32CsrReleaseConsole(PCSR_PROCESS Process)
@ -266,30 +519,63 @@ Win32CsrReleaseConsole(PCSR_PROCESS Process)
PCSRSS_CONSOLE Console; PCSRSS_CONSOLE Console;
ULONG i; ULONG i;
/* Close all console handles and detach process from console */ DPRINT1("Win32CsrReleaseConsole\n");
RtlEnterCriticalSection(&ProcessData->HandleTableLock); RtlEnterCriticalSection(&ProcessData->HandleTableLock);
/* Close all console handles and free the handle table memory */
for (i = 0; i < ProcessData->HandleTableSize; i++) for (i = 0; i < ProcessData->HandleTableSize; i++)
{
Win32CsrCloseHandleEntry(&ProcessData->HandleTable[i]); Win32CsrCloseHandleEntry(&ProcessData->HandleTable[i]);
}
ProcessData->HandleTableSize = 0; ProcessData->HandleTableSize = 0;
RtlFreeHeap(ConSrvHeap, 0, ProcessData->HandleTable); RtlFreeHeap(ConSrvHeap, 0, ProcessData->HandleTable);
ProcessData->HandleTable = NULL; ProcessData->HandleTable = NULL;
/* Detach process from console */
Console = ProcessData->Console; Console = ProcessData->Console;
if (Console != NULL) if (Console != NULL)
{ {
DPRINT1("Win32CsrReleaseConsole - Console->ReferenceCount = %lu - We are going to decrement it !\n", Console->ReferenceCount);
ProcessData->Console = NULL; ProcessData->Console = NULL;
EnterCriticalSection(&Console->Lock); EnterCriticalSection(&Console->Lock);
RemoveEntryList(&ProcessData->ConsoleLink); RemoveEntryList(&ProcessData->ConsoleLink);
LeaveCriticalSection(&Console->Lock); Win32CsrUnlockConsole(Console);
if (_InterlockedDecrement(&Console->ReferenceCount) == 0)
ConioDeleteConsole(&Console->Header);
//CloseHandle(ProcessData->ConsoleEvent); //CloseHandle(ProcessData->ConsoleEvent);
//ProcessData->ConsoleEvent = NULL; //ProcessData->ConsoleEvent = NULL;
} }
RtlLeaveCriticalSection(&ProcessData->HandleTableLock); RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
} }
VOID
WINAPI
ConsoleDisconnect(PCSR_PROCESS Process)
{
PCONSOLE_PROCESS_DATA ProcessData = ConsoleGetPerProcessData(Process);
/**************************************************************************
* This function is called whenever a new process (GUI or CUI) is destroyed.
*
* Only do something if the process is a CUI. <-- modify this behaviour if
* we deal with a GUI which
* quits and acquired a
* console...
**************************************************************************/
DPRINT1("ConsoleDisconnect called\n");
// if (ProcessData->Console != NULL)
if (ProcessData->ConsoleApp)
{
DPRINT1("ConsoleDisconnect - calling Win32CsrReleaseConsole\n");
Win32CsrReleaseConsole(Process);
}
RtlDeleteCriticalSection(&ProcessData->HandleTableLock);
}
CSR_API(SrvCloseHandle) CSR_API(SrvCloseHandle)
{ {
PCSRSS_CLOSE_HANDLE CloseHandleRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.CloseHandleRequest; PCSRSS_CLOSE_HANDLE CloseHandleRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.CloseHandleRequest;
@ -374,6 +660,7 @@ CSR_API(SrvDuplicateHandle)
return ApiMessage->Status; return ApiMessage->Status;
} }
/**
CSR_API(CsrGetInputWaitHandle) CSR_API(CsrGetInputWaitHandle)
{ {
PCSRSS_GET_INPUT_WAIT_HANDLE GetConsoleInputWaitHandle = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GetConsoleInputWaitHandle; PCSRSS_GET_INPUT_WAIT_HANDLE GetConsoleInputWaitHandle = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GetConsoleInputWaitHandle;
@ -383,5 +670,6 @@ CSR_API(CsrGetInputWaitHandle)
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }
**/
/* EOF */ /* EOF */

View file

@ -460,8 +460,8 @@ CSR_SERVER_DLL_INIT(ConServerDllInitialization)
LoadedServerDll->ValidTable = ConsoleServerApiServerValidTable; LoadedServerDll->ValidTable = ConsoleServerApiServerValidTable;
LoadedServerDll->NameTable = ConsoleServerApiNameTable; LoadedServerDll->NameTable = ConsoleServerApiNameTable;
LoadedServerDll->SizeOfProcessData = sizeof(CONSOLE_PROCESS_DATA); LoadedServerDll->SizeOfProcessData = sizeof(CONSOLE_PROCESS_DATA);
LoadedServerDll->ConnectCallback = NULL; LoadedServerDll->ConnectCallback = ConsoleConnect;
LoadedServerDll->DisconnectCallback = Win32CsrReleaseConsole; LoadedServerDll->DisconnectCallback = ConsoleDisconnect;
LoadedServerDll->NewProcessCallback = ConsoleNewProcess; LoadedServerDll->NewProcessCallback = ConsoleNewProcess;
// LoadedServerDll->HardErrorCallback = Win32CsrHardError; // LoadedServerDll->HardErrorCallback = Win32CsrHardError;