[KERNEL32], [WIN32CSR] More fixes for console winetest
[reactos.git] / reactos / dll / win32 / kernel32 / misc / console.c
index 6e6f57c..2d6d5ba 100644 (file)
 #define NDEBUG
 #include <debug.h>
 
-extern BOOL WINAPI DefaultConsoleCtrlHandler(DWORD Event);
-extern __declspec(noreturn) VOID CALLBACK ConsoleControlDispatcher(DWORD CodeAndFlag);
 extern RTL_CRITICAL_SECTION ConsoleLock;
 extern BOOL ConsoleInitialized;
 extern BOOL WINAPI IsDebuggerPresent(VOID);
 
 /* GLOBALS *******************************************************************/
 
-static PHANDLER_ROUTINE* CtrlHandlers = NULL;
-static ULONG NrCtrlHandlers = 0;
+PHANDLER_ROUTINE InitialHandler[1];
+PHANDLER_ROUTINE* CtrlHandlers;
+ULONG NrCtrlHandlers;
+ULONG NrAllocatedHandlers;
+
 #define INPUTEXENAME_BUFLEN 256
 static WCHAR InputExeName[INPUTEXENAME_BUFLEN] = L"";
 
@@ -38,6 +39,7 @@ BOOL
 WINAPI
 DefaultConsoleCtrlHandler(DWORD Event)
 {
+    DPRINT("Default handler called: %lx\n", Event);
     switch(Event)
     {
         case CTRL_C_EVENT:
@@ -61,11 +63,10 @@ DefaultConsoleCtrlHandler(DWORD Event)
             break;
     }
 
-    ExitProcess(0);
+    ExitProcess(CONTROL_C_EXIT);
     return TRUE;
 }
 
-
 __declspec(noreturn)
 VOID
 CALLBACK
@@ -74,7 +75,9 @@ ConsoleControlDispatcher(DWORD CodeAndFlag)
     DWORD nExitCode = 0;
     DWORD nCode = CodeAndFlag & MAXLONG;
     UINT i;
-
+    EXCEPTION_RECORD erException;
+    
+    DPRINT("Console Dispatcher Active: %lx %lx\n", CodeAndFlag, nCode);
     SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST);
 
     switch(nCode)
@@ -82,51 +85,78 @@ ConsoleControlDispatcher(DWORD CodeAndFlag)
         case CTRL_C_EVENT:
         case CTRL_BREAK_EVENT:
         {
-            if(IsDebuggerPresent())
+            if (IsDebuggerPresent())
             {
-                EXCEPTION_RECORD erException;
-                erException.ExceptionCode =
-                    (nCode == CTRL_C_EVENT ? DBG_CONTROL_C : DBG_CONTROL_BREAK);
+                erException.ExceptionCode = (nCode == CTRL_C_EVENT ?
+                                             DBG_CONTROL_C : DBG_CONTROL_BREAK);
                 erException.ExceptionFlags = 0;
                 erException.ExceptionRecord = NULL;
-                erException.ExceptionAddress = &DefaultConsoleCtrlHandler;
+                erException.ExceptionAddress = DefaultConsoleCtrlHandler;
                 erException.NumberParameters = 0;
-                RtlRaiseException(&erException);
-            }
-
-            if (!ConsoleInitialized) ExitThread(0);
-            RtlEnterCriticalSection(&ConsoleLock);
-
-            if (!(nCode == CTRL_C_EVENT &&
-                NtCurrentPeb()->ProcessParameters->ConsoleFlags & 1))
-            {
-                for(i = NrCtrlHandlers; i > 0; -- i)
-                    if(CtrlHandlers[i - 1](nCode)) break;
+                
+                _SEH2_TRY
+                {
+                    RtlRaiseException(&erException);
+                }
+                _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+                {
+                    RtlEnterCriticalSection(&ConsoleLock);
+                    
+                    if ((nCode != CTRL_C_EVENT) ||
+                        (NtCurrentPeb()->ProcessParameters->ConsoleFlags != 1))
+                    {
+                        for (i = NrCtrlHandlers; i > 0; i--)
+                        {
+                            if (CtrlHandlers[i - 1](nCode)) break;
+                        }
+                    }
+                    
+                    RtlLeaveCriticalSection(&ConsoleLock);
+                }
+                _SEH2_END;
+                
+                ExitThread(0);
             }
-            RtlLeaveCriticalSection(&ConsoleLock);
-            ExitThread(0);
+            
+            break;
         }
 
         case CTRL_CLOSE_EVENT:
         case CTRL_LOGOFF_EVENT:
         case CTRL_SHUTDOWN_EVENT:
             break;
