Allow launching of console apps from GUI apps

svn path=/trunk/; revision=7107
This commit is contained in:
Gé van Geldorp 2003-12-18 09:51:08 +00:00
parent 41b4cb6b5a
commit 78aaee0a8b
8 changed files with 166 additions and 76 deletions

View file

@ -32,6 +32,7 @@ typedef struct
typedef struct typedef struct
{ {
HANDLE Console;
HANDLE InputHandle; HANDLE InputHandle;
HANDLE OutputHandle; HANDLE OutputHandle;
} CSRSS_CREATE_PROCESS_REPLY, *PCSRSS_CREATE_PROCESS_REPLY; } CSRSS_CREATE_PROCESS_REPLY, *PCSRSS_CREATE_PROCESS_REPLY;
@ -77,6 +78,7 @@ typedef struct
typedef struct typedef struct
{ {
HANDLE Console;
HANDLE InputHandle; HANDLE InputHandle;
HANDLE OutputHandle; HANDLE OutputHandle;
} CSRSS_ALLOC_CONSOLE_REPLY, *PCSRSS_ALLOC_CONSOLE_REPLY; } CSRSS_ALLOC_CONSOLE_REPLY, *PCSRSS_ALLOC_CONSOLE_REPLY;

View file

@ -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 * COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS system libraries * PROJECT: ReactOS system libraries
@ -1253,6 +1253,7 @@ WINBOOL STDCALL AllocConsole(VOID)
SetLastErrorByStatus ( Status ); SetLastErrorByStatus ( Status );
return FALSE; return FALSE;
} }
NtCurrentPeb()->ProcessParameters->hConsole = Reply.Data.AllocConsoleReply.Console;
SetStdHandle( STD_INPUT_HANDLE, Reply.Data.AllocConsoleReply.InputHandle ); SetStdHandle( STD_INPUT_HANDLE, Reply.Data.AllocConsoleReply.InputHandle );
SetStdHandle( STD_OUTPUT_HANDLE, Reply.Data.AllocConsoleReply.OutputHandle ); SetStdHandle( STD_OUTPUT_HANDLE, Reply.Data.AllocConsoleReply.OutputHandle );
hStdError = DuplicateConsoleHandle(Reply.Data.AllocConsoleReply.OutputHandle, hStdError = DuplicateConsoleHandle(Reply.Data.AllocConsoleReply.OutputHandle,

View file

@ -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 * COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS system libraries * PROJECT: ReactOS system libraries
@ -712,6 +712,8 @@ CreateProcessW
WCHAR TempCommandLineNameW[256]; WCHAR TempCommandLineNameW[256];
UNICODE_STRING RuntimeInfo_U; UNICODE_STRING RuntimeInfo_U;
PVOID ImageBaseAddress; PVOID ImageBaseAddress;
BOOL InputSet, OutputSet, ErrorSet;
BOOL InputDup, OutputDup, ErrorDup;
DPRINT("CreateProcessW(lpApplicationName '%S', lpCommandLine '%S')\n", DPRINT("CreateProcessW(lpApplicationName '%S', lpCommandLine '%S')\n",
lpApplicationName, lpCommandLine); lpApplicationName, lpCommandLine);
@ -1044,11 +1046,18 @@ CreateProcessW
CsrRequest.Data.CreateProcessRequest.NewProcessId = CsrRequest.Data.CreateProcessRequest.NewProcessId =
ProcessBasicInfo.UniqueProcessId; ProcessBasicInfo.UniqueProcessId;
if (Sii.Subsystem == IMAGE_SUBSYSTEM_WINDOWS_GUI) if (Sii.Subsystem == IMAGE_SUBSYSTEM_WINDOWS_GUI)
{ {
/* Do not create a console for GUI applications */ /* Do not create a console for GUI applications */
dwCreationFlags &= ~CREATE_NEW_CONSOLE; dwCreationFlags &= ~CREATE_NEW_CONSOLE;
dwCreationFlags |= DETACHED_PROCESS; 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.Flags = dwCreationFlags;
CsrRequest.Data.CreateProcessRequest.CtrlDispatcher = ConsoleControlDispatcher; CsrRequest.Data.CreateProcessRequest.CtrlDispatcher = ConsoleControlDispatcher;
Status = CsrClientCallServer(&CsrRequest, Status = CsrClientCallServer(&CsrRequest,
@ -1059,92 +1068,163 @@ CreateProcessW
{ {
DbgPrint("Failed to tell csrss about new process. Expect trouble.\n"); 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 InputSet = FALSE;
Ppb->hStdInput = NtCurrentPeb()->ProcessParameters->hStdInput; OutputSet = FALSE;
Ppb->hStdOutput = NtCurrentPeb()->ProcessParameters->hStdOutput; ErrorSet = FALSE;
Ppb->hStdError = NtCurrentPeb()->ProcessParameters->hStdError;
/* Set the child console handles */
/* First check if handles were passed in startup info */
if (lpStartupInfo && (lpStartupInfo->dwFlags & STARTF_USESTDHANDLES)) if (lpStartupInfo && (lpStartupInfo->dwFlags & STARTF_USESTDHANDLES))
{ {
if (lpStartupInfo->hStdInput) if (lpStartupInfo->hStdInput)
{
Ppb->hStdInput = lpStartupInfo->hStdInput; Ppb->hStdInput = lpStartupInfo->hStdInput;
InputSet = TRUE;
InputDup = TRUE;
}
if (lpStartupInfo->hStdOutput) if (lpStartupInfo->hStdOutput)
{
Ppb->hStdOutput = lpStartupInfo->hStdOutput; Ppb->hStdOutput = lpStartupInfo->hStdOutput;
OutputSet = TRUE;
OutputDup = TRUE;
}
if (lpStartupInfo->hStdError) if (lpStartupInfo->hStdError)
{
Ppb->hStdError = lpStartupInfo->hStdError; Ppb->hStdError = lpStartupInfo->hStdError;
} ErrorSet = TRUE;
ErrorDup = TRUE;
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);
} }
} }
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; if (! InputSet)
}
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); 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; Ppb->hStdInput = NtCurrentPeb()->ProcessParameters->hStdInput;
CsrRequest.Data.DuplicateHandleRequest.ProcessId = ProcessBasicInfo.UniqueProcessId; InputDup = TRUE;
CsrRequest.Data.DuplicateHandleRequest.Handle = CsrReply.Data.CreateProcessReply.OutputHandle; }
Status = CsrClientCallServer(&CsrRequest, if (! OutputSet)
&CsrReply, {
sizeof(CSRSS_API_REQUEST), Ppb->hStdOutput = NtCurrentPeb()->ProcessParameters->hStdOutput;
sizeof(CSRSS_API_REPLY)); OutputDup = TRUE;
if (!NT_SUCCESS(Status) || !NT_SUCCESS(CsrReply.Status)) }
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 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"); if (IsConsoleHandle(Ppb->hStdOutput))
Status = NtDuplicateObject (NtCurrentProcess(),
Ppb->hStdError,
hProcess,
&Ppb->hStdError,
0,
TRUE,
DUPLICATE_SAME_ACCESS);
if(!NT_SUCCESS(Status))
{ {
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);
}
} }
} }

