mirror of
https://github.com/reactos/reactos.git
synced 2024-10-19 23:50:05 +00:00
[KERNEL32] [WIN32CSR] Implement SetConsoleScreenBufferSize. FAR Manager now works again.
svn path=/trunk/; revision=47165
This commit is contained in:
parent
acb61e7d31
commit
630ecdce7c
|
@ -3086,16 +3086,29 @@ FlushConsoleInputBuffer(HANDLE hConsoleInput)
|
|||
/*--------------------------------------------------------------
|
||||
* SetConsoleScreenBufferSize
|
||||
*
|
||||
* @unimplemented
|
||||
* @implemented
|
||||
*/
|
||||
BOOL
|
||||
WINAPI
|
||||
SetConsoleScreenBufferSize(HANDLE hConsoleOutput,
|
||||
COORD dwSize)
|
||||
{
|
||||
DPRINT1("SetConsoleScreenBufferSize(0x%x, 0x%x) UNIMPLEMENTED!\n", hConsoleOutput, dwSize);
|
||||
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
|
||||
return FALSE;
|
||||
CSR_API_MESSAGE Request;
|
||||
ULONG CsrRequest;
|
||||
NTSTATUS Status;
|
||||
|
||||
CsrRequest = MAKE_CSR_API(SET_SCREEN_BUFFER_SIZE, CSR_CONSOLE);
|
||||
Request.Data.SetScreenBufferSize.OutputHandle = hConsoleOutput;
|
||||
Request.Data.SetScreenBufferSize.Size = dwSize;
|
||||
|
||||
Status = CsrClientCallServer(&Request, NULL, CsrRequest, sizeof(CSR_API_MESSAGE));
|
||||
if (!NT_SUCCESS(Status) || !NT_SUCCESS(Status = Request.Status))
|
||||
{
|
||||
SetLastErrorByStatus(Status);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------
|
||||
|
|
|
@ -472,6 +472,11 @@ typedef struct
|
|||
DWORD ProcessGroup;
|
||||
} CSRSS_GENERATE_CTRL_EVENT, *PCSRSS_GENERATE_CTRL_EVENT;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
HANDLE OutputHandle;
|
||||
COORD Size;
|
||||
} CSRSS_SET_SCREEN_BUFFER_SIZE, *PCSRSS_SET_SCREEN_BUFFER_SIZE;
|
||||
|
||||
|
||||
#define CSR_API_MESSAGE_HEADER_SIZE(Type) (FIELD_OFFSET(CSR_API_MESSAGE, Data) + sizeof(Type))
|
||||
|
@ -551,6 +556,7 @@ typedef struct
|
|||
#define GET_CONSOLE_ALIASES_EXES_LENGTH (0x3D)
|
||||
#define GENERATE_CTRL_EVENT (0x3E)
|
||||
#define CREATE_THREAD (0x3F)
|
||||
#define SET_SCREEN_BUFFER_SIZE (0x40)
|
||||
|
||||
/* Keep in sync with definition below. */
|
||||
#define CSRSS_HEADER_SIZE (sizeof(PORT_MESSAGE) + sizeof(ULONG) + sizeof(NTSTATUS))
|
||||
|
@ -624,6 +630,7 @@ typedef struct _CSR_API_MESSAGE
|
|||
CSRSS_GET_CONSOLE_ALIASES_EXES GetConsoleAliasesExes;
|
||||
CSRSS_GET_CONSOLE_ALIASES_EXES_LENGTH GetConsoleAliasesExesLength;
|
||||
CSRSS_GENERATE_CTRL_EVENT GenerateCtrlEvent;
|
||||
CSRSS_SET_SCREEN_BUFFER_SIZE SetScreenBufferSize;
|
||||
} Data;
|
||||
} CSR_API_MESSAGE, *PCSR_API_MESSAGE;
|
||||
|
||||
|
|
|
@ -3118,4 +3118,33 @@ CSR_API(CsrGenerateCtrlEvent)
|
|||
return Status;
|
||||
}
|
||||
|
||||
CSR_API(CsrSetScreenBufferSize)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
PCSRSS_CONSOLE Console;
|
||||
PCSRSS_SCREEN_BUFFER Buff;
|
||||
|
||||
Request->Header.u1.s1.TotalLength = sizeof(CSR_API_MESSAGE);
|
||||
Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE);
|
||||
|
||||
Status = ConioConsoleFromProcessData(ProcessData, &Console);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
return Status;
|
||||
}
|
||||
|
||||
Status = ConioLockScreenBuffer(ProcessData, Request->Data.SetScreenBufferSize.OutputHandle, &Buff, GENERIC_WRITE);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
ConioUnlockConsole(Console);
|
||||
return Status;
|
||||
}
|
||||
|
||||
Status = ConioResizeBuffer(Console, Buff, Request->Data.SetScreenBufferSize.Size);
|
||||
ConioUnlockScreenBuffer(Buff);
|
||||
ConioUnlockConsole(Console);
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* EOF */
|
||||
|
|
|
@ -74,6 +74,7 @@ static CSRSS_API_DEFINITION Win32CsrApiDefinitions[] =
|
|||
CSRSS_DEFINE_API(GET_CONSOLE_ALIASES_EXES, CsrGetConsoleAliasesExes),
|
||||
CSRSS_DEFINE_API(GET_CONSOLE_ALIASES_EXES_LENGTH, CsrGetConsoleAliasesExesLength),
|
||||
CSRSS_DEFINE_API(GENERATE_CTRL_EVENT, CsrGenerateCtrlEvent),
|
||||
CSRSS_DEFINE_API(SET_SCREEN_BUFFER_SIZE, CsrSetScreenBufferSize),
|
||||
{ 0, 0, NULL }
|
||||
};
|
||||
|
||||
|
|
|
@ -1708,11 +1708,105 @@ GuiConsoleHandleScrollbarMenu()
|
|||
|
||||
}
|
||||
|
||||
static NTSTATUS WINAPI
|
||||
GuiResizeBuffer(PCSRSS_CONSOLE Console, PCSRSS_SCREEN_BUFFER ScreenBuffer, COORD Size)
|
||||
{
|
||||
BYTE * Buffer;
|
||||
DWORD Offset = 0;
|
||||
BYTE * OldPtr;
|
||||
USHORT CurrentY;
|
||||
BYTE * OldBuffer;
|
||||
#if HAVE_WMEMSET
|
||||
USHORT value = MAKEWORD(' ', ScreenBuffer->DefaultAttrib);
|
||||
#endif
|
||||
DWORD diff;
|
||||
DWORD i;
|
||||
|
||||
/* Buffer size is not allowed to be smaller than window size */
|
||||
if (Size.X < Console->Size.X || Size.Y < Console->Size.Y)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
|
||||
if (Size.X == ScreenBuffer->MaxX && Size.Y == ScreenBuffer->MaxY)
|
||||
return STATUS_SUCCESS;
|
||||
|
||||
Buffer = HeapAlloc(Win32CsrApiHeap, 0, Size.X * Size.Y * 2);
|
||||
if (!Buffer)
|
||||
return STATUS_NO_MEMORY;
|
||||
|
||||
DPRINT1("Resizing (%d,%d) to (%d,%d)\n", ScreenBuffer->MaxX, ScreenBuffer->MaxY, Size.X, Size.Y);
|
||||
OldBuffer = ScreenBuffer->Buffer;
|
||||
|
||||
for (CurrentY = 0; CurrentY < ScreenBuffer->MaxY && CurrentY < Size.Y; CurrentY++)
|
||||
{
|
||||
OldPtr = ConioCoordToPointer(ScreenBuffer, 0, CurrentY);
|
||||
if (Size.X <= ScreenBuffer->MaxX)
|
||||
{
|
||||
/* reduce size */
|
||||
RtlCopyMemory(&Buffer[Offset], OldPtr, Size.X * 2);
|
||||
Offset += (Size.X * 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* enlarge size */
|
||||
RtlCopyMemory(&Buffer[Offset], OldPtr, ScreenBuffer->MaxX * 2);
|
||||
Offset += (ScreenBuffer->MaxX * 2);
|
||||
|
||||
diff = Size.X - ScreenBuffer->MaxX;
|
||||
/* zero new part of it */
|
||||
#if HAVE_WMEMSET
|
||||
wmemset((WCHAR*)&Buffer[Offset], value, diff);
|
||||
#else
|
||||
for (i = 0; i < diff; i++)
|
||||
{
|
||||
Buffer[Offset++] = ' ';
|
||||
Buffer[Offset++] = ScreenBuffer->DefaultAttrib;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
if (Size.Y > ScreenBuffer->MaxY)
|
||||
{
|
||||
diff = Size.X * (Size.Y - ScreenBuffer->MaxY);
|
||||
#if HAVE_WMEMSET
|
||||
wmemset((WCHAR*)&Buffer[Offset], value, diff);
|
||||
#else
|
||||
for (i = 0; i < diff; i++)
|
||||
{
|
||||
Buffer[Offset++] = ' ';
|
||||
Buffer[Offset++] = ScreenBuffer->DefaultAttrib;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
(void)InterlockedExchangePointer((PVOID volatile *)&ScreenBuffer->Buffer, Buffer);
|
||||
HeapFree(Win32CsrApiHeap, 0, OldBuffer);
|
||||
ScreenBuffer->MaxX = Size.X;
|
||||
ScreenBuffer->MaxY = Size.Y;
|
||||
ScreenBuffer->VirtualY = 0;
|
||||
|
||||
/* Ensure cursor and window are within buffer */
|
||||
if (ScreenBuffer->CurrentX >= Size.X)
|
||||
ScreenBuffer->CurrentX = Size.X - 1;
|
||||
if (ScreenBuffer->CurrentY >= Size.Y)
|
||||
ScreenBuffer->CurrentY = Size.Y - 1;
|
||||
if (ScreenBuffer->ShowX > Size.X - Console->Size.X)
|
||||
ScreenBuffer->ShowX = Size.X - Console->Size.X;
|
||||
if (ScreenBuffer->ShowY > Size.Y - Console->Size.Y)
|
||||
ScreenBuffer->ShowY = Size.Y - Console->Size.Y;
|
||||
|
||||
/* TODO: Should update scrollbar, but can't use anything that
|
||||
* calls SendMessage or it could cause deadlock */
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static VOID FASTCALL
|
||||
GuiApplyUserSettings(PCSRSS_CONSOLE Console, PGUI_CONSOLE_DATA GuiData, PConsoleInfo pConInfo)
|
||||
{
|
||||
DWORD windx, windy;
|
||||
PCSRSS_SCREEN_BUFFER ActiveBuffer = Console->ActiveBuffer;
|
||||
COORD BufSize;
|
||||
BOOL SizeChanged = FALSE;
|
||||
|
||||
EnterCriticalSection(&ActiveBuffer->Header.Lock);
|
||||
|
@ -1724,85 +1818,6 @@ GuiApplyUserSettings(PCSRSS_CONSOLE Console, PGUI_CONSOLE_DATA GuiData, PConsole
|
|||
/* apply cursor size */
|
||||
ActiveBuffer->CursorInfo.dwSize = min(max(pConInfo->CursorSize, 1), 100);
|
||||
|
||||
windx = LOWORD(pConInfo->ScreenBuffer);
|
||||
windy = HIWORD(pConInfo->ScreenBuffer);
|
||||
|
||||
if (windx != ActiveBuffer->MaxX || windy != ActiveBuffer->MaxY)
|
||||
{
|
||||
BYTE * Buffer = HeapAlloc(Win32CsrApiHeap, 0, windx * windy * 2);
|
||||
|
||||
if (Buffer)
|
||||
{
|
||||
DWORD Offset = 0;
|
||||
BYTE * OldPtr;
|
||||
USHORT CurrentY;
|
||||
BYTE * OldBuffer;
|
||||
USHORT value;
|
||||
DWORD diff;
|
||||
DWORD i;
|
||||
|
||||
value = MAKEWORD(' ', ActiveBuffer->DefaultAttrib);
|
||||
|
||||
DPRINT("MaxX %d MaxY %d windx %d windy %d value %04x DefaultAttrib %d\n",ActiveBuffer->MaxX, ActiveBuffer->MaxY, windx, windy, value, ActiveBuffer->DefaultAttrib);
|
||||
OldBuffer = ActiveBuffer->Buffer;
|
||||
|
||||
for (CurrentY = 0; CurrentY < min(ActiveBuffer->MaxY, windy); CurrentY++)
|
||||
{
|
||||
OldPtr = ConioCoordToPointer(ActiveBuffer, 0, CurrentY);
|
||||
if (windx <= ActiveBuffer->MaxX)
|
||||
{
|
||||
/* reduce size */
|
||||
RtlCopyMemory(&Buffer[Offset], OldPtr, windx * 2);
|
||||
Offset += (windx * 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* enlarge size */
|
||||
RtlCopyMemory(&Buffer[Offset], OldPtr, ActiveBuffer->MaxX * 2);
|
||||
Offset += (ActiveBuffer->MaxX * 2);
|
||||
|
||||
diff = windx - ActiveBuffer->MaxX;
|
||||
/* zero new part of it */
|
||||
#if HAVE_WMEMSET
|
||||
wmemset((WCHAR*)&Buffer[Offset], value, diff);
|
||||
#else
|
||||
for (i = 0; i < diff; i++)
|
||||
{
|
||||
Buffer[Offset++] = ' ';
|
||||
Buffer[Offset++] = ActiveBuffer->DefaultAttrib;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
if (windy > ActiveBuffer->MaxY)
|
||||
{
|
||||
diff = windy - ActiveBuffer->MaxY;
|
||||
#if HAVE_WMEMSET
|
||||
wmemset((WCHAR*)&Buffer[Offset], value, diff * windx);
|
||||
#else
|
||||
for (i = 0; i < diff * windx; i++)
|
||||
{
|
||||
Buffer[Offset++] = ' ';
|
||||
Buffer[Offset++] = ActiveBuffer->DefaultAttrib;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
(void)InterlockedExchangePointer((PVOID volatile *)&ActiveBuffer->Buffer, Buffer);
|
||||
HeapFree(Win32CsrApiHeap, 0, OldBuffer);
|
||||
ActiveBuffer->MaxX = windx;
|
||||
ActiveBuffer->MaxY = windy;
|
||||
ActiveBuffer->VirtualY = 0;
|
||||
SizeChanged = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
LeaveCriticalSection(&ActiveBuffer->Header.Lock);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
windx = LOWORD(pConInfo->WindowSize);
|
||||
windy = HIWORD(pConInfo->WindowSize);
|
||||
|
||||
|
@ -1814,6 +1829,14 @@ GuiApplyUserSettings(PCSRSS_CONSOLE Console, PGUI_CONSOLE_DATA GuiData, PConsole
|
|||
SizeChanged = TRUE;
|
||||
}
|
||||
|
||||
BufSize.X = LOWORD(pConInfo->ScreenBuffer);
|
||||
BufSize.Y = HIWORD(pConInfo->ScreenBuffer);
|
||||
if (BufSize.X != ActiveBuffer->MaxX || BufSize.Y != ActiveBuffer->MaxY)
|
||||
{
|
||||
if (NT_SUCCESS(GuiResizeBuffer(Console, ActiveBuffer, BufSize)))
|
||||
SizeChanged = TRUE;
|
||||
}
|
||||
|
||||
if (SizeChanged)
|
||||
{
|
||||
GuiData->WindowSizeLock = TRUE;
|
||||
|
@ -2222,7 +2245,8 @@ static CSRSS_CONSOLE_VTBL GuiVtbl =
|
|||
GuiUpdateScreenInfo,
|
||||
GuiChangeTitle,
|
||||
GuiCleanupConsole,
|
||||
GuiChangeIcon
|
||||
GuiChangeIcon,
|
||||
GuiResizeBuffer,
|
||||
};
|
||||
|
||||
NTSTATUS FASTCALL
|
||||
|
|
|
@ -290,6 +290,19 @@ TuiCleanupConsole(PCSRSS_CONSOLE Console)
|
|||
}
|
||||
}
|
||||
|
||||
static BOOL WINAPI
|
||||
TuiChangeIcon(PCSRSS_CONSOLE Console, HICON hWindowIcon)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static NTSTATUS WINAPI
|
||||
TuiResizeBuffer(PCSRSS_CONSOLE Console, PCSRSS_SCREEN_BUFFER ScreenBuffer, COORD Size)
|
||||
{
|
||||
UNIMPLEMENTED;
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
DWORD WINAPI
|
||||
TuiConsoleThread (PVOID Data)
|
||||
{
|
||||
|
@ -340,7 +353,8 @@ static CSRSS_CONSOLE_VTBL TuiVtbl =
|
|||
TuiUpdateScreenInfo,
|
||||
TuiChangeTitle,
|
||||
TuiCleanupConsole,
|
||||
NULL // ChangeIcon
|
||||
TuiChangeIcon,
|
||||
TuiResizeBuffer,
|
||||
};
|
||||
|
||||
NTSTATUS FASTCALL
|
||||
|
|
Loading…
Reference in a new issue