[WIN32CSR]

- 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
This commit is contained in:
Jeffrey Morlan 2010-05-23 05:33:21 +00:00
parent ff2f27f29b
commit 3c777cde9c
5 changed files with 113 additions and 244 deletions

View file

@ -53,9 +53,9 @@ ConioConsoleFromProcessData(PCSRSS_PROCESS_DATA ProcessData, PCSRSS_CONSOLE *Con
return STATUS_INVALID_HANDLE; return STATUS_INVALID_HANDLE;
} }
InterlockedIncrement(&ProcessConsole->Header.ReferenceCount); InterlockedIncrement(&ProcessConsole->ReferenceCount);
RtlLeaveCriticalSection(&ProcessData->HandleTableLock); RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
EnterCriticalSection(&(ProcessConsole->Header.Lock)); EnterCriticalSection(&(ProcessConsole->Lock));
*Console = ProcessConsole; *Console = ProcessConsole;
return STATUS_SUCCESS; return STATUS_SUCCESS;
@ -117,7 +117,8 @@ CsrInitConsoleScreenBuffer(PCSRSS_CONSOLE Console,
DPRINT("CsrInitConsoleScreenBuffer Size X %d Size Y %d\n", Buffer->MaxX, Buffer->MaxY); DPRINT("CsrInitConsoleScreenBuffer Size X %d Size Y %d\n", Buffer->MaxX, Buffer->MaxY);
Buffer->Header.Type = CONIO_SCREEN_BUFFER_MAGIC; Buffer->Header.Type = CONIO_SCREEN_BUFFER_MAGIC;
Buffer->Header.ReferenceCount = 0; Buffer->Header.Console = Console;
Buffer->Header.HandleCount = 0;
Buffer->ShowX = 0; Buffer->ShowX = 0;
Buffer->ShowY = 0; Buffer->ShowY = 0;
Buffer->VirtualY = 0; Buffer->VirtualY = 0;
@ -126,7 +127,6 @@ CsrInitConsoleScreenBuffer(PCSRSS_CONSOLE Console,
{ {
return STATUS_INSUFFICIENT_RESOURCES; return STATUS_INSUFFICIENT_RESOURCES;
} }
InitializeCriticalSection(&Buffer->Header.Lock);
ConioInitScreenBuffer(Console, Buffer); ConioInitScreenBuffer(Console, Buffer);
/* initialize buffer to be empty with default attributes */ /* initialize buffer to be empty with default attributes */
for (Buffer->CurrentY = 0 ; Buffer->CurrentY < Buffer->MaxY; Buffer->CurrentY++) for (Buffer->CurrentY = 0 ; Buffer->CurrentY < Buffer->MaxY; Buffer->CurrentY++)
@ -154,11 +154,12 @@ CsrInitConsole(PCSRSS_CONSOLE Console)
//FIXME //FIXME
RtlCreateUnicodeString(&Console->Title, L"Command Prompt"); RtlCreateUnicodeString(&Console->Title, L"Command Prompt");
Console->Header.ReferenceCount = 0; Console->ReferenceCount = 0;
Console->WaitingChars = 0; Console->WaitingChars = 0;
Console->WaitingLines = 0; Console->WaitingLines = 0;
Console->EchoCount = 0; Console->EchoCount = 0;
Console->Header.Type = CONIO_CONSOLE_MAGIC; 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->Mode = ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT | ENABLE_PROCESSED_INPUT | ENABLE_MOUSE_INPUT;
Console->EarlyReturn = FALSE; Console->EarlyReturn = FALSE;
Console->ActiveBuffer = NULL; Console->ActiveBuffer = NULL;
@ -177,7 +178,7 @@ CsrInitConsole(PCSRSS_CONSOLE Console)
return STATUS_UNSUCCESSFUL; return STATUS_UNSUCCESSFUL;
} }
Console->PrivateData = NULL; Console->PrivateData = NULL;
InitializeCriticalSection(&Console->Header.Lock); InitializeCriticalSection(&Console->Lock);
GuiMode = DtbgIsDesktopVisible(); GuiMode = DtbgIsDesktopVisible();
@ -186,7 +187,7 @@ CsrInitConsole(PCSRSS_CONSOLE Console)
if (NULL == NewBuffer) if (NULL == NewBuffer)
{ {
RtlFreeUnicodeString(&Console->Title); RtlFreeUnicodeString(&Console->Title);
DeleteCriticalSection(&Console->Header.Lock); DeleteCriticalSection(&Console->Lock);
CloseHandle(Console->ActiveEvent); CloseHandle(Console->ActiveEvent);
return STATUS_INSUFFICIENT_RESOURCES; return STATUS_INSUFFICIENT_RESOURCES;
} }
@ -212,7 +213,7 @@ CsrInitConsole(PCSRSS_CONSOLE Console)
{ {
HeapFree(Win32CsrApiHeap,0, NewBuffer); HeapFree(Win32CsrApiHeap,0, NewBuffer);
RtlFreeUnicodeString(&Console->Title); RtlFreeUnicodeString(&Console->Title);
DeleteCriticalSection(&Console->Header.Lock); DeleteCriticalSection(&Console->Lock);
CloseHandle(Console->ActiveEvent); CloseHandle(Console->ActiveEvent);
DPRINT1("GuiInitConsole: failed\n"); DPRINT1("GuiInitConsole: failed\n");
return Status; return Status;
@ -224,16 +225,13 @@ CsrInitConsole(PCSRSS_CONSOLE Console)
{ {
ConioCleanupConsole(Console); ConioCleanupConsole(Console);
RtlFreeUnicodeString(&Console->Title); RtlFreeUnicodeString(&Console->Title);
DeleteCriticalSection(&Console->Header.Lock); DeleteCriticalSection(&Console->Lock);
CloseHandle(Console->ActiveEvent); CloseHandle(Console->ActiveEvent);
HeapFree(Win32CsrApiHeap, 0, NewBuffer); HeapFree(Win32CsrApiHeap, 0, NewBuffer);
DPRINT1("CsrInitConsoleScreenBuffer: failed\n"); DPRINT1("CsrInitConsoleScreenBuffer: failed\n");
return Status; return Status;
} }
/* add a reference count because the buffer is tied to the console */
InterlockedIncrement(&Console->ActiveBuffer->Header.ReferenceCount);
/* copy buffer contents to screen */ /* copy buffer contents to screen */
ConioDrawConsole(Console); ConioDrawConsole(Console);
@ -308,7 +306,7 @@ CSR_API(CsrAllocConsole)
Request->Data.AllocConsoleRequest.Console = Console; Request->Data.AllocConsoleRequest.Console = Console;
/* Add a reference count because the process is tied to the console */ /* Add a reference count because the process is tied to the console */
Console->Header.ReferenceCount++; _InterlockedIncrement(&Console->ReferenceCount);
if (NewConsole || !ProcessData->bInheritHandles) if (NewConsole || !ProcessData->bInheritHandles)
{ {
@ -836,15 +834,16 @@ CSR_API(CsrWriteConsole)
Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE); Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE);
return STATUS_INVALID_PARAMETER; return STATUS_INVALID_PARAMETER;
} }
Status = ConioConsoleFromProcessData(ProcessData, &Console);
Request->Header.u1.s1.TotalLength = sizeof(CSR_API_MESSAGE); Request->Header.u1.s1.TotalLength = sizeof(CSR_API_MESSAGE);
Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_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)) if (! NT_SUCCESS(Status))
{ {
return Status; return Status;
} }
Console = Buff->Header.Console;
if(Request->Data.WriteConsoleRequest.Unicode) if(Request->Data.WriteConsoleRequest.Unicode)
{ {
@ -872,7 +871,6 @@ CSR_API(CsrWriteConsole)
if (Buffer) if (Buffer)
{ {
Status = ConioLockScreenBuffer(ProcessData, Request->Data.WriteConsoleRequest.ConsoleHandle, &Buff, GENERIC_WRITE);
if (NT_SUCCESS(Status)) if (NT_SUCCESS(Status))
{ {
Status = ConioWriteConsole(Console, Buff, Buffer, Status = ConioWriteConsole(Console, Buff, Buffer,
@ -881,14 +879,13 @@ CSR_API(CsrWriteConsole)
{ {
Written = Request->Data.WriteConsoleRequest.NrCharactersToWrite; Written = Request->Data.WriteConsoleRequest.NrCharactersToWrite;
} }
ConioUnlockScreenBuffer(Buff);
} }
if (Request->Data.WriteConsoleRequest.Unicode) if (Request->Data.WriteConsoleRequest.Unicode)
{ {
RtlFreeHeap(GetProcessHeap(), 0, Buffer); RtlFreeHeap(GetProcessHeap(), 0, Buffer);
} }
} }
ConioUnlockConsole(Console); ConioUnlockScreenBuffer(Buff);
Request->Data.WriteConsoleRequest.NrCharactersWritten = Written; Request->Data.WriteConsoleRequest.NrCharactersWritten = Written;
@ -899,7 +896,6 @@ VOID WINAPI
ConioDeleteScreenBuffer(Object_t *Object) ConioDeleteScreenBuffer(Object_t *Object)
{ {
PCSRSS_SCREEN_BUFFER Buffer = (PCSRSS_SCREEN_BUFFER) Object; PCSRSS_SCREEN_BUFFER Buffer = (PCSRSS_SCREEN_BUFFER) Object;
DeleteCriticalSection(&Buffer->Header.Lock);
HeapFree(Win32CsrApiHeap, 0, Buffer->Buffer); HeapFree(Win32CsrApiHeap, 0, Buffer->Buffer);
HeapFree(Win32CsrApiHeap, 0, Buffer); HeapFree(Win32CsrApiHeap, 0, Buffer);
} }
@ -933,15 +929,12 @@ ConioDeleteConsole(Object_t *Object)
} }
ConioCleanupConsole(Console); ConioCleanupConsole(Console);
if (0 == InterlockedDecrement(&Console->ActiveBuffer->Header.ReferenceCount))
{
ConioDeleteScreenBuffer((Object_t *) Console->ActiveBuffer); ConioDeleteScreenBuffer((Object_t *) Console->ActiveBuffer);
}
Console->ActiveBuffer = NULL; Console->ActiveBuffer = NULL;
CloseHandle(Console->ActiveEvent); CloseHandle(Console->ActiveEvent);
DeleteCriticalSection(&Console->Header.Lock); DeleteCriticalSection(&Console->Lock);
RtlFreeUnicodeString(&Console->Title); RtlFreeUnicodeString(&Console->Title);
IntDeleteAllAliases(Console->Aliases); IntDeleteAllAliases(Console->Aliases);
HeapFree(Win32CsrApiHeap, 0, Console); HeapFree(Win32CsrApiHeap, 0, Console);
@ -1280,17 +1273,12 @@ CSR_API(CsrGetScreenBufferInfo)
Request->Header.u1.s1.TotalLength = sizeof(CSR_API_MESSAGE); Request->Header.u1.s1.TotalLength = sizeof(CSR_API_MESSAGE);
Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_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); Status = ConioLockScreenBuffer(ProcessData, Request->Data.ScreenBufferInfoRequest.ConsoleHandle, &Buff, GENERIC_READ);
if (! NT_SUCCESS(Status)) if (! NT_SUCCESS(Status))
{ {
ConioUnlockConsole(Console);
return Status; return Status;
} }
Console = Buff->Header.Console;
pInfo = &Request->Data.ScreenBufferInfoRequest.Info; pInfo = &Request->Data.ScreenBufferInfoRequest.Info;
pInfo->dwSize.X = Buff->MaxX; pInfo->dwSize.X = Buff->MaxX;
pInfo->dwSize.Y = Buff->MaxY; pInfo->dwSize.Y = Buff->MaxY;
@ -1304,7 +1292,6 @@ CSR_API(CsrGetScreenBufferInfo)
pInfo->dwMaximumWindowSize.X = Buff->MaxX; pInfo->dwMaximumWindowSize.X = Buff->MaxX;
pInfo->dwMaximumWindowSize.Y = Buff->MaxY; pInfo->dwMaximumWindowSize.Y = Buff->MaxY;
ConioUnlockScreenBuffer(Buff); ConioUnlockScreenBuffer(Buff);
ConioUnlockConsole(Console);
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }
@ -1319,21 +1306,15 @@ CSR_API(CsrSetCursor)
DPRINT("CsrSetCursor\n"); 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.TotalLength = sizeof(CSR_API_MESSAGE);
Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE); Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE);
Status = ConioLockScreenBuffer(ProcessData, Request->Data.SetCursorRequest.ConsoleHandle, &Buff, GENERIC_WRITE); Status = ConioLockScreenBuffer(ProcessData, Request->Data.SetCursorRequest.ConsoleHandle, &Buff, GENERIC_WRITE);
if (! NT_SUCCESS(Status)) if (! NT_SUCCESS(Status))
{ {
ConioUnlockConsole(Console);
return Status; return Status;
} }
Console = Buff->Header.Console;
NewCursorX = Request->Data.SetCursorRequest.Position.X; NewCursorX = Request->Data.SetCursorRequest.Position.X;
NewCursorY = Request->Data.SetCursorRequest.Position.Y; NewCursorY = Request->Data.SetCursorRequest.Position.Y;
@ -1341,7 +1322,6 @@ CSR_API(CsrSetCursor)
NewCursorY < 0 || NewCursorY >= Buff->MaxY) NewCursorY < 0 || NewCursorY >= Buff->MaxY)
{ {
ConioUnlockScreenBuffer(Buff); ConioUnlockScreenBuffer(Buff);
ConioUnlockConsole(Console);
return STATUS_INVALID_PARAMETER; return STATUS_INVALID_PARAMETER;
} }
OldCursorX = Buff->CurrentX; OldCursorX = Buff->CurrentX;
@ -1353,13 +1333,11 @@ CSR_API(CsrSetCursor)
if (! ConioSetScreenInfo(Console, Buff, OldCursorX, OldCursorY)) if (! ConioSetScreenInfo(Console, Buff, OldCursorX, OldCursorY))
{ {
ConioUnlockScreenBuffer(Buff); ConioUnlockScreenBuffer(Buff);
ConioUnlockConsole(Console);
return STATUS_UNSUCCESSFUL; return STATUS_UNSUCCESSFUL;
} }
} }
ConioUnlockScreenBuffer(Buff); ConioUnlockScreenBuffer(Buff);
ConioUnlockConsole(Console);
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }
@ -1415,11 +1393,15 @@ CSR_API(CsrWriteConsoleOutputChar)
return STATUS_INVALID_PARAMETER; 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.TotalLength = sizeof(CSR_API_MESSAGE);
Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE); Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE);
if (NT_SUCCESS(Status)) if (NT_SUCCESS(Status))
{ {
Console = Buff->Header.Console;
if(Request->Data.WriteConsoleOutputCharRequest.Unicode) if(Request->Data.WriteConsoleOutputCharRequest.Unicode)
{ {
Length = WideCharToMultiByte(Console->OutputCodePage, 0, Length = WideCharToMultiByte(Console->OutputCodePage, 0,
@ -1446,10 +1428,6 @@ CSR_API(CsrWriteConsoleOutputChar)
if (String) if (String)
{ {
Status = ConioLockScreenBuffer(ProcessData,
Request->Data.WriteConsoleOutputCharRequest.ConsoleHandle,
&Buff,
GENERIC_WRITE);
if (NT_SUCCESS(Status)) if (NT_SUCCESS(Status))
{ {
X = Request->Data.WriteConsoleOutputCharRequest.Coord.X; X = Request->Data.WriteConsoleOutputCharRequest.Coord.X;
@ -1481,14 +1459,13 @@ CSR_API(CsrWriteConsoleOutputChar)
Request->Data.WriteConsoleOutputCharRequest.EndCoord.X = X; Request->Data.WriteConsoleOutputCharRequest.EndCoord.X = X;
Request->Data.WriteConsoleOutputCharRequest.EndCoord.Y = (Y + Buff->MaxY - Buff->VirtualY) % Buff->MaxY; Request->Data.WriteConsoleOutputCharRequest.EndCoord.Y = (Y + Buff->MaxY - Buff->VirtualY) % Buff->MaxY;
ConioUnlockScreenBuffer(Buff);
} }
if (Request->Data.WriteConsoleRequest.Unicode) if (Request->Data.WriteConsoleRequest.Unicode)
{ {
RtlFreeHeap(GetProcessHeap(), 0, tmpString); RtlFreeHeap(GetProcessHeap(), 0, tmpString);
} }
} }
ConioUnlockConsole(Console); ConioUnlockScreenBuffer(Buff);
} }
Request->Data.WriteConsoleOutputCharRequest.NrCharactersWritten = Written; Request->Data.WriteConsoleOutputCharRequest.NrCharactersWritten = Written;
return Status; return Status;
@ -1509,18 +1486,12 @@ CSR_API(CsrFillOutputChar)
Request->Header.u1.s1.TotalLength = sizeof(CSR_API_MESSAGE); Request->Header.u1.s1.TotalLength = sizeof(CSR_API_MESSAGE);
Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_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); Status = ConioLockScreenBuffer(ProcessData, Request->Data.FillOutputRequest.ConsoleHandle, &Buff, GENERIC_WRITE);
if (! NT_SUCCESS(Status)) if (! NT_SUCCESS(Status))
{ {
ConioUnlockConsole(Console);
return Status; return Status;
} }
Console = Buff->Header.Console;
X = Request->Data.FillOutputRequest.Position.X; X = Request->Data.FillOutputRequest.Position.X;
Y = (Request->Data.FillOutputRequest.Position.Y + Buff->VirtualY) % Buff->MaxY; Y = (Request->Data.FillOutputRequest.Position.Y + Buff->VirtualY) % Buff->MaxY;
@ -1554,7 +1525,6 @@ CSR_API(CsrFillOutputChar)
} }
ConioUnlockScreenBuffer(Buff); ConioUnlockScreenBuffer(Buff);
ConioUnlockConsole(Console);
Length = Request->Data.FillOutputRequest.Length; Length = Request->Data.FillOutputRequest.Length;
Request->Data.FillOutputRequest.NrCharactersWritten = Length; Request->Data.FillOutputRequest.NrCharactersWritten = Length;
return STATUS_SUCCESS; return STATUS_SUCCESS;
@ -1661,13 +1631,8 @@ CSR_API(CsrWriteConsoleOutputAttrib)
return STATUS_INVALID_PARAMETER; return STATUS_INVALID_PARAMETER;
} }
Status = ConioConsoleFromProcessData(ProcessData, &Console);
Request->Header.u1.s1.TotalLength = sizeof(CSR_API_MESSAGE); Request->Header.u1.s1.TotalLength = sizeof(CSR_API_MESSAGE);
Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE); Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE);
if (! NT_SUCCESS(Status))
{
return Status;
}
Status = ConioLockScreenBuffer(ProcessData, Status = ConioLockScreenBuffer(ProcessData,
Request->Data.WriteConsoleOutputAttribRequest.ConsoleHandle, Request->Data.WriteConsoleOutputAttribRequest.ConsoleHandle,
@ -1675,9 +1640,9 @@ CSR_API(CsrWriteConsoleOutputAttrib)
GENERIC_WRITE); GENERIC_WRITE);
if (! NT_SUCCESS(Status)) if (! NT_SUCCESS(Status))
{ {
ConioUnlockConsole(Console);
return Status; return Status;
} }
Console = Buff->Header.Console;
X = Request->Data.WriteConsoleOutputAttribRequest.Coord.X; X = Request->Data.WriteConsoleOutputAttribRequest.Coord.X;
Y = (Request->Data.WriteConsoleOutputAttribRequest.Coord.Y + Buff->VirtualY) % Buff->MaxY; Y = (Request->Data.WriteConsoleOutputAttribRequest.Coord.Y + Buff->VirtualY) % Buff->MaxY;
@ -1706,8 +1671,6 @@ CSR_API(CsrWriteConsoleOutputAttrib)
ConioDrawRegion(Console, &UpdateRect); ConioDrawRegion(Console, &UpdateRect);
} }
ConioUnlockConsole(Console);
Request->Data.WriteConsoleOutputAttribRequest.EndCoord.X = X; Request->Data.WriteConsoleOutputAttribRequest.EndCoord.X = X;
Request->Data.WriteConsoleOutputAttribRequest.EndCoord.Y = (Y + Buff->MaxY - Buff->VirtualY) % Buff->MaxY; Request->Data.WriteConsoleOutputAttribRequest.EndCoord.Y = (Y + Buff->MaxY - Buff->VirtualY) % Buff->MaxY;
@ -1728,20 +1691,14 @@ CSR_API(CsrFillOutputAttrib)
DPRINT("CsrFillOutputAttrib\n"); 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.TotalLength = sizeof(CSR_API_MESSAGE);
Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE); Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE);
Status = ConioLockScreenBuffer(ProcessData, Request->Data.FillOutputAttribRequest.ConsoleHandle, &Buff, GENERIC_WRITE); Status = ConioLockScreenBuffer(ProcessData, Request->Data.FillOutputAttribRequest.ConsoleHandle, &Buff, GENERIC_WRITE);
if (! NT_SUCCESS(Status)) if (! NT_SUCCESS(Status))
{ {
ConioUnlockConsole(Console);
return Status; return Status;
} }
Console = Buff->Header.Console;
X = Request->Data.FillOutputAttribRequest.Coord.X; X = Request->Data.FillOutputAttribRequest.Coord.X;
Y = (Request->Data.FillOutputAttribRequest.Coord.Y + Buff->VirtualY) % Buff->MaxY; Y = (Request->Data.FillOutputAttribRequest.Coord.Y + Buff->VirtualY) % Buff->MaxY;
@ -1771,7 +1728,6 @@ CSR_API(CsrFillOutputAttrib)
} }
ConioUnlockScreenBuffer(Buff); ConioUnlockScreenBuffer(Buff);
ConioUnlockConsole(Console);
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }
@ -1812,18 +1768,12 @@ CSR_API(CsrSetCursorInfo)
Request->Header.u1.s1.TotalLength = sizeof(CSR_API_MESSAGE); Request->Header.u1.s1.TotalLength = sizeof(CSR_API_MESSAGE);
Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_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); Status = ConioLockScreenBuffer(ProcessData, Request->Data.SetCursorInfoRequest.ConsoleHandle, &Buff, GENERIC_WRITE);
if (! NT_SUCCESS(Status)) if (! NT_SUCCESS(Status))
{ {
ConioUnlockConsole(Console);
return Status; return Status;
} }
Console = Buff->Header.Console;
Size = Request->Data.SetCursorInfoRequest.Info.dwSize; Size = Request->Data.SetCursorInfoRequest.Info.dwSize;
Visible = Request->Data.SetCursorInfoRequest.Info.bVisible; Visible = Request->Data.SetCursorInfoRequest.Info.bVisible;
@ -1845,13 +1795,11 @@ CSR_API(CsrSetCursorInfo)
if (! ConioSetCursorInfo(Console, Buff)) if (! ConioSetCursorInfo(Console, Buff))
{ {
ConioUnlockScreenBuffer(Buff); ConioUnlockScreenBuffer(Buff);
ConioUnlockConsole(Console);
return STATUS_UNSUCCESSFUL; return STATUS_UNSUCCESSFUL;
} }
} }
ConioUnlockScreenBuffer(Buff); ConioUnlockScreenBuffer(Buff);
ConioUnlockConsole(Console);
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }
@ -1864,18 +1812,12 @@ CSR_API(CsrSetTextAttrib)
DPRINT("CsrSetTextAttrib\n"); DPRINT("CsrSetTextAttrib\n");
Status = ConioConsoleFromProcessData(ProcessData, &Console);
if (! NT_SUCCESS(Status))
{
return Status;
}
Status = ConioLockScreenBuffer(ProcessData, Request->Data.SetCursorRequest.ConsoleHandle, &Buff, GENERIC_WRITE); Status = ConioLockScreenBuffer(ProcessData, Request->Data.SetCursorRequest.ConsoleHandle, &Buff, GENERIC_WRITE);
if (! NT_SUCCESS(Status)) if (! NT_SUCCESS(Status))
{ {
ConioUnlockConsole(Console);
return Status; return Status;
} }
Console = Buff->Header.Console;
Buff->DefaultAttrib = Request->Data.SetAttribRequest.Attrib; Buff->DefaultAttrib = Request->Data.SetAttribRequest.Attrib;
if (Buff == Console->ActiveBuffer) if (Buff == Console->ActiveBuffer)
@ -1883,13 +1825,11 @@ CSR_API(CsrSetTextAttrib)
if (! ConioUpdateScreenInfo(Console, Buff)) if (! ConioUpdateScreenInfo(Console, Buff))
{ {
ConioUnlockScreenBuffer(Buff); ConioUnlockScreenBuffer(Buff);
ConioUnlockConsole(Console);
return STATUS_UNSUCCESSFUL; return STATUS_UNSUCCESSFUL;
} }
} }
ConioUnlockScreenBuffer(Buff); ConioUnlockScreenBuffer(Buff);
ConioUnlockConsole(Console);
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }
@ -1904,9 +1844,9 @@ CSR_API(CsrSetConsoleMode)
Request->Header.u1.s1.TotalLength = sizeof(CSR_API_MESSAGE); Request->Header.u1.s1.TotalLength = sizeof(CSR_API_MESSAGE);
Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE); Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE);
Status = Win32CsrGetObject(ProcessData, Status = Win32CsrLockObject(ProcessData,
Request->Data.SetConsoleModeRequest.ConsoleHandle, Request->Data.SetConsoleModeRequest.ConsoleHandle,
(Object_t **) &Console, GENERIC_WRITE); (Object_t **) &Console, GENERIC_WRITE, 0);
if (! NT_SUCCESS(Status)) if (! NT_SUCCESS(Status))
{ {
return Status; return Status;
@ -1926,7 +1866,7 @@ CSR_API(CsrSetConsoleMode)
Status = STATUS_INVALID_HANDLE; Status = STATUS_INVALID_HANDLE;
} }
Win32CsrReleaseObjectByPointer((Object_t *)Console); Win32CsrUnlockObject((Object_t *)Console);
return Status; return Status;
} }
@ -1941,8 +1881,8 @@ CSR_API(CsrGetConsoleMode)
Request->Header.u1.s1.TotalLength = sizeof(CSR_API_MESSAGE); Request->Header.u1.s1.TotalLength = sizeof(CSR_API_MESSAGE);
Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE); Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE);
Status = Win32CsrGetObject(ProcessData, Request->Data.GetConsoleModeRequest.ConsoleHandle, Status = Win32CsrLockObject(ProcessData, Request->Data.GetConsoleModeRequest.ConsoleHandle,
(Object_t **) &Console, GENERIC_READ); (Object_t **) &Console, GENERIC_READ, 0);
if (! NT_SUCCESS(Status)) if (! NT_SUCCESS(Status))
{ {
return Status; return Status;
@ -1962,7 +1902,7 @@ CSR_API(CsrGetConsoleMode)
Status = STATUS_INVALID_HANDLE; Status = STATUS_INVALID_HANDLE;
} }
Win32CsrReleaseObjectByPointer((Object_t *)Console); Win32CsrUnlockObject((Object_t *)Console);
return Status; return Status;
} }
@ -2039,43 +1979,33 @@ CSR_API(CsrSetScreenBuffer)
DPRINT("CsrSetScreenBuffer\n"); 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.TotalLength = sizeof(CSR_API_MESSAGE);
Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE); Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE);
Status = ConioLockScreenBuffer(ProcessData, Request->Data.SetScreenBufferRequest.OutputHandle, &Buff, GENERIC_WRITE); Status = ConioLockScreenBuffer(ProcessData, Request->Data.SetScreenBufferRequest.OutputHandle, &Buff, GENERIC_WRITE);
if (! NT_SUCCESS(Status)) if (! NT_SUCCESS(Status))
{ {
ConioUnlockConsole(Console);
return Status; return Status;
} }
Console = Buff->Header.Console;
if (Buff == Console->ActiveBuffer) if (Buff == Console->ActiveBuffer)
{ {
ConioUnlockScreenBuffer(Buff); ConioUnlockScreenBuffer(Buff);
ConioUnlockConsole(Console);
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }
/* drop reference to old buffer, maybe delete */ /* If old buffer has no handles, it's now unreferenced */
if (! InterlockedDecrement(&Console->ActiveBuffer->Header.ReferenceCount)) if (Console->ActiveBuffer->Header.HandleCount == 0)
{ {
ConioDeleteScreenBuffer((Object_t *) Console->ActiveBuffer); ConioDeleteScreenBuffer((Object_t *) Console->ActiveBuffer);
} }
/* tie console to new buffer */ /* tie console to new buffer */
Console->ActiveBuffer = Buff; Console->ActiveBuffer = Buff;
/* inc ref count on new buffer */
InterlockedIncrement(&Buff->Header.ReferenceCount);
/* Redraw the console */ /* Redraw the console */
ConioDrawConsole(Console); ConioDrawConsole(Console);
ConioUnlockScreenBuffer(Buff); ConioUnlockScreenBuffer(Buff);
ConioUnlockConsole(Console);
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }
@ -2181,12 +2111,6 @@ CSR_API(CsrWriteConsoleOutput)
DPRINT("CsrWriteConsoleOutput\n"); 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.TotalLength = sizeof(CSR_API_MESSAGE);
Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE); Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE);
Status = ConioLockScreenBuffer(ProcessData, Status = ConioLockScreenBuffer(ProcessData,
@ -2195,9 +2119,9 @@ CSR_API(CsrWriteConsoleOutput)
GENERIC_WRITE); GENERIC_WRITE);
if (! NT_SUCCESS(Status)) if (! NT_SUCCESS(Status))
{ {
ConioUnlockConsole(Console);
return Status; return Status;
} }
Console = Buff->Header.Console;
BufferSize = Request->Data.WriteConsoleOutputRequest.BufferSize; BufferSize = Request->Data.WriteConsoleOutputRequest.BufferSize;
PSize = BufferSize.X * BufferSize.Y * sizeof(CHAR_INFO); PSize = BufferSize.X * BufferSize.Y * sizeof(CHAR_INFO);
@ -2208,7 +2132,6 @@ CSR_API(CsrWriteConsoleOutput)
((ULONG_PTR)ProcessData->CsrSectionViewBase + ProcessData->CsrSectionViewSize))) ((ULONG_PTR)ProcessData->CsrSectionViewBase + ProcessData->CsrSectionViewSize)))
{ {
ConioUnlockScreenBuffer(Buff); ConioUnlockScreenBuffer(Buff);
ConioUnlockConsole(Console);
return STATUS_ACCESS_VIOLATION; return STATUS_ACCESS_VIOLATION;
} }
WriteRegion.left = Request->Data.WriteConsoleOutputRequest.WriteRegion.Left; WriteRegion.left = Request->Data.WriteConsoleOutputRequest.WriteRegion.Left;
@ -2226,7 +2149,6 @@ CSR_API(CsrWriteConsoleOutput)
if (! ConioGetIntersection(&WriteRegion, &ScreenBuffer, &WriteRegion)) if (! ConioGetIntersection(&WriteRegion, &ScreenBuffer, &WriteRegion))
{ {
ConioUnlockScreenBuffer(Buff); ConioUnlockScreenBuffer(Buff);
ConioUnlockConsole(Console);
/* It is okay to have a WriteRegion completely outside the screen buffer. /* It is okay to have a WriteRegion completely outside the screen buffer.
No data is written then. */ No data is written then. */
@ -2257,7 +2179,6 @@ CSR_API(CsrWriteConsoleOutput)
ConioDrawRegion(Console, &WriteRegion); ConioDrawRegion(Console, &WriteRegion);
ConioUnlockScreenBuffer(Buff); ConioUnlockScreenBuffer(Buff);
ConioUnlockConsole(Console);
Request->Data.WriteConsoleOutputRequest.WriteRegion.Right = WriteRegion.left + SizeX - 1; Request->Data.WriteConsoleOutputRequest.WriteRegion.Right = WriteRegion.left + SizeX - 1;
Request->Data.WriteConsoleOutputRequest.WriteRegion.Bottom = WriteRegion.top + SizeY - 1; Request->Data.WriteConsoleOutputRequest.WriteRegion.Bottom = WriteRegion.top + SizeY - 1;
@ -2327,20 +2248,14 @@ CSR_API(CsrScrollConsoleScreenBuffer)
DestinationOrigin = Request->Data.ScrollConsoleScreenBufferRequest.DestinationOrigin; DestinationOrigin = Request->Data.ScrollConsoleScreenBufferRequest.DestinationOrigin;
Fill = Request->Data.ScrollConsoleScreenBufferRequest.Fill; 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.TotalLength = sizeof(CSR_API_MESSAGE);
Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE); Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE);
Status = ConioLockScreenBuffer(ProcessData, ConsoleHandle, &Buff, GENERIC_WRITE); Status = ConioLockScreenBuffer(ProcessData, ConsoleHandle, &Buff, GENERIC_WRITE);
if (! NT_SUCCESS(Status)) if (! NT_SUCCESS(Status))
{ {
ConioUnlockConsole(Console);
return Status; return Status;
} }
Console = Buff->Header.Console;
ScrollRectangle.left = Request->Data.ScrollConsoleScreenBufferRequest.ScrollRectangle.Left; ScrollRectangle.left = Request->Data.ScrollConsoleScreenBufferRequest.ScrollRectangle.Left;
ScrollRectangle.top = Request->Data.ScrollConsoleScreenBufferRequest.ScrollRectangle.Top; ScrollRectangle.top = Request->Data.ScrollConsoleScreenBufferRequest.ScrollRectangle.Top;
@ -2352,7 +2267,6 @@ CSR_API(CsrScrollConsoleScreenBuffer)
if (! ConioGetIntersection(&SrcRegion, &ScreenBuffer, &ScrollRectangle)) if (! ConioGetIntersection(&SrcRegion, &ScreenBuffer, &ScrollRectangle))
{ {
ConioUnlockScreenBuffer(Buff); ConioUnlockScreenBuffer(Buff);
ConioUnlockConsole(Console);
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }
@ -2374,7 +2288,6 @@ CSR_API(CsrScrollConsoleScreenBuffer)
ClipRectangle.bottom = Request->Data.ScrollConsoleScreenBufferRequest.ClipRectangle.Bottom; ClipRectangle.bottom = Request->Data.ScrollConsoleScreenBufferRequest.ClipRectangle.Bottom;
if (!ConioGetIntersection(&ClipRectangle, &ClipRectangle, &ScreenBuffer)) if (!ConioGetIntersection(&ClipRectangle, &ClipRectangle, &ScreenBuffer))
{ {
ConioUnlockConsole(Console);
ConioUnlockScreenBuffer(Buff); ConioUnlockScreenBuffer(Buff);
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }
@ -2408,7 +2321,6 @@ CSR_API(CsrScrollConsoleScreenBuffer)
} }
ConioUnlockScreenBuffer(Buff); ConioUnlockScreenBuffer(Buff);
ConioUnlockConsole(Console);
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }
@ -2432,18 +2344,12 @@ CSR_API(CsrReadConsoleOutputChar)
CharSize = (Request->Data.ReadConsoleOutputCharRequest.Unicode ? sizeof(WCHAR) : sizeof(CHAR)); 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); Status = ConioLockScreenBuffer(ProcessData, Request->Data.ReadConsoleOutputCharRequest.ConsoleHandle, &Buff, GENERIC_READ);
if (! NT_SUCCESS(Status)) if (! NT_SUCCESS(Status))
{ {
ConioUnlockConsole(Console);
return Status; return Status;
} }
Console = Buff->Header.Console;
Xpos = Request->Data.ReadConsoleOutputCharRequest.ReadCoord.X; Xpos = Request->Data.ReadConsoleOutputCharRequest.ReadCoord.X;
Ypos = (Request->Data.ReadConsoleOutputCharRequest.ReadCoord.Y + Buff->VirtualY) % Buff->MaxY; 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; Request->Data.ReadConsoleOutputCharRequest.EndCoord.Y = (Ypos - Buff->VirtualY + Buff->MaxY) % Buff->MaxY;
ConioUnlockScreenBuffer(Buff); ConioUnlockScreenBuffer(Buff);
ConioUnlockConsole(Console);
Request->Data.ReadConsoleOutputCharRequest.CharsRead = (DWORD)((ULONG_PTR)ReadBuffer - (ULONG_PTR)Request->Data.ReadConsoleOutputCharRequest.String) / CharSize; 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)) 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.TotalLength = sizeof(CSR_API_MESSAGE);
Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_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); Status = ConioLockScreenBuffer(ProcessData, Request->Data.SetScreenBufferSize.OutputHandle, &Buff, GENERIC_WRITE);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
ConioUnlockConsole(Console);
return Status; return Status;
} }
Console = Buff->Header.Console;
Status = ConioResizeBuffer(Console, Buff, Request->Data.SetScreenBufferSize.Size); Status = ConioResizeBuffer(Console, Buff, Request->Data.SetScreenBufferSize.Size);
ConioUnlockScreenBuffer(Buff); ConioUnlockScreenBuffer(Buff);
ConioUnlockConsole(Console);
return Status; return Status;
} }

