Author: hbelusca
Date: Sun Jan 13 17:07:25 2013
New Revision: 58166

URL: http://svn.reactos.org/svn/reactos?rev=58166&view=rev
Log:
[KERNEL32]
- Correct a error return code (in AllocConsole).
- Implement AttachConsole (inspired by AllocConsole).

[CONSRV]
- Correct a error return code (in AllocConsole).
- Introduce helper functions to simplify console-initialization code.
- Implement server-side of AttachConsole (I used pieces of code from 
ConsoleNewProcess, ConsoleConnect and SrvAllocConsole).

Some debug prints were introduced (for debug-purposes :P), will be removed when 
all things work.

TODO: have a look on the handles code.

Modified:
    branches/ros-csrss/dll/win32/kernel32/client/console/console.c
    branches/ros-csrss/include/reactos/subsys/win/conmsg.h
    branches/ros-csrss/win32ss/user/consrv/console.c
    branches/ros-csrss/win32ss/user/consrv/consrv.h
    branches/ros-csrss/win32ss/user/consrv/handle.c
    branches/ros-csrss/win32ss/user/consrv/init.c

Modified: branches/ros-csrss/dll/win32/kernel32/client/console/console.c
URL: 
http://svn.reactos.org/svn/reactos/branches/ros-csrss/dll/win32/kernel32/client/console/console.c?rev=58166&r1=58165&r2=58166&view=diff
==============================================================================
--- branches/ros-csrss/dll/win32/kernel32/client/console/console.c [iso-8859-1] 
(original)
+++ branches/ros-csrss/dll/win32/kernel32/client/console/console.c [iso-8859-1] 
Sun Jan 13 17:07:25 2013
@@ -802,8 +802,8 @@
 
     if (NtCurrentPeb()->ProcessParameters->ConsoleHandle)
     {
-        DPRINT("AllocConsole: Allocate duplicate console to the same 
Process\n");
-        BaseSetLastNTError (STATUS_OBJECT_NAME_EXISTS);
+        DPRINT1("AllocConsole: Allocate duplicate console to the same 
Process\n");
+        SetLastError(ERROR_ACCESS_DENIED);
         return FALSE;
     }
 
@@ -824,7 +824,6 @@
     }
 
     NtCurrentPeb()->ProcessParameters->ConsoleHandle = 
AllocConsoleRequest->Console;
-
     SetStdHandle(STD_INPUT_HANDLE , AllocConsoleRequest->InputHandle );
     SetStdHandle(STD_OUTPUT_HANDLE, AllocConsoleRequest->OutputHandle);
     SetStdHandle(STD_ERROR_HANDLE , AllocConsoleRequest->ErrorHandle );
@@ -1910,13 +1909,50 @@
 /*--------------------------------------------------------------
  *     AttachConsole
  *
- * @unimplemented
+ * @implemented
+ *
+ * @note Strongly inspired by AllocConsole.
  */
 BOOL
 WINAPI
 AttachConsole(DWORD dwProcessId)
 {
-    DPRINT1("AttachConsole(0x%x) UNIMPLEMENTED!\n", dwProcessId);
+    NTSTATUS Status;
+    CONSOLE_API_MESSAGE ApiMessage;
+    PCONSOLE_ATTACHCONSOLE AttachConsoleRequest = 
&ApiMessage.Data.AttachConsoleRequest;
+
+    DPRINT1("AttachConsole(%lu)\n", dwProcessId);
+
+    if (NtCurrentPeb()->ProcessParameters->ConsoleHandle)
+    {
+        DPRINT1("AttachConsole: Attaching a console to a process already 
having one\n");
+        SetLastError(ERROR_ACCESS_DENIED);
+        return FALSE;
+    }
+
+    AttachConsoleRequest->ProcessId = dwProcessId;
+    AttachConsoleRequest->CtrlDispatcher = ConsoleControlDispatcher;
+
+    Status = CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
+                                 NULL,
+                                 CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, 
ConsolepAttach),
+                                 sizeof(CONSOLE_ATTACHCONSOLE));
+    if (!NT_SUCCESS(Status) || !NT_SUCCESS(Status = ApiMessage.Status))
+    {
+        BaseSetLastNTError(Status);
+        return FALSE;
+    }
+
+    NtCurrentPeb()->ProcessParameters->ConsoleHandle = 
AttachConsoleRequest->Console;
+    SetStdHandle(STD_INPUT_HANDLE , AttachConsoleRequest->InputHandle );
+    SetStdHandle(STD_OUTPUT_HANDLE, AttachConsoleRequest->OutputHandle);
+    SetStdHandle(STD_ERROR_HANDLE , AttachConsoleRequest->ErrorHandle );
+
+    /* Initialize Console Ctrl Handler */
+    InitConsoleCtrlHandling();
+
+    InputWaitHandle = AttachConsoleRequest->InputWaitHandle;
+
     return TRUE;
 }
 

