[WIN32CSR]
authorJeffrey Morlan <mrnobo1024@yahoo.com>
Sun, 23 May 2010 05:33:21 +0000 (05:33 +0000)
committerJeffrey Morlan <mrnobo1024@yahoo.com>
Sun, 23 May 2010 05:33:21 +0000 (05:33 +0000)
- Simplify locking: having a lock for each screen buffer is overkill since most programs only use one screen buffer at a time. (besides, almost all APIs were taking the console lock anyway) Reduce to just having one lock for a console.
- Instead of keeping track of how many references a screen buffer has, keep track of handles only.  When all handles to a screen buffer are closed, it should be deleted even if it's the active buffer (not yet implemented).

svn path=/trunk/; revision=47317

reactos/subsystems/win32/csrss/win32csr/conio.c
reactos/subsystems/win32/csrss/win32csr/conio.h
reactos/subsystems/win32/csrss/win32csr/guiconsole.c
reactos/subsystems/win32/csrss/win32csr/handle.c
reactos/subsystems/win32/csrss/win32csr/win32csr.h

index cb75428..4b8e65c 100644 (file)
@@ -53,9 +53,9 @@ ConioConsoleFromProcessData(PCSRSS_PROCESS_DATA ProcessData, PCSRSS_CONSOLE *Con
       return STATUS_INVALID_HANDLE;
     }
 
-  InterlockedIncrement(&ProcessConsole->Header.ReferenceCount);
+  InterlockedIncrement(&ProcessConsole->ReferenceCount);
   RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
-  EnterCriticalSection(&(ProcessConsole->Header.Lock));
+  EnterCriticalSection(&(ProcessConsole->Lock));
   *Console = ProcessConsole;
 
   return STATUS_SUCCESS;
@@ -117,7 +117,8 @@ CsrInitConsoleScreenBuffer(PCSRSS_CONSOLE Console,
   DPRINT("CsrInitConsoleScreenBuffer Size X %d Size Y %d\n", Buffer->MaxX, Buffer->MaxY);
 
   Buffer->Header.Type = CONIO_SCREEN_BUFFER_MAGIC;
-  Buffer->Header.ReferenceCount = 0;
+  Buffer->Header.Console = Console;
+  Buffer->Header.HandleCount = 0;
   Buffer->ShowX = 0;
   Buffer->ShowY = 0;
   Buffer->VirtualY = 0;
@@ -126,7 +127,6 @@ CsrInitConsoleScreenBuffer(PCSRSS_CONSOLE Console,
     {
       return STATUS_INSUFFICIENT_RESOURCES;
     }
-  InitializeCriticalSection(&Buffer->Header.Lock);
   ConioInitScreenBuffer(Console, Buffer);
   /* initialize buffer to be empty with default attributes */
   for (Buffer->CurrentY = 0 ; Buffer->CurrentY < Buffer->MaxY; Buffer->CurrentY++)
@@ -154,11 +154,12 @@ CsrInitConsole(PCSRSS_CONSOLE Console)
   //FIXME
   RtlCreateUnicodeString(&Console->Title, L"Command Prompt");
 
-  Console->Header.ReferenceCount = 0;
+  Console->ReferenceCount = 0;
   Console->WaitingChars = 0;
   Console->WaitingLines = 0;
   Console->EchoCount = 0;
   Console->Header.Type = CONIO_CONSOLE_MAGIC;
+  Console->Header.Console = Console;
   Console->Mode = ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT | ENABLE_PROCESSED_INPUT | ENABLE_MOUSE_INPUT;
   Console->EarlyReturn = FALSE;
   Console->ActiveBuffer = NULL;
@@ -177,7 +178,7 @@ CsrInitConsole(PCSRSS_CONSOLE Console)
       return STATUS_UNSUCCESSFUL;
     }
   Console->PrivateData = NULL;
-  InitializeCriticalSection(&Console->Header.Lock);
+  InitializeCriticalSection(&Console->Lock);
 
   GuiMode = DtbgIsDesktopVisible();
 
@@ -186,7 +187,7 @@ CsrInitConsole(PCSRSS_CONSOLE Console)
   if (NULL == NewBuffer)
     {
       RtlFreeUnicodeString(&Console->Title);
-      DeleteCriticalSection(&Console->Header.Lock);
+      DeleteCriticalSection(&Console->Lock);
       CloseHandle(Console->ActiveEvent);
       return STATUS_INSUFFICIENT_RESOURCES;
     }
@@ -212,7 +213,7 @@ CsrInitConsole(PCSRSS_CONSOLE Console)
         {
           HeapFree(Win32CsrApiHeap,0, NewBuffer);
           RtlFreeUnicodeString(&Console->Title);
-          DeleteCriticalSection(&Console->Header.Lock);
+          DeleteCriticalSection(&Console->Lock);
           CloseHandle(Console->ActiveEvent);
           DPRINT1("GuiInitConsole: failed\n");
           return Status;
@@ -224,16 +225,13 @@ CsrInitConsole(PCSRSS_CONSOLE Console)
     {
       ConioCleanupConsole(Console);
       RtlFreeUnicodeString(&Console->Title);
-      DeleteCriticalSection(&Console->Header.Lock);
+      DeleteCriticalSection(&Console->Lock);
       CloseHandle(Console->ActiveEvent);
       HeapFree(Win32CsrApiHeap, 0, NewBuffer);
       DPRINT1("CsrInitConsoleScreenBuffer: failed\n");
       return Status;
     }
 
-  /* add a reference count because the buffer is tied to the console */
-  InterlockedIncrement(&Console->ActiveBuffer->Header.ReferenceCount);
-
   /* copy buffer contents to screen */
   ConioDrawConsole(Console);
 
@@ -308,7 +306,7 @@ CSR_API(CsrAllocConsole)
     Request->Data.AllocConsoleRequest.Console = Console;
 
     /* Add a reference count because the process is tied to the console */
-    Console->Header.ReferenceCount++;
+    _InterlockedIncrement(&Console->ReferenceCount);
 
     if (NewConsole || !ProcessData->bInheritHandles)
     {
@@ -836,15 +834,16 @@ CSR_API(CsrWriteConsole)
       Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE);
       return STATUS_INVALID_PARAMETER;
     }
-  Status = ConioConsoleFromProcessData(ProcessData, &Console);
 
   Request->Header.u1.s1.TotalLength = sizeof(CSR_API_MESSAGE);
   Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE);
 
