[WIN32CSR] Protect ProcessData->Console with the HandleTableLock.
[reactos.git] / reactos / subsystems / win32 / csrss / win32csr / conio.c
index 19223ad..cb75428 100644 (file)
@@ -8,9 +8,8 @@
 
 /* INCLUDES ******************************************************************/
 
-#include "w32csr.h"
-
 #define NDEBUG
+#include "w32csr.h"
 #include <debug.h>
 
 /* GLOBALS *******************************************************************/
 #define ConsoleInputUnicodeCharToAnsiChar(Console, dChar, sWChar) \
   WideCharToMultiByte((Console)->CodePage, 0, (sWChar), 1, (dChar), 1, NULL, NULL)
 
+#define ConsoleInputAnsiCharToUnicodeChar(Console, dWChar, sChar) \
+  MultiByteToWideChar((Console)->CodePage, 0, (sChar), 1, (dWChar), 1)
+
 #define ConsoleUnicodeCharToAnsiChar(Console, dChar, sWChar) \
   WideCharToMultiByte((Console)->OutputCodePage, 0, (sWChar), 1, (dChar), 1, NULL, NULL)
 
-#define ConsoleAnsiCharToUnicodeChar(Console, sWChar, dChar) \
-  MultiByteToWideChar((Console)->OutputCodePage, 0, (dChar), 1, (sWChar), 1)
+#define ConsoleAnsiCharToUnicodeChar(Console, dWChar, sChar) \
+  MultiByteToWideChar((Console)->OutputCodePage, 0, (sChar), 1, (dWChar), 1)
 
 
 /* FUNCTIONS *****************************************************************/
 NTSTATUS FASTCALL
 ConioConsoleFromProcessData(PCSRSS_PROCESS_DATA ProcessData, PCSRSS_CONSOLE *Console)
 {
-  PCSRSS_CONSOLE ProcessConsole = ProcessData->Console;
+  PCSRSS_CONSOLE ProcessConsole;
+
+  RtlEnterCriticalSection(&ProcessData->HandleTableLock);
+  ProcessConsole = ProcessData->Console;
 
   if (!ProcessConsole)
     {
       *Console = NULL;
+      RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
       return STATUS_INVALID_HANDLE;
     }
 
   InterlockedIncrement(&ProcessConsole->Header.ReferenceCount);
+  RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
   EnterCriticalSection(&(ProcessConsole->Header.Lock));
   *Console = ProcessConsole;
 
@@ -66,7 +73,7 @@ ConioConsoleCtrlEventTimeout(DWORD Event, PCSRSS_PROCESS_DATA ProcessData, DWORD
 
       Thread = CreateRemoteThread(ProcessData->Process, NULL, 0,
                                   (LPTHREAD_START_ROUTINE) ProcessData->CtrlDispatcher,
-                                  (PVOID) Event, 0, NULL);
+                                  UlongToPtr(Event), 0, NULL);
       if (NULL == Thread)
         {
           DPRINT1("Failed thread creation (Error: 0x%x)\n", GetLastError());
@@ -133,7 +140,7 @@ CsrInitConsoleScreenBuffer(PCSRSS_CONSOLE Console,
   return STATUS_SUCCESS;
 }
 
-static NTSTATUS STDCALL
+static NTSTATUS WINAPI
 CsrInitConsole(PCSRSS_CONSOLE Console)
 {
   NTSTATUS Status;
@@ -185,7 +192,7 @@ CsrInitConsole(PCSRSS_CONSOLE Console)
     }
   /* init screen buffer with defaults */
   NewBuffer->CursorInfo.bVisible = TRUE;
-  NewBuffer->CursorInfo.dwSize = 5;
+  NewBuffer->CursorInfo.dwSize = CSR_DEFAULT_CURSOR_SIZE;
   /* make console active, and insert into console list */
   Console->ActiveBuffer = (PCSRSS_SCREEN_BUFFER) NewBuffer;
 
@@ -245,9 +252,11 @@ CSR_API(CsrAllocConsole)
     Request->Header.u1.s1.TotalLength = sizeof(CSR_API_MESSAGE);
     Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE);
 
+    RtlEnterCriticalSection(&ProcessData->HandleTableLock);
     if (ProcessData->Console)
     {
         DPRINT1("Process already has a console\n");
+        RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
         return STATUS_INVALID_PARAMETER;
     }
 
@@ -255,6 +264,7 @@ CSR_API(CsrAllocConsole)
     if (!Request->Data.AllocConsoleRequest.ConsoleNeeded)
     {
         DPRINT("No console needed\n");
+        RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
         return STATUS_SUCCESS;
     }
 
@@ -268,6 +278,7 @@ CSR_API(CsrAllocConsole)
         if (NULL == Console)
         {
             DPRINT1("Not enough memory for console\n");
+            RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
             return STATUS_NO_MEMORY;
         }
         /* initialize list head */
@@ -280,6 +291,7 @@ CSR_API(CsrAllocConsole)
         {
             DPRINT1("Console init failed\n");
             HeapFree(Win32CsrApiHeap, 0, Console);
+            RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
             return Status;
         }
     }
@@ -311,6 +323,7 @@ CSR_API(CsrAllocConsole)
             DPRINT1("Failed to insert object\n");
             ConioDeleteConsole((Object_t *) Console);
             ProcessData->Console = 0;
+            RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
             return Status;
         }
 
@@ -326,6 +339,7 @@ CSR_API(CsrAllocConsole)
             Win32CsrReleaseObject(ProcessData,
                                   Request->Data.AllocConsoleRequest.InputHandle);
             ProcessData->Console = 0;
+            RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
             return Status;
         }
     }
@@ -349,6 +363,7 @@ CSR_API(CsrAllocConsole)
                                   Request->Data.AllocConsoleRequest.InputHandle);
         }
         ProcessData->Console = 0;
+        RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
         return Status;
     }
 
@@ -362,30 +377,16 @@ CSR_API(CsrAllocConsole)
         InsertHeadList(&ProcessData->Console->ProcessList, &ProcessData->ProcessEntry);
     }
 
+    RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
     return STATUS_SUCCESS;
 }
 
 CSR_API(CsrFreeConsole)
 {
-  PCSRSS_CONSOLE Console;
-
-
   Request->Header.u1.s1.TotalLength = sizeof(CSR_API_MESSAGE);
   Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE);
 
-  if (ProcessData->Console == NULL)
-    {
-      return STATUS_INVALID_PARAMETER;
-    }
-
-  Console = ProcessData->Console;
-  ProcessData->Console = NULL;
-  RemoveEntryList(&ProcessData->ProcessEntry);
-  if (0 == InterlockedDecrement(&Console->Header.ReferenceCount))
-    {
-      ConioDeleteConsole((Object_t *) Console);
-    }
-  return STATUS_SUCCESS;
+  return Win32CsrReleaseConsole(ProcessData);
 }
 
 static VOID FASTCALL
@@ -574,7 +575,6 @@ CSR_API(CsrReadConsole)
       CurrentEntry = RemoveHeadList(&Console->InputEvents);
       if (IsListEmpty(&Console->InputEvents))
       {
-         CHECKPOINT;
          ResetEvent(Console->ActiveEvent);
       }
       Input = CONTAINING_RECORD(CurrentEntry, ConsoleInput, ListEntry);
@@ -618,7 +618,7 @@ CSR_API(CsrReadConsole)
           else
             {
               if(Request->Data.ReadConsoleRequest.Unicode)
-                UnicodeBuffer[i] = Input->InputEvent.Event.KeyEvent.uChar.AsciiChar; /* FIXME */
+                ConsoleInputAnsiCharToUnicodeChar(Console, &UnicodeBuffer[i], &Input->InputEvent.Event.KeyEvent.uChar.AsciiChar);
               else
                 Buffer[i] = Input->InputEvent.Event.KeyEvent.uChar.AsciiChar;
             }
@@ -681,7 +681,7 @@ CSR_API(CsrReadConsole)
   return Status;
 }
 
-BOOLEAN __inline ConioGetIntersection(
+__inline BOOLEAN ConioGetIntersection(
   RECT *Intersection,
   RECT *Rect1,
   RECT *Rect2)
@@ -707,7 +707,7 @@ BOOLEAN __inline ConioGetIntersection(
   return TRUE;
 }
 
-BOOLEAN __inline ConioGetUnion(
+__inline BOOLEAN ConioGetUnion(
   RECT *Union,
   RECT *Rect1,
   RECT *Rect2)
@@ -895,7 +895,7 @@ CSR_API(CsrWriteConsole)
   return Status;
 }
 
-VOID STDCALL
+VOID WINAPI
 ConioDeleteScreenBuffer(Object_t *Object)
 {
   PCSRSS_SCREEN_BUFFER Buffer = (PCSRSS_SCREEN_BUFFER) Object;
@@ -915,7 +915,7 @@ ConioDrawConsole(PCSRSS_CONSOLE Console)
 }
 
 
-VOID STDCALL
+VOID WINAPI
 ConioDeleteConsole(Object_t *Object)
 {
   PCSRSS_CONSOLE Console = (PCSRSS_CONSOLE) Object;
@@ -947,7 +947,7 @@ ConioDeleteConsole(Object_t *Object)
   HeapFree(Win32CsrApiHeap, 0, Console);
 }
 
-VOID STDCALL
+VOID WINAPI
 CsrInitConsoleSupport(VOID)
 {
   DPRINT("CSR: CsrInitConsoleSupport()\n");
@@ -960,7 +960,6 @@ ConioProcessChar(PCSRSS_CONSOLE Console,
                  ConsoleInput *KeyEventRecord)
 {
   BOOL updown;
-  BOOL bClientWake = FALSE;
   ConsoleInput *TempInput;
 
   if (0 != (Console->Mode & (ENABLE_PROCESSED_INPUT | ENABLE_LINE_INPUT)))
@@ -1004,8 +1003,6 @@ ConioProcessChar(PCSRSS_CONSOLE Console,
         {
           Console->WaitingLines++;
         }
-      bClientWake = TRUE;
-      SetEvent(Console->ActiveEvent);
     }
   KeyEventRecord->Echoed = FALSE;
   if (0 != (Console->Mode & (ENABLE_PROCESSED_INPUT | ENABLE_LINE_INPUT))
@@ -1037,10 +1034,7 @@ ConioProcessChar(PCSRSS_CONSOLE Console,
           RemoveEntryList(&KeyEventRecord->ListEntry);
           HeapFree(Win32CsrApiHeap, 0, KeyEventRecord);
           Console->WaitingChars -= 2;
-        }
-      else
-        {
-          SetEvent(Console->ActiveEvent);
+          return;
         }
     }
   else
@@ -1061,10 +1055,7 @@ ConioProcessChar(PCSRSS_CONSOLE Console,
     }
 
   /* Console->WaitingChars++; */
-  if (bClientWake || 0 == (Console->Mode & ENABLE_LINE_INPUT))
-    {
-      SetEvent(Console->ActiveEvent);
-    }
+  SetEvent(Console->ActiveEvent);
 }
 
 static DWORD FASTCALL
@@ -1097,7 +1088,7 @@ ConioGetShiftState(PBYTE KeyState)
   return ssOut;
 }
 
-VOID STDCALL
+VOID WINAPI
 ConioProcessKey(MSG *msg, PCSRSS_CONSOLE Console, BOOL TextMode)
 {
   static BYTE KeyState[256] = { 0 };
@@ -1983,6 +1974,7 @@ CSR_API(CsrCreateScreenBuffer)
 
   DPRINT("CsrCreateScreenBuffer\n");
 
+  RtlEnterCriticalSection(&ProcessData->HandleTableLock);
   Status = ConioConsoleFromProcessData(ProcessData, &Console);
   if (! NT_SUCCESS(Status))
     {
@@ -2006,7 +1998,7 @@ CSR_API(CsrCreateScreenBuffer)
       else
         {
           Buff->CursorInfo.bVisible = TRUE;
-          Buff->CursorInfo.dwSize = 5;
+          Buff->CursorInfo.dwSize = CSR_DEFAULT_CURSOR_SIZE;
         }
 
       if (Buff->MaxX == 0)
@@ -2035,6 +2027,7 @@ CSR_API(CsrCreateScreenBuffer)
     }
 
   ConioUnlockConsole(Console);
+  RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
   return Status;
 }
 
@@ -2981,14 +2974,16 @@ CSR_API(CsrSetConsoleCodePage)
 
   Request->Header.u1.s1.TotalLength = sizeof(CSR_API_MESSAGE);
   Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE);
+
   if (IsValidCodePage(Request->Data.SetConsoleCodePage.CodePage))
     {
       Console->CodePage = Request->Data.SetConsoleCodePage.CodePage;
       ConioUnlockConsole(Console);
       return STATUS_SUCCESS;
     }
+
   ConioUnlockConsole(Console);
-  return STATUS_UNSUCCESSFUL;
+  return STATUS_INVALID_PARAMETER;
 }
 
 CSR_API(CsrGetConsoleOutputCodePage)
@@ -3026,14 +3021,16 @@ CSR_API(CsrSetConsoleOutputCodePage)
 
   Request->Header.u1.s1.TotalLength = sizeof(CSR_API_MESSAGE);
   Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE);
+
   if (IsValidCodePage(Request->Data.SetConsoleOutputCodePage.CodePage))
     {
       Console->OutputCodePage = Request->Data.SetConsoleOutputCodePage.CodePage;
       ConioUnlockConsole(Console);
       return STATUS_SUCCESS;
     }
+
   ConioUnlockConsole(Console);
-  return STATUS_UNSUCCESSFUL;
+  return STATUS_INVALID_PARAMETER;
 }
 
 CSR_API(CsrGetProcessList)
@@ -3125,4 +3122,33 @@ CSR_API(CsrGenerateCtrlEvent)
   return Status;
 }
 
+CSR_API(CsrSetScreenBufferSize)
+{
+    NTSTATUS Status;
+    PCSRSS_CONSOLE Console;
+    PCSRSS_SCREEN_BUFFER Buff;
+
+    Request->Header.u1.s1.TotalLength = sizeof(CSR_API_MESSAGE);
+    Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE);
+
+    Status = ConioConsoleFromProcessData(ProcessData, &Console);
+    if (!NT_SUCCESS(Status))
+    {
+        return Status;
+    }
+
+    Status = ConioLockScreenBuffer(ProcessData, Request->Data.SetScreenBufferSize.OutputHandle, &Buff, GENERIC_WRITE);
+    if (!NT_SUCCESS(Status))
+    {
+        ConioUnlockConsole(Console);
+        return Status;
+    }
+
+    Status = ConioResizeBuffer(Console, Buff, Request->Data.SetScreenBufferSize.Size);
+    ConioUnlockScreenBuffer(Buff);
+    ConioUnlockConsole(Console);
+
+    return Status;
+}
+
 /* EOF */