From 78aaee0a8bb3fd51ba62396dc4992dd12b2b274f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A9=20van=20Geldorp?= Date: Thu, 18 Dec 2003 09:51:08 +0000 Subject: [PATCH] Allow launching of console apps from GUI apps svn path=/trunk/; revision=7107 --- reactos/include/csrss/csrss.h | 2 + reactos/lib/kernel32/misc/console.c | 3 +- reactos/lib/kernel32/process/create.c | 212 ++++++++++++++------- reactos/subsys/csrss/api/process.c | 4 +- reactos/subsys/csrss/win32csr/conio.c | 3 +- reactos/subsys/csrss/win32csr/guiconsole.c | 9 +- reactos/subsys/system/cmd/cmd.c | 5 +- reactos/subsys/system/winlogon/winlogon.c | 4 +- 8 files changed, 166 insertions(+), 76 deletions(-) diff --git a/reactos/include/csrss/csrss.h b/reactos/include/csrss/csrss.h index d552a497134..8c03f679df6 100644 --- a/reactos/include/csrss/csrss.h +++ b/reactos/include/csrss/csrss.h @@ -32,6 +32,7 @@ typedef struct typedef struct { + HANDLE Console; HANDLE InputHandle; HANDLE OutputHandle; } CSRSS_CREATE_PROCESS_REPLY, *PCSRSS_CREATE_PROCESS_REPLY; @@ -77,6 +78,7 @@ typedef struct typedef struct { + HANDLE Console; HANDLE InputHandle; HANDLE OutputHandle; } CSRSS_ALLOC_CONSOLE_REPLY, *PCSRSS_ALLOC_CONSOLE_REPLY; diff --git a/reactos/lib/kernel32/misc/console.c b/reactos/lib/kernel32/misc/console.c index b7e6c1dc236..76db717c71c 100644 --- a/reactos/lib/kernel32/misc/console.c +++ b/reactos/lib/kernel32/misc/console.c @@ -1,4 +1,4 @@ -/* $Id: console.c,v 1.70 2003/12/02 11:38:46 gvg Exp $ +/* $Id: console.c,v 1.71 2003/12/18 09:51:08 gvg Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS system libraries @@ -1253,6 +1253,7 @@ WINBOOL STDCALL AllocConsole(VOID) SetLastErrorByStatus ( Status ); return FALSE; } + NtCurrentPeb()->ProcessParameters->hConsole = Reply.Data.AllocConsoleReply.Console; SetStdHandle( STD_INPUT_HANDLE, Reply.Data.AllocConsoleReply.InputHandle ); SetStdHandle( STD_OUTPUT_HANDLE, Reply.Data.AllocConsoleReply.OutputHandle ); hStdError = DuplicateConsoleHandle(Reply.Data.AllocConsoleReply.OutputHandle, diff --git a/reactos/lib/kernel32/process/create.c b/reactos/lib/kernel32/process/create.c index 8089925825a..8e6779a561d 100644 --- a/reactos/lib/kernel32/process/create.c +++ b/reactos/lib/kernel32/process/create.c @@ -1,4 +1,4 @@ -/* $Id: create.c,v 1.72 2003/10/31 16:27:01 navaraf Exp $ +/* $Id: create.c,v 1.73 2003/12/18 09:51:08 gvg Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS system libraries @@ -712,6 +712,8 @@ CreateProcessW WCHAR TempCommandLineNameW[256]; UNICODE_STRING RuntimeInfo_U; PVOID ImageBaseAddress; + BOOL InputSet, OutputSet, ErrorSet; + BOOL InputDup, OutputDup, ErrorDup; DPRINT("CreateProcessW(lpApplicationName '%S', lpCommandLine '%S')\n", lpApplicationName, lpCommandLine); @@ -1044,11 +1046,18 @@ CreateProcessW CsrRequest.Data.CreateProcessRequest.NewProcessId = ProcessBasicInfo.UniqueProcessId; if (Sii.Subsystem == IMAGE_SUBSYSTEM_WINDOWS_GUI) - { - /* Do not create a console for GUI applications */ - dwCreationFlags &= ~CREATE_NEW_CONSOLE; - dwCreationFlags |= DETACHED_PROCESS; - } + { + /* Do not create a console for GUI applications */ + dwCreationFlags &= ~CREATE_NEW_CONSOLE; + dwCreationFlags |= DETACHED_PROCESS; + } + else if (Sii.Subsystem == IMAGE_SUBSYSTEM_WINDOWS_CUI) + { + if (NULL == Ppb->hConsole) + { + dwCreationFlags |= CREATE_NEW_CONSOLE; + } + } CsrRequest.Data.CreateProcessRequest.Flags = dwCreationFlags; CsrRequest.Data.CreateProcessRequest.CtrlDispatcher = ConsoleControlDispatcher; Status = CsrClientCallServer(&CsrRequest, @@ -1059,92 +1068,163 @@ CreateProcessW { DbgPrint("Failed to tell csrss about new process. Expect trouble.\n"); } + else if (Sii.Subsystem == IMAGE_SUBSYSTEM_WINDOWS_CUI) + { + Ppb->hConsole = CsrReply.Data.CreateProcessReply.Console; + } - // Set the child console handles - Ppb->hStdInput = NtCurrentPeb()->ProcessParameters->hStdInput; - Ppb->hStdOutput = NtCurrentPeb()->ProcessParameters->hStdOutput; - Ppb->hStdError = NtCurrentPeb()->ProcessParameters->hStdError; + InputSet = FALSE; + OutputSet = FALSE; + ErrorSet = FALSE; + /* Set the child console handles */ + + /* First check if handles were passed in startup info */ if (lpStartupInfo && (lpStartupInfo->dwFlags & STARTF_USESTDHANDLES)) { if (lpStartupInfo->hStdInput) + { Ppb->hStdInput = lpStartupInfo->hStdInput; + InputSet = TRUE; + InputDup = TRUE; + } if (lpStartupInfo->hStdOutput) + { Ppb->hStdOutput = lpStartupInfo->hStdOutput; + OutputSet = TRUE; + OutputDup = TRUE; + } if (lpStartupInfo->hStdError) + { Ppb->hStdError = lpStartupInfo->hStdError; - } - - if (IsConsoleHandle(Ppb->hStdInput)) - { - Ppb->hStdInput = CsrReply.Data.CreateProcessReply.InputHandle; - } - else - { - DPRINT("Duplicate input handle\n"); - Status = NtDuplicateObject (NtCurrentProcess(), - Ppb->hStdInput, - hProcess, - &Ppb->hStdInput, - 0, - TRUE, - DUPLICATE_SAME_ACCESS); - if(!NT_SUCCESS(Status)) - { - DPRINT("NtDuplicateObject failed, status %x\n", Status); + ErrorSet = TRUE; + ErrorDup = TRUE; } } - if (IsConsoleHandle(Ppb->hStdOutput)) + /* Check if new console was created, use it for input and output if + not overridden */ + if (0 != (dwCreationFlags & CREATE_NEW_CONSOLE) + && NT_SUCCESS(Status) && NT_SUCCESS(CsrReply.Status)) { - Ppb->hStdOutput = CsrReply.Data.CreateProcessReply.OutputHandle; - } - else - { - DPRINT("Duplicate output handle\n"); - Status = NtDuplicateObject (NtCurrentProcess(), - Ppb->hStdOutput, - hProcess, - &Ppb->hStdOutput, - 0, - TRUE, - DUPLICATE_SAME_ACCESS); - if(!NT_SUCCESS(Status)) + if (! InputSet) { - DPRINT("NtDuplicateObject failed, status %x\n", Status); + Ppb->hStdInput = CsrReply.Data.CreateProcessReply.InputHandle; + InputSet = TRUE; + InputDup = FALSE; + } + if (! OutputSet) + { + Ppb->hStdOutput = CsrReply.Data.CreateProcessReply.OutputHandle; + OutputSet = TRUE; + OutputDup = FALSE; + } + if (! ErrorSet) + { + Ppb->hStdError = CsrReply.Data.CreateProcessReply.OutputHandle; + ErrorSet = TRUE; + ErrorDup = FALSE; } } - if (IsConsoleHandle(Ppb->hStdError)) + + /* Use existing handles otherwise */ + if (! InputSet) { - CsrRequest.Type = CSRSS_DUPLICATE_HANDLE; - CsrRequest.Data.DuplicateHandleRequest.ProcessId = ProcessBasicInfo.UniqueProcessId; - CsrRequest.Data.DuplicateHandleRequest.Handle = CsrReply.Data.CreateProcessReply.OutputHandle; - Status = CsrClientCallServer(&CsrRequest, - &CsrReply, - sizeof(CSRSS_API_REQUEST), - sizeof(CSRSS_API_REPLY)); - if (!NT_SUCCESS(Status) || !NT_SUCCESS(CsrReply.Status)) + Ppb->hStdInput = NtCurrentPeb()->ProcessParameters->hStdInput; + InputDup = TRUE; + } + if (! OutputSet) + { + Ppb->hStdOutput = NtCurrentPeb()->ProcessParameters->hStdOutput; + OutputDup = TRUE; + } + if (! ErrorSet) + { + Ppb->hStdError = NtCurrentPeb()->ProcessParameters->hStdError; + ErrorDup = TRUE; + } + + /* Now duplicate handles if required */ + if (InputDup) + { + if (IsConsoleHandle(Ppb->hStdInput)) { - Ppb->hStdError = INVALID_HANDLE_VALUE; + Ppb->hStdInput = CsrReply.Data.CreateProcessReply.InputHandle; } else { - Ppb->hStdError = CsrReply.Data.DuplicateHandleReply.Handle; + DPRINT("Duplicate input handle\n"); + Status = NtDuplicateObject (NtCurrentProcess(), + Ppb->hStdInput, + hProcess, + &Ppb->hStdInput, + 0, + TRUE, + DUPLICATE_SAME_ACCESS); + if(!NT_SUCCESS(Status)) + { + DPRINT("NtDuplicateObject failed, status %x\n", Status); + } } } - else + + if (OutputDup) { - DPRINT("Duplicate error handle\n"); - Status = NtDuplicateObject (NtCurrentProcess(), - Ppb->hStdError, - hProcess, - &Ppb->hStdError, - 0, - TRUE, - DUPLICATE_SAME_ACCESS); - if(!NT_SUCCESS(Status)) + if (IsConsoleHandle(Ppb->hStdOutput)) { - DPRINT("NtDuplicateObject failed, status %x\n", Status); + Ppb->hStdOutput = CsrReply.Data.CreateProcessReply.OutputHandle; + } + else + { + DPRINT("Duplicate output handle\n"); + Status = NtDuplicateObject (NtCurrentProcess(), + Ppb->hStdOutput, + hProcess, + &Ppb->hStdOutput, + 0, + TRUE, + DUPLICATE_SAME_ACCESS); + if(!NT_SUCCESS(Status)) + { + DPRINT("NtDuplicateObject failed, status %x\n", Status); + } + } + } + + if (ErrorDup) + { + if (IsConsoleHandle(Ppb->hStdError)) + { + CsrRequest.Type = CSRSS_DUPLICATE_HANDLE; + CsrRequest.Data.DuplicateHandleRequest.ProcessId = ProcessBasicInfo.UniqueProcessId; + CsrRequest.Data.DuplicateHandleRequest.Handle = CsrReply.Data.CreateProcessReply.OutputHandle; + Status = CsrClientCallServer(&CsrRequest, + &CsrReply, + sizeof(CSRSS_API_REQUEST), + sizeof(CSRSS_API_REPLY)); + if (!NT_SUCCESS(Status) || !NT_SUCCESS(CsrReply.Status)) + { + Ppb->hStdError = INVALID_HANDLE_VALUE; + } + else + { + Ppb->hStdError = CsrReply.Data.DuplicateHandleReply.Handle; + } + } + else + { + DPRINT("Duplicate error handle\n"); + Status = NtDuplicateObject (NtCurrentProcess(), + Ppb->hStdError, + hProcess, + &Ppb->hStdError, + 0, + TRUE, + DUPLICATE_SAME_ACCESS); + if(!NT_SUCCESS(Status)) + { + DPRINT("NtDuplicateObject failed, status %x\n", Status); + } } } diff --git a/reactos/subsys/csrss/api/process.c b/reactos/subsys/csrss/api/process.c index 37635e23ffb..d15c42bcc42 100644 --- a/reactos/subsys/csrss/api/process.c +++ b/reactos/subsys/csrss/api/process.c @@ -1,4 +1,4 @@ -/* $Id: process.c,v 1.30 2003/12/02 11:38:47 gvg Exp $ +/* $Id: process.c,v 1.31 2003/12/18 09:51:08 gvg Exp $ * * reactos/subsys/csrss/api/process.c * @@ -252,6 +252,8 @@ CSR_API(CsrCreateProcess) RtlLeaveCriticalSection(&ProcessDataLock); } + Reply->Data.CreateProcessReply.Console = NewProcessData->Console; + Reply->Status = STATUS_SUCCESS; return(STATUS_SUCCESS); } diff --git a/reactos/subsys/csrss/win32csr/conio.c b/reactos/subsys/csrss/win32csr/conio.c index d97bc825ac1..27cef02a44e 100644 --- a/reactos/subsys/csrss/win32csr/conio.c +++ b/reactos/subsys/csrss/win32csr/conio.c @@ -1,4 +1,4 @@ -/* $Id: conio.c,v 1.1 2003/12/02 11:38:46 gvg Exp $ +/* $Id: conio.c,v 1.2 2003/12/18 09:51:08 gvg Exp $ * * reactos/subsys/csrss/win32csr/conio.c * @@ -314,6 +314,7 @@ CSR_API(CsrAllocConsole) return Reply->Status; } ProcessData->Console = Console; + Reply->Data.AllocConsoleReply.Console = Console; /* add a reference count because the process is tied to the console */ Console->Header.ReferenceCount++; diff --git a/reactos/subsys/csrss/win32csr/guiconsole.c b/reactos/subsys/csrss/win32csr/guiconsole.c index 07a23594fec..98d210dc083 100644 --- a/reactos/subsys/csrss/win32csr/guiconsole.c +++ b/reactos/subsys/csrss/win32csr/guiconsole.c @@ -1,4 +1,4 @@ -/* $Id: guiconsole.c,v 1.3 2003/12/07 23:02:57 gvg Exp $ +/* $Id: guiconsole.c,v 1.4 2003/12/18 09:51:08 gvg Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS system libraries @@ -482,6 +482,7 @@ GuiConsoleNotifyWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) NULL, (HINSTANCE) GetModuleHandleW(NULL), (PVOID) Console); +Console->hWindow = NewWindow; if (NULL != NewWindow) { SetWindowLongW(hWnd, GWL_USERDATA, GetWindowLongW(hWnd, GWL_USERDATA) + 1); @@ -645,9 +646,15 @@ GuiConsoleInitConsole(PCSRSS_CONSOLE Console) { Console->Size.X = 80; Console->Size.Y = 25; +#ifdef TODO Console->hWindow = (HWND) SendMessageW(NotifyWnd, PM_CREATE_CONSOLE, 0, (LPARAM) Console); return NULL != Console->hWindow; +#else + PostMessageW(NotifyWnd, PM_CREATE_CONSOLE, 0, (LPARAM) Console); + + return TRUE; +#endif } VOID STDCALL diff --git a/reactos/subsys/system/cmd/cmd.c b/reactos/subsys/system/cmd/cmd.c index f1816450c26..c72d919f443 100644 --- a/reactos/subsys/system/cmd/cmd.c +++ b/reactos/subsys/system/cmd/cmd.c @@ -1,4 +1,4 @@ -/* $Id: cmd.c,v 1.7 2003/08/18 11:55:43 hbirr Exp $ +/* $Id: cmd.c,v 1.8 2003/12/18 09:51:08 gvg Exp $ * * CMD.C - command-line interface. * @@ -1228,9 +1228,6 @@ int main (int argc, char *argv[]) SetFileApisToOEM(); - AllocConsole(); - - hConsole = CreateFile(_T("CONOUT$"), GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); diff --git a/reactos/subsys/system/winlogon/winlogon.c b/reactos/subsys/system/winlogon/winlogon.c index ce9818905e6..0d22fafe80c 100644 --- a/reactos/subsys/system/winlogon/winlogon.c +++ b/reactos/subsys/system/winlogon/winlogon.c @@ -1,4 +1,4 @@ -/* $Id: winlogon.c,v 1.22 2003/12/07 00:04:20 weiden Exp $ +/* $Id: winlogon.c,v 1.23 2003/12/18 09:51:08 gvg Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -372,7 +372,7 @@ static BOOL DoLoginUser(PWCHAR Name, PWCHAR Password) NULL, NULL, FALSE, - DETACHED_PROCESS, + CREATE_NEW_CONSOLE, NULL, CurrentDirectory, &StartupInfo,