Modified: branches/ros-csrss/include/reactos/subsys/win/conmsg.h
URL: 
http://svn.reactos.org/svn/reactos/branches/ros-csrss/include/reactos/subsys/win/conmsg.h?rev=58166&r1=58165&r2=58166&view=diff
==============================================================================
--- branches/ros-csrss/include/reactos/subsys/win/conmsg.h [iso-8859-1] 
(original)
+++ branches/ros-csrss/include/reactos/subsys/win/conmsg.h [iso-8859-1] Sun Jan 
13 17:07:25 2013
@@ -102,7 +102,7 @@
     // ConsolepRegisterConsoleIME,
     // ConsolepUnregisterConsoleIME,
     // ConsolepGetLangId,
-    // ConsolepAttach,
+    ConsolepAttach,
     ConsolepGetSelectionInfo,
     ConsolepGetProcessList,
     ConsolepGetHistory,
@@ -176,6 +176,17 @@
     HANDLE InputWaitHandle;
     LPTHREAD_START_ROUTINE CtrlDispatcher;
 } CONSOLE_ALLOCCONSOLE, *PCONSOLE_ALLOCCONSOLE;
+
+typedef struct
+{
+    DWORD ProcessId; // If ProcessId == ATTACH_PARENT_PROCESS == -1, then 
attach the current process to its parent process console.
+    HANDLE Console; // ConsoleHandle // In fact, it is a PCSRSS_CONSOLE <-- 
correct that !!
+    HANDLE InputHandle;
+    HANDLE OutputHandle;
+    HANDLE ErrorHandle;
+    HANDLE InputWaitHandle;
+    LPTHREAD_START_ROUTINE CtrlDispatcher;
+} CONSOLE_ATTACHCONSOLE, *PCONSOLE_ATTACHCONSOLE;
 
 typedef struct
 {
@@ -543,6 +554,7 @@
     union
     {
         CONSOLE_ALLOCCONSOLE AllocConsoleRequest;
+        CONSOLE_ATTACHCONSOLE AttachConsoleRequest;
         CONSOLE_FREECONSOLE FreeConsoleRequest;
 
         /* Handles */

Modified: branches/ros-csrss/win32ss/user/consrv/console.c
URL: 
http://svn.reactos.org/svn/reactos/branches/ros-csrss/win32ss/user/consrv/console.c?rev=58166&r1=58165&r2=58166&view=diff
==============================================================================
--- branches/ros-csrss/win32ss/user/consrv/console.c [iso-8859-1] (original)
+++ branches/ros-csrss/win32ss/user/consrv/console.c [iso-8859-1] Sun Jan 13 
17:07:25 2013
@@ -301,57 +301,51 @@
     if (ProcessData->Console != NULL)
     {
         DPRINT1("Process already has a console\n");
-        return STATUS_INVALID_PARAMETER;
-    }
-
-    RtlEnterCriticalSection(&ProcessData->HandleTableLock);
-
+        return STATUS_ACCESS_DENIED;
+    }
+
+/******************************************************************************/
+/** This comes from ConsoleConnect!!                                         
**/
     DPRINT1("SrvAllocConsole - Checkpoint 1\n");
-
-    /* Initialize a new Console owned by the Console Leader Process */
-    Status = CsrInitConsole(&ProcessData->Console, 
AllocConsoleRequest->ShowCmd, ConsoleLeader);
-    if (!NT_SUCCESS(Status))
-    {
-        DPRINT1("Console initialization failed\n");
-        RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
-        return Status;
-    }
-
-    /* Insert the process into the processes list of the console */
-    InsertHeadList(&ProcessData->Console->ProcessList, 
&ProcessData->ConsoleLink);
-
-    /* Return it to the caller */
-    AllocConsoleRequest->Console = ProcessData->Console;
-
-    /* Add a reference count because the process is tied to the console */
-    _InterlockedIncrement(&ProcessData->Console->ReferenceCount);
 
 #if 0000
     /*
-     * 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 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.
+     * Therefore, free the console we can have and our handles table,
+     * and recreate a new one later on.
      */
-
-    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;
+    Win32CsrReleaseConsole(ProcessData);
+    // Win32CsrFreeHandlesTable(ProcessData);
 #endif
+
+    /* Initialize a new Console owned by the Console Leader Process */
+    Status = CsrInitConsole(&ProcessData->Console, 
AllocConsoleRequest->ShowCmd, ConsoleLeader);
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT1("Console initialization failed\n");
+        return Status;
+    }
+
+    /* Add a reference count because the process is tied to the console */
+    _InterlockedIncrement(&ProcessData->Console->ReferenceCount);
+
+    /* Insert the process into the processes list of the console */
+    InsertHeadList(&ProcessData->Console->ProcessList, 
&ProcessData->ConsoleLink);
+
+    /* Return it to the caller */
+    AllocConsoleRequest->Console = ProcessData->Console;
+
 
     /*
      * Create a new handle table - Insert the IO handles
      */