+  Status = ConioLockScreenBuffer(ProcessData, Request->Data.WriteConsoleRequest.ConsoleHandle, &Buff, GENERIC_WRITE);
   if (! NT_SUCCESS(Status))
     {
       return Status;
     }
+  Console = Buff->Header.Console;
 
   if(Request->Data.WriteConsoleRequest.Unicode)
     {
@@ -872,7 +871,6 @@ CSR_API(CsrWriteConsole)
 
   if (Buffer)
     {
-      Status = ConioLockScreenBuffer(ProcessData, Request->Data.WriteConsoleRequest.ConsoleHandle, &Buff, GENERIC_WRITE);
       if (NT_SUCCESS(Status))
         {
           Status = ConioWriteConsole(Console, Buff, Buffer,
@@ -881,14 +879,13 @@ CSR_API(CsrWriteConsole)
             {
               Written = Request->Data.WriteConsoleRequest.NrCharactersToWrite;
             }
-          ConioUnlockScreenBuffer(Buff);
         }
       if (Request->Data.WriteConsoleRequest.Unicode)
         {
           RtlFreeHeap(GetProcessHeap(), 0, Buffer);
         }
     }
-  ConioUnlockConsole(Console);
+  ConioUnlockScreenBuffer(Buff);
 
   Request->Data.WriteConsoleRequest.NrCharactersWritten = Written;
 
@@ -899,7 +896,6 @@ VOID WINAPI
 ConioDeleteScreenBuffer(Object_t *Object)
 {
   PCSRSS_SCREEN_BUFFER Buffer = (PCSRSS_SCREEN_BUFFER) Object;
-  DeleteCriticalSection(&Buffer->Header.Lock);
   HeapFree(Win32CsrApiHeap, 0, Buffer->Buffer);
   HeapFree(Win32CsrApiHeap, 0, Buffer);
 }
@@ -933,15 +929,12 @@ ConioDeleteConsole(Object_t *Object)
     }
 
   ConioCleanupConsole(Console);
-  if (0 == InterlockedDecrement(&Console->ActiveBuffer->Header.ReferenceCount))
-    {
-      ConioDeleteScreenBuffer((Object_t *) Console->ActiveBuffer);
-    }
+  ConioDeleteScreenBuffer((Object_t *) Console->ActiveBuffer);
 
   Console->ActiveBuffer = NULL;
 
   CloseHandle(Console->ActiveEvent);
-  DeleteCriticalSection(&Console->Header.Lock);
+  DeleteCriticalSection(&Console->Lock);
   RtlFreeUnicodeString(&Console->Title);
   IntDeleteAllAliases(Console->Aliases);
   HeapFree(Win32CsrApiHeap, 0, Console);
@@ -1280,17 +1273,12 @@ CSR_API(CsrGetScreenBufferInfo)
   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.ScreenBufferInfoRequest.ConsoleHandle, &Buff, GENERIC_READ);
   if (! NT_SUCCESS(Status))
     {
-      ConioUnlockConsole(Console);
       return Status;
     }
+  Console = Buff->Header.Console;
   pInfo = &Request->Data.ScreenBufferInfoRequest.Info;
   pInfo->dwSize.X = Buff->MaxX;
   pInfo->dwSize.Y = Buff->MaxY;
@@ -1304,7 +1292,6 @@ CSR_API(CsrGetScreenBufferInfo)
   pInfo->dwMaximumWindowSize.X = Buff->MaxX;
   pInfo->dwMaximumWindowSize.Y = Buff->MaxY;
   ConioUnlockScreenBuffer(Buff);
-  ConioUnlockConsole(Console);
 
   return STATUS_SUCCESS;
 }
@@ -1319,21 +1306,15 @@ CSR_API(CsrSetCursor)
 
   DPRINT("CsrSetCursor\n");
 
-  Status = ConioConsoleFromProcessData(ProcessData, &Console);
-  if (! NT_SUCCESS(Status))
-    {
-      return Status;
-    }
-
   Request->Header.u1.s1.TotalLength = sizeof(CSR_API_MESSAGE);
   Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE);
 
   Status = ConioLockScreenBuffer(ProcessData, Request->Data.SetCursorRequest.ConsoleHandle, &Buff, GENERIC_WRITE);
   if (! NT_SUCCESS(Status))
     {
-      ConioUnlockConsole(Console);
       return Status;
     }
+  Console = Buff->Header.Console;
 
   NewCursorX = Request->Data.SetCursorRequest.Position.X;
   NewCursorY = Request->Data.SetCursorRequest.Position.Y;
@@ -1341,7 +1322,6 @@ CSR_API(CsrSetCursor)
       NewCursorY < 0 || NewCursorY >= Buff->MaxY)
     {
       ConioUnlockScreenBuffer(Buff);
-      ConioUnlockConsole(Console);
       return STATUS_INVALID_PARAMETER;
     }
   OldCursorX = Buff->CurrentX;