View file

@ -69,6 +69,8 @@ typedef struct tagCSRSS_CONSOLE_VTBL
typedef struct tagCSRSS_CONSOLE typedef struct tagCSRSS_CONSOLE
{ {
Object_t Header; /* Object header */ Object_t Header; /* Object header */
LONG ReferenceCount;
CRITICAL_SECTION Lock;
PCSRSS_CONSOLE Prev, Next; /* Next and Prev consoles in console wheel */ PCSRSS_CONSOLE Prev, Next; /* Next and Prev consoles in console wheel */
HANDLE ActiveEvent; HANDLE ActiveEvent;
LIST_ENTRY InputEvents; /* List head for input event queue */ LIST_ENTRY InputEvents; /* List head for input event queue */

View file

@ -872,7 +872,7 @@ GuiConsolePaint(PCSRSS_CONSOLE Console,
Buff = Console->ActiveBuffer; Buff = Console->ActiveBuffer;
EnterCriticalSection(&Buff->Header.Lock); EnterCriticalSection(&Buff->Header.Console->Lock);
TopLine = rc->top / GuiData->CharHeight + Buff->ShowY; TopLine = rc->top / GuiData->CharHeight + Buff->ShowY;
BottomLine = (rc->bottom + (GuiData->CharHeight - 1)) / GuiData->CharHeight - 1 + 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, SelectObject(hDC,
OldFont); OldFont);
@ -1327,7 +1327,7 @@ GuiConsoleHandleClose(HWND hWnd)
GuiConsoleGetDataPointers(hWnd, &Console, &GuiData); GuiConsoleGetDataPointers(hWnd, &Console, &GuiData);
EnterCriticalSection(&Console->Header.Lock); EnterCriticalSection(&Console->Lock);
current_entry = Console->ProcessList.Flink; current_entry = Console->ProcessList.Flink;
while (current_entry != &Console->ProcessList) while (current_entry != &Console->ProcessList)
@ -1341,7 +1341,7 @@ GuiConsoleHandleClose(HWND hWnd)
ConioConsoleCtrlEvent(CTRL_CLOSE_EVENT, current); ConioConsoleCtrlEvent(CTRL_CLOSE_EVENT, current);
} }
LeaveCriticalSection(&Console->Header.Lock); LeaveCriticalSection(&Console->Lock);
} }
static VOID FASTCALL static VOID FASTCALL
@ -1809,7 +1809,7 @@ GuiApplyUserSettings(PCSRSS_CONSOLE Console, PGUI_CONSOLE_DATA GuiData, PConsole
COORD BufSize; COORD BufSize;
BOOL SizeChanged = FALSE; BOOL SizeChanged = FALSE;
EnterCriticalSection(&ActiveBuffer->Header.Lock); EnterCriticalSection(&Console->Lock);
/* apply text / background color */ /* apply text / background color */
GuiData->ScreenText = pConInfo->ScreenText; GuiData->ScreenText = pConInfo->ScreenText;
@ -1844,7 +1844,7 @@ GuiApplyUserSettings(PCSRSS_CONSOLE Console, PGUI_CONSOLE_DATA GuiData, PConsole
GuiData->WindowSizeLock = FALSE; GuiData->WindowSizeLock = FALSE;
} }
LeaveCriticalSection(&ActiveBuffer->Header.Lock); LeaveCriticalSection(&Console->Lock);
InvalidateRect(pConInfo->hConsoleWindow, NULL, TRUE); InvalidateRect(pConInfo->hConsoleWindow, NULL, TRUE);
} }

