Author: hbelusca Date: Mon Aug 4 16:25:12 2014 New Revision: 63803
URL: http://svn.reactos.org/svn/reactos?rev=63803&view=rev Log: [KERNEL32] Add a bunch of missing _SEH_YIELD in 'return' clues in _SEH_TRY clauses.
[KERNEL32][CONSRV] Make kernel32 / winsrv console CSR structures Win2k3-compliant for Read/WriteConsoleOutput functions. The last missing ones are Alloc/Attach/FreeConsole APIs!!
Part 9/10
CORE-7931
Added: branches/condrv_restructure/win32ss/user/winsrv/consrv/include/rect.h (with props) Modified: branches/condrv_restructure/dll/win32/kernel32/client/console/readwrite.c branches/condrv_restructure/include/reactos/subsys/win/conmsg.h branches/condrv_restructure/win32ss/user/winsrv/consrv/condrv/conoutput.c branches/condrv_restructure/win32ss/user/winsrv/consrv/condrv/text.c branches/condrv_restructure/win32ss/user/winsrv/consrv/conoutput.c branches/condrv_restructure/win32ss/user/winsrv/consrv/include/conio.h branches/condrv_restructure/win32ss/user/winsrv/consrv/include/conio_winsrv.h
Modified: branches/condrv_restructure/dll/win32/kernel32/client/console/readwrite.c URL: http://svn.reactos.org/svn/reactos/branches/condrv_restructure/dll/win32/ker... ============================================================================== --- branches/condrv_restructure/dll/win32/kernel32/client/console/readwrite.c [iso-8859-1] (original) +++ branches/condrv_restructure/dll/win32/kernel32/client/console/readwrite.c [iso-8859-1] Mon Aug 4 16:25:12 2014 @@ -18,6 +18,13 @@ #include <debug.h>
+/* See consrv/include/rect.h */ +#define ConioRectHeight(Rect) \ + (((Rect)->Top) > ((Rect)->Bottom) ? 0 : ((Rect)->Bottom) - ((Rect)->Top) + 1) +#define ConioRectWidth(Rect) \ + (((Rect)->Left) > ((Rect)->Right) ? 0 : ((Rect)->Right) - ((Rect)->Left) + 1) + + /* PRIVATE FUNCTIONS **********************************************************/
/****************** @@ -57,7 +64,7 @@ */ // 1- Get the exe name length in characters, including NULL character. ReadConsoleRequest->ExeLength = - GetConsoleInputExeNameW(0, (PWCHAR)ReadConsoleRequest->StaticBuffer); + (USHORT)GetConsoleInputExeNameW(0, (PWCHAR)ReadConsoleRequest->StaticBuffer); // 2- Get the exe name (GetConsoleInputExeNameW returns 1 in case of success). if (GetConsoleInputExeNameW(ReadConsoleRequest->ExeLength, (PWCHAR)ReadConsoleRequest->StaticBuffer) != 1) @@ -170,7 +177,7 @@ // HACK if (CaptureBuffer) CsrFreeCaptureBuffer(CaptureBuffer); SetLastError(ERROR_INVALID_ACCESS); - return FALSE; + _SEH2_YIELD(return FALSE); } _SEH2_END;
@@ -356,41 +363,73 @@ IN OUT PSMALL_RECT lpReadRegion, IN BOOLEAN bUnicode) { + BOOL Success; CONSOLE_API_MESSAGE ApiMessage; PCONSOLE_READOUTPUT ReadOutputRequest = &ApiMessage.Data.ReadOutputRequest; - PCSR_CAPTURE_BUFFER CaptureBuffer; - DWORD Size, SizeX, SizeY; - - if (lpBuffer == NULL) + PCSR_CAPTURE_BUFFER CaptureBuffer = NULL; + + SHORT SizeX, SizeY; + ULONG NumCells; + + /* Set up the data to send to the Console Server */ + ReadOutputRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle; + ReadOutputRequest->OutputHandle = hConsoleOutput; + ReadOutputRequest->Unicode = bUnicode; + + /* Update lpReadRegion */ + _SEH2_TRY + { + SizeX = min(dwBufferSize.X - dwBufferCoord.X, ConioRectWidth(lpReadRegion)); + SizeY = min(dwBufferSize.Y - dwBufferCoord.Y, ConioRectHeight(lpReadRegion)); + if (SizeX <= 0 || SizeY <= 0) + { + SetLastError(ERROR_INVALID_PARAMETER); + _SEH2_YIELD(return FALSE); + } + lpReadRegion->Right = lpReadRegion->Left + SizeX - 1; + lpReadRegion->Bottom = lpReadRegion->Top + SizeY - 1; + + ReadOutputRequest->ReadRegion = *lpReadRegion; + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { SetLastError(ERROR_INVALID_ACCESS); - return FALSE; - } - - Size = dwBufferSize.X * dwBufferSize.Y * sizeof(CHAR_INFO); - - DPRINT("IntReadConsoleOutput: %lx %p\n", Size, lpReadRegion); - - /* Allocate a Capture Buffer */ - CaptureBuffer = CsrAllocateCaptureBuffer(1, Size); - if (CaptureBuffer == NULL) - { - DPRINT1("CsrAllocateCaptureBuffer failed with size 0x%x!\n", Size); - SetLastError(ERROR_NOT_ENOUGH_MEMORY); - return FALSE; - } - - /* Allocate space in the Buffer */ - CsrAllocateMessagePointer(CaptureBuffer, - Size, - (PVOID*)&ReadOutputRequest->CharInfo); - - /* Set up the data to send to the Console Server */ - ReadOutputRequest->OutputHandle = hConsoleOutput; - ReadOutputRequest->Unicode = bUnicode; - ReadOutputRequest->BufferSize = dwBufferSize; - ReadOutputRequest->BufferCoord = dwBufferCoord; - ReadOutputRequest->ReadRegion = *lpReadRegion; + _SEH2_YIELD(return FALSE); + } + _SEH2_END; + + NumCells = SizeX * SizeY; + DPRINT1("IntReadConsoleOutput: (%d x %d)\n", SizeX, SizeY); + + /* + * For optimization purposes, Windows (and hence ReactOS, too, for + * compatibility reasons) uses a static buffer if no more than one + * cell is read. Otherwise a new buffer is allocated. + * This behaviour is also expected in the server-side. + */ + if (NumCells <= 1) + { + ReadOutputRequest->CharInfo = &ReadOutputRequest->StaticBuffer; + // CaptureBuffer = NULL; + } + else + { + ULONG Size = NumCells * sizeof(CHAR_INFO); + + /* Allocate a Capture Buffer */ + CaptureBuffer = CsrAllocateCaptureBuffer(1, Size); + if (CaptureBuffer == NULL) + { + DPRINT1("CsrAllocateCaptureBuffer failed with size %ld!\n", Size); + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + return FALSE; + } + + /* Allocate space in the Buffer */ + CsrAllocateMessagePointer(CaptureBuffer, + Size, + (PVOID*)&ReadOutputRequest->CharInfo); + }
/* Call the server */ CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage, @@ -399,32 +438,56 @@ sizeof(*ReadOutputRequest));
/* Check for success */ - if (NT_SUCCESS(ApiMessage.Status)) - { - /* Copy into the buffer */ - DPRINT("Copying to buffer\n"); - SizeX = ReadOutputRequest->ReadRegion.Right - - ReadOutputRequest->ReadRegion.Left + 1; - SizeY = ReadOutputRequest->ReadRegion.Bottom - - ReadOutputRequest->ReadRegion.Top + 1; - RtlCopyMemory(lpBuffer, - ReadOutputRequest->CharInfo, - sizeof(CHAR_INFO) * SizeX * SizeY); - } - else - { - BaseSetLastNTError(ApiMessage.Status); - } - - /* Return the read region */ - DPRINT("read region: %p\n", ReadOutputRequest->ReadRegion); - *lpReadRegion = ReadOutputRequest->ReadRegion; - - /* Release the capture buffer */ - CsrFreeCaptureBuffer(CaptureBuffer); - - /* Return TRUE or FALSE */ - return NT_SUCCESS(ApiMessage.Status); + Success = NT_SUCCESS(ApiMessage.Status); + + /* Retrieve the results */ + _SEH2_TRY + { + *lpReadRegion = ReadOutputRequest->ReadRegion; + + if (Success) + { +#if 0 + SHORT x, X; +#endif + SHORT y, Y; + + /* Copy into the buffer */ + + SizeX = ReadOutputRequest->ReadRegion.Right - + ReadOutputRequest->ReadRegion.Left + 1; + + for (y = 0, Y = ReadOutputRequest->ReadRegion.Top; Y <= ReadOutputRequest->ReadRegion.Bottom; ++y, ++Y) + { + RtlCopyMemory(lpBuffer + (y + dwBufferCoord.Y) * dwBufferSize.X + dwBufferCoord.X, + ReadOutputRequest->CharInfo + y * SizeX, + SizeX * sizeof(CHAR_INFO)); +#if 0 + for (x = 0, X = ReadOutputRequest->ReadRegion.Left; X <= ReadOutputRequest->ReadRegion.Right; ++x, ++X) + { + *(lpBuffer + (y + dwBufferCoord.Y) * dwBufferSize.X + (x + dwBufferCoord.X)) = + *(ReadOutputRequest->CharInfo + y * SizeX + x); + } +#endif + } + } + else + { + BaseSetLastNTError(ApiMessage.Status); + } + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + SetLastError(ERROR_INVALID_ACCESS); + Success = FALSE; + } + _SEH2_END; + + /* Release the capture buffer if needed */ + if (CaptureBuffer) CsrFreeCaptureBuffer(CaptureBuffer); + + /* Return success status */ + return Success; }
@@ -602,7 +665,7 @@ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { SetLastError(ERROR_INVALID_ACCESS); - return FALSE; + _SEH2_YIELD(return FALSE); } _SEH2_END; } @@ -704,7 +767,7 @@ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { SetLastError(ERROR_INVALID_ACCESS); - return FALSE; + _SEH2_YIELD(return FALSE); } _SEH2_END; } @@ -770,49 +833,107 @@ IN OUT PSMALL_RECT lpWriteRegion, IN BOOLEAN bUnicode) { + BOOL Success; CONSOLE_API_MESSAGE ApiMessage; PCONSOLE_WRITEOUTPUT WriteOutputRequest = &ApiMessage.Data.WriteOutputRequest; - PCSR_CAPTURE_BUFFER CaptureBuffer; - ULONG Size; - - if ((lpBuffer == NULL) || (lpWriteRegion == NULL)) + PCSR_CAPTURE_BUFFER CaptureBuffer = NULL; + + SHORT SizeX, SizeY; + ULONG NumCells; + + /* Set up the data to send to the Console Server */ + WriteOutputRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle; + WriteOutputRequest->OutputHandle = hConsoleOutput; + WriteOutputRequest->Unicode = bUnicode; + + /* Update lpWriteRegion */ + _SEH2_TRY + { + SizeX = min(dwBufferSize.X - dwBufferCoord.X, ConioRectWidth(lpWriteRegion)); + SizeY = min(dwBufferSize.Y - dwBufferCoord.Y, ConioRectHeight(lpWriteRegion)); + if (SizeX <= 0 || SizeY <= 0) + { + SetLastError(ERROR_INVALID_PARAMETER); + _SEH2_YIELD(return FALSE); + } + lpWriteRegion->Right = lpWriteRegion->Left + SizeX - 1; + lpWriteRegion->Bottom = lpWriteRegion->Top + SizeY - 1; + + WriteOutputRequest->WriteRegion = *lpWriteRegion; + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { SetLastError(ERROR_INVALID_ACCESS); - return FALSE; - } + _SEH2_YIELD(return FALSE); + } + _SEH2_END; + + NumCells = SizeX * SizeY; + DPRINT1("IntWriteConsoleOutput: (%d x %d)\n", SizeX, SizeY); + /* - if (lpWriteRegion == NULL) - { - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; - } - */ - - Size = dwBufferSize.Y * dwBufferSize.X * sizeof(CHAR_INFO); - - DPRINT("IntWriteConsoleOutput: %lx %p\n", Size, lpWriteRegion); - - /* Allocate a Capture Buffer */ - CaptureBuffer = CsrAllocateCaptureBuffer(1, Size); - if (CaptureBuffer == NULL) - { - DPRINT1("CsrAllocateCaptureBuffer failed!\n"); - SetLastError(ERROR_NOT_ENOUGH_MEMORY); - return FALSE; - } - - /* Capture the user buffer */ - CsrCaptureMessageBuffer(CaptureBuffer, - (PVOID)lpBuffer, - Size, - (PVOID*)&WriteOutputRequest->CharInfo); - - /* Set up the data to send to the Console Server */ - WriteOutputRequest->OutputHandle = hConsoleOutput; - WriteOutputRequest->Unicode = bUnicode; - WriteOutputRequest->BufferSize = dwBufferSize; - WriteOutputRequest->BufferCoord = dwBufferCoord; - WriteOutputRequest->WriteRegion = *lpWriteRegion; + * For optimization purposes, Windows (and hence ReactOS, too, for + * compatibility reasons) uses a static buffer if no more than one + * cell is written. Otherwise a new buffer is allocated. + * This behaviour is also expected in the server-side. + */ + if (NumCells <= 1) + { + WriteOutputRequest->CharInfo = &WriteOutputRequest->StaticBuffer; + // CaptureBuffer = NULL; + } + else + { + ULONG Size = NumCells * sizeof(CHAR_INFO); + + /* Allocate a Capture Buffer */ + CaptureBuffer = CsrAllocateCaptureBuffer(1, Size); + if (CaptureBuffer == NULL) + { + DPRINT1("CsrAllocateCaptureBuffer failed with size %ld!\n", Size); + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + return FALSE; + } + + /* Allocate space in the Buffer */ + CsrAllocateMessagePointer(CaptureBuffer, + Size, + (PVOID*)&WriteOutputRequest->CharInfo); + } + + /* Capture the user buffer contents */ + _SEH2_TRY + { +#if 0 + SHORT x, X; +#endif + SHORT y, Y; + + /* Copy into the buffer */ + + SizeX = WriteOutputRequest->WriteRegion.Right - + WriteOutputRequest->WriteRegion.Left + 1; + + for (y = 0, Y = WriteOutputRequest->WriteRegion.Top; Y <= WriteOutputRequest->WriteRegion.Bottom; ++y, ++Y) + { + RtlCopyMemory(WriteOutputRequest->CharInfo + y * SizeX, + lpBuffer + (y + dwBufferCoord.Y) * dwBufferSize.X + dwBufferCoord.X, + SizeX * sizeof(CHAR_INFO)); +#if 0 + for (x = 0, X = WriteOutputRequest->WriteRegion.Left; X <= WriteOutputRequest->WriteRegion.Right; ++x, ++X) + { + *(WriteOutputRequest->CharInfo + y * SizeX + x) = + *(lpBuffer + (y + dwBufferCoord.Y) * dwBufferSize.X + (x + dwBufferCoord.X)); + } +#endif + } + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + SetLastError(ERROR_INVALID_ACCESS); + _SEH2_YIELD(return FALSE); + } + _SEH2_END;
/* Call the server */ CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage, @@ -821,20 +942,28 @@ sizeof(*WriteOutputRequest));
/* Check for success */ - if (!NT_SUCCESS(ApiMessage.Status)) - { - BaseSetLastNTError(ApiMessage.Status); - } - - /* Return the read region */ - DPRINT("read region: %p\n", WriteOutputRequest->WriteRegion); - *lpWriteRegion = WriteOutputRequest->WriteRegion; - - /* Release the capture buffer */ - CsrFreeCaptureBuffer(CaptureBuffer); - - /* Return TRUE or FALSE */ - return NT_SUCCESS(ApiMessage.Status); + Success = NT_SUCCESS(ApiMessage.Status); + + /* Release the capture buffer if needed */ + if (CaptureBuffer) CsrFreeCaptureBuffer(CaptureBuffer); + + /* Retrieve the results */ + _SEH2_TRY + { + *lpWriteRegion = WriteOutputRequest->WriteRegion; + + if (!Success) + BaseSetLastNTError(ApiMessage.Status); + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + SetLastError(ERROR_INVALID_ACCESS); + Success = FALSE; + } + _SEH2_END; + + /* Return success status */ + return Success; }
@@ -907,7 +1036,7 @@ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { SetLastError(ERROR_INVALID_ACCESS); - return FALSE; + _SEH2_YIELD(return FALSE); } _SEH2_END; }
Modified: branches/condrv_restructure/include/reactos/subsys/win/conmsg.h URL: http://svn.reactos.org/svn/reactos/branches/condrv_restructure/include/react... ============================================================================== --- branches/condrv_restructure/include/reactos/subsys/win/conmsg.h [iso-8859-1] (original) +++ branches/condrv_restructure/include/reactos/subsys/win/conmsg.h [iso-8859-1] Mon Aug 4 16:25:12 2014 @@ -429,17 +429,6 @@
typedef struct { - HANDLE OutputHandle; - - BOOL Unicode; - COORD BufferSize; - COORD BufferCoord; // WriteCoord - SMALL_RECT WriteRegion; - PCHAR_INFO CharInfo; -} CONSOLE_WRITEOUTPUT, *PCONSOLE_WRITEOUTPUT; - -typedef struct -{ HANDLE ConsoleHandle; HANDLE InputHandle; } CONSOLE_FLUSHINPUTBUFFER, *PCONSOLE_FLUSHINPUTBUFFER; @@ -533,14 +522,29 @@
typedef struct { - HANDLE OutputHandle; - - BOOL Unicode; - COORD BufferSize; - COORD BufferCoord; + HANDLE ConsoleHandle; + HANDLE OutputHandle; + + CHAR_INFO StaticBuffer; + PCHAR_INFO CharInfo; + SMALL_RECT ReadRegion; + BOOLEAN Unicode; +} CONSOLE_READOUTPUT, *PCONSOLE_READOUTPUT; + +typedef struct +{ + HANDLE ConsoleHandle; + HANDLE OutputHandle; + + CHAR_INFO StaticBuffer; PCHAR_INFO CharInfo; -} CONSOLE_READOUTPUT, *PCONSOLE_READOUTPUT; + + SMALL_RECT WriteRegion; + BOOLEAN Unicode; + + ULONG Unknown; +} CONSOLE_WRITEOUTPUT, *PCONSOLE_WRITEOUTPUT;
typedef struct {
Modified: branches/condrv_restructure/win32ss/user/winsrv/consrv/condrv/conoutput.c URL: http://svn.reactos.org/svn/reactos/branches/condrv_restructure/win32ss/user/... ============================================================================== --- branches/condrv_restructure/win32ss/user/winsrv/consrv/condrv/conoutput.c [iso-8859-1] (original) +++ branches/condrv_restructure/win32ss/user/winsrv/consrv/condrv/conoutput.c [iso-8859-1] Mon Aug 4 16:25:12 2014 @@ -159,7 +159,8 @@
if (ActiveBuffer) { - ConioInitRect(&Region, 0, 0, ActiveBuffer->ViewSize.Y - 1, ActiveBuffer->ViewSize.X - 1); + ConioInitRect(&Region, 0, 0, + ActiveBuffer->ViewSize.Y - 1, ActiveBuffer->ViewSize.X - 1); TermDrawRegion(Console, &Region); } }
Modified: branches/condrv_restructure/win32ss/user/winsrv/consrv/condrv/text.c URL: http://svn.reactos.org/svn/reactos/branches/condrv_restructure/win32ss/user/... ============================================================================== --- branches/condrv_restructure/win32ss/user/winsrv/consrv/condrv/text.c [iso-8859-1] (original) +++ branches/condrv_restructure/win32ss/user/winsrv/consrv/condrv/text.c [iso-8859-1] Mon Aug 4 16:25:12 2014 @@ -138,65 +138,6 @@ Ptr->Char.UnicodeChar = L' '; Ptr->Attributes = Buff->ScreenDefaultAttrib; } -} - -static __inline BOOLEAN -ConioGetIntersection(OUT PSMALL_RECT Intersection, - IN PSMALL_RECT Rect1, - IN PSMALL_RECT Rect2) -{ - if ( ConioIsRectEmpty(Rect1) || - ConioIsRectEmpty(Rect2) || - (Rect1->Top > Rect2->Bottom) || - (Rect1->Left > Rect2->Right) || - (Rect1->Bottom < Rect2->Top) || - (Rect1->Right < Rect2->Left) ) - { - /* The rectangles do not intersect */ - ConioInitRect(Intersection, 0, -1, 0, -1); - return FALSE; - } - - ConioInitRect(Intersection, - max(Rect1->Top , Rect2->Top ), - max(Rect1->Left , Rect2->Left ), - min(Rect1->Bottom, Rect2->Bottom), - min(Rect1->Right , Rect2->Right )); - - return TRUE; -} - -static __inline BOOLEAN -ConioGetUnion(OUT PSMALL_RECT Union, - IN PSMALL_RECT Rect1, - IN PSMALL_RECT Rect2) -{ - if (ConioIsRectEmpty(Rect1)) - { - if (ConioIsRectEmpty(Rect2)) - { - ConioInitRect(Union, 0, -1, 0, -1); - return FALSE; - } - else - { - *Union = *Rect2; - } - } - else if (ConioIsRectEmpty(Rect2)) - { - *Union = *Rect1; - } - else - { - ConioInitRect(Union, - min(Rect1->Top , Rect2->Top ), - min(Rect1->Left , Rect2->Left ), - max(Rect1->Bottom, Rect2->Bottom), - max(Rect1->Right , Rect2->Right )); - } - - return TRUE; }
static VOID @@ -669,21 +610,15 @@ IN PTEXTMODE_SCREEN_BUFFER Buffer, IN BOOLEAN Unicode, OUT PCHAR_INFO CharInfo/*Buffer*/, - IN PCOORD BufferSize, - IN PCOORD BufferCoord, IN OUT PSMALL_RECT ReadRegion) { + SHORT X, Y; + SMALL_RECT ScreenBuffer; PCHAR_INFO CurCharInfo; - SHORT SizeX, SizeY; SMALL_RECT CapturedReadRegion; - SMALL_RECT ScreenRect; - DWORD i; PCHAR_INFO Ptr; - LONG X, Y; - UINT CodePage; - - if (Console == NULL || Buffer == NULL || CharInfo == NULL || - BufferSize == NULL || BufferCoord == NULL || ReadRegion == NULL) + + if (Console == NULL || Buffer == NULL || CharInfo == NULL || ReadRegion == NULL) { return STATUS_INVALID_PARAMETER; } @@ -693,26 +628,24 @@
CapturedReadRegion = *ReadRegion;
- /* FIXME: Is this correct? */ - CodePage = Console->OutputCodePage; - - SizeX = min(BufferSize->X - BufferCoord->X, ConioRectWidth(&CapturedReadRegion)); - SizeY = min(BufferSize->Y - BufferCoord->Y, ConioRectHeight(&CapturedReadRegion)); - CapturedReadRegion.Right = CapturedReadRegion.Left + SizeX; - CapturedReadRegion.Bottom = CapturedReadRegion.Top + SizeY; - - ConioInitRect(&ScreenRect, 0, 0, Buffer->ScreenBufferSize.Y, Buffer->ScreenBufferSize.X); - if (!ConioGetIntersection(&CapturedReadRegion, &ScreenRect, &CapturedReadRegion)) - { + /* Make sure ReadRegion is inside the screen buffer */ + ConioInitRect(&ScreenBuffer, 0, 0, + Buffer->ScreenBufferSize.Y - 1, Buffer->ScreenBufferSize.X - 1); + if (!ConioGetIntersection(&CapturedReadRegion, &ScreenBuffer, &CapturedReadRegion)) + { + /* + * It is okay to have a ReadRegion completely outside + * the screen buffer. No data is read then. + */ return STATUS_SUCCESS; }
- for (i = 0, Y = CapturedReadRegion.Top; Y < CapturedReadRegion.Bottom; ++i, ++Y) - { - CurCharInfo = CharInfo + (i * BufferSize->X); - + CurCharInfo = CharInfo; + + for (Y = CapturedReadRegion.Top; Y <= CapturedReadRegion.Bottom; ++Y) + { Ptr = ConioCoordToPointer(Buffer, CapturedReadRegion.Left, Y); - for (X = CapturedReadRegion.Left; X < CapturedReadRegion.Right; ++X) + for (X = CapturedReadRegion.Left; X <= CapturedReadRegion.Right; ++X) { if (Unicode) { @@ -721,7 +654,7 @@ else { // ConsoleUnicodeCharToAnsiChar(Console, &CurCharInfo->Char.AsciiChar, &Ptr->Char.UnicodeChar); - WideCharToMultiByte(CodePage, 0, &Ptr->Char.UnicodeChar, 1, + WideCharToMultiByte(Console->OutputCodePage, 0, &Ptr->Char.UnicodeChar, 1, &CurCharInfo->Char.AsciiChar, 1, NULL, NULL); } CurCharInfo->Attributes = Ptr->Attributes; @@ -730,10 +663,7 @@ } }
- ReadRegion->Left = CapturedReadRegion.Left; - ReadRegion->Top = CapturedReadRegion.Top ; - ReadRegion->Right = CapturedReadRegion.Left + SizeX - 1; - ReadRegion->Bottom = CapturedReadRegion.Top + SizeY - 1; + *ReadRegion = CapturedReadRegion;
return STATUS_SUCCESS; } @@ -743,18 +673,15 @@ IN PTEXTMODE_SCREEN_BUFFER Buffer, IN BOOLEAN Unicode, IN PCHAR_INFO CharInfo/*Buffer*/, - IN PCOORD BufferSize, - IN PCOORD BufferCoord, IN OUT PSMALL_RECT WriteRegion) { - SHORT i, X, Y, SizeX, SizeY; + SHORT X, Y; SMALL_RECT ScreenBuffer; PCHAR_INFO CurCharInfo; SMALL_RECT CapturedWriteRegion; PCHAR_INFO Ptr;
- if (Console == NULL || Buffer == NULL || CharInfo == NULL || - BufferSize == NULL || BufferCoord == NULL || WriteRegion == NULL) + if (Console == NULL || Buffer == NULL || CharInfo == NULL || WriteRegion == NULL) { return STATUS_INVALID_PARAMETER; } @@ -764,13 +691,9 @@
CapturedWriteRegion = *WriteRegion;
- SizeX = min(BufferSize->X - BufferCoord->X, ConioRectWidth(&CapturedWriteRegion)); - SizeY = min(BufferSize->Y - BufferCoord->Y, ConioRectHeight(&CapturedWriteRegion)); - CapturedWriteRegion.Right = CapturedWriteRegion.Left + SizeX - 1; - CapturedWriteRegion.Bottom = CapturedWriteRegion.Top + SizeY - 1; - /* Make sure WriteRegion is inside the screen buffer */ - ConioInitRect(&ScreenBuffer, 0, 0, Buffer->ScreenBufferSize.Y - 1, Buffer->ScreenBufferSize.X - 1); + ConioInitRect(&ScreenBuffer, 0, 0, + Buffer->ScreenBufferSize.Y - 1, Buffer->ScreenBufferSize.X - 1); if (!ConioGetIntersection(&CapturedWriteRegion, &ScreenBuffer, &CapturedWriteRegion)) { /* @@ -780,12 +703,12 @@ return STATUS_SUCCESS; }
- for (i = 0, Y = CapturedWriteRegion.Top; Y <= CapturedWriteRegion.Bottom; i++, Y++) - { - CurCharInfo = CharInfo + (i + BufferCoord->Y) * BufferSize->X + BufferCoord->X; - + CurCharInfo = CharInfo; + + for (Y = CapturedWriteRegion.Top; Y <= CapturedWriteRegion.Bottom; ++Y) + { Ptr = ConioCoordToPointer(Buffer, CapturedWriteRegion.Left, Y); - for (X = CapturedWriteRegion.Left; X <= CapturedWriteRegion.Right; X++) + for (X = CapturedWriteRegion.Left; X <= CapturedWriteRegion.Right; ++X) { if (Unicode) { @@ -803,10 +726,7 @@
TermDrawRegion(Console, &CapturedWriteRegion);
- WriteRegion->Left = CapturedWriteRegion.Left; - WriteRegion->Top = CapturedWriteRegion.Top ; - WriteRegion->Right = CapturedWriteRegion.Left + SizeX - 1; - WriteRegion->Bottom = CapturedWriteRegion.Top + SizeY - 1; + *WriteRegion = CapturedWriteRegion;
return STATUS_SUCCESS; } @@ -1293,7 +1213,8 @@ CapturedDestinationOrigin = *DestinationOrigin;
/* Make sure the source rectangle is inside the screen buffer */ - ConioInitRect(&ScreenBuffer, 0, 0, Buffer->ScreenBufferSize.Y - 1, Buffer->ScreenBufferSize.X - 1); + ConioInitRect(&ScreenBuffer, 0, 0, + Buffer->ScreenBufferSize.Y - 1, Buffer->ScreenBufferSize.X - 1); if (!ConioGetIntersection(&SrcRegion, &ScreenBuffer, ScrollRectangle)) { return STATUS_SUCCESS;
Modified: branches/condrv_restructure/win32ss/user/winsrv/consrv/conoutput.c URL: http://svn.reactos.org/svn/reactos/branches/condrv_restructure/win32ss/user/... ============================================================================== --- branches/condrv_restructure/win32ss/user/winsrv/consrv/conoutput.c [iso-8859-1] (original) +++ branches/condrv_restructure/win32ss/user/winsrv/consrv/conoutput.c [iso-8859-1] Mon Aug 4 16:25:12 2014 @@ -451,8 +451,6 @@ IN PTEXTMODE_SCREEN_BUFFER Buffer, IN BOOLEAN Unicode, OUT PCHAR_INFO CharInfo/*Buffer*/, - IN PCOORD BufferSize, - IN PCOORD BufferCoord, IN OUT PSMALL_RECT ReadRegion); CSR_API(SrvReadConsoleOutput) { @@ -460,14 +458,40 @@ PCONSOLE_READOUTPUT ReadOutputRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.ReadOutputRequest; PTEXTMODE_SCREEN_BUFFER Buffer;
+ ULONG NumCells; + PCHAR_INFO CharInfo; + DPRINT("SrvReadConsoleOutput\n");
- if (!CsrValidateMessageBuffer(ApiMessage, - (PVOID*)&ReadOutputRequest->CharInfo, - ReadOutputRequest->BufferSize.X * ReadOutputRequest->BufferSize.Y, - sizeof(CHAR_INFO))) - { - return STATUS_INVALID_PARAMETER; + /* + * For optimization purposes, Windows (and hence ReactOS, too, for + * compatibility reasons) uses a static buffer if no more than one + * cell is read. Otherwise a new buffer is used. + * The client-side expects that we know this behaviour. + */ + NumCells = (ReadOutputRequest->ReadRegion.Right - ReadOutputRequest->ReadRegion.Left + 1) * + (ReadOutputRequest->ReadRegion.Bottom - ReadOutputRequest->ReadRegion.Top + 1); + + if (NumCells <= 1) + { + /* + * Adjust the internal pointer, because its old value points to + * the static buffer in the original ApiMessage structure. + */ + // ReadOutputRequest->CharInfo = &ReadOutputRequest->StaticBuffer; + CharInfo = &ReadOutputRequest->StaticBuffer; + } + else + { + if (!CsrValidateMessageBuffer(ApiMessage, + (PVOID*)&ReadOutputRequest->CharInfo, + NumCells, + sizeof(CHAR_INFO))) + { + return STATUS_INVALID_PARAMETER; + } + + CharInfo = ReadOutputRequest->CharInfo; }
Status = ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process), @@ -478,9 +502,7 @@ Status = ConDrvReadConsoleOutput(Buffer->Header.Console, Buffer, ReadOutputRequest->Unicode, - ReadOutputRequest->CharInfo, - &ReadOutputRequest->BufferSize, - &ReadOutputRequest->BufferCoord, + CharInfo, &ReadOutputRequest->ReadRegion);
ConSrvReleaseScreenBuffer(Buffer, TRUE); @@ -492,8 +514,6 @@ IN PTEXTMODE_SCREEN_BUFFER Buffer, IN BOOLEAN Unicode, IN PCHAR_INFO CharInfo/*Buffer*/, - IN PCOORD BufferSize, - IN PCOORD BufferCoord, IN OUT PSMALL_RECT WriteRegion); CSR_API(SrvWriteConsoleOutput) { @@ -501,14 +521,40 @@ PCONSOLE_WRITEOUTPUT WriteOutputRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.WriteOutputRequest; PTEXTMODE_SCREEN_BUFFER Buffer;
+ ULONG NumCells; + PCHAR_INFO CharInfo; + DPRINT("SrvWriteConsoleOutput\n");
- if (!CsrValidateMessageBuffer(ApiMessage, - (PVOID*)&WriteOutputRequest->CharInfo, - WriteOutputRequest->BufferSize.X * WriteOutputRequest->BufferSize.Y, - sizeof(CHAR_INFO))) - { - return STATUS_INVALID_PARAMETER; + /* + * For optimization purposes, Windows (and hence ReactOS, too, for + * compatibility reasons) uses a static buffer if no more than one + * cell is written. Otherwise a new buffer is used. + * The client-side expects that we know this behaviour. + */ + NumCells = (WriteOutputRequest->WriteRegion.Right - WriteOutputRequest->WriteRegion.Left + 1) * + (WriteOutputRequest->WriteRegion.Bottom - WriteOutputRequest->WriteRegion.Top + 1); + + if (NumCells <= 1) + { + /* + * Adjust the internal pointer, because its old value points to + * the static buffer in the original ApiMessage structure. + */ + // WriteOutputRequest->CharInfo = &WriteOutputRequest->StaticBuffer; + CharInfo = &WriteOutputRequest->StaticBuffer; + } + else + { + if (!CsrValidateMessageBuffer(ApiMessage, + (PVOID*)&WriteOutputRequest->CharInfo, + NumCells, + sizeof(CHAR_INFO))) + { + return STATUS_INVALID_PARAMETER; + } + + CharInfo = WriteOutputRequest->CharInfo; }
Status = ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process), @@ -519,9 +565,7 @@ Status = ConDrvWriteConsoleOutput(Buffer->Header.Console, Buffer, WriteOutputRequest->Unicode, - WriteOutputRequest->CharInfo, - &WriteOutputRequest->BufferSize, - &WriteOutputRequest->BufferCoord, + CharInfo, &WriteOutputRequest->WriteRegion);
ConSrvReleaseScreenBuffer(Buffer, TRUE);
Modified: branches/condrv_restructure/win32ss/user/winsrv/consrv/include/conio.h URL: http://svn.reactos.org/svn/reactos/branches/condrv_restructure/win32ss/user/... ============================================================================== --- branches/condrv_restructure/win32ss/user/winsrv/consrv/include/conio.h [iso-8859-1] (original) +++ branches/condrv_restructure/win32ss/user/winsrv/consrv/include/conio.h [iso-8859-1] Mon Aug 4 16:25:12 2014 @@ -9,6 +9,8 @@ */
#pragma once + +#include "rect.h"
#define CSR_DEFAULT_CURSOR_SIZE 25
@@ -342,19 +344,6 @@ PINPUT_RECORD InputEvent);
/* conoutput.c */ -#define ConioInitRect(Rect, top, left, bottom, right) \ -do { \ - ((Rect)->Top) = top; \ - ((Rect)->Left) = left; \ - ((Rect)->Bottom) = bottom; \ - ((Rect)->Right) = right; \ -} while (0) -#define ConioIsRectEmpty(Rect) \ - (((Rect)->Left > (Rect)->Right) || ((Rect)->Top > (Rect)->Bottom)) -#define ConioRectHeight(Rect) \ - (((Rect)->Top) > ((Rect)->Bottom) ? 0 : ((Rect)->Bottom) - ((Rect)->Top) + 1) -#define ConioRectWidth(Rect) \ - (((Rect)->Left) > ((Rect)->Right) ? 0 : ((Rect)->Right) - ((Rect)->Left) + 1)
/* * From MSDN:
Modified: branches/condrv_restructure/win32ss/user/winsrv/consrv/include/conio_winsrv.h URL: http://svn.reactos.org/svn/reactos/branches/condrv_restructure/win32ss/user/... ============================================================================== --- branches/condrv_restructure/win32ss/user/winsrv/consrv/include/conio_winsrv.h [iso-8859-1] (original) +++ branches/condrv_restructure/win32ss/user/winsrv/consrv/include/conio_winsrv.h [iso-8859-1] Mon Aug 4 16:25:12 2014 @@ -9,6 +9,8 @@ */
#pragma once + +#include "rect.h"
#define CSR_DEFAULT_CURSOR_SIZE 25
@@ -151,19 +153,6 @@ PINPUT_RECORD InputEvent);
/* conoutput.c */ -#define ConioInitRect(Rect, top, left, bottom, right) \ -do { \ - ((Rect)->Top) = top; \ - ((Rect)->Left) = left; \ - ((Rect)->Bottom) = bottom; \ - ((Rect)->Right) = right; \ -} while (0) -#define ConioIsRectEmpty(Rect) \ - (((Rect)->Left > (Rect)->Right) || ((Rect)->Top > (Rect)->Bottom)) -#define ConioRectHeight(Rect) \ - (((Rect)->Top) > ((Rect)->Bottom) ? 0 : ((Rect)->Bottom) - ((Rect)->Top) + 1) -#define ConioRectWidth(Rect) \ - (((Rect)->Left) > ((Rect)->Right) ? 0 : ((Rect)->Right) - ((Rect)->Left) + 1)
/* * From MSDN:
Added: branches/condrv_restructure/win32ss/user/winsrv/consrv/include/rect.h URL: http://svn.reactos.org/svn/reactos/branches/condrv_restructure/win32ss/user/... ============================================================================== --- branches/condrv_restructure/win32ss/user/winsrv/consrv/include/rect.h (added) +++ branches/condrv_restructure/win32ss/user/winsrv/consrv/include/rect.h [iso-8859-1] Mon Aug 4 16:25:12 2014 @@ -0,0 +1,85 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Console Server DLL + * FILE: consrv/include/rect.h + * PURPOSE: Rectangle helper functions + * PROGRAMMERS: Gé van Geldorp + * Jeffrey Morlan + */ + +#pragma once + +#define ConioInitRect(Rect, top, left, bottom, right) \ +do { \ + ((Rect)->Top) = top; \ + ((Rect)->Left) = left; \ + ((Rect)->Bottom) = bottom; \ + ((Rect)->Right) = right; \ +} while (0) +#define ConioIsRectEmpty(Rect) \ + (((Rect)->Left > (Rect)->Right) || ((Rect)->Top > (Rect)->Bottom)) + +#define ConioRectHeight(Rect) \ + (((Rect)->Top) > ((Rect)->Bottom) ? 0 : ((Rect)->Bottom) - ((Rect)->Top) + 1) +#define ConioRectWidth(Rect) \ + (((Rect)->Left) > ((Rect)->Right) ? 0 : ((Rect)->Right) - ((Rect)->Left) + 1) + + +static __inline BOOLEAN +ConioGetIntersection(OUT PSMALL_RECT Intersection, + IN PSMALL_RECT Rect1, + IN PSMALL_RECT Rect2) +{ + if ( ConioIsRectEmpty(Rect1) || + ConioIsRectEmpty(Rect2) || + (Rect1->Top > Rect2->Bottom) || + (Rect1->Left > Rect2->Right) || + (Rect1->Bottom < Rect2->Top) || + (Rect1->Right < Rect2->Left) ) + { + /* The rectangles do not intersect */ + ConioInitRect(Intersection, 0, -1, 0, -1); + return FALSE; + } + + ConioInitRect(Intersection, + max(Rect1->Top , Rect2->Top ), + max(Rect1->Left , Rect2->Left ), + min(Rect1->Bottom, Rect2->Bottom), + min(Rect1->Right , Rect2->Right )); + + return TRUE; +} + +static __inline BOOLEAN +ConioGetUnion(OUT PSMALL_RECT Union, + IN PSMALL_RECT Rect1, + IN PSMALL_RECT Rect2) +{ + if (ConioIsRectEmpty(Rect1)) + { + if (ConioIsRectEmpty(Rect2)) + { + ConioInitRect(Union, 0, -1, 0, -1); + return FALSE; + } + else + { + *Union = *Rect2; + } + } + else if (ConioIsRectEmpty(Rect2)) + { + *Union = *Rect1; + } + else + { + ConioInitRect(Union, + min(Rect1->Top , Rect2->Top ), + min(Rect1->Left , Rect2->Left ), + max(Rect1->Bottom, Rect2->Bottom), + max(Rect1->Right , Rect2->Right )); + } + + return TRUE; +}
Propchange: branches/condrv_restructure/win32ss/user/winsrv/consrv/include/rect.h ------------------------------------------------------------------------------ svn:eol-style = native