* LICENSE: GPL - See COPYING in the top level directory
* PROJECT: ReactOS Console Server DLL
* FILE: win32ss/user/consrv/handle.c
- * PURPOSE: Console IO Handle functions
+ * PURPOSE: Console I/O Handles functions
* PROGRAMMERS:
*/
/* PRIVATE FUNCTIONS *********************************************************/
static INT
-AdjustHandleCounts(PCSRSS_HANDLE Entry, INT Change)
+AdjustHandleCounts(PCONSOLE_IO_HANDLE Entry, INT Change)
{
Object_t *Object = Entry->Object;
}
static VOID
-Win32CsrCreateHandleEntry(PCSRSS_HANDLE Entry)
+ConSrvCreateHandleEntry(PCONSOLE_IO_HANDLE Entry)
{
- Object_t *Object = Entry->Object;
- EnterCriticalSection(&Object->Console->Lock);
+ /// LOCK /// Object_t *Object = Entry->Object;
+ /// LOCK /// EnterCriticalSection(&Object->Console->Lock);
AdjustHandleCounts(Entry, +1);
- LeaveCriticalSection(&Object->Console->Lock);
+ /// LOCK /// LeaveCriticalSection(&Object->Console->Lock);
}
static VOID
-Win32CsrCloseHandleEntry(PCSRSS_HANDLE Entry)
+ConSrvCloseHandleEntry(PCONSOLE_IO_HANDLE Entry)
{
Object_t *Object = Entry->Object;
if (Object != NULL)
{
- PCSRSS_CONSOLE Console = Object->Console;
- EnterCriticalSection(&Console->Lock);
+ /// 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)
{
- PCSRSS_SCREEN_BUFFER Buffer = (PCSRSS_SCREEN_BUFFER)Object;
+ 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)
+ else if (Object->Type == CONIO_INPUT_BUFFER_MAGIC)
{
- /* TODO: FIXME: Destroy here the console ?? */
- // ConioDeleteConsole(Console);
+ DPRINT1("Closing the input buffer\n");
}
}
- LeaveCriticalSection(&Console->Lock);
+ /// 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
-Win32CsrInsertObject(PCONSOLE_PROCESS_DATA ProcessData,
- PHANDLE Handle,
- Object_t *Object,
- DWORD Access,
- BOOL Inheritable,
- DWORD ShareMode)
+ConSrvInsertObject(PCONSOLE_PROCESS_DATA ProcessData,
+ PHANDLE Handle,
+ Object_t *Object,
+ DWORD Access,
+ BOOL Inheritable,
+ DWORD ShareMode)
{
+#define IO_HANDLES_INCREMENT 2*3
+
ULONG i;
- PCSRSS_HANDLE Block;
+ PCONSOLE_IO_HANDLE Block;
RtlEnterCriticalSection(&ProcessData->HandleTableLock);
{
Block = RtlAllocateHeap(ConSrvHeap,
HEAP_ZERO_MEMORY,
- (ProcessData->HandleTableSize + 64) * sizeof(CSRSS_HANDLE));
+ (ProcessData->HandleTableSize +
+ IO_HANDLES_INCREMENT) * sizeof(CONSOLE_IO_HANDLE));
if (Block == NULL)
{
RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
}
RtlCopyMemory(Block,
ProcessData->HandleTable,
- ProcessData->HandleTableSize * sizeof(CSRSS_HANDLE));
+ ProcessData->HandleTableSize * sizeof(CONSOLE_IO_HANDLE));
RtlFreeHeap(ConSrvHeap, 0, ProcessData->HandleTable);
ProcessData->HandleTable = Block;
- ProcessData->HandleTableSize += 64;
+ 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;
- Win32CsrCreateHandleEntry(&ProcessData->HandleTable[i]);
- *Handle = UlongToHandle((i << 2) | 0x3);
+ ConSrvCreateHandleEntry(&ProcessData->HandleTable[i]);
+ *Handle = ULongToHandle((i << 2) | 0x3);
+
RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
+
return STATUS_SUCCESS;
}
NTSTATUS
FASTCALL
-Win32CsrReleaseObject(PCONSOLE_PROCESS_DATA ProcessData,
- HANDLE Handle)
+ConSrvRemoveObject(PCONSOLE_PROCESS_DATA ProcessData,
+ HANDLE Handle)
{
ULONG_PTR h = (ULONG_PTR)Handle >> 2;
Object_t *Object;
return STATUS_INVALID_HANDLE;
}
- DPRINT1("Win32CsrReleaseObject - Process 0x%p, Release 0x%p\n", ProcessData->Process, &ProcessData->HandleTable[h]);
- Win32CsrCloseHandleEntry(&ProcessData->HandleTable[h]);
+ DPRINT1("ConSrvRemoveObject - Process 0x%p, Release 0x%p\n", ProcessData->Process, &ProcessData->HandleTable[h]);
+ ConSrvCloseHandleEntry(&ProcessData->HandleTable[h]);
RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
NTSTATUS
FASTCALL
-Win32CsrLockObject(PCONSOLE_PROCESS_DATA ProcessData,
- HANDLE Handle,
- Object_t **Object,
- DWORD Access,
- LONG Type)
+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;
- DPRINT("Win32CsrLockObject, Object: %x, %x, %x\n",
- Object, Handle, ProcessData ? ProcessData->HandleTableSize : 0);
+ 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 ||
- (*Object = ProcessData->HandleTable[h].Object) == NULL ||
- ~ProcessData->HandleTable[h].Access & Access ||
- (Type != 0 && (*Object)->Type != Type) )
+ if ( IsConsoleHandle(Handle) &&
+ h < ProcessData->HandleTableSize )
{
- DPRINT1("CsrGetObject returning invalid handle (%x)\n", Handle);
+ 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(&(*Object)->Console->ReferenceCount);
+ _InterlockedIncrement(&ObjectEntry->Console->ReferenceCount);
RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
- EnterCriticalSection(&((*Object)->Console->Lock));
+ if (LockConsole) EnterCriticalSection(&ObjectEntry->Console->Lock);
+
+ /* Return the objects to the caller */
+ *Object = ObjectEntry;
+ if (Entry) *Entry = HandleEntry;
+
return STATUS_SUCCESS;
}
-VOID FASTCALL
-Win32CsrUnlockConsole(PCSRSS_CONSOLE Console)
+VOID
+FASTCALL
+ConSrvReleaseObject(Object_t *Object,
+ BOOL IsConsoleLocked)
{
- LeaveCriticalSection(&Console->Lock);
+ ConSrvReleaseConsole(Object->Console, IsConsoleLocked);
+}
- /* Decrement reference count */
- if (_InterlockedDecrement(&Console->ReferenceCount) == 0)
- ConioDeleteConsole(Console);
+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
-Win32CsrUnlockObject(Object_t *Object)
+ConSrvRemoveConsole(PCONSOLE_PROCESS_DATA ProcessData)
{
- Win32CsrUnlockConsole(Object->Console);
+ 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);
+}
-/** Remark: this function can be called by SrvAttachConsole (not yet implemented) **/
NTSTATUS
NTAPI
-ConsoleNewProcess(PCSR_PROCESS SourceProcess,
- PCSR_PROCESS TargetProcess)
+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 ConsoleConnect call. Why we are doing
+ * 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
- * ConsoleConnect we don't have any reference to the parent process anymore.
+ * ConSrvConnect we don't have any reference to the parent process anymore.
**************************************************************************/
PCONSOLE_PROCESS_DATA SourceProcessData, TargetProcessData;
- ULONG i;
-
- DPRINT1("ConsoleNewProcess inside\n");
- DPRINT1("SourceProcess = 0x%p ; TargetProcess = 0x%p\n", SourceProcess, TargetProcess);
/* An empty target process is invalid */
- if (!TargetProcess)
- return STATUS_INVALID_PARAMETER;
-
- DPRINT1("ConsoleNewProcess - OK\n");
+ if (!TargetProcess) return STATUS_INVALID_PARAMETER;
TargetProcessData = ConsoleGetPerProcessData(TargetProcess);
- DPRINT1("TargetProcessData = 0x%p\n", TargetProcessData);
/**** HACK !!!! ****/ RtlZeroMemory(TargetProcessData, sizeof(*TargetProcessData));
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;
+ 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,
if ( SourceProcessData->Console != NULL && /* SourceProcessData->ConsoleApp */
TargetProcessData->ConsoleApp )
{
-/*
- if (TargetProcessData->HandleTableSize)
- {
- return STATUS_INVALID_PARAMETER;
- }
-*/
+ NTSTATUS Status;
- 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(CSRSS_HANDLE));
- if (TargetProcessData->HandleTable == NULL)
- {
- RtlLeaveCriticalSection(&SourceProcessData->HandleTableLock);
- return STATUS_UNSUCCESSFUL;
- }
-
- 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]);
- }
- }
+ Status = ConSrvInheritHandlesTable(SourceProcessData, TargetProcessData);
+ if (!NT_SUCCESS(Status)) return Status;
- 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);
+ /* Temporary save the parent's console */
+ TargetProcessData->ParentConsole = SourceProcessData->Console;
}
return STATUS_SUCCESS;
NTSTATUS
NTAPI
-ConsoleConnect(IN PCSR_PROCESS CsrProcess,
- IN OUT PVOID ConnectionInfo,
- IN OUT PULONG ConnectionInfoLength)
+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);
- BOOLEAN NewConsole = FALSE;
- // PCSRSS_CONSOLE Console = NULL;
-
- DPRINT1("ConsoleConnect\n");
if ( ConnectionInfo == NULL ||
ConnectionInfoLength == NULL ||
/* If we don't need a console, then get out of here */
if (!ConnectInfo->ConsoleNeeded || !ProcessData->ConsoleApp) // In fact, it is for GUI apps.
{
- DPRINT("ConsoleConnect - No console needed\n");
return STATUS_SUCCESS;
}
- RtlEnterCriticalSection(&ProcessData->HandleTableLock);
-
/* If we don't have a console, then create a new one... */
if (!ConnectInfo->Console ||
ConnectInfo->Console != ProcessData->ParentConsole)
{
- 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");
+ DPRINT1("ConSrvConnect - Allocate a new 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
+ * 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 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
+ * Therefore, free the console we can have and our handles table,
+ * and recreate a new one later on.
*/
+ ConSrvRemoveConsole(ProcessData);
- /* 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);
+ /* 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("Failed to insert the output handle\n");
- ConioDeleteConsole(ProcessData->Console);
- Win32CsrReleaseObject(ProcessData,
- ConnectInfo->InputHandle);
- ProcessData->Console = NULL;
- RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
+ DPRINT1("Console allocation failed\n");
return Status;
}
+ }
+ else /* We inherit it from the parent */
+ {
+ DPRINT1("ConSrvConnect - Reuse current (parent's) console\n");
- /* Insert the Error handle */
- Status = Win32CsrInsertObject(ProcessData,
- &ConnectInfo->ErrorHandle,
- &ProcessData->Console->ActiveBuffer->Header,
- GENERIC_READ | GENERIC_WRITE,
- TRUE,
- FILE_SHARE_READ | FILE_SHARE_WRITE);
+ /* Reuse our current console */
+ Status = ConSrvInheritConsole(ProcessData,
+ ConnectInfo->Console,
+ FALSE,
+ NULL, // &ConnectInfo->InputHandle,
+ NULL, // &ConnectInfo->OutputHandle,
+ NULL); // &ConnectInfo->ErrorHandle);
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);
+ DPRINT1("Console inheritance failed\n");
return Status;
}
}
- /* Duplicate the Event */
- Status = NtDuplicateObject(NtCurrentProcess(),
- ProcessData->Console->ActiveEvent,
- ProcessData->Process->ProcessHandle,
- &ProcessData->ConsoleEvent,
- EVENT_ALL_ACCESS, 0, 0);
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("NtDuplicateObject() failed: %lu\n", Status);
- ConioDeleteConsole(ProcessData->Console);
- if (NewConsole /* || !ProcessData->bInheritHandles */)
- {
- Win32CsrReleaseObject(ProcessData,
- ConnectInfo->ErrorHandle);
- Win32CsrReleaseObject(ProcessData,
- ConnectInfo->OutputHandle);
- Win32CsrReleaseObject(ProcessData,
- ConnectInfo->InputHandle);
- }
- ProcessData->Console = NULL;
- RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
- return Status;
- }
+ /* 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;
- DPRINT("CSRSS:CtrlDispatcher address: %x\n", ProcessData->CtrlDispatcher);
- RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
return STATUS_SUCCESS;
}
VOID
-WINAPI
-Win32CsrReleaseConsole(PCSR_PROCESS Process)
-{
- PCONSOLE_PROCESS_DATA ProcessData = ConsoleGetPerProcessData(Process);
- PCSRSS_CONSOLE Console;
- ULONG i;
-
- DPRINT1("Win32CsrReleaseConsole\n");
-
- RtlEnterCriticalSection(&ProcessData->HandleTableLock);
-
- /* 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);
- RemoveEntryList(&ProcessData->ConsoleLink);
- Win32CsrUnlockConsole(Console);
- //CloseHandle(ProcessData->ConsoleEvent);
- //ProcessData->ConsoleEvent = NULL;
- }
-
- RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
-}
-
-VOID
-WINAPI
-ConsoleDisconnect(PCSR_PROCESS Process)
+NTAPI
+ConSrvDisconnect(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("ConSrvDisconnect\n");
+
+ if ( ProcessData->Console != NULL ||
+ ProcessData->HandleTable != NULL )
{
- DPRINT1("ConsoleDisconnect - calling Win32CsrReleaseConsole\n");
- Win32CsrReleaseConsole(Process);
+ DPRINT1("ConSrvDisconnect - calling ConSrvRemoveConsole\n");
+ ConSrvRemoveConsole(ProcessData);
}
RtlDeleteCriticalSection(&ProcessData->HandleTableLock);
CSR_API(SrvCloseHandle)
{
- PCSRSS_CLOSE_HANDLE CloseHandleRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.CloseHandleRequest;
+ PCONSOLE_CLOSEHANDLE CloseHandleRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.CloseHandleRequest;
- return Win32CsrReleaseObject(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
- CloseHandleRequest->Handle);
+ return ConSrvRemoveObject(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
+ CloseHandleRequest->ConsoleHandle);
}
CSR_API(SrvVerifyConsoleIoHandle)
{
NTSTATUS Status = STATUS_SUCCESS;
- PCSRSS_VERIFY_HANDLE VerifyHandleRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.VerifyHandleRequest;
+ PCONSOLE_VERIFYHANDLE VerifyHandleRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.VerifyHandleRequest;
PCONSOLE_PROCESS_DATA ProcessData = ConsoleGetPerProcessData(CsrGetClientThread()->Process);
- HANDLE Handle = VerifyHandleRequest->Handle;
- ULONG_PTR Index = (ULONG_PTR)Handle >> 2;
+ HANDLE ConsoleHandle = VerifyHandleRequest->ConsoleHandle;
+ ULONG_PTR Index = (ULONG_PTR)ConsoleHandle >> 2;
RtlEnterCriticalSection(&ProcessData->HandleTableLock);
- if (!IsConsoleHandle(Handle) ||
+ if (!IsConsoleHandle(ConsoleHandle) ||
Index >= ProcessData->HandleTableSize ||
ProcessData->HandleTable[Index].Object == NULL)
{
- DPRINT("CsrVerifyObject failed\n");
+ DPRINT("SrvVerifyConsoleIoHandle failed\n");
Status = STATUS_INVALID_HANDLE;
}
CSR_API(SrvDuplicateHandle)
{
- PCSRSS_HANDLE Entry;
+ PCONSOLE_IO_HANDLE Entry;
DWORD DesiredAccess;
- PCSRSS_DUPLICATE_HANDLE DuplicateHandleRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.DuplicateHandleRequest;
+ PCONSOLE_DUPLICATEHANDLE DuplicateHandleRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.DuplicateHandleRequest;
PCONSOLE_PROCESS_DATA ProcessData = ConsoleGetPerProcessData(CsrGetClientThread()->Process);
- HANDLE Handle = DuplicateHandleRequest->Handle;
- ULONG_PTR Index = (ULONG_PTR)Handle >> 2;
+ HANDLE ConsoleHandle = DuplicateHandleRequest->ConsoleHandle;
+ ULONG_PTR Index = (ULONG_PTR)ConsoleHandle >> 2;
RtlEnterCriticalSection(&ProcessData->HandleTableLock);
- if ( /** !IsConsoleHandle(Handle) || **/
+ if ( /** !IsConsoleHandle(ConsoleHandle) || **/
Index >= ProcessData->HandleTableSize ||
(Entry = &ProcessData->HandleTable[Index])->Object == NULL)
{
- DPRINT1("Couldn't duplicate invalid handle %p\n", Handle);
+ DPRINT1("Couldn't duplicate invalid handle %p\n", ConsoleHandle);
RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
return STATUS_INVALID_HANDLE;
}
{
DesiredAccess = DuplicateHandleRequest->Access;
/* Make sure the source handle has all the desired flags */
- if (~Entry->Access & DesiredAccess)
+ if ((Entry->Access & DesiredAccess) == 0)
{
DPRINT1("Handle %p only has access %X; requested %X\n",
- Handle, Entry->Access, DesiredAccess);
+ ConsoleHandle, Entry->Access, DesiredAccess);
RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
return STATUS_INVALID_PARAMETER;
}
}
- ApiMessage->Status = Win32CsrInsertObject(ProcessData,
- &DuplicateHandleRequest->Handle, // Use the new handle value!
- Entry->Object,
- DesiredAccess,
- DuplicateHandleRequest->Inheritable,
- Entry->ShareMode);
+ 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)
{
- Win32CsrCloseHandleEntry(Entry);
+ ConSrvCloseHandleEntry(Entry);
}
RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
return ApiMessage->Status;
}
-/**
-CSR_API(CsrGetInputWaitHandle)
-{
- PCSRSS_GET_INPUT_WAIT_HANDLE GetConsoleInputWaitHandle = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GetConsoleInputWaitHandle;
-
- GetConsoleInputWaitHandle->InputWaitHandle =
- ConsoleGetPerProcessData(CsrGetClientThread()->Process)->ConsoleEvent;
-
- return STATUS_SUCCESS;
-}
-**/
-
/* EOF */