+
+    RtlEnterCriticalSection(&ProcessData->HandleTableLock);
 
     /* Insert the Input handle */
     Status = Win32CsrInsertObject(ProcessData,
@@ -363,9 +357,10 @@
     if (!NT_SUCCESS(Status))
     {
         DPRINT1("Failed to insert the input handle\n");
-        ConioDeleteConsole(ProcessData->Console);
-        ProcessData->Console = NULL;
         RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
+        Win32CsrReleaseConsole(ProcessData);
+        // ConioDeleteConsole(ProcessData->Console);
+        // ProcessData->Console = NULL;
         return Status;
     }
 
@@ -379,11 +374,12 @@
     if (!NT_SUCCESS(Status))
     {
         DPRINT1("Failed to insert the output handle\n");
-        ConioDeleteConsole(ProcessData->Console);
-        Win32CsrReleaseObject(ProcessData,
-                              AllocConsoleRequest->InputHandle);
-        ProcessData->Console = NULL;
         RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
+        Win32CsrReleaseConsole(ProcessData);
+        // Win32CsrReleaseObject(ProcessData,
+                              // AllocConsoleRequest->InputHandle);
+        // ConioDeleteConsole(ProcessData->Console);
+        // ProcessData->Console = NULL;
         return Status;
     }
 
@@ -397,15 +393,18 @@
     if (!NT_SUCCESS(Status))
     {
         DPRINT1("Failed to insert the error handle\n");
-        ConioDeleteConsole(ProcessData->Console);
-        Win32CsrReleaseObject(ProcessData,
-                              AllocConsoleRequest->OutputHandle);
-        Win32CsrReleaseObject(ProcessData,
-                              AllocConsoleRequest->InputHandle);
-        ProcessData->Console = NULL;
         RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
+        Win32CsrReleaseConsole(ProcessData);
+        // Win32CsrReleaseObject(ProcessData,
+                              // AllocConsoleRequest->OutputHandle);
+        // Win32CsrReleaseObject(ProcessData,
+                              // AllocConsoleRequest->InputHandle);
+        // ConioDeleteConsole(ProcessData->Console);
+        // ProcessData->Console = NULL;
         return Status;
     }
+
+    RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
 
     /* Duplicate the Event */
     Status = NtDuplicateObject(NtCurrentProcess(),
@@ -416,18 +415,18 @@
     if (!NT_SUCCESS(Status))
     {
         DPRINT1("NtDuplicateObject() failed: %lu\n", Status);
-        ConioDeleteConsole(ProcessData->Console);
-        // if (NewConsole /* || !ProcessData->bInheritHandles */)
-        {
-            Win32CsrReleaseObject(ProcessData,
-                                  AllocConsoleRequest->ErrorHandle);
-            Win32CsrReleaseObject(ProcessData,
-                                  AllocConsoleRequest->OutputHandle);
-            Win32CsrReleaseObject(ProcessData,
-                                  AllocConsoleRequest->InputHandle);
-        }
-        ProcessData->Console = NULL;
-        RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
+        Win32CsrReleaseConsole(ProcessData);
+        // if (NewConsole)
+        // {
+            // Win32CsrReleaseObject(ProcessData,
+                                  // AllocConsoleRequest->ErrorHandle);
+            // Win32CsrReleaseObject(ProcessData,
+                                  // AllocConsoleRequest->OutputHandle);
+            // Win32CsrReleaseObject(ProcessData,
+                                  // AllocConsoleRequest->InputHandle);
+        // }
+        // ConioDeleteConsole(ProcessData->Console); // FIXME: Just release 
the console ?
+        // ProcessData->Console = NULL;
         return Status;
     }
     /* Input Wait Handle */
@@ -436,15 +435,149 @@
     /* Set the Ctrl Dispatcher */
     ProcessData->CtrlDispatcher = AllocConsoleRequest->CtrlDispatcher;
     DPRINT("CONSRV: CtrlDispatcher address: %x\n", 
ProcessData->CtrlDispatcher);
-
-    RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
+/******************************************************************************/
+
     return STATUS_SUCCESS;
 }
 
+CSR_API(SrvAttachConsole)
+{
+    NTSTATUS Status = STATUS_SUCCESS;
+    PCONSOLE_ATTACHCONSOLE AttachConsoleRequest = 
&((PCONSOLE_API_MESSAGE)ApiMessage)->Data.AttachConsoleRequest;
+    PCSR_PROCESS SourceProcess = NULL;  // The parent process.
+    PCSR_PROCESS TargetProcess = CsrGetClientThread()->Process; // Ourselves.
+    HANDLE ProcessId = ULongToHandle(AttachConsoleRequest->ProcessId);
+    PCONSOLE_PROCESS_DATA SourceProcessData, TargetProcessData;
+
+    DPRINT("SrvAttachConsole\n");
+
+    TargetProcessData = ConsoleGetPerProcessData(TargetProcess);
+
+    if (TargetProcessData->Console != NULL)
+    {
+        DPRINT1("Process already has a console\n");
+        return STATUS_ACCESS_DENIED;
+    }
+
+    if (ProcessId == ULongToHandle(ATTACH_PARENT_PROCESS))
+    {
+        PROCESS_BASIC_INFORMATION ProcessInfo;
+        ULONG Length = sizeof(ProcessInfo);
+
+        /* Get the real parent's ID */
+
+        Status = NtQueryInformationProcess(TargetProcess->ProcessHandle,
+                                           ProcessBasicInformation,
+                                           &ProcessInfo,
+                                           Length, &Length);
+        if (!NT_SUCCESS(Status))
+        {
+            DPRINT1("SrvAttachConsole - Cannot retrieve basic process info, 
Status = %lu\n", Status);
+            return Status;
+        }
+
+        DPRINT("We, process (ID) %lu;%lu\n", 
TargetProcess->ClientId.UniqueProcess, TargetProcess->ClientId.UniqueThread);
+        ProcessId = ULongToHandle(ProcessInfo.InheritedFromUniqueProcessId);
+        DPRINT("Parent process ID = %lu\n", ProcessId);
+    }
+
+    /* Lock the target process via its PID */
+    DPRINT1("Lock process Id %lu\n", ProcessId);
+    Status = CsrLockProcessByClientId(ProcessId, &SourceProcess);
+    DPRINT1("Lock process Status %lu\n", Status);
+    if (!NT_SUCCESS(Status)) return Status;
+    DPRINT1("AttachConsole OK\n");
+
+/******************************************************************************/
+/** This comes from ConsoleNewProcess!!                                      
**/
+    SourceProcessData = ConsoleGetPerProcessData(SourceProcess);
+
+    /*
+     * Inherit the console from the parent,
+     * if any, otherwise return an error.
+     */
+    DPRINT1("SourceProcessData->Console = 0x%p\n", SourceProcessData->Console);
+    if (SourceProcessData->Console == NULL)
+    {
+        Status = STATUS_INVALID_HANDLE;
+        goto Quit;
+    }
+    TargetProcessData->Console = SourceProcessData->Console;
+
+    DPRINT1("SrvAttachConsole - Copy the handle table (1)\n");
+    Status = Win32CsrInheritHandlesTable(SourceProcessData, TargetProcessData);
+    DPRINT1("SrvAttachConsole - Copy the handle table (2)\n");
+    if (!NT_SUCCESS(Status))
+    {
+        goto Quit;
+    }
+
+/******************************************************************************/
+
+/******************************************************************************/
+/** This comes from ConsoleConnect / SrvAllocConsole!!                       
**/
+    /* Add a reference count because the process is tied to the console */
+    _InterlockedIncrement(&TargetProcessData->Console->ReferenceCount);
+
+    /* Insert the process into the processes list of the console */
+    InsertHeadList(&TargetProcessData->Console->ProcessList, 
&TargetProcessData->ConsoleLink);
+
+    /* Return it to the caller */
+    AttachConsoleRequest->Console = TargetProcessData->Console;
+
+    /** Here, we inherited the console handles from the "source" process,
+     ** so no need to reinitialize the handles table. **/
+
+    DPRINT1("SrvAttachConsole - Checkpoint\n");
+
+    /* Duplicate the Event */
+    Status = NtDuplicateObject(NtCurrentProcess(),
+                               TargetProcessData->Console->ActiveEvent,
+                               TargetProcessData->Process->ProcessHandle,
+                               &TargetProcessData->ConsoleEvent,
+                               EVENT_ALL_ACCESS, 0, 0);
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT1("NtDuplicateObject() failed: %lu\n", Status);
+        Win32CsrReleaseConsole(TargetProcessData);
+// #if 0
+        // if (NewConsole)
+        // {
+            // Win32CsrReleaseObject(TargetProcessData,
+                                  // AttachConsoleRequest->ErrorHandle);
+            // Win32CsrReleaseObject(TargetProcessData,
+                                  // AttachConsoleRequest->OutputHandle);
+            // Win32CsrReleaseObject(TargetProcessData,
+                                  // AttachConsoleRequest->InputHandle);
+        // }
+// #endif
+        // ConioDeleteConsole(TargetProcessData->Console); // FIXME: Just 
release the console ?
+        // TargetProcessData->Console = NULL;
+        goto Quit;
+    }
+    /* Input Wait Handle */
+    AttachConsoleRequest->InputWaitHandle = TargetProcessData->ConsoleEvent;
+
+    /* Set the Ctrl Dispatcher */
+    TargetProcessData->CtrlDispatcher = AttachConsoleRequest->CtrlDispatcher;
+    DPRINT("CONSRV: CtrlDispatcher address: %x\n", 
TargetProcessData->CtrlDispatcher);
+
+    Status = STATUS_SUCCESS;
+/******************************************************************************/
+
+Quit:
+    DPRINT1("SrvAttachConsole - exiting 1\n");
+    /* Unlock the "source" process */
+    CsrUnlockProcess(SourceProcess);
+    DPRINT1("SrvAttachConsole - exiting 2\n");
+
+    return Status;
+}
+
 CSR_API(SrvFreeConsole)
 {
     DPRINT1("SrvFreeConsole\n");
-    Win32CsrReleaseConsole(CsrGetClientThread()->Process);
+    
Win32CsrReleaseConsole(ConsoleGetPerProcessData(CsrGetClientThread()->Process));
     return STATUS_SUCCESS;
 }
 

Modified: branches/ros-csrss/win32ss/user/consrv/consrv.h
URL: 
http://svn.reactos.org/svn/reactos/branches/ros-csrss/win32ss/user/consrv/consrv.h?rev=58166&r1=58165&r2=58166&view=diff
==============================================================================
--- branches/ros-csrss/win32ss/user/consrv/consrv.h [iso-8859-1] (original)
+++ branches/ros-csrss/win32ss/user/consrv/consrv.h [iso-8859-1] Sun Jan 13 
17:07:25 2013
@@ -73,7 +73,6 @@
     /* PCONSOLE */ struct _CONSOLE* Console;
     /* PCONSOLE */ struct _CONSOLE* ParentConsole;
 
-    // BOOL bInheritHandles;
     BOOL ConsoleApp;    // TRUE if it is a CUI app, FALSE otherwise.
 
     RTL_CRITICAL_SECTION HandleTableLock;
@@ -118,6 +117,7 @@
 /* console.c */
 CSR_API(SrvOpenConsole);
 CSR_API(SrvAllocConsole);
+CSR_API(SrvAttachConsole);
 CSR_API(SrvFreeConsole);
 CSR_API(SrvSetConsoleMode);
 CSR_API(SrvGetConsoleMode);
@@ -139,6 +139,9 @@
 CSR_API(SrvDuplicateHandle);
 /// CSR_API(CsrGetInputWaitHandle);
 
+NTSTATUS FASTCALL Win32CsrInheritHandlesTable(IN PCONSOLE_PROCESS_DATA 
SourceProcessData,
+                                              IN PCONSOLE_PROCESS_DATA 
TargetProcessData);
+VOID FASTCALL Win32CsrFreeHandlesTable(PCONSOLE_PROCESS_DATA ProcessData);
 NTSTATUS FASTCALL Win32CsrInsertObject(PCONSOLE_PROCESS_DATA ProcessData,
                                        PHANDLE Handle,
                                        Object_t *Object,
@@ -153,6 +156,7 @@
 VOID FASTCALL Win32CsrUnlockObject(Object_t *Object);
 NTSTATUS FASTCALL Win32CsrReleaseObject(PCONSOLE_PROCESS_DATA ProcessData,
                                         HANDLE Handle);
+VOID FASTCALL Win32CsrReleaseConsole(PCONSOLE_PROCESS_DATA ProcessData);
 
 NTSTATUS NTAPI ConsoleNewProcess(PCSR_PROCESS SourceProcess,
                                  PCSR_PROCESS TargetProcess);
@@ -160,7 +164,6 @@
                               IN OUT PVOID ConnectionInfo,
                               IN OUT PULONG ConnectionInfoLength);
 VOID NTAPI ConsoleDisconnect(PCSR_PROCESS Process);
-VOID NTAPI Win32CsrReleaseConsole(PCSR_PROCESS Process);
 
 /* lineinput.c */
 CSR_API(SrvGetConsoleCommandHistoryLength);

Modified: branches/ros-csrss/win32ss/user/consrv/handle.c
URL: 
http://svn.reactos.org/svn/reactos/branches/ros-csrss/win32ss/user/consrv/handle.c?rev=58166&r1=58165&r2=58166&view=diff
==============================================================================
--- branches/ros-csrss/win32ss/user/consrv/handle.c [iso-8859-1] (original)
+++ branches/ros-csrss/win32ss/user/consrv/handle.c [iso-8859-1] Sun Jan 13 
17:07:25 2013
@@ -81,6 +81,85 @@
 
 NTSTATUS
 FASTCALL
+Win32CsrInheritHandlesTable(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 Win32CsrCreateHandleEntry).
+             */
+            TargetProcessData->HandleTable[i] = 
SourceProcessData->HandleTable[i];
+            Win32CsrCreateHandleEntry(&TargetProcessData->HandleTable[i]);
+        }
+    }
+
+Quit:
+    RtlLeaveCriticalSection(&SourceProcessData->HandleTableLock);
+    return Status;
+}
+
+VOID
+FASTCALL
+Win32CsrFreeHandlesTable(PCONSOLE_PROCESS_DATA ProcessData)
+{
+    DPRINT1("Win32CsrFreeHandlesTable\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++)
+        {
+            Win32CsrCloseHandleEntry(&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,
@@ -122,7 +201,8 @@
     ProcessData->HandleTable[i].Inheritable = Inheritable;
     ProcessData->HandleTable[i].ShareMode   = ShareMode;
     Win32CsrCreateHandleEntry(&ProcessData->HandleTable[i]);
-    *Handle = UlongToHandle((i << 2) | 0x3);
+    *Handle = ULongToHandle((i << 2) | 0x3);
+
     RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
     return STATUS_SUCCESS;
 }
@@ -202,9 +282,33 @@
     Win32CsrUnlockConsole(Object->Console);
 }
 
-
-
-/** Remark: this function can be called by SrvAttachConsole (not yet 
implemented) **/
+VOID
+FASTCALL
+Win32CsrReleaseConsole(PCONSOLE_PROCESS_DATA ProcessData)
+{
+    PCONSOLE Console;
+
+    DPRINT1("Win32CsrReleaseConsole\n");
+
+    /* Close all console handles and free the handle table memory */
+    Win32CsrFreeHandlesTable(ProcessData);
+
+    /* 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;
+    }
+}
+
+
+
 NTSTATUS
 NTAPI
 ConsoleNewProcess(PCSR_PROCESS SourceProcess,
@@ -223,7 +327,6 @@
      
**************************************************************************/
 
     PCONSOLE_PROCESS_DATA SourceProcessData, TargetProcessData;
-    ULONG i;
 
     DPRINT1("ConsoleNewProcess inside\n");
     DPRINT1("SourceProcess = 0x%p ; TargetProcess = 0x%p\n", SourceProcess, 
TargetProcess);
@@ -243,14 +346,13 @@
     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));
+    /**** HACK !!!! ****/ RtlZeroMemory(&TargetProcessData->HandleTableLock, 
sizeof(RTL_CRITICAL_SECTION));
     RtlInitializeCriticalSection(&TargetProcessData->HandleTableLock);
 
     /* Do nothing if the source process is NULL */
@@ -267,51 +369,17 @@
     if ( SourceProcessData->Console != NULL && /* 
SourceProcessData->ConsoleApp */
          TargetProcessData->ConsoleApp )
     {
-/*
-        if (TargetProcessData->HandleTableSize)
-        {
-            return STATUS_INVALID_PARAMETER;
-        }
-*/
-
-        DPRINT1("ConsoleNewProcess - Copy the handle table (1)\n");
+        NTSTATUS Status;
+
+        Status = Win32CsrInheritHandlesTable(SourceProcessData, 
TargetProcessData);
+        if (!NT_SUCCESS(Status))
+        {
+            return Status;
+        }
+
+        // FIXME: Do it before, or after the handles table inheritance ??
         /* 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(&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]);
-            }
-        }
-
-        RtlLeaveCriticalSection(&SourceProcessData->HandleTableLock);
     }
     else
     {
@@ -335,7 +403,6 @@
     PCONSOLE_CONNECTION_INFO ConnectInfo = 
(PCONSOLE_CONNECTION_INFO)ConnectionInfo;
     PCONSOLE_PROCESS_DATA ProcessData = ConsoleGetPerProcessData(CsrProcess);
     BOOLEAN NewConsole = FALSE;
-    // PCONSOLE Console = NULL;
 
     DPRINT1("ConsoleConnect\n");
 
@@ -354,13 +421,23 @@
         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");
+
+        /*
+         * We are about to create 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 the console we can have and our handles table,
+         * and recreate a new one later on.
+         */
+        Win32CsrReleaseConsole(ProcessData);
 
         /* Initialize a new Console owned by the Console Leader Process */
         NewConsole = TRUE;
@@ -368,7 +445,6 @@
         if (!NT_SUCCESS(Status))
         {
             DPRINT1("Console initialization failed\n");
-            RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
             return Status;
         }
     }
@@ -381,41 +457,22 @@
         ProcessData->Console = ConnectInfo->Console;
     }
 
