[KERNEL32/BASESRV/CONSRV]
authorHermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
Tue, 1 Jan 2013 23:36:19 +0000 (23:36 +0000)
committerHermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
Tue, 1 Jan 2013 23:36:19 +0000 (23:36 +0000)
- Fix console apps initialization.
- Introduce a helper function InitConsoleCtrlHandling for initializing console control handling.
- We now initialize the new created console when connecting the client (kernel32) to the server (consrv) by calling CsrClientConnectToServer with real parameters (not dummy ones).
- Add/activate some debug prints (will be removed when all things work).

Part 1/2

svn path=/branches/ros-csrss/; revision=58096

dll/win32/kernel32/client/console/console.c
dll/win32/kernel32/client/dllmain.c
dll/win32/kernel32/client/proc.c
dll/win32/kernel32/include/kernel32.h
include/reactos/subsys/win/conmsg.h
subsystems/win/basesrv/server.c

index 0833f7f..89bc128 100644 (file)
@@ -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;
 }
 
index 07f23a3..5ac130f 100644 (file)
@@ -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;
 
index 0c4f36b..a1bbceb 100644 (file)
@@ -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 */
index dc311bf..409cb8a 100644 (file)
@@ -186,6 +186,8 @@ VOID
 NTAPI
 BaseDllInitializeMemoryManager(VOID);
 
+VOID WINAPI InitConsoleCtrlHandling(VOID);
+
 BOOL WINAPI VerifyConsoleIoHandle(HANDLE Handle);
 
 BOOL WINAPI CloseConsoleHandle(HANDLE Handle);
index 7763f2f..d9a5788 100644 (file)
@@ -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
index f30ca3b..ad01745 100644 (file)
@@ -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
     }