diff --git a/reactos/include/subsys/csrss/csrss.h b/reactos/include/subsys/csrss/csrss.h index d276e6a7e08..9c9f5405bba 100644 --- a/reactos/include/subsys/csrss/csrss.h +++ b/reactos/include/subsys/csrss/csrss.h @@ -33,6 +33,7 @@ typedef struct { HANDLE NewProcessId; ULONG Flags; + BOOL bInheritHandles; } CSRSS_CREATE_PROCESS, *PCSRSS_CREATE_PROCESS; typedef struct diff --git a/reactos/subsys/csrss/api/handle.c b/reactos/subsys/csrss/api/handle.c index f3c59db7055..ae57db53853 100644 --- a/reactos/subsys/csrss/api/handle.c +++ b/reactos/subsys/csrss/api/handle.c @@ -72,7 +72,7 @@ NTSTATUS STDCALL CsrGetObject( PCSRSS_PROCESS_DATA ProcessData, HANDLE Handle, O } if (!CsrIsConsoleHandle(Handle) || ProcessData->HandleTableSize <= h) { - DPRINT1("CsrGetObject returning invalid handle\n"); + DPRINT1("CsrGetObject returning invalid handle (%x)\n", Handle); return STATUS_INVALID_HANDLE; } *Object = ProcessData->HandleTable[h]; @@ -177,6 +177,43 @@ NTSTATUS STDCALL CsrInsertObject( PCSRSS_PROCESS_DATA ProcessData, PHANDLE Handl return(STATUS_SUCCESS); } +NTSTATUS STDCALL CsrDuplicateHandleTable(PCSRSS_PROCESS_DATA SourceProcessData, + PCSRSS_PROCESS_DATA TargetProcessData) +{ + ULONG i; + + if (SourceProcessData == NULL || + TargetProcessData == NULL || + TargetProcessData->HandleTableSize) + { + return STATUS_INVALID_PARAMETER; + } + + RtlEnterCriticalSection(&SourceProcessData->HandleTableLock); + + /* we are called from CreateProcessData, it isn't necessary to lock the target process data */ + + TargetProcessData->HandleTable = RtlAllocateHeap(CsrssApiHeap, + HEAP_ZERO_MEMORY, + SourceProcessData->HandleTableSize * sizeof(HANDLE)); + if (TargetProcessData->HandleTable == NULL) + { + RtlLeaveCriticalSection(&SourceProcessData->HandleTableLock); + return(STATUS_UNSUCCESSFUL); + } + TargetProcessData->HandleTableSize = SourceProcessData->HandleTableSize; + for (i = 0; i < SourceProcessData->HandleTableSize; i++) + { + if (SourceProcessData->HandleTable[i]) + { + TargetProcessData->HandleTable[i] = SourceProcessData->HandleTable[i]; + InterlockedIncrement( &SourceProcessData->HandleTable[i]->ReferenceCount ); + } + } + RtlLeaveCriticalSection(&SourceProcessData->HandleTableLock); + return(STATUS_SUCCESS); +} + NTSTATUS STDCALL CsrVerifyObject( PCSRSS_PROCESS_DATA ProcessData, HANDLE Handle ) { ULONG h = (((ULONG)Handle) >> 2) - 1; diff --git a/reactos/subsys/csrss/api/process.c b/reactos/subsys/csrss/api/process.c index 7bffb18308c..bc8880d193e 100644 --- a/reactos/subsys/csrss/api/process.c +++ b/reactos/subsys/csrss/api/process.c @@ -192,6 +192,7 @@ NTSTATUS STDCALL CsrFreeProcessData(HANDLE Pid) CSR_API(CsrCreateProcess) { PCSRSS_PROCESS_DATA NewProcessData; + NTSTATUS Status; Request->Header.DataSize = sizeof(CSR_API_MESSAGE) - LPC_MESSAGE_BASE_SIZE; Request->Header.MessageSize = sizeof(CSR_API_MESSAGE); @@ -203,6 +204,16 @@ CSR_API(CsrCreateProcess) return(STATUS_NO_MEMORY); } + if (!(Request->Data.CreateProcessRequest.Flags & (CREATE_NEW_CONSOLE|DETACHED_PROCESS))) + { + NewProcessData->ParentConsole = ProcessData->Console; + NewProcessData->bInheritHandles = Request->Data.CreateProcessRequest.bInheritHandles; + if (Request->Data.CreateProcessRequest.bInheritHandles) + { + Status = CsrDuplicateHandleTable(ProcessData, NewProcessData); + } + } + /* Set default shutdown parameters */ NewProcessData->ShutdownLevel = 0x280; NewProcessData->ShutdownFlags = 0; diff --git a/reactos/subsys/csrss/include/api.h b/reactos/subsys/csrss/include/api.h index 18f3af2b8ec..9d31035f861 100644 --- a/reactos/subsys/csrss/include/api.h +++ b/reactos/subsys/csrss/include/api.h @@ -35,6 +35,8 @@ typedef struct tagCSRSS_CONSOLE *PCSRSS_CONSOLE; typedef struct _CSRSS_PROCESS_DATA { PCSRSS_CONSOLE Console; + PCSRSS_CONSOLE ParentConsole; + BOOL bInheritHandles; RTL_CRITICAL_SECTION HandleTableLock; ULONG HandleTableSize; Object_t ** HandleTable; @@ -116,6 +118,7 @@ NTSTATUS STDCALL CsrFreeProcessData( HANDLE Pid ); /* api/handle.c */ NTSTATUS FASTCALL CsrRegisterObjectDefinitions(PCSRSS_OBJECT_DEFINITION NewDefinitions); NTSTATUS STDCALL CsrInsertObject( PCSRSS_PROCESS_DATA ProcessData, PHANDLE Handle, Object_t *Object ); +NTSTATUS STDCALL CsrDuplicateHandleTable(PCSRSS_PROCESS_DATA SourceProcessData, PCSRSS_PROCESS_DATA TargetProcessData); NTSTATUS STDCALL CsrGetObject( PCSRSS_PROCESS_DATA ProcessData, HANDLE Handle, Object_t **Object ); BOOL STDCALL CsrServerInitialization (ULONG ArgumentCount, PWSTR *ArgumentArray); NTSTATUS STDCALL CsrReleaseObjectByPointer(Object_t *Object); diff --git a/reactos/subsys/csrss/win32csr/conio.c b/reactos/subsys/csrss/win32csr/conio.c index c52047801c6..2ec7b459702 100644 --- a/reactos/subsys/csrss/win32csr/conio.c +++ b/reactos/subsys/csrss/win32csr/conio.c @@ -212,7 +212,7 @@ CsrInitConsole(PCSRSS_CONSOLE Console) } Console->ActiveBuffer = NewBuffer; /* add a reference count because the buffer is tied to the console */ - Console->ActiveBuffer->Header.ReferenceCount++; + InterlockedIncrement(&Console->ActiveBuffer->Header.ReferenceCount); /* make console active, and insert into console list */ /* copy buffer contents to screen */ ConioDrawConsole(Console); @@ -225,6 +225,7 @@ CSR_API(CsrAllocConsole) { PCSRSS_CONSOLE Console; NTSTATUS Status; + BOOLEAN NewConsole = FALSE; DPRINT("CsrAllocConsole\n"); @@ -255,9 +256,11 @@ CSR_API(CsrAllocConsole) } /* If we already have one, then don't create a new one... */ - if (!Request->Data.AllocConsoleRequest.Console) + if (!Request->Data.AllocConsoleRequest.Console || + Request->Data.AllocConsoleRequest.Console != ProcessData->ParentConsole) { /* Allocate a console structure */ + NewConsole = TRUE; Console = HeapAlloc(Win32CsrApiHeap, 0, sizeof(CSRSS_CONSOLE)); if (NULL == Console) { @@ -290,28 +293,32 @@ CSR_API(CsrAllocConsole) /* Add a reference count because the process is tied to the console */ Console->Header.ReferenceCount++; - /* Insert the Objects */ - Status = Win32CsrInsertObject(ProcessData, - &Request->Data.AllocConsoleRequest.InputHandle, - &Console->Header); - if (! NT_SUCCESS(Status)) + if (NewConsole || !ProcessData->bInheritHandles) { - DPRINT1("Failed to insert object\n"); - ConioDeleteConsole((Object_t *) Console); - ProcessData->Console = 0; - return Request->Status = Status; - } - Status = Win32CsrInsertObject(ProcessData, - &Request->Data.AllocConsoleRequest.OutputHandle, - &Console->ActiveBuffer->Header); - if (!NT_SUCCESS(Status)) - { - DPRINT1("Failed to insert object\n"); - Console->Header.ReferenceCount--; - Win32CsrReleaseObject(ProcessData, - Request->Data.AllocConsoleRequest.InputHandle); - ProcessData->Console = 0; - return Request->Status = Status; + /* Insert the Objects */ + Status = Win32CsrInsertObject(ProcessData, + &Request->Data.AllocConsoleRequest.InputHandle, + &Console->Header); + if (! NT_SUCCESS(Status)) + { + DPRINT1("Failed to insert object\n"); + ConioDeleteConsole((Object_t *) Console); + ProcessData->Console = 0; + return Request->Status = Status; + } + + Status = Win32CsrInsertObject(ProcessData, + &Request->Data.AllocConsoleRequest.OutputHandle, + &Console->ActiveBuffer->Header); + if (!NT_SUCCESS(Status)) + { + DPRINT1("Failed to insert object\n"); + ConioDeleteConsole((Object_t *) Console); + Win32CsrReleaseObject(ProcessData, + Request->Data.AllocConsoleRequest.InputHandle); + ProcessData->Console = 0; + return Request->Status = Status; + } } /* Duplicate the Event */ @@ -324,14 +331,16 @@ CSR_API(CsrAllocConsole) 0)) { DPRINT1("DuplicateHandle() failed: %d\n", GetLastError); - Console->Header.ReferenceCount--; - Win32CsrReleaseObject(ProcessData, - Request->Data.AllocConsoleRequest.OutputHandle); - Win32CsrReleaseObject(ProcessData, - Request->Data.AllocConsoleRequest.InputHandle); + ConioDeleteConsole((Object_t *) Console); + if (NewConsole || !ProcessData->bInheritHandles) + { + Win32CsrReleaseObject(ProcessData, + Request->Data.AllocConsoleRequest.OutputHandle); + Win32CsrReleaseObject(ProcessData, + Request->Data.AllocConsoleRequest.InputHandle); + } ProcessData->Console = 0; - Request->Status = Status; - return Status; + return Request->Status = Status; } /* Set the Ctrl Dispatcher */ @@ -358,9 +367,8 @@ CSR_API(CsrFreeConsole) } Console = ProcessData->Console; - Console->Header.ReferenceCount--; ProcessData->Console = NULL; - if (0 == Console->Header.ReferenceCount) + if (0 == InterlockedDecrement(&Console->Header.ReferenceCount)) { ConioDeleteConsole((Object_t *) Console); } @@ -1002,7 +1010,7 @@ ConioDeleteConsole(Object_t *Object) HeapFree(Win32CsrApiHeap, 0, Event); } - if (0 == --Console->ActiveBuffer->Header.ReferenceCount) + if (0 == InterlockedDecrement(&Console->ActiveBuffer->Header.ReferenceCount)) { ConioDeleteScreenBuffer((Object_t *) Console->ActiveBuffer); }