View file

@ -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 * reactos/subsys/csrss/api/process.c
* *
@ -252,6 +252,8 @@ CSR_API(CsrCreateProcess)
RtlLeaveCriticalSection(&ProcessDataLock); RtlLeaveCriticalSection(&ProcessDataLock);
} }
Reply->Data.CreateProcessReply.Console = NewProcessData->Console;
Reply->Status = STATUS_SUCCESS; Reply->Status = STATUS_SUCCESS;
return(STATUS_SUCCESS); return(STATUS_SUCCESS);
} }

View file

@ -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 * reactos/subsys/csrss/win32csr/conio.c
* *
@ -314,6 +314,7 @@ CSR_API(CsrAllocConsole)
return Reply->Status; return Reply->Status;
} }
ProcessData->Console = Console; ProcessData->Console = Console;
Reply->Data.AllocConsoleReply.Console = Console;
/* add a reference count because the process is tied to the console */ /* add a reference count because the process is tied to the console */
Console->Header.ReferenceCount++; Console->Header.ReferenceCount++;

View file

@ -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 * COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS system libraries * PROJECT: ReactOS system libraries
@ -482,6 +482,7 @@ GuiConsoleNotifyWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
NULL, NULL,
(HINSTANCE) GetModuleHandleW(NULL), (HINSTANCE) GetModuleHandleW(NULL),
(PVOID) Console); (PVOID) Console);
Console->hWindow = NewWindow;
if (NULL != NewWindow) if (NULL != NewWindow)
{ {
SetWindowLongW(hWnd, GWL_USERDATA, GetWindowLongW(hWnd, GWL_USERDATA) + 1); SetWindowLongW(hWnd, GWL_USERDATA, GetWindowLongW(hWnd, GWL_USERDATA) + 1);
@ -645,9 +646,15 @@ GuiConsoleInitConsole(PCSRSS_CONSOLE Console)
{ {
Console->Size.X = 80; Console->Size.X = 80;
Console->Size.Y = 25; Console->Size.Y = 25;
#ifdef TODO
Console->hWindow = (HWND) SendMessageW(NotifyWnd, PM_CREATE_CONSOLE, 0, (LPARAM) Console); Console->hWindow = (HWND) SendMessageW(NotifyWnd, PM_CREATE_CONSOLE, 0, (LPARAM) Console);
return NULL != Console->hWindow; return NULL != Console->hWindow;
#else
PostMessageW(NotifyWnd, PM_CREATE_CONSOLE, 0, (LPARAM) Console);
return TRUE;
#endif
} }
VOID STDCALL VOID STDCALL

View file

@ -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. * CMD.C - command-line interface.
* *
@ -1228,9 +1228,6 @@ int main (int argc, char *argv[])
SetFileApisToOEM(); SetFileApisToOEM();
AllocConsole();
hConsole = CreateFile(_T("CONOUT$"), GENERIC_READ|GENERIC_WRITE, hConsole = CreateFile(_T("CONOUT$"), GENERIC_READ|GENERIC_WRITE,
FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL,
OPEN_EXISTING, 0, NULL); OPEN_EXISTING, 0, NULL);

View file

@ -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 * COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel * PROJECT: ReactOS kernel
@ -372,7 +372,7 @@ static BOOL DoLoginUser(PWCHAR Name, PWCHAR Password)
NULL, NULL,
NULL, NULL,
FALSE, FALSE,
DETACHED_PROCESS, CREATE_NEW_CONSOLE,
NULL, NULL,
CurrentDirectory, CurrentDirectory,
&StartupInfo, &StartupInfo,