- Implemented CsrDuplicateHandleTable.
- Duplicate the handle table in CsrCreateProcess if the caller wants to inherit all handles.  
- Don't allocate new handles in CsrAllocConsole if the caller wants to reuse a console and if the parent handles were inherited.  
- Do only allow to reuse the console from parent.
Modified: trunk/reactos/include/subsys/csrss/csrss.h
Modified: trunk/reactos/subsys/csrss/api/handle.c
Modified: trunk/reactos/subsys/csrss/api/process.c
Modified: trunk/reactos/subsys/csrss/include/api.h
Modified: trunk/reactos/subsys/csrss/win32csr/conio.c

Modified: trunk/reactos/include/subsys/csrss/csrss.h
--- trunk/reactos/include/subsys/csrss/csrss.h	2005-07-31 21:02:05 UTC (rev 16923)
+++ trunk/reactos/include/subsys/csrss/csrss.h	2005-07-31 21:23:40 UTC (rev 16924)
@@ -33,6 +33,7 @@
 {
    HANDLE NewProcessId;
    ULONG Flags;
+   BOOL bInheritHandles;
 } CSRSS_CREATE_PROCESS, *PCSRSS_CREATE_PROCESS;
 
 typedef struct

Modified: trunk/reactos/subsys/csrss/api/handle.c
--- trunk/reactos/subsys/csrss/api/handle.c	2005-07-31 21:02:05 UTC (rev 16923)
+++ trunk/reactos/subsys/csrss/api/handle.c	2005-07-31 21:23:40 UTC (rev 16924)
@@ -72,7 +72,7 @@
     }
   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 @@
    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;

Modified: trunk/reactos/subsys/csrss/api/process.c
--- trunk/reactos/subsys/csrss/api/process.c	2005-07-31 21:02:05 UTC (rev 16923)
+++ trunk/reactos/subsys/csrss/api/process.c	2005-07-31 21:23:40 UTC (rev 16924)
@@ -192,6 +192,7 @@
 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 @@
 	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;

Modified: trunk/reactos/subsys/csrss/include/api.h
--- trunk/reactos/subsys/csrss/include/api.h	2005-07-31 21:02:05 UTC (rev 16923)
+++ trunk/reactos/subsys/csrss/include/api.h	2005-07-31 21:23:40 UTC (rev 16924)
@@ -35,6 +35,8 @@
 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 @@
 /* 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);

Modified: trunk/reactos/subsys/csrss/win32csr/conio.c
--- trunk/reactos/subsys/csrss/win32csr/conio.c	2005-07-31 21:02:05 UTC (rev 16923)
+++ trunk/reactos/subsys/csrss/win32csr/conio.c	2005-07-31 21:23:40 UTC (rev 16924)
@@ -212,7 +212,7 @@
     }
   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 @@
 {
     PCSRSS_CONSOLE Console;
     NTSTATUS Status;
+    BOOLEAN NewConsole = FALSE;
 
     DPRINT("CsrAllocConsole\n");
 
@@ -255,9 +256,11 @@
     }
 
     /* 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,29 +293,33 @@
     /* 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;
+        /* 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;
+        }
     }
-    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;
-    }
 
     /* Duplicate the Event */
     if (!DuplicateHandle(GetCurrentProcess(), 
@@ -324,14 +331,16 @@
                          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 @@
     }
 
   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 @@
       HeapFree(Win32CsrApiHeap, 0, Event);
     }
 
-  if (0 == --Console->ActiveBuffer->Header.ReferenceCount)
+  if (0 == InterlockedDecrement(&Console->ActiveBuffer->Header.ReferenceCount))
     {
       ConioDeleteScreenBuffer((Object_t *) Console->ActiveBuffer);
     }