+    /* Add a reference count because the process is tied to the console */
+    _InterlockedIncrement(&ProcessData->Console->ReferenceCount);
+
     /* 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;
-
+    if (NewConsole)
+    {
         /*
          * Create a new handle table - Insert the IO handles
          */
+
+        RtlEnterCriticalSection(&ProcessData->HandleTableLock);
 
         /* Insert the Input handle */
         Status = Win32CsrInsertObject(ProcessData,
@@ -427,9 +484,10 @@
         if (!NT_SUCCESS(Status))
         {
             DPRINT1("Failed to insert the input handle\n");
-            ConioDeleteConsole(ProcessData->Console);
-            ProcessData->Console = NULL;
             RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
+            Win32CsrReleaseConsole(ProcessData);
+            // ConioDeleteConsole(ProcessData->Console);
+            // ProcessData->Console = NULL;
             return Status;
         }
 
@@ -443,11 +501,12 @@
         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);
+            Win32CsrReleaseConsole(ProcessData);
+            // Win32CsrReleaseObject(ProcessData,
+                                  // ConnectInfo->InputHandle);
+            // ConioDeleteConsole(ProcessData->Console);
+            // ProcessData->Console = NULL;
             return Status;
         }
 
@@ -461,15 +520,18 @@
         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);
+            Win32CsrReleaseConsole(ProcessData);
+            // Win32CsrReleaseObject(ProcessData,
+                                  // ConnectInfo->OutputHandle);
+            // Win32CsrReleaseObject(ProcessData,
+                                  // ConnectInfo->InputHandle);
+            // ConioDeleteConsole(ProcessData->Console);
+            // ProcessData->Console = NULL;
             return Status;
         }
