+ if (LockConsole) EnterCriticalSection(&ProcessConsole->Lock);
+
+ *Console = ProcessConsole;
+
+ return STATUS_SUCCESS;
+}
+
+VOID FASTCALL
+ConSrvReleaseConsole(PCONSOLE Console,
+ BOOL IsConsoleLocked)
+{
+ if (IsConsoleLocked) LeaveCriticalSection(&Console->Lock);
+
+ /* Decrement reference count */
+ if (_InterlockedDecrement(&Console->ReferenceCount) == 0)
+ ConSrvDeleteConsole(Console);
+}
+
+NTSTATUS
+NTAPI
+ConSrvNewProcess(PCSR_PROCESS SourceProcess,
+ PCSR_PROCESS TargetProcess)
+{
+ /**************************************************************************
+ * This function is called whenever a new process (GUI or CUI) is created.
+ *
+ * Copy the parent's handles table here if both the parent and the child
+ * processes are CUI. If we must actually create our proper console (and
+ * thus do not inherit from the console handles of the parent's), then we
+ * will clean this table in the next ConSrvConnect call. Why we are doing
+ * this? It's because here, we still don't know whether or not we must create
+ * a new console instead of inherit it from the parent, and, because in
+ * ConSrvConnect we don't have any reference to the parent process anymore.
+ **************************************************************************/
+
+ PCONSOLE_PROCESS_DATA SourceProcessData, TargetProcessData;
+
+ /* An empty target process is invalid */
+ if (!TargetProcess) return STATUS_INVALID_PARAMETER;
+
+ TargetProcessData = ConsoleGetPerProcessData(TargetProcess);
+
+ /**** HACK !!!! ****/ RtlZeroMemory(TargetProcessData, sizeof(*TargetProcessData));
+
+ /* Initialize the new (target) process */
+ TargetProcessData->Process = TargetProcess;
+ TargetProcessData->ConsoleEvent = NULL;
+ TargetProcessData->Console = TargetProcessData->ParentConsole = NULL;
+ TargetProcessData->ConsoleApp = ((TargetProcess->Flags & CsrProcessIsConsoleApp) ? TRUE : FALSE);
+
+ // Testing
+ TargetProcessData->HandleTableSize = 0;
+ TargetProcessData->HandleTable = NULL;
+
+ RtlInitializeCriticalSection(&TargetProcessData->HandleTableLock);
+
+ /* Do nothing if the source process is NULL */
+ if (!SourceProcess) return STATUS_SUCCESS;
+
+ SourceProcessData = ConsoleGetPerProcessData(SourceProcess);
+
+ /*
+ * If both of the processes (parent and new child) are console applications,
+ * then try to inherit handles from the parent process.
+ */
+ if ( SourceProcessData->Console != NULL && /* SourceProcessData->ConsoleApp */
+ TargetProcessData->ConsoleApp )
+ {
+ NTSTATUS Status;
+
+ Status = ConSrvInheritHandlesTable(SourceProcessData, TargetProcessData);
+ if (!NT_SUCCESS(Status)) return Status;
+
+ /* Temporary save the parent's console */
+ TargetProcessData->ParentConsole = SourceProcessData->Console;
+ }
+
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS
+NTAPI
+ConSrvConnect(IN PCSR_PROCESS CsrProcess,
+ IN OUT PVOID ConnectionInfo,
+ IN OUT PULONG ConnectionInfoLength)
+{
+ /**************************************************************************
+ * This function is called whenever a CUI new process is created.
+ **************************************************************************/
+
+ NTSTATUS Status = STATUS_SUCCESS;
+ PCONSOLE_CONNECTION_INFO ConnectInfo = (PCONSOLE_CONNECTION_INFO)ConnectionInfo;
+ PCONSOLE_PROCESS_DATA ProcessData = ConsoleGetPerProcessData(CsrProcess);
+
+ if ( ConnectionInfo == NULL ||
+ ConnectionInfoLength == NULL ||
+ *ConnectionInfoLength != sizeof(CONSOLE_CONNECTION_INFO) )
+ {
+ DPRINT1("CONSRV: Connection failed\n");
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ /* If we don't need a console, then get out of here */
+ if (!ConnectInfo->ConsoleNeeded || !ProcessData->ConsoleApp) // In fact, it is for GUI apps.
+ {
+ return STATUS_SUCCESS;
+ }
+
+ /* If we don't have a console, then create a new one... */
+ if (!ConnectInfo->Console ||
+ ConnectInfo->Console != ProcessData->ParentConsole)
+ {
+ DPRINT1("ConSrvConnect - Allocate a new console\n");
+
+ /*
+ * We are about to create a new console. However when ConSrvNewProcess
+ * 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.
+ */
+ ConSrvRemoveConsole(ProcessData);
+
+ /* Initialize a new Console owned by the Console Leader Process */
+ Status = ConSrvAllocateConsole(ProcessData,
+ ConnectInfo->AppPath,
+ &ConnectInfo->InputHandle,
+ &ConnectInfo->OutputHandle,
+ &ConnectInfo->ErrorHandle,
+ &ConnectInfo->ConsoleStartInfo);
+ if (!NT_SUCCESS(Status))