diff --git a/dll/win32/kernel32/client/console/console.c b/dll/win32/kernel32/client/console/console.c index 0833f7fa224..89bc128d7af 100644 --- a/dll/win32/kernel32/client/console/console.c +++ b/dll/win32/kernel32/client/console/console.c @@ -29,6 +29,8 @@ PHANDLER_ROUTINE* CtrlHandlers; ULONG NrCtrlHandlers; ULONG NrAllocatedHandlers; +HANDLE InputWaitHandle = INVALID_HANDLE_VALUE; + #define INPUTEXENAME_BUFLEN 256 static WCHAR InputExeName[INPUTEXENAME_BUFLEN]; @@ -76,7 +78,7 @@ ConsoleControlDispatcher(IN LPVOID lpThreadParameter) UINT i; EXCEPTION_RECORD erException; - DPRINT("Console Dispatcher Active: %lx %lx\n", CodeAndFlag, nCode); + DPRINT1("Console Dispatcher Active: %lx %lx\n", CodeAndFlag, nCode); SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST); switch(nCode) @@ -174,6 +176,16 @@ ConsoleControlDispatcher(IN LPVOID lpThreadParameter) return STATUS_SUCCESS; } +VOID +WINAPI +InitConsoleCtrlHandling(VOID) +{ + /* Initialize Console Ctrl Handler */ + NrAllocatedHandlers = NrCtrlHandlers = 1; + CtrlHandlers = InitialHandler; + CtrlHandlers[0] = DefaultConsoleCtrlHandler; +} + /* FUNCTIONS ******************************************************************/ @@ -321,10 +333,6 @@ HANDLE WINAPI GetConsoleInputWaitHandle(VOID) { -/// HACK !!!!!!!!!!!!! - ASSERT(FALSE); - return NULL; - #if 0 NTSTATUS Status; CONSOLE_API_MESSAGE ApiMessage; @@ -341,6 +349,8 @@ GetConsoleInputWaitHandle(VOID) return ApiMessage.Data.GetConsoleInputWaitHandle.InputWaitHandle; #endif + + return InputWaitHandle; } @@ -786,9 +796,10 @@ AllocConsole(VOID) NTSTATUS Status; CONSOLE_API_MESSAGE ApiMessage; PCSRSS_ALLOC_CONSOLE AllocConsoleRequest = &ApiMessage.Data.AllocConsoleRequest; - HANDLE hStdError; STARTUPINFO si; + DPRINT1("AllocConsole called !!!!\n"); + if (NtCurrentPeb()->ProcessParameters->ConsoleHandle) { DPRINT("AllocConsole: Allocate duplicate console to the same Process\n"); @@ -798,9 +809,9 @@ AllocConsole(VOID) GetStartupInfo(&si); - AllocConsoleRequest->CtrlDispatcher = ConsoleControlDispatcher; - AllocConsoleRequest->ConsoleNeeded = TRUE; AllocConsoleRequest->ShowCmd = si.wShowWindow; + AllocConsoleRequest->Console = NULL; + AllocConsoleRequest->CtrlDispatcher = ConsoleControlDispatcher; Status = CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage, NULL, @@ -814,15 +825,15 @@ AllocConsole(VOID) NtCurrentPeb()->ProcessParameters->ConsoleHandle = AllocConsoleRequest->Console; - SetStdHandle(STD_INPUT_HANDLE, AllocConsoleRequest->InputHandle); + SetStdHandle(STD_INPUT_HANDLE , AllocConsoleRequest->InputHandle ); SetStdHandle(STD_OUTPUT_HANDLE, AllocConsoleRequest->OutputHandle); + SetStdHandle(STD_ERROR_HANDLE , AllocConsoleRequest->ErrorHandle ); - hStdError = DuplicateConsoleHandle(AllocConsoleRequest->OutputHandle, - 0, - TRUE, - DUPLICATE_SAME_ACCESS); + /* Initialize Console Ctrl Handler */ + InitConsoleCtrlHandling(); + + InputWaitHandle = AllocConsoleRequest->InputWaitHandle; - SetStdHandle(STD_ERROR_HANDLE, hStdError); return TRUE; } @@ -853,6 +864,10 @@ FreeConsole(VOID) } NtCurrentPeb()->ProcessParameters->ConsoleHandle = NULL; + + CloseHandle(InputWaitHandle); + InputWaitHandle = INVALID_HANDLE_VALUE; + return TRUE; } diff --git a/dll/win32/kernel32/client/dllmain.c b/dll/win32/kernel32/client/dllmain.c index 07f23a32b30..5ac130fd8d8 100644 --- a/dll/win32/kernel32/client/dllmain.c +++ b/dll/win32/kernel32/client/dllmain.c @@ -36,12 +36,9 @@ static BOOL DllInitialized = FALSE; RTL_CRITICAL_SECTION BaseDllDirectoryLock; RTL_CRITICAL_SECTION ConsoleLock; -extern BOOL WINAPI DefaultConsoleCtrlHandler(DWORD Event); extern DWORD WINAPI ConsoleControlDispatcher(IN LPVOID lpThreadParameter); -extern PHANDLER_ROUTINE InitialHandler[1]; -extern PHANDLER_ROUTINE* CtrlHandlers; -extern ULONG NrCtrlHandlers; -extern ULONG NrAllocatedHandlers; +extern HANDLE InputWaitHandle; + extern BOOL FASTCALL NlsInit(VOID); extern VOID FASTCALL NlsUninit(VOID); @@ -55,9 +52,6 @@ WINAPI BasepInitConsole(VOID) { NTSTATUS Status; - CONSOLE_API_MESSAGE ApiMessage; - PCSRSS_ALLOC_CONSOLE AllocConsoleRequest = &ApiMessage.Data.AllocConsoleRequest; - BOOLEAN NotConsole = FALSE; PRTL_USER_PROCESS_PARAMETERS Parameters = NtCurrentPeb()->ProcessParameters; LPCWSTR ExeName; STARTUPINFO si; @@ -65,12 +59,8 @@ BasepInitConsole(VOID) ULONG SessionId = NtCurrentPeb()->SessionId; BOOLEAN InServer; - // HACK - /* - CSR_CONNECTION_INFO CsrConnectionInfo; - ULONG ConnectionSize = sizeof(CsrConnectionInfo); - */ - // END HACK + CONSOLE_CONNECTION_INFO ConnectInfo; + ULONG ConnectInfoSize = sizeof(ConnectInfo); WCHAR lpTest[MAX_PATH]; GetModuleFileNameW(NULL, lpTest, MAX_PATH); @@ -79,28 +69,33 @@ BasepInitConsole(VOID) Parameters->ConsoleHandle, Parameters->StandardInput, Parameters->StandardOutput, Parameters->StandardError); + /* Initialize our global console DLL lock */ + Status = RtlInitializeCriticalSection(&ConsoleLock); + if (!NT_SUCCESS(Status)) return FALSE; + ConsoleInitialized = TRUE; + /* We have nothing to do if this isn't a console app... */ if (RtlImageNtHeader(GetModuleHandle(NULL))->OptionalHeader.Subsystem != IMAGE_SUBSYSTEM_WINDOWS_CUI) { DPRINT("Image is not a console application\n"); Parameters->ConsoleHandle = NULL; - AllocConsoleRequest->ConsoleNeeded = FALSE; + ConnectInfo.ConsoleNeeded = FALSE; // ConsoleNeeded is used for knowing whether or not this is a CUI app. } else { /* Assume one is needed */ GetStartupInfo(&si); - AllocConsoleRequest->ConsoleNeeded = TRUE; - AllocConsoleRequest->ShowCmd = si.wShowWindow; + ConnectInfo.ConsoleNeeded = TRUE; + ConnectInfo.ShowCmd = si.wShowWindow; - /* Handle the special flags given to us by BasepInitializeEnvironment */ + /* Handle the special flags given to us by BasePushProcessParameters */ if (Parameters->ConsoleHandle == HANDLE_DETACHED_PROCESS) { /* No console to create */ DPRINT("No console to create\n"); Parameters->ConsoleHandle = NULL; - AllocConsoleRequest->ConsoleNeeded = FALSE; + ConnectInfo.ConsoleNeeded = FALSE; } else if (Parameters->ConsoleHandle == HANDLE_CREATE_NEW_CONSOLE) { @@ -113,33 +108,29 @@ BasepInitConsole(VOID) /* We'll get the real one soon */ DPRINT("Creating new invisible console\n"); Parameters->ConsoleHandle = NULL; - AllocConsoleRequest->ShowCmd = SW_HIDE; + ConnectInfo.ShowCmd = SW_HIDE; } else { if (Parameters->ConsoleHandle == INVALID_HANDLE_VALUE) { - Parameters->ConsoleHandle = 0; + Parameters->ConsoleHandle = NULL; } DPRINT("Using existing console: %x\n", Parameters->ConsoleHandle); } } + /* Now use the proper console handle */ + ConnectInfo.Console = Parameters->ConsoleHandle; + /* Initialize Console Ctrl Handler and input EXE name */ - ConsoleInitialized = TRUE; - RtlInitializeCriticalSection(&ConsoleLock); - NrAllocatedHandlers = 1; - NrCtrlHandlers = 1; - CtrlHandlers = InitialHandler; - CtrlHandlers[0] = DefaultConsoleCtrlHandler; + InitConsoleCtrlHandling(); + ConnectInfo.CtrlDispatcher = ConsoleControlDispatcher; ExeName = wcsrchr(Parameters->ImagePathName.Buffer, L'\\'); if (ExeName) SetConsoleInputExeNameW(ExeName + 1); - /* Now use the proper console handle */ - AllocConsoleRequest->Console = Parameters->ConsoleHandle; - /* Setup the right Object Directory path */ if (!SessionId) { @@ -156,61 +147,45 @@ BasepInitConsole(VOID) WIN_OBJ_DIR); } - /* Connect to the base server */ - DPRINT("Connecting to CSR in BasepInitConsole...\n"); + /* Connect to the Console Server */ + DPRINT("Connecting to the Console Server in BasepInitConsole...\n"); Status = CsrClientConnectToServer(SessionDir, CONSRV_SERVERDLL_INDEX, - /* &CsrConnectionInfo, */ NULL, // TODO: Give it a console connection info - /* &ConnectionSize, */ NULL, // TODO: Give it a console connection info + &ConnectInfo, + &ConnectInfoSize, &InServer); if (!NT_SUCCESS(Status)) { - DPRINT1("Failed to connect to CSR (Status %lx)\n", Status); + DPRINT1("Failed to connect to the Console Server (Status %lx)\n", Status); return FALSE; } /* Nothing to do for server-to-server */ if (InServer) return TRUE; - /* - * Normally, we should be connecting to the Console CSR Server... - * but we don't have one yet, so we will instead simply send a create - * console message to the Base Server. When we finally have a Console - * Server, this code should be changed to send connection data instead. - */ - AllocConsoleRequest->CtrlDispatcher = ConsoleControlDispatcher; - Status = CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage, - NULL, - CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepAlloc), - sizeof(CSRSS_ALLOC_CONSOLE)); - if(!NT_SUCCESS(Status) || !NT_SUCCESS(Status = ApiMessage.Status)) - { - DPRINT1("CSR Failed to give us a console\n"); - /* We're lying here, so at least the process can load... */ - return TRUE; - } - /* Nothing to do if not a console app */ - if (NotConsole) return TRUE; + if (!ConnectInfo.ConsoleNeeded) return TRUE; /* We got the handles, let's set them */ - if ((Parameters->ConsoleHandle = AllocConsoleRequest->Console)) + if ((Parameters->ConsoleHandle = ConnectInfo.Console)) { /* If we already had some, don't use the new ones */ if (!Parameters->StandardInput) { - Parameters->StandardInput = AllocConsoleRequest->InputHandle; + Parameters->StandardInput = ConnectInfo.InputHandle; } if (!Parameters->StandardOutput) { - Parameters->StandardOutput = AllocConsoleRequest->OutputHandle; + Parameters->StandardOutput = ConnectInfo.OutputHandle; } if (!Parameters->StandardError) { - Parameters->StandardError = AllocConsoleRequest->OutputHandle; + Parameters->StandardError = ConnectInfo.ErrorHandle; } } + InputWaitHandle = ConnectInfo.InputWaitHandle; + DPRINT("Console setup: %lx, %lx, %lx, %lx\n", Parameters->ConsoleHandle, Parameters->StandardInput, @@ -403,9 +378,9 @@ DllMain(HANDLE hDll, if (ConsoleInitialized == TRUE) { ConsoleInitialized = FALSE; - RtlDeleteCriticalSection (&ConsoleLock); + RtlDeleteCriticalSection(&ConsoleLock); } - RtlDeleteCriticalSection (&BaseDllDirectoryLock); + RtlDeleteCriticalSection(&BaseDllDirectoryLock); } break; diff --git a/dll/win32/kernel32/client/proc.c b/dll/win32/kernel32/client/proc.c index 0c4f36b4ed4..a1bbceb9022 100644 --- a/dll/win32/kernel32/client/proc.c +++ b/dll/win32/kernel32/client/proc.c @@ -581,6 +581,16 @@ BasepCreateFirstThread(HANDLE ProcessHandle, CreateProcessRequest->CreationFlags = dwCreationFlags; CreateProcessRequest->bInheritHandles = InheritHandles; + /* + * For GUI applications we turn on the 2nd bit. This also allows + * us to know whether or not the application is a GUI or CUI app. + */ + if (IMAGE_SUBSYSTEM_WINDOWS_GUI == SectionImageInfo->SubSystemType) + { + CreateProcessRequest->ProcessHandle = (HANDLE) + ((ULONG_PTR)CreateProcessRequest->ProcessHandle | 2); + } + /* Call CSR */ DPRINT1("Calling CsrClientCallServer from BasepCreateFirstThread...\n"); Status = CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage, @@ -937,19 +947,19 @@ BasePushProcessParameters(IN ULONG ParameterFlags, ProcessParameters->StandardError = StartupInfo->hStdError; } - /* Use Special Flags for ConDllInitialize in Kernel32 */ + /* Use Special Flags for BasepInitConsole in Kernel32 */ if (CreationFlags & DETACHED_PROCESS) { ProcessParameters->ConsoleHandle = HANDLE_DETACHED_PROCESS; } - else if (CreationFlags & CREATE_NO_WINDOW) - { - ProcessParameters->ConsoleHandle = HANDLE_CREATE_NO_WINDOW; - } else if (CreationFlags & CREATE_NEW_CONSOLE) { ProcessParameters->ConsoleHandle = HANDLE_CREATE_NEW_CONSOLE; } + else if (CreationFlags & CREATE_NO_WINDOW) + { + ProcessParameters->ConsoleHandle = HANDLE_CREATE_NO_WINDOW; + } else { /* Inherit our Console Handle */ diff --git a/dll/win32/kernel32/include/kernel32.h b/dll/win32/kernel32/include/kernel32.h index dc311bfb977..409cb8a2841 100644 --- a/dll/win32/kernel32/include/kernel32.h +++ b/dll/win32/kernel32/include/kernel32.h @@ -186,6 +186,8 @@ VOID NTAPI BaseDllInitializeMemoryManager(VOID); +VOID WINAPI InitConsoleCtrlHandling(VOID); + BOOL WINAPI VerifyConsoleIoHandle(HANDLE Handle); BOOL WINAPI CloseConsoleHandle(HANDLE Handle); diff --git a/include/reactos/subsys/win/conmsg.h b/include/reactos/subsys/win/conmsg.h index 7763f2fd8ae..d9a5788770d 100644 --- a/include/reactos/subsys/win/conmsg.h +++ b/include/reactos/subsys/win/conmsg.h @@ -114,7 +114,16 @@ typedef enum _CONSRV_API_NUMBER typedef struct _CONSOLE_CONNECTION_INFO { - ULONG Dummy; + BOOL ConsoleNeeded; // Used for GUI apps only. + + /* Copied from CSRSS_ALLOC_CONSOLE */ + INT ShowCmd; + HANDLE Console; // ConsoleHandle // In fact, it is a PCSRSS_CONSOLE <-- correct that !! + HANDLE InputHandle; + HANDLE OutputHandle; + HANDLE ErrorHandle; + HANDLE InputWaitHandle; + LPTHREAD_START_ROUTINE CtrlDispatcher; } CONSOLE_CONNECTION_INFO, *PCONSOLE_CONNECTION_INFO; @@ -157,12 +166,13 @@ typedef struct typedef struct { - LPTHREAD_START_ROUTINE CtrlDispatcher; - BOOL ConsoleNeeded; INT ShowCmd; - HANDLE Console; + HANDLE Console; // ConsoleHandle // In fact, it is a PCSRSS_CONSOLE <-- correct that !! HANDLE InputHandle; HANDLE OutputHandle; + HANDLE ErrorHandle; + HANDLE InputWaitHandle; + LPTHREAD_START_ROUTINE CtrlDispatcher; } CSRSS_ALLOC_CONSOLE, *PCSRSS_ALLOC_CONSOLE; typedef struct diff --git a/subsystems/win/basesrv/server.c b/subsystems/win/basesrv/server.c index f30ca3bc2d0..ad017454665 100644 --- a/subsystems/win/basesrv/server.c +++ b/subsystems/win/basesrv/server.c @@ -81,6 +81,11 @@ CSR_API(BaseSrvCreateProcess) { DebugFlags |= CsrProcessCreateNewGroup; } + if ((Flags & 2) == 0) + { + DPRINT1("BaseSrvCreateProcess - Launching a Console process\n"); + DebugFlags |= CsrProcessIsConsoleApp; + } /* FIXME: SxS Stuff */ @@ -129,8 +134,8 @@ CSR_API(BaseSrvCreateThread) if (!CurrentThread) { DPRINT1("Server Thread TID: [%lx.%lx]\n", - CreateThreadRequest->ClientId.UniqueProcess, - CreateThreadRequest->ClientId.UniqueThread); + CreateThreadRequest->ClientId.UniqueProcess, + CreateThreadRequest->ClientId.UniqueThread); return STATUS_SUCCESS; // server-to-server }