View file

@ -16,13 +16,6 @@
/* FUNCTIONS *****************************************************************/ /* FUNCTIONS *****************************************************************/
static unsigned ObjectDefinitionsCount = 2;
static CSRSS_OBJECT_DEFINITION ObjectDefinitions[] =
{
{ CONIO_CONSOLE_MAGIC, ConioDeleteConsole },
{ CONIO_SCREEN_BUFFER_MAGIC, ConioDeleteScreenBuffer },
};
static static
BOOL BOOL
CsrIsConsoleHandle(HANDLE Handle) CsrIsConsoleHandle(HANDLE Handle)
@ -30,58 +23,40 @@ CsrIsConsoleHandle(HANDLE Handle)
return ((ULONG_PTR)Handle & 0x10000003) == 0x3; return ((ULONG_PTR)Handle & 0x10000003) == 0x3;
} }
NTSTATUS static VOID
FASTCALL Win32CsrCreateHandleEntry(
Win32CsrGetObject( PCSRSS_HANDLE Entry,
PCSRSS_PROCESS_DATA ProcessData, Object_t *Object,
HANDLE Handle, DWORD Access,
Object_t **Object, BOOL Inheritable)
DWORD Access )
{ {
ULONG_PTR h = (ULONG_PTR)Handle >> 2; Entry->Object = Object;
Entry->Access = Access;
DPRINT("CsrGetObject, Object: %x, %x, %x\n", Entry->Inheritable = Inheritable;
Object, Handle, ProcessData ? ProcessData->HandleTableSize : 0); _InterlockedIncrement(&Object->HandleCount);
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;
} }
static VOID
NTSTATUS Win32CsrCloseHandleEntry(
FASTCALL PCSRSS_HANDLE Entry)
Win32CsrReleaseObjectByPointer(
Object_t *Object)
{ {
unsigned DefIndex; Object_t *Object = Entry->Object;
if (Object != NULL)
/* dec ref count */
if (_InterlockedDecrement(&Object->ReferenceCount) == 0)
{ {
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) PCSRSS_CONSOLE Console = Object->Console;
{ EnterCriticalSection(&Console->Lock);
(ObjectDefinitions[DefIndex].CsrCleanupObjectProc)(Object); /* TODO: Should delete even the active buffer, but we're not yet ready
return STATUS_SUCCESS; * 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 NTSTATUS
@ -100,10 +75,9 @@ Win32CsrReleaseObject(
RtlLeaveCriticalSection(&ProcessData->HandleTableLock); RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
return STATUS_INVALID_HANDLE; return STATUS_INVALID_HANDLE;
} }
ProcessData->HandleTable[h].Object = NULL; Win32CsrCloseHandleEntry(&ProcessData->HandleTable[h]);
RtlLeaveCriticalSection(&ProcessData->HandleTableLock); RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
return STATUS_SUCCESS;
return Win32CsrReleaseObjectByPointer(Object);
} }
NTSTATUS NTSTATUS
@ -114,22 +88,25 @@ Win32CsrLockObject(PCSRSS_PROCESS_DATA ProcessData,
DWORD Access, DWORD Access,
LONG Type) LONG Type)
{ {
NTSTATUS Status; ULONG_PTR h = (ULONG_PTR)Handle >> 2;
Status = Win32CsrGetObject(ProcessData, Handle, Object, Access); DPRINT("CsrGetObject, Object: %x, %x, %x\n",
if (! NT_SUCCESS(Status)) Object, Handle, ProcessData ? ProcessData->HandleTableSize : 0);
{
return Status;
}
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; return STATUS_INVALID_HANDLE;
} }
_InterlockedIncrement(&(*Object)->Console->ReferenceCount);
RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
EnterCriticalSection(&((*Object)->Lock)); EnterCriticalSection(&((*Object)->Console->Lock));
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }
@ -137,8 +114,11 @@ VOID
FASTCALL FASTCALL
Win32CsrUnlockObject(Object_t *Object) Win32CsrUnlockObject(Object_t *Object)
{ {
LeaveCriticalSection(&(Object->Lock)); PCSRSS_CONSOLE Console = Object->Console;
Win32CsrReleaseObjectByPointer(Object); LeaveCriticalSection(&Console->Lock);
/* dec ref count */
if (_InterlockedDecrement(&Console->ReferenceCount) == 0)
ConioDeleteConsole(&Console->Header);
} }
NTSTATUS NTSTATUS
@ -153,27 +133,24 @@ Win32CsrReleaseConsole(
RtlEnterCriticalSection(&ProcessData->HandleTableLock); RtlEnterCriticalSection(&ProcessData->HandleTableLock);
for (i = 0; i < ProcessData->HandleTableSize; i++) for (i = 0; i < ProcessData->HandleTableSize; i++)
{ Win32CsrCloseHandleEntry(&ProcessData->HandleTable[i]);
if (ProcessData->HandleTable[i].Object != NULL)
Win32CsrReleaseObjectByPointer(ProcessData->HandleTable[i].Object);
}
ProcessData->HandleTableSize = 0; ProcessData->HandleTableSize = 0;
RtlFreeHeap(Win32CsrApiHeap, 0, ProcessData->HandleTable); RtlFreeHeap(Win32CsrApiHeap, 0, ProcessData->HandleTable);
ProcessData->HandleTable = NULL; ProcessData->HandleTable = NULL;
Console = ProcessData->Console; Console = ProcessData->Console;
ProcessData->Console = NULL;
RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
if (Console != NULL) if (Console != NULL)
{ {
EnterCriticalSection(&Console->Header.Lock); ProcessData->Console = NULL;
EnterCriticalSection(&Console->Lock);
RemoveEntryList(&ProcessData->ProcessEntry); RemoveEntryList(&ProcessData->ProcessEntry);
LeaveCriticalSection(&Console->Header.Lock); LeaveCriticalSection(&Console->Lock);
Win32CsrReleaseObjectByPointer(&Console->Header); if (_InterlockedDecrement(&Console->ReferenceCount) == 0)
ConioDeleteConsole(&Console->Header);
RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }
RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
return STATUS_INVALID_PARAMETER; return STATUS_INVALID_PARAMETER;
} }
@ -215,11 +192,8 @@ Win32CsrInsertObject(
ProcessData->HandleTable = Block; ProcessData->HandleTable = Block;
ProcessData->HandleTableSize += 64; ProcessData->HandleTableSize += 64;
} }
ProcessData->HandleTable[i].Object = Object; Win32CsrCreateHandleEntry(&ProcessData->HandleTable[i], Object, Access, Inheritable);
ProcessData->HandleTable[i].Access = Access;
ProcessData->HandleTable[i].Inheritable = Inheritable;
*Handle = UlongToHandle((i << 2) | 0x3); *Handle = UlongToHandle((i << 2) | 0x3);
_InterlockedIncrement( &Object->ReferenceCount );
RtlLeaveCriticalSection(&ProcessData->HandleTableLock); RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
return(STATUS_SUCCESS); return(STATUS_SUCCESS);
} }
@ -256,8 +230,10 @@ Win32CsrDuplicateHandleTable(
if (SourceProcessData->HandleTable[i].Object != NULL && if (SourceProcessData->HandleTable[i].Object != NULL &&
SourceProcessData->HandleTable[i].Inheritable) SourceProcessData->HandleTable[i].Inheritable)
{ {
TargetProcessData->HandleTable[i] = SourceProcessData->HandleTable[i]; Win32CsrCreateHandleEntry(&TargetProcessData->HandleTable[i],
_InterlockedIncrement( &SourceProcessData->HandleTable[i].Object->ReferenceCount ); SourceProcessData->HandleTable[i].Object,
SourceProcessData->HandleTable[i].Access,
SourceProcessData->HandleTable[i].Inheritable);
} }
} }
RtlLeaveCriticalSection(&SourceProcessData->HandleTableLock); RtlLeaveCriticalSection(&SourceProcessData->HandleTableLock);
@ -385,9 +361,7 @@ CSR_API(CsrDuplicateHandle)
if (NT_SUCCESS(Request->Status) if (NT_SUCCESS(Request->Status)
&& Request->Data.DuplicateHandleRequest.Options & DUPLICATE_CLOSE_SOURCE) && Request->Data.DuplicateHandleRequest.Options & DUPLICATE_CLOSE_SOURCE)
{ {
/* Close the original handle. This cannot drop the count to 0, since a new handle now exists */ Win32CsrCloseHandleEntry(Entry);
_InterlockedDecrement(&Entry->Object->ReferenceCount);
Entry->Object = NULL;
} }
RtlLeaveCriticalSection(&ProcessData->HandleTableLock); RtlLeaveCriticalSection(&ProcessData->HandleTableLock);

View file

@ -17,8 +17,8 @@ extern HINSTANCE Win32CsrDllHandle;
typedef struct Object_tt typedef struct Object_tt
{ {
LONG Type; LONG Type;
LONG ReferenceCount; struct tagCSRSS_CONSOLE *Console;
CRITICAL_SECTION Lock; LONG HandleCount;
} Object_t; } Object_t;
typedef struct _CSRSS_HANDLE typedef struct _CSRSS_HANDLE
@ -48,11 +48,6 @@ NTSTATUS FASTCALL Win32CsrLockObject(PCSRSS_PROCESS_DATA ProcessData,
DWORD Access, DWORD Access,
long Type); long Type);
VOID FASTCALL Win32CsrUnlockObject(Object_t *Object); 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, NTSTATUS FASTCALL Win32CsrReleaseObject(PCSRSS_PROCESS_DATA ProcessData,
HANDLE Object); HANDLE Object);
NTSTATUS WINAPI Win32CsrReleaseConsole(PCSRSS_PROCESS_DATA ProcessData); NTSTATUS WINAPI Win32CsrReleaseConsole(PCSRSS_PROCESS_DATA ProcessData);