@@ -1353,13 +1333,11 @@ CSR_API(CsrSetCursor)
       if (! ConioSetScreenInfo(Console, Buff, OldCursorX, OldCursorY))
         {
           ConioUnlockScreenBuffer(Buff);
-          ConioUnlockConsole(Console);
           return STATUS_UNSUCCESSFUL;
         }
     }
 
   ConioUnlockScreenBuffer(Buff);
-  ConioUnlockConsole(Console);
 
   return STATUS_SUCCESS;
 }
@@ -1415,11 +1393,15 @@ CSR_API(CsrWriteConsoleOutputChar)
       return STATUS_INVALID_PARAMETER;
     }
 
-  Status = ConioConsoleFromProcessData(ProcessData, &Console);
+  Status = ConioLockScreenBuffer(ProcessData,
+                                 Request->Data.WriteConsoleOutputCharRequest.ConsoleHandle,
+                                 &Buff,
+                                 GENERIC_WRITE);
   Request->Header.u1.s1.TotalLength = sizeof(CSR_API_MESSAGE);
   Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE);
   if (NT_SUCCESS(Status))
     {
+      Console = Buff->Header.Console;
       if(Request->Data.WriteConsoleOutputCharRequest.Unicode)
         {
           Length = WideCharToMultiByte(Console->OutputCodePage, 0,
@@ -1446,10 +1428,6 @@ CSR_API(CsrWriteConsoleOutputChar)
 
       if (String)
         {
-          Status = ConioLockScreenBuffer(ProcessData,
-                                         Request->Data.WriteConsoleOutputCharRequest.ConsoleHandle,
-                                         &Buff,
-                                         GENERIC_WRITE);
           if (NT_SUCCESS(Status))
             {
               X = Request->Data.WriteConsoleOutputCharRequest.Coord.X;
@@ -1481,14 +1459,13 @@ CSR_API(CsrWriteConsoleOutputChar)
                 Request->Data.WriteConsoleOutputCharRequest.EndCoord.X = X;
                 Request->Data.WriteConsoleOutputCharRequest.EndCoord.Y = (Y + Buff->MaxY - Buff->VirtualY) % Buff->MaxY;
 
-                ConioUnlockScreenBuffer(Buff);
             }
           if (Request->Data.WriteConsoleRequest.Unicode)
             {
               RtlFreeHeap(GetProcessHeap(), 0, tmpString);
             }
         }
-      ConioUnlockConsole(Console);
+      ConioUnlockScreenBuffer(Buff);
     }
   Request->Data.WriteConsoleOutputCharRequest.NrCharactersWritten = Written;
   return Status;
@@ -1509,18 +1486,12 @@ CSR_API(CsrFillOutputChar)
   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.FillOutputRequest.ConsoleHandle, &Buff, GENERIC_WRITE);
   if (! NT_SUCCESS(Status))
     {
-      ConioUnlockConsole(Console);
       return Status;
     }
+  Console = Buff->Header.Console;
 
   X = Request->Data.FillOutputRequest.Position.X;
   Y = (Request->Data.FillOutputRequest.Position.Y + Buff->VirtualY) % Buff->MaxY;
@@ -1554,7 +1525,6 @@ CSR_API(CsrFillOutputChar)
     }
 
   ConioUnlockScreenBuffer(Buff);
-  ConioUnlockConsole(Console);
   Length = Request->Data.FillOutputRequest.Length;
   Request->Data.FillOutputRequest.NrCharactersWritten = Length;
   return STATUS_SUCCESS;
@@ -1661,13 +1631,8 @@ CSR_API(CsrWriteConsoleOutputAttrib)
       return STATUS_INVALID_PARAMETER;
     }
 
-  Status = ConioConsoleFromProcessData(ProcessData, &Console);
   Request->Header.u1.s1.TotalLength = sizeof(CSR_API_MESSAGE);
   Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE);
-  if (! NT_SUCCESS(Status))
-    {
-      return Status;
-    }
 
   Status = ConioLockScreenBuffer(ProcessData,
                                  Request->Data.WriteConsoleOutputAttribRequest.ConsoleHandle,
@@ -1675,9 +1640,9 @@ CSR_API(CsrWriteConsoleOutputAttrib)
                                  GENERIC_WRITE);
   if (! NT_SUCCESS(Status))
     {
-      ConioUnlockConsole(Console);
       return Status;
     }
+  Console = Buff->Header.Console;
 
   X = Request->Data.WriteConsoleOutputAttribRequest.Coord.X;
   Y = (Request->Data.WriteConsoleOutputAttribRequest.Coord.Y + Buff->VirtualY) % Buff->MaxY;
@@ -1706,8 +1671,6 @@ CSR_API(CsrWriteConsoleOutputAttrib)
       ConioDrawRegion(Console, &UpdateRect);
     }
 
-  ConioUnlockConsole(Console);
-
   Request->Data.WriteConsoleOutputAttribRequest.EndCoord.X = X;
   Request->Data.WriteConsoleOutputAttribRequest.EndCoord.Y = (Y + Buff->MaxY - Buff->VirtualY) % Buff->MaxY;
 
@@ -1728,20 +1691,14 @@ CSR_API(CsrFillOutputAttrib)
 
   DPRINT("CsrFillOutputAttrib\n");
 