+            
+        case 3:
+        
+            ExitThread(0);
+            break;
+        
+        case 4:
+        
+            ExitProcess(CONTROL_C_EXIT);
+            break;
 
-        default: ExitThread(0);
+        default:
+        
+            ASSERT(FALSE);
+            break;
     }
-
-    if (!ConsoleInitialized) ExitThread(0);
+    
+    ASSERT(ConsoleInitialized);
+    
     RtlEnterCriticalSection(&ConsoleLock);
-
-    if (!(nCode == CTRL_C_EVENT &&
-        NtCurrentPeb()->ProcessParameters->ConsoleFlags & 1))
+    nExitCode = 0;
+    if ((nCode != CTRL_C_EVENT) || (NtCurrentPeb()->ProcessParameters->ConsoleFlags != 1))
     {
-        i = NrCtrlHandlers;
-        while (i > 0)
+        for (i = NrCtrlHandlers; i > 0; i--)
         {
-            if (i == 1 && (CodeAndFlag & MINLONG) &&
-                (nCode == CTRL_LOGOFF_EVENT || nCode == CTRL_SHUTDOWN_EVENT))
+            if ((i == 1) &&
+                (CodeAndFlag & MINLONG) &&
+                ((nCode == CTRL_LOGOFF_EVENT) || (nCode == CTRL_SHUTDOWN_EVENT)))
+            {
+                DPRINT("Skipping system/service apps\n");
                 break;
+            }
 
             if (CtrlHandlers[i - 1](nCode))
             {
@@ -135,13 +165,15 @@ ConsoleControlDispatcher(DWORD CodeAndFlag)
                     case CTRL_CLOSE_EVENT:
                     case CTRL_LOGOFF_EVENT:
                     case CTRL_SHUTDOWN_EVENT:
+                    case 3:
                         nExitCode = CodeAndFlag;
+                        break;
                 }
                 break;
             }
-            --i;
         }
     }
+    
     RtlLeaveCriticalSection(&ConsoleLock);
     ExitThread(nExitCode);
 }
