* LICENSE: GPL - See COPYING in the top level directory
* PROJECT: ReactOS Console Server DLL
* FILE: win32ss/user/consrv/handle.c
- * PURPOSE: Handle functions
+ * PURPOSE: Console IO Handle functions
* PROGRAMMERS:
*/
#include "consrv.h"
#include "conio.h"
-#define NDEBUG
+//#define NDEBUG
#include <debug.h>
-typedef struct _CSRSS_HANDLE
-{
- Object_t *Object;
- DWORD Access;
- BOOL Inheritable;
- DWORD ShareMode;
-} CSRSS_HANDLE, *PCSRSS_HANDLE;
-
-
-/* FUNCTIONS *****************************************************************/
-
-static
-BOOL
-CsrIsConsoleHandle(HANDLE Handle)
-{
- return ((ULONG_PTR)Handle & 0x10000003) == 0x3;
-}
+/* PRIVATE FUNCTIONS *********************************************************/
static INT
-AdjustHandleCounts(PCSRSS_HANDLE Entry, INT Change)
+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
-Win32CsrCreateHandleEntry(PCSRSS_HANDLE Entry)
+Win32CsrCreateHandleEntry(PCONSOLE_IO_HANDLE Entry)
{
Object_t *Object = Entry->Object;
EnterCriticalSection(&Object->Console->Lock);
}
static VOID
-Win32CsrCloseHandleEntry(PCSRSS_HANDLE Entry)
+Win32CsrCloseHandleEntry(PCONSOLE_IO_HANDLE Entry)
{
Object_t *Object = Entry->Object;
if (Object != NULL)
{
- PCSRSS_CONSOLE Console = Object->Console;
+ PCONSOLE Console = Object->Console;
EnterCriticalSection(&Console->Lock);
- /* If the last handle to a screen buffer is closed, delete it */
- if (AdjustHandleCounts(Entry, -1) == 0
- && Object->Type == CONIO_SCREEN_BUFFER_MAGIC)
+
+ /* If the last handle to a screen buffer is closed, delete it... */
+ if (AdjustHandleCounts(Entry, -1) == 0)
{
- PCSRSS_SCREEN_BUFFER Buffer = (PCSRSS_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);
+ 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_CONSOLE_MAGIC)
+ {
+ /* TODO: FIXME: Destroy here the console ?? */
+ // ConioDeleteConsole(Console);
+ }
}
+
LeaveCriticalSection(&Console->Lock);
Entry->Object = NULL;
}
}
+
+/* FUNCTIONS *****************************************************************/
+
+NTSTATUS
+FASTCALL
+Win32CsrInsertObject(PCONSOLE_PROCESS_DATA ProcessData,
+ PHANDLE Handle,
+ Object_t *Object,
+ DWORD Access,
+ BOOL Inheritable,
+ DWORD ShareMode)
+{
+ 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 + 64) * 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 += 64;
+ }
+ ProcessData->HandleTable[i].Object = Object;
+ ProcessData->HandleTable[i].Access = Access;
+ ProcessData->HandleTable[i].Inheritable = Inheritable;
+ ProcessData->HandleTable[i].ShareMode = ShareMode;
+ Win32CsrCreateHandleEntry(&ProcessData->HandleTable[i]);
+ *Handle = UlongToHandle((i << 2) | 0x3);
+ RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
+ return STATUS_SUCCESS;
+}
+
NTSTATUS
FASTCALL
-Win32CsrReleaseObject(PCSR_PROCESS ProcessData,
+Win32CsrReleaseObject(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)
+
+ if (h >= ProcessData->HandleTableSize ||
+ (Object = ProcessData->HandleTable[h].Object) == NULL)
{
RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
return STATUS_INVALID_HANDLE;
}
+
+ DPRINT1("Win32CsrReleaseObject - Process 0x%p, Release 0x%p\n", ProcessData->Process, &ProcessData->HandleTable[h]);
Win32CsrCloseHandleEntry(&ProcessData->HandleTable[h]);
+
RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
+
return STATUS_SUCCESS;
}
NTSTATUS
FASTCALL
-Win32CsrLockObject(PCSR_PROCESS ProcessData,
+Win32CsrLockObject(PCONSOLE_PROCESS_DATA ProcessData,
HANDLE Handle,
Object_t **Object,
DWORD Access,
{
ULONG_PTR h = (ULONG_PTR)Handle >> 2;
- DPRINT("CsrGetObject, Object: %x, %x, %x\n",
+ DPRINT("Win32CsrLockObject, Object: %x, %x, %x\n",
Object, Handle, ProcessData ? ProcessData->HandleTableSize : 0);
RtlEnterCriticalSection(&ProcessData->HandleTableLock);
- if (!CsrIsConsoleHandle(Handle) || h >= ProcessData->HandleTableSize
- || (*Object = ProcessData->HandleTable[h].Object) == NULL
- || ~ProcessData->HandleTable[h].Access & Access
- || (Type != 0 && (*Object)->Type != Type))
+
+ if ( !IsConsoleHandle(Handle) ||
+ h >= ProcessData->HandleTableSize ||
+ (*Object = ProcessData->HandleTable[h].Object) == NULL ||
+ ~ProcessData->HandleTable[h].Access & Access ||
+ (Type != 0 && (*Object)->Type != Type) )
{
DPRINT1("CsrGetObject returning invalid handle (%x)\n", Handle);
RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
return STATUS_INVALID_HANDLE;
}
+
_InterlockedIncrement(&(*Object)->Console->ReferenceCount);
RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
return STATUS_SUCCESS;
}
-VOID
-FASTCALL
-Win32CsrUnlockObject(Object_t *Object)
+VOID FASTCALL
+Win32CsrUnlockConsole(PCONSOLE Console)
{
- PCSRSS_CONSOLE Console = Object->Console;
LeaveCriticalSection(&Console->Lock);
- /* dec ref count */
+
+ /* Decrement reference count */
if (_InterlockedDecrement(&Console->ReferenceCount) == 0)
- ConioDeleteConsole(&Console->Header);
+ ConioDeleteConsole(Console);
}
VOID
-WINAPI
-Win32CsrReleaseConsole(PCSR_PROCESS ProcessData)
+FASTCALL
+Win32CsrUnlockObject(Object_t *Object)
{
- PCSRSS_CONSOLE Console;
- ULONG i;
+ Win32CsrUnlockConsole(Object->Console);
+}
- /* Close all console handles and detach process from console */
- RtlEnterCriticalSection(&ProcessData->HandleTableLock);
- for (i = 0; i < ProcessData->HandleTableSize; i++)
- Win32CsrCloseHandleEntry(&ProcessData->HandleTable[i]);
- ProcessData->HandleTableSize = 0;
- RtlFreeHeap(ConSrvHeap, 0, ProcessData->HandleTable);
- ProcessData->HandleTable = NULL;
-
- Console = ProcessData->Console;
- if (Console != NULL)
- {
- ProcessData->Console = NULL;
- EnterCriticalSection(&Console->Lock);
- RemoveEntryList(&ProcessData->ConsoleLink);
- LeaveCriticalSection(&Console->Lock);
- if (_InterlockedDecrement(&Console->ReferenceCount) == 0)
- ConioDeleteConsole(&Console->Header);
- //CloseHandle(ProcessData->ConsoleEvent);
- //ProcessData->ConsoleEvent = NULL;
- }
- RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
-}
+/** Remark: this function can be called by SrvAttachConsole (not yet implemented) **/
NTSTATUS
-FASTCALL
-Win32CsrInsertObject(PCSR_PROCESS ProcessData,
- PHANDLE Handle,
- Object_t *Object,
- DWORD Access,
- BOOL Inheritable,
- DWORD ShareMode)
+NTAPI
+ConsoleNewProcess(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 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;
ULONG i;
- PCSRSS_HANDLE Block;
- RtlEnterCriticalSection(&ProcessData->HandleTableLock);
+ DPRINT1("ConsoleNewProcess inside\n");
+ DPRINT1("SourceProcess = 0x%p ; TargetProcess = 0x%p\n", SourceProcess, TargetProcess);
- for (i = 0; i < ProcessData->HandleTableSize; i++)
+ /* An empty target process is invalid */
+ if (!TargetProcess)
+ return STATUS_INVALID_PARAMETER;
+
+ DPRINT1("ConsoleNewProcess - OK\n");
+
+ TargetProcessData = ConsoleGetPerProcessData(TargetProcess);
+ DPRINT1("TargetProcessData = 0x%p\n", TargetProcessData);
+
+ /**** HACK !!!! ****/ RtlZeroMemory(TargetProcessData, sizeof(*TargetProcessData));
+
+ /* Initialize the new (target) process */
+ 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);
+
+ /* Do nothing if the source process is NULL */
+ if (!SourceProcess)
+ return STATUS_SUCCESS;
+
+ SourceProcessData = ConsoleGetPerProcessData(SourceProcess);
+ DPRINT1("SourceProcessData = 0x%p\n", SourceProcessData);
+
+ /*
+ * 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 )
{
- if (ProcessData->HandleTable[i].Object == NULL)
+/*
+ if (TargetProcessData->HandleTableSize)
{
- break;
+ return STATUS_INVALID_PARAMETER;
}
- }
- if (i >= ProcessData->HandleTableSize)
- {
- Block = RtlAllocateHeap(ConSrvHeap,
- HEAP_ZERO_MEMORY,
- (ProcessData->HandleTableSize + 64) * sizeof(CSRSS_HANDLE));
- if (Block == NULL)
+*/
+
+ DPRINT1("ConsoleNewProcess - Copy the handle table (1)\n");
+ /* Temporary "inherit" the console from the parent */
+ TargetProcessData->ParentConsole = SourceProcessData->Console;
+ RtlEnterCriticalSection(&SourceProcessData->HandleTableLock);
+ DPRINT1("ConsoleNewProcess - Copy the handle table (2)\n");
+
+ /* 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)
{
- RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
- return(STATUS_UNSUCCESSFUL);
+ RtlLeaveCriticalSection(&SourceProcessData->HandleTableLock);
+ return STATUS_UNSUCCESSFUL;
}
- RtlCopyMemory(Block,
- ProcessData->HandleTable,
- ProcessData->HandleTableSize * sizeof(CSRSS_HANDLE));
- RtlFreeHeap(ConSrvHeap, 0, ProcessData->HandleTable);
- ProcessData->HandleTable = Block;
- ProcessData->HandleTableSize += 64;
+
+ 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]);
+ }
+ }
+
+ RtlLeaveCriticalSection(&SourceProcessData->HandleTableLock);
}
- ProcessData->HandleTable[i].Object = Object;
- ProcessData->HandleTable[i].Access = Access;
- ProcessData->HandleTable[i].Inheritable = Inheritable;
- ProcessData->HandleTable[i].ShareMode = ShareMode;
- Win32CsrCreateHandleEntry(&ProcessData->HandleTable[i]);
- *Handle = UlongToHandle((i << 2) | 0x3);
- RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
- return(STATUS_SUCCESS);
+ 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;
}
NTSTATUS
-WINAPI
-Win32CsrDuplicateHandleTable(PCSR_PROCESS SourceProcessData,
- PCSR_PROCESS TargetProcessData)
+NTAPI
+ConsoleConnect(IN PCSR_PROCESS CsrProcess,
+ IN OUT PVOID ConnectionInfo,
+ IN OUT PULONG ConnectionInfoLength)
{
- ULONG i;
-
- /* Only inherit if the flag was set */
- if (!TargetProcessData->bInheritHandles) return STATUS_SUCCESS;
+ /**************************************************************************
+ * 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;
+ // PCONSOLE Console = NULL;
- if (TargetProcessData->HandleTableSize)
+ DPRINT1("ConsoleConnect\n");
+
+ if ( ConnectionInfo == NULL ||
+ ConnectionInfoLength == NULL ||
+ *ConnectionInfoLength != sizeof(CONSOLE_CONNECTION_INFO) )
{
- return STATUS_INVALID_PARAMETER;
+ DPRINT1("CONSRV: Connection failed\n");
+ return STATUS_UNSUCCESSFUL;
}
- RtlEnterCriticalSection(&SourceProcessData->HandleTableLock);
+ /* 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;
+ }
- /* we are called from CreateProcessData, it isn't necessary to lock the target process data */
+ RtlEnterCriticalSection(&ProcessData->HandleTableLock);
- TargetProcessData->HandleTable = RtlAllocateHeap(ConSrvHeap,
- HEAP_ZERO_MEMORY,
- SourceProcessData->HandleTableSize
- * sizeof(CSRSS_HANDLE));
- if (TargetProcessData->HandleTable == NULL)
+ /* If we don't have a console, then create a new one... */
+ if (!ConnectInfo->Console ||
+ ConnectInfo->Console != ProcessData->ParentConsole)
{
- RtlLeaveCriticalSection(&SourceProcessData->HandleTableLock);
- return(STATUS_UNSUCCESSFUL);
+ DPRINT1("ConsoleConnect - Allocate a new console\n");
+
+ /* Initialize a new Console owned by the Console Leader Process */
+ NewConsole = TRUE;
+ Status = CsrInitConsole(&ProcessData->Console, ConnectInfo->ShowCmd, CsrProcess);
+ 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;
+ }
}
- TargetProcessData->HandleTableSize = SourceProcessData->HandleTableSize;
- for (i = 0; i < SourceProcessData->HandleTableSize; i++)
+
+ /* Duplicate the Event */
+ Status = NtDuplicateObject(NtCurrentProcess(),
+ ProcessData->Console->ActiveEvent,
+ ProcessData->Process->ProcessHandle,
+ &ProcessData->ConsoleEvent,
+ EVENT_ALL_ACCESS, 0, 0);
+ if (!NT_SUCCESS(Status))
{
- if (SourceProcessData->HandleTable[i].Object != NULL &&
- SourceProcessData->HandleTable[i].Inheritable)
+ DPRINT1("NtDuplicateObject() failed: %lu\n", Status);
+ ConioDeleteConsole(ProcessData->Console);
+ if (NewConsole /* || !ProcessData->bInheritHandles */)
{
- TargetProcessData->HandleTable[i] = SourceProcessData->HandleTable[i];
- Win32CsrCreateHandleEntry(&TargetProcessData->HandleTable[i]);
+ Win32CsrReleaseObject(ProcessData,
+ ConnectInfo->ErrorHandle);
+ Win32CsrReleaseObject(ProcessData,
+ ConnectInfo->OutputHandle);
+ Win32CsrReleaseObject(ProcessData,
+ ConnectInfo->InputHandle);
}
+ ProcessData->Console = NULL;
+ RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
+ return Status;
}
- RtlLeaveCriticalSection(&SourceProcessData->HandleTableLock);
- return(STATUS_SUCCESS);
+ /* 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;
}
-CSR_API(CsrGetHandle)
+VOID
+WINAPI
+Win32CsrReleaseConsole(PCSR_PROCESS Process)
{
- NTSTATUS Status = STATUS_SUCCESS;
- PCSRSS_GET_INPUT_HANDLE GetInputHandleRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GetInputHandleRequest;
- PCSR_PROCESS ProcessData = CsrGetClientThread()->Process;
+ PCONSOLE_PROCESS_DATA ProcessData = ConsoleGetPerProcessData(Process);
+ PCONSOLE Console;
+ ULONG i;
- GetInputHandleRequest->Handle = INVALID_HANDLE_VALUE;
+ DPRINT1("Win32CsrReleaseConsole\n");
RtlEnterCriticalSection(&ProcessData->HandleTableLock);
- if (ProcessData->Console)
- {
- DWORD DesiredAccess = GetInputHandleRequest->Access;
- DWORD ShareMode = GetInputHandleRequest->ShareMode;
- PCSRSS_CONSOLE Console = ProcessData->Console;
- Object_t *Object;
+ /* 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;
+ /* Detach process from console */
+ Console = ProcessData->Console;
+ if (Console != NULL)
+ {
+ DPRINT1("Win32CsrReleaseConsole - Console->ReferenceCount = %lu - We are going to decrement it !\n", Console->ReferenceCount);
+ ProcessData->Console = NULL;
EnterCriticalSection(&Console->Lock);
- if (ApiMessage->ApiNumber == ConsolepGetHandleInformation)
- Object = &Console->ActiveBuffer->Header;
- else
- Object = &Console->Header;
-
- if (((DesiredAccess & GENERIC_READ) && Object->ExclusiveRead != 0) ||
- ((DesiredAccess & GENERIC_WRITE) && Object->ExclusiveWrite != 0) ||
- (!(ShareMode & FILE_SHARE_READ) && Object->AccessRead != 0) ||
- (!(ShareMode & FILE_SHARE_WRITE) && Object->AccessWrite != 0))
- {
- DPRINT1("Sharing violation\n");
- Status = STATUS_SHARING_VIOLATION;
- }
- else
- {
- Status = Win32CsrInsertObject(ProcessData,
- &GetInputHandleRequest->Handle,
- Object,
- DesiredAccess,
- GetInputHandleRequest->Inheritable,
- ShareMode);
- }
- LeaveCriticalSection(&Console->Lock);
+ RemoveEntryList(&ProcessData->ConsoleLink);
+ Win32CsrUnlockConsole(Console);
+ //CloseHandle(ProcessData->ConsoleEvent);
+ //ProcessData->ConsoleEvent = NULL;
}
+
RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
+}
- return Status;
+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(CsrSetHandle) ??
+
CSR_API(SrvCloseHandle)
{
- PCSRSS_CLOSE_HANDLE CloseHandleRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.CloseHandleRequest;
+ PCONSOLE_CLOSEHANDLE CloseHandleRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.CloseHandleRequest;
- return Win32CsrReleaseObject(CsrGetClientThread()->Process, CloseHandleRequest->Handle);
+ return Win32CsrReleaseObject(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
+ CloseHandleRequest->ConsoleHandle);
}
CSR_API(SrvVerifyConsoleIoHandle)
{
NTSTATUS Status = STATUS_SUCCESS;
- PCSRSS_VERIFY_HANDLE VerifyHandleRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.VerifyHandleRequest;
- PCSR_PROCESS ProcessData = CsrGetClientThread()->Process;
- ULONG_PTR Index;
+ 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;
- Index = (ULONG_PTR)VerifyHandleRequest->Handle >> 2;
RtlEnterCriticalSection(&ProcessData->HandleTableLock);
- if (Index >= ProcessData->HandleTableSize ||
+
+ if (!IsConsoleHandle(ConsoleHandle) ||
+ Index >= ProcessData->HandleTableSize ||
ProcessData->HandleTable[Index].Object == NULL)
{
DPRINT("CsrVerifyObject failed\n");
Status = STATUS_INVALID_HANDLE;
}
+
RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
return Status;
CSR_API(SrvDuplicateHandle)
{
- ULONG_PTR Index;
- PCSRSS_HANDLE Entry;
+ PCONSOLE_IO_HANDLE Entry;
DWORD DesiredAccess;
- PCSRSS_DUPLICATE_HANDLE DuplicateHandleRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.DuplicateHandleRequest;
- PCSR_PROCESS ProcessData = CsrGetClientThread()->Process;
+ 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;
- Index = (ULONG_PTR)DuplicateHandleRequest->Handle >> 2;
RtlEnterCriticalSection(&ProcessData->HandleTableLock);
- if (Index >= ProcessData->HandleTableSize
- || (Entry = &ProcessData->HandleTable[Index])->Object == NULL)
+
+ if ( /** !IsConsoleHandle(ConsoleHandle) || **/
+ Index >= ProcessData->HandleTableSize ||
+ (Entry = &ProcessData->HandleTable[Index])->Object == NULL)
{
- DPRINT1("Couldn't dup invalid handle %p\n", DuplicateHandleRequest->Handle);
+ DPRINT1("Couldn't duplicate invalid handle %p\n", ConsoleHandle);
RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
return STATUS_INVALID_HANDLE;
}
if (~Entry->Access & DesiredAccess)
{
DPRINT1("Handle %p only has access %X; requested %X\n",
- DuplicateHandleRequest->Handle, Entry->Access, DesiredAccess);
+ ConsoleHandle, Entry->Access, DesiredAccess);
RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
return STATUS_INVALID_PARAMETER;
}
}
ApiMessage->Status = Win32CsrInsertObject(ProcessData,
- &DuplicateHandleRequest->Handle,
- Entry->Object,
- DesiredAccess,
- DuplicateHandleRequest->Inheritable,
- Entry->ShareMode);
- if (NT_SUCCESS(ApiMessage->Status)
- && DuplicateHandleRequest->Options & DUPLICATE_CLOSE_SOURCE)
+ &DuplicateHandleRequest->ConsoleHandle, // Use the new handle value!
+ Entry->Object,
+ DesiredAccess,
+ DuplicateHandleRequest->Inheritable,
+ Entry->ShareMode);
+ if (NT_SUCCESS(ApiMessage->Status) &&
+ DuplicateHandleRequest->Options & DUPLICATE_CLOSE_SOURCE)
{
Win32CsrCloseHandleEntry(Entry);
}
return ApiMessage->Status;
}
+/**
CSR_API(CsrGetInputWaitHandle)
{
PCSRSS_GET_INPUT_WAIT_HANDLE GetConsoleInputWaitHandle = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GetConsoleInputWaitHandle;
- GetConsoleInputWaitHandle->InputWaitHandle = CsrGetClientThread()->Process->ConsoleEvent;
+ GetConsoleInputWaitHandle->InputWaitHandle =
+ ConsoleGetPerProcessData(CsrGetClientThread()->Process)->ConsoleEvent;
+
return STATUS_SUCCESS;
}
+**/
/* EOF */