reactos/win32ss/user/consrv/handle.c
Hermès Bélusca-Maïto 17c9d97fe7 [CONSRV]
- Fix console initialization / uninitialization and resources release when initialization fails.
- Remove unneeded DPRINTs.

svn path=/branches/ros-csrss/; revision=58462
2013-03-10 15:37:22 +00:00

846 lines
28 KiB
C

/*
* LICENSE: GPL - See COPYING in the top level directory
* PROJECT: ReactOS Console Server DLL
* FILE: win32ss/user/consrv/handle.c
* PURPOSE: Console I/O Handles functions
* PROGRAMMERS:
*/
/* INCLUDES ******************************************************************/
#include "consrv.h"
#include "conio.h"
//#define NDEBUG
#include <debug.h>
/* PRIVATE FUNCTIONS *********************************************************/
static INT
AdjustHandleCounts(PCONSOLE_IO_HANDLE Entry, INT Change)
{
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_WRITE) Object->AccessWrite += Change;
if (!(Entry->ShareMode & FILE_SHARE_READ)) Object->ExclusiveRead += Change;
if (!(Entry->ShareMode & FILE_SHARE_WRITE)) Object->ExclusiveWrite += Change;
Object->HandleCount += Change;
return Object->HandleCount;
}
static VOID
ConSrvCreateHandleEntry(PCONSOLE_IO_HANDLE Entry)
{
/// LOCK /// Object_t *Object = Entry->Object;
/// LOCK /// EnterCriticalSection(&Object->Console->Lock);
AdjustHandleCounts(Entry, +1);
/// LOCK /// LeaveCriticalSection(&Object->Console->Lock);
}
static VOID
ConSrvCloseHandleEntry(PCONSOLE_IO_HANDLE Entry)
{
Object_t *Object = Entry->Object;
if (Object != NULL)
{
/// LOCK /// PCONSOLE Console = Object->Console;
/// LOCK /// EnterCriticalSection(&Console->Lock);
/*
* If this is a input handle, notify and dereference
* all the waits related to this handle.
*/
if (Object->Type == CONIO_INPUT_BUFFER_MAGIC)
{
PCONSOLE_INPUT_BUFFER InputBuffer = (PCONSOLE_INPUT_BUFFER)Object;
/*
* Wake up all the writing waiters related to this handle for this
* input buffer, if any, then dereference them and purge them all
* from the list.
* To select them amongst all the waiters for this input buffer,
* pass the handle pointer to the waiters, then they will check
* whether or not they are related to this handle and if so, they
* return.
*/
CsrNotifyWait(&InputBuffer->ReadWaitQueue,
WaitAll,
NULL,
(PVOID)Entry);
if (!IsListEmpty(&InputBuffer->ReadWaitQueue))
{
CsrDereferenceWait(&InputBuffer->ReadWaitQueue);
}
}
/* If the last handle to a screen buffer is closed, delete it... */
if (AdjustHandleCounts(Entry, -1) == 0)
{
if (Object->Type == CONIO_SCREEN_BUFFER_MAGIC)
{
PCONSOLE_SCREEN_BUFFER Buffer = (PCONSOLE_SCREEN_BUFFER)Object;
/* ...unless it's the only buffer left. Windows allows deletion
* even of the last buffer, but having to deal with a lack of
* any active buffer might be error-prone. */
if (Buffer->ListEntry.Flink != Buffer->ListEntry.Blink)
ConioDeleteScreenBuffer(Buffer);
}
else if (Object->Type == CONIO_INPUT_BUFFER_MAGIC)
{
DPRINT1("Closing the input buffer\n");
}
}
/// LOCK /// LeaveCriticalSection(&Console->Lock);
Entry->Object = NULL;
}
}
/* FUNCTIONS *****************************************************************/
/* static */ NTSTATUS
FASTCALL
ConSrvInitHandlesTable(IN OUT PCONSOLE_PROCESS_DATA ProcessData,
OUT PHANDLE pInputHandle,
OUT PHANDLE pOutputHandle,
OUT PHANDLE pErrorHandle)
{
NTSTATUS Status;
HANDLE InputHandle = INVALID_HANDLE_VALUE,
OutputHandle = INVALID_HANDLE_VALUE,
ErrorHandle = INVALID_HANDLE_VALUE;
/*
* Initialize the handles table. Use temporary variables to store
* the handles values in such a way that, if we fail, we don't
* return to the caller invalid handle values.
*
* Insert the IO handles.
*/
RtlEnterCriticalSection(&ProcessData->HandleTableLock);
/* Insert the Input handle */
Status = ConSrvInsertObject(ProcessData,
&InputHandle,
&ProcessData->Console->InputBuffer.Header,
GENERIC_READ | GENERIC_WRITE,
TRUE,
FILE_SHARE_READ | FILE_SHARE_WRITE);
if (!NT_SUCCESS(Status))
{
DPRINT1("Failed to insert the input handle\n");
RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
ConSrvFreeHandlesTable(ProcessData);
return Status;
}
/* Insert the Output handle */
Status = ConSrvInsertObject(ProcessData,
&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");
RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
ConSrvFreeHandlesTable(ProcessData);
return Status;
}
/* Insert the Error handle */
Status = ConSrvInsertObject(ProcessData,
&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");
RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
ConSrvFreeHandlesTable(ProcessData);
return Status;
}
/* Return the newly created handles */
*pInputHandle = InputHandle;
*pOutputHandle = OutputHandle;
*pErrorHandle = ErrorHandle;
RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
return STATUS_SUCCESS;
}
NTSTATUS
FASTCALL
ConSrvInheritHandlesTable(IN PCONSOLE_PROCESS_DATA SourceProcessData,
IN PCONSOLE_PROCESS_DATA TargetProcessData)
{
NTSTATUS Status = STATUS_SUCCESS;
ULONG i;
RtlEnterCriticalSection(&SourceProcessData->HandleTableLock);
/* Inherit a handles table only if there is no already */
if (TargetProcessData->HandleTable != NULL /* || TargetProcessData->HandleTableSize != 0 */)
{
Status = STATUS_UNSUCCESSFUL; /* STATUS_INVALID_PARAMETER */
goto Quit;
}
/* Allocate a new handle table for the child process */
TargetProcessData->HandleTable = RtlAllocateHeap(ConSrvHeap,
HEAP_ZERO_MEMORY,
SourceProcessData->HandleTableSize
* sizeof(CONSOLE_IO_HANDLE));
if (TargetProcessData->HandleTable == NULL)
{
Status = STATUS_NO_MEMORY;
goto Quit;
}
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 ConSrvCreateHandleEntry).
*/
TargetProcessData->HandleTable[i] = SourceProcessData->HandleTable[i];
ConSrvCreateHandleEntry(&TargetProcessData->HandleTable[i]);
}
}
Quit:
RtlLeaveCriticalSection(&SourceProcessData->HandleTableLock);
return Status;
}
VOID
FASTCALL
ConSrvFreeHandlesTable(PCONSOLE_PROCESS_DATA ProcessData)
{
DPRINT1("ConSrvFreeHandlesTable\n");
RtlEnterCriticalSection(&ProcessData->HandleTableLock);
if (ProcessData->HandleTable != NULL)
{
ULONG i;
/* Close all console handles and free the handle table memory */
for (i = 0; i < ProcessData->HandleTableSize; i++)
{
ConSrvCloseHandleEntry(&ProcessData->HandleTable[i]);
}
RtlFreeHeap(ConSrvHeap, 0, ProcessData->HandleTable);
ProcessData->HandleTable = NULL;
}
ProcessData->HandleTableSize = 0;
RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
}
NTSTATUS
FASTCALL
ConSrvInsertObject(PCONSOLE_PROCESS_DATA ProcessData,
PHANDLE Handle,
Object_t *Object,
DWORD Access,
BOOL Inheritable,
DWORD ShareMode)
{
#define IO_HANDLES_INCREMENT 2*3
ULONG i;
PCONSOLE_IO_HANDLE Block;
RtlEnterCriticalSection(&ProcessData->HandleTableLock);
for (i = 0; i < ProcessData->HandleTableSize; i++)
{
if (ProcessData->HandleTable[i].Object == NULL)
{
break;
}
}
if (i >= ProcessData->HandleTableSize)
{
Block = RtlAllocateHeap(ConSrvHeap,
HEAP_ZERO_MEMORY,
(ProcessData->HandleTableSize +
IO_HANDLES_INCREMENT) * sizeof(CONSOLE_IO_HANDLE));
if (Block == NULL)
{
RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
return STATUS_UNSUCCESSFUL;
}
RtlCopyMemory(Block,
ProcessData->HandleTable,
ProcessData->HandleTableSize * sizeof(CONSOLE_IO_HANDLE));
RtlFreeHeap(ConSrvHeap, 0, ProcessData->HandleTable);
ProcessData->HandleTable = Block;
ProcessData->HandleTableSize += IO_HANDLES_INCREMENT;
}
ProcessData->HandleTable[i].Object = Object;
ProcessData->HandleTable[i].Access = Access;
ProcessData->HandleTable[i].Inheritable = Inheritable;
ProcessData->HandleTable[i].ShareMode = ShareMode;
ConSrvCreateHandleEntry(&ProcessData->HandleTable[i]);
*Handle = ULongToHandle((i << 2) | 0x3);
RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
return STATUS_SUCCESS;
}
NTSTATUS
FASTCALL
ConSrvRemoveObject(PCONSOLE_PROCESS_DATA ProcessData,
HANDLE Handle)
{
ULONG_PTR h = (ULONG_PTR)Handle >> 2;
Object_t *Object;
RtlEnterCriticalSection(&ProcessData->HandleTableLock);
if (h >= ProcessData->HandleTableSize ||
(Object = ProcessData->HandleTable[h].Object) == NULL)
{
RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
return STATUS_INVALID_HANDLE;
}
DPRINT1("ConSrvRemoveObject - Process 0x%p, Release 0x%p\n", ProcessData->Process, &ProcessData->HandleTable[h]);
ConSrvCloseHandleEntry(&ProcessData->HandleTable[h]);
RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
return STATUS_SUCCESS;
}
NTSTATUS
FASTCALL
ConSrvGetObject(PCONSOLE_PROCESS_DATA ProcessData,
HANDLE Handle,
Object_t** Object,
PCONSOLE_IO_HANDLE* Entry OPTIONAL,
DWORD Access,
BOOL LockConsole,
ULONG Type)
{
ULONG_PTR h = (ULONG_PTR)Handle >> 2;
PCONSOLE_IO_HANDLE HandleEntry = NULL;
Object_t* ObjectEntry = NULL;
ASSERT(Object);
if (Entry) *Entry = NULL;
// DPRINT("ConSrvGetObject, Object: %x, %x, %x\n",
// Object, Handle, ProcessData ? ProcessData->HandleTableSize : 0);
RtlEnterCriticalSection(&ProcessData->HandleTableLock);
if ( IsConsoleHandle(Handle) &&
h < ProcessData->HandleTableSize )
{
HandleEntry = &ProcessData->HandleTable[h];
ObjectEntry = HandleEntry->Object;
}
if ( HandleEntry == NULL ||
ObjectEntry == NULL ||
(HandleEntry->Access & Access) == 0 ||
(Type != 0 && ObjectEntry->Type != Type) )
{
DPRINT1("ConSrvGetObject returning invalid handle (%x) of type %lu with access %lu\n", Handle, Type, Access);
RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
return STATUS_INVALID_HANDLE;
}
_InterlockedIncrement(&ObjectEntry->Console->ReferenceCount);
RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
if (LockConsole) EnterCriticalSection(&ObjectEntry->Console->Lock);
/* Return the objects to the caller */
*Object = ObjectEntry;
if (Entry) *Entry = HandleEntry;
return STATUS_SUCCESS;
}
VOID
FASTCALL
ConSrvReleaseObject(Object_t *Object,
BOOL IsConsoleLocked)
{
ConSrvReleaseConsole(Object->Console, IsConsoleLocked);
}
NTSTATUS
FASTCALL
ConSrvAllocateConsole(PCONSOLE_PROCESS_DATA ProcessData,
LPCWSTR AppPath,
PHANDLE pInputHandle,
PHANDLE pOutputHandle,
PHANDLE pErrorHandle,
PCONSOLE_START_INFO ConsoleStartInfo)
{
NTSTATUS Status = STATUS_SUCCESS;
/* Initialize a new Console owned by this process */
Status = ConSrvInitConsole(&ProcessData->Console, AppPath, ConsoleStartInfo, ProcessData->Process);
if (!NT_SUCCESS(Status))
{
DPRINT1("Console initialization failed\n");
return Status;
}
/* Initialize the handles table */
Status = ConSrvInitHandlesTable(ProcessData,
pInputHandle,
pOutputHandle,
pErrorHandle);
if (!NT_SUCCESS(Status))
{
DPRINT1("Failed to initialize the handles table\n");
ConSrvDeleteConsole(ProcessData->Console);
ProcessData->Console = NULL;
return Status;
}
/* Duplicate the Input Event */
Status = NtDuplicateObject(NtCurrentProcess(),
ProcessData->Console->InputBuffer.ActiveEvent,
ProcessData->Process->ProcessHandle,
&ProcessData->ConsoleEvent,
EVENT_ALL_ACCESS, 0, 0);
if (!NT_SUCCESS(Status))
{
DPRINT1("NtDuplicateObject() failed: %lu\n", Status);
ConSrvFreeHandlesTable(ProcessData);
ConSrvDeleteConsole(ProcessData->Console);
ProcessData->Console = NULL;
return Status;
}
/* Insert the process into the processes list of the console */
InsertHeadList(&ProcessData->Console->ProcessList, &ProcessData->ConsoleLink);
/* Add a reference count because the process is tied to the console */
_InterlockedIncrement(&ProcessData->Console->ReferenceCount);
return STATUS_SUCCESS;
}
NTSTATUS
FASTCALL
ConSrvInheritConsole(PCONSOLE_PROCESS_DATA ProcessData,
PCONSOLE Console,
BOOL CreateNewHandlesTable,
PHANDLE pInputHandle,
PHANDLE pOutputHandle,
PHANDLE pErrorHandle)
{
NTSTATUS Status = STATUS_SUCCESS;
/* Inherit the console */
ProcessData->Console = Console;
if (CreateNewHandlesTable)
{
/* Initialize the handles table */
Status = ConSrvInitHandlesTable(ProcessData,
pInputHandle,
pOutputHandle,
pErrorHandle);
if (!NT_SUCCESS(Status))
{
DPRINT1("Failed to initialize the handles table\n");
ProcessData->Console = NULL;
return Status;
}
}
/* Duplicate the Input Event */
Status = NtDuplicateObject(NtCurrentProcess(),
ProcessData->Console->InputBuffer.ActiveEvent,
ProcessData->Process->ProcessHandle,
&ProcessData->ConsoleEvent,
EVENT_ALL_ACCESS, 0, 0);
if (!NT_SUCCESS(Status))
{
DPRINT1("NtDuplicateObject() failed: %lu\n", Status);
ConSrvFreeHandlesTable(ProcessData); // NOTE: Always free the handles table.
ProcessData->Console = NULL;
return Status;
}
/* Insert the process into the processes list of the console */
InsertHeadList(&ProcessData->Console->ProcessList, &ProcessData->ConsoleLink);
/* Add a reference count because the process is tied to the console */
_InterlockedIncrement(&ProcessData->Console->ReferenceCount);
return STATUS_SUCCESS;
}
VOID
FASTCALL
ConSrvRemoveConsole(PCONSOLE_PROCESS_DATA ProcessData)
{
PCONSOLE Console;
DPRINT1("ConSrvRemoveConsole\n");
/* Close all console handles and free the handle table memory */
ConSrvFreeHandlesTable(ProcessData);
/* Detach process from console */
Console = ProcessData->Console;
if (Console != NULL)
{
DPRINT1("ConSrvRemoveConsole - Console->ReferenceCount = %lu - We are going to decrement it !\n", Console->ReferenceCount);
ProcessData->Console = NULL;
EnterCriticalSection(&Console->Lock);
DPRINT1("ConSrvRemoveConsole - Locking OK\n");
/* Remove ourselves from the console's list of processes */
RemoveEntryList(&ProcessData->ConsoleLink);
/* Update the console leader process */
// SetConsoleWndConsoleLeaderCID(Console);
/* Release the console */
ConSrvReleaseConsole(Console, TRUE);
//CloseHandle(ProcessData->ConsoleEvent);
//ProcessData->ConsoleEvent = NULL;
}
}
NTSTATUS
FASTCALL
ConSrvGetConsole(PCONSOLE_PROCESS_DATA ProcessData,
PCONSOLE* Console,
BOOL LockConsole)
{
PCONSOLE ProcessConsole;
RtlEnterCriticalSection(&ProcessData->HandleTableLock);
ProcessConsole = ProcessData->Console;
if (!ProcessConsole)
{
*Console = NULL;
RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
return STATUS_INVALID_HANDLE;
}
InterlockedIncrement(&ProcessConsole->ReferenceCount);
RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
if (LockConsole) EnterCriticalSection(&ProcessConsole->Lock);
*Console = ProcessConsole;
return STATUS_SUCCESS;
}
VOID FASTCALL
ConSrvReleaseConsole(PCONSOLE Console,
BOOL IsConsoleLocked)
{
if (IsConsoleLocked) LeaveCriticalSection(&Console->Lock);
/* Decrement reference count */
if (_InterlockedDecrement(&Console->ReferenceCount) == 0)
ConSrvDeleteConsole(Console);
}
NTSTATUS
NTAPI
ConSrvNewProcess(PCSR_PROCESS SourceProcess,
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 ConSrvConnect 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
* ConSrvConnect we don't have any reference to the parent process anymore.
**************************************************************************/
PCONSOLE_PROCESS_DATA SourceProcessData, TargetProcessData;
/* An empty target process is invalid */
if (!TargetProcess) return STATUS_INVALID_PARAMETER;
TargetProcessData = ConsoleGetPerProcessData(TargetProcess);
/**** HACK !!!! ****/ RtlZeroMemory(TargetProcessData, sizeof(*TargetProcessData));
/* Initialize the new (target) process */
TargetProcessData->Process = TargetProcess;
TargetProcessData->ConsoleEvent = NULL;
TargetProcessData->Console = TargetProcessData->ParentConsole = NULL;
TargetProcessData->ConsoleApp = ((TargetProcess->Flags & CsrProcessIsConsoleApp) ? TRUE : FALSE);
// Testing
TargetProcessData->HandleTableSize = 0;
TargetProcessData->HandleTable = NULL;
RtlInitializeCriticalSection(&TargetProcessData->HandleTableLock);
/* Do nothing if the source process is NULL */
if (!SourceProcess) return STATUS_SUCCESS;
SourceProcessData = ConsoleGetPerProcessData(SourceProcess);
/*
* 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 )
{
NTSTATUS Status;
Status = ConSrvInheritHandlesTable(SourceProcessData, TargetProcessData);
if (!NT_SUCCESS(Status)) return Status;
/* Temporary save the parent's console */
TargetProcessData->ParentConsole = SourceProcessData->Console;
}
return STATUS_SUCCESS;
}
NTSTATUS
NTAPI
ConSrvConnect(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);
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("ConSrvConnect - No console needed\n");
return STATUS_SUCCESS;
}
/* If we don't have a console, then create a new one... */
if (!ConnectInfo->Console ||
ConnectInfo->Console != ProcessData->ParentConsole)
{
DPRINT1("ConSrvConnect - Allocate a new console\n");
/*
* We are about to create a new console. However when ConSrvNewProcess
* 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 the console we can have and our handles table,
* and recreate a new one later on.
*/
ConSrvRemoveConsole(ProcessData);
/* Initialize a new Console owned by the Console Leader Process */
Status = ConSrvAllocateConsole(ProcessData,
ConnectInfo->AppPath,
&ConnectInfo->InputHandle,
&ConnectInfo->OutputHandle,
&ConnectInfo->ErrorHandle,
&ConnectInfo->ConsoleStartInfo);
if (!NT_SUCCESS(Status))
{
DPRINT1("Console allocation failed\n");
return Status;
}
}
else /* We inherit it from the parent */
{
DPRINT1("ConSrvConnect - Reuse current (parent's) console\n");
/* Reuse our current console */
Status = ConSrvInheritConsole(ProcessData,
ConnectInfo->Console,
FALSE,
NULL, // &ConnectInfo->InputHandle,
NULL, // &ConnectInfo->OutputHandle,
NULL); // &ConnectInfo->ErrorHandle);
if (!NT_SUCCESS(Status))
{
DPRINT1("Console inheritance failed\n");
return Status;
}
}
/* Return it to the caller */
ConnectInfo->Console = ProcessData->Console;
/* Input Wait Handle */
ConnectInfo->InputWaitHandle = ProcessData->ConsoleEvent;
/* Set the Property Dialog Handler */
ProcessData->PropDispatcher = ConnectInfo->PropDispatcher;
/* Set the Ctrl Dispatcher */
ProcessData->CtrlDispatcher = ConnectInfo->CtrlDispatcher;
return STATUS_SUCCESS;
}
VOID
NTAPI
ConSrvDisconnect(PCSR_PROCESS Process)
{
PCONSOLE_PROCESS_DATA ProcessData = ConsoleGetPerProcessData(Process);
/**************************************************************************
* This function is called whenever a new process (GUI or CUI) is destroyed.
**************************************************************************/
DPRINT1("ConSrvDisconnect\n");
if ( ProcessData->Console != NULL ||
ProcessData->HandleTable != NULL )
{
DPRINT1("ConSrvDisconnect - calling ConSrvRemoveConsole\n");
ConSrvRemoveConsole(ProcessData);
}
RtlDeleteCriticalSection(&ProcessData->HandleTableLock);
}
CSR_API(SrvCloseHandle)
{
PCONSOLE_CLOSEHANDLE CloseHandleRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.CloseHandleRequest;
return ConSrvRemoveObject(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
CloseHandleRequest->ConsoleHandle);
}
CSR_API(SrvVerifyConsoleIoHandle)
{
NTSTATUS Status = STATUS_SUCCESS;
PCONSOLE_VERIFYHANDLE VerifyHandleRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.VerifyHandleRequest;
PCONSOLE_PROCESS_DATA ProcessData = ConsoleGetPerProcessData(CsrGetClientThread()->Process);
HANDLE ConsoleHandle = VerifyHandleRequest->ConsoleHandle;
ULONG_PTR Index = (ULONG_PTR)ConsoleHandle >> 2;
RtlEnterCriticalSection(&ProcessData->HandleTableLock);
if (!IsConsoleHandle(ConsoleHandle) ||
Index >= ProcessData->HandleTableSize ||
ProcessData->HandleTable[Index].Object == NULL)
{
DPRINT("SrvVerifyConsoleIoHandle failed\n");
Status = STATUS_INVALID_HANDLE;
}
RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
return Status;
}
CSR_API(SrvDuplicateHandle)
{
PCONSOLE_IO_HANDLE Entry;
DWORD DesiredAccess;
PCONSOLE_DUPLICATEHANDLE DuplicateHandleRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.DuplicateHandleRequest;
PCONSOLE_PROCESS_DATA ProcessData = ConsoleGetPerProcessData(CsrGetClientThread()->Process);
HANDLE ConsoleHandle = DuplicateHandleRequest->ConsoleHandle;
ULONG_PTR Index = (ULONG_PTR)ConsoleHandle >> 2;
RtlEnterCriticalSection(&ProcessData->HandleTableLock);
if ( /** !IsConsoleHandle(ConsoleHandle) || **/
Index >= ProcessData->HandleTableSize ||
(Entry = &ProcessData->HandleTable[Index])->Object == NULL)
{
DPRINT1("Couldn't duplicate invalid handle %p\n", ConsoleHandle);
RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
return STATUS_INVALID_HANDLE;
}
if (DuplicateHandleRequest->Options & DUPLICATE_SAME_ACCESS)
{
DesiredAccess = Entry->Access;
}
else
{
DesiredAccess = DuplicateHandleRequest->Access;
/* Make sure the source handle has all the desired flags */
if ((Entry->Access & DesiredAccess) == 0)
{
DPRINT1("Handle %p only has access %X; requested %X\n",
ConsoleHandle, Entry->Access, DesiredAccess);
RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
return STATUS_INVALID_PARAMETER;
}
}
ApiMessage->Status = ConSrvInsertObject(ProcessData,
&DuplicateHandleRequest->ConsoleHandle, // Use the new handle value!
Entry->Object,
DesiredAccess,
DuplicateHandleRequest->Inheritable,
Entry->ShareMode);
if (NT_SUCCESS(ApiMessage->Status) &&
DuplicateHandleRequest->Options & DUPLICATE_CLOSE_SOURCE)
{
ConSrvCloseHandleEntry(Entry);
}
RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
return ApiMessage->Status;
}
/* EOF */