+
+        RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
     }
 
     /* Duplicate the Event */
@@ -481,18 +543,18 @@
     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);
+        Win32CsrReleaseConsole(ProcessData);
+        // if (NewConsole)
+        // {
+            // Win32CsrReleaseObject(ProcessData,
+                                  // ConnectInfo->ErrorHandle);
+            // Win32CsrReleaseObject(ProcessData,
+                                  // ConnectInfo->OutputHandle);
+            // Win32CsrReleaseObject(ProcessData,
+                                  // ConnectInfo->InputHandle);
+        // }
+        // ConioDeleteConsole(ProcessData->Console); // FIXME: Just release 
the console ?
+        // ProcessData->Console = NULL;
         return Status;
     }
     /* Input Wait Handle */
@@ -500,47 +562,9 @@
 
     /* Set the Ctrl Dispatcher */
     ProcessData->CtrlDispatcher = ConnectInfo->CtrlDispatcher;
-    DPRINT("CSRSS:CtrlDispatcher address: %x\n", ProcessData->CtrlDispatcher);
-
-    RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
+    DPRINT("CONSRV: CtrlDispatcher address: %x\n", 
ProcessData->CtrlDispatcher);
+
     return STATUS_SUCCESS;
-}
-
-VOID
-WINAPI
-Win32CsrReleaseConsole(PCSR_PROCESS Process)
-{
-    PCONSOLE_PROCESS_DATA ProcessData = ConsoleGetPerProcessData(Process);
-    PCONSOLE 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
@@ -551,19 +575,14 @@
 
     /**************************************************************************
      * 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)
+    if ( ProcessData->Console     != NULL ||
+         ProcessData->HandleTable != NULL )
     {
         DPRINT1("ConsoleDisconnect - calling Win32CsrReleaseConsole\n");
-        Win32CsrReleaseConsole(Process);
+        Win32CsrReleaseConsole(ProcessData);
     }
 
     RtlDeleteCriticalSection(&ProcessData->HandleTableLock);

Modified: branches/ros-csrss/win32ss/user/consrv/init.c
URL: 
http://svn.reactos.org/svn/reactos/branches/ros-csrss/win32ss/user/consrv/init.c?rev=58166&r1=58165&r2=58166&view=diff
==============================================================================
--- branches/ros-csrss/win32ss/user/consrv/init.c [iso-8859-1] (original)
+++ branches/ros-csrss/win32ss/user/consrv/init.c [iso-8859-1] Sun Jan 13 
17:07:25 2013
@@ -107,7 +107,7 @@
     // SrvRegisterConsoleIME,
     // SrvUnregisterConsoleIME,
     // SrvGetConsoleLangId,
-    // SrvAttachConsole,
+    SrvAttachConsole,
     SrvGetConsoleSelectionInfo,
     SrvGetConsoleProcessList,
     SrvGetConsoleHistory,
@@ -198,7 +198,7 @@
     // FALSE,   // SrvRegisterConsoleIME,
     // FALSE,   // SrvUnregisterConsoleIME,
     // FALSE,   // SrvGetConsoleLangId,
-    // FALSE,   // SrvAttachConsole,
+    FALSE,   // SrvAttachConsole,
     FALSE,   // SrvGetConsoleSelectionInfo,
     FALSE,   // SrvGetConsoleProcessList,
     FALSE,   // SrvGetConsoleHistory,
@@ -291,7 +291,7 @@
     // "RegisterConsoleIME",
     // "UnregisterConsoleIME",
     // "GetConsoleLangId",
-    // "AttachConsole",
+    "AttachConsole",
     "GetConsoleSelectionInfo",
     "GetConsoleProcessList",
     "GetConsoleHistory",


Reply via email to