-  Status = ConioConsoleFromProcessData(ProcessData, &Console);
-  if (! NT_SUCCESS(Status))
-    {
-      return Status;
-    }
-
   Request->Header.u1.s1.TotalLength = sizeof(CSR_API_MESSAGE);
   Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE);
   Status = ConioLockScreenBuffer(ProcessData, Request->Data.FillOutputAttribRequest.ConsoleHandle, &Buff, GENERIC_WRITE);
   if (! NT_SUCCESS(Status))
     {
-      ConioUnlockConsole(Console);
       return Status;
     }
+  Console = Buff->Header.Console;
 
   X = Request->Data.FillOutputAttribRequest.Coord.X;
   Y = (Request->Data.FillOutputAttribRequest.Coord.Y + Buff->VirtualY) % Buff->MaxY;
@@ -1771,7 +1728,6 @@ CSR_API(CsrFillOutputAttrib)
     }
 
   ConioUnlockScreenBuffer(Buff);
-  ConioUnlockConsole(Console);
 
   return STATUS_SUCCESS;
 }
@@ -1812,18 +1768,12 @@ CSR_API(CsrSetCursorInfo)
   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.SetCursorInfoRequest.ConsoleHandle, &Buff, GENERIC_WRITE);
   if (! NT_SUCCESS(Status))
     {
-      ConioUnlockConsole(Console);
       return Status;
     }
+  Console = Buff->Header.Console;
 
   Size = Request->Data.SetCursorInfoRequest.Info.dwSize;
   Visible = Request->Data.SetCursorInfoRequest.Info.bVisible;
@@ -1845,13 +1795,11 @@ CSR_API(CsrSetCursorInfo)
       if (! ConioSetCursorInfo(Console, Buff))
         {
           ConioUnlockScreenBuffer(Buff);
-          ConioUnlockConsole(Console);
           return STATUS_UNSUCCESSFUL;
         }
     }
 
   ConioUnlockScreenBuffer(Buff);
-  ConioUnlockConsole(Console);
 
   return STATUS_SUCCESS;
 }
@@ -1864,18 +1812,12 @@ CSR_API(CsrSetTextAttrib)
 
   DPRINT("CsrSetTextAttrib\n");
 
-  Status = ConioConsoleFromProcessData(ProcessData, &Console);
-  if (! NT_SUCCESS(Status))
-    {
-      return Status;
-    }
-
   Status = ConioLockScreenBuffer(ProcessData, Request->Data.SetCursorRequest.ConsoleHandle, &Buff, GENERIC_WRITE);
   if (! NT_SUCCESS(Status))
     {
-      ConioUnlockConsole(Console);
       return Status;
     }
+  Console = Buff->Header.Console;
 
   Buff->DefaultAttrib = Request->Data.SetAttribRequest.Attrib;
   if (Buff == Console->ActiveBuffer)
@@ -1883,13 +1825,11 @@ CSR_API(CsrSetTextAttrib)
       if (! ConioUpdateScreenInfo(Console, Buff))
         {
           ConioUnlockScreenBuffer(Buff);
-          ConioUnlockConsole(Console);
           return STATUS_UNSUCCESSFUL;
         }
     }
 
   ConioUnlockScreenBuffer(Buff);
-  ConioUnlockConsole(Console);
 
   return STATUS_SUCCESS;
 }
@@ -1904,9 +1844,9 @@ CSR_API(CsrSetConsoleMode)
 
   Request->Header.u1.s1.TotalLength = sizeof(CSR_API_MESSAGE);
   Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE);
-  Status = Win32CsrGetObject(ProcessData,
-                             Request->Data.SetConsoleModeRequest.ConsoleHandle,
-                             (Object_t **) &Console, GENERIC_WRITE);
+  Status = Win32CsrLockObject(ProcessData,
+                              Request->Data.SetConsoleModeRequest.ConsoleHandle,
+                              (Object_t **) &Console, GENERIC_WRITE, 0);
   if (! NT_SUCCESS(Status))
     {
       return Status;
@@ -1926,7 +1866,7 @@ CSR_API(CsrSetConsoleMode)
       Status = STATUS_INVALID_HANDLE;
     }
 
-  Win32CsrReleaseObjectByPointer((Object_t *)Console);
+  Win32CsrUnlockObject((Object_t *)Console);
 
   return Status;
 }
@@ -1941,8 +1881,8 @@ CSR_API(CsrGetConsoleMode)
 
   Request->Header.u1.s1.TotalLength = sizeof(CSR_API_MESSAGE);
   Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE);
-  Status = Win32CsrGetObject(ProcessData, Request->Data.GetConsoleModeRequest.ConsoleHandle,
-                             (Object_t **) &Console, GENERIC_READ);
+  Status = Win32CsrLockObject(ProcessData, Request->Data.GetConsoleModeRequest.ConsoleHandle,
+                              (Object_t **) &Console, GENERIC_READ, 0);
   if (! NT_SUCCESS(Status))
     {
       return Status;
@@ -1962,7 +1902,7 @@ CSR_API(CsrGetConsoleMode)
       Status = STATUS_INVALID_HANDLE;
     }
 
-  Win32CsrReleaseObjectByPointer((Object_t *)Console);
+  Win32CsrUnlockObject((Object_t *)Console);
   return Status;
 }
 
@@ -2039,43 +1979,33 @@ CSR_API(CsrSetScreenBuffer)
 
   DPRINT("CsrSetScreenBuffer\n");
 
-  Status = ConioConsoleFromProcessData(ProcessData, &Console);
-  if (! NT_SUCCESS(Status))
-    {
-      return Status;
-    }
-
   Request->Header.u1.s1.TotalLength = sizeof(CSR_API_MESSAGE);
   Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE);
 
   Status = ConioLockScreenBuffer(ProcessData, Request->Data.SetScreenBufferRequest.OutputHandle, &Buff, GENERIC_WRITE);
   if (! NT_SUCCESS(Status))
     {
-      ConioUnlockConsole(Console);
       return Status;
     }
