mirror of
https://github.com/reactos/reactos.git
synced 2025-07-05 11:21:21 +00:00
[CONSRV]
- 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:
parent
e635242284
commit
dd5a9c5231
6 changed files with 519 additions and 200 deletions
|
@ -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);
|
||||||
|
|
|
@ -489,58 +489,60 @@ 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(WriteConsoleRequest->Unicode)
|
|
||||||
{
|
|
||||||
Length = WideCharToMultiByte(Console->OutputCodePage, 0,
|
|
||||||
(PWCHAR)WriteConsoleRequest->Buffer,
|
|
||||||
WriteConsoleRequest->NrCharactersToWrite,
|
|
||||||
NULL, 0, NULL, NULL);
|
|
||||||
Buffer = RtlAllocateHeap(GetProcessHeap(), 0, Length);
|
|
||||||
if (Buffer)
|
|
||||||
{
|
|
||||||
WideCharToMultiByte(Console->OutputCodePage, 0,
|
|
||||||
(PWCHAR)WriteConsoleRequest->Buffer,
|
|
||||||
WriteConsoleRequest->NrCharactersToWrite,
|
|
||||||
Buffer, Length, NULL, NULL);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Status = STATUS_NO_MEMORY;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Buffer = (PCHAR)WriteConsoleRequest->Buffer;
|
if(WriteConsoleRequest->Unicode)
|
||||||
}
|
|
||||||
|
|
||||||
if (Buffer)
|
|
||||||
{
|
|
||||||
if (NT_SUCCESS(Status))
|
|
||||||
{
|
{
|
||||||
Status = ConioWriteConsole(Console, Buff, Buffer,
|
Length = WideCharToMultiByte(Console->OutputCodePage, 0,
|
||||||
WriteConsoleRequest->NrCharactersToWrite, TRUE);
|
(PWCHAR)WriteConsoleRequest->Buffer,
|
||||||
if (NT_SUCCESS(Status))
|
WriteConsoleRequest->NrCharactersToWrite,
|
||||||
|
NULL, 0, NULL, NULL);
|
||||||
|
Buffer = RtlAllocateHeap(GetProcessHeap(), 0, Length);
|
||||||
|
if (Buffer)
|
||||||
{
|
{
|
||||||
Written = WriteConsoleRequest->NrCharactersToWrite;
|
WideCharToMultiByte(Console->OutputCodePage, 0,
|
||||||
|
(PWCHAR)WriteConsoleRequest->Buffer,
|
||||||
|
WriteConsoleRequest->NrCharactersToWrite,
|
||||||
|
Buffer, Length, NULL, NULL);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Status = STATUS_NO_MEMORY;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (WriteConsoleRequest->Unicode)
|
else
|
||||||
{
|
{
|
||||||
RtlFreeHeap(GetProcessHeap(), 0, Buffer);
|
Buffer = (PCHAR)WriteConsoleRequest->Buffer;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
WriteConsoleRequest->NrCharactersWritten = Written;
|
if (Buffer)
|
||||||
|
{
|
||||||
|
if (NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
Status = ConioWriteConsole(Console, Buff, Buffer,
|
||||||
|
WriteConsoleRequest->NrCharactersToWrite, TRUE);
|
||||||
|
if (NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
Written = WriteConsoleRequest->NrCharactersToWrite;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (WriteConsoleRequest->Unicode)
|
||||||
|
{
|
||||||
|
RtlFreeHeap(GetProcessHeap(), 0, Buffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
WriteConsoleRequest->NrCharactersWritten = Written;
|
||||||
|
}
|
||||||
|
|
||||||
ConioUnlockScreenBuffer(Buff);
|
ConioUnlockScreenBuffer(Buff);
|
||||||
return Status;
|
return Status;
|
||||||
|
|
|
@ -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);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
DPRINT("No console needed\n");
|
DPRINT1("Console initialization failed\n");
|
||||||
RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
|
RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
|
||||||
return STATUS_SUCCESS;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If we already have one, then don't create a new one... */
|
/* Insert the process into the processes list of the console */
|
||||||
if (!AllocConsoleRequest->Console ||
|
InsertHeadList(&ProcessData->Console->ProcessList, &ProcessData->ConsoleLink);
|
||||||
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))
|
|
||||||
{
|
|
||||||
DPRINT1("Console init failed\n");
|
|
||||||
HeapFree(ConSrvHeap, 0, Console);
|
|
||||||
RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
|
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Reuse our current console */
|
|
||||||
Console = AllocConsoleRequest->Console;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Set the Process Console */
|
|
||||||
ProcessData->Console = Console;
|
|
||||||
|
|
||||||
/* 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]);
|
||||||
Status = Win32CsrInsertObject(ProcessData,
|
}
|
||||||
&AllocConsoleRequest->InputHandle,
|
ProcessData->HandleTableSize = 0;
|
||||||
&Console->Header,
|
RtlFreeHeap(ConSrvHeap, 0, ProcessData->HandleTable);
|
||||||
GENERIC_READ | GENERIC_WRITE,
|
ProcessData->HandleTable = NULL;
|
||||||
TRUE,
|
#endif
|
||||||
FILE_SHARE_READ | FILE_SHARE_WRITE);
|
|
||||||
if (! NT_SUCCESS(Status))
|
|
||||||
{
|
|
||||||
DPRINT1("Failed to insert object\n");
|
|
||||||
ConioDeleteConsole((Object_t *) Console);
|
|
||||||
ProcessData->Console = NULL;
|
|
||||||
RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
|
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
|
|
||||||
Status = Win32CsrInsertObject(ProcessData,
|
/*
|
||||||
&AllocConsoleRequest->OutputHandle,
|
* Create a new handle table - Insert the IO handles
|
||||||
&Console->ActiveBuffer->Header,
|
*/
|
||||||
GENERIC_READ | GENERIC_WRITE,
|
|
||||||
TRUE,
|
/* Insert the Input handle */
|
||||||
FILE_SHARE_READ | FILE_SHARE_WRITE);
|
Status = Win32CsrInsertObject(ProcessData,
|
||||||
if (!NT_SUCCESS(Status))
|
&AllocConsoleRequest->InputHandle,
|
||||||
{
|
&ProcessData->Console->Header,
|
||||||
DPRINT1("Failed to insert object\n");
|
GENERIC_READ | GENERIC_WRITE,
|
||||||
ConioDeleteConsole((Object_t *) Console);
|
TRUE,
|
||||||
Win32CsrReleaseObject(ProcessData,
|
FILE_SHARE_READ | FILE_SHARE_WRITE);
|
||||||
AllocConsoleRequest->InputHandle);
|
if (!NT_SUCCESS(Status))
|
||||||
ProcessData->Console = NULL;
|
{
|
||||||
RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
|
DPRINT1("Failed to insert the input handle\n");
|
||||||
return Status;
|
ConioDeleteConsole(ProcessData->Console);
|
||||||
}
|
ProcessData->Console = NULL;
|
||||||
|
RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Insert the Output handle */
|
||||||
|
Status = Win32CsrInsertObject(ProcessData,
|
||||||
|
&AllocConsoleRequest->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,
|
||||||
|
AllocConsoleRequest->InputHandle);
|
||||||
|
ProcessData->Console = NULL;
|
||||||
|
RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
|
||||||
|
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)
|
||||||
{
|
{
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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,17 +51,26 @@ 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)
|
||||||
{
|
{
|
||||||
PCSRSS_SCREEN_BUFFER Buffer = (PCSRSS_SCREEN_BUFFER)Object;
|
if (Object->Type == CONIO_SCREEN_BUFFER_MAGIC)
|
||||||
/* ...unless it's the only buffer left. Windows allows deletion
|
{
|
||||||
* even of the last buffer, but having to deal with a lack of
|
PCSRSS_SCREEN_BUFFER Buffer = (PCSRSS_SCREEN_BUFFER)Object;
|
||||||
* any active buffer might be error-prone. */
|
/* ...unless it's the only buffer left. Windows allows deletion
|
||||||
if (Buffer->ListEntry.Flink != Buffer->ListEntry.Blink)
|
* even of the last buffer, but having to deal with a lack of
|
||||||
ConioDeleteScreenBuffer(Buffer);
|
* any active buffer might be error-prone. */
|
||||||
|
if (Buffer->ListEntry.Flink != Buffer->ListEntry.Blink)
|
||||||
|
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,51 +258,256 @@ 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.
|
||||||
|
*/
|
||||||
|
if ( SourceProcessData->Console != NULL && /* SourceProcessData->ConsoleApp */
|
||||||
|
TargetProcessData->ConsoleApp )
|
||||||
{
|
{
|
||||||
// NewProcess == TargetProcess.
|
/*
|
||||||
NewProcess->ParentConsole = Process->Console;
|
if (TargetProcessData->HandleTableSize)
|
||||||
NewProcess->bInheritHandles = CreateProcessRequest->bInheritHandles;
|
{
|
||||||
}
|
return STATUS_INVALID_PARAMETER;
|
||||||
*/
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
/* Only inherit if the if the flag was set */
|
DPRINT1("ConsoleNewProcess - Copy the handle table (1)\n");
|
||||||
if (!TargetProcessData->bInheritHandles) return STATUS_SUCCESS;
|
/* Temporary "inherit" the console from the parent */
|
||||||
|
TargetProcessData->ParentConsole = SourceProcessData->Console;
|
||||||
|
RtlEnterCriticalSection(&SourceProcessData->HandleTableLock);
|
||||||
|
DPRINT1("ConsoleNewProcess - Copy the handle table (2)\n");
|
||||||
|
|
||||||
if (TargetProcessData->HandleTableSize)
|
/* Allocate a new handle table for the child process */
|
||||||
{
|
TargetProcessData->HandleTable = RtlAllocateHeap(ConSrvHeap,
|
||||||
return STATUS_INVALID_PARAMETER;
|
HEAP_ZERO_MEMORY,
|
||||||
}
|
SourceProcessData->HandleTableSize
|
||||||
|
* sizeof(CSRSS_HANDLE));
|
||||||
|
if (TargetProcessData->HandleTable == NULL)
|
||||||
|
{
|
||||||
|
RtlLeaveCriticalSection(&SourceProcessData->HandleTableLock);
|
||||||
|
return STATUS_UNSUCCESSFUL;
|
||||||
|
}
|
||||||
|
|
||||||
RtlEnterCriticalSection(&SourceProcessData->HandleTableLock);
|
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++)
|
||||||
|
{
|
||||||
|
if (SourceProcessData->HandleTable[i].Object != NULL &&
|
||||||
|
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];
|
||||||
|
Win32CsrCreateHandleEntry(&TargetProcessData->HandleTable[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
TargetProcessData->HandleTable = RtlAllocateHeap(ConSrvHeap,
|
|
||||||
HEAP_ZERO_MEMORY,
|
|
||||||
SourceProcessData->HandleTableSize
|
|
||||||
* sizeof(CSRSS_HANDLE));
|
|
||||||
if (TargetProcessData->HandleTable == NULL)
|
|
||||||
{
|
|
||||||
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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;
|
return STATUS_UNSUCCESSFUL;
|
||||||
}
|
}
|
||||||
|
|
||||||
TargetProcessData->HandleTableSize = SourceProcessData->HandleTableSize;
|
/* If we don't need a console, then get out of here */
|
||||||
|
if (!ConnectInfo->ConsoleNeeded || !ProcessData->ConsoleApp) // In fact, it is for GUI apps.
|
||||||
for (i = 0; i < SourceProcessData->HandleTableSize; i++)
|
|
||||||
{
|
{
|
||||||
if (SourceProcessData->HandleTable[i].Object != NULL &&
|
DPRINT("ConsoleConnect - No console needed\n");
|
||||||
SourceProcessData->HandleTable[i].Inheritable)
|
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))
|
||||||
{
|
{
|
||||||
TargetProcessData->HandleTable[i] = SourceProcessData->HandleTable[i];
|
DPRINT1("Console initialization failed\n");
|
||||||
Win32CsrCreateHandleEntry(&TargetProcessData->HandleTable[i]);
|
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
RtlLeaveCriticalSection(&SourceProcessData->HandleTableLock);
|
/* 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;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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 */
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue