[KERNEL32], [WIN32CSR] More fixes for console winetest
[reactos.git] / reactos / dll / win32 / kernel32 / misc / dllmain.c
index c886f70..5247b64 100644 (file)
@@ -26,11 +26,11 @@ HMODULE hCurrentModule = NULL;
 HANDLE hBaseDir = NULL;
 PPEB Peb;
 ULONG SessionId;
+BOOL ConsoleInitialized = FALSE;
 
 static BOOL DllInitialized = FALSE;
-static BOOL ConsoleInitialized = FALSE;
 
-BOOL STDCALL
+BOOL WINAPI
 DllMain(HANDLE hInst,
        DWORD dwReason,
        LPVOID lpReserved);
@@ -41,13 +41,16 @@ RTL_CRITICAL_SECTION ConsoleLock;
 
 extern BOOL WINAPI DefaultConsoleCtrlHandler(DWORD Event);
 extern __declspec(noreturn) VOID CALLBACK ConsoleControlDispatcher(DWORD CodeAndFlag);
-
-extern BOOL FASTCALL NlsInit();
-extern VOID FASTCALL NlsUninit();
+extern PHANDLER_ROUTINE InitialHandler[1];
+extern PHANDLER_ROUTINE* CtrlHandlers;
+extern ULONG NrCtrlHandlers;
+extern ULONG NrAllocatedHandlers;
+extern BOOL FASTCALL NlsInit(VOID);
+extern VOID FASTCALL NlsUninit(VOID);
 BOOLEAN InWindows = FALSE;
 
 HANDLE
-STDCALL
+WINAPI
 DuplicateConsoleHandle(HANDLE hConsole,
                        DWORD dwDesiredAccess,
                        BOOL    bInheritHandle,
@@ -119,13 +122,15 @@ BaseProcessInitPostImport(VOID)
 }
 
 BOOL
-STDCALL
+WINAPI
 BasepInitConsole(VOID)
 {
     CSR_API_MESSAGE Request;
     ULONG CsrRequest;
     NTSTATUS Status;
+    BOOLEAN NotConsole = FALSE;
     PRTL_USER_PROCESS_PARAMETERS Parameters = NtCurrentPeb()->ProcessParameters;
+    LPCWSTR ExeName;
 
     WCHAR lpTest[MAX_PATH];
     GetModuleFileNameW(NULL, lpTest, MAX_PATH);
@@ -140,46 +145,57 @@ BasepInitConsole(VOID)
     {
         DPRINT("Image is not a console application\n");
         Parameters->ConsoleHandle = NULL;
-        return TRUE;
-    }
-
-    /* Assume one is needed */
-    Request.Data.AllocConsoleRequest.ConsoleNeeded = TRUE;
-
-    /* Handle the special flags given to us by BasepInitializeEnvironment */
-    if (Parameters->ConsoleHandle == HANDLE_DETACHED_PROCESS)
-    {
-        /* No console to create */
-        DPRINT("No console to create\n");
-        Parameters->ConsoleHandle = NULL;
         Request.Data.AllocConsoleRequest.ConsoleNeeded = FALSE;
     }
-    else if (Parameters->ConsoleHandle == HANDLE_CREATE_NEW_CONSOLE)
-    {
-        /* We'll get the real one soon */
-        DPRINT("Creating new console\n");
-        Parameters->ConsoleHandle = NULL;
-    }
-    else if (Parameters->ConsoleHandle == HANDLE_CREATE_NO_WINDOW)
-    {
-        /* We'll get the real one soon */
-        DPRINT1("NOT SUPPORTED: HANDLE_CREATE_NO_WINDOW\n");
-        Parameters->ConsoleHandle = NULL;
-    }
     else
     {
-        if (Parameters->ConsoleHandle == INVALID_HANDLE_VALUE)
+        /* Assume one is needed */
+        Request.Data.AllocConsoleRequest.ConsoleNeeded = TRUE;
+        Request.Data.AllocConsoleRequest.Visible = TRUE;
+
+        /* Handle the special flags given to us by BasepInitializeEnvironment */
+        if (Parameters->ConsoleHandle == HANDLE_DETACHED_PROCESS)
+        {
+            /* No console to create */
+            DPRINT("No console to create\n");
+            Parameters->ConsoleHandle = NULL;
+            Request.Data.AllocConsoleRequest.ConsoleNeeded = FALSE;
+        }
+        else if (Parameters->ConsoleHandle == HANDLE_CREATE_NEW_CONSOLE)
         {
-            Parameters->ConsoleHandle = 0;
+            /* We'll get the real one soon */
+            DPRINT("Creating new console\n");
+            Parameters->ConsoleHandle = NULL;
+        }
+        else if (Parameters->ConsoleHandle == HANDLE_CREATE_NO_WINDOW)
+        {
+            /* We'll get the real one soon */
+            DPRINT("Creating new invisible console\n");
+            Parameters->ConsoleHandle = NULL;
+            Request.Data.AllocConsoleRequest.Visible = FALSE;
+        }
+        else
+        {
+            if (Parameters->ConsoleHandle == INVALID_HANDLE_VALUE)
+            {
+                Parameters->ConsoleHandle = 0;
+            }
+            DPRINT("Using existing console: %x\n", Parameters->ConsoleHandle);
         }
-        DPRINT("Using existing console: %x\n", Parameters->ConsoleHandle);
     }
 
-    /* Initialize Console Ctrl Handler */
+    /* Initialize Console Ctrl Handler and input EXE name */
     ConsoleInitialized = TRUE;
     RtlInitializeCriticalSection(&ConsoleLock);
-    SetConsoleCtrlHandler(DefaultConsoleCtrlHandler, TRUE);
-
+    NrAllocatedHandlers = 1;
+    NrCtrlHandlers = 1;
+    CtrlHandlers = InitialHandler;
+    CtrlHandlers[0] = DefaultConsoleCtrlHandler;
+
+    ExeName = wcsrchr(Parameters->ImagePathName.Buffer, L'\\');
+    if (ExeName)
+        SetConsoleInputExeNameW(ExeName + 1);
+    
     /* Now use the proper console handle */
     Request.Data.AllocConsoleRequest.Console = Parameters->ConsoleHandle;
 
@@ -188,9 +204,6 @@ BasepInitConsole(VOID)
      * 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.
-     *
-     * Also note that this connection should be made for any console app, even
-     * in the case above where -we- return.
      */
     CsrRequest = MAKE_CSR_API(ALLOC_CONSOLE, CSR_CONSOLE);
     Request.Data.AllocConsoleRequest.CtrlDispatcher = ConsoleControlDispatcher;
@@ -204,6 +217,8 @@ BasepInitConsole(VOID)
         /* We're lying here, so at least the process can load... */
         return TRUE;
     }