+  Console = Buff->Header.Console;
 
   if (Buff == Console->ActiveBuffer)
     {
       ConioUnlockScreenBuffer(Buff);
-      ConioUnlockConsole(Console);
       return STATUS_SUCCESS;
     }
 
-  /* drop reference to old buffer, maybe delete */
-  if (! InterlockedDecrement(&Console->ActiveBuffer->Header.ReferenceCount))
+  /* If old buffer has no handles, it's now unreferenced */
+  if (Console->ActiveBuffer->Header.HandleCount == 0)
     {
       ConioDeleteScreenBuffer((Object_t *) Console->ActiveBuffer);
     }
   /* tie console to new buffer */
   Console->ActiveBuffer = Buff;
-  /* inc ref count on new buffer */
-  InterlockedIncrement(&Buff->Header.ReferenceCount);
   /* Redraw the console */
   ConioDrawConsole(Console);
 
   ConioUnlockScreenBuffer(Buff);
-  ConioUnlockConsole(Console);
 
   return STATUS_SUCCESS;
 }
@@ -2181,12 +2111,6 @@ CSR_API(CsrWriteConsoleOutput)
 
   DPRINT("CsrWriteConsoleOutput\n");
 
-  Status = ConioConsoleFromProcessData(ProcessData, &Console);
-  if (! NT_SUCCESS(Status))
-    {
-      return Status;
-    }
-
   Request->Header.u1.s1.TotalLength = sizeof(CSR_API_MESSAGE);
   Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE);
   Status = ConioLockScreenBuffer(ProcessData,
@@ -2195,9 +2119,9 @@ CSR_API(CsrWriteConsoleOutput)
                                  GENERIC_WRITE);
   if (! NT_SUCCESS(Status))
     {
-      ConioUnlockConsole(Console);
       return Status;
     }
+  Console = Buff->Header.Console;
 
   BufferSize = Request->Data.WriteConsoleOutputRequest.BufferSize;
   PSize = BufferSize.X * BufferSize.Y * sizeof(CHAR_INFO);
@@ -2208,7 +2132,6 @@ CSR_API(CsrWriteConsoleOutput)
        ((ULONG_PTR)ProcessData->CsrSectionViewBase + ProcessData->CsrSectionViewSize)))
     {
       ConioUnlockScreenBuffer(Buff);
-      ConioUnlockConsole(Console);
       return STATUS_ACCESS_VIOLATION;
     }
   WriteRegion.left = Request->Data.WriteConsoleOutputRequest.WriteRegion.Left;
@@ -2226,7 +2149,6 @@ CSR_API(CsrWriteConsoleOutput)
   if (! ConioGetIntersection(&WriteRegion, &ScreenBuffer, &WriteRegion))
     {
       ConioUnlockScreenBuffer(Buff);
-      ConioUnlockConsole(Console);
 
       /* It is okay to have a WriteRegion completely outside the screen buffer.
          No data is written then. */
@@ -2257,7 +2179,6 @@ CSR_API(CsrWriteConsoleOutput)
   ConioDrawRegion(Console, &WriteRegion);
 
   ConioUnlockScreenBuffer(Buff);
-  ConioUnlockConsole(Console);
 
   Request->Data.WriteConsoleOutputRequest.WriteRegion.Right = WriteRegion.left + SizeX - 1;
   Request->Data.WriteConsoleOutputRequest.WriteRegion.Bottom = WriteRegion.top + SizeY - 1;
@@ -2327,20 +2248,14 @@ CSR_API(CsrScrollConsoleScreenBuffer)
   DestinationOrigin = Request->Data.ScrollConsoleScreenBufferRequest.DestinationOrigin;
   Fill = Request->Data.ScrollConsoleScreenBufferRequest.Fill;
 
-  Status = ConioConsoleFromProcessData(ProcessData, &Console);
-  if (! NT_SUCCESS(Status))
-    {
-      return Status;
-    }
-
   Request->Header.u1.s1.TotalLength = sizeof(CSR_API_MESSAGE);
   Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE);
   Status = ConioLockScreenBuffer(ProcessData, ConsoleHandle, &Buff, GENERIC_WRITE);
   if (! NT_SUCCESS(Status))
     {
-      ConioUnlockConsole(Console);
       return Status;
     }
+  Console = Buff->Header.Console;
 
   ScrollRectangle.left = Request->Data.ScrollConsoleScreenBufferRequest.ScrollRectangle.Left;
   ScrollRectangle.top = Request->Data.ScrollConsoleScreenBufferRequest.ScrollRectangle.Top;
@@ -2352,7 +2267,6 @@ CSR_API(CsrScrollConsoleScreenBuffer)
   if (! ConioGetIntersection(&SrcRegion, &ScreenBuffer, &ScrollRectangle))
     {
       ConioUnlockScreenBuffer(Buff);
-      ConioUnlockConsole(Console);
       return STATUS_SUCCESS;
     }
 
@@ -2374,7 +2288,6 @@ CSR_API(CsrScrollConsoleScreenBuffer)
       ClipRectangle.bottom = Request->Data.ScrollConsoleScreenBufferRequest.ClipRectangle.Bottom;
       if (!ConioGetIntersection(&ClipRectangle, &ClipRectangle, &ScreenBuffer))
         {
-          ConioUnlockConsole(Console);
           ConioUnlockScreenBuffer(Buff);
           return STATUS_SUCCESS;
       }
@@ -2408,7 +2321,6 @@ CSR_API(CsrScrollConsoleScreenBuffer)
     }
 
   ConioUnlockScreenBuffer(Buff);
-  ConioUnlockConsole(Console);
 
   return STATUS_SUCCESS;
 }
@@ -2432,18 +2344,12 @@ CSR_API(CsrReadConsoleOutputChar)
 
   CharSize = (Request->Data.ReadConsoleOutputCharRequest.Unicode ? sizeof(WCHAR) : sizeof(CHAR));
 
-  Status = ConioConsoleFromProcessData(ProcessData, &Console);
-  if (! NT_SUCCESS(Status))
-    {
-      return Status;
-    }
-
   Status = ConioLockScreenBuffer(ProcessData, Request->Data.ReadConsoleOutputCharRequest.ConsoleHandle, &Buff, GENERIC_READ);
   if (! NT_SUCCESS(Status))
     {
-      ConioUnlockConsole(Console);
       return Status;
     }
+  Console = Buff->Header.Console;
 
   Xpos = Request->Data.ReadConsoleOutputCharRequest.ReadCoord.X;
   Ypos = (Request->Data.ReadConsoleOutputCharRequest.ReadCoord.Y + Buff->VirtualY) % Buff->MaxY;
@@ -2479,7 +2385,6 @@ CSR_API(CsrReadConsoleOutputChar)
   Request->Data.ReadConsoleOutputCharRequest.EndCoord.Y = (Ypos - Buff->VirtualY + Buff->MaxY) % Buff->MaxY;
 
   ConioUnlockScreenBuffer(Buff);
-  ConioUnlockConsole(Console);
 
   Request->Data.ReadConsoleOutputCharRequest.CharsRead = (DWORD)((ULONG_PTR)ReadBuffer - (ULONG_PTR)Request->Data.ReadConsoleOutputCharRequest.String) / CharSize;
   if (Request->Data.ReadConsoleOutputCharRequest.CharsRead * CharSize + CSR_API_MESSAGE_HEADER_SIZE(CSRSS_READ_CONSOLE_OUTPUT_CHAR) > sizeof(CSR_API_MESSAGE))
@@ -3131,22 +3036,15 @@ CSR_API(CsrSetScreenBufferSize)
     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;
     }
+    Console = Buff->Header.Console;
 
     Status = ConioResizeBuffer(Console, Buff, Request->Data.SetScreenBufferSize.Size);
     ConioUnlockScreenBuffer(Buff);
-    ConioUnlockConsole(Console);
 
     return Status;
 }
index 1d1ab7f..14abebf 100644 (file)
@@ -69,6 +69,8 @@ typedef struct tagCSRSS_CONSOLE_VTBL
 typedef struct tagCSRSS_CONSOLE
 {
   Object_t Header;                      /* Object header */
+  LONG ReferenceCount;
+  CRITICAL_SECTION Lock;
   PCSRSS_CONSOLE Prev, Next;            /* Next and Prev consoles in console wheel */
   HANDLE ActiveEvent;
   LIST_ENTRY InputEvents;               /* List head for input event queue */
index 243246d..625b1b5 100644 (file)
@@ -872,7 +872,7 @@ GuiConsolePaint(PCSRSS_CONSOLE Console,
 
     Buff = Console->ActiveBuffer;
 
-    EnterCriticalSection(&Buff->Header.Lock);
+    EnterCriticalSection(&Buff->Header.Console->Lock);
 
     TopLine = rc->top / GuiData->CharHeight + Buff->ShowY;
     BottomLine = (rc->bottom + (GuiData->CharHeight - 1)) / GuiData->CharHeight - 1 + Buff->ShowY;
@@ -971,7 +971,7 @@ GuiConsolePaint(PCSRSS_CONSOLE Console,
         }
     }
 
-    LeaveCriticalSection(&Buff->Header.Lock);
+    LeaveCriticalSection(&Buff->Header.Console->Lock);
 
     SelectObject(hDC,
                  OldFont);
@@ -1327,7 +1327,7 @@ GuiConsoleHandleClose(HWND hWnd)
 
   GuiConsoleGetDataPointers(hWnd, &Console, &GuiData);
 
-  EnterCriticalSection(&Console->Header.Lock);
+  EnterCriticalSection(&Console->Lock);
 
   current_entry = Console->ProcessList.Flink;
   while (current_entry != &Console->ProcessList)
@@ -1341,7 +1341,7 @@ GuiConsoleHandleClose(HWND hWnd)
       ConioConsoleCtrlEvent(CTRL_CLOSE_EVENT, current);
     }
 
-  LeaveCriticalSection(&Console->Header.Lock);
+  LeaveCriticalSection(&Console->Lock);
 }
 
 static VOID FASTCALL
@@ -1809,7 +1809,7 @@ GuiApplyUserSettings(PCSRSS_CONSOLE Console, PGUI_CONSOLE_DATA GuiData, PConsole
   COORD BufSize;
   BOOL SizeChanged = FALSE;
 
-  EnterCriticalSection(&ActiveBuffer->Header.Lock);
+  EnterCriticalSection(&Console->Lock);
 
   /* apply text / background color */
   GuiData->ScreenText = pConInfo->ScreenText;
@@ -1844,7 +1844,7 @@ GuiApplyUserSettings(PCSRSS_CONSOLE Console, PGUI_CONSOLE_DATA GuiData, PConsole
       GuiData->WindowSizeLock = FALSE;
   }
 
-  LeaveCriticalSection(&ActiveBuffer->Header.Lock);
+  LeaveCriticalSection(&Console->Lock);
   InvalidateRect(pConInfo->hConsoleWindow, NULL, TRUE);
 }
 
index e1afd16..a712fd3 100644 (file)
 
 /* FUNCTIONS *****************************************************************/
 
-static unsigned ObjectDefinitionsCount = 2;
-static CSRSS_OBJECT_DEFINITION ObjectDefinitions[] =
-{
-    { CONIO_CONSOLE_MAGIC,       ConioDeleteConsole },
-    { CONIO_SCREEN_BUFFER_MAGIC, ConioDeleteScreenBuffer },
-};
-
 static
 BOOL
 CsrIsConsoleHandle(HANDLE Handle)
@@ -30,58 +23,40 @@ CsrIsConsoleHandle(HANDLE Handle)
     return ((ULONG_PTR)Handle & 0x10000003) == 0x3;
 }
 
-NTSTATUS
-FASTCALL
-Win32CsrGetObject(
-    PCSRSS_PROCESS_DATA ProcessData,
-    HANDLE Handle,
-    Object_t **Object,
-    DWORD Access )
+static VOID
+Win32CsrCreateHandleEntry(
+    PCSRSS_HANDLE Entry,
+    Object_t *Object,
+    DWORD Access,
+    BOOL Inheritable)
 {
-    ULONG_PTR h = (ULONG_PTR)Handle >> 2;
-
-    DPRINT("CsrGetObject, Object: %x, %x, %x\n", 
-           Object, Handle, ProcessData ? ProcessData->HandleTableSize : 0);
-
-    RtlEnterCriticalSection(&ProcessData->HandleTableLock);
-    if (!CsrIsConsoleHandle(Handle) || h >= ProcessData->HandleTableSize
-            || (*Object = ProcessData->HandleTable[h].Object) == NULL
-            || ~ProcessData->HandleTable[h].Access & Access)
-    {
-        DPRINT1("CsrGetObject returning invalid handle (%x)\n", Handle);
-        RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
-        return STATUS_INVALID_HANDLE;
-    }
-    _InterlockedIncrement(&(*Object)->ReferenceCount);
-    RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
-    //   DbgPrint( "CsrGetObject returning\n" );
-    return STATUS_SUCCESS;
+    Entry->Object = Object;
+    Entry->Access = Access;
+    Entry->Inheritable = Inheritable;
+    _InterlockedIncrement(&Object->HandleCount);
 }
 
-
-NTSTATUS
-FASTCALL
-Win32CsrReleaseObjectByPointer(
-    Object_t *Object)
+static VOID
+Win32CsrCloseHandleEntry(
+    PCSRSS_HANDLE Entry)
 {
-    unsigned DefIndex;
-
-    /* dec ref count */
-    if (_InterlockedDecrement(&Object->ReferenceCount) == 0)
+    Object_t *Object = Entry->Object;
+    if (Object != NULL)
     {
-        for (DefIndex = 0; DefIndex < ObjectDefinitionsCount; DefIndex++)
+        Entry->Object = NULL;
+        /* If the last handle to a screen buffer is closed, delete it */
+        if (_InterlockedDecrement(&Object->HandleCount) == 0
+            && Object->Type == CONIO_SCREEN_BUFFER_MAGIC)
         {
-            if (Object->Type == ObjectDefinitions[DefIndex].Type)
-            {
-                (ObjectDefinitions[DefIndex].CsrCleanupObjectProc)(Object);
-                return STATUS_SUCCESS;
-            }
+            PCSRSS_CONSOLE Console = Object->Console;
+            EnterCriticalSection(&Console->Lock);
+            /* TODO: Should delete even the active buffer, but we're not yet ready
+             * to deal with the case where this results in no buffers left. */
+            if (Object != &Console->ActiveBuffer->Header)
+                ConioDeleteScreenBuffer(Object);
+            LeaveCriticalSection(&Console->Lock);
         }
-
-        DPRINT1("CSR: Error: releasing unknown object type 0x%x", Object->Type);
     }
-
-    return STATUS_SUCCESS;
 }
 
 NTSTATUS
@@ -100,10 +75,9 @@ Win32CsrReleaseObject(
         RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
         return STATUS_INVALID_HANDLE;
     }
-    ProcessData->HandleTable[h].Object = NULL;
+    Win32CsrCloseHandleEntry(&ProcessData->HandleTable[h]);
     RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
-
-    return Win32CsrReleaseObjectByPointer(Object);
+    return STATUS_SUCCESS;
 }
 
 NTSTATUS
@@ -114,22 +88,25 @@ Win32CsrLockObject(PCSRSS_PROCESS_DATA ProcessData,
                    DWORD Access,
                    LONG Type)
 {
-    NTSTATUS Status;
+    ULONG_PTR h = (ULONG_PTR)Handle >> 2;
 
-    Status = Win32CsrGetObject(ProcessData, Handle, Object, Access);
-    if (! NT_SUCCESS(Status))
-    {
-        return Status;
-    }
+    DPRINT("CsrGetObject, Object: %x, %x, %x\n", 
+           Object, Handle, ProcessData ? ProcessData->HandleTableSize : 0);
 
-    if ((*Object)->Type != Type)
+    RtlEnterCriticalSection(&ProcessData->HandleTableLock);
+    if (!CsrIsConsoleHandle(Handle) || h >= ProcessData->HandleTableSize
+            || (*Object = ProcessData->HandleTable[h].Object) == NULL
+            || ~ProcessData->HandleTable[h].Access & Access
+            || (Type != 0 && (*Object)->Type != Type))
     {
-        Win32CsrReleaseObjectByPointer(*Object);
+        DPRINT1("CsrGetObject returning invalid handle (%x)\n", Handle);
+        RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
         return STATUS_INVALID_HANDLE;
     }
+    _InterlockedIncrement(&(*Object)->Console->ReferenceCount);
+    RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
 
-    EnterCriticalSection(&((*Object)->Lock));
-
+    EnterCriticalSection(&((*Object)->Console->Lock));
     return STATUS_SUCCESS;
 }
 
@@ -137,8 +114,11 @@ VOID
 FASTCALL
 Win32CsrUnlockObject(Object_t *Object)
 {
-    LeaveCriticalSection(&(Object->Lock));
-    Win32CsrReleaseObjectByPointer(Object);
+    PCSRSS_CONSOLE Console = Object->Console;
+    LeaveCriticalSection(&Console->Lock);
+    /* dec ref count */
+    if (_InterlockedDecrement(&Console->ReferenceCount) == 0)
+        ConioDeleteConsole(&Console->Header);
 }
 
 NTSTATUS
@@ -153,27 +133,24 @@ Win32CsrReleaseConsole(
     RtlEnterCriticalSection(&ProcessData->HandleTableLock);
 
     for (i = 0; i < ProcessData->HandleTableSize; i++)
-    {
-        if (ProcessData->HandleTable[i].Object != NULL)
-            Win32CsrReleaseObjectByPointer(ProcessData->HandleTable[i].Object);
-    }
+        Win32CsrCloseHandleEntry(&ProcessData->HandleTable[i]);
     ProcessData->HandleTableSize = 0;
     RtlFreeHeap(Win32CsrApiHeap, 0, ProcessData->HandleTable);
     ProcessData->HandleTable = NULL;
 
     Console = ProcessData->Console;
-    ProcessData->Console = NULL;
-    RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
-
     if (Console != NULL)
     {
-        EnterCriticalSection(&Console->Header.Lock);
+        ProcessData->Console = NULL;
+        EnterCriticalSection(&Console->Lock);
         RemoveEntryList(&ProcessData->ProcessEntry);
-        LeaveCriticalSection(&Console->Header.Lock);
-        Win32CsrReleaseObjectByPointer(&Console->Header);
+        LeaveCriticalSection(&Console->Lock);
+        if (_InterlockedDecrement(&Console->ReferenceCount) == 0)
+            ConioDeleteConsole(&Console->Header);
+        RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
         return STATUS_SUCCESS;
     }
-
+    RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
     return STATUS_INVALID_PARAMETER;
 }
 
@@ -215,11 +192,8 @@ Win32CsrInsertObject(
         ProcessData->HandleTable = Block;
         ProcessData->HandleTableSize += 64;
     }
-    ProcessData->HandleTable[i].Object = Object;
-    ProcessData->HandleTable[i].Access = Access;
-    ProcessData->HandleTable[i].Inheritable = Inheritable;
+    Win32CsrCreateHandleEntry(&ProcessData->HandleTable[i], Object, Access, Inheritable);
     *Handle = UlongToHandle((i << 2) | 0x3);
-    _InterlockedIncrement( &Object->ReferenceCount );
     RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
     return(STATUS_SUCCESS);
 }
@@ -256,8 +230,10 @@ Win32CsrDuplicateHandleTable(
         if (SourceProcessData->HandleTable[i].Object != NULL &&
             SourceProcessData->HandleTable[i].Inheritable)
         {
-            TargetProcessData->HandleTable[i] = SourceProcessData->HandleTable[i];
-            _InterlockedIncrement( &SourceProcessData->HandleTable[i].Object->ReferenceCount );
+            Win32CsrCreateHandleEntry(&TargetProcessData->HandleTable[i],
+                                       SourceProcessData->HandleTable[i].Object,
+                                       SourceProcessData->HandleTable[i].Access,
+                                       SourceProcessData->HandleTable[i].Inheritable);
         }
     }
     RtlLeaveCriticalSection(&SourceProcessData->HandleTableLock);
@@ -385,9 +361,7 @@ CSR_API(CsrDuplicateHandle)
     if (NT_SUCCESS(Request->Status)
         && Request->Data.DuplicateHandleRequest.Options & DUPLICATE_CLOSE_SOURCE)
     {
-        /* Close the original handle. This cannot drop the count to 0, since a new handle now exists */
-        _InterlockedDecrement(&Entry->Object->ReferenceCount);
-        Entry->Object = NULL;
+        Win32CsrCloseHandleEntry(Entry);
     }
 
     RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
index 5bcd0c2..0bb4440 100644 (file)
@@ -17,8 +17,8 @@ extern HINSTANCE Win32CsrDllHandle;
 typedef struct Object_tt
 {
   LONG Type;
-  LONG ReferenceCount;
-  CRITICAL_SECTION Lock;
+  struct tagCSRSS_CONSOLE *Console;
+  LONG HandleCount;
 } Object_t;
 
 typedef struct _CSRSS_HANDLE
@@ -48,11 +48,6 @@ NTSTATUS FASTCALL Win32CsrLockObject(PCSRSS_PROCESS_DATA ProcessData,
                                      DWORD Access,
                                      long Type);
 VOID FASTCALL Win32CsrUnlockObject(Object_t *Object);
-NTSTATUS FASTCALL Win32CsrGetObject(PCSRSS_PROCESS_DATA ProcessData,
-                                    HANDLE Handle,
-                                    Object_t **Object,
-                                    DWORD Access);
-NTSTATUS FASTCALL Win32CsrReleaseObjectByPointer(Object_t *Object);
 NTSTATUS FASTCALL Win32CsrReleaseObject(PCSRSS_PROCESS_DATA ProcessData,
                                         HANDLE Object);
 NTSTATUS WINAPI Win32CsrReleaseConsole(PCSRSS_PROCESS_DATA ProcessData);