[CONSRV]: Use NtDuplicateObject with DUPLICATE_CLOSE_SOURCE to close a duplicated...
[reactos.git] / reactos / win32ss / user / winsrv / consrv / handle.c
index 9a435bb..125dfab 100644 (file)
@@ -494,10 +494,14 @@ ConSrvAllocateConsole(PCONSOLE_PROCESS_DATA ProcessData,
     ConSrvFreeHandlesTable(ProcessData);
 
     /* Initialize a new Console owned by this process */
+    DPRINT("Initialization of console '%S' for process '%S' on desktop '%S'\n",
+           ConsoleInitInfo->ConsoleTitle ? ConsoleInitInfo->ConsoleTitle : L"n/a",
+           ConsoleInitInfo->AppName ? ConsoleInitInfo->AppName : L"n/a",
+           ConsoleInitInfo->Desktop ? ConsoleInitInfo->Desktop : L"n/a");
     Status = ConSrvInitConsole(&ConsoleHandle,
                                &Console,
                                ConsoleInitInfo,
-                               HandleToUlong(ProcessData->Process->ClientId.UniqueProcess));
+                               ProcessData->Process);
     if (!NT_SUCCESS(Status))
     {
         DPRINT1("Console initialization failed\n");
@@ -544,7 +548,9 @@ ConSrvAllocateConsole(PCONSOLE_PROCESS_DATA ProcessData,
     if (!NT_SUCCESS(Status))
     {
         DPRINT1("NtDuplicateObject(InitEvents[INIT_FAILURE]) failed: %lu\n", Status);
-        NtClose(ConsoleInitInfo->ConsoleStartInfo->InitEvents[INIT_SUCCESS]);
+        NtDuplicateObject(ProcessData->Process->ProcessHandle,
+                          ConsoleInitInfo->ConsoleStartInfo->InitEvents[INIT_SUCCESS],
+                          NULL, NULL, 0, 0, DUPLICATE_CLOSE_SOURCE);
         ConSrvFreeHandlesTable(ProcessData);
         ConSrvDeleteConsole(Console);
         ProcessData->ConsoleHandle = NULL;
@@ -555,21 +561,36 @@ ConSrvAllocateConsole(PCONSOLE_PROCESS_DATA ProcessData,
     Status = NtDuplicateObject(NtCurrentProcess(),
                                Console->InputBuffer.ActiveEvent,
                                ProcessData->Process->ProcessHandle,
-                               &ProcessData->InputWaitHandle,
+                               &ConsoleInitInfo->ConsoleStartInfo->InputWaitHandle,
                                EVENT_ALL_ACCESS, 0, 0);
     if (!NT_SUCCESS(Status))
     {
         DPRINT1("NtDuplicateObject(InputWaitHandle) failed: %lu\n", Status);
-        NtClose(ConsoleInitInfo->ConsoleStartInfo->InitEvents[INIT_FAILURE]);
-        NtClose(ConsoleInitInfo->ConsoleStartInfo->InitEvents[INIT_SUCCESS]);
+        NtDuplicateObject(ProcessData->Process->ProcessHandle,
+                          ConsoleInitInfo->ConsoleStartInfo->InitEvents[INIT_FAILURE],
+                          NULL, NULL, 0, 0, DUPLICATE_CLOSE_SOURCE);
+        NtDuplicateObject(ProcessData->Process->ProcessHandle,
+                          ConsoleInitInfo->ConsoleStartInfo->InitEvents[INIT_SUCCESS],
+                          NULL, NULL, 0, 0, DUPLICATE_CLOSE_SOURCE);
         ConSrvFreeHandlesTable(ProcessData);
         ConSrvDeleteConsole(Console);
         ProcessData->ConsoleHandle = NULL;
         return Status;
     }
 
-    /* Insert the process into the processes list of the console */
+    /* Mark the process as having a console */
+    ProcessData->ConsoleApp = TRUE;
+    ProcessData->Process->Flags |= CsrProcessIsConsoleApp;
+
+    /* Return the console handle to the caller */
+    ConsoleInitInfo->ConsoleStartInfo->ConsoleHandle = ProcessData->ConsoleHandle;
+
+    /*
+     * Insert the process into the processes list of the console,
+     * and set its foreground priority.
+     */
     InsertHeadList(&Console->ProcessList, &ProcessData->ConsoleLink);
+    ConSrvSetProcessFocus(ProcessData->Process, Console->HasFocus);
 
     /* Add a reference count because the process is tied to the console */
     _InterlockedIncrement(&Console->ReferenceCount);
@@ -654,7 +675,9 @@ ConSrvInheritConsole(PCONSOLE_PROCESS_DATA ProcessData,
     if (!NT_SUCCESS(Status))
     {
         DPRINT1("NtDuplicateObject(InitEvents[INIT_FAILURE]) failed: %lu\n", Status);
-        NtClose(ConsoleStartInfo->InitEvents[INIT_SUCCESS]);
+        NtDuplicateObject(ProcessData->Process->ProcessHandle,
+                          ConsoleStartInfo->InitEvents[INIT_SUCCESS],
+                          NULL, NULL, 0, 0, DUPLICATE_CLOSE_SOURCE);
         ConSrvFreeHandlesTable(ProcessData);
         ProcessData->ConsoleHandle = NULL;
         goto Quit;
@@ -664,20 +687,35 @@ ConSrvInheritConsole(PCONSOLE_PROCESS_DATA ProcessData,
     Status = NtDuplicateObject(NtCurrentProcess(),
                                Console->InputBuffer.ActiveEvent,
                                ProcessData->Process->ProcessHandle,
-                               &ProcessData->InputWaitHandle,
+                               &ConsoleStartInfo->InputWaitHandle,
                                EVENT_ALL_ACCESS, 0, 0);
     if (!NT_SUCCESS(Status))
     {
         DPRINT1("NtDuplicateObject(InputWaitHandle) failed: %lu\n", Status);
-        NtClose(ConsoleStartInfo->InitEvents[INIT_FAILURE]);
-        NtClose(ConsoleStartInfo->InitEvents[INIT_SUCCESS]);
+        NtDuplicateObject(ProcessData->Process->ProcessHandle,
+                          ConsoleStartInfo->InitEvents[INIT_FAILURE],
+                          NULL, NULL, 0, 0, DUPLICATE_CLOSE_SOURCE);
+        NtDuplicateObject(ProcessData->Process->ProcessHandle,
+                          ConsoleStartInfo->InitEvents[INIT_SUCCESS],
+                          NULL, NULL, 0, 0, DUPLICATE_CLOSE_SOURCE);
         ConSrvFreeHandlesTable(ProcessData); // NOTE: Always free the handles table.
         ProcessData->ConsoleHandle = NULL;
         goto Quit;
     }
 
-    /* Insert the process into the processes list of the console */
+    /* Mark the process as having a console */
+    ProcessData->ConsoleApp = TRUE;
+    ProcessData->Process->Flags |= CsrProcessIsConsoleApp;
+
+    /* Return the console handle to the caller */
+    ConsoleStartInfo->ConsoleHandle = ProcessData->ConsoleHandle;
+
+    /*
+     * Insert the process into the processes list of the console,
+     * and set its foreground priority.
+     */
     InsertHeadList(&Console->ProcessList, &ProcessData->ConsoleLink);
+    ConSrvSetProcessFocus(ProcessData->Process, Console->HasFocus);
 
     /* Add a reference count because the process is tied to the console */
     _InterlockedIncrement(&Console->ReferenceCount);
@@ -693,74 +731,78 @@ Quit:
     return Status;
 }
 
-VOID
+NTSTATUS
 ConSrvRemoveConsole(PCONSOLE_PROCESS_DATA ProcessData)
 {
     PCONSOLE Console;
+    PCONSOLE_PROCESS_DATA ConsoleLeaderProcess;
 
     DPRINT("ConSrvRemoveConsole\n");
 
-    // RtlEnterCriticalSection(&ProcessData->HandleTableLock);
+    /* Mark the process as not having a console anymore */
+    ProcessData->ConsoleApp = FALSE;
+    ProcessData->Process->Flags &= ~CsrProcessIsConsoleApp;
 
     /* Validate and lock the console */
-    if (ConSrvValidateConsole(&Console,
-                              ProcessData->ConsoleHandle,
-                              CONSOLE_RUNNING, TRUE))
+    if (!ConSrvValidateConsole(&Console,
+                               ProcessData->ConsoleHandle,
+                               CONSOLE_RUNNING, TRUE))
     {
-        /* Retrieve the console leader process */
-        PCONSOLE_PROCESS_DATA ConsoleLeaderProcess = ConSrvGetConsoleLeaderProcess(Console);
+        // FIXME: Find another status code
+        return STATUS_UNSUCCESSFUL;
+    }
 
-        DPRINT("ConSrvRemoveConsole - Locking OK\n");
+    DPRINT("ConSrvRemoveConsole - Locking OK\n");
 
-        /* Close all console handles and free the handles table */
-        ConSrvFreeHandlesTable(ProcessData);
+    /* Retrieve the console leader process */
+    ConsoleLeaderProcess = ConSrvGetConsoleLeaderProcess(Console);
 
-        /* Detach the process from the console */
-        ProcessData->ConsoleHandle = NULL;
+    /* Close all console handles and free the handles table */
+    ConSrvFreeHandlesTable(ProcessData);
 
-        /* Remove the process from the console's list of processes */
-        RemoveEntryList(&ProcessData->ConsoleLink);
+    /* Detach the process from the console */
+    ProcessData->ConsoleHandle = NULL;
 
-        /* Check whether the console should send a last close notification */
-        if (Console->NotifyLastClose)
+    /* Remove the process from the console's list of processes */
+    RemoveEntryList(&ProcessData->ConsoleLink);
+
+    /* Check whether the console should send a last close notification */
+    if (Console->NotifyLastClose)
+    {
+        /* If we are removing the process which wants the last close notification... */
+        if (ProcessData == Console->NotifiedLastCloseProcess)
+        {
+            /* ... just reset the flag and the pointer... */
+            Console->NotifyLastClose = FALSE;
+            Console->NotifiedLastCloseProcess = NULL;
+        }
+        /*
+         * ... otherwise, if we are removing the console leader process
+         * (that cannot be the process wanting the notification, because
+         * the previous case already dealt with it)...
+         */
+        else if (ProcessData == ConsoleLeaderProcess)
         {
-            /* If we are removing the process which wants the last close notification... */
-            if (ProcessData == Console->NotifiedLastCloseProcess)
-            {
-                /* ... just reset the flag and the pointer... */
-                Console->NotifyLastClose = FALSE;
-                Console->NotifiedLastCloseProcess = NULL;
-            }
             /*
-             * ... otherwise, if we are removing the console leader process
-             * (that cannot be the process wanting the notification, because
-             * the previous case already dealt with it)...
+             * ... reset the flag first (so that we avoid multiple notifications)
+             * and then send the last close notification.
              */
-            else if (ProcessData == ConsoleLeaderProcess)
-            {
-                /*
-                 * ... reset the flag first (so that we avoid multiple notifications)
-                 * and then send the last close notification.
-                 */
-                Console->NotifyLastClose = FALSE;
-                ConSrvConsoleCtrlEvent(CTRL_LAST_CLOSE_EVENT, Console->NotifiedLastCloseProcess);
-
-                /* Only now, reset the pointer */
-                Console->NotifiedLastCloseProcess = NULL;
-            }
+            Console->NotifyLastClose = FALSE;
+            ConSrvConsoleCtrlEvent(CTRL_LAST_CLOSE_EVENT, Console->NotifiedLastCloseProcess);
+
+            /* Only now, reset the pointer */
+            Console->NotifiedLastCloseProcess = NULL;
         }
+    }
 
-        /* Update the internal info of the terminal */
-        TermRefreshInternalInfo(Console);
+    /* Update the internal info of the terminal */
+    TermRefreshInternalInfo(Console);
 
-        /* Release the console */
-        DPRINT("ConSrvRemoveConsole - Decrement Console->ReferenceCount = %lu\n", Console->ReferenceCount);
-        ConSrvReleaseConsole(Console, TRUE);
-        //CloseHandle(ProcessData->InputWaitHandle);
-        //ProcessData->InputWaitHandle = NULL;
-    }
+    /* Release the console */
+    DPRINT("ConSrvRemoveConsole - Decrement Console->ReferenceCount = %lu\n", Console->ReferenceCount);
+    ConSrvReleaseConsole(Console, TRUE);
 
-    // RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
+    return STATUS_SUCCESS;
 }
 
 
@@ -787,7 +829,7 @@ CSR_API(SrvOpenConsole)
     Status = ConSrvGetConsole(ProcessData, &Console, TRUE);
     if (!NT_SUCCESS(Status))
     {
-        DPRINT1("Can't get console\n");
+        DPRINT1("Can't get console, status %lx\n", Status);
         return Status;
     }
 
@@ -846,7 +888,7 @@ CSR_API(SrvDuplicateHandle)
     Status = ConSrvGetConsole(ProcessData, &Console, TRUE);
     if (!NT_SUCCESS(Status))
     {
-        DPRINT1("Can't get console\n");
+        DPRINT1("Can't get console, status %lx\n", Status);
         return Status;
     }
 
@@ -916,7 +958,7 @@ CSR_API(SrvGetHandleInformation)
     Status = ConSrvGetConsole(ProcessData, &Console, TRUE);
     if (!NT_SUCCESS(Status))
     {
-        DPRINT1("Can't get console\n");
+        DPRINT1("Can't get console, status %lx\n", Status);
         return Status;
     }
 
@@ -964,7 +1006,7 @@ CSR_API(SrvSetHandleInformation)
     Status = ConSrvGetConsole(ProcessData, &Console, TRUE);
     if (!NT_SUCCESS(Status))
     {
-        DPRINT1("Can't get console\n");
+        DPRINT1("Can't get console, status %lx\n", Status);
         return Status;
     }
 
@@ -1010,7 +1052,7 @@ CSR_API(SrvCloseHandle)
     Status = ConSrvGetConsole(ProcessData, &Console, TRUE);
     if (!NT_SUCCESS(Status))
     {
-        DPRINT1("Can't get console\n");
+        DPRINT1("Can't get console, status %lx\n", Status);
         return Status;
     }
 
@@ -1035,7 +1077,7 @@ CSR_API(SrvVerifyConsoleIoHandle)
     Status = ConSrvGetConsole(ProcessData, &Console, TRUE);
     if (!NT_SUCCESS(Status))
     {
-        DPRINT1("Can't get console\n");
+        DPRINT1("Can't get console, status %lx\n", Status);
         return Status;
     }