+    
+    if (NotConsole) return TRUE;
 
     /* We got the handles, let's set them */
     if ((Parameters->ConsoleHandle = Request.Data.AllocConsoleRequest.Console))
@@ -233,7 +248,7 @@ BasepInitConsole(VOID)
 
 
 BOOL
-STDCALL
+WINAPI
 DllMain(HANDLE hDll,
         DWORD dwReason,
         LPVOID lpReserved)
@@ -257,42 +272,6 @@ DllMain(HANDLE hDll,
     {
         case DLL_PROCESS_ATTACH:
 
-#ifdef _M_IX86
-        /* OK, yes, this is really retarded but it works for now */
-        InWindows = NtCurrentPeb()->BeingDebugged;
-
-        /*
-         * CreateProcess will run in the real kernel32 and it will write
-         * its own BaseProcessStartThunk EIP in the CONTEXT that ZwContinue
-         * will get. We'll be first called by Ldr while initializing, and we'll
-         * be wrapped in 3 layers of SEH, followed by two frames, finally 
-         * followed by our CONTEXT on the stack. We'll modify the EIP in it
-         * to match the correct one (our own) and then everything works.
-         * Tested on XP and 2K3, probably doesn't work in 2K.
-         */
-        if (InWindows)
-        {
-            /* 
-             * Due to yet another bug in how Windows handles .local, LDR will
-             * actually end up loading us twice. The second time will be the
-             * "official" load, at a totally different address. It will be,
-             * it will be at -that- address that all the APIs will be called.
-             * However, that address is dynamic while this one will be static,
-             * so we'll do initilization with this one. Plus, at this one,
-             * we know exactly that we're within 3 SEH layers.
-             */
-            if (hDll == (HANDLE)0x7c800000)
-            {
-                PULONG Eip;
-                __debugbreak();
-                Eip = (PULONG)*(PULONG)*(PULONG)NtCurrentTeb()->Tib.ExceptionList +
-                    0x9 +
-                    FIELD_OFFSET(CONTEXT, Eip) / sizeof(ULONG);
-                *Eip = (ULONG)BaseProcessStartThunk;
-            }
-        }
-#endif
-
         /* Don't bother us for each thread */
         LdrDisableThreadCalloutsForDll((PVOID)hDll);
 
@@ -358,6 +337,9 @@ DllMain(HANDLE hDll,
         wcscpy(SystemDirectory.Buffer, WindowsDirectory.Buffer);
         wcscat(SystemDirectory.Buffer, L"\\System32");
 
+        /* Initialize command line */
+        InitCommandLines();
+
         /* Open object base directory */
         Status = OpenBaseDirectory(&hBaseDir);
         if (!NT_SUCCESS(Status))
@@ -410,6 +392,7 @@ DllMain(HANDLE hDll,
                 /* Delete DLL critical section */
                 if (ConsoleInitialized == TRUE)
                 {
+                    ConsoleInitialized = FALSE;
                     RtlDeleteCriticalSection (&ConsoleLock);
                 }
                 RtlDeleteCriticalSection (&DllLock);
@@ -429,6 +412,12 @@ DllMain(HANDLE hDll,
     return TRUE;
 }
 
+#undef InterlockedIncrement
+#undef InterlockedDecrement
+#undef InterlockedExchange
+#undef InterlockedExchangeAdd
+#undef InterlockedCompareExchange
+
 LONG
 WINAPI
 InterlockedIncrement(IN OUT LONG volatile *lpAddend)