[CSRSRV]
[reactos.git] / win32ss / user / consrv / handle.c
index 785a488..339dbb3 100644 (file)
@@ -73,7 +73,10 @@ ConSrvCloseHandleEntry(PCONSOLE_IO_HANDLE Entry)
                           WaitAll,
                           NULL,
                           (PVOID)Entry);
-            // TODO: Dereference the notified waits.
+            if (!IsListEmpty(&InputBuffer->ReadWaitQueue))
+            {
+                CsrDereferenceWait(&InputBuffer->ReadWaitQueue);
+            }
         }
 
         /* If the last handle to a screen buffer is closed, delete it... */
@@ -126,11 +129,11 @@ ConSrvInitHandlesTable(IN OUT PCONSOLE_PROCESS_DATA ProcessData,
 
     /* Insert the Input handle */
     Status = ConSrvInsertObject(ProcessData,
-                                  &InputHandle,
-                                  &ProcessData->Console->InputBuffer.Header,
-                                  GENERIC_READ | GENERIC_WRITE,
-                                  TRUE,
-                                  FILE_SHARE_READ | FILE_SHARE_WRITE);
+                                &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");
@@ -141,11 +144,11 @@ ConSrvInitHandlesTable(IN OUT PCONSOLE_PROCESS_DATA ProcessData,
 
     /* Insert the Output handle */
     Status = ConSrvInsertObject(ProcessData,
-                                  &OutputHandle,
-                                  &ProcessData->Console->ActiveBuffer->Header,
-                                  GENERIC_READ | GENERIC_WRITE,
-                                  TRUE,
-                                  FILE_SHARE_READ | FILE_SHARE_WRITE);
+                                &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");
@@ -156,11 +159,11 @@ ConSrvInitHandlesTable(IN OUT PCONSOLE_PROCESS_DATA ProcessData,
 
     /* Insert the Error handle */
     Status = ConSrvInsertObject(ProcessData,
-                                  &ErrorHandle,
-                                  &ProcessData->Console->ActiveBuffer->Header,
-                                  GENERIC_READ | GENERIC_WRITE,
-                                  TRUE,
-                                  FILE_SHARE_READ | FILE_SHARE_WRITE);
+                                &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");
@@ -370,7 +373,7 @@ ConSrvGetObject(PCONSOLE_PROCESS_DATA ProcessData,
          (HandleEntry->Access & Access) == 0 ||
          (Type != 0 && ObjectEntry->Type != Type) )
     {
-        DPRINT1("CsrGetObject returning invalid handle (%x) of type %lu with access %lu\n", Handle, Type, Access);
+        DPRINT1("ConSrvGetObject returning invalid handle (%x) of type %lu with access %lu\n", Handle, Type, Access);
         RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
         return STATUS_INVALID_HANDLE;
     }
@@ -398,16 +401,16 @@ ConSrvReleaseObject(Object_t *Object,
 NTSTATUS
 FASTCALL
 ConSrvAllocateConsole(PCONSOLE_PROCESS_DATA ProcessData,
+                      LPCWSTR AppPath,
                       PHANDLE pInputHandle,
                       PHANDLE pOutputHandle,
                       PHANDLE pErrorHandle,
-                      int ShowCmd,
-                      PCSR_PROCESS CsrProcess)
+                      PCONSOLE_START_INFO ConsoleStartInfo)
 {
     NTSTATUS Status = STATUS_SUCCESS;
 
-    /* Initialize a new Console owned by the Console Leader Process */
-    Status = ConSrvInitConsole(&ProcessData->Console, ShowCmd, CsrProcess);
+    /* 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");
@@ -416,21 +419,91 @@ ConSrvAllocateConsole(PCONSOLE_PROCESS_DATA ProcessData,
 
     /* Initialize the handles table */
     Status = ConSrvInitHandlesTable(ProcessData,
-                                      pInputHandle,
-                                      pOutputHandle,
-                                      pErrorHandle);
+                                    pInputHandle,
+                                    pOutputHandle,
+                                    pErrorHandle);
     if (!NT_SUCCESS(Status))
     {
         DPRINT1("Failed to initialize the handles table\n");
+        ConSrvDeleteConsole(ProcessData->Console);
+        ProcessData->Console = NULL;
+        return Status;
+    }
 
-        // ConSrvRemoveConsole(ProcessData);
+    /* 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;
     }
 
-    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
@@ -450,9 +523,17 @@ ConSrvRemoveConsole(PCONSOLE_PROCESS_DATA ProcessData)
     {
         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;
@@ -498,8 +579,6 @@ ConSrvReleaseConsole(PCONSOLE Console,
         ConSrvDeleteConsole(Console);
 }
 
-
-
 NTSTATUS
 NTAPI
 ConSrvNewProcess(PCSR_PROCESS SourceProcess,
@@ -519,17 +598,10 @@ ConSrvNewProcess(PCSR_PROCESS SourceProcess,
 
     PCONSOLE_PROCESS_DATA SourceProcessData, TargetProcessData;
 
-    DPRINT1("ConSrvNewProcess 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("ConSrvNewProcess - OK\n");
+    if (!TargetProcess) return STATUS_INVALID_PARAMETER;
 
     TargetProcessData = ConsoleGetPerProcessData(TargetProcess);
-    DPRINT1("TargetProcessData = 0x%p\n", TargetProcessData);
 
     /**** HACK !!!! ****/ RtlZeroMemory(TargetProcessData, sizeof(*TargetProcessData));
 
@@ -543,15 +615,12 @@ ConSrvNewProcess(PCSR_PROCESS SourceProcess,
     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,
@@ -563,18 +632,11 @@ ConSrvNewProcess(PCSR_PROCESS SourceProcess,
         NTSTATUS Status;
 
         Status = ConSrvInheritHandlesTable(SourceProcessData, TargetProcessData);
-        if (!NT_SUCCESS(Status))
-        {
-            return Status;
-        }
+        if (!NT_SUCCESS(Status)) return Status;
 
-        /* Temporary "inherit" the console from the parent */
+        /* Temporary save the parent's console */
         TargetProcessData->ParentConsole = SourceProcessData->Console;
     }
-    else
-    {
-        DPRINT1("ConSrvNewProcess - We don't launch a Console process : SourceProcessData->Console = 0x%p ; TargetProcess->Flags = %lu\n", SourceProcessData->Console, TargetProcess->Flags);
-    }
 
     return STATUS_SUCCESS;
 }
@@ -593,8 +655,6 @@ ConSrvConnect(IN PCSR_PROCESS CsrProcess,
     PCONSOLE_CONNECTION_INFO ConnectInfo = (PCONSOLE_CONNECTION_INFO)ConnectionInfo;
     PCONSOLE_PROCESS_DATA ProcessData = ConsoleGetPerProcessData(CsrProcess);
 
-    DPRINT1("ConSrvConnect\n");
-
     if ( ConnectionInfo       == NULL ||
          ConnectionInfoLength == NULL ||
         *ConnectionInfoLength != sizeof(CONSOLE_CONNECTION_INFO) )
@@ -606,7 +666,6 @@ ConSrvConnect(IN PCSR_PROCESS CsrProcess,
     /* 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("ConSrvConnect - No console needed\n");
         return STATUS_SUCCESS;
     }
 
@@ -630,11 +689,11 @@ ConSrvConnect(IN PCSR_PROCESS CsrProcess,
 
         /* Initialize a new Console owned by the Console Leader Process */
         Status = ConSrvAllocateConsole(ProcessData,
-                                         &ConnectInfo->InputHandle,
-                                         &ConnectInfo->OutputHandle,
-                                         &ConnectInfo->ErrorHandle,
-                                         ConnectInfo->ShowCmd,
-                                         CsrProcess);
+                                       ConnectInfo->AppPath,
+                                       &ConnectInfo->InputHandle,
+                                       &ConnectInfo->OutputHandle,
+                                       &ConnectInfo->ErrorHandle,
+                                       &ConnectInfo->ConsoleStartInfo);
         if (!NT_SUCCESS(Status))
         {
             DPRINT1("Console allocation failed\n");
@@ -646,27 +705,17 @@ ConSrvConnect(IN PCSR_PROCESS CsrProcess,
         DPRINT1("ConSrvConnect - Reuse current (parent's) console\n");
 
         /* Reuse our current console */
-        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);
-
-    /// TODO: Move this up ?
-    /* Duplicate the 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);
-        ConSrvRemoveConsole(ProcessData);
-        return Status;
+        Status = ConSrvInheritConsole(ProcessData,
+                                      ConnectInfo->Console,
+                                      FALSE,
+                                      NULL,  // &ConnectInfo->InputHandle,
+                                      NULL,  // &ConnectInfo->OutputHandle,
+                                      NULL); // &ConnectInfo->ErrorHandle);
+        if (!NT_SUCCESS(Status))
+        {
+            DPRINT1("Console inheritance failed\n");
+            return Status;
+        }
     }
 
     /* Return it to the caller */
@@ -675,15 +724,17 @@ ConSrvConnect(IN PCSR_PROCESS CsrProcess,
     /* 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("CONSRV: CtrlDispatcher address: %x\n", ProcessData->CtrlDispatcher);
 
     return STATUS_SUCCESS;
 }
 
 VOID
-WINAPI
+NTAPI
 ConSrvDisconnect(PCSR_PROCESS Process)
 {
     PCONSOLE_PROCESS_DATA ProcessData = ConsoleGetPerProcessData(Process);
@@ -692,7 +743,8 @@ ConSrvDisconnect(PCSR_PROCESS Process)
      * This function is called whenever a new process (GUI or CUI) is destroyed.
      **************************************************************************/
 
-    DPRINT1("ConSrvDisconnect called\n");
+    DPRINT1("ConSrvDisconnect\n");
+
     if ( ProcessData->Console     != NULL ||
          ProcessData->HandleTable != NULL )
     {
@@ -727,7 +779,7 @@ CSR_API(SrvVerifyConsoleIoHandle)
         Index >= ProcessData->HandleTableSize ||
         ProcessData->HandleTable[Index].Object == NULL)
     {
-        DPRINT("CsrVerifyObject failed\n");
+        DPRINT("SrvVerifyConsoleIoHandle failed\n");
         Status = STATUS_INVALID_HANDLE;
     }
 
@@ -774,11 +826,11 @@ CSR_API(SrvDuplicateHandle)
     }
 
     ApiMessage->Status = ConSrvInsertObject(ProcessData,
-                                              &DuplicateHandleRequest->ConsoleHandle, // Use the new handle value!
-                                              Entry->Object,
-                                              DesiredAccess,
-                                              DuplicateHandleRequest->Inheritable,
-                                              Entry->ShareMode);
+                                            &DuplicateHandleRequest->ConsoleHandle, // Use the new handle value!
+                                            Entry->Object,
+                                            DesiredAccess,
+                                            DuplicateHandleRequest->Inheritable,
+                                            Entry->ShareMode);
     if (NT_SUCCESS(ApiMessage->Status) &&
         DuplicateHandleRequest->Options & DUPLICATE_CLOSE_SOURCE)
     {
@@ -789,16 +841,4 @@ CSR_API(SrvDuplicateHandle)
     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 */