@@ -961,11 +993,11 @@ OpenConsoleW(LPCWSTR wsName,
     ULONG CsrRequest;
     NTSTATUS Status = STATUS_SUCCESS;
 
-    if (0 == _wcsicmp(wsName, L"CONIN$"))
+    if (wsName && 0 == _wcsicmp(wsName, L"CONIN$"))
     {
         CsrRequest = MAKE_CSR_API(GET_INPUT_HANDLE, CSR_NATIVE);
     }
-    else if (0 == _wcsicmp(wsName, L"CONOUT$"))
+    else if (wsName && 0 == _wcsicmp(wsName, L"CONOUT$"))
     {
         CsrRequest = MAKE_CSR_API(GET_OUTPUT_HANDLE, CSR_NATIVE);
     }
@@ -990,6 +1022,7 @@ OpenConsoleW(LPCWSTR wsName,
     /* Structures for GET_INPUT_HANDLE and GET_OUTPUT_HANDLE requests are identical */
     Request.Data.GetInputHandleRequest.Access = dwDesiredAccess;
     Request.Data.GetInputHandleRequest.Inheritable = bInheritHandle;
+    Request.Data.GetInputHandleRequest.ShareMode = dwShareMode;
 
     Status = CsrClientCallServer(&Request,
                                  NULL,
@@ -1001,7 +1034,7 @@ OpenConsoleW(LPCWSTR wsName,
         return INVALID_HANDLE_VALUE;
     }
 
-    return Request.Data.GetInputHandleRequest.InputHandle;
+    return Request.Data.GetInputHandleRequest.Handle;
 }
 
 
@@ -1659,6 +1692,7 @@ AllocConsole(VOID)
 
     Request.Data.AllocConsoleRequest.CtrlDispatcher = ConsoleControlDispatcher;
     Request.Data.AllocConsoleRequest.ConsoleNeeded = TRUE;
+    Request.Data.AllocConsoleRequest.Visible = TRUE;
 
     CsrRequest = MAKE_CSR_API(ALLOC_CONSOLE, CSR_CONSOLE);
 
@@ -3054,16 +3088,29 @@ FlushConsoleInputBuffer(HANDLE hConsoleInput)
 /*--------------------------------------------------------------
  *     SetConsoleScreenBufferSize
  *
- * @unimplemented
+ * @implemented
  */
 BOOL
 WINAPI
 SetConsoleScreenBufferSize(HANDLE hConsoleOutput,
                            COORD dwSize)
 {
-    DPRINT1("SetConsoleScreenBufferSize(0x%x, 0x%x) UNIMPLEMENTED!\n", hConsoleOutput, dwSize);
-    SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-    return FALSE;
+    CSR_API_MESSAGE Request;
+    ULONG CsrRequest;
+    NTSTATUS Status;
+
+    CsrRequest = MAKE_CSR_API(SET_SCREEN_BUFFER_SIZE, CSR_CONSOLE);
+    Request.Data.SetScreenBufferSize.OutputHandle = hConsoleOutput;
+    Request.Data.SetScreenBufferSize.Size = dwSize;
+
+    Status = CsrClientCallServer(&Request, NULL, CsrRequest, sizeof(CSR_API_MESSAGE));
+    if (!NT_SUCCESS(Status) || !NT_SUCCESS(Status = Request.Status))
+    {
+        SetLastErrorByStatus(Status);
+        return FALSE;
+    }
+
+    return TRUE;
 }
 
 /*--------------------------------------------------------------
@@ -3235,38 +3282,37 @@ static
 BOOL
 AddConsoleCtrlHandler(PHANDLER_ROUTINE HandlerRoutine)
 {
+    PHANDLER_ROUTINE* NewCtrlHandlers = NULL;
+
     if (HandlerRoutine == NULL)
     {
         NtCurrentPeb()->ProcessParameters->ConsoleFlags = TRUE;
-        return(TRUE);
+        return TRUE;
     }
-    else
+    
+    if (NrCtrlHandlers == NrAllocatedHandlers)
     {
-        NrCtrlHandlers++;
-        if (CtrlHandlers == NULL)
-        {
-            CtrlHandlers = RtlAllocateHeap(RtlGetProcessHeap(),
-                                           HEAP_ZERO_MEMORY,
-                                           NrCtrlHandlers * sizeof(PHANDLER_ROUTINE));
-        }
-        else
+        NewCtrlHandlers = RtlAllocateHeap(RtlGetProcessHeap(),
+                                          0,
+                                          (NrCtrlHandlers + 4) * sizeof(PHANDLER_ROUTINE));
+        if (NewCtrlHandlers == NULL)   
         {
-            CtrlHandlers = RtlReAllocateHeap(RtlGetProcessHeap(),
-                                             HEAP_ZERO_MEMORY,
-                                             (PVOID)CtrlHandlers,
-                                             NrCtrlHandlers * sizeof(PHANDLER_ROUTINE));
-        }
-
-        if (CtrlHandlers == NULL)
-        {
-            NrCtrlHandlers = 0;
             SetLastError(ERROR_NOT_ENOUGH_MEMORY);
             return FALSE;
         }
-
-        CtrlHandlers[NrCtrlHandlers - 1] = HandlerRoutine;
-        return TRUE;
+        
+        memmove(NewCtrlHandlers, CtrlHandlers, sizeof(PHANDLER_ROUTINE) * NrCtrlHandlers);
+        
+        if (NrAllocatedHandlers > 1) RtlFreeHeap(RtlGetProcessHeap(), 0, CtrlHandlers);
+        
+        CtrlHandlers = NewCtrlHandlers;
+        NrAllocatedHandlers += 4;
     }
+    
+    ASSERT(NrCtrlHandlers < NrAllocatedHandlers);
+
+    CtrlHandlers[NrCtrlHandlers++] = HandlerRoutine;
+    return TRUE;
 }
 
 
@@ -3279,30 +3325,27 @@ RemoveConsoleCtrlHandler(PHANDLER_ROUTINE HandlerRoutine)
     if (HandlerRoutine == NULL)
     {
         NtCurrentPeb()->ProcessParameters->ConsoleFlags = FALSE;
-        return(TRUE);
+        return TRUE;
     }
-    else
+
+    for (i = 0; i < NrCtrlHandlers; i++)
     {
-        for (i = 0; i < NrCtrlHandlers; i++)
+        if (CtrlHandlers[i] == HandlerRoutine)
         {
-            if ( ((void*)(CtrlHandlers[i])) == (void*)HandlerRoutine)
+            if (i < (NrCtrlHandlers - 1))
             {
-                NrCtrlHandlers--;
-                memmove(CtrlHandlers + i,
-                        CtrlHandlers + i + 1,
-                        (NrCtrlHandlers - i) * sizeof(PHANDLER_ROUTINE));
-
-                CtrlHandlers = RtlReAllocateHeap(RtlGetProcessHeap(),
-                                                 HEAP_ZERO_MEMORY,
-                                                 (PVOID)CtrlHandlers,
-                                                 NrCtrlHandlers * sizeof(PHANDLER_ROUTINE));
-                return(TRUE);
+                memmove(&CtrlHandlers[i],
+                        &CtrlHandlers[i+1],
+                        (NrCtrlHandlers - i + 1) * sizeof(PHANDLER_ROUTINE));
             }
+
+            NrCtrlHandlers--;
+            return TRUE;
         }
     }
 
     SetLastError(ERROR_INVALID_PARAMETER);
-    return(FALSE);
+    return FALSE;
 }
 
 
@@ -3710,7 +3753,8 @@ WINAPI
 GetConsoleProcessList(LPDWORD lpdwProcessList,
                       DWORD dwProcessCount)
 {
-    PCSR_API_MESSAGE Request;
+    PCSR_CAPTURE_BUFFER CaptureBuffer;
+    CSR_API_MESSAGE Request;
     ULONG CsrRequest;
     ULONG nProcesses;
     NTSTATUS Status;
@@ -3721,43 +3765,38 @@ GetConsoleProcessList(LPDWORD lpdwProcessList,
         return 0;
     }
 
-    Request = RtlAllocateHeap(RtlGetProcessHeap(),
-                              0,
-                              max(sizeof(CSR_API_MESSAGE),
-                              CSR_API_MESSAGE_HEADER_SIZE(CSRSS_GET_PROCESS_LIST)
-                                + min (dwProcessCount, CSRSS_MAX_GET_PROCESS_LIST / sizeof(DWORD)) * sizeof(DWORD)));
-    if (Request == NULL)
+    CaptureBuffer = CsrAllocateCaptureBuffer(1, dwProcessCount * sizeof(DWORD));
+    if (CaptureBuffer == NULL)
     {
         SetLastError(ERROR_NOT_ENOUGH_MEMORY);
         return FALSE;
     }
 
     CsrRequest = MAKE_CSR_API(GET_PROCESS_LIST, CSR_CONSOLE);
-    Request->Data.GetProcessListRequest.nMaxIds = min (dwProcessCount, CSRSS_MAX_GET_PROCESS_LIST / sizeof(DWORD));
+    Request.Data.GetProcessListRequest.nMaxIds = dwProcessCount;
+    CsrAllocateMessagePointer(CaptureBuffer,
+                              dwProcessCount * sizeof(DWORD),
+                              (PVOID*)&Request.Data.GetProcessListRequest.ProcessId);
 
-    Status = CsrClientCallServer(Request,
-                                 NULL,
+    Status = CsrClientCallServer(&Request,
+                                 CaptureBuffer,
                                  CsrRequest,
-                                 max(sizeof(CSR_API_MESSAGE),
-                                 CSR_API_MESSAGE_HEADER_SIZE(CSRSS_GET_PROCESS_LIST)
-                                    + Request->Data.GetProcessListRequest.nMaxIds * sizeof(DWORD)));
-    if (!NT_SUCCESS(Status) || !NT_SUCCESS(Status = Request->Status))
+                                 sizeof(CSR_API_MESSAGE));
+    if (!NT_SUCCESS(Status) || !NT_SUCCESS(Status = Request.Status))
     {
-        RtlFreeHeap(RtlGetProcessHeap(), 0, Request);
         SetLastErrorByStatus (Status);
         nProcesses = 0;
     }
     else
     {
-        nProcesses = Request->Data.GetProcessListRequest.nProcessIdsCopied;
+        nProcesses = Request.Data.GetProcessListRequest.nProcessIdsTotal;
         if (dwProcessCount >= nProcesses)
         {
-            memcpy(lpdwProcessList, Request->Data.GetProcessListRequest.ProcessId, nProcesses * sizeof(DWORD));
+            memcpy(lpdwProcessList, Request.Data.GetProcessListRequest.ProcessId, nProcesses * sizeof(DWORD));
         }
     }
 
-    RtlFreeHeap(RtlGetProcessHeap(), 0, Request);
-
+    CsrFreeCaptureBuffer(CaptureBuffer);
     return nProcesses;
 }