From e98f4ce2f0c337884fa8641b649dbf8ccbcfe181 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A9=20van=20Geldorp?= Date: Sun, 11 Jan 2004 17:31:16 +0000 Subject: [PATCH] Auto-detect whether to create a GUI or a TUI console svn path=/trunk/; revision=7571 --- reactos/drivers/dd/blue/blue.c | 547 +-- reactos/drivers/dd/blue/makefile | 5 +- reactos/include/ddk/ntddblue.h | 40 +- reactos/subsys/csrss/api/handle.c | 28 +- reactos/subsys/csrss/api/process.c | 3 +- reactos/subsys/csrss/include/api.h | 75 +- reactos/subsys/csrss/include/conio.h | 105 +- reactos/subsys/csrss/include/desktopbg.h | 4 +- reactos/subsys/csrss/include/win32csr.h | 18 +- reactos/subsys/csrss/win32csr/Makefile | 4 +- reactos/subsys/csrss/win32csr/conio.c | 4046 +++++++++----------- reactos/subsys/csrss/win32csr/desktopbg.c | 33 +- reactos/subsys/csrss/win32csr/dllmain.c | 38 +- reactos/subsys/csrss/win32csr/guiconsole.c | 292 +- reactos/subsys/csrss/win32csr/guiconsole.h | 6 +- reactos/subsys/csrss/win32csr/tuiconsole.c | 346 ++ reactos/subsys/csrss/win32csr/tuiconsole.h | 15 + 17 files changed, 2977 insertions(+), 2628 deletions(-) create mode 100644 reactos/subsys/csrss/win32csr/tuiconsole.c create mode 100644 reactos/subsys/csrss/win32csr/tuiconsole.h diff --git a/reactos/drivers/dd/blue/blue.c b/reactos/drivers/dd/blue/blue.c index b49473771ec..06d66ffd5fe 100644 --- a/reactos/drivers/dd/blue/blue.c +++ b/reactos/drivers/dd/blue/blue.c @@ -1,4 +1,4 @@ -/* $Id: blue.c,v 1.41 2003/11/17 02:12:48 hyperion Exp $ +/* $Id: blue.c,v 1.42 2004/01/11 17:31:14 gvg Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -302,290 +302,327 @@ NTSTATUS STDCALL ScrIoControl(PDEVICE_OBJECT DeviceObject, PIRP Irp) { - PIO_STACK_LOCATION stk = IoGetCurrentIrpStackLocation (Irp); - PDEVICE_EXTENSION DeviceExtension; - NTSTATUS Status; - DeviceExtension = DeviceObject->DeviceExtension; - switch (stk->Parameters.DeviceIoControl.IoControlCode) + PIO_STACK_LOCATION stk = IoGetCurrentIrpStackLocation (Irp); + PDEVICE_EXTENSION DeviceExtension; + NTSTATUS Status; + + DeviceExtension = DeviceObject->DeviceExtension; + switch (stk->Parameters.DeviceIoControl.IoControlCode) { - case IOCTL_CONSOLE_GET_SCREEN_BUFFER_INFO: + case IOCTL_CONSOLE_GET_SCREEN_BUFFER_INFO: + { + PCONSOLE_SCREEN_BUFFER_INFO pcsbi = (PCONSOLE_SCREEN_BUFFER_INFO)Irp->AssociatedIrp.SystemBuffer; + int rows = DeviceExtension->Rows; + int columns = DeviceExtension->Columns; + unsigned int offset; + + /* read cursor position from crtc */ + __asm__("cli\n\t"); + WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_CURSORPOSLO); + offset = READ_PORT_UCHAR (CRTC_DATA); + WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_CURSORPOSHI); + offset += (READ_PORT_UCHAR (CRTC_DATA) << 8); + __asm__("sti\n\t"); + + pcsbi->dwSize.X = columns; + pcsbi->dwSize.Y = rows; + + pcsbi->dwCursorPosition.X = (SHORT)(offset % columns); + pcsbi->dwCursorPosition.Y = (SHORT)(offset / columns); + + pcsbi->wAttributes = DeviceExtension->CharAttribute; + + pcsbi->srWindow.Left = 0; + pcsbi->srWindow.Right = columns - 1; + pcsbi->srWindow.Top = 0; + pcsbi->srWindow.Bottom = rows - 1; + + pcsbi->dwMaximumWindowSize.X = columns; + pcsbi->dwMaximumWindowSize.Y = rows; + + Irp->IoStatus.Information = sizeof (CONSOLE_SCREEN_BUFFER_INFO); + Status = STATUS_SUCCESS; + } + break; + + case IOCTL_CONSOLE_SET_SCREEN_BUFFER_INFO: + { + PCONSOLE_SCREEN_BUFFER_INFO pcsbi = (PCONSOLE_SCREEN_BUFFER_INFO)Irp->AssociatedIrp.SystemBuffer; + unsigned int offset; + + DeviceExtension->CharAttribute = pcsbi->wAttributes; + offset = (pcsbi->dwCursorPosition.Y * DeviceExtension->Columns) + + pcsbi->dwCursorPosition.X; + + __asm__("cli\n\t"); + WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_CURSORPOSLO); + WRITE_PORT_UCHAR (CRTC_DATA, offset); + WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_CURSORPOSHI); + WRITE_PORT_UCHAR (CRTC_DATA, offset>>8); + __asm__("sti\n\t"); + + Irp->IoStatus.Information = 0; + Status = STATUS_SUCCESS; + } + break; + + case IOCTL_CONSOLE_GET_CURSOR_INFO: + { + PCONSOLE_CURSOR_INFO pcci = (PCONSOLE_CURSOR_INFO)Irp->AssociatedIrp.SystemBuffer; + + pcci->dwSize = DeviceExtension->CursorSize; + pcci->bVisible = DeviceExtension->CursorVisible; + + Irp->IoStatus.Information = sizeof (CONSOLE_CURSOR_INFO); + Status = STATUS_SUCCESS; + } + break; + + case IOCTL_CONSOLE_SET_CURSOR_INFO: + { + PCONSOLE_CURSOR_INFO pcci = (PCONSOLE_CURSOR_INFO)Irp->AssociatedIrp.SystemBuffer; + BYTE data, value; + DWORD size, height; + + DeviceExtension->CursorSize = pcci->dwSize; + DeviceExtension->CursorVisible = pcci->bVisible; + height = DeviceExtension->ScanLines; + data = (pcci->bVisible) ? 0x00 : 0x20; + + size = (pcci->dwSize * height) / 100; + if (size < 1) { - PCONSOLE_SCREEN_BUFFER_INFO pcsbi = (PCONSOLE_SCREEN_BUFFER_INFO)Irp->AssociatedIrp.SystemBuffer; - int rows = DeviceExtension->Rows; - int columns = DeviceExtension->Columns; - unsigned int offset; - - /* read cursor position from crtc */ - __asm__("cli\n\t"); - WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_CURSORPOSLO); - offset = READ_PORT_UCHAR (CRTC_DATA); - WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_CURSORPOSHI); - offset += (READ_PORT_UCHAR (CRTC_DATA) << 8); - __asm__("sti\n\t"); - - pcsbi->dwSize.X = columns; - pcsbi->dwSize.Y = rows; - - pcsbi->dwCursorPosition.X = (SHORT)(offset % columns); - pcsbi->dwCursorPosition.Y = (SHORT)(offset / columns); - - pcsbi->wAttributes = DeviceExtension->CharAttribute; - - pcsbi->srWindow.Left = 0; - pcsbi->srWindow.Right = columns - 1; - pcsbi->srWindow.Top = 0; - pcsbi->srWindow.Bottom = rows - 1; - - pcsbi->dwMaximumWindowSize.X = columns; - pcsbi->dwMaximumWindowSize.Y = rows; - - Irp->IoStatus.Information = sizeof (CONSOLE_SCREEN_BUFFER_INFO); - Status = STATUS_SUCCESS; + size = 1; } - break; - case IOCTL_CONSOLE_SET_SCREEN_BUFFER_INFO: + data |= (BYTE)(height - size); + + __asm__("cli\n\t"); + WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_CURSORSTART); + WRITE_PORT_UCHAR (CRTC_DATA, data); + WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_CURSOREND); + value = READ_PORT_UCHAR (CRTC_DATA) & 0xE0; + WRITE_PORT_UCHAR (CRTC_DATA, value | (height - 1)); + + __asm__("sti\n\t"); + + Irp->IoStatus.Information = 0; + Status = STATUS_SUCCESS; + } + break; + + case IOCTL_CONSOLE_GET_MODE: + { + PCONSOLE_MODE pcm = (PCONSOLE_MODE)Irp->AssociatedIrp.SystemBuffer; + + pcm->dwMode = DeviceExtension->Mode; + + Irp->IoStatus.Information = sizeof(CONSOLE_MODE); + Status = STATUS_SUCCESS; + } + break; + + case IOCTL_CONSOLE_SET_MODE: + { + PCONSOLE_MODE pcm = (PCONSOLE_MODE)Irp->AssociatedIrp.SystemBuffer; + + DeviceExtension->Mode = pcm->dwMode; + + Irp->IoStatus.Information = 0; + Status = STATUS_SUCCESS; + } + break; + + case IOCTL_CONSOLE_FILL_OUTPUT_ATTRIBUTE: + { + POUTPUT_ATTRIBUTE Buf = (POUTPUT_ATTRIBUTE)Irp->AssociatedIrp.SystemBuffer; + char *vidmem; + int offset; + DWORD dwCount; + + vidmem = DeviceExtension->VideoMemory; + offset = (Buf->dwCoord.Y * DeviceExtension->Columns * 2) + + (Buf->dwCoord.X * 2) + 1; + + for (dwCount = 0; dwCount < Buf->nLength; dwCount++) { - PCONSOLE_SCREEN_BUFFER_INFO pcsbi = (PCONSOLE_SCREEN_BUFFER_INFO)Irp->AssociatedIrp.SystemBuffer; - unsigned int offset; - - DeviceExtension->CharAttribute = pcsbi->wAttributes; - offset = (pcsbi->dwCursorPosition.Y * DeviceExtension->Columns) + - pcsbi->dwCursorPosition.X; - - __asm__("cli\n\t"); - WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_CURSORPOSLO); - WRITE_PORT_UCHAR (CRTC_DATA, offset); - WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_CURSORPOSHI); - WRITE_PORT_UCHAR (CRTC_DATA, offset>>8); - __asm__("sti\n\t"); - - Irp->IoStatus.Information = 0; - Status = STATUS_SUCCESS; + vidmem[offset + (dwCount * 2)] = (char) Buf->wAttribute; } - break; - case IOCTL_CONSOLE_GET_CURSOR_INFO: - { - PCONSOLE_CURSOR_INFO pcci = (PCONSOLE_CURSOR_INFO)Irp->AssociatedIrp.SystemBuffer; - - pcci->dwSize = DeviceExtension->CursorSize; - pcci->bVisible = DeviceExtension->CursorVisible; - - Irp->IoStatus.Information = sizeof (CONSOLE_CURSOR_INFO); - Status = STATUS_SUCCESS; - } - break; - - case IOCTL_CONSOLE_SET_CURSOR_INFO: - { - PCONSOLE_CURSOR_INFO pcci = (PCONSOLE_CURSOR_INFO)Irp->AssociatedIrp.SystemBuffer; - BYTE data, value; - DWORD size, height; - - DeviceExtension->CursorSize = pcci->dwSize; - DeviceExtension->CursorVisible = pcci->bVisible; - height = DeviceExtension->ScanLines; - data = (pcci->bVisible) ? 0x40 : 0x20; - - size = (pcci->dwSize * height) / 100; - if (size < 1) - size = 1; - - data |= (BYTE)(height - size); - - __asm__("cli\n\t"); - WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_CURSORSTART); - WRITE_PORT_UCHAR (CRTC_DATA, data); - WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_CURSOREND); - value = READ_PORT_UCHAR (CRTC_DATA) & 0xE0; - WRITE_PORT_UCHAR (CRTC_DATA, value | (height - 1)); - - __asm__("sti\n\t"); - - Irp->IoStatus.Information = 0; - Status = STATUS_SUCCESS; - } - break; - - case IOCTL_CONSOLE_GET_MODE: - { - PCONSOLE_MODE pcm = (PCONSOLE_MODE)Irp->AssociatedIrp.SystemBuffer; - - pcm->dwMode = DeviceExtension->Mode; - - Irp->IoStatus.Information = sizeof(CONSOLE_MODE); - Status = STATUS_SUCCESS; - } - break; - - case IOCTL_CONSOLE_SET_MODE: - { - PCONSOLE_MODE pcm = (PCONSOLE_MODE)Irp->AssociatedIrp.SystemBuffer; - - DeviceExtension->Mode = pcm->dwMode; - - Irp->IoStatus.Information = 0; - Status = STATUS_SUCCESS; - } - break; - - case IOCTL_CONSOLE_FILL_OUTPUT_ATTRIBUTE: - { - POUTPUT_ATTRIBUTE Buf = (POUTPUT_ATTRIBUTE)Irp->AssociatedIrp.SystemBuffer; - char *vidmem; - int offset; - DWORD dwCount; - - vidmem = DeviceExtension->VideoMemory; - offset = (Buf->dwCoord.Y * DeviceExtension->Columns * 2) + - (Buf->dwCoord.X * 2) + 1; - - for (dwCount = 0; dwCount < Buf->nLength; dwCount++) - { - vidmem[offset + (dwCount * 2)] = (char) Buf->wAttribute; - } - - Buf->dwTransfered = Buf->nLength; + Buf->dwTransfered = Buf->nLength; - Irp->IoStatus.Information = 0; - Status = STATUS_SUCCESS; - } - break; + Irp->IoStatus.Information = 0; + Status = STATUS_SUCCESS; + } + break; - case IOCTL_CONSOLE_READ_OUTPUT_ATTRIBUTE: + case IOCTL_CONSOLE_READ_OUTPUT_ATTRIBUTE: + { + POUTPUT_ATTRIBUTE Buf = (POUTPUT_ATTRIBUTE)Irp->AssociatedIrp.SystemBuffer; + PWORD pAttr = (PWORD)MmGetSystemAddressForMdl(Irp->MdlAddress); + char *vidmem; + int offset; + DWORD dwCount; + + vidmem = DeviceExtension->VideoMemory; + offset = (Buf->dwCoord.Y * DeviceExtension->Columns * 2) + + (Buf->dwCoord.X * 2) + 1; + + for (dwCount = 0; dwCount < stk->Parameters.DeviceIoControl.OutputBufferLength; dwCount++, pAttr++) { - POUTPUT_ATTRIBUTE Buf = (POUTPUT_ATTRIBUTE)Irp->AssociatedIrp.SystemBuffer; - PWORD pAttr = (PWORD)MmGetSystemAddressForMdl(Irp->MdlAddress); - char *vidmem; - int offset; - DWORD dwCount; - - vidmem = DeviceExtension->VideoMemory; - offset = (Buf->dwCoord.Y * DeviceExtension->Columns * 2) + - (Buf->dwCoord.X * 2) + 1; - - for (dwCount = 0; dwCount < stk->Parameters.DeviceIoControl.OutputBufferLength; dwCount++, pAttr++) - { - (char) *pAttr = vidmem[offset + (dwCount * 2)]; - } - - Buf->dwTransfered = dwCount; - - Irp->IoStatus.Information = sizeof(OUTPUT_ATTRIBUTE); - Status = STATUS_SUCCESS; + (char) *pAttr = vidmem[offset + (dwCount * 2)]; } - break; - case IOCTL_CONSOLE_WRITE_OUTPUT_ATTRIBUTE: + Buf->dwTransfered = dwCount; + + Irp->IoStatus.Information = sizeof(OUTPUT_ATTRIBUTE); + Status = STATUS_SUCCESS; + } + break; + + case IOCTL_CONSOLE_WRITE_OUTPUT_ATTRIBUTE: + { + COORD *pCoord = (COORD *)MmGetSystemAddressForMdl(Irp->MdlAddress); + CHAR *pAttr = (CHAR *)(pCoord + 1); + char *vidmem; + int offset; + DWORD dwCount; + + vidmem = DeviceExtension->VideoMemory; + offset = (pCoord->Y * DeviceExtension->Columns * 2) + + (pCoord->X * 2) + 1; + + for (dwCount = 0; dwCount < (stk->Parameters.DeviceIoControl.InputBufferLength - sizeof( COORD )); dwCount++, pAttr++) { - COORD *pCoord = (COORD *)MmGetSystemAddressForMdl(Irp->MdlAddress); - CHAR *pAttr = (CHAR *)(pCoord + 1); - char *vidmem; - int offset; - DWORD dwCount; - - vidmem = DeviceExtension->VideoMemory; - offset = (pCoord->Y * DeviceExtension->Columns * 2) + - (pCoord->X * 2) + 1; - - for (dwCount = 0; dwCount < (stk->Parameters.DeviceIoControl.InputBufferLength - sizeof( COORD )); dwCount++, pAttr++) - { - vidmem[offset + (dwCount * 2)] = *pAttr; - } - Irp->IoStatus.Information = 0; - Status = STATUS_SUCCESS; + vidmem[offset + (dwCount * 2)] = *pAttr; } - break; + Irp->IoStatus.Information = 0; + Status = STATUS_SUCCESS; + } + break; - case IOCTL_CONSOLE_SET_TEXT_ATTRIBUTE: - DeviceExtension->CharAttribute = (WORD)*(PWORD)Irp->AssociatedIrp.SystemBuffer; - Irp->IoStatus.Information = 0; - Status = STATUS_SUCCESS; - break; + case IOCTL_CONSOLE_SET_TEXT_ATTRIBUTE: + DeviceExtension->CharAttribute = (WORD)*(PWORD)Irp->AssociatedIrp.SystemBuffer; + Irp->IoStatus.Information = 0; + Status = STATUS_SUCCESS; + break; + case IOCTL_CONSOLE_FILL_OUTPUT_CHARACTER: + { + POUTPUT_CHARACTER Buf = (POUTPUT_CHARACTER)Irp->AssociatedIrp.SystemBuffer; + char *vidmem; + int offset; + DWORD dwCount; - case IOCTL_CONSOLE_FILL_OUTPUT_CHARACTER: + vidmem = DeviceExtension->VideoMemory; + offset = (Buf->dwCoord.Y * DeviceExtension->Columns * 2) + + (Buf->dwCoord.X * 2); + + CHECKPOINT + + for (dwCount = 0; dwCount < Buf->nLength; dwCount++) { - POUTPUT_CHARACTER Buf = (POUTPUT_CHARACTER)Irp->AssociatedIrp.SystemBuffer; - char *vidmem; - int offset; - DWORD dwCount; - - vidmem = DeviceExtension->VideoMemory; - offset = (Buf->dwCoord.Y * DeviceExtension->Columns * 2) + - (Buf->dwCoord.X * 2); - - CHECKPOINT - - for (dwCount = 0; dwCount < Buf->nLength; dwCount++) - { - vidmem[offset + (dwCount * 2)] = (char) Buf->cCharacter; - } - - Buf->dwTransfered = Buf->nLength; - - Irp->IoStatus.Information = 0; - Status = STATUS_SUCCESS; + vidmem[offset + (dwCount * 2)] = (char) Buf->cCharacter; } - break; - case IOCTL_CONSOLE_READ_OUTPUT_CHARACTER: + Buf->dwTransfered = Buf->nLength; + + Irp->IoStatus.Information = 0; + Status = STATUS_SUCCESS; + } + break; + + case IOCTL_CONSOLE_READ_OUTPUT_CHARACTER: + { + POUTPUT_CHARACTER Buf = (POUTPUT_CHARACTER)Irp->AssociatedIrp.SystemBuffer; + LPSTR pChar = (LPSTR)MmGetSystemAddressForMdl(Irp->MdlAddress); + char *vidmem; + int offset; + DWORD dwCount; + + vidmem = DeviceExtension->VideoMemory; + offset = (Buf->dwCoord.Y * DeviceExtension->Columns * 2) + + (Buf->dwCoord.X * 2); + + for (dwCount = 0; dwCount < stk->Parameters.DeviceIoControl.OutputBufferLength; dwCount++, pChar++) { - POUTPUT_CHARACTER Buf = (POUTPUT_CHARACTER)Irp->AssociatedIrp.SystemBuffer; - LPSTR pChar = (LPSTR)MmGetSystemAddressForMdl(Irp->MdlAddress); - char *vidmem; - int offset; - DWORD dwCount; - - vidmem = DeviceExtension->VideoMemory; - offset = (Buf->dwCoord.Y * DeviceExtension->Columns * 2) + - (Buf->dwCoord.X * 2); - - for (dwCount = 0; dwCount < stk->Parameters.DeviceIoControl.OutputBufferLength; dwCount++, pChar++) - { - *pChar = vidmem[offset + (dwCount * 2)]; - } - - Buf->dwTransfered = dwCount; - - Irp->IoStatus.Information = sizeof(OUTPUT_ATTRIBUTE); - Status = STATUS_SUCCESS; + *pChar = vidmem[offset + (dwCount * 2)]; } - break; - case IOCTL_CONSOLE_WRITE_OUTPUT_CHARACTER: + Buf->dwTransfered = dwCount; + + Irp->IoStatus.Information = sizeof(OUTPUT_ATTRIBUTE); + Status = STATUS_SUCCESS; + } + break; + + case IOCTL_CONSOLE_WRITE_OUTPUT_CHARACTER: + { + COORD *pCoord; + LPSTR pChar; + char *vidmem; + int offset; + DWORD dwCount; + + pCoord = (COORD *)MmGetSystemAddressForMdl(Irp->MdlAddress); + pChar = (CHAR *)(pCoord + 1); + vidmem = DeviceExtension->VideoMemory; + offset = (pCoord->Y * DeviceExtension->Columns * 2) + + (pCoord->X * 2); + + for (dwCount = 0; dwCount < (stk->Parameters.DeviceIoControl.InputBufferLength - sizeof( COORD )); dwCount++, pChar++) { - COORD *pCoord; - LPSTR pChar; - char *vidmem; - int offset; - DWORD dwCount; - pCoord = (COORD *)MmGetSystemAddressForMdl(Irp->MdlAddress); - pChar = (CHAR *)(pCoord + 1); - vidmem = DeviceExtension->VideoMemory; - offset = (pCoord->Y * DeviceExtension->Columns * 2) + - (pCoord->X * 2); - - for (dwCount = 0; dwCount < (stk->Parameters.DeviceIoControl.InputBufferLength - sizeof( COORD )); dwCount++, pChar++) - { - vidmem[offset + (dwCount * 2)] = *pChar; - } - - Irp->IoStatus.Information = 0; - Status = STATUS_SUCCESS; + vidmem[offset + (dwCount * 2)] = *pChar; } - break; + Irp->IoStatus.Information = 0; + Status = STATUS_SUCCESS; + } + break; - default: - Status = STATUS_NOT_IMPLEMENTED; + case IOCTL_CONSOLE_DRAW: + { + PCONSOLE_DRAW ConsoleDraw; + char *Src, *Dest; + UINT SrcDelta, DestDelta, i, Offset; + + ConsoleDraw = (PCONSOLE_DRAW) MmGetSystemAddressForMdl(Irp->MdlAddress); + Src = (char *) (ConsoleDraw + 1); + SrcDelta = ConsoleDraw->SizeX * 2; + Dest = DeviceExtension->VideoMemory + + (ConsoleDraw->Y * DeviceExtension->Columns + ConsoleDraw->X) * 2; + DestDelta = DeviceExtension->Columns * 2; + + for (i = 0; i < ConsoleDraw->SizeY; i++) + { + RtlCopyMemory(Dest, Src, SrcDelta); + Src += SrcDelta; + Dest += DestDelta; + } + + Offset = (ConsoleDraw->CursorY * DeviceExtension->Columns) + + ConsoleDraw->CursorX; + + __asm__("cli\n\t"); + WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_CURSORPOSLO); + WRITE_PORT_UCHAR (CRTC_DATA, Offset); + WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_CURSORPOSHI); + WRITE_PORT_UCHAR (CRTC_DATA, Offset >> 8); + __asm__("sti\n\t"); + + Irp->IoStatus.Information = 0; + Status = STATUS_SUCCESS; + } + break; + + default: + Status = STATUS_NOT_IMPLEMENTED; } - Irp->IoStatus.Status = Status; - IoCompleteRequest (Irp, IO_NO_INCREMENT); + Irp->IoStatus.Status = Status; + IoCompleteRequest (Irp, IO_NO_INCREMENT); - return (Status); + return Status; } diff --git a/reactos/drivers/dd/blue/makefile b/reactos/drivers/dd/blue/makefile index 55f72a7cbbf..a02b408edb5 100644 --- a/reactos/drivers/dd/blue/makefile +++ b/reactos/drivers/dd/blue/makefile @@ -1,4 +1,4 @@ -# $Id: makefile,v 1.21 2003/11/13 14:20:53 ekohl Exp $ +# $Id: makefile,v 1.22 2004/01/11 17:31:14 gvg Exp $ PATH_TO_TOP = ../../.. @@ -15,3 +15,6 @@ TARGET_CFLAGS = -Wall -Werror include $(PATH_TO_TOP)/rules.mak include $(TOOLS_PATH)/helper.mk + +DEP_OBJECTS := $(TARGET_OBJECTS) +include $(PATH_TO_TOP)/tools/depend.mk diff --git a/reactos/include/ddk/ntddblue.h b/reactos/include/ddk/ntddblue.h index 818a989297d..582d63100e8 100644 --- a/reactos/include/ddk/ntddblue.h +++ b/reactos/include/ddk/ntddblue.h @@ -21,43 +21,45 @@ #define IOCTL_CONSOLE_READ_OUTPUT_CHARACTER CTL_CODE(FILE_DEVICE_SCREEN, 0x821, METHOD_OUT_DIRECT, FILE_ANY_ACCESS) #define IOCTL_CONSOLE_WRITE_OUTPUT_CHARACTER CTL_CODE(FILE_DEVICE_SCREEN, 0x822, METHOD_IN_DIRECT, FILE_ANY_ACCESS) - -#define IOCTL_CONSOLE_DRAW CTL_CODE(FILE_DEVICE_SCREEN, 0x830, METHOD_IN_DIRECT, FILE_ANY_ACCESS) +#define IOCTL_CONSOLE_DRAW CTL_CODE(FILE_DEVICE_SCREEN, 0x830, METHOD_IN_DIRECT, FILE_WRITE_ACCESS) /* TYPEDEFS **************************************************************/ -typedef struct _CONSOLE_MODE +typedef struct tagCONSOLE_MODE { - DWORD dwMode; + DWORD dwMode; } CONSOLE_MODE, *PCONSOLE_MODE; -typedef struct _OUTPUT_ATTRIBUTE +typedef struct tagOUTPUT_ATTRIBUTE { - WORD wAttribute; - DWORD nLength; - COORD dwCoord; - DWORD dwTransfered; + WORD wAttribute; + DWORD nLength; + COORD dwCoord; + DWORD dwTransfered; } OUTPUT_ATTRIBUTE, *POUTPUT_ATTRIBUTE; -typedef struct _OUTPUT_CHARACTER +typedef struct tagOUTPUT_CHARACTER { - CHAR cCharacter; - DWORD nLength; - COORD dwCoord; - DWORD dwTransfered; + CHAR cCharacter; + DWORD nLength; + COORD dwCoord; + DWORD dwTransfered; } OUTPUT_CHARACTER, *POUTPUT_CHARACTER; -typedef struct _CONSOLE_DRAW +typedef struct tagCONSOLE_DRAW { - SHORT X; /* Origin */ - SHORT Y; - SHORT SizeX; /* Size of the screen buffer */ - SHORT SizeY; + UINT X; /* Origin */ + UINT Y; + UINT SizeX; /* Size of the screen buffer (chars) */ + UINT SizeY; + UINT CursorX; /* New cursor position (screen-relative) */ + UINT CursorY; + /* Followed by screen buffer in char/attrib format */ } CONSOLE_DRAW, *PCONSOLE_DRAW; diff --git a/reactos/subsys/csrss/api/handle.c b/reactos/subsys/csrss/api/handle.c index 43c7fc5648b..ebc61c02e6a 100644 --- a/reactos/subsys/csrss/api/handle.c +++ b/reactos/subsys/csrss/api/handle.c @@ -1,4 +1,4 @@ -/* $Id: handle.c,v 1.15 2003/12/02 11:38:47 gvg Exp $ +/* $Id: handle.c,v 1.16 2004/01/11 17:31:15 gvg Exp $ * * reactos/subsys/csrss/api/handle.c * @@ -60,21 +60,21 @@ CsrRegisterObjectDefinitions(PCSRSS_OBJECT_DEFINITION NewDefinitions) NTSTATUS STDCALL CsrGetObject( PCSRSS_PROCESS_DATA ProcessData, HANDLE Handle, Object_t **Object ) { - ULONG h = (((ULONG)Handle) >> 2) - 1; - DPRINT("CsrGetObject, Object: %x, %x, %x\n", Object, Handle, ProcessData ? ProcessData->HandleTableSize : 0); + ULONG h = (((ULONG)Handle) >> 2) - 1; + DPRINT("CsrGetObject, Object: %x, %x, %x\n", Object, Handle, ProcessData ? ProcessData->HandleTableSize : 0); - if (ProcessData == NULL) - { + if (ProcessData == NULL) + { return STATUS_INVALID_PARAMETER; - } - if( h >= ProcessData->HandleTableSize ) - { - DPRINT("CsrGetObject returning invalid handle\n"); - return STATUS_INVALID_HANDLE; - } - *Object = ProcessData->HandleTable[h]; - // DbgPrint( "CsrGetObject returning\n" ); - return *Object ? STATUS_SUCCESS : STATUS_INVALID_HANDLE; + } + if (ProcessData->HandleTableSize <= h) + { + DPRINT1("CsrGetObject returning invalid handle\n"); + return STATUS_INVALID_HANDLE; + } + *Object = ProcessData->HandleTable[h]; + // DbgPrint( "CsrGetObject returning\n" ); + return *Object ? STATUS_SUCCESS : STATUS_INVALID_HANDLE; } diff --git a/reactos/subsys/csrss/api/process.c b/reactos/subsys/csrss/api/process.c index d15c42bcc42..ef36f194bf8 100644 --- a/reactos/subsys/csrss/api/process.c +++ b/reactos/subsys/csrss/api/process.c @@ -1,4 +1,4 @@ -/* $Id: process.c,v 1.31 2003/12/18 09:51:08 gvg Exp $ +/* $Id: process.c,v 1.32 2004/01/11 17:31:15 gvg Exp $ * * reactos/subsys/csrss/api/process.c * @@ -14,6 +14,7 @@ #include #include #include "api.h" +#include "conio.h" #define NDEBUG #include diff --git a/reactos/subsys/csrss/include/api.h b/reactos/subsys/csrss/include/api.h index 8b359055f09..7358c39dd3b 100644 --- a/reactos/subsys/csrss/include/api.h +++ b/reactos/subsys/csrss/include/api.h @@ -1,4 +1,4 @@ -/* $Id: api.h,v 1.3 2003/12/02 11:38:46 gvg Exp $ +/* $Id: api.h,v 1.4 2004/01/11 17:31:15 gvg Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS system libraries @@ -15,8 +15,9 @@ typedef struct Object_tt { - LONG Type; - LONG ReferenceCount; + LONG Type; + LONG ReferenceCount; + CRITICAL_SECTION Lock; } Object_t; typedef struct ConsoleInput_t @@ -28,63 +29,7 @@ typedef struct ConsoleInput_t BOOLEAN NotChar; // message should not be used to return a character } ConsoleInput; -typedef struct CSRSS_CONSOLE_t *PCSRSS_CONSOLE; - -/************************************************************************ - * Screen buffer structure represents the win32 screen buffer object. * - * Internally, the portion of the buffer being shown CAN loop past the * - * bottom of the virtual buffer and wrap around to the top. Win32 does * - * not do this. I decided to do this because it eliminates the need to * - * do a massive memcpy() to scroll the contents of the buffer up to * - * scroll the screen on output, instead I just shift down the position * - * to be displayed, and let it wrap around to the top again. * - * The VirtualX member keeps track of the top X coord that win32 * - * clients THINK is currently being displayed, because they think that * - * when the display reaches the bottom of the buffer and another line * - * being printed causes another line to scroll down, that the buffer IS * - * memcpy()'s up, and the bottom of the buffer is still displayed, but * - * internally, I just wrap back to the top of the buffer. * - ***********************************************************************/ - -typedef struct CSRSS_SCREEN_BUFFER_t -{ - Object_t Header; /* Object header */ - BYTE *Buffer; /* pointer to screen buffer */ - USHORT MaxX, MaxY; /* size of the entire scrollback buffer */ - USHORT ShowX, ShowY; /* beginning offset for the actual display area */ - ULONG CurrentX; /* Current X cursor position */ - ULONG CurrentY; /* Current Y cursor position */ - BYTE DefaultAttrib; /* default char attribute */ - USHORT VirtualX; /* top row of buffer being displayed, reported to callers */ - CONSOLE_CURSOR_INFO CursorInfo; - USHORT Mode; - PCSRSS_CONSOLE Console; /* Console this buffer is currently attached to */ - CRITICAL_SECTION Lock; -} CSRSS_SCREEN_BUFFER, *PCSRSS_SCREEN_BUFFER; - -typedef struct CSRSS_CONSOLE_t -{ - Object_t Header; /* Object header */ - struct CSRSS_CONSOLE_t *Prev, *Next; /* Next and Prev consoles in console wheel */ - HANDLE ActiveEvent; - LIST_ENTRY InputEvents; /* List head for input event queue */ - WORD WaitingChars; - WORD WaitingLines; /* number of chars and lines in input queue */ - PCSRSS_SCREEN_BUFFER ActiveBuffer; /* Pointer to currently active screen buffer */ - WORD Mode; /* Console mode flags */ - WORD EchoCount; /* count of chars to echo, in line buffered mode */ - UNICODE_STRING Title; /* Title of console */ - struct { /* active code pages */ - UINT Input; - UINT Output; - } CodePageId; - BOOL EarlyReturn; /* wake client and return data, even if we are in line buffered mode, and we don't have a complete line */ - DWORD HardwareState; /* _GDI_MANAGED, _DIRECT */ - HWND hWindow; - COORD Size; - PVOID GuiConsoleData; - LIST_ENTRY ProcessList; -} CSRSS_CONSOLE; +typedef struct tagCSRSS_CONSOLE *PCSRSS_CONSOLE; typedef struct _CSRSS_PROCESS_DATA { @@ -157,11 +102,6 @@ VOID Console_Api( DWORD Ignored ); extern HANDLE CsrssApiHeap; /* api/conio.c */ -NTSTATUS STDCALL CsrInitConsole(PCSRSS_CONSOLE Console); -NTSTATUS STDCALL CsrInitConsoleScreenBuffer(PCSRSS_SCREEN_BUFFER Buffer, - PCSRSS_CONSOLE Console, - unsigned Width, - unsigned Height); VOID STDCALL CsrInitConsoleSupport(VOID); /* api/process.c */ @@ -177,10 +117,7 @@ BOOL STDCALL CsrServerInitialization (ULONG ArgumentCount, PWSTR *ArgumentArray) NTSTATUS STDCALL CsrReleaseObjectByPointer(Object_t *Object); NTSTATUS STDCALL CsrReleaseObject( PCSRSS_PROCESS_DATA ProcessData, HANDLE Object ); NTSTATUS STDCALL CsrVerifyObject( PCSRSS_PROCESS_DATA ProcessData, HANDLE Object ); -VOID STDCALL CsrDrawConsole(PCSRSS_CONSOLE Console); -NTSTATUS CsrpEchoUnicodeChar( PCSRSS_SCREEN_BUFFER Console, - WCHAR UnicodeChar ); -NTSTATUS STDCALL CsrpWriteConsole( PCSRSS_SCREEN_BUFFER Buff, CHAR *Buffer, DWORD Length, BOOL Attrib ); + CSR_API(CsrGetInputHandle); CSR_API(CsrGetOutputHandle); CSR_API(CsrCloseHandle); diff --git a/reactos/subsys/csrss/include/conio.h b/reactos/subsys/csrss/include/conio.h index a0ab381eeab..d4466ba948a 100644 --- a/reactos/subsys/csrss/include/conio.h +++ b/reactos/subsys/csrss/include/conio.h @@ -1,4 +1,4 @@ -/* $Id: conio.h,v 1.1 2003/12/02 11:38:46 gvg Exp $ +/* $Id: conio.h,v 1.2 2004/01/11 17:31:15 gvg Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS system libraries @@ -10,15 +10,91 @@ #define CONIO_H_INCLUDED #include "api.h" +#include "win32csr.h" /* Object type magic numbers */ #define CONIO_CONSOLE_MAGIC 0x00000001 #define CONIO_SCREEN_BUFFER_MAGIC 0x00000002 +/************************************************************************ + * Screen buffer structure represents the win32 screen buffer object. * + * Internally, the portion of the buffer being shown CAN loop past the * + * bottom of the virtual buffer and wrap around to the top. Win32 does * + * not do this. I decided to do this because it eliminates the need to * + * do a massive memcpy() to scroll the contents of the buffer up to * + * scroll the screen on output, instead I just shift down the position * + * to be displayed, and let it wrap around to the top again. * + * The VirtualX member keeps track of the top X coord that win32 * + * clients THINK is currently being displayed, because they think that * + * when the display reaches the bottom of the buffer and another line * + * being printed causes another line to scroll down, that the buffer IS * + * memcpy()'s up, and the bottom of the buffer is still displayed, but * + * internally, I just wrap back to the top of the buffer. * + ***********************************************************************/ + +typedef struct tagCSRSS_SCREEN_BUFFER +{ + Object_t Header; /* Object header */ + BYTE *Buffer; /* pointer to screen buffer */ + USHORT MaxX, MaxY; /* size of the entire scrollback buffer */ + USHORT ShowX, ShowY; /* beginning offset for the actual display area */ + ULONG CurrentX; /* Current X cursor position */ + ULONG CurrentY; /* Current Y cursor position */ + BYTE DefaultAttrib; /* default char attribute */ + USHORT VirtualX; /* top row of buffer being displayed, reported to callers */ + CONSOLE_CURSOR_INFO CursorInfo; + USHORT Mode; +} CSRSS_SCREEN_BUFFER, *PCSRSS_SCREEN_BUFFER; + +typedef struct tagCSRSS_CONSOLE_VTBL +{ + VOID (STDCALL *InitScreenBuffer)(PCSRSS_CONSOLE Console, PCSRSS_SCREEN_BUFFER ScreenBuffer); + VOID (STDCALL *WriteStream)(PCSRSS_CONSOLE Console, RECT *Block, UINT CursorStartX, UINT CursorStartY, + UINT ScrolledLines, CHAR *Buffer, UINT Length); + VOID (STDCALL *DrawRegion)(PCSRSS_CONSOLE Console, RECT *Region); + BOOL (STDCALL *SetCursorInfo)(PCSRSS_CONSOLE Console, PCSRSS_SCREEN_BUFFER ScreenBuffer); + BOOL (STDCALL *SetScreenInfo)(PCSRSS_CONSOLE Console, PCSRSS_SCREEN_BUFFER ScreenBuffer, + UINT OldCursorX, UINT OldCursorY); + BOOL (STDCALL *ChangeTitle)(PCSRSS_CONSOLE Console); + VOID (STDCALL *CleanupConsole)(PCSRSS_CONSOLE Console); +} CSRSS_CONSOLE_VTBL, *PCSRSS_CONSOLE_VTBL; + +typedef struct tagCSRSS_CONSOLE +{ + Object_t Header; /* Object header */ + PCSRSS_CONSOLE Prev, Next; /* Next and Prev consoles in console wheel */ + HANDLE ActiveEvent; + LIST_ENTRY InputEvents; /* List head for input event queue */ + WORD WaitingChars; + WORD WaitingLines; /* number of chars and lines in input queue */ + PCSRSS_SCREEN_BUFFER ActiveBuffer; /* Pointer to currently active screen buffer */ + WORD Mode; /* Console mode flags */ + WORD EchoCount; /* count of chars to echo, in line buffered mode */ + UNICODE_STRING Title; /* Title of console */ + struct /* active code pages */ + { + UINT Input; + UINT Output; + } CodePageId; + BOOL EarlyReturn; /* wake client and return data, even if we are in line buffered mode, and we don't have a complete line */ + DWORD HardwareState; /* _GDI_MANAGED, _DIRECT */ + HWND hWindow; + COORD Size; + PVOID PrivateData; + PCSRSS_CONSOLE_VTBL Vtbl; + LIST_ENTRY ProcessList; +} CSRSS_CONSOLE; + VOID STDCALL ConioDeleteConsole(Object_t *Object); VOID STDCALL ConioDeleteScreenBuffer(Object_t *Buffer); -void STDCALL CsrProcessKey(MSG *msg, PCSRSS_CONSOLE Console); +void STDCALL ConioProcessKey(MSG *msg, PCSRSS_CONSOLE Console, BOOL TextMode); +void FASTCALL ConioPhysicalToLogical(PCSRSS_SCREEN_BUFFER Buff, + ULONG PhysicalX, + ULONG PhysicalY, + LONG *LogicalX, + LONG *LogicalY); +VOID FASTCALL ConioDrawConsole(PCSRSS_CONSOLE Console); /* api/conio.c */ CSR_API(CsrWriteConsole); @@ -54,6 +130,31 @@ CSR_API(CsrWriteConsoleInput); CSR_API(CsrHardwareStateProperty); CSR_API(CsrGetConsoleWindow); +#define ConioInitScreenBuffer(Console, Buff) (Console)->Vtbl->InitScreenBuffer((Console), (Buff)) +#define ConioDrawRegion(Console, Region) (Console)->Vtbl->DrawRegion((Console), (Region)) +#define ConioWriteStream(Console, Block, CurStartX, CurStartY, ScrolledLines, Buffer, Length) \ + (Console)->Vtbl->WriteStream((Console), (Block), (CurStartX), (CurStartY), \ + (ScrolledLines), (Buffer), (Length)) +#define ConioSetCursorInfo(Console, Buff) (Console)->Vtbl->SetCursorInfo((Console), (Buff)) +#define ConioSetScreenInfo(Console, Buff, OldCursorX, OldCursorY) \ + (Console)->Vtbl->SetScreenInfo((Console), (Buff), (OldCursorX), (OldCursorY)) +#define ConioChangeTitle(Console) (Console)->Vtbl->ChangeTitle(Console) +#define ConioCleanupConsole(Console) (Console)->Vtbl->CleanupConsole(Console) + +#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) + +#define ConioLockConsole(ProcessData, Handle, Ptr) \ + Win32CsrLockObject((ProcessData), (Handle), (Object_t **)(Ptr), CONIO_CONSOLE_MAGIC) +#define ConioUnlockConsole(Console) \ + Win32CsrUnlockObject((Object_t *) Console) +#define ConioLockScreenBuffer(ProcessData, Handle, Ptr) \ + Win32CsrLockObject((ProcessData), (Handle), (Object_t **)(Ptr), CONIO_SCREEN_BUFFER_MAGIC) +#define ConioUnlockScreenBuffer(Buff) \ + Win32CsrUnlockObject((Object_t *) Buff) + #endif /* CONIO_H_INCLUDED */ /* EOF */ diff --git a/reactos/subsys/csrss/include/desktopbg.h b/reactos/subsys/csrss/include/desktopbg.h index 7d322519005..1a8cdc8d48a 100644 --- a/reactos/subsys/csrss/include/desktopbg.h +++ b/reactos/subsys/csrss/include/desktopbg.h @@ -1,4 +1,4 @@ -/* $Id: desktopbg.h,v 1.1 2003/12/07 23:02:57 gvg Exp $ +/* $Id: desktopbg.h,v 1.2 2004/01/11 17:31:15 gvg Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS system libraries @@ -16,6 +16,8 @@ CSR_API(CsrCreateDesktop); CSR_API(CsrShowDesktop); CSR_API(CsrHideDesktop); +BOOL FASTCALL DtbgIsDesktopVisible(VOID); + #endif /* DESKTOPBG_H_INCLUDED */ /* EOF */ diff --git a/reactos/subsys/csrss/include/win32csr.h b/reactos/subsys/csrss/include/win32csr.h index d85bf014b2f..efb827d6825 100644 --- a/reactos/subsys/csrss/include/win32csr.h +++ b/reactos/subsys/csrss/include/win32csr.h @@ -1,4 +1,4 @@ -/* $Id: win32csr.h,v 1.1 2003/12/02 11:38:46 gvg Exp $ +/* $Id: win32csr.h,v 1.2 2004/01/11 17:31:15 gvg Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS system libraries @@ -6,6 +6,10 @@ * PURPOSE: Interface to win32csr.dll */ + +#ifndef WIN32CSR_H_INCLUDED +#define WIN32CSR_H_INCLUDED + #include extern HANDLE Win32CsrApiHeap; @@ -13,8 +17,20 @@ extern HANDLE Win32CsrApiHeap; NTSTATUS FASTCALL Win32CsrInsertObject(PCSRSS_PROCESS_DATA ProcessData, PHANDLE Handle, Object_t *Object); +NTSTATUS FASTCALL Win32CsrLockObject(PCSRSS_PROCESS_DATA ProcessData, + HANDLE Handle, + Object_t **Object, + long Type); +VOID FASTCALL Win32CsrUnlockObject(Object_t *Object); + +#ifndef TODO NTSTATUS FASTCALL Win32CsrGetObject(PCSRSS_PROCESS_DATA ProcessData, HANDLE Handle, Object_t **Object); NTSTATUS FASTCALL Win32CsrReleaseObject(PCSRSS_PROCESS_DATA ProcessData, HANDLE Object); +#endif + +#endif /* WIN32CSR_H_INCLUDED */ + +/* EOF */ diff --git a/reactos/subsys/csrss/win32csr/Makefile b/reactos/subsys/csrss/win32csr/Makefile index e6332ea378f..084a56bcc13 100644 --- a/reactos/subsys/csrss/win32csr/Makefile +++ b/reactos/subsys/csrss/win32csr/Makefile @@ -1,4 +1,4 @@ -# $Id: Makefile,v 1.2 2003/12/07 23:02:57 gvg Exp $ +# $Id: Makefile,v 1.3 2004/01/11 17:31:15 gvg Exp $ PATH_TO_TOP = ../../.. @@ -15,7 +15,7 @@ TARGET_LFLAGS = -nostartfiles -nostdlib TARGET_SDKLIBS = ntdll.a kernel32.a user32.a gdi32.a -TARGET_OBJECTS = dllmain.o conio.o guiconsole.o desktopbg.o +TARGET_OBJECTS = dllmain.o conio.o desktopbg.o guiconsole.o tuiconsole.o TARGET_ENTRY = _DllMain@12 diff --git a/reactos/subsys/csrss/win32csr/conio.c b/reactos/subsys/csrss/win32csr/conio.c index 27cef02a44e..362abf7fa12 100644 --- a/reactos/subsys/csrss/win32csr/conio.c +++ b/reactos/subsys/csrss/win32csr/conio.c @@ -1,4 +1,4 @@ -/* $Id: conio.c,v 1.2 2003/12/18 09:51:08 gvg Exp $ +/* $Id: conio.c,v 1.3 2004/01/11 17:31:16 gvg Exp $ * * reactos/subsys/csrss/win32csr/conio.c * @@ -20,18 +20,16 @@ #include #include "api.h" #include "conio.h" +#include "desktopbg.h" #include "guiconsole.h" +#include "tuiconsole.h" #include "win32csr.h" #define NDEBUG #include -#define LOCK RtlEnterCriticalSection(&ActiveConsoleLock) -#define UNLOCK RtlLeaveCriticalSection(&ActiveConsoleLock) - /* FIXME: Is there a way to create real aliasses with gcc? [CSH] */ #define ALIAS(Name, Target) typeof(Target) Name = Target -extern VOID CsrConsoleCtrlEvent(DWORD Event, PCSRSS_PROCESS_DATA ProcessData); /* Private user32 routines for CSRSS, not defined in any header file */ extern VOID STDCALL PrivateCsrssRegisterPrimitive(VOID); @@ -39,244 +37,197 @@ extern VOID STDCALL PrivateCsrssAcquireOrReleaseInputOwnership(BOOL Release); /* GLOBALS *******************************************************************/ -static HANDLE ConsoleDeviceHandle; -static PCSRSS_CONSOLE ActiveConsole; -CRITICAL_SECTION ActiveConsoleLock; -static COORD PhysicalConsoleSize; -static BOOL TextMode = TRUE; -static BOOL GuiConsolesInitialized = FALSE; +#define ConioInitRect(Rect, Top, Left, Bottom, Right) \ + ((Rect)->top) = Top; \ + ((Rect)->left) = Left; \ + ((Rect)->bottom) = Bottom; \ + ((Rect)->right) = Right -#define CsrpInitRect(_Rect, _Top, _Left, _Bottom, _Right) \ -{ \ - ((_Rect).Top) = _Top; \ - ((_Rect).Left) = _Left; \ - ((_Rect).Bottom) = _Bottom; \ - ((_Rect).Right) = _Right; \ -} - -#define CsrpRectHeight(Rect) \ - ((Rect.Top) > (Rect.Bottom) ? 0 : (Rect.Bottom) - (Rect.Top) + 1) - -#define CsrpRectWidth(Rect) \ - ((Rect.Left) > (Rect.Right) ? 0 : (Rect.Right) - (Rect.Left) + 1) - -#define CsrpIsRectEmpty(Rect) \ - ((Rect.Left > Rect.Right) || (Rect.Top > Rect.Bottom)) +#define ConioIsRectEmpty(Rect) \ + (((Rect)->left > (Rect)->right) || ((Rect)->top > (Rect)->bottom)) /* FUNCTIONS *****************************************************************/ -/* Text (blue screen) console support ****************************************/ - -static BOOL FASTCALL -CsrInitTextConsoleSupport(VOID) +STATIC NTSTATUS FASTCALL +ConioConsoleFromProcessData(PCSRSS_PROCESS_DATA ProcessData, PCSRSS_CONSOLE *Console) { - OBJECT_ATTRIBUTES ObjectAttributes; - UNICODE_STRING DeviceName; - NTSTATUS Status; - IO_STATUS_BLOCK Iosb; - CONSOLE_SCREEN_BUFFER_INFO ScrInfo; - - RtlRosInitUnicodeStringFromLiteral(&DeviceName, L"\\??\\BlueScreen"); - InitializeObjectAttributes(&ObjectAttributes, - &DeviceName, - 0, - NULL, - NULL); - Status = NtOpenFile(&ConsoleDeviceHandle, - FILE_ALL_ACCESS, - &ObjectAttributes, - &Iosb, - 0, - FILE_SYNCHRONOUS_IO_ALERT); - if (! NT_SUCCESS(Status)) + if (NULL == ProcessData->Console) { - DPRINT1("CSR: Failed to open console. Expect problems.\n"); - return FALSE; + *Console = NULL; + return STATUS_SUCCESS; } - ActiveConsole = 0; - RtlInitializeCriticalSection(&ActiveConsoleLock); - Status = NtDeviceIoControlFile(ConsoleDeviceHandle, NULL, NULL, NULL, &Iosb, IOCTL_CONSOLE_GET_SCREEN_BUFFER_INFO, 0, 0, &ScrInfo, sizeof(ScrInfo)); - if (! NT_SUCCESS(Status)) - { - DPRINT1("CSR: Failed to get console info, expect trouble\n"); - return FALSE; - } - PhysicalConsoleSize = ScrInfo.dwSize; + EnterCriticalSection(&(ProcessData->Console->Header.Lock)); + *Console = ProcessData->Console; - return TRUE; + return STATUS_SUCCESS; } -/* - * Screen buffer must be locked when this function is called - */ -inline NTSTATUS CsrpSetConsoleDeviceCursor(PCSRSS_SCREEN_BUFFER ScreenBuffer, SHORT X, SHORT Y) +STATIC VOID FASTCALL +CsrConsoleCtrlEvent(DWORD Event, PCSRSS_PROCESS_DATA ProcessData) { - CONSOLE_SCREEN_BUFFER_INFO ScrInfo; - IO_STATUS_BLOCK Iosb; - - ScrInfo.dwCursorPosition.X = X; - ScrInfo.dwCursorPosition.Y = Y; - ScrInfo.wAttributes = ScreenBuffer->DefaultAttrib; - - return NtDeviceIoControlFile( ConsoleDeviceHandle, NULL, NULL, NULL, &Iosb, - IOCTL_CONSOLE_SET_SCREEN_BUFFER_INFO, &ScrInfo, sizeof( ScrInfo ), 0, 0 ); -} - -static VOID FASTCALL -CsrTextConsoleDrawRegion(PCSRSS_CONSOLE Console, SMALL_RECT Region) -{ - IO_STATUS_BLOCK Iosb; - NTSTATUS Status; - CONSOLE_MODE Mode; - int i, y; - DWORD BytesPerLine; - DWORD SrcOffset; - DWORD SrcDelta; - PCSRSS_SCREEN_BUFFER ScreenBuffer = Console->ActiveBuffer; - - Mode.dwMode = 0; /* clear ENABLE_PROCESSED_OUTPUT mode */ - Status = NtDeviceIoControlFile( ConsoleDeviceHandle, NULL, NULL, NULL, &Iosb, - IOCTL_CONSOLE_SET_MODE, &Mode, sizeof( Mode ), 0, 0 ); - if( !NT_SUCCESS( Status ) ) - { - DbgPrint( "CSR: Failed to set console mode\n" ); - return; - } - - /* blast out buffer */ - BytesPerLine = CsrpRectWidth(Region) * 2; - SrcOffset = (((Region.Top + ScreenBuffer->ShowY) % ScreenBuffer->MaxY) * ScreenBuffer->MaxX + Region.Left + ScreenBuffer->ShowX) * 2; - SrcDelta = ScreenBuffer->MaxX * 2; - for( i = Region.Top, y = ScreenBuffer->ShowY; i <= Region.Bottom; i++ ) - { - /* Position the cursor correctly */ - Status = CsrpSetConsoleDeviceCursor(ScreenBuffer, Region.Left, i); - if( !NT_SUCCESS( Status ) ) - { - DbgPrint( "CSR: Failed to set console info\n" ); - return; - } - - Status = NtWriteFile( ConsoleDeviceHandle, NULL, NULL, NULL, &Iosb, - &ScreenBuffer->Buffer[ SrcOffset ], - BytesPerLine, 0, 0 ); - if( !NT_SUCCESS( Status ) ) - { - DbgPrint( "CSR: Write to console failed\n" ); - return; - } - - /* wrap back around the end of the buffer */ - if( ++y == ScreenBuffer->MaxY ) - { - y = 0; - SrcOffset = (Region.Left + ScreenBuffer->ShowX) * 2; - } - else - { - SrcOffset += SrcDelta; - } - } - Mode.dwMode = ENABLE_PROCESSED_OUTPUT; - Status = NtDeviceIoControlFile( ConsoleDeviceHandle, NULL, NULL, NULL, &Iosb, - IOCTL_CONSOLE_SET_MODE, &Mode, sizeof( Mode ), 0, 0 ); - if( !NT_SUCCESS( Status ) ) - { - DbgPrint( "CSR: Failed to set console mode\n" ); - return; - } - Status = CsrpSetConsoleDeviceCursor( - ScreenBuffer, - ScreenBuffer->CurrentX - ScreenBuffer->ShowX, - ((ScreenBuffer->CurrentY + ScreenBuffer->MaxY) - ScreenBuffer->ShowY) % ScreenBuffer->MaxY); - if( !NT_SUCCESS( Status ) ) - { - DbgPrint( "CSR: Failed to set console info\n" ); - return; - } - Status = NtDeviceIoControlFile( ConsoleDeviceHandle, NULL, NULL, NULL, &Iosb, - IOCTL_CONSOLE_SET_CURSOR_INFO, &ScreenBuffer->CursorInfo, - sizeof( ScreenBuffer->CursorInfo ), 0, 0 ); - if( !NT_SUCCESS( Status ) ) - { - DbgPrint( "CSR: Failed to set cursor info\n" ); - return; - } -} - -/* Graphics console support **************************************************/ - -static VOID FASTCALL -CsrInitGraphicsConsoleSupport(VOID) -{ - RtlInitializeCriticalSection(&ActiveConsoleLock); - GuiConsolesInitialized = FALSE; -} - -/* - * Region - Region of virtual screen buffer to draw onto the physical console - * Screen buffer must be locked when this function is called - */ -static VOID CsrpDrawRegion( - PCSRSS_CONSOLE Console, - SMALL_RECT Region) -{ - if (TextMode) - { - CsrTextConsoleDrawRegion(Console, Region); - } - else - { - GuiConsoleDrawRegion(Console, Region); - } -} - - -VOID CsrConsoleCtrlEvent(DWORD Event, PCSRSS_PROCESS_DATA ProcessData) -{ - HANDLE Process, hThread; - NTSTATUS Status; - CLIENT_ID ClientId, ClientId1; + HANDLE Process, Thread; - DPRINT1("CsrConsoleCtrlEvent Parent ProcessId = %x\n", ClientId.UniqueProcess); + DPRINT("CsrConsoleCtrlEvent Parent ProcessId = %x\n", ClientId.UniqueProcess); - if (ProcessData->CtrlDispatcher) + if (ProcessData->CtrlDispatcher) { - ClientId.UniqueProcess = (HANDLE) ProcessData->ProcessId; - Status = NtOpenProcess( &Process, PROCESS_DUP_HANDLE, 0, &ClientId ); - if( !NT_SUCCESS( Status ) ) - { - DPRINT("CsrConsoleCtrlEvent: Failed for handle duplication\n"); - return; - } + Process = OpenProcess(PROCESS_DUP_HANDLE, FALSE, ProcessData->ProcessId); + if (NULL == Process) + { + DPRINT1("Failed for handle duplication\n"); + return; + } - DPRINT1("CsrConsoleCtrlEvent Process Handle = %x\n", Process); + DPRINT("CsrConsoleCtrlEvent Process Handle = %x\n", Process); - - Status = RtlCreateUserThread(Process, NULL, FALSE, 0, NULL, NULL, - (PTHREAD_START_ROUTINE)ProcessData->CtrlDispatcher, - (PVOID) Event, &hThread, &ClientId1); - if( !NT_SUCCESS( Status ) ) - { - DPRINT("CsrConsoleCtrlEvent: Failed Thread creation\n"); - NtClose(Process); - return; - } - DPRINT1("CsrConsoleCtrlEvent Parent ProcessId = %x, ReturnPId = %x, hT = %x\n", - ClientId.UniqueProcess, ClientId1.UniqueProcess, hThread); - NtClose(hThread); - NtClose(Process); + Thread = CreateRemoteThread(Process, NULL, 0, + (LPTHREAD_START_ROUTINE) ProcessData->CtrlDispatcher, + (PVOID) Event, 0, NULL); + if (NULL == Thread) + { + DPRINT1("Failed thread creation\n"); + CloseHandle(Process); + return; + } + CloseHandle(Thread); + CloseHandle(Process); } } +#define GET_CELL_BUFFER(b,o)\ +(b)->Buffer[(o)++]; + +#define SET_CELL_BUFFER(b,o,c,a)\ +(b)->Buffer[(o)++]=(c);\ +(b)->Buffer[(o)++]=(a); + +static VOID FASTCALL +ClearLineBuffer(PCSRSS_SCREEN_BUFFER Buff) +{ + DWORD Offset = 2 * (Buff->CurrentY * Buff->MaxX); + UINT Pos; + + for (Pos = 0; Pos < Buff->MaxX; Pos++) + { + /* Fill the cell: Offset is incremented by the macro */ + SET_CELL_BUFFER(Buff, Offset, ' ', Buff->DefaultAttrib) + } +} + +STATIC NTSTATUS FASTCALL +CsrInitConsoleScreenBuffer(PCSRSS_CONSOLE Console, + PCSRSS_SCREEN_BUFFER Buffer) +{ + Buffer->Header.Type = CONIO_SCREEN_BUFFER_MAGIC; + Buffer->Header.ReferenceCount = 0; + Buffer->MaxX = Console->Size.X; + Buffer->MaxY = Console->Size.Y; + Buffer->ShowX = 0; + Buffer->ShowY = 0; + Buffer->Buffer = HeapAlloc(Win32CsrApiHeap, 0, Buffer->MaxX * Buffer->MaxY * 2); + if (NULL == Buffer->Buffer) + { + return STATUS_INSUFFICIENT_RESOURCES; + } + ConioInitScreenBuffer(Console, Buffer); + /* initialize buffer to be empty with default attributes */ + for (Buffer->CurrentY = 0 ; Buffer->CurrentY < Buffer->MaxY; Buffer->CurrentY++) + { + ClearLineBuffer(Buffer); + } + Buffer->CursorInfo.bVisible = TRUE; + Buffer->CursorInfo.dwSize = 5; + Buffer->Mode = ENABLE_PROCESSED_OUTPUT | ENABLE_WRAP_AT_EOL_OUTPUT; + Buffer->CurrentX = 0; + Buffer->CurrentY = 0; + + return STATUS_SUCCESS; +} + +STATIC NTSTATUS STDCALL +CsrInitConsole(PCSRSS_CONSOLE Console) +{ + NTSTATUS Status; + SECURITY_ATTRIBUTES SecurityAttributes; + PCSRSS_SCREEN_BUFFER NewBuffer; + BOOL GuiMode; + + Console->Title.MaximumLength = Console->Title.Length = 0; + Console->Title.Buffer = NULL; + + RtlCreateUnicodeString(&Console->Title, L"Command Prompt"); + + Console->Header.ReferenceCount = 0; + Console->WaitingChars = 0; + Console->WaitingLines = 0; + Console->EchoCount = 0; + Console->Header.Type = CONIO_CONSOLE_MAGIC; + Console->Mode = ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT | ENABLE_PROCESSED_INPUT | ENABLE_MOUSE_INPUT; + Console->EarlyReturn = FALSE; + Console->ActiveBuffer = NULL; + InitializeListHead(&Console->InputEvents); + InitializeListHead(&Console->ProcessList); + + SecurityAttributes.nLength = sizeof(SECURITY_ATTRIBUTES); + SecurityAttributes.lpSecurityDescriptor = NULL; + SecurityAttributes.bInheritHandle = TRUE; + + Console->ActiveEvent = CreateEventW(&SecurityAttributes, FALSE, FALSE, NULL); + if (NULL == Console->ActiveEvent) + { + return STATUS_UNSUCCESSFUL; + } + Console->PrivateData = NULL; + GuiMode = DtbgIsDesktopVisible(); + if (! GuiMode) + { + Status = TuiInitConsole(Console); + if (! NT_SUCCESS(Status)) + { + DPRINT1("Failed to open text-mode console, switching to gui-mode\n"); + GuiMode = TRUE; + } + } + if (GuiMode) + { + Status = GuiInitConsole(Console); + if (! NT_SUCCESS(Status)) + { + CloseHandle(Console->ActiveEvent); + return Status; + } + } + + NewBuffer = HeapAlloc(Win32CsrApiHeap, 0, sizeof(CSRSS_SCREEN_BUFFER)); + if (NULL == NewBuffer) + { + CloseHandle(Console->ActiveEvent); + return STATUS_INSUFFICIENT_RESOURCES; + } + Status = CsrInitConsoleScreenBuffer(Console, NewBuffer); + if (! NT_SUCCESS(Status)) + { + CloseHandle(Console->ActiveEvent); + HeapFree(Win32CsrApiHeap, 0, NewBuffer); + return Status; + } + Console->ActiveBuffer = NewBuffer; + /* add a reference count because the buffer is tied to the console */ + Console->ActiveBuffer->Header.ReferenceCount++; + /* make console active, and insert into console list */ + /* copy buffer contents to screen */ + ConioDrawConsole(Console); + + return STATUS_SUCCESS; +} + CSR_API(CsrAllocConsole) { PCSRSS_CONSOLE Console; HANDLE Process; NTSTATUS Status; - CLIENT_ID ClientId; DPRINT("CsrAllocConsole\n"); @@ -285,7 +236,7 @@ CSR_API(CsrAllocConsole) if (ProcessData == NULL) { - return(Reply->Status = STATUS_INVALID_PARAMETER); + return Reply->Status = STATUS_INVALID_PARAMETER; } if (ProcessData->Console) @@ -294,14 +245,8 @@ CSR_API(CsrAllocConsole) return STATUS_INVALID_PARAMETER; } - if (! GuiConsolesInitialized && ! TextMode) - { - GuiConsoleInitConsoleSupport(); - GuiConsolesInitialized = TRUE; - } - Reply->Status = STATUS_SUCCESS; - Console = RtlAllocateHeap( Win32CsrApiHeap, 0, sizeof( CSRSS_CONSOLE ) ); + Console = HeapAlloc(Win32CsrApiHeap, 0, sizeof(CSRSS_CONSOLE)); if (NULL == Console) { Reply->Status = STATUS_NO_MEMORY; @@ -310,7 +255,7 @@ CSR_API(CsrAllocConsole) Reply->Status = CsrInitConsole(Console); if (! NT_SUCCESS(Reply->Status)) { - RtlFreeHeap(Win32CsrApiHeap, 0, Console); + HeapFree(Win32CsrApiHeap, 0, Console); return Reply->Status; } ProcessData->Console = Console; @@ -334,11 +279,10 @@ CSR_API(CsrAllocConsole) return Reply->Status = Status; } - ClientId.UniqueProcess = (HANDLE) ProcessData->ProcessId; - Status = NtOpenProcess(&Process, PROCESS_DUP_HANDLE, 0, &ClientId); - if (! NT_SUCCESS(Status)) + Process = OpenProcess(PROCESS_DUP_HANDLE, FALSE, ProcessData->ProcessId); + if (NULL == Process) { - DbgPrint( "CSR: NtOpenProcess() failed for handle duplication\n" ); + DPRINT1("OpenProcess() failed for handle duplication\n"); Console->Header.ReferenceCount--; ProcessData->Console = 0; Win32CsrReleaseObject(ProcessData, Reply->Data.AllocConsoleReply.OutputHandle); @@ -346,11 +290,11 @@ CSR_API(CsrAllocConsole) Reply->Status = Status; return Status; } - Status = NtDuplicateObject(NtCurrentProcess(), ProcessData->Console->ActiveEvent, Process, &ProcessData->ConsoleEvent, SYNCHRONIZE, FALSE, 0); - if (! NT_SUCCESS(Status)) + if (! DuplicateHandle(GetCurrentProcess(), ProcessData->Console->ActiveEvent, + Process, &ProcessData->ConsoleEvent, EVENT_ALL_ACCESS, FALSE, 0)) { - DbgPrint( "CSR: NtDuplicateObject() failed: %x\n", Status ); - NtClose(Process); + DPRINT1("DuplicateHandle() failed: %d\n", GetLastError); + CloseHandle(Process); Console->Header.ReferenceCount--; Win32CsrReleaseObject(ProcessData, Reply->Data.AllocConsoleReply.OutputHandle); Win32CsrReleaseObject(ProcessData, Reply->Data.AllocConsoleReply.InputHandle); @@ -358,156 +302,321 @@ CSR_API(CsrAllocConsole) Reply->Status = Status; return Status; } - NtClose(Process); - LOCK; + CloseHandle(Process); ProcessData->CtrlDispatcher = Request->Data.AllocConsoleRequest.CtrlDispatcher; DPRINT("CSRSS:CtrlDispatcher address: %x\n", ProcessData->CtrlDispatcher); InsertHeadList(&ProcessData->Console->ProcessList, &ProcessData->ProcessEntry); - UNLOCK; return STATUS_SUCCESS; } CSR_API(CsrFreeConsole) { - PCSRSS_CONSOLE Console; + PCSRSS_CONSOLE Console; - DPRINT("CsrFreeConsole\n"); + DPRINT("CsrFreeConsole\n"); - Reply->Header.MessageSize = sizeof(CSRSS_API_REPLY); - Reply->Header.DataSize = sizeof(CSRSS_API_REPLY) - - sizeof(LPC_MESSAGE); + Reply->Header.MessageSize = sizeof(CSRSS_API_REPLY); + Reply->Header.DataSize = sizeof(CSRSS_API_REPLY) - sizeof(LPC_MESSAGE); - LOCK; - if (ProcessData == NULL || ProcessData->Console == NULL) - { - UNLOCK; - return(Reply->Status = STATUS_INVALID_PARAMETER); - } + if (ProcessData == NULL || ProcessData->Console == NULL) + { + return Reply->Status = STATUS_INVALID_PARAMETER; + } - Console = ProcessData->Console; - Console->Header.ReferenceCount--; - ProcessData->Console = 0; - if( Console->Header.ReferenceCount == 0 ) { - if( Console != ActiveConsole ) - ConioDeleteConsole((Object_t *) Console); - } - - UNLOCK; + Console = ProcessData->Console; + Console->Header.ReferenceCount--; + ProcessData->Console = NULL; + if (0 == Console->Header.ReferenceCount) + { + ConioDeleteConsole((Object_t *) Console); + } - return(STATUS_SUCCESS); + return STATUS_SUCCESS; +} + +STATIC VOID FASTCALL +ConioNextLine(PCSRSS_SCREEN_BUFFER Buff, RECT *UpdateRect, UINT *ScrolledLines) +{ + /* slide the viewable screen */ + if (((Buff->CurrentY - Buff->ShowY + Buff->MaxY) % Buff->MaxY) == Buff->MaxY - 1) + { + if (++Buff->ShowY == Buff->MaxY) + { + Buff->ShowY = 0; + } + (*ScrolledLines)++; + } + if (++Buff->CurrentY == Buff->MaxY) + { + Buff->CurrentY = 0; + } + ClearLineBuffer(Buff); + UpdateRect->left = 0; + UpdateRect->right = Buff->MaxX - 1; + if (UpdateRect->top == Buff->CurrentY) + { + if (++UpdateRect->top == Buff->MaxY) + { + UpdateRect->top = 0; + } + } + UpdateRect->bottom = Buff->CurrentY; +} + +STATIC NTSTATUS FASTCALL +ConioWriteConsole(PCSRSS_CONSOLE Console, PCSRSS_SCREEN_BUFFER Buff, + CHAR *Buffer, DWORD Length, BOOL Attrib) +{ + int i; + DWORD Offset; + RECT UpdateRect; + LONG CursorStartX, CursorStartY; + UINT ScrolledLines; + + ConioPhysicalToLogical(Buff, Buff->CurrentX, Buff->CurrentY, &CursorStartX, &CursorStartY); + UpdateRect.left = Buff->MaxX; + UpdateRect.top = Buff->CurrentY; + UpdateRect.right = -1; + UpdateRect.bottom = Buff->CurrentY; + ScrolledLines = 0; + + for (i = 0; i < Length; i++) + { + switch(Buffer[i]) + { + /* --- LF --- */ + case '\n': + Buff->CurrentX = 0; + ConioNextLine(Buff, &UpdateRect, &ScrolledLines); + break; + + /* --- BS --- */ + case '\b': + /* Only handle BS if we're not on the first pos of the first line */ + if (0 != Buff->CurrentX || Buff->ShowY != Buff->CurrentY) + { + if (0 == Buff->CurrentX) + { + /* slide virtual position up */ + Buff->CurrentX = Buff->MaxX - 1; + if (0 == Buff->CurrentY) + { + Buff->CurrentY = Buff->MaxY; + } + else + { + Buff->CurrentY--; + } + if ((0 == UpdateRect.top && UpdateRect.bottom < Buff->CurrentY) + || (0 != UpdateRect.top && Buff->CurrentY < UpdateRect.top)) + { + UpdateRect.top = Buff->CurrentY; + } + } + else + { + Buff->CurrentX--; + } + Offset = 2 * ((Buff->CurrentY * Buff->MaxX) + Buff->CurrentX); + SET_CELL_BUFFER(Buff, Offset, ' ', Buff->DefaultAttrib); + UpdateRect.left = RtlRosMin(UpdateRect.left, Buff->CurrentX); + UpdateRect.right = RtlRosMax(UpdateRect.right, (LONG) Buff->CurrentX); + } + break; + + /* --- CR --- */ + case '\r': + Buff->CurrentX = 0; + UpdateRect.left = RtlRosMin(UpdateRect.left, Buff->CurrentX); + UpdateRect.right = RtlRosMax(UpdateRect.right, (LONG) Buff->CurrentX); + break; + + /* --- TAB --- */ + case '\t': + { + UINT EndX; + + UpdateRect.left = RtlRosMin(UpdateRect.left, Buff->CurrentX); + EndX = 8 * ((Buff->CurrentX + 8) / 8); + if (Buff->MaxX < EndX) + { + EndX = Buff->MaxX; + } + Offset = 2 * (((Buff->CurrentY * Buff->MaxX)) + Buff->CurrentX); + while (Buff->CurrentX < EndX) + { + Buff->Buffer[Offset] = ' '; + Offset += 2; + Buff->CurrentX++; + } + UpdateRect.right = RtlRosMax(UpdateRect.right, (LONG) Buff->CurrentX - 1); + if (Buff->CurrentX == Buff->MaxX) + { + Buff->CurrentX = 0; + ConioNextLine(Buff, &UpdateRect, &ScrolledLines); + } + } + break; + + /* --- */ + default: + UpdateRect.left = RtlRosMin(UpdateRect.left, Buff->CurrentX); + UpdateRect.right = RtlRosMax(UpdateRect.right, (LONG) Buff->CurrentX); + Offset = 2 * (((Buff->CurrentY * Buff->MaxX)) + Buff->CurrentX); + Buff->Buffer[Offset++] = Buffer[i]; + if (Attrib) + { + Buff->Buffer[Offset] = Buff->DefaultAttrib; + } + Buff->CurrentX++; + if (Buff->CurrentX == Buff->MaxX) + { + Buff->CurrentX = 0; + ConioNextLine(Buff, &UpdateRect, &ScrolledLines); + } + break; + } + } + + ConioPhysicalToLogical(Buff, UpdateRect.left, UpdateRect.top, &(UpdateRect.left), + &(UpdateRect.top)); + ConioPhysicalToLogical(Buff, UpdateRect.right, UpdateRect.bottom, &(UpdateRect.right), + &(UpdateRect.bottom)); + if (! ConioIsRectEmpty(&UpdateRect) && NULL != Console && Buff == Console->ActiveBuffer) + { + ConioWriteStream(Console, &UpdateRect, CursorStartX, CursorStartY, ScrolledLines, + Buffer, Length); + } + + return STATUS_SUCCESS; } CSR_API(CsrReadConsole) { - PLIST_ENTRY CurrentEntry; - ConsoleInput *Input; - PCHAR Buffer; - int i = 0; - ULONG nNumberOfCharsToRead; - PCSRSS_CONSOLE Console; - NTSTATUS Status; + PLIST_ENTRY CurrentEntry; + ConsoleInput *Input; + PCHAR Buffer; + int i; + ULONG nNumberOfCharsToRead; + PCSRSS_CONSOLE Console; + NTSTATUS Status; - DPRINT("CsrReadConsole\n"); + DPRINT("CsrReadConsole\n"); /* truncate length to CSRSS_MAX_READ_CONSOLE_REQUEST */ - nNumberOfCharsToRead = Request->Data.ReadConsoleRequest.NrCharactersToRead > CSRSS_MAX_READ_CONSOLE_REQUEST ? CSRSS_MAX_READ_CONSOLE_REQUEST : Request->Data.ReadConsoleRequest.NrCharactersToRead; - Reply->Header.MessageSize = sizeof(CSRSS_API_REPLY); - Reply->Header.DataSize = Reply->Header.MessageSize - - sizeof(LPC_MESSAGE); + nNumberOfCharsToRead = Request->Data.ReadConsoleRequest.NrCharactersToRead > CSRSS_MAX_READ_CONSOLE_REQUEST ? CSRSS_MAX_READ_CONSOLE_REQUEST : Request->Data.ReadConsoleRequest.NrCharactersToRead; + Reply->Header.MessageSize = sizeof(CSRSS_API_REPLY); + Reply->Header.DataSize = Reply->Header.MessageSize - sizeof(LPC_MESSAGE); - Buffer = Reply->Data.ReadConsoleReply.Buffer; - LOCK; - Status = Win32CsrGetObject( ProcessData, Request->Data.ReadConsoleRequest.ConsoleHandle, (Object_t **)&Console ); - if( !NT_SUCCESS( Status ) ) - { - Reply->Status = Status; - UNLOCK; - return Status; - } - if( Console->Header.Type != CONIO_CONSOLE_MAGIC ) - { - Reply->Status = STATUS_INVALID_HANDLE; - UNLOCK; - return STATUS_INVALID_HANDLE; - } - Reply->Data.ReadConsoleReply.EventHandle = ProcessData->ConsoleEvent; - for (; iInputEvents.Flink != &Console->InputEvents; i++ ) - { - // remove input event from queue - CurrentEntry = RemoveHeadList(&Console->InputEvents); - Input = CONTAINING_RECORD(CurrentEntry, ConsoleInput, ListEntry); + Buffer = Reply->Data.ReadConsoleReply.Buffer; + Status = ConioLockConsole(ProcessData, Request->Data.ReadConsoleRequest.ConsoleHandle, + &Console); + if (! NT_SUCCESS(Status)) + { + return Reply->Status = Status; + } + Reply->Data.ReadConsoleReply.EventHandle = ProcessData->ConsoleEvent; + for (i = 0; i < nNumberOfCharsToRead && Console->InputEvents.Flink != &Console->InputEvents; i++) + { + /* remove input event from queue */ + CurrentEntry = RemoveHeadList(&Console->InputEvents); + Input = CONTAINING_RECORD(CurrentEntry, ConsoleInput, ListEntry); - // only pay attention to valid ascii chars, on key down - if( Input->InputEvent.EventType == KEY_EVENT && - Input->InputEvent.Event.KeyEvent.bKeyDown == TRUE && - Input->InputEvent.Event.KeyEvent.uChar.AsciiChar ) - { - // backspace handling - if( Input->InputEvent.Event.KeyEvent.uChar.AsciiChar == '\b' ) - { - // echo if it has not already been done, and either we or the client has chars to be deleted - if( !Input->Echoed && ( i || Request->Data.ReadConsoleRequest.nCharsCanBeDeleted ) ) - CsrpWriteConsole( Console->ActiveBuffer, &Input->InputEvent.Event.KeyEvent.uChar.AsciiChar, 1, TRUE ); - if( i ) - i-=2; // if we already have something to return, just back it up by 2 - else - { // otherwise, return STATUS_NOTIFY_CLEANUP to tell client to back up its buffer - Reply->Data.ReadConsoleReply.NrCharactersRead = 0; - Reply->Status = STATUS_NOTIFY_CLEANUP; - Console->WaitingChars--; - RtlFreeHeap( Win32CsrApiHeap, 0, Input ); - UNLOCK; - return STATUS_NOTIFY_CLEANUP; - } - Request->Data.ReadConsoleRequest.nCharsCanBeDeleted--; - Input->Echoed = TRUE; // mark as echoed so we don't echo it below - } - // do not copy backspace to buffer - else { - Buffer[i] = Input->InputEvent.Event.KeyEvent.uChar.AsciiChar; - } - // echo to screen if enabled and we did not already echo the char - if( Console->Mode & ENABLE_ECHO_INPUT && - !Input->Echoed && - Input->InputEvent.Event.KeyEvent.uChar.AsciiChar != '\r' ) - CsrpWriteConsole( Console->ActiveBuffer, &Input->InputEvent.Event.KeyEvent.uChar.AsciiChar, 1, TRUE ); - } - else i--; - Console->WaitingChars--; - RtlFreeHeap( Win32CsrApiHeap, 0, Input ); - } - Reply->Data.ReadConsoleReply.NrCharactersRead = i; - if( !i ) - Reply->Status = STATUS_PENDING; // we didn't read anything - else if( Console->Mode & ENABLE_LINE_INPUT ) - if( !Console->WaitingLines || Buffer[i-1] != '\n' ) - { - Reply->Status = STATUS_PENDING; // line buffered, didn't get a complete line - } - else { - Console->WaitingLines--; - Reply->Status = STATUS_SUCCESS; // line buffered, did get a complete line - } - else Reply->Status = STATUS_SUCCESS; // not line buffered, did read something - if( Reply->Status == STATUS_PENDING ) - { - Console->EchoCount = nNumberOfCharsToRead - i; - } - else { - Console->EchoCount = 0; // if the client is no longer waiting on input, do not echo - } - Reply->Header.MessageSize += i; - UNLOCK; - return Reply->Status; + /* only pay attention to valid ascii chars, on key down */ + if (KEY_EVENT == Input->InputEvent.EventType + && Input->InputEvent.Event.KeyEvent.bKeyDown + && Input->InputEvent.Event.KeyEvent.uChar.AsciiChar) + { + /* backspace handling */ + if ('\b' == Input->InputEvent.Event.KeyEvent.uChar.AsciiChar) + { + /* echo if it has not already been done, and either we or the client has chars to be deleted */ + if (! Input->Echoed + && (0 != i || Request->Data.ReadConsoleRequest.nCharsCanBeDeleted)) + { + ConioWriteConsole(Console, Console->ActiveBuffer, + &Input->InputEvent.Event.KeyEvent.uChar.AsciiChar, 1, TRUE); + } + if (0 != i) + { + i -= 2; /* if we already have something to return, just back it up by 2 */ + } + else + { /* otherwise, return STATUS_NOTIFY_CLEANUP to tell client to back up its buffer */ + Reply->Data.ReadConsoleReply.NrCharactersRead = 0; + Reply->Status = STATUS_NOTIFY_CLEANUP; + Console->WaitingChars--; + HeapFree(Win32CsrApiHeap, 0, Input); + ConioUnlockConsole(Console); + return STATUS_NOTIFY_CLEANUP; + } + Request->Data.ReadConsoleRequest.nCharsCanBeDeleted--; + Input->Echoed = TRUE; /* mark as echoed so we don't echo it below */ + } + /* do not copy backspace to buffer */ + else + { + Buffer[i] = Input->InputEvent.Event.KeyEvent.uChar.AsciiChar; + } + /* echo to screen if enabled and we did not already echo the char */ + if (0 != (Console->Mode & ENABLE_ECHO_INPUT) + && ! Input->Echoed + && '\r' != Input->InputEvent.Event.KeyEvent.uChar.AsciiChar) + { + ConioWriteConsole(Console, Console->ActiveBuffer, + &Input->InputEvent.Event.KeyEvent.uChar.AsciiChar, 1, TRUE); + } + } + else + { + i--; + } + Console->WaitingChars--; + HeapFree(Win32CsrApiHeap, 0, Input); + } + Reply->Data.ReadConsoleReply.NrCharactersRead = i; + if (0 == i) + { + Reply->Status = STATUS_PENDING; /* we didn't read anything */ + } + else if (0 != (Console->Mode & ENABLE_LINE_INPUT)) + { + if (0 == Console->WaitingLines || '\n' != Buffer[i - 1]) + { + Reply->Status = STATUS_PENDING; /* line buffered, didn't get a complete line */ + } + else + { + Console->WaitingLines--; + Reply->Status = STATUS_SUCCESS; /* line buffered, did get a complete line */ + } + } + else + { + Reply->Status = STATUS_SUCCESS; /* not line buffered, did read something */ + } + + if (Reply->Status == STATUS_PENDING) + { + Console->EchoCount = nNumberOfCharsToRead - i; + } + else + { + Console->EchoCount = 0; /* if the client is no longer waiting on input, do not echo */ + } + Reply->Header.MessageSize += i; + + ConioUnlockConsole(Console); + return Reply->Status; } -void FASTCALL -CsrpPhysicalToLogical(PCSRSS_SCREEN_BUFFER Buff, - ULONG PhysicalX, - ULONG PhysicalY, - SHORT *LogicalX, - SHORT *LogicalY) +VOID FASTCALL +ConioPhysicalToLogical(PCSRSS_SCREEN_BUFFER Buff, + ULONG PhysicalX, + ULONG PhysicalY, + LONG *LogicalX, + LONG *LogicalY) { *LogicalX = PhysicalX; if (PhysicalY < Buff->ShowY) @@ -520,340 +629,124 @@ CsrpPhysicalToLogical(PCSRSS_SCREEN_BUFFER Buff, } } -#define GET_CELL_BUFFER(b,o)\ -(b)->Buffer[(o)++]; - -#define SET_CELL_BUFFER(b,o,c,a)\ -(b)->Buffer[(o)++]=(c);\ -(b)->Buffer[(o)++]=(a); - -static VOID FASTCALL -ClearLineBuffer(PCSRSS_SCREEN_BUFFER Buff, DWORD StartX, BOOL Redraw) +inline BOOLEAN ConioIsEqualRect( + RECT *Rect1, + RECT *Rect2) { - DWORD Offset = 2 * ((Buff->CurrentY * Buff->MaxX) + StartX); - SMALL_RECT UpdateRect; - - CsrpPhysicalToLogical(Buff, StartX, Buff->CurrentY, &(UpdateRect.Left), - &(UpdateRect.Top)); - for ( ; StartX < Buff->MaxX; StartX ++) - { - /* Fill the cell: Offset is incremented by the macro */ - SET_CELL_BUFFER(Buff, Offset, ' ', Buff->DefaultAttrib) - } - - if (! TextMode && Redraw && NULL != Buff->Console) - { - CsrpPhysicalToLogical(Buff, Buff->MaxX - 1, Buff->CurrentY, &(UpdateRect.Right), - &(UpdateRect.Bottom)); - CsrpDrawRegion(Buff->Console, UpdateRect); - } + return ((Rect1->left == Rect2->left) && (Rect1->right == Rect2->right) && + (Rect1->top == Rect2->top) && (Rect1->bottom == Rect2->bottom)); } -static VOID FASTCALL -CsrpScrollUpOneLine(PCSRSS_CONSOLE Console) +inline BOOLEAN ConioGetIntersection( + RECT *Intersection, + RECT *Rect1, + RECT *Rect2) { - RECT Source, Dest; + 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; + } - if (! TextMode) - { - Source.top = 1; - Source.left = 0; - Source.bottom = Console->Size.Y - 1; - Source.right = Console->Size.X - 1; - Dest.top = 0; - Dest.left = 0; - Dest.bottom = Console->Size.Y - 2; - Dest.right = Console->Size.X - 1; + ConioInitRect(Intersection, + RtlRosMax(Rect1->top, Rect2->top), + RtlRosMax(Rect1->left, Rect2->left), + RtlRosMin(Rect1->bottom, Rect2->bottom), + RtlRosMin(Rect1->right, Rect2->right)); - GuiConsoleCopyRegion(Console, &Source, &Dest); - } + return TRUE; } -NTSTATUS STDCALL CsrpWriteConsole( PCSRSS_SCREEN_BUFFER Buff, CHAR *Buffer, DWORD Length, BOOL Attrib ) +inline BOOLEAN ConioGetUnion( + RECT *Union, + RECT *Rect1, + RECT *Rect2) { - IO_STATUS_BLOCK Iosb; - NTSTATUS Status; - int i; - DWORD Offset; - SMALL_RECT UpdateRect; - - CsrpPhysicalToLogical(Buff, Buff->CurrentX, Buff->CurrentY, &(UpdateRect.Left), - &(UpdateRect.Top)); - - for (i = 0; i < Length; i++) + if (ConioIsRectEmpty(Rect1)) { - switch(Buffer[i]) + if (ConioIsRectEmpty(Rect2)) { - case '\n': - case '\b': - case '\r': - case '\t': - if (! TextMode && NULL != Buff->Console) - { - CsrpPhysicalToLogical(Buff, Buff->CurrentX, Buff->CurrentY, - &(UpdateRect.Right), &(UpdateRect.Bottom)); - CsrpDrawRegion(Buff->Console, UpdateRect); - } - break; + ConioInitRect(Union, 0, -1, 0, -1); + return FALSE; } - - switch(Buffer[i]) + else { - /* --- LF --- */ - case '\n': - Buff->CurrentX = 0; - /* slide the viewable screen */ - if (((Buff->CurrentY - Buff->ShowY + Buff->MaxY) % Buff->MaxY) == Buff->MaxY - 1) - { - if (NULL != Buff->Console) - { - CsrpScrollUpOneLine(Buff->Console); - } - if (++Buff->ShowY == Buff->MaxY) - { - Buff->ShowY = 0; - } - } - if (++Buff->CurrentY == Buff->MaxY) - { - Buff->CurrentY = 0; - } - ClearLineBuffer(Buff, 0, TRUE); - CsrpPhysicalToLogical(Buff, Buff->CurrentX, Buff->CurrentY, - &(UpdateRect.Left), &(UpdateRect.Top)); - break; - - /* --- BS --- */ - case '\b': - if (0 == Buff->CurrentX) - { - /* slide viewable screen up */ - if (Buff->ShowY == Buff->CurrentY) - { - if (Buff->ShowY == 0) - { - Buff->ShowY = Buff->MaxY; - } - else - { - Buff->ShowY--; - } - } - /* slide virtual position up */ - Buff->CurrentX = Buff->MaxX; - if (0 == Buff->CurrentY) - { - Buff->CurrentY = Buff->MaxY; - } - else - { - Buff->CurrentY--; - } - } - else - { - Buff->CurrentX--; - } - Offset = 2 * ((Buff->CurrentY * Buff->MaxX) + Buff->CurrentX); - SET_CELL_BUFFER(Buff, Offset, ' ', Buff->DefaultAttrib); - CsrpPhysicalToLogical(Buff, Buff->CurrentX, Buff->CurrentY, - &(UpdateRect.Left), &(UpdateRect.Top)); - break; - - /* --- CR --- */ - case '\r': - Buff->CurrentX = 0; - CsrpPhysicalToLogical(Buff, Buff->CurrentX, Buff->CurrentY, - &(UpdateRect.Left), &(UpdateRect.Top)); - break; - - /* --- TAB --- */ - case '\t': - CsrpWriteConsole(Buff, " ", (8 - (Buff->CurrentX % 8)), FALSE); - CsrpPhysicalToLogical(Buff, Buff->CurrentX, Buff->CurrentY, - &(UpdateRect.Left), &(UpdateRect.Top)); - break; - - /* --- */ - default: - Offset = 2 * (((Buff->CurrentY * Buff->MaxX)) + Buff->CurrentX); - Buff->Buffer[Offset++] = Buffer[i]; - if (Attrib) - { - Buff->Buffer[Offset] = Buff->DefaultAttrib; - } - Buff->CurrentX++; - if (Buff->CurrentX == Buff->MaxX) - { - /* if end of line, go to next */ - if (! TextMode && NULL != Buff->Console) - { - CsrpPhysicalToLogical(Buff, Buff->CurrentX, Buff->CurrentY, - &(UpdateRect.Right), &(UpdateRect.Bottom)); - CsrpDrawRegion(Buff->Console, UpdateRect); - } - - Buff->CurrentX = 0; - /* slide the viewable screen */ - if (((Buff->CurrentY - Buff->ShowY + Buff->MaxY) % Buff->MaxY) == Buff->MaxY - 1) - { - if (NULL != Buff->Console) - { - CsrpScrollUpOneLine(Buff->Console); - } - if (++Buff->ShowY == Buff->MaxY) - { - Buff->ShowY = 0; - } - } - if (++Buff->CurrentY == Buff->MaxY) - { - /* if end of buffer, wrap back to beginning */ - Buff->CurrentY = 0; - } - /* clear new line */ - ClearLineBuffer(Buff, 0, TRUE); - CsrpPhysicalToLogical(Buff, Buff->CurrentX, Buff->CurrentY, - &(UpdateRect.Left), &(UpdateRect.Top)); - } - break; + *Union = *Rect2; } } - - CsrpPhysicalToLogical(Buff, Buff->CurrentX, Buff->CurrentY, &(UpdateRect.Right), - &(UpdateRect.Bottom)); - if (! TextMode && NULL != Buff->Console) + else if (ConioIsRectEmpty(Rect2)) { - CsrpDrawRegion(Buff->Console, UpdateRect); + *Union = *Rect1; } - else if (TextMode && Buff == ActiveConsole->ActiveBuffer) - { /* only write to screen if Console is Active, and not scrolled up */ - if (Attrib) + else + { + ConioInitRect(Union, + RtlRosMin(Rect1->top, Rect2->top), + RtlRosMin(Rect1->left, Rect2->left), + RtlRosMax(Rect1->bottom, Rect2->bottom), + RtlRosMax(Rect1->right, Rect2->right)); + } + + return TRUE; +} + +inline BOOLEAN ConioSubtractRect( + RECT *Subtraction, + RECT *Rect1, + RECT *Rect2) +{ + RECT tmp; + + if (ConioIsRectEmpty(Rect1)) + { + ConioInitRect(Subtraction, 0, -1, 0, -1); + return FALSE; + } + *Subtraction = *Rect1; + if (ConioGetIntersection(&tmp, Rect1, Rect2)) + { + if (ConioIsEqualRect(&tmp, Subtraction)) { - Status = NtWriteFile(ConsoleDeviceHandle, NULL, NULL, NULL, &Iosb, Buffer, Length, NULL, 0); - if (!NT_SUCCESS(Status)) + ConioInitRect(Subtraction, 0, -1, 0, -1); + return FALSE; + } + if ((tmp.top == Subtraction->top) && (tmp.bottom == Subtraction->bottom)) + { + if (tmp.left == Subtraction->left) { - DbgPrint("CSR: Write failed\n"); + Subtraction->left = tmp.right; + } + else if (tmp.right == Subtraction->right) + { + Subtraction->right = tmp.left; + } + } + else if ((tmp.left == Subtraction->left) && (tmp.right == Subtraction->right)) + { + if (tmp.top == Subtraction->top) + { + Subtraction->top = tmp.bottom; + } + else if (tmp.bottom == Subtraction->bottom) + { + Subtraction->bottom = tmp.top; } } } - return(STATUS_SUCCESS); -} - -inline BOOLEAN CsrpIsEqualRect( - SMALL_RECT Rect1, - SMALL_RECT Rect2) -{ - return ((Rect1.Left == Rect2.Left) && (Rect1.Right == Rect2.Right) && - (Rect1.Top == Rect2.Top) && (Rect1.Bottom == Rect2.Bottom)); -} - -inline BOOLEAN CsrpGetIntersection( - PSMALL_RECT Intersection, - SMALL_RECT Rect1, - SMALL_RECT Rect2) -{ - if (CsrpIsRectEmpty(Rect1) || - (CsrpIsRectEmpty(Rect2)) || - (Rect1.Top > Rect2.Bottom) || - (Rect1.Left > Rect2.Right) || - (Rect1.Bottom < Rect2.Top) || - (Rect1.Right < Rect2.Left)) - { - /* The rectangles do not intersect */ - CsrpInitRect(*Intersection, 0, -1, 0, -1) - return FALSE; - } - - CsrpInitRect( - *Intersection, - RtlRosMax(Rect1.Top, Rect2.Top), - RtlRosMax(Rect1.Left, Rect2.Left), - RtlRosMin(Rect1.Bottom, Rect2.Bottom), - RtlRosMin(Rect1.Right, Rect2.Right)); return TRUE; } -inline BOOLEAN CsrpGetUnion( - PSMALL_RECT Union, - SMALL_RECT Rect1, - SMALL_RECT Rect2) -{ - if (CsrpIsRectEmpty(Rect1)) - { - if (CsrpIsRectEmpty(Rect2)) - { - CsrpInitRect(*Union, 0, -1, 0, -1); - return FALSE; - } - else - *Union = Rect2; - } - else - { - if (CsrpIsRectEmpty(Rect2)) - { - *Union = Rect1; - } - else - { - CsrpInitRect( - *Union, - RtlRosMin(Rect1.Top, Rect2.Top), - RtlRosMin(Rect1.Left, Rect2.Left), - RtlRosMax(Rect1.Bottom, Rect2.Bottom), - RtlRosMax(Rect1.Right, Rect2.Right)); - } - } - return TRUE; -} - -inline BOOLEAN CsrpSubtractRect( - PSMALL_RECT Subtraction, - SMALL_RECT Rect1, - SMALL_RECT Rect2) -{ - SMALL_RECT tmp; - - if (CsrpIsRectEmpty(Rect1)) - { - CsrpInitRect(*Subtraction, 0, -1, 0, -1); - return FALSE; - } - *Subtraction = Rect1; - if (CsrpGetIntersection(&tmp, Rect1, Rect2)) - { - if (CsrpIsEqualRect(tmp, *Subtraction)) - { - CsrpInitRect(*Subtraction, 0, -1, 0, -1); - return FALSE; - } - if ((tmp.Top == Subtraction->Top) && (tmp.Bottom == Subtraction->Bottom)) - { - if (tmp.Left == Subtraction->Left) - Subtraction->Left = tmp.Right; - else if (tmp.Right == Subtraction->Right) - Subtraction->Right = tmp.Left; - } - else if ((tmp.Left == Subtraction->Left) && (tmp.Right == Subtraction->Right)) - { - if (tmp.Top == Subtraction->Top) - Subtraction->Top = tmp.Bottom; - else if (tmp.Bottom == Subtraction->Bottom) - Subtraction->Bottom = tmp.Top; - } - } - return TRUE; -} - -/* - * Screen buffer must be locked when this function is called - */ -static VOID CsrpCopyRegion( - PCSRSS_SCREEN_BUFFER ScreenBuffer, - SMALL_RECT SrcRegion, - SMALL_RECT DstRegion) +STATIC VOID FASTCALL +ConioCopyRegion(PCSRSS_SCREEN_BUFFER ScreenBuffer, + RECT *SrcRegion, + RECT *DstRegion) { SHORT SrcY, DstY; DWORD SrcOffset; @@ -861,82 +754,81 @@ static VOID CsrpCopyRegion( DWORD BytesPerLine; ULONG i; - DstY = DstRegion.Top; - BytesPerLine = CsrpRectWidth(DstRegion) * 2; + DstY = DstRegion->top; + BytesPerLine = ConioRectWidth(DstRegion) * 2; - SrcY = (SrcRegion.Top + ScreenBuffer->ShowY) % ScreenBuffer->MaxY; - DstY = (DstRegion.Top + ScreenBuffer->ShowY) % ScreenBuffer->MaxY; - SrcOffset = (SrcY * ScreenBuffer->MaxX + SrcRegion.Left + ScreenBuffer->ShowX) * 2; - DstOffset = (DstY * ScreenBuffer->MaxX + DstRegion.Left + ScreenBuffer->ShowX) * 2; + SrcY = (SrcRegion->top + ScreenBuffer->ShowY) % ScreenBuffer->MaxY; + DstY = (DstRegion->top + ScreenBuffer->ShowY) % ScreenBuffer->MaxY; + SrcOffset = (SrcY * ScreenBuffer->MaxX + SrcRegion->left + ScreenBuffer->ShowX) * 2; + DstOffset = (DstY * ScreenBuffer->MaxX + DstRegion->left + ScreenBuffer->ShowX) * 2; - for (i = SrcRegion.Top; i <= SrcRegion.Bottom; i++) - { - RtlCopyMemory( - &ScreenBuffer->Buffer[DstOffset], - &ScreenBuffer->Buffer[SrcOffset], - BytesPerLine); + for (i = SrcRegion->top; i <= SrcRegion->bottom; i++) + { + RtlCopyMemory( + &ScreenBuffer->Buffer[DstOffset], + &ScreenBuffer->Buffer[SrcOffset], + BytesPerLine); - if (++DstY == ScreenBuffer->MaxY) - { - DstY = 0; - DstOffset = (DstRegion.Left + ScreenBuffer->ShowX) * 2; - } - else - { - DstOffset += ScreenBuffer->MaxX * 2; - } + if (++DstY == ScreenBuffer->MaxY) + { + DstY = 0; + DstOffset = (DstRegion->left + ScreenBuffer->ShowX) * 2; + } + else + { + DstOffset += ScreenBuffer->MaxX * 2; + } - if (++SrcY == ScreenBuffer->MaxY) - { - SrcY = 0; - SrcOffset = (SrcRegion.Left + ScreenBuffer->ShowX) * 2; + if (++SrcY == ScreenBuffer->MaxY) + { + SrcY = 0; + SrcOffset = (SrcRegion->left + ScreenBuffer->ShowX) * 2; + } + else + { + SrcOffset += ScreenBuffer->MaxX * 2; + } } - else - { - SrcOffset += ScreenBuffer->MaxX * 2; - } - } } -/* - * Screen buffer must be locked when this function is called - */ -static VOID CsrpFillRegion( - PCSRSS_SCREEN_BUFFER ScreenBuffer, - SMALL_RECT Region, - CHAR_INFO CharInfo) +STATIC VOID FASTCALL +ConioFillRegion(PCSRSS_SCREEN_BUFFER ScreenBuffer, + RECT *Region, + CHAR_INFO CharInfo) { SHORT X, Y; DWORD Offset; DWORD Delta; ULONG i; - Y = (Region.Top + ScreenBuffer->ShowY) % ScreenBuffer->MaxY; - Offset = (Y * ScreenBuffer->MaxX + Region.Left + ScreenBuffer->ShowX) * 2; - Delta = (ScreenBuffer->MaxX - CsrpRectWidth(Region)) * 2; + Y = (Region->top + ScreenBuffer->ShowY) % ScreenBuffer->MaxY; + Offset = (Y * ScreenBuffer->MaxX + Region->left + ScreenBuffer->ShowX) * 2; + Delta = (ScreenBuffer->MaxX - ConioRectWidth(Region)) * 2; - for (i = Region.Top; i <= Region.Bottom; i++) - { - for (X = Region.Left; X <= Region.Right; X++) + for (i = Region->top; i <= Region->bottom; i++) { - SET_CELL_BUFFER(ScreenBuffer, Offset, CharInfo.Char.AsciiChar, CharInfo.Attributes); + for (X = Region->left; X <= Region->right; X++) + { + SET_CELL_BUFFER(ScreenBuffer, Offset, CharInfo.Char.AsciiChar, CharInfo.Attributes); + } + if (++Y == ScreenBuffer->MaxY) + { + Y = 0; + Offset = (Region->left + ScreenBuffer->ShowX) * 2; + } + else + { + Offset += Delta; + } } - if (++Y == ScreenBuffer->MaxY) - { - Y = 0; - Offset = (Region.Left + ScreenBuffer->ShowX) * 2; - } - else - { - Offset += Delta; - } - } } CSR_API(CsrWriteConsole) { + NTSTATUS Status; BYTE *Buffer = Request->Data.WriteConsoleRequest.Buffer; PCSRSS_SCREEN_BUFFER Buff; + PCSRSS_CONSOLE Console; DPRINT("CsrWriteConsole\n"); @@ -951,222 +843,94 @@ CSR_API(CsrWriteConsole) DPRINT1("Invalid request size\n"); return Reply->Status = STATUS_INVALID_PARAMETER; } - - LOCK; - if (! NT_SUCCESS(Win32CsrGetObject(ProcessData, - Request->Data.WriteConsoleRequest.ConsoleHandle, - (Object_t **) &Buff)) - || Buff->Header.Type != CONIO_SCREEN_BUFFER_MAGIC) + Status = ConioConsoleFromProcessData(ProcessData, &Console); + if (! NT_SUCCESS(Status)) { - UNLOCK; - return Reply->Status = STATUS_INVALID_HANDLE; - } - RtlEnterCriticalSection(&(Buff->Lock)); - CsrpWriteConsole( Buff, Buffer, Request->Data.WriteConsoleRequest.NrCharactersToWrite, TRUE ); - RtlLeaveCriticalSection(&(Buff->Lock)); - UNLOCK; - return Reply->Status = STATUS_SUCCESS; -} - - -NTSTATUS STDCALL CsrInitConsoleScreenBuffer(PCSRSS_SCREEN_BUFFER Buffer, - PCSRSS_CONSOLE Console, - unsigned Width, - unsigned Height) -{ - Buffer->Header.Type = CONIO_SCREEN_BUFFER_MAGIC; - Buffer->Header.ReferenceCount = 0; - Buffer->MaxX = Width; - Buffer->MaxY = Height; - Buffer->ShowX = 0; - Buffer->ShowY = 0; - Buffer->CurrentX = 0; - Buffer->CurrentY = 0; - Buffer->Buffer = RtlAllocateHeap( Win32CsrApiHeap, 0, Buffer->MaxX * Buffer->MaxY * 2 ); - if( Buffer->Buffer == 0 ) - return STATUS_INSUFFICIENT_RESOURCES; - Buffer->DefaultAttrib = (TextMode ? 0x17 : 0x0f); - /* initialize buffer to be empty with default attributes */ - for( ; Buffer->CurrentY < Buffer->MaxY; Buffer->CurrentY++ ) - { - ClearLineBuffer(Buffer, 0, FALSE); + return Reply->Status = Status; } - Buffer->CursorInfo.bVisible = TRUE; - Buffer->CursorInfo.dwSize = 5; - Buffer->Mode = ENABLE_PROCESSED_OUTPUT | ENABLE_WRAP_AT_EOL_OUTPUT; - Buffer->CurrentX = 0; - Buffer->CurrentY = 0; - Buffer->Console = Console; - RtlInitializeCriticalSection(&(Buffer->Lock)); - return STATUS_SUCCESS; + Status = ConioLockScreenBuffer(ProcessData, Request->Data.WriteConsoleRequest.ConsoleHandle, &Buff); + if (! NT_SUCCESS(Status)) + { + if (NULL != Console) + { + ConioUnlockConsole(Console); + } + return Reply->Status = Status; + } + + ConioWriteConsole(Console, Buff, Buffer, + Request->Data.WriteConsoleRequest.NrCharactersToWrite, TRUE); + ConioUnlockScreenBuffer(Buff); + if (NULL != Console) + { + ConioUnlockConsole(Console); + } + + return Reply->Status = STATUS_SUCCESS; } -VOID STDCALL ConioDeleteScreenBuffer(Object_t *Object) +VOID STDCALL +ConioDeleteScreenBuffer(Object_t *Object) { PCSRSS_SCREEN_BUFFER Buffer = (PCSRSS_SCREEN_BUFFER) Object; - RtlFreeHeap(Win32CsrApiHeap, 0, Buffer->Buffer); - RtlFreeHeap(Win32CsrApiHeap, 0, Buffer); + HeapFree(Win32CsrApiHeap, 0, Buffer->Buffer); + HeapFree(Win32CsrApiHeap, 0, Buffer); } -NTSTATUS STDCALL CsrInitConsole(PCSRSS_CONSOLE Console) +VOID FASTCALL +ConioDrawConsole(PCSRSS_CONSOLE Console) { - NTSTATUS Status; - OBJECT_ATTRIBUTES ObjectAttributes; - PCSRSS_SCREEN_BUFFER NewBuffer; + RECT Region; - Console->Title.MaximumLength = Console->Title.Length = 0; - Console->Title.Buffer = 0; - - RtlCreateUnicodeString( &Console->Title, L"Command Prompt" ); - - Console->Header.ReferenceCount = 0; - Console->WaitingChars = 0; - Console->WaitingLines = 0; - Console->EchoCount = 0; - Console->Header.Type = CONIO_CONSOLE_MAGIC; - Console->Mode = ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT | ENABLE_PROCESSED_INPUT | ENABLE_MOUSE_INPUT; - Console->EarlyReturn = FALSE; - InitializeListHead(&Console->InputEvents); - InitializeListHead(&Console->ProcessList); + ConioInitRect(&Region, 0, 0, Console->Size.Y - 1, Console->Size.X - 1); - InitializeObjectAttributes(&ObjectAttributes, NULL, OBJ_INHERIT, NULL, NULL); - - Status = NtCreateEvent( &Console->ActiveEvent, STANDARD_RIGHTS_ALL, &ObjectAttributes, FALSE, FALSE ); - if( !NT_SUCCESS( Status ) ) - { - return Status; - } - Console->GuiConsoleData = NULL; - if (! TextMode) - { - Console->ActiveBuffer = NULL; - GuiConsoleInitConsole(Console); - } - else - { - Console->hWindow = (HWND) NULL; - Console->Size = PhysicalConsoleSize; - } - NewBuffer = RtlAllocateHeap( Win32CsrApiHeap, 0, sizeof( CSRSS_SCREEN_BUFFER ) ); - if (! NewBuffer ) - { - NtClose(Console->ActiveEvent); - return STATUS_INSUFFICIENT_RESOURCES; - } - Status = CsrInitConsoleScreenBuffer(NewBuffer, Console, Console->Size.X, Console->Size.Y); - if( !NT_SUCCESS( Status ) ) - { - NtClose( Console->ActiveEvent ); - RtlFreeHeap( Win32CsrApiHeap, 0, NewBuffer ); - return Status; - } - Console->ActiveBuffer = NewBuffer; - /* add a reference count because the buffer is tied to the console */ - Console->ActiveBuffer->Header.ReferenceCount++; - /* make console active, and insert into console list */ - LOCK; - if( ActiveConsole ) - { - Console->Prev = ActiveConsole; - Console->Next = ActiveConsole->Next; - ActiveConsole->Next->Prev = Console; - ActiveConsole->Next = Console; - } - else { - Console->Prev = Console; - Console->Next = Console; - } - ActiveConsole = Console; - /* copy buffer contents to screen */ - CsrDrawConsole(Console); - UNLOCK; - return STATUS_SUCCESS; -} - -/*************************************************************** - * CsrDrawConsole blasts the console buffer onto the screen * - * must be called while holding the active console lock * - **************************************************************/ -VOID STDCALL CsrDrawConsole(PCSRSS_CONSOLE Console) -{ - SMALL_RECT Region; - - CsrpInitRect( - Region, - 0, - 0, - Console->Size.Y - 1, - Console->Size.X - 1); - - CsrpDrawRegion(Console, Region); + ConioDrawRegion(Console, &Region); } -VOID STDCALL ConioDeleteConsole(Object_t *Object) +VOID STDCALL +ConioDeleteConsole(Object_t *Object) { PCSRSS_CONSOLE Console = (PCSRSS_CONSOLE) Object; ConsoleInput *Event; + DPRINT("ConioDeleteConsole\n"); - LOCK; + /* Drain input event queue */ while (Console->InputEvents.Flink != &Console->InputEvents) { Event = (ConsoleInput *) Console->InputEvents.Flink; Console->InputEvents.Flink = Console->InputEvents.Flink->Flink; Console->InputEvents.Flink->Flink->Blink = &Console->InputEvents; - RtlFreeHeap(Win32CsrApiHeap, 0, Event); - } - /* Switch to next console */ - if (ActiveConsole == Console) - { - ActiveConsole = Console->Next != Console ? Console->Next : NULL; - } - if (Console->Next != Console) - { - Console->Prev->Next = Console->Next; - Console->Next->Prev = Console->Prev; - } - - if (ActiveConsole) - { - CsrDrawConsole(ActiveConsole); + HeapFree(Win32CsrApiHeap, 0, Event); } - if (! --Console->ActiveBuffer->Header.ReferenceCount) + if (0 == --Console->ActiveBuffer->Header.ReferenceCount) { ConioDeleteScreenBuffer((Object_t *) Console->ActiveBuffer); } + Console->ActiveBuffer = NULL; - if (! TextMode) - { - GuiConsoleDeleteConsole(Console); - } - UNLOCK; - NtClose(Console->ActiveEvent); + ConioCleanupConsole(Console); + + CloseHandle(Console->ActiveEvent); RtlFreeUnicodeString(&Console->Title); - RtlFreeHeap(Win32CsrApiHeap, 0, Console); + HeapFree(Win32CsrApiHeap, 0, Console); } -VOID STDCALL CsrInitConsoleSupport(VOID) +VOID STDCALL +CsrInitConsoleSupport(VOID) { DPRINT("CSR: CsrInitConsoleSupport()\n"); /* Should call LoadKeyboardLayout */ - - if (TextMode) - { - TextMode = CsrInitTextConsoleSupport(); - } - - if (! TextMode) - { - CsrInitGraphicsConsoleSupport(); - } } -static void CsrpProcessChar( PCSRSS_CONSOLE Console, - ConsoleInput *KeyEventRecord ) { +STATIC VOID FASTCALL +ConioProcessChar(PCSRSS_CONSOLE Console, + ConsoleInput *KeyEventRecord) +{ BOOL updown; BOOL bClientWake = FALSE; ConsoleInput *TempInput; @@ -1181,7 +945,6 @@ static void CsrpProcessChar( PCSRSS_CONSOLE Console, PCSRSS_PROCESS_DATA current; PLIST_ENTRY current_entry; DPRINT1("Console_Api Ctrl-C\n"); - LOCK; current_entry = Console->ProcessList.Flink; while (current_entry != &Console->ProcessList) { @@ -1189,197 +952,224 @@ static void CsrpProcessChar( PCSRSS_CONSOLE Console, current_entry = current_entry->Flink; CsrConsoleCtrlEvent((DWORD)CTRL_C_EVENT, current); } - UNLOCK; - RtlFreeHeap( Win32CsrApiHeap, 0, KeyEventRecord ); + HeapFree(Win32CsrApiHeap, 0, KeyEventRecord); return; } - if( KeyEventRecord->InputEvent.Event.KeyEvent.dwControlKeyState & - ( RIGHT_ALT_PRESSED | LEFT_ALT_PRESSED ) && - ( KeyEventRecord->InputEvent.Event.KeyEvent.wVirtualKeyCode == VK_UP || - KeyEventRecord->InputEvent.Event.KeyEvent.wVirtualKeyCode == VK_DOWN) ) + + if (0 != (KeyEventRecord->InputEvent.Event.KeyEvent.dwControlKeyState + & (RIGHT_ALT_PRESSED | LEFT_ALT_PRESSED)) + && (VK_UP == KeyEventRecord->InputEvent.Event.KeyEvent.wVirtualKeyCode + || VK_DOWN == KeyEventRecord->InputEvent.Event.KeyEvent.wVirtualKeyCode)) { - if( KeyEventRecord->InputEvent.Event.KeyEvent.bKeyDown == TRUE ) + if (KeyEventRecord->InputEvent.Event.KeyEvent.bKeyDown) { /* scroll up or down */ - LOCK; - if( Console == 0 ) + if (NULL == Console) { - DbgPrint( "CSR: No Active Console!\n" ); - UNLOCK; - RtlFreeHeap( Win32CsrApiHeap, 0, KeyEventRecord ); + DPRINT1("No Active Console!\n"); + HeapFree(Win32CsrApiHeap, 0, KeyEventRecord); return; } - if( KeyEventRecord->InputEvent.Event.KeyEvent.wVirtualKeyCode == VK_UP ) + if (VK_UP == KeyEventRecord->InputEvent.Event.KeyEvent.wVirtualKeyCode) { /* only scroll up if there is room to scroll up into */ - if( Console->ActiveBuffer->ShowY != ((Console->ActiveBuffer->CurrentY + 1) % - Console->ActiveBuffer->MaxY) ) - Console->ActiveBuffer->ShowY = (Console->ActiveBuffer->ShowY + - Console->ActiveBuffer->MaxY - 1) % Console->ActiveBuffer->MaxY; - } - else if( Console->ActiveBuffer->ShowY != Console->ActiveBuffer->CurrentY ) + if (Console->ActiveBuffer->ShowY != ((Console->ActiveBuffer->CurrentY + 1) % + Console->ActiveBuffer->MaxY)) + { + Console->ActiveBuffer->ShowY = (Console->ActiveBuffer->ShowY + + Console->ActiveBuffer->MaxY - 1) % + Console->ActiveBuffer->MaxY; + } + } + else if (Console->ActiveBuffer->ShowY != Console->ActiveBuffer->CurrentY) /* only scroll down if there is room to scroll down into */ - if( Console->ActiveBuffer->ShowY % Console->ActiveBuffer->MaxY != - Console->ActiveBuffer->CurrentY ) - - if( ((Console->ActiveBuffer->CurrentY + 1) % Console->ActiveBuffer->MaxY) != - (Console->ActiveBuffer->ShowY + Console->ActiveBuffer->MaxY) % Console->ActiveBuffer->MaxY ) - Console->ActiveBuffer->ShowY = (Console->ActiveBuffer->ShowY + 1) % - Console->ActiveBuffer->MaxY; - CsrDrawConsole(Console); - UNLOCK; - } - RtlFreeHeap( Win32CsrApiHeap, 0, KeyEventRecord ); + { + if (Console->ActiveBuffer->ShowY % Console->ActiveBuffer->MaxY != + Console->ActiveBuffer->CurrentY) + { + if (((Console->ActiveBuffer->CurrentY + 1) % Console->ActiveBuffer->MaxY) != + (Console->ActiveBuffer->ShowY + Console->ActiveBuffer->MaxY) % + Console->ActiveBuffer->MaxY) + { + Console->ActiveBuffer->ShowY = (Console->ActiveBuffer->ShowY + 1) % + Console->ActiveBuffer->MaxY; + } + } + } + ConioDrawConsole(Console); + } + HeapFree(Win32CsrApiHeap, 0, KeyEventRecord); return; } - if( Console == 0 ) + if (NULL == Console) { - DbgPrint( "CSR: No Active Console!\n" ); - UNLOCK; - RtlFreeHeap( Win32CsrApiHeap, 0, KeyEventRecord ); + DPRINT1("No Active Console!\n"); + HeapFree(Win32CsrApiHeap, 0, KeyEventRecord); return; } - if( Console->Mode & (ENABLE_PROCESSED_INPUT | ENABLE_LINE_INPUT) ) - switch( KeyEventRecord->InputEvent.Event.KeyEvent.uChar.AsciiChar ) - { - case '\r': - // first add the \r - KeyEventRecord->InputEvent.EventType = KEY_EVENT; - updown = KeyEventRecord->InputEvent.Event.KeyEvent.bKeyDown; - KeyEventRecord->Echoed = FALSE; - KeyEventRecord->InputEvent.Event.KeyEvent.wVirtualKeyCode = VK_RETURN; - KeyEventRecord->InputEvent.Event.KeyEvent.uChar.AsciiChar = '\r'; - InsertTailList(&Console->InputEvents, &KeyEventRecord->ListEntry); - Console->WaitingChars++; - KeyEventRecord = RtlAllocateHeap( Win32CsrApiHeap, 0, sizeof( ConsoleInput ) ); - if( !KeyEventRecord ) - { - DbgPrint( "CSR: Failed to allocate KeyEventRecord\n" ); - return; - } - KeyEventRecord->InputEvent.EventType = KEY_EVENT; - KeyEventRecord->InputEvent.Event.KeyEvent.bKeyDown = updown; - KeyEventRecord->InputEvent.Event.KeyEvent.wVirtualKeyCode = 0; - KeyEventRecord->InputEvent.Event.KeyEvent.wVirtualScanCode = 0; - KeyEventRecord->InputEvent.Event.KeyEvent.uChar.AsciiChar = '\n'; - KeyEventRecord->Fake = TRUE; - } - // add event to the queue + if (0 != (Console->Mode & (ENABLE_PROCESSED_INPUT | ENABLE_LINE_INPUT))) + { + switch(KeyEventRecord->InputEvent.Event.KeyEvent.uChar.AsciiChar) + { + case '\r': + /* first add the \r */ + KeyEventRecord->InputEvent.EventType = KEY_EVENT; + updown = KeyEventRecord->InputEvent.Event.KeyEvent.bKeyDown; + KeyEventRecord->Echoed = FALSE; + KeyEventRecord->InputEvent.Event.KeyEvent.wVirtualKeyCode = VK_RETURN; + KeyEventRecord->InputEvent.Event.KeyEvent.uChar.AsciiChar = '\r'; + InsertTailList(&Console->InputEvents, &KeyEventRecord->ListEntry); + Console->WaitingChars++; + KeyEventRecord = HeapAlloc(Win32CsrApiHeap, 0, sizeof(ConsoleInput)); + if (NULL == KeyEventRecord) + { + DPRINT1("Failed to allocate KeyEventRecord\n"); + return; + } + KeyEventRecord->InputEvent.EventType = KEY_EVENT; + KeyEventRecord->InputEvent.Event.KeyEvent.bKeyDown = updown; + KeyEventRecord->InputEvent.Event.KeyEvent.wVirtualKeyCode = 0; + KeyEventRecord->InputEvent.Event.KeyEvent.wVirtualScanCode = 0; + KeyEventRecord->InputEvent.Event.KeyEvent.uChar.AsciiChar = '\n'; + KeyEventRecord->Fake = TRUE; + break; + } + } + /* add event to the queue */ InsertTailList(&Console->InputEvents, &KeyEventRecord->ListEntry); Console->WaitingChars++; - // if line input mode is enabled, only wake the client on enter key down - if( !(Console->Mode & ENABLE_LINE_INPUT ) || - Console->EarlyReturn || - ( KeyEventRecord->InputEvent.Event.KeyEvent.uChar.AsciiChar == '\n' && - KeyEventRecord->InputEvent.Event.KeyEvent.bKeyDown == FALSE) ) + /* if line input mode is enabled, only wake the client on enter key down */ + if (0 == (Console->Mode & ENABLE_LINE_INPUT) + || Console->EarlyReturn + || ('\n' == KeyEventRecord->InputEvent.Event.KeyEvent.uChar.AsciiChar + && ! KeyEventRecord->InputEvent.Event.KeyEvent.bKeyDown)) { - if( KeyEventRecord->InputEvent.Event.KeyEvent.uChar.AsciiChar == '\n' ) - Console->WaitingLines++; + if ('\n' == KeyEventRecord->InputEvent.Event.KeyEvent.uChar.AsciiChar) + { + Console->WaitingLines++; + } bClientWake = TRUE; - NtSetEvent( Console->ActiveEvent, 0 ); + SetEvent(Console->ActiveEvent); } KeyEventRecord->Echoed = FALSE; - if( Console->Mode & (ENABLE_PROCESSED_INPUT | ENABLE_LINE_INPUT) && - KeyEventRecord->InputEvent.Event.KeyEvent.uChar.AsciiChar == '\b' && - KeyEventRecord->InputEvent.Event.KeyEvent.bKeyDown ) + if (0 != (Console->Mode & (ENABLE_PROCESSED_INPUT | ENABLE_LINE_INPUT)) + && '\b' == KeyEventRecord->InputEvent.Event.KeyEvent.uChar.AsciiChar + && KeyEventRecord->InputEvent.Event.KeyEvent.bKeyDown) { - // walk the input queue looking for a char to backspace - for( TempInput = (ConsoleInput *)Console->InputEvents.Blink; - TempInput != (ConsoleInput *)&Console->InputEvents && - (TempInput->InputEvent.EventType != KEY_EVENT || - TempInput->InputEvent.Event.KeyEvent.bKeyDown == FALSE || - TempInput->InputEvent.Event.KeyEvent.uChar.AsciiChar == '\b' ); - TempInput = (ConsoleInput *)TempInput->ListEntry.Blink ); - // if we found one, delete it, otherwise, wake the client - if( TempInput != (ConsoleInput *)&Console->InputEvents ) + /* walk the input queue looking for a char to backspace */ + for (TempInput = (ConsoleInput *) Console->InputEvents.Blink; + TempInput != (ConsoleInput *) &Console->InputEvents + && (KEY_EVENT == TempInput->InputEvent.EventType + || ! TempInput->InputEvent.Event.KeyEvent.bKeyDown + || '\b' == TempInput->InputEvent.Event.KeyEvent.uChar.AsciiChar); + TempInput = (ConsoleInput *) TempInput->ListEntry.Blink) + { + /* NOP */; + } + /* if we found one, delete it, otherwise, wake the client */ + if (TempInput != (ConsoleInput *) &Console->InputEvents) { - // delete previous key in queue, maybe echo backspace to screen, and do not place backspace on queue + /* delete previous key in queue, maybe echo backspace to screen, and do not place backspace on queue */ RemoveEntryList(&TempInput->ListEntry); - if( TempInput->Echoed ) - CsrpWriteConsole( Console->ActiveBuffer, &KeyEventRecord->InputEvent.Event.KeyEvent.uChar.AsciiChar, 1, TRUE ); - RtlFreeHeap( Win32CsrApiHeap, 0, TempInput ); + if (TempInput->Echoed) + { + ConioWriteConsole(Console, Console->ActiveBuffer, + &KeyEventRecord->InputEvent.Event.KeyEvent.uChar.AsciiChar, + 1, TRUE); + } + HeapFree(Win32CsrApiHeap, 0, TempInput); RemoveEntryList(&KeyEventRecord->ListEntry); - RtlFreeHeap( Win32CsrApiHeap, 0, KeyEventRecord ); + HeapFree(Win32CsrApiHeap, 0, KeyEventRecord); Console->WaitingChars -= 2; } - else { - NtSetEvent( Console->ActiveEvent, 0 ); - } + else + { + SetEvent(Console->ActiveEvent); + } } - else { - // echo chars if we are supposed to and client is waiting for some - if( ( Console->Mode & ENABLE_ECHO_INPUT ) && Console->EchoCount && - KeyEventRecord->InputEvent.Event.KeyEvent.uChar.AsciiChar && - KeyEventRecord->InputEvent.Event.KeyEvent.bKeyDown == TRUE && - KeyEventRecord->InputEvent.Event.KeyEvent.uChar.AsciiChar != '\r' ) - { - // mark the char as already echoed - CsrpWriteConsole( Console->ActiveBuffer, &KeyEventRecord->InputEvent.Event.KeyEvent.uChar.AsciiChar, 1, TRUE ); - Console->EchoCount--; - KeyEventRecord->Echoed = TRUE; - } - } + else + { + /* echo chars if we are supposed to and client is waiting for some */ + if (0 != (Console->Mode & ENABLE_ECHO_INPUT) && Console->EchoCount + && KeyEventRecord->InputEvent.Event.KeyEvent.uChar.AsciiChar + && KeyEventRecord->InputEvent.Event.KeyEvent.bKeyDown + && '\r' != KeyEventRecord->InputEvent.Event.KeyEvent.uChar.AsciiChar) + { + /* mark the char as already echoed */ + ConioWriteConsole(Console, Console->ActiveBuffer, + &KeyEventRecord->InputEvent.Event.KeyEvent.uChar.AsciiChar, + 1, TRUE); + Console->EchoCount--; + KeyEventRecord->Echoed = TRUE; + } + } + /* Console->WaitingChars++; */ - if( bClientWake || !(Console->Mode & ENABLE_LINE_INPUT) ) { - NtSetEvent( Console->ActiveEvent, 0 ); - } + if (bClientWake || 0 == (Console->Mode & ENABLE_LINE_INPUT)) + { + SetEvent(Console->ActiveEvent); + } } -static DWORD CsrpGetShiftState( PBYTE KeyState ) { +STATIC DWORD FASTCALL +ConioGetShiftState(PBYTE KeyState) +{ int i; DWORD ssOut = 0; - for( i = 0; i < 0x100; i++ ) { - if( KeyState[i] & 0x80 ) { - UINT vk = MapVirtualKeyExW( i, 3, 0 ) & 0xff; - switch( vk ) { - case VK_LSHIFT: - case VK_RSHIFT: - case VK_SHIFT: - ssOut |= SHIFT_PRESSED; - break; + for (i = 0; i < 0x100; i++) + { + if (0 != (KeyState[i] & 0x80)) + { + UINT vk = MapVirtualKeyExW(i, 3, 0) & 0xff; + switch(vk) + { + case VK_LSHIFT: + case VK_RSHIFT: + case VK_SHIFT: + ssOut |= SHIFT_PRESSED; + break; - case VK_LCONTROL: - case VK_CONTROL: - ssOut |= LEFT_CTRL_PRESSED; - break; + case VK_LCONTROL: + case VK_CONTROL: + ssOut |= LEFT_CTRL_PRESSED; + break; - case VK_RCONTROL: - ssOut |= RIGHT_CTRL_PRESSED | ENHANCED_KEY; - break; + case VK_RCONTROL: + ssOut |= RIGHT_CTRL_PRESSED | ENHANCED_KEY; + break; - case VK_LMENU: - case VK_MENU: - ssOut |= LEFT_ALT_PRESSED; - break; + case VK_LMENU: + case VK_MENU: + ssOut |= LEFT_ALT_PRESSED; + break; - case VK_RMENU: - ssOut |= RIGHT_ALT_PRESSED | ENHANCED_KEY; - break; + case VK_RMENU: + ssOut |= RIGHT_ALT_PRESSED | ENHANCED_KEY; + break; - case VK_CAPITAL: - ssOut |= CAPSLOCK_ON; - break; + case VK_CAPITAL: + ssOut |= CAPSLOCK_ON; + break; - case VK_NUMLOCK: - ssOut |= NUMLOCK_ON; - break; + case VK_NUMLOCK: + ssOut |= NUMLOCK_ON; + break; - case VK_SCROLL: - ssOut |= SCROLLLOCK_ON; - break; - } + case VK_SCROLL: + ssOut |= SCROLLLOCK_ON; + break; + } + } } - } return ssOut; } -void STDCALL -CsrProcessKey(MSG *msg, PCSRSS_CONSOLE Console) +VOID STDCALL +ConioProcessKey(MSG *msg, PCSRSS_CONSOLE Console, BOOL TextMode) { - static PCSRSS_CONSOLE SwapConsole = 0; /* console we are thinking about swapping with */ static BYTE KeyState[256] = { 0 }; /* MSDN mentions that you should use the last virtual key code received * when putting a virtual key identity to a WM_CHAR message since multiple @@ -1394,8 +1184,6 @@ CsrProcessKey(MSG *msg, PCSRSS_CONSOLE Console) UINT VirtualScanCode; BOOL Down = FALSE; INPUT_RECORD er; - NTSTATUS Status; - IO_STATUS_BLOCK Iosb; ULONG ResultSize = 0; RepeatCount = 1; @@ -1404,7 +1192,7 @@ CsrProcessKey(MSG *msg, PCSRSS_CONSOLE Console) msg->message == WM_SYSKEYDOWN || msg->message == WM_SYSCHAR; GetKeyboardState(KeyState); - ShiftState = CsrpGetShiftState(KeyState); + ShiftState = ConioGetShiftState(KeyState); if (msg->message == WM_CHAR || msg->message == WM_SYSCHAR) { @@ -1428,12 +1216,17 @@ CsrProcessKey(MSG *msg, PCSRSS_CONSOLE Console) } if (UnicodeChar) - RtlUnicodeToOemN(&AsciiChar, - 1, - &ResultSize, - &UnicodeChar, - sizeof(WCHAR)); - if (!ResultSize) AsciiChar = 0; + { + RtlUnicodeToOemN(&AsciiChar, + 1, + &ResultSize, + &UnicodeChar, + sizeof(WCHAR)); + } + if (0 == ResultSize) + { + AsciiChar = 0; + } er.EventType = KEY_EVENT; er.Event.KeyEvent.bKeyDown = Down; @@ -1442,95 +1235,37 @@ CsrProcessKey(MSG *msg, PCSRSS_CONSOLE Console) er.Event.KeyEvent.dwControlKeyState = ShiftState; er.Event.KeyEvent.wVirtualKeyCode = VirtualKeyCode; er.Event.KeyEvent.wVirtualScanCode = VirtualScanCode; - - if (TextMode && ShiftState & (RIGHT_ALT_PRESSED | LEFT_ALT_PRESSED) - && VirtualKeyCode == VK_TAB ) - { - if (Down) + + if (TextMode) + { + if (0 != (ShiftState & (RIGHT_ALT_PRESSED | LEFT_ALT_PRESSED)) + && VK_TAB == VirtualKeyCode) { - ANSI_STRING Title; - void * Buffer; - COORD *pos; - - /* alt-tab, swap consoles */ - /* move SwapConsole to next console, and print its title */ - LOCK; - if (! SwapConsole) + if (Down) { - SwapConsole = ActiveConsole; + TuiSwapConsole(ShiftState & SHIFT_PRESSED ? -1 : 1); } - - SwapConsole = (ShiftState & SHIFT_PRESSED ? SwapConsole->Prev : - SwapConsole->Next); - Title.MaximumLength = RtlUnicodeStringToAnsiSize(&SwapConsole->Title); - Title.Length = 0; - Buffer = RtlAllocateHeap(Win32CsrApiHeap, - 0, - sizeof( COORD ) + Title.MaximumLength); - pos = (COORD *)Buffer; - Title.Buffer = Buffer + sizeof( COORD ); - RtlUnicodeStringToAnsiString(&Title, &SwapConsole->Title, FALSE); - pos->Y = PhysicalConsoleSize.Y / 2; - pos->X = ( PhysicalConsoleSize.X - Title.Length ) / 2; - /* redraw the console to clear off old title */ - CsrDrawConsole(ActiveConsole); - Status = NtDeviceIoControlFile(ConsoleDeviceHandle, - NULL, - NULL, - NULL, - &Iosb, - IOCTL_CONSOLE_WRITE_OUTPUT_CHARACTER, - Buffer, - sizeof(COORD) + Title.Length, - NULL, - 0); - if (! NT_SUCCESS(Status)) - { - DPRINT1( "Error writing to console\n" ); - } - RtlFreeHeap(Win32CsrApiHeap, 0, Buffer); - - UNLOCK; + return; } - - return; - } - else if (TextMode && SwapConsole && VirtualKeyCode == VK_MENU && ! Down) - { - /* alt key released, swap consoles */ - - LOCK; - if (SwapConsole != ActiveConsole) + else if (VK_MENU == VirtualKeyCode && ! Down) { - /* first remove swapconsole from the list */ - SwapConsole->Prev->Next = SwapConsole->Next; - SwapConsole->Next->Prev = SwapConsole->Prev; - /* now insert before activeconsole */ - SwapConsole->Next = ActiveConsole; - SwapConsole->Prev = ActiveConsole->Prev; - ActiveConsole->Prev->Next = SwapConsole; - ActiveConsole->Prev = SwapConsole; + if (TuiSwapConsole(0)) + { + return; + } } - ActiveConsole = SwapConsole; - SwapConsole = 0; - CsrDrawConsole(ActiveConsole); - UNLOCK; - return; } - LOCK; if (NULL == Console) { - UNLOCK; return; } - ConInRec = RtlAllocateHeap(Win32CsrApiHeap, 0, sizeof(ConsoleInput)); + ConInRec = HeapAlloc(Win32CsrApiHeap, 0, sizeof(ConsoleInput)); if (NULL == ConInRec) { - UNLOCK; return; } @@ -1554,152 +1289,166 @@ CsrProcessKey(MSG *msg, PCSRSS_CONSOLE Console) (AsciiChar >= ' ') ? AsciiChar : '.', ShiftState); - if (!ConInRec->Fake || !ConInRec->NotChar) - CsrpProcessChar(Console, ConInRec); + if (! ConInRec->Fake || ! ConInRec->NotChar) + { + ConioProcessChar(Console, ConInRec); + } else - RtlFreeHeap(Win32CsrApiHeap,0,ConInRec); - UNLOCK; + { + HeapFree(Win32CsrApiHeap, 0, ConInRec); + } } -VOID Console_Api( DWORD RefreshEvent ) +VOID +Console_Api(DWORD RefreshEvent) { /* keep reading events from the keyboard and stuffing them into the current console's input queue */ MSG msg; /* This call establishes our message queue */ - PeekMessageW( &msg, 0,0,0, PM_NOREMOVE ); + PeekMessageW(&msg, 0, 0, 0, PM_NOREMOVE); /* This call registers our message queue */ PrivateCsrssRegisterPrimitive(); /* This call turns on the input system in win32k */ PrivateCsrssAcquireOrReleaseInputOwnership(FALSE); - while (TRUE) { - GetMessageW(&msg, 0, 0, 0); - TranslateMessage(&msg); + while (TRUE) + { + GetMessageW(&msg, 0, 0, 0); + TranslateMessage(&msg); - if ((msg.message == WM_CHAR || msg.message == WM_SYSCHAR || - msg.message == WM_KEYDOWN || msg.message == WM_KEYUP || - msg.message == WM_SYSKEYDOWN || msg.message == WM_SYSKEYUP)) { - CsrProcessKey(&msg, ActiveConsole); + if (msg.message == WM_CHAR || msg.message == WM_SYSCHAR || + msg.message == WM_KEYDOWN || msg.message == WM_KEYUP || + msg.message == WM_SYSKEYDOWN || msg.message == WM_SYSKEYUP) + { + ConioProcessKey(&msg, TuiGetFocusConsole(), TRUE); + } } - } - PrivateCsrssAcquireOrReleaseInputOwnership( TRUE ); + PrivateCsrssAcquireOrReleaseInputOwnership(TRUE); } CSR_API(CsrGetScreenBufferInfo) { - NTSTATUS Status; - PCSRSS_SCREEN_BUFFER Buff; - PCONSOLE_SCREEN_BUFFER_INFO pInfo; - IO_STATUS_BLOCK Iosb; + NTSTATUS Status; + PCSRSS_SCREEN_BUFFER Buff; + PCONSOLE_SCREEN_BUFFER_INFO pInfo; - DPRINT("CsrGetScreenBufferInfo\n"); + DPRINT("CsrGetScreenBufferInfo\n"); - Reply->Header.MessageSize = sizeof(CSRSS_API_REPLY); - Reply->Header.DataSize = sizeof(CSRSS_API_REPLY) - - sizeof(LPC_MESSAGE); + Reply->Header.MessageSize = sizeof(CSRSS_API_REPLY); + Reply->Header.DataSize = sizeof(CSRSS_API_REPLY) - sizeof(LPC_MESSAGE); - LOCK; - if( !NT_SUCCESS( Win32CsrGetObject( ProcessData, Request->Data.ScreenBufferInfoRequest.ConsoleHandle, - (Object_t **)&Buff ) ) || Buff->Header.Type != CONIO_SCREEN_BUFFER_MAGIC ) - { - UNLOCK; - return Reply->Status = STATUS_INVALID_HANDLE; - } - pInfo = &Reply->Data.ScreenBufferInfoReply.Info; - if(Buff == ActiveConsole->ActiveBuffer && TextMode) - { - Status = NtDeviceIoControlFile( ConsoleDeviceHandle, NULL, NULL, NULL, &Iosb, - IOCTL_CONSOLE_GET_SCREEN_BUFFER_INFO, 0, 0, pInfo, sizeof( *pInfo ) ); - if( !NT_SUCCESS( Status ) ) - DbgPrint( "CSR: Failed to get console info, expect trouble\n" ); - Reply->Status = Status; - } - else { - pInfo->dwSize.X = Buff->MaxX; - pInfo->dwSize.Y = Buff->MaxY; - pInfo->dwCursorPosition.X = Buff->CurrentX - Buff->ShowX; - pInfo->dwCursorPosition.Y = (Buff->CurrentY + Buff->MaxY - Buff->ShowY) % Buff->MaxY; - pInfo->wAttributes = Buff->DefaultAttrib; - pInfo->srWindow.Left = 0; - pInfo->srWindow.Right = Buff->MaxX - 1; - pInfo->srWindow.Top = 0; - pInfo->srWindow.Bottom = Buff->MaxY - 1; - Reply->Status = STATUS_SUCCESS; - } - UNLOCK; - return Reply->Status; + Status = ConioLockScreenBuffer(ProcessData, Request->Data.ScreenBufferInfoRequest.ConsoleHandle, &Buff); + if (! NT_SUCCESS(Status)) + { + return Reply->Status = Status; + } + pInfo = &Reply->Data.ScreenBufferInfoReply.Info; + pInfo->dwSize.X = Buff->MaxX; + pInfo->dwSize.Y = Buff->MaxY; + pInfo->dwCursorPosition.X = Buff->CurrentX - Buff->ShowX; + pInfo->dwCursorPosition.Y = (Buff->CurrentY + Buff->MaxY - Buff->ShowY) % Buff->MaxY; + pInfo->wAttributes = Buff->DefaultAttrib; + pInfo->srWindow.Left = 0; + pInfo->srWindow.Right = Buff->MaxX - 1; + pInfo->srWindow.Top = 0; + pInfo->srWindow.Bottom = Buff->MaxY - 1; + pInfo->dwMaximumWindowSize.X = Buff->MaxX; + pInfo->dwMaximumWindowSize.Y = Buff->MaxY; + ConioUnlockScreenBuffer(Buff); + + Reply->Status = STATUS_SUCCESS; + + return Reply->Status; } CSR_API(CsrSetCursor) { NTSTATUS Status; + PCSRSS_CONSOLE Console; PCSRSS_SCREEN_BUFFER Buff; - CONSOLE_SCREEN_BUFFER_INFO Info; - IO_STATUS_BLOCK Iosb; - SMALL_RECT UpdateRect; + LONG OldCursorX, OldCursorY; DPRINT("CsrSetCursor\n"); + Status = ConioConsoleFromProcessData(ProcessData, &Console); + if (! NT_SUCCESS(Status)) + { + return Reply->Status = Status; + } + Reply->Header.MessageSize = sizeof(CSRSS_API_REPLY); Reply->Header.DataSize = sizeof(CSRSS_API_REPLY) - sizeof(LPC_MESSAGE); - LOCK; - if( !NT_SUCCESS( Win32CsrGetObject( ProcessData, Request->Data.SetCursorRequest.ConsoleHandle, - (Object_t **)&Buff ) ) || Buff->Header.Type != CONIO_SCREEN_BUFFER_MAGIC ) + Status = ConioLockScreenBuffer(ProcessData, Request->Data.SetCursorRequest.ConsoleHandle, &Buff); + if (! NT_SUCCESS(Status)) { - UNLOCK; - return Reply->Status = STATUS_INVALID_HANDLE; - } - RtlEnterCriticalSection(&(Buff->Lock)); - Info.dwCursorPosition = Request->Data.SetCursorRequest.Position; - Info.wAttributes = Buff->DefaultAttrib; - - CsrpPhysicalToLogical(Buff, Buff->CurrentX, Buff->CurrentY, - &(UpdateRect.Left), &(UpdateRect.Top)); - Buff->CurrentX = Info.dwCursorPosition.X + Buff->ShowX; - Buff->CurrentY = (Info.dwCursorPosition.Y + Buff->ShowY) % Buff->MaxY; - if (! TextMode && ProcessData->Console->ActiveBuffer == Buff) - { - /* Redraw char at old position (removes cursor) */ - UpdateRect.Right = UpdateRect.Left; - UpdateRect.Bottom = UpdateRect.Top; - CsrpDrawRegion(Buff->Console, UpdateRect); - /* Redraw char at new position (shows cursor) */ - CsrpPhysicalToLogical(Buff, Buff->CurrentX, Buff->CurrentY, - &(UpdateRect.Left), &(UpdateRect.Top)); - UpdateRect.Right = UpdateRect.Left; - UpdateRect.Bottom = UpdateRect.Top; - CsrpDrawRegion(Buff->Console, UpdateRect); - } - else if (TextMode && Buff == ActiveConsole->ActiveBuffer) - { - Status = NtDeviceIoControlFile(ConsoleDeviceHandle, NULL, NULL, NULL, &Iosb, - IOCTL_CONSOLE_SET_SCREEN_BUFFER_INFO, &Info, - sizeof(Info), 0, 0); - if (! NT_SUCCESS(Status)) + if (NULL != Console) { - DbgPrint( "CSR: Failed to set console info, expect trouble\n" ); + ConioUnlockConsole(Console); + } + return Reply->Status = Status; + } + + ConioPhysicalToLogical(Buff, Buff->CurrentX, Buff->CurrentY, &OldCursorX, &OldCursorY); + Buff->CurrentX = Request->Data.SetCursorRequest.Position.X + Buff->ShowX; + Buff->CurrentY = (Request->Data.SetCursorRequest.Position.Y + Buff->ShowY) % Buff->MaxY; + if (NULL != Console && Buff == Console->ActiveBuffer) + { + if (! ConioSetScreenInfo(Console, Buff, OldCursorX, OldCursorY)) + { + ConioUnlockScreenBuffer(Buff); + return Reply->Status = STATUS_UNSUCCESSFUL; } } - RtlLeaveCriticalSection(&(Buff->Lock)); - UNLOCK; + ConioUnlockScreenBuffer(Buff); + if (NULL != Console) + { + ConioUnlockConsole(Console); + } - return Reply->Status = Status; + return Reply->Status = STATUS_SUCCESS; +} + +STATIC FASTCALL VOID +ConioComputeUpdateRect(PCSRSS_SCREEN_BUFFER Buff, RECT *UpdateRect, COORD *Start, UINT Length) +{ + if (Buff->MaxX <= Start->X + Length) + { + UpdateRect->left = 0; + } + else + { + UpdateRect->left = Start->X; + } + if (Buff->MaxX <= Start->X + Length) + { + UpdateRect->right = Buff->MaxX - 1; + } + else + { + UpdateRect->right = Start->X + Length - 1; + } + UpdateRect->top = Start->Y; + UpdateRect->bottom = Start->Y+ (Start->X + Length - 1) / Buff->MaxX; + if (Buff->MaxY <= UpdateRect->bottom) + { + UpdateRect->bottom = Buff->MaxY - 1; + } } CSR_API(CsrWriteConsoleOutputChar) { + NTSTATUS Status; PBYTE String = Request->Data.WriteConsoleOutputCharRequest.String; PBYTE Buffer; + PCSRSS_CONSOLE Console; PCSRSS_SCREEN_BUFFER Buff; DWORD X, Y, Length; - NTSTATUS Status; - IO_STATUS_BLOCK Iosb; - SMALL_RECT UpdateRect; + RECT UpdateRect; DPRINT("CsrWriteConsoleOutputChar\n"); @@ -1715,34 +1464,34 @@ CSR_API(CsrWriteConsoleOutputChar) return Reply->Status = STATUS_INVALID_PARAMETER; } - LOCK; - if (! NT_SUCCESS(Win32CsrGetObject(ProcessData, - Request->Data.WriteConsoleOutputCharRequest.ConsoleHandle, - (Object_t **) &Buff)) - || Buff->Header.Type != CONIO_SCREEN_BUFFER_MAGIC) + Status = ConioConsoleFromProcessData(ProcessData, &Console); + if (! NT_SUCCESS(Status)) { - UNLOCK; - return Reply->Status = STATUS_INVALID_HANDLE; + return Reply->Status = Status; } + Status = ConioLockScreenBuffer(ProcessData, + Request->Data.WriteConsoleOutputCharRequest.ConsoleHandle, + &Buff); + if (! NT_SUCCESS(Status)) + { + if (NULL != Console) + { + ConioUnlockConsole(Console); + } + return Reply->Status = Status; + } X = Request->Data.WriteConsoleOutputCharRequest.Coord.X + Buff->ShowX; Y = (Request->Data.WriteConsoleOutputCharRequest.Coord.Y + Buff->ShowY) % Buff->MaxY; Length = Request->Data.WriteConsoleOutputCharRequest.Length; Buffer = &Buff->Buffer[2 * (Y * Buff->MaxX + X)]; - CsrpPhysicalToLogical(Buff, X, Y, &(UpdateRect.Left), &(UpdateRect.Top)); while (Length--) { *Buffer = *String++; Buffer += 2; if (++X == Buff->MaxX) { - if (! TextMode && NULL != Buff->Console) - { - CsrpPhysicalToLogical(Buff, X - 1, Y, &(UpdateRect.Right), &(UpdateRect.Bottom)); - CsrpDrawRegion(Buff->Console, UpdateRect); - CsrpPhysicalToLogical(Buff, 0, Y + 1, &(UpdateRect.Left), &(UpdateRect.Top)); - } if (++Y == Buff->MaxY) { Y = 0; @@ -1752,177 +1501,156 @@ CSR_API(CsrWriteConsoleOutputChar) } } - if (! TextMode && NULL != Buff->Console) + if (NULL != Console && Buff == Console->ActiveBuffer) { - CsrpPhysicalToLogical(Buff, X - 1, Y, &(UpdateRect.Right), &(UpdateRect.Bottom)); - CsrpDrawRegion(Buff->Console, UpdateRect); - } - else if (TextMode && ActiveConsole->ActiveBuffer == Buff) - { - Status = NtDeviceIoControlFile(ConsoleDeviceHandle, - NULL, - NULL, - NULL, - &Iosb, - IOCTL_CONSOLE_WRITE_OUTPUT_CHARACTER, - &Request->Data.WriteConsoleOutputCharRequest.Coord, - sizeof(COORD) + Request->Data.WriteConsoleOutputCharRequest.Length, - NULL, - 0); - if (! NT_SUCCESS(Status)) - { - DPRINT1( "Failed to write output chars: %x\n", Status ); - } + ConioComputeUpdateRect(Buff, &UpdateRect, &Request->Data.WriteConsoleOutputCharRequest.Coord, + Request->Data.WriteConsoleOutputCharRequest.Length); + ConioDrawRegion(Console, &UpdateRect); } + Reply->Data.WriteConsoleOutputCharReply.EndCoord.X = X - Buff->ShowX; Reply->Data.WriteConsoleOutputCharReply.EndCoord.Y = (Y + Buff->MaxY - Buff->ShowY) % Buff->MaxY; - UNLOCK; + + ConioUnlockScreenBuffer(Buff); + if (NULL != Console) + { + ConioUnlockConsole(Console); + } + return Reply->Status = STATUS_SUCCESS; } CSR_API(CsrFillOutputChar) { - PCSRSS_SCREEN_BUFFER Buff; - DWORD X, Y, Length; - BYTE Char; - OUTPUT_CHARACTER Character; - PBYTE Buffer; - NTSTATUS Status; - IO_STATUS_BLOCK Iosb; - SMALL_RECT UpdateRect; + NTSTATUS Status; + PCSRSS_CONSOLE Console; + PCSRSS_SCREEN_BUFFER Buff; + DWORD X, Y, Length; + BYTE Char; + PBYTE Buffer; + RECT UpdateRect; - DPRINT("CsrFillOutputChar\n"); + DPRINT("CsrFillOutputChar\n"); - Reply->Header.MessageSize = sizeof(CSRSS_API_REPLY); - Reply->Header.DataSize = sizeof(CSRSS_API_REPLY) - - sizeof(LPC_MESSAGE); + Reply->Header.MessageSize = sizeof(CSRSS_API_REPLY); + Reply->Header.DataSize = sizeof(CSRSS_API_REPLY) - sizeof(LPC_MESSAGE); - LOCK; - if( !NT_SUCCESS( Win32CsrGetObject( ProcessData, Request->Data.FillOutputRequest.ConsoleHandle, (Object_t **)&Buff ) ) || Buff->Header.Type != CONIO_SCREEN_BUFFER_MAGIC ) - { - UNLOCK; - return Reply->Status = STATUS_INVALID_HANDLE; - } - X = Request->Data.FillOutputRequest.Position.X + Buff->ShowX; - Y = (Request->Data.FillOutputRequest.Position.Y + Buff->ShowY) % Buff->MaxY; - Buffer = &Buff->Buffer[2 * (Y * Buff->MaxX + X)]; - Char = Request->Data.FillOutputRequest.Char; - Length = Request->Data.FillOutputRequest.Length; - CsrpPhysicalToLogical(Buff, X, Y, &(UpdateRect.Left), &(UpdateRect.Top)); - while (Length--) - { + Status = ConioConsoleFromProcessData(ProcessData, &Console); + if (! NT_SUCCESS(Status)) + { + return Reply->Status = Status; + } + + Status = ConioLockScreenBuffer(ProcessData, Request->Data.FillOutputRequest.ConsoleHandle, &Buff); + if (! NT_SUCCESS(Status)) + { + if (NULL != Console) + { + ConioUnlockConsole(Console); + } + return Reply->Status = Status; + } + + X = Request->Data.FillOutputRequest.Position.X + Buff->ShowX; + Y = (Request->Data.FillOutputRequest.Position.Y + Buff->ShowY) % Buff->MaxY; + Buffer = &Buff->Buffer[2 * (Y * Buff->MaxX + X)]; + Char = Request->Data.FillOutputRequest.Char; + Length = Request->Data.FillOutputRequest.Length; + while (Length--) + { *Buffer = Char; Buffer += 2; - if( ++X == Buff->MaxX ) - { - if (! TextMode && NULL != Buff->Console) - { - CsrpPhysicalToLogical(Buff, X - 1, Y, &(UpdateRect.Right), &(UpdateRect.Bottom)); - CsrpDrawRegion(Buff->Console, UpdateRect); - CsrpPhysicalToLogical(Buff, 0, Y + 1, &(UpdateRect.Left), &(UpdateRect.Top)); - } - if( ++Y == Buff->MaxY ) - { - Y = 0; - Buffer = Buff->Buffer; - } - X = 0; - } - } - if (! TextMode && NULL != Buff->Console) - { - CsrpPhysicalToLogical(Buff, X - 1, Y, &(UpdateRect.Right), &(UpdateRect.Bottom)); - CsrpDrawRegion(Buff->Console, UpdateRect); - } - else if (TextMode && Buff == ActiveConsole->ActiveBuffer) - { - Character.dwCoord = Request->Data.FillOutputRequest.Position; - Character.cCharacter = Char; - Character.nLength = Request->Data.FillOutputRequest.Length; - Status = NtDeviceIoControlFile(ConsoleDeviceHandle, - NULL, - NULL, - NULL, - &Iosb, - IOCTL_CONSOLE_FILL_OUTPUT_CHARACTER, - &Character, - sizeof(Character), - NULL, - 0); - if (!NT_SUCCESS(Status)) - DPRINT1( "Failed to write output characters to console\n" ); - } - UNLOCK; - return Reply->Status; + if (++X == Buff->MaxX) + { + if (++Y == Buff->MaxY) + { + Y = 0; + Buffer = Buff->Buffer; + } + X = 0; + } + } + + if (NULL != Console && Buff == Console->ActiveBuffer) + { + ConioComputeUpdateRect(Buff, &UpdateRect, &Request->Data.FillOutputRequest.Position, + Request->Data.FillOutputRequest.Length); + ConioDrawRegion(Console, &UpdateRect); + } + + ConioUnlockScreenBuffer(Buff); + if (NULL != Console) + { + ConioUnlockConsole(Console); + } + + return Reply->Status; } CSR_API(CsrReadInputEvent) { - PLIST_ENTRY CurrentEntry; - PCSRSS_CONSOLE Console; - NTSTATUS Status; - BOOLEAN Done = FALSE; - ConsoleInput *Input; + PLIST_ENTRY CurrentEntry; + PCSRSS_CONSOLE Console; + NTSTATUS Status; + BOOLEAN Done = FALSE; + ConsoleInput *Input; - DPRINT("CsrReadInputEvent\n"); + DPRINT("CsrReadInputEvent\n"); - Reply->Header.MessageSize = sizeof(CSRSS_API_REPLY); - Reply->Header.DataSize = sizeof(CSRSS_API_REPLY) - - sizeof(LPC_MESSAGE); - Reply->Data.ReadInputReply.Event = ProcessData->ConsoleEvent; + Reply->Header.MessageSize = sizeof(CSRSS_API_REPLY); + Reply->Header.DataSize = sizeof(CSRSS_API_REPLY) - sizeof(LPC_MESSAGE); + Reply->Data.ReadInputReply.Event = ProcessData->ConsoleEvent; - LOCK; - Status = Win32CsrGetObject( ProcessData, Request->Data.ReadInputRequest.ConsoleHandle, (Object_t **)&Console ); - if( !NT_SUCCESS( Status ) || (Status = Console->Header.Type == CONIO_CONSOLE_MAGIC ? 0 : STATUS_INVALID_HANDLE)) - { - Reply->Status = Status; - UNLOCK; - return Status; - } + Status = ConioLockConsole(ProcessData, Request->Data.ReadInputRequest.ConsoleHandle, &Console); + if (! NT_SUCCESS(Status)) + { + return Reply->Status = Status; + } - // only get input if there is any - while( Console->InputEvents.Flink != &Console->InputEvents && - !Done ) - { - CurrentEntry = RemoveHeadList(&Console->InputEvents); - Input = CONTAINING_RECORD(CurrentEntry, ConsoleInput, ListEntry); - Done = !Input->Fake; - Reply->Data.ReadInputReply.Input = Input->InputEvent; + /* only get input if there is any */ + while (Console->InputEvents.Flink != &Console->InputEvents && ! Done) + { + CurrentEntry = RemoveHeadList(&Console->InputEvents); + Input = CONTAINING_RECORD(CurrentEntry, ConsoleInput, ListEntry); + Done = !Input->Fake; + Reply->Data.ReadInputReply.Input = Input->InputEvent; - if( Input->InputEvent.EventType == KEY_EVENT ) - { - if( Console->Mode & ENABLE_LINE_INPUT && - Input->InputEvent.Event.KeyEvent.bKeyDown == TRUE && - Input->InputEvent.Event.KeyEvent.uChar.AsciiChar == '\r' ) { - Console->WaitingLines--; - } - Console->WaitingChars--; - } - RtlFreeHeap( Win32CsrApiHeap, 0, Input ); + if (Input->InputEvent.EventType == KEY_EVENT) + { + if (0 != (Console->Mode & ENABLE_LINE_INPUT) + && Input->InputEvent.Event.KeyEvent.bKeyDown + && '\r' == Input->InputEvent.Event.KeyEvent.uChar.AsciiChar) + { + Console->WaitingLines--; + } + Console->WaitingChars--; + } + HeapFree(Win32CsrApiHeap, 0, Input); - Reply->Data.ReadInputReply.MoreEvents = (Console->InputEvents.Flink != &Console->InputEvents) ? TRUE : FALSE; - Status = STATUS_SUCCESS; - Console->EarlyReturn = FALSE; // clear early return - } + Reply->Data.ReadInputReply.MoreEvents = (Console->InputEvents.Flink != &Console->InputEvents); + Status = STATUS_SUCCESS; + Console->EarlyReturn = FALSE; /* clear early return */ + } - if( !Done ) - { - Status = STATUS_PENDING; - Console->EarlyReturn = TRUE; // mark for early return - } + if (! Done) + { + Status = STATUS_PENDING; + Console->EarlyReturn = TRUE; /* mark for early return */ + } - UNLOCK; - return Reply->Status = Status; + ConioUnlockConsole(Console); + + return Reply->Status = Status; } CSR_API(CsrWriteConsoleOutputAttrib) { + PCSRSS_CONSOLE Console; PCSRSS_SCREEN_BUFFER Buff; PUCHAR Buffer, Attribute; - NTSTATUS Status; int X, Y, Length; - IO_STATUS_BLOCK Iosb; - SMALL_RECT UpdateRect; + NTSTATUS Status; + RECT UpdateRect; DPRINT("CsrWriteConsoleOutputAttrib\n"); @@ -1938,35 +1666,35 @@ CSR_API(CsrWriteConsoleOutputAttrib) return Reply->Status = STATUS_INVALID_PARAMETER; } - LOCK; - Status = Win32CsrGetObject(ProcessData, - Request->Data.WriteConsoleOutputAttribRequest.ConsoleHandle, - (Object_t **) &Buff); - if (! NT_SUCCESS(Status) - || (Status = Buff->Header.Type == CONIO_SCREEN_BUFFER_MAGIC ? 0 : STATUS_INVALID_HANDLE )) + Status = ConioConsoleFromProcessData(ProcessData, &Console); + if (! NT_SUCCESS(Status)) { - Reply->Status = Status; - UNLOCK; - return Status; + return Reply->Status = Status; } + + Status = ConioLockScreenBuffer(ProcessData, + Request->Data.WriteConsoleOutputAttribRequest.ConsoleHandle, + &Buff); + if (! NT_SUCCESS(Status)) + { + if (NULL != Console) + { + ConioUnlockConsole(Console); + } + return Reply->Status = Status; + } + X = Request->Data.WriteConsoleOutputAttribRequest.Coord.X + Buff->ShowX; Y = (Request->Data.WriteConsoleOutputAttribRequest.Coord.Y + Buff->ShowY) % Buff->MaxY; Length = Request->Data.WriteConsoleOutputAttribRequest.Length; Buffer = &Buff->Buffer[2 * (Y * Buff->MaxX + X) + 1]; Attribute = Request->Data.WriteConsoleOutputAttribRequest.String; - CsrpPhysicalToLogical(Buff, X, Y, &(UpdateRect.Left), &(UpdateRect.Top)); while (Length--) { *Buffer = *Attribute++; Buffer += 2; - if( ++X == Buff->MaxX ) + if (++X == Buff->MaxX) { - if (! TextMode && NULL != Buff->Console) - { - CsrpPhysicalToLogical(Buff, X - 1, Y, &(UpdateRect.Right), &(UpdateRect.Bottom)); - CsrpDrawRegion(Buff->Console, UpdateRect); - CsrpPhysicalToLogical(Buff, 0, Y + 1, &(UpdateRect.Left), &(UpdateRect.Top)); - } if (++Y == Buff->MaxY) { Y = 0; @@ -1976,370 +1704,394 @@ CSR_API(CsrWriteConsoleOutputAttrib) } } - if (! TextMode && NULL != Buff->Console) + if (NULL != Console && Buff == Console->ActiveBuffer) { - CsrpPhysicalToLogical(Buff, X - 1, Y, &(UpdateRect.Right), &(UpdateRect.Bottom)); - CsrpDrawRegion(Buff->Console, UpdateRect); + ConioComputeUpdateRect(Buff, &UpdateRect, &Request->Data.WriteConsoleOutputAttribRequest.Coord, + Request->Data.WriteConsoleOutputAttribRequest.Length); + ConioDrawRegion(Console, &UpdateRect); } - else if (TextMode && Buff == ActiveConsole->ActiveBuffer) + + if (NULL != Console) { - Status = NtDeviceIoControlFile(ConsoleDeviceHandle, - NULL, - NULL, - NULL, - &Iosb, - IOCTL_CONSOLE_WRITE_OUTPUT_ATTRIBUTE, - &Request->Data.WriteConsoleOutputAttribRequest.Coord, - Request->Data.WriteConsoleOutputAttribRequest.Length + - sizeof(COORD), - NULL, - 0); - if (! NT_SUCCESS(Status)) - { - DPRINT1( "Failed to write output attributes to console\n" ); - } + ConioUnlockConsole(Console); } Reply->Data.WriteConsoleOutputAttribReply.EndCoord.X = Buff->CurrentX - Buff->ShowX; - Reply->Data.WriteConsoleOutputAttribReply.EndCoord.Y = ( Buff->CurrentY + Buff->MaxY - Buff->ShowY ) % Buff->MaxY; - UNLOCK; + Reply->Data.WriteConsoleOutputAttribReply.EndCoord.Y = (Buff->CurrentY + Buff->MaxY - Buff->ShowY) % Buff->MaxY; + + ConioUnlockScreenBuffer(Buff); return Reply->Status = STATUS_SUCCESS; } CSR_API(CsrFillOutputAttrib) { - OUTPUT_ATTRIBUTE Attribute; - PCSRSS_SCREEN_BUFFER Buff; - PCHAR Buffer; - NTSTATUS Status; - int X, Y, Length; - IO_STATUS_BLOCK Iosb; - UCHAR Attr; - SMALL_RECT UpdateRect; + PCSRSS_SCREEN_BUFFER Buff; + PCHAR Buffer; + NTSTATUS Status; + int X, Y, Length; + UCHAR Attr; + RECT UpdateRect; + PCSRSS_CONSOLE Console; - DPRINT("CsrFillOutputAttrib\n"); + DPRINT("CsrFillOutputAttrib\n"); + + Status = ConioConsoleFromProcessData(ProcessData, &Console); + if (! NT_SUCCESS(Status)) + { + return Reply->Status = Status; + } - Reply->Header.MessageSize = sizeof(CSRSS_API_REPLY); - Reply->Header.DataSize = sizeof(CSRSS_API_REPLY) - - sizeof(LPC_MESSAGE); - LOCK; - Status = Win32CsrGetObject( ProcessData, Request->Data.FillOutputAttribRequest.ConsoleHandle, (Object_t **)&Buff ); - if( !NT_SUCCESS( Status ) || (Status = Buff->Header.Type == CONIO_SCREEN_BUFFER_MAGIC ? 0 : STATUS_INVALID_HANDLE )) - { - Reply->Status = Status; - UNLOCK; - return Status; - } - X = Request->Data.FillOutputAttribRequest.Coord.X + Buff->ShowX; - Y = (Request->Data.FillOutputAttribRequest.Coord.Y + Buff->ShowY) % Buff->MaxY; - Length = Request->Data.FillOutputAttribRequest.Length; - Attr = Request->Data.FillOutputAttribRequest.Attribute; - Buffer = &Buff->Buffer[(Y * Buff->MaxX * 2) + (X * 2) + 1]; - UpdateRect.Left = X; - UpdateRect.Top = Y; - while(Length--) - { + Reply->Header.MessageSize = sizeof(CSRSS_API_REPLY); + Reply->Header.DataSize = sizeof(CSRSS_API_REPLY) - sizeof(LPC_MESSAGE); + Status = ConioLockScreenBuffer(ProcessData, Request->Data.FillOutputAttribRequest.ConsoleHandle, &Buff); + if (! NT_SUCCESS(Status)) + { + if (NULL != Console) + { + ConioUnlockConsole(Console); + } + return Reply->Status = Status; + } + + X = Request->Data.FillOutputAttribRequest.Coord.X + Buff->ShowX; + Y = (Request->Data.FillOutputAttribRequest.Coord.Y + Buff->ShowY) % Buff->MaxY; + Length = Request->Data.FillOutputAttribRequest.Length; + Attr = Request->Data.FillOutputAttribRequest.Attribute; + Buffer = &Buff->Buffer[(Y * Buff->MaxX * 2) + (X * 2) + 1]; + while (Length--) + { *Buffer = Attr; Buffer += 2; - if( ++X == Buff->MaxX ) - { - if (! TextMode && NULL != Buff->Console) - { - UpdateRect.Right = X - 1; - UpdateRect.Bottom = Y; - CsrpDrawRegion(Buff->Console, UpdateRect); - UpdateRect.Left = 0; - UpdateRect.Top = Y + 1; - } - if( ++Y == Buff->MaxY ) - { - Y = 0; - Buffer = Buff->Buffer + 1; - UpdateRect.Top = 0; - } - X = 0; - } - } - UpdateRect.Right = X - 1; - UpdateRect.Bottom = Y; - if (! TextMode && NULL != Buff->Console) - { - CsrpDrawRegion(Buff->Console, UpdateRect); - } - else if (TextMode && Buff == ActiveConsole->ActiveBuffer) - { - Attribute.wAttribute = Attr; - Attribute.nLength = Request->Data.FillOutputAttribRequest.Length; - Attribute.dwCoord = Request->Data.FillOutputAttribRequest.Coord; - Status = NtDeviceIoControlFile(ConsoleDeviceHandle, - NULL, - NULL, - NULL, - &Iosb, - IOCTL_CONSOLE_FILL_OUTPUT_ATTRIBUTE, - &Attribute, - sizeof(OUTPUT_ATTRIBUTE), - NULL, - 0); - if( !NT_SUCCESS( Status ) ) - DPRINT1( "Failed to fill output attributes to console\n" ); - } - UNLOCK; - return Reply->Status = STATUS_SUCCESS; + if (++X == Buff->MaxX) + { + if (++Y == Buff->MaxY) + { + Y = 0; + Buffer = Buff->Buffer + 1; + } + X = 0; + } + } + + if (NULL != Console && Buff == Console->ActiveBuffer) + { + ConioComputeUpdateRect(Buff, &UpdateRect, &Request->Data.FillOutputAttribRequest.Coord, + Request->Data.FillOutputAttribRequest.Length); + ConioDrawRegion(Console, &UpdateRect); + } + + ConioUnlockScreenBuffer(Buff); + if (NULL != Console) + { + ConioUnlockConsole(Console); + } + + return Reply->Status = STATUS_SUCCESS; } CSR_API(CsrGetCursorInfo) { - PCSRSS_SCREEN_BUFFER Buff; - NTSTATUS Status; + PCSRSS_SCREEN_BUFFER Buff; + NTSTATUS Status; - DPRINT("CsrGetCursorInfo\n"); + DPRINT("CsrGetCursorInfo\n"); - Reply->Header.MessageSize = sizeof(CSRSS_API_REPLY); - Reply->Header.DataSize = sizeof(CSRSS_API_REPLY) - - sizeof(LPC_MESSAGE); - LOCK; - Status = Win32CsrGetObject( ProcessData, Request->Data.GetCursorInfoRequest.ConsoleHandle, (Object_t **)&Buff ); - if( !NT_SUCCESS( Status ) || (Status = Buff->Header.Type == CONIO_SCREEN_BUFFER_MAGIC ? 0 : STATUS_INVALID_HANDLE )) - { - Reply->Status = Status; - UNLOCK; - return Status; - } - Reply->Data.GetCursorInfoReply.Info = Buff->CursorInfo; - UNLOCK; - return Reply->Status = STATUS_SUCCESS; + Reply->Header.MessageSize = sizeof(CSRSS_API_REPLY); + Reply->Header.DataSize = sizeof(CSRSS_API_REPLY) - sizeof(LPC_MESSAGE); + + Status = ConioLockScreenBuffer(ProcessData, Request->Data.GetCursorInfoRequest.ConsoleHandle, &Buff); + if (! NT_SUCCESS(Status)) + { + return Reply->Status = Status; + } + Reply->Data.GetCursorInfoReply.Info = Buff->CursorInfo; + ConioUnlockScreenBuffer(Buff); + + return Reply->Status = STATUS_SUCCESS; } CSR_API(CsrSetCursorInfo) { + PCSRSS_CONSOLE Console; PCSRSS_SCREEN_BUFFER Buff; + DWORD Size; + BOOL Visible; NTSTATUS Status; - IO_STATUS_BLOCK Iosb; - SMALL_RECT UpdateRect; DPRINT("CsrSetCursorInfo\n"); Reply->Header.MessageSize = sizeof(CSRSS_API_REPLY); Reply->Header.DataSize = sizeof(CSRSS_API_REPLY) - sizeof(LPC_MESSAGE); - LOCK; - Status = Win32CsrGetObject( ProcessData, - Request->Data.SetCursorInfoRequest.ConsoleHandle, (Object_t **)&Buff ); - if (! NT_SUCCESS(Status) || (Status = Buff->Header.Type == CONIO_SCREEN_BUFFER_MAGIC ? 0 : STATUS_INVALID_HANDLE )) + Status = ConioConsoleFromProcessData(ProcessData, &Console); + if (! NT_SUCCESS(Status)) { - Reply->Status = Status; - UNLOCK; - return Status; + return Reply->Status = Status; } - RtlEnterCriticalSection(&(Buff->Lock)); - Buff->CursorInfo = Request->Data.SetCursorInfoRequest.Info; - if (Buff->CursorInfo.dwSize < 1) + + Status = ConioLockScreenBuffer(ProcessData, Request->Data.SetCursorInfoRequest.ConsoleHandle, &Buff); + if (! NT_SUCCESS(Status)) { - Buff->CursorInfo.dwSize = 1; - } - if (100 < Buff->CursorInfo.dwSize) - { - Buff->CursorInfo.dwSize = 100; - } - if (! TextMode && ProcessData->Console->ActiveBuffer == Buff) - { - CsrpPhysicalToLogical(Buff, Buff->CurrentX, Buff->CurrentY, - &UpdateRect.Left, &UpdateRect.Top); - UpdateRect.Right = UpdateRect.Left; - UpdateRect.Bottom = UpdateRect.Top; - CsrpDrawRegion(ProcessData->Console, UpdateRect); - } - else if (TextMode && Buff == ActiveConsole->ActiveBuffer) - { - Status = NtDeviceIoControlFile( ConsoleDeviceHandle, NULL, NULL, NULL, &Iosb, IOCTL_CONSOLE_SET_CURSOR_INFO, &Buff->CursorInfo, sizeof( Buff->CursorInfo ), 0, 0 ); - if (! NT_SUCCESS(Status)) + if (NULL != Console) { - DbgPrint( "CSR: Failed to set cursor info\n" ); - return Reply->Status = Status; + ConioUnlockConsole(Console); + } + return Reply->Status = Status; + } + + Size = Request->Data.SetCursorInfoRequest.Info.dwSize; + Visible = Request->Data.SetCursorInfoRequest.Info.bVisible; + if (Size < 1) + { + Size = 1; + } + if (100 < Size) + { + Size = 100; + } + + if (Size != Buff->CursorInfo.dwSize + || (Visible && ! Buff->CursorInfo.bVisible) || (! Visible && Buff->CursorInfo.bVisible)) + { + Buff->CursorInfo.dwSize = Size; + Buff->CursorInfo.bVisible = Visible; + + if (NULL != Console && ! ConioSetCursorInfo(Console, Buff)) + { + ConioUnlockScreenBuffer(Buff); + ConioUnlockConsole(Console); + return Reply->Status = STATUS_UNSUCCESSFUL; } } - RtlLeaveCriticalSection(&(Buff->Lock)); - UNLOCK; + + ConioUnlockScreenBuffer(Buff); + if (NULL != Console) + { + ConioUnlockConsole(Console); + } return Reply->Status = STATUS_SUCCESS; } CSR_API(CsrSetTextAttrib) { - NTSTATUS Status; - CONSOLE_SCREEN_BUFFER_INFO ScrInfo; - IO_STATUS_BLOCK Iosb; - PCSRSS_SCREEN_BUFFER Buff; + NTSTATUS Status; + PCSRSS_CONSOLE Console; + PCSRSS_SCREEN_BUFFER Buff; + LONG OldCursorX, OldCursorY; - DPRINT("CsrSetTextAttrib\n"); - - Reply->Header.MessageSize = sizeof(CSRSS_API_REPLY); - Reply->Header.DataSize = sizeof(CSRSS_API_REPLY) - - sizeof(LPC_MESSAGE); - LOCK; - Status = Win32CsrGetObject( ProcessData, Request->Data.SetAttribRequest.ConsoleHandle, (Object_t **)&Buff ); - if( !NT_SUCCESS( Status ) || (Status = Buff->Header.Type == CONIO_SCREEN_BUFFER_MAGIC ? 0 : STATUS_INVALID_HANDLE )) - { - Reply->Status = Status; - UNLOCK; - return Status; - } - Buff->DefaultAttrib = Request->Data.SetAttribRequest.Attrib; - if (! TextMode && Buff == ActiveConsole->ActiveBuffer) - { - ScrInfo.wAttributes = Buff->DefaultAttrib; - ScrInfo.dwCursorPosition.X = Buff->CurrentX - Buff->ShowX; - ScrInfo.dwCursorPosition.Y = ((Buff->CurrentY + Buff->MaxY) - Buff->ShowY) % Buff->MaxY; - Status = NtDeviceIoControlFile( ConsoleDeviceHandle, NULL, NULL, NULL, &Iosb, IOCTL_CONSOLE_SET_SCREEN_BUFFER_INFO, &ScrInfo, sizeof( ScrInfo ), 0, 0 ); - if( !NT_SUCCESS( Status ) ) - { - DbgPrint( "CSR: Failed to set console info\n" ); - UNLOCK; - return Reply->Status = Status; - } - } - UNLOCK; - return Reply->Status = STATUS_SUCCESS; + DPRINT("CsrSetTextAttrib\n"); + + Status = ConioConsoleFromProcessData(ProcessData, &Console); + if (! NT_SUCCESS(Status)) + { + return Reply->Status = Status; + } + + Status = ConioLockScreenBuffer(ProcessData, Request->Data.SetCursorRequest.ConsoleHandle, &Buff); + if (! NT_SUCCESS(Status)) + { + if (NULL != Console) + { + ConioUnlockConsole(Console); + } + return Reply->Status = Status; + } + + ConioPhysicalToLogical(Buff, Buff->CurrentX, Buff->CurrentY, &OldCursorX, &OldCursorY); + + Buff->DefaultAttrib = Request->Data.SetAttribRequest.Attrib; + if (NULL != Console && Buff == Console->ActiveBuffer) + { + if (! ConioSetScreenInfo(Console, Buff, OldCursorX, OldCursorY)) + { + ConioUnlockScreenBuffer(Buff); + ConioUnlockConsole(Console); + return Reply->Status = STATUS_UNSUCCESSFUL; + } + } + + ConioUnlockScreenBuffer(Buff); + if (NULL != Console) + { + ConioUnlockConsole(Console); + } + + return Reply->Status = STATUS_SUCCESS; } CSR_API(CsrSetConsoleMode) { - NTSTATUS Status; - PCSRSS_CONSOLE Console; - PCSRSS_SCREEN_BUFFER Buff; + NTSTATUS Status; + PCSRSS_CONSOLE Console; + PCSRSS_SCREEN_BUFFER Buff; - DPRINT("CsrSetConsoleMode\n"); + DPRINT("CsrSetConsoleMode\n"); - Reply->Header.MessageSize = sizeof(CSRSS_API_REPLY); - Reply->Header.DataSize = sizeof(CSRSS_API_REPLY) - sizeof(LPC_MESSAGE); - LOCK; - Status = Win32CsrGetObject( ProcessData, - Request->Data.SetConsoleModeRequest.ConsoleHandle, - (Object_t **)&Console ); - if( !NT_SUCCESS( Status ) ) - { - Reply->Status = Status; - UNLOCK; - return Status; - } + Reply->Header.MessageSize = sizeof(CSRSS_API_REPLY); + Reply->Header.DataSize = sizeof(CSRSS_API_REPLY) - sizeof(LPC_MESSAGE); + Status = Win32CsrGetObject(ProcessData, + Request->Data.SetConsoleModeRequest.ConsoleHandle, + (Object_t **) &Console); + if (! NT_SUCCESS(Status)) + { + return Reply->Status = Status; + } - Buff = (PCSRSS_SCREEN_BUFFER)Console; - if( Console->Header.Type == CONIO_CONSOLE_MAGIC ) + Buff = (PCSRSS_SCREEN_BUFFER)Console; + if (CONIO_CONSOLE_MAGIC == Console->Header.Type) + { Console->Mode = Request->Data.SetConsoleModeRequest.Mode & CONSOLE_INPUT_MODE_VALID; - else if( Console->Header.Type == CONIO_SCREEN_BUFFER_MAGIC ) + } + else if (CONIO_SCREEN_BUFFER_MAGIC == Console->Header.Type) + { Buff->Mode = Request->Data.SetConsoleModeRequest.Mode & CONSOLE_OUTPUT_MODE_VALID; - else { - Reply->Status = STATUS_INVALID_HANDLE; - UNLOCK; - return Status; - } - UNLOCK; - Reply->Status = STATUS_SUCCESS; - return Reply->Status; + } + else + { + return Reply->Status = STATUS_INVALID_HANDLE; + } + + Reply->Status = STATUS_SUCCESS; + + return Reply->Status; } CSR_API(CsrGetConsoleMode) { - NTSTATUS Status; - PCSRSS_CONSOLE Console; - PCSRSS_SCREEN_BUFFER Buff; /* gee, I really wish I could use an anonymous union here */ + NTSTATUS Status; + PCSRSS_CONSOLE Console; + PCSRSS_SCREEN_BUFFER Buff; /* gee, I really wish I could use an anonymous union here */ - DPRINT("CsrGetConsoleMode\n"); + DPRINT("CsrGetConsoleMode\n"); - Reply->Header.MessageSize = sizeof(CSRSS_API_REPLY); - Reply->Header.DataSize = sizeof(CSRSS_API_REPLY) - sizeof(LPC_MESSAGE); - LOCK; - Status = Win32CsrGetObject( ProcessData, - Request->Data.GetConsoleModeRequest.ConsoleHandle, - (Object_t **)&Console ); - if( !NT_SUCCESS( Status ) ) - { - Reply->Status = Status; - UNLOCK; - return Status; - } - Reply->Status = STATUS_SUCCESS; - Buff = (PCSRSS_SCREEN_BUFFER)Console; - if( Console->Header.Type == CONIO_CONSOLE_MAGIC ) + Reply->Header.MessageSize = sizeof(CSRSS_API_REPLY); + Reply->Header.DataSize = sizeof(CSRSS_API_REPLY) - sizeof(LPC_MESSAGE); + Status = Win32CsrGetObject(ProcessData, Request->Data.GetConsoleModeRequest.ConsoleHandle, + (Object_t **) &Console); + if (! NT_SUCCESS(Status)) + { + return Reply->Status = Status; + } + Reply->Status = STATUS_SUCCESS; + Buff = (PCSRSS_SCREEN_BUFFER) Console; + if (CONIO_CONSOLE_MAGIC == Console->Header.Type) + { Reply->Data.GetConsoleModeReply.ConsoleMode = Console->Mode; - else if( Buff->Header.Type == CONIO_SCREEN_BUFFER_MAGIC ) + } + else if (CONIO_SCREEN_BUFFER_MAGIC == Buff->Header.Type) + { Reply->Data.GetConsoleModeReply.ConsoleMode = Buff->Mode; - else Status = STATUS_INVALID_HANDLE; - UNLOCK; - return Reply->Status; + } + else + { + Reply->Status = STATUS_INVALID_HANDLE; + } + + return Reply->Status; } CSR_API(CsrCreateScreenBuffer) { - PCSRSS_SCREEN_BUFFER Buff; - NTSTATUS Status; + PCSRSS_CONSOLE Console; + PCSRSS_SCREEN_BUFFER Buff; + NTSTATUS Status; - DPRINT("CsrCreateScreenBuffer\n"); + DPRINT("CsrCreateScreenBuffer\n"); - Reply->Header.MessageSize = sizeof( CSRSS_API_REPLY ); - Reply->Header.DataSize = sizeof(CSRSS_API_REPLY) - sizeof(LPC_MESSAGE); + if (ProcessData == NULL) + { + return Reply->Status = STATUS_INVALID_PARAMETER; + } - if (ProcessData == NULL) - { - return(Reply->Status = STATUS_INVALID_PARAMETER); - } + Status = ConioConsoleFromProcessData(ProcessData, &Console); + if (! NT_SUCCESS(Status)) + { + return Reply->Status = Status; + } + if (NULL == Console) + { + return Reply->Status = STATUS_INVALID_HANDLE; + } - Buff = RtlAllocateHeap( Win32CsrApiHeap, 0, sizeof( CSRSS_SCREEN_BUFFER ) ); - if( !Buff ) + Reply->Header.MessageSize = sizeof(CSRSS_API_REPLY); + Reply->Header.DataSize = sizeof(CSRSS_API_REPLY) - sizeof(LPC_MESSAGE); + + Buff = HeapAlloc(Win32CsrApiHeap, 0, sizeof(CSRSS_SCREEN_BUFFER)); + if (NULL == Buff) + { Reply->Status = STATUS_INSUFFICIENT_RESOURCES; - LOCK; - if (TextMode) - { - Status = CsrInitConsoleScreenBuffer(Buff, NULL, PhysicalConsoleSize.X, PhysicalConsoleSize.Y); - } else { - /* FIXME From where do we get the size???? */ - Status = CsrInitConsoleScreenBuffer(Buff, NULL, 80, 25); - } - if( !NT_SUCCESS( Status ) ) + } + + Status = CsrInitConsoleScreenBuffer(Console, Buff); + if(! NT_SUCCESS(Status)) + { Reply->Status = Status; - else { - Status = Win32CsrInsertObject( ProcessData, &Reply->Data.CreateScreenBufferReply.OutputHandle, &Buff->Header ); - if( !NT_SUCCESS( Status ) ) - Reply->Status = Status; - else Reply->Status = STATUS_SUCCESS; - } - UNLOCK; - return Reply->Status; + } + else + { + Reply->Status = Win32CsrInsertObject(ProcessData, &Reply->Data.CreateScreenBufferReply.OutputHandle, &Buff->Header); + } + + ConioUnlockConsole(Console); + + return Reply->Status; } CSR_API(CsrSetScreenBuffer) { - NTSTATUS Status; - PCSRSS_SCREEN_BUFFER Buff; + NTSTATUS Status; + PCSRSS_CONSOLE Console; + PCSRSS_SCREEN_BUFFER Buff; - DPRINT("CsrSetScreenBuffer\n"); + DPRINT("CsrSetScreenBuffer\n"); - Reply->Header.MessageSize = sizeof( CSRSS_API_REPLY ); - Reply->Header.DataSize = sizeof(CSRSS_API_REPLY) - sizeof(LPC_MESSAGE); - LOCK; - Status = Win32CsrGetObject( ProcessData, Request->Data.SetScreenBufferRequest.OutputHandle, (Object_t **)&Buff ); - if( !NT_SUCCESS( Status ) ) - Reply->Status = Status; - else { - // drop reference to old buffer, maybe delete - ProcessData->Console->ActiveBuffer->Console = NULL; - if( !InterlockedDecrement( &ProcessData->Console->ActiveBuffer->Header.ReferenceCount ) ) - ConioDeleteScreenBuffer((Object_t *) ProcessData->Console->ActiveBuffer); - // tie console to new buffer - ProcessData->Console->ActiveBuffer = Buff; - Buff->Console = ProcessData->Console; - // inc ref count on new buffer - InterlockedIncrement( &Buff->Header.ReferenceCount ); - // if the console is active, redraw it - if (! TextMode || ActiveConsole == ProcessData->Console) - CsrDrawConsole(ProcessData->Console); - Reply->Status = STATUS_SUCCESS; - } - UNLOCK; - return Reply->Status; + Status = ConioConsoleFromProcessData(ProcessData, &Console); + if (! NT_SUCCESS(Status)) + { + return Reply->Status = Status; + } + if (NULL == Console) + { + DPRINT1("Trying to set screen buffer for app without console\n"); + return Reply->Status = STATUS_INVALID_HANDLE; + } + + Reply->Header.MessageSize = sizeof(CSRSS_API_REPLY); + Reply->Header.DataSize = sizeof(CSRSS_API_REPLY) - sizeof(LPC_MESSAGE); + + Status = ConioLockScreenBuffer(ProcessData, Request->Data.SetScreenBufferRequest.OutputHandle, &Buff); + if (! NT_SUCCESS(Status)) + { + ConioUnlockConsole(Console); + return Reply->Status; + } + + if (Buff == Console->ActiveBuffer) + { + ConioUnlockScreenBuffer(Buff); + ConioUnlockConsole(Console); + return STATUS_SUCCESS; + } + + /* drop reference to old buffer, maybe delete */ + if (! InterlockedDecrement(&Console->ActiveBuffer->Header.ReferenceCount)) + { + 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 Reply->Status = STATUS_SUCCESS; } CSR_API(CsrSetTitle) @@ -2349,7 +2101,7 @@ CSR_API(CsrSetTitle) DPRINT("CsrSetTitle\n"); - Reply->Header.MessageSize = sizeof( CSRSS_API_REPLY ); + Reply->Header.MessageSize = sizeof(CSRSS_API_REPLY); Reply->Header.DataSize = sizeof(CSRSS_API_REPLY) - sizeof(LPC_MESSAGE); if (Request->Header.DataSize @@ -2360,10 +2112,7 @@ CSR_API(CsrSetTitle) return Reply->Status = STATUS_INVALID_PARAMETER; } - LOCK; - Status = Win32CsrGetObject(ProcessData, - Request->Data.SetTitleRequest.Console, - (Object_t **) &Console); + Status = ConioLockConsole(ProcessData, Request->Data.SetTitleRequest.Console, &Console); if(! NT_SUCCESS(Status)) { Reply->Status = Status; @@ -2373,137 +2122,148 @@ CSR_API(CsrSetTitle) /* copy title to console */ RtlFreeUnicodeString(&Console->Title); RtlCreateUnicodeString(&Console->Title, Request->Data.SetTitleRequest.Title); - if (! TextMode) + if (! ConioChangeTitle(Console)) { - GuiConsoleChangeTitle(Console); + Reply->Status = STATUS_UNSUCCESSFUL; + } + else + { + Reply->Status = STATUS_SUCCESS; } - Reply->Status = STATUS_SUCCESS; } - - UNLOCK; + ConioUnlockConsole(Console); return Reply->Status; } CSR_API(CsrGetTitle) { - NTSTATUS Status; - PCSRSS_CONSOLE Console; + NTSTATUS Status; + PCSRSS_CONSOLE Console; - DPRINT("CsrGetTitle\n"); + DPRINT("CsrGetTitle\n"); - Reply->Header.MessageSize = sizeof (CSRSS_API_REPLY); - Reply->Header.DataSize = - sizeof (CSRSS_API_REPLY) - - sizeof(LPC_MESSAGE); - LOCK; - Status = Win32CsrGetObject ( - ProcessData, - Request->Data.GetTitleRequest.ConsoleHandle, - (Object_t **) & Console - ); - if ( !NT_SUCCESS( Status ) ) - { - Reply->Status = Status; - } - else - { - HANDLE ConsoleHandle = Request->Data.GetTitleRequest.ConsoleHandle; + Reply->Header.MessageSize = sizeof(CSRSS_API_REPLY); + Reply->Header.DataSize = sizeof(CSRSS_API_REPLY) - sizeof(LPC_MESSAGE); + Status = ConioLockConsole(ProcessData, + Request->Data.GetTitleRequest.ConsoleHandle, + &Console); + if (! NT_SUCCESS(Status)) + { + DPRINT1("Can't get console\n"); + return Reply->Status = Status; + } - /* Copy title of the console to the user title buffer */ - RtlZeroMemory ( - & Reply->Data.GetTitleReply, - sizeof (CSRSS_GET_TITLE_REPLY) - ); - Reply->Data.GetTitleReply.ConsoleHandle = ConsoleHandle; - Reply->Data.GetTitleReply.Length = Console->Title.Length; - wcscpy (Reply->Data.GetTitleReply.Title, Console->Title.Buffer); - Reply->Header.MessageSize += Console->Title.Length; - Reply->Header.DataSize += Console->Title.Length; - Reply->Status = STATUS_SUCCESS; - } - UNLOCK; - return Reply->Status; + /* Copy title of the console to the user title buffer */ + RtlZeroMemory(&Reply->Data.GetTitleReply, sizeof(CSRSS_GET_TITLE_REPLY)); + Reply->Data.GetTitleReply.ConsoleHandle = Request->Data.GetTitleRequest.ConsoleHandle; + Reply->Data.GetTitleReply.Length = Console->Title.Length; + wcscpy (Reply->Data.GetTitleReply.Title, Console->Title.Buffer); + Reply->Header.MessageSize += Console->Title.Length; + Reply->Header.DataSize += Console->Title.Length; + Reply->Status = STATUS_SUCCESS; + + ConioUnlockConsole(Console); + + return Reply->Status; } CSR_API(CsrWriteConsoleOutput) { - SHORT i, X, Y, SizeX, SizeY; - PCSRSS_SCREEN_BUFFER Buff; - SMALL_RECT ScreenBuffer; - CHAR_INFO* CurCharInfo; - SMALL_RECT WriteRegion; - CHAR_INFO* CharInfo; - COORD BufferCoord; - COORD BufferSize; - NTSTATUS Status; - DWORD Offset; - DWORD PSize; + SHORT i, X, Y, SizeX, SizeY; + PCSRSS_CONSOLE Console; + PCSRSS_SCREEN_BUFFER Buff; + RECT ScreenBuffer; + CHAR_INFO* CurCharInfo; + RECT WriteRegion; + CHAR_INFO* CharInfo; + COORD BufferCoord; + COORD BufferSize; + NTSTATUS Status; + DWORD Offset; + DWORD PSize; - DPRINT("CsrWriteConsoleOutput\n"); + DPRINT("CsrWriteConsoleOutput\n"); - Reply->Header.MessageSize = sizeof(CSRSS_API_REPLY); - Reply->Header.DataSize = sizeof(CSRSS_API_REPLY) - sizeof(LPC_MESSAGE); - LOCK; - Status = Win32CsrGetObject( ProcessData, Request->Data.WriteConsoleOutputRequest.ConsoleHandle, (Object_t **)&Buff ); - if( !NT_SUCCESS( Status ) || (Status = Buff->Header.Type == CONIO_SCREEN_BUFFER_MAGIC ? STATUS_SUCCESS : STATUS_INVALID_HANDLE )) - { - Reply->Status = Status; - UNLOCK; - return Status; - } + Status = ConioConsoleFromProcessData(ProcessData, &Console); + if (! NT_SUCCESS(Status)) + { + return Reply->Status = Status; + } - BufferSize = Request->Data.WriteConsoleOutputRequest.BufferSize; - PSize = BufferSize.X * BufferSize.Y * sizeof(CHAR_INFO); - BufferCoord = Request->Data.WriteConsoleOutputRequest.BufferCoord; - CharInfo = Request->Data.WriteConsoleOutputRequest.CharInfo; - if (((PVOID)CharInfo < ProcessData->CsrSectionViewBase) || - (((PVOID)CharInfo + PSize) > - (ProcessData->CsrSectionViewBase + ProcessData->CsrSectionViewSize))) - { - UNLOCK; - Reply->Status = STATUS_ACCESS_VIOLATION; - return(Reply->Status); - } - WriteRegion = Request->Data.WriteConsoleOutputRequest.WriteRegion; + Reply->Header.MessageSize = sizeof(CSRSS_API_REPLY); + Reply->Header.DataSize = sizeof(CSRSS_API_REPLY) - sizeof(LPC_MESSAGE); + Status = ConioLockScreenBuffer(ProcessData, + Request->Data.WriteConsoleOutputRequest.ConsoleHandle, + &Buff); + if (! NT_SUCCESS(Status)) + { + if (NULL != Console) + { + ConioUnlockConsole(Console); + } + return Reply->Status = Status; + } - SizeY = RtlRosMin(BufferSize.Y - BufferCoord.Y, CsrpRectHeight(WriteRegion)); - SizeX = RtlRosMin(BufferSize.X - BufferCoord.X, CsrpRectWidth(WriteRegion)); - WriteRegion.Bottom = WriteRegion.Top + SizeY - 1; - WriteRegion.Right = WriteRegion.Left + SizeX - 1; + BufferSize = Request->Data.WriteConsoleOutputRequest.BufferSize; + PSize = BufferSize.X * BufferSize.Y * sizeof(CHAR_INFO); + BufferCoord = Request->Data.WriteConsoleOutputRequest.BufferCoord; + CharInfo = Request->Data.WriteConsoleOutputRequest.CharInfo; + if (((PVOID)CharInfo < ProcessData->CsrSectionViewBase) || + (((PVOID)CharInfo + PSize) > + (ProcessData->CsrSectionViewBase + ProcessData->CsrSectionViewSize))) + { + ConioUnlockScreenBuffer(Buff); + ConioUnlockConsole(Console); + return Reply->Status = STATUS_ACCESS_VIOLATION; + } + WriteRegion.left = Request->Data.WriteConsoleOutputRequest.WriteRegion.Left; + WriteRegion.top = Request->Data.WriteConsoleOutputRequest.WriteRegion.Top; + WriteRegion.right = Request->Data.WriteConsoleOutputRequest.WriteRegion.Right; + WriteRegion.bottom = Request->Data.WriteConsoleOutputRequest.WriteRegion.Bottom; - /* Make sure WriteRegion is inside the screen buffer */ - CsrpInitRect(ScreenBuffer, 0, 0, Buff->MaxY - 1, Buff->MaxX - 1); - if (!CsrpGetIntersection(&WriteRegion, ScreenBuffer, WriteRegion)) - { - UNLOCK; - /* It is okay to have a WriteRegion completely outside the screen buffer. - No data is written then. */ - return (Reply->Status = STATUS_SUCCESS); - } + SizeY = RtlRosMin(BufferSize.Y - BufferCoord.Y, ConioRectHeight(&WriteRegion)); + SizeX = RtlRosMin(BufferSize.X - BufferCoord.X, ConioRectWidth(&WriteRegion)); + WriteRegion.bottom = WriteRegion.top + SizeY - 1; + WriteRegion.right = WriteRegion.left + SizeX - 1; - for ( i = 0, Y = WriteRegion.Top; Y <= WriteRegion.Bottom; i++, Y++ ) - { - CurCharInfo = CharInfo + (i + BufferCoord.Y) * BufferSize.X + BufferCoord.X; - Offset = (((Y + Buff->ShowY) % Buff->MaxY) * Buff->MaxX + WriteRegion.Left) * 2; - for ( X = WriteRegion.Left; X <= WriteRegion.Right; X++ ) - { - SET_CELL_BUFFER(Buff, Offset, CurCharInfo->Char.AsciiChar, CurCharInfo->Attributes); - CurCharInfo++; - } - } + /* Make sure WriteRegion is inside the screen buffer */ + ConioInitRect(&ScreenBuffer, 0, 0, Buff->MaxY - 1, Buff->MaxX - 1); + if (! ConioGetIntersection(&WriteRegion, &ScreenBuffer, &WriteRegion)) + { + ConioUnlockScreenBuffer(Buff); + ConioUnlockConsole(Console); - if( Buff == ActiveConsole->ActiveBuffer ) - { - CsrpDrawRegion(ActiveConsole, WriteRegion); - } + /* It is okay to have a WriteRegion completely outside the screen buffer. + No data is written then. */ + return Reply->Status = STATUS_SUCCESS; + } - UNLOCK; - Reply->Data.WriteConsoleOutputReply.WriteRegion.Right = WriteRegion.Left + SizeX - 1; - Reply->Data.WriteConsoleOutputReply.WriteRegion.Bottom = WriteRegion.Top + SizeY - 1; - Reply->Data.WriteConsoleOutputReply.WriteRegion.Left = WriteRegion.Left; - Reply->Data.WriteConsoleOutputReply.WriteRegion.Top = WriteRegion.Top; - return (Reply->Status = STATUS_SUCCESS); + for (i = 0, Y = WriteRegion.top; Y <= WriteRegion.bottom; i++, Y++) + { + CurCharInfo = CharInfo + (i + BufferCoord.Y) * BufferSize.X + BufferCoord.X; + Offset = (((Y + Buff->ShowY) % Buff->MaxY) * Buff->MaxX + WriteRegion.left) * 2; + for (X = WriteRegion.left; X <= WriteRegion.right; X++) + { + SET_CELL_BUFFER(Buff, Offset, CurCharInfo->Char.AsciiChar, CurCharInfo->Attributes); + CurCharInfo++; + } + } + + if (NULL != Console) + { + ConioDrawRegion(Console, &WriteRegion); + } + + ConioUnlockScreenBuffer(Buff); + ConioUnlockConsole(Console); + + Reply->Data.WriteConsoleOutputReply.WriteRegion.Right = WriteRegion.left + SizeX - 1; + Reply->Data.WriteConsoleOutputReply.WriteRegion.Bottom = WriteRegion.top + SizeY - 1; + Reply->Data.WriteConsoleOutputReply.WriteRegion.Left = WriteRegion.left; + Reply->Data.WriteConsoleOutputReply.WriteRegion.Top = WriteRegion.top; + + return Reply->Status = STATUS_SUCCESS; } CSR_API(CsrFlushInputBuffer) @@ -2517,13 +2277,12 @@ CSR_API(CsrFlushInputBuffer) Reply->Header.MessageSize = sizeof(CSRSS_API_REPLY); Reply->Header.DataSize = sizeof(CSRSS_API_REPLY) - sizeof(LPC_MESSAGE); - LOCK; - Status = Win32CsrGetObject( ProcessData, Request->Data.FlushInputBufferRequest.ConsoleInput, (Object_t **)&Console ); - if( !NT_SUCCESS( Status ) || (Status = Console->Header.Type == CONIO_CONSOLE_MAGIC ? STATUS_SUCCESS : STATUS_INVALID_HANDLE )) + Status = ConioLockConsole(ProcessData, + Request->Data.FlushInputBufferRequest.ConsoleInput, + &Console); + if(! NT_SUCCESS(Status)) { - Reply->Status = Status; - UNLOCK; - return Status; + return Reply->Status = Status; } /* Discard all entries in the input event queue */ @@ -2532,115 +2291,132 @@ CSR_API(CsrFlushInputBuffer) CurrentEntry = RemoveHeadList(&Console->InputEvents); Input = CONTAINING_RECORD(CurrentEntry, ConsoleInput, ListEntry); /* Destroy the event */ - RtlFreeHeap( Win32CsrApiHeap, 0, Input ); + HeapFree(Win32CsrApiHeap, 0, Input); } Console->WaitingChars=0; - UNLOCK; - return (Reply->Status = STATUS_SUCCESS); + ConioUnlockConsole(Console); + + return Reply->Status = STATUS_SUCCESS; } CSR_API(CsrScrollConsoleScreenBuffer) { + PCSRSS_CONSOLE Console; PCSRSS_SCREEN_BUFFER Buff; - SMALL_RECT ScreenBuffer; - SMALL_RECT SrcRegion; - SMALL_RECT DstRegion; - SMALL_RECT FillRegion; + RECT ScreenBuffer; + RECT SrcRegion; + RECT DstRegion; + RECT FillRegion; + RECT ScrollRectangle; + RECT ClipRectangle; NTSTATUS Status; BOOLEAN DoFill; DPRINT("CsrScrollConsoleScreenBuffer\n"); ALIAS(ConsoleHandle,Request->Data.ScrollConsoleScreenBufferRequest.ConsoleHandle); - ALIAS(ScrollRectangle,Request->Data.ScrollConsoleScreenBufferRequest.ScrollRectangle); ALIAS(UseClipRectangle,Request->Data.ScrollConsoleScreenBufferRequest.UseClipRectangle); - ALIAS(ClipRectangle,Request->Data.ScrollConsoleScreenBufferRequest.ClipRectangle); ALIAS(DestinationOrigin,Request->Data.ScrollConsoleScreenBufferRequest.DestinationOrigin); ALIAS(Fill,Request->Data.ScrollConsoleScreenBufferRequest.Fill); + Status = ConioConsoleFromProcessData(ProcessData, &Console); + if (! NT_SUCCESS(Status)) + { + return Reply->Status = Status; + } + Reply->Header.MessageSize = sizeof(CSRSS_API_REPLY); Reply->Header.DataSize = sizeof(CSRSS_API_REPLY) - sizeof(LPC_MESSAGE); - LOCK; - Status = Win32CsrGetObject( ProcessData, ConsoleHandle, (Object_t **)&Buff ); - if( !NT_SUCCESS( Status ) || (Status = Buff->Header.Type == CONIO_SCREEN_BUFFER_MAGIC ? STATUS_SUCCESS : STATUS_INVALID_HANDLE )) - { - Reply->Status = Status; - UNLOCK; - return Status; - } + Status = ConioLockScreenBuffer(ProcessData, ConsoleHandle, &Buff); + if (! NT_SUCCESS(Status)) + { + if (NULL != Console) + { + ConioUnlockConsole(Console); + } + return Reply->Status = Status; + } + + ScrollRectangle.left = Request->Data.ScrollConsoleScreenBufferRequest.ScrollRectangle.Left; + ScrollRectangle.top = Request->Data.ScrollConsoleScreenBufferRequest.ScrollRectangle.Top; + ScrollRectangle.right = Request->Data.ScrollConsoleScreenBufferRequest.ScrollRectangle.Right; + ScrollRectangle.bottom = Request->Data.ScrollConsoleScreenBufferRequest.ScrollRectangle.Bottom; + ClipRectangle.left = Request->Data.ScrollConsoleScreenBufferRequest.ClipRectangle.Left; + ClipRectangle.top = Request->Data.ScrollConsoleScreenBufferRequest.ClipRectangle.Top; + ClipRectangle.right = Request->Data.ScrollConsoleScreenBufferRequest.ClipRectangle.Right; + ClipRectangle.bottom = Request->Data.ScrollConsoleScreenBufferRequest.ClipRectangle.Bottom; /* Make sure source rectangle is inside the screen buffer */ - CsrpInitRect(ScreenBuffer, 0, 0, Buff->MaxY - 1, Buff->MaxX - 1); - if (!CsrpGetIntersection(&SrcRegion, ScreenBuffer, ScrollRectangle)) + ConioInitRect(&ScreenBuffer, 0, 0, Buff->MaxY - 1, Buff->MaxX - 1); + if (! ConioGetIntersection(&SrcRegion, &ScreenBuffer, &ScrollRectangle)) { - UNLOCK; - return (Reply->Status = STATUS_INVALID_PARAMETER); + ConioUnlockScreenBuffer(Buff); + return Reply->Status = STATUS_INVALID_PARAMETER; } - if (UseClipRectangle) + if (UseClipRectangle && ! ConioGetIntersection(&SrcRegion, &SrcRegion, &ClipRectangle)) { - if (!CsrpGetIntersection(&SrcRegion, SrcRegion, ClipRectangle)) - { - UNLOCK; - return (Reply->Status = STATUS_SUCCESS); - } + ConioUnlockScreenBuffer(Buff); + return Reply->Status = STATUS_SUCCESS; } - CsrpInitRect( - DstRegion, - DestinationOrigin.Y, - DestinationOrigin.X, - DestinationOrigin.Y + CsrpRectHeight(ScrollRectangle) - 1, - DestinationOrigin.X + CsrpRectWidth(ScrollRectangle) - 1) + ConioInitRect(&DstRegion, + DestinationOrigin.Y, + DestinationOrigin.X, + DestinationOrigin.Y + ConioRectHeight(&ScrollRectangle) - 1, + DestinationOrigin.X + ConioRectWidth(&ScrollRectangle) - 1); /* Make sure destination rectangle is inside the screen buffer */ - if (!CsrpGetIntersection(&DstRegion, DstRegion, ScreenBuffer)) + if (! ConioGetIntersection(&DstRegion, &DstRegion, &ScreenBuffer)) { - UNLOCK; - return (Reply->Status = STATUS_INVALID_PARAMETER); + ConioUnlockScreenBuffer(Buff); + return Reply->Status = STATUS_INVALID_PARAMETER; } - CsrpCopyRegion(Buff, SrcRegion, DstRegion); - + ConioCopyRegion(Buff, &SrcRegion, &DstRegion); /* Get the region that should be filled with the specified character and attributes */ DoFill = FALSE; - CsrpGetUnion(&FillRegion, SrcRegion, DstRegion); + ConioGetUnion(&FillRegion, &SrcRegion, &DstRegion); - if (CsrpSubtractRect(&FillRegion, FillRegion, DstRegion)) + if (ConioSubtractRect(&FillRegion, &FillRegion, &DstRegion)) { /* FIXME: The subtracted rectangle is off by one line */ - FillRegion.Top += 1; + FillRegion.top += 1; - CsrpFillRegion(Buff, FillRegion, Fill); + ConioFillRegion(Buff, &FillRegion, Fill); DoFill = TRUE; } - if (Buff == ActiveConsole->ActiveBuffer) + if (NULL != Console && Buff == Console->ActiveBuffer) { /* Draw destination region */ - CsrpDrawRegion(ActiveConsole, DstRegion); + ConioDrawRegion(Console, &DstRegion); if (DoFill) { /* Draw filled region */ - CsrpDrawRegion(ActiveConsole, FillRegion); + ConioDrawRegion(Console, &FillRegion); } } - UNLOCK; - return(Reply->Status = STATUS_SUCCESS); -} + ConioUnlockScreenBuffer(Buff); + if (NULL != Console) + { + ConioUnlockConsole(Console); + } + return Reply->Status = STATUS_SUCCESS; +} CSR_API(CsrReadConsoleOutputChar) { NTSTATUS Status; - PCSRSS_SCREEN_BUFFER ScreenBuffer; + PCSRSS_SCREEN_BUFFER Buff; DWORD Xpos, Ypos; BYTE* ReadBuffer; DWORD i; @@ -2651,61 +2427,51 @@ CSR_API(CsrReadConsoleOutputChar) Reply->Header.DataSize = Reply->Header.MessageSize - sizeof(LPC_MESSAGE); ReadBuffer = Reply->Data.ReadConsoleOutputCharReply.String; - LOCK; - - Status = Win32CsrGetObject(ProcessData, Request->Data.ReadConsoleOutputCharRequest.ConsoleHandle, (Object_t**)&ScreenBuffer); - if (!NT_SUCCESS(Status)) + Status = ConioLockScreenBuffer(ProcessData, Request->Data.ReadConsoleOutputCharRequest.ConsoleHandle, Buff); + if (! NT_SUCCESS(Status)) { - Reply->Status = Status; - UNLOCK; - return(Reply->Status); + return Reply->Status = Status; } - if (ScreenBuffer->Header.Type != CONIO_SCREEN_BUFFER_MAGIC) - { - Reply->Status = STATUS_INVALID_HANDLE; - UNLOCK; - return(Reply->Status); - } - - Xpos = Request->Data.ReadConsoleOutputCharRequest.ReadCoord.X + ScreenBuffer->ShowX; - Ypos = (Request->Data.ReadConsoleOutputCharRequest.ReadCoord.Y + ScreenBuffer->ShowY) % ScreenBuffer->MaxY; + Xpos = Request->Data.ReadConsoleOutputCharRequest.ReadCoord.X + Buff->ShowX; + Ypos = (Request->Data.ReadConsoleOutputCharRequest.ReadCoord.Y + Buff->ShowY) % Buff->MaxY; for (i = 0; i < Request->Data.ReadConsoleOutputCharRequest.NumCharsToRead; ++i) { - *ReadBuffer = ScreenBuffer->Buffer[(Xpos * 2) + (Ypos * 2 * ScreenBuffer->MaxX)]; + *ReadBuffer = Buff->Buffer[(Xpos * 2) + (Ypos * 2 * Buff->MaxX)]; ReadBuffer++; Xpos++; - if (Xpos == ScreenBuffer->MaxX) + if (Xpos == Buff->MaxX) { Xpos = 0; Ypos++; - if (Ypos == ScreenBuffer->MaxY) - Ypos = 0; + if (Ypos == Buff->MaxY) + { + Ypos = 0; + } } } *ReadBuffer = 0; - Reply->Status = STATUS_SUCCESS; - Reply->Data.ReadConsoleOutputCharReply.EndCoord.X = Xpos - ScreenBuffer->ShowX; - Reply->Data.ReadConsoleOutputCharReply.EndCoord.Y = (Ypos - ScreenBuffer->ShowY + ScreenBuffer->MaxY) % ScreenBuffer->MaxY; + Reply->Data.ReadConsoleOutputCharReply.EndCoord.X = Xpos - Buff->ShowX; + Reply->Data.ReadConsoleOutputCharReply.EndCoord.Y = (Ypos - Buff->ShowY + Buff->MaxY) % Buff->MaxY; Reply->Header.MessageSize += Request->Data.ReadConsoleOutputCharRequest.NumCharsToRead; Reply->Header.DataSize += Request->Data.ReadConsoleOutputCharRequest.NumCharsToRead; - UNLOCK; + ConioUnlockScreenBuffer(Buff); - return(Reply->Status); + return Reply->Status; } CSR_API(CsrReadConsoleOutputAttrib) { NTSTATUS Status; - PCSRSS_SCREEN_BUFFER ScreenBuffer; + PCSRSS_SCREEN_BUFFER Buff; DWORD Xpos, Ypos; CHAR* ReadBuffer; DWORD i; @@ -2716,54 +2482,45 @@ CSR_API(CsrReadConsoleOutputAttrib) Reply->Header.DataSize = Reply->Header.MessageSize - sizeof(LPC_MESSAGE); ReadBuffer = Reply->Data.ReadConsoleOutputAttribReply.String; - LOCK; - - Status = Win32CsrGetObject(ProcessData, Request->Data.ReadConsoleOutputAttribRequest.ConsoleHandle, (Object_t**)&ScreenBuffer); - if (!NT_SUCCESS(Status)) + Status = ConioLockScreenBuffer(ProcessData, Request->Data.ReadConsoleOutputAttribRequest.ConsoleHandle, &Buff); + if (! NT_SUCCESS(Status)) { - Reply->Status = Status; - UNLOCK; - return(Reply->Status); + return Reply->Status = Status; } - if (ScreenBuffer->Header.Type != CONIO_SCREEN_BUFFER_MAGIC) - { - Reply->Status = STATUS_INVALID_HANDLE; - UNLOCK; - return(Reply->Status); - } - - Xpos = Request->Data.ReadConsoleOutputAttribRequest.ReadCoord.X + ScreenBuffer->ShowX; - Ypos = (Request->Data.ReadConsoleOutputAttribRequest.ReadCoord.Y + ScreenBuffer->ShowY) % ScreenBuffer->MaxY; + Xpos = Request->Data.ReadConsoleOutputAttribRequest.ReadCoord.X + Buff->ShowX; + Ypos = (Request->Data.ReadConsoleOutputAttribRequest.ReadCoord.Y + Buff->ShowY) % Buff->MaxY; for (i = 0; i < Request->Data.ReadConsoleOutputAttribRequest.NumAttrsToRead; ++i) { - *ReadBuffer = ScreenBuffer->Buffer[(Xpos * 2) + (Ypos * 2 * ScreenBuffer->MaxX) + 1]; + *ReadBuffer = Buff->Buffer[(Xpos * 2) + (Ypos * 2 * Buff->MaxX) + 1]; ReadBuffer++; Xpos++; - if (Xpos == ScreenBuffer->MaxX) - { - Xpos = 0; - Ypos++; + if (Xpos == Buff->MaxX) + { + Xpos = 0; + Ypos++; - if (Ypos == ScreenBuffer->MaxY) - Ypos = 0; - } + if (Ypos == Buff->MaxY) + { + Ypos = 0; + } + } } *ReadBuffer = 0; Reply->Status = STATUS_SUCCESS; - Reply->Data.ReadConsoleOutputAttribReply.EndCoord.X = Xpos - ScreenBuffer->ShowX; - Reply->Data.ReadConsoleOutputAttribReply.EndCoord.Y = (Ypos - ScreenBuffer->ShowY + ScreenBuffer->MaxY) % ScreenBuffer->MaxY; + Reply->Data.ReadConsoleOutputAttribReply.EndCoord.X = Xpos - Buff->ShowX; + Reply->Data.ReadConsoleOutputAttribReply.EndCoord.Y = (Ypos - Buff->ShowY + Buff->MaxY) % Buff->MaxY; Reply->Header.MessageSize += Request->Data.ReadConsoleOutputAttribRequest.NumAttrsToRead; Reply->Header.DataSize += Request->Data.ReadConsoleOutputAttribRequest.NumAttrsToRead; - UNLOCK; + ConioUnlockScreenBuffer(Buff); - return(Reply->Status); + return Reply->Status; } @@ -2779,37 +2536,27 @@ CSR_API(CsrGetNumberOfConsoleInputEvents) Reply->Header.MessageSize = sizeof(CSRSS_API_REPLY); Reply->Header.DataSize = Reply->Header.MessageSize - sizeof(LPC_MESSAGE); - LOCK; - - Status = Win32CsrGetObject(ProcessData, Request->Data.GetNumInputEventsRequest.ConsoleHandle, (Object_t**)&Console); - if (!NT_SUCCESS(Status)) + Status = ConioLockConsole(ProcessData, Request->Data.GetNumInputEventsRequest.ConsoleHandle, &Console); + if (! NT_SUCCESS(Status)) { - Reply->Status = Status; - UNLOCK; - return(Reply->Status); - } - - if (Console->Header.Type != CONIO_CONSOLE_MAGIC) - { - Reply->Status = STATUS_INVALID_HANDLE; - UNLOCK; - return(Reply->Status); + return Reply->Status = Status; } CurrentItem = &Console->InputEvents; NumEvents = 0; - // If there are any events ... - if(CurrentItem->Flink != CurrentItem) - { - do + /* If there are any events ... */ + if (CurrentItem->Flink != CurrentItem) { - CurrentItem = CurrentItem->Flink; - ++NumEvents; - }while(CurrentItem != &Console->InputEvents); - } - - UNLOCK; + do + { + CurrentItem = CurrentItem->Flink; + ++NumEvents; + } + while (CurrentItem != &Console->InputEvents); + } + + ConioUnlockConsole(Console); Reply->Status = STATUS_SUCCESS; Reply->Data.GetNumInputEventsReply.NumInputEvents = NumEvents; @@ -2820,233 +2567,210 @@ CSR_API(CsrGetNumberOfConsoleInputEvents) CSR_API(CsrPeekConsoleInput) { - NTSTATUS Status; - PCSRSS_CONSOLE Console; - DWORD Size; - DWORD Length; - PLIST_ENTRY CurrentItem; - PINPUT_RECORD InputRecord; - ConsoleInput* Item; - UINT NumItems; + NTSTATUS Status; + PCSRSS_CONSOLE Console; + DWORD Size; + DWORD Length; + PLIST_ENTRY CurrentItem; + PINPUT_RECORD InputRecord; + ConsoleInput* Item; + UINT NumItems; - DPRINT("CsrPeekConsoleInput\n"); + DPRINT("CsrPeekConsoleInput\n"); - Reply->Header.MessageSize = sizeof(CSRSS_API_REPLY); - Reply->Header.DataSize = sizeof(CSRSS_API_REPLY) - sizeof(LPC_MESSAGE); + Reply->Header.MessageSize = sizeof(CSRSS_API_REPLY); + Reply->Header.DataSize = sizeof(CSRSS_API_REPLY) - sizeof(LPC_MESSAGE); - LOCK; + Status = ConioLockConsole(ProcessData, Request->Data.GetNumInputEventsRequest.ConsoleHandle, &Console); + if(! NT_SUCCESS(Status)) + { + return Reply->Status = Status; + } - Status = Win32CsrGetObject(ProcessData, Request->Data.GetNumInputEventsRequest.ConsoleHandle, (Object_t**)&Console); - if(!NT_SUCCESS(Status)) - { - Reply->Status = Status; - UNLOCK; - return Reply->Status; - } - - if(Console->Header.Type != CONIO_CONSOLE_MAGIC) - { - Reply->Status = STATUS_INVALID_HANDLE; - UNLOCK; - return Reply->Status; - } + InputRecord = Request->Data.PeekConsoleInputRequest.InputRecord; + Length = Request->Data.PeekConsoleInputRequest.Length; + Size = Length * sizeof(INPUT_RECORD); - InputRecord = Request->Data.PeekConsoleInputRequest.InputRecord; - Length = Request->Data.PeekConsoleInputRequest.Length; - Size = Length * sizeof(INPUT_RECORD); - - if(((PVOID)InputRecord < ProcessData->CsrSectionViewBase) - || (((PVOID)InputRecord + Size) > (ProcessData->CsrSectionViewBase + ProcessData->CsrSectionViewSize))) - { - UNLOCK; + if (((PVOID)InputRecord < ProcessData->CsrSectionViewBase) + || (((PVOID)InputRecord + Size) > (ProcessData->CsrSectionViewBase + ProcessData->CsrSectionViewSize))) + { + ConioUnlockConsole(Console); Reply->Status = STATUS_ACCESS_VIOLATION; return Reply->Status ; - } + } - NumItems = 0; + NumItems = 0; - if(!IsListEmpty(&Console->InputEvents)) - { + if (! IsListEmpty(&Console->InputEvents)) + { CurrentItem = &Console->InputEvents; - while(NumItems < Length) - { - ++NumItems; - Item = CONTAINING_RECORD(CurrentItem, ConsoleInput, ListEntry); - *InputRecord++ = Item->InputEvent; + while (NumItems < Length) + { + ++NumItems; + Item = CONTAINING_RECORD(CurrentItem, ConsoleInput, ListEntry); + *InputRecord++ = Item->InputEvent; - if(CurrentItem->Flink == &Console->InputEvents) - break; - else - CurrentItem = CurrentItem->Flink; - } - } + if (CurrentItem->Flink == &Console->InputEvents) + { + break; + } + else + { + CurrentItem = CurrentItem->Flink; + } + } + } - UNLOCK; - - Reply->Status = STATUS_SUCCESS; - Reply->Data.PeekConsoleInputReply.Length = NumItems; - return Reply->Status; + ConioUnlockConsole(Console); + + Reply->Status = STATUS_SUCCESS; + Reply->Data.PeekConsoleInputReply.Length = NumItems; + + return Reply->Status; } CSR_API(CsrReadConsoleOutput) { - PCHAR_INFO CharInfo; - PCHAR_INFO CurCharInfo; - PCSRSS_SCREEN_BUFFER ScreenBuffer; - DWORD Size; - DWORD Length; - DWORD SizeX, SizeY; - NTSTATUS Status; - COORD BufferSize; - COORD BufferCoord; - SMALL_RECT ReadRegion; - SMALL_RECT ScreenRect; - DWORD i, Y, X, Offset; + PCHAR_INFO CharInfo; + PCHAR_INFO CurCharInfo; + PCSRSS_SCREEN_BUFFER Buff; + DWORD Size; + DWORD Length; + DWORD SizeX, SizeY; + NTSTATUS Status; + COORD BufferSize; + COORD BufferCoord; + RECT ReadRegion; + RECT ScreenRect; + DWORD i, Y, X, Offset; - DPRINT("CsrReadConsoleOutput\n"); + DPRINT("CsrReadConsoleOutput\n"); - Reply->Header.MessageSize = sizeof(CSRSS_API_REPLY); - Reply->Header.DataSize = sizeof(CSRSS_API_REPLY) - sizeof(LPC_MESSAGE); + Reply->Header.MessageSize = sizeof(CSRSS_API_REPLY); + Reply->Header.DataSize = sizeof(CSRSS_API_REPLY) - sizeof(LPC_MESSAGE); - LOCK; - - Status = Win32CsrGetObject(ProcessData, Request->Data.ReadConsoleOutputRequest.ConsoleHandle, (Object_t**)&ScreenBuffer); - if(!NT_SUCCESS(Status)) - { - Reply->Status = Status; - UNLOCK; - return Reply->Status; - } - - if(ScreenBuffer->Header.Type != CONIO_SCREEN_BUFFER_MAGIC) - { - Reply->Status = STATUS_INVALID_HANDLE; - UNLOCK; - return Reply->Status; - } + Status = ConioLockScreenBuffer(ProcessData, Request->Data.ReadConsoleOutputRequest.ConsoleHandle, &Buff); + if (! NT_SUCCESS(Status)) + { + return Reply->Status = Status; + } - CharInfo = Request->Data.ReadConsoleOutputRequest.CharInfo; - ReadRegion = Request->Data.ReadConsoleOutputRequest.ReadRegion; - BufferSize = Request->Data.ReadConsoleOutputRequest.BufferSize; - BufferCoord = Request->Data.ReadConsoleOutputRequest.BufferCoord; - Length = BufferSize.X * BufferSize.Y; - Size = Length * sizeof(CHAR_INFO); + CharInfo = Request->Data.ReadConsoleOutputRequest.CharInfo; + ReadRegion.left = Request->Data.ReadConsoleOutputRequest.ReadRegion.Left; + ReadRegion.top = Request->Data.ReadConsoleOutputRequest.ReadRegion.Top; + ReadRegion.right = Request->Data.ReadConsoleOutputRequest.ReadRegion.Right; + ReadRegion.bottom = Request->Data.ReadConsoleOutputRequest.ReadRegion.Bottom; + BufferSize = Request->Data.ReadConsoleOutputRequest.BufferSize; + BufferCoord = Request->Data.ReadConsoleOutputRequest.BufferCoord; + Length = BufferSize.X * BufferSize.Y; + Size = Length * sizeof(CHAR_INFO); - if(((PVOID)CharInfo < ProcessData->CsrSectionViewBase) - || (((PVOID)CharInfo + Size) > (ProcessData->CsrSectionViewBase + ProcessData->CsrSectionViewSize))) - { - UNLOCK; + if (((PVOID)CharInfo < ProcessData->CsrSectionViewBase) + || (((PVOID)CharInfo + Size) > (ProcessData->CsrSectionViewBase + ProcessData->CsrSectionViewSize))) + { + ConioUnlockScreenBuffer(Buff); Reply->Status = STATUS_ACCESS_VIOLATION; return Reply->Status ; - } + } - SizeY = RtlRosMin(BufferSize.Y - BufferCoord.Y, CsrpRectHeight(ReadRegion)); - SizeX = RtlRosMin(BufferSize.X - BufferCoord.X, CsrpRectWidth(ReadRegion)); - ReadRegion.Bottom = ReadRegion.Top + SizeY; - ReadRegion.Right = ReadRegion.Left + SizeX; + SizeY = RtlRosMin(BufferSize.Y - BufferCoord.Y, ConioRectHeight(&ReadRegion)); + SizeX = RtlRosMin(BufferSize.X - BufferCoord.X, ConioRectWidth(&ReadRegion)); + ReadRegion.bottom = ReadRegion.top + SizeY; + ReadRegion.right = ReadRegion.left + SizeX; - CsrpInitRect(ScreenRect, 0, 0, ScreenBuffer->MaxY, ScreenBuffer->MaxX); - if (!CsrpGetIntersection(&ReadRegion, ScreenRect, ReadRegion)) - { - UNLOCK; + ConioInitRect(&ScreenRect, 0, 0, Buff->MaxY, Buff->MaxX); + if (! ConioGetIntersection(&ReadRegion, &ScreenRect, &ReadRegion)) + { + ConioUnlockScreenBuffer(Buff); Reply->Status = STATUS_SUCCESS; return Reply->Status; - } + } - for(i = 0, Y = ReadRegion.Top; Y < ReadRegion.Bottom; ++i, ++Y) - { - CurCharInfo = CharInfo + (i * BufferSize.X); + for (i = 0, Y = ReadRegion.top; Y < ReadRegion.bottom; ++i, ++Y) + { + CurCharInfo = CharInfo + (i * BufferSize.X); - Offset = (((Y + ScreenBuffer->ShowY) % ScreenBuffer->MaxY) * ScreenBuffer->MaxX + ReadRegion.Left) * 2; - for(X = ReadRegion.Left; X < ReadRegion.Right; ++X) - { - CurCharInfo->Char.AsciiChar = GET_CELL_BUFFER(ScreenBuffer, Offset); - CurCharInfo->Attributes = GET_CELL_BUFFER(ScreenBuffer, Offset); - ++CurCharInfo; - } - } + Offset = (((Y + Buff->ShowY) % Buff->MaxY) * Buff->MaxX + ReadRegion.left) * 2; + for (X = ReadRegion.left; X < ReadRegion.right; ++X) + { + CurCharInfo->Char.AsciiChar = GET_CELL_BUFFER(Buff, Offset); + CurCharInfo->Attributes = GET_CELL_BUFFER(Buff, Offset); + ++CurCharInfo; + } + } + + ConioUnlockScreenBuffer(Buff); - UNLOCK; + Reply->Status = STATUS_SUCCESS; + Reply->Data.ReadConsoleOutputReply.ReadRegion.Right = ReadRegion.left + SizeX - 1; + Reply->Data.ReadConsoleOutputReply.ReadRegion.Bottom = ReadRegion.top + SizeY - 1; + Reply->Data.ReadConsoleOutputReply.ReadRegion.Left = ReadRegion.left; + Reply->Data.ReadConsoleOutputReply.ReadRegion.Top = ReadRegion.top; - Reply->Status = STATUS_SUCCESS; - Reply->Data.ReadConsoleOutputReply.ReadRegion.Right = ReadRegion.Left + SizeX - 1; - Reply->Data.ReadConsoleOutputReply.ReadRegion.Bottom = ReadRegion.Top + SizeY - 1; - Reply->Data.ReadConsoleOutputReply.ReadRegion.Left = ReadRegion.Left; - Reply->Data.ReadConsoleOutputReply.ReadRegion.Top = ReadRegion.Top; - - return Reply->Status; + return Reply->Status; } CSR_API(CsrWriteConsoleInput) { - PINPUT_RECORD InputRecord; - PCSRSS_CONSOLE Console; - NTSTATUS Status; - DWORD Length; - DWORD Size; - DWORD i; - ConsoleInput* Record; + PINPUT_RECORD InputRecord; + PCSRSS_CONSOLE Console; + NTSTATUS Status; + DWORD Length; + DWORD Size; + DWORD i; + ConsoleInput* Record; - DPRINT("CsrWriteConsoleInput\n"); + DPRINT("CsrWriteConsoleInput\n"); - Reply->Header.MessageSize = sizeof(CSRSS_API_REPLY); - Reply->Header.DataSize = sizeof(CSRSS_API_REPLY) - sizeof(LPC_MESSAGE); + Reply->Header.MessageSize = sizeof(CSRSS_API_REPLY); + Reply->Header.DataSize = sizeof(CSRSS_API_REPLY) - sizeof(LPC_MESSAGE); - LOCK; + Status = ConioLockConsole(ProcessData, Request->Data.WriteConsoleInputRequest.ConsoleHandle, &Console); + if (! NT_SUCCESS(Status)) + { + return Reply->Status = Status; + } - Status = Win32CsrGetObject(ProcessData, Request->Data.WriteConsoleInputRequest.ConsoleHandle, (Object_t**)&Console); - if(!NT_SUCCESS(Status)) - { - Reply->Status = Status; - UNLOCK; - return Reply->Status; - } - - if(Console->Header.Type != CONIO_CONSOLE_MAGIC) - { - Reply->Status = STATUS_INVALID_HANDLE; - UNLOCK; - return Reply->Status; - } + InputRecord = Request->Data.WriteConsoleInputRequest.InputRecord; + Length = Request->Data.WriteConsoleInputRequest.Length; + Size = Length * sizeof(INPUT_RECORD); - InputRecord = Request->Data.WriteConsoleInputRequest.InputRecord; - Length = Request->Data.WriteConsoleInputRequest.Length; - Size = Length * sizeof(INPUT_RECORD); - - if(((PVOID)InputRecord < ProcessData->CsrSectionViewBase) - || (((PVOID)InputRecord + Size) > (ProcessData->CsrSectionViewBase + ProcessData->CsrSectionViewSize))) - { - UNLOCK; + if (((PVOID)InputRecord < ProcessData->CsrSectionViewBase) + || (((PVOID)InputRecord + Size) > (ProcessData->CsrSectionViewBase + ProcessData->CsrSectionViewSize))) + { + ConioUnlockConsole(Console); Reply->Status = STATUS_ACCESS_VIOLATION; return Reply->Status ; - } + } - for(i = 0; i < Length; ++i) - { - Record = RtlAllocateHeap(Win32CsrApiHeap, 0, sizeof(ConsoleInput)); - if(Record == NULL) - { - UNLOCK; - Reply->Status = STATUS_INSUFFICIENT_RESOURCES; - return Reply->Status; - } + for (i = 0; i < Length; i++) + { + Record = HeapAlloc(Win32CsrApiHeap, 0, sizeof(ConsoleInput)); + if (NULL == Record) + { + ConioUnlockConsole(Console); + Reply->Status = STATUS_INSUFFICIENT_RESOURCES; + return Reply->Status; + } Record->Echoed = FALSE; Record->Fake = FALSE; Record->InputEvent = *InputRecord++; - if( Record->InputEvent.EventType == KEY_EVENT ) { - CsrpProcessChar( Console, Record ); - } - } - - UNLOCK; + if (KEY_EVENT == Record->InputEvent.EventType) + { + ConioProcessChar(Console, Record); + } + } + + ConioUnlockConsole(Console); - Reply->Status = STATUS_SUCCESS; - Reply->Data.WriteConsoleInputReply.Length = i; - return Reply->Status; + Reply->Status = STATUS_SUCCESS; + Reply->Data.WriteConsoleInputReply.Length = i; + + return Reply->Status; } /********************************************************************** @@ -3063,115 +2787,89 @@ CSR_API(CsrWriteConsoleInput) * ConsoleHwState has the correct size to be compatible * with NT's, but values are not. */ -static NTSTATUS FASTCALL SetConsoleHardwareState (PCSRSS_CONSOLE Console, DWORD ConsoleHwState) +STATIC NTSTATUS FASTCALL +SetConsoleHardwareState (PCSRSS_CONSOLE Console, DWORD ConsoleHwState) { - DbgPrint( "Console Hardware State: %d\n", ConsoleHwState ); + DPRINT1("Console Hardware State: %d\n", ConsoleHwState); - if ( (CONSOLE_HARDWARE_STATE_GDI_MANAGED == ConsoleHwState) + if ((CONSOLE_HARDWARE_STATE_GDI_MANAGED == ConsoleHwState) ||(CONSOLE_HARDWARE_STATE_DIRECT == ConsoleHwState)) - { + { if (Console->HardwareState != ConsoleHwState) - { - /* TODO: implement switching from full screen to windowed mode */ - /* TODO: or back; now simply store the hardware state */ - Console->HardwareState = ConsoleHwState; - } + { + /* TODO: implement switching from full screen to windowed mode */ + /* TODO: or back; now simply store the hardware state */ + Console->HardwareState = ConsoleHwState; + } + return STATUS_SUCCESS; - } - return STATUS_INVALID_PARAMETER_3; // Client: (handle, set_get, [mode]) + } + + return STATUS_INVALID_PARAMETER_3; /* Client: (handle, set_get, [mode]) */ } CSR_API(CsrHardwareStateProperty) { - PCSRSS_CONSOLE Console; - NTSTATUS Status; + PCSRSS_CONSOLE Console; + NTSTATUS Status; - DPRINT("CsrHardwareStateProperty\n"); + DPRINT("CsrHardwareStateProperty\n"); - Reply->Header.MessageSize = sizeof(CSRSS_API_REPLY); - Reply->Header.DataSize = sizeof(CSRSS_API_REPLY) - sizeof(LPC_MESSAGE); - - LOCK; + Reply->Header.MessageSize = sizeof(CSRSS_API_REPLY); + Reply->Header.DataSize = sizeof(CSRSS_API_REPLY) - sizeof(LPC_MESSAGE); - Status = Win32CsrGetObject ( - ProcessData, - Request->Data.ConsoleHardwareStateRequest.ConsoleHandle, - (Object_t**) & Console - ); - if (!NT_SUCCESS(Status)) - { - DbgPrint( "Failed to get console handle in SetConsoleHardwareState\n" ); - Reply->Status = Status; - } - else - { - if(Console->Header.Type != CONIO_CONSOLE_MAGIC) - { - DbgPrint( "Bad magic on Console: %08x\n", Console->Header.Type ); - Reply->Status = STATUS_INVALID_HANDLE; - } - else - { - switch (Request->Data.ConsoleHardwareStateRequest.SetGet) - { - case CONSOLE_HARDWARE_STATE_GET: - Reply->Data.ConsoleHardwareStateReply.State = Console->HardwareState; - break; + Status = ConioLockConsole(ProcessData, + Request->Data.ConsoleHardwareStateRequest.ConsoleHandle, + &Console); + if (! NT_SUCCESS(Status)) + { + DPRINT1("Failed to get console handle in SetConsoleHardwareState\n"); + return Reply->Status = Status; + } + + switch (Request->Data.ConsoleHardwareStateRequest.SetGet) + { + case CONSOLE_HARDWARE_STATE_GET: + Reply->Data.ConsoleHardwareStateReply.State = Console->HardwareState; + break; - case CONSOLE_HARDWARE_STATE_SET: - DbgPrint( "Setting console hardware state.\n" ); - Reply->Status = SetConsoleHardwareState (Console, Request->Data.ConsoleHardwareStateRequest.State); - break; + case CONSOLE_HARDWARE_STATE_SET: + DPRINT("Setting console hardware state.\n"); + Reply->Status = SetConsoleHardwareState(Console, Request->Data.ConsoleHardwareStateRequest.State); + break; - default: - Reply->Status = STATUS_INVALID_PARAMETER_2; // Client: (handle, [set_get], mode) - break; - } - } - } + default: + Reply->Status = STATUS_INVALID_PARAMETER_2; /* Client: (handle, [set_get], mode) */ + break; + } - UNLOCK; + ConioUnlockConsole(Console); - return Reply->Status; + return Reply->Status; } CSR_API(CsrGetConsoleWindow) { - PCSRSS_CONSOLE Console; - NTSTATUS Status; + PCSRSS_CONSOLE Console; + NTSTATUS Status; - DPRINT("CsrGetConsoleWindow\n"); + DPRINT("CsrGetConsoleWindow\n"); - Reply->Header.MessageSize = sizeof(CSRSS_API_REPLY); - Reply->Header.DataSize = sizeof(CSRSS_API_REPLY) - sizeof(LPC_MESSAGE); - - LOCK; + Reply->Header.MessageSize = sizeof(CSRSS_API_REPLY); + Reply->Header.DataSize = sizeof(CSRSS_API_REPLY) - sizeof(LPC_MESSAGE); - Status = Win32CsrGetObject ( - ProcessData, - Request->Data.ConsoleWindowRequest.ConsoleHandle, - (Object_t**) & Console - ); - if (!NT_SUCCESS(Status)) - { - Reply->Status = Status; - } - else - { - if(Console->Header.Type != CONIO_CONSOLE_MAGIC) - { - Reply->Status = STATUS_INVALID_HANDLE; - } - else - { - // Is this GDI handle valid in the client's context? - Reply->Data.ConsoleWindowReply.WindowHandle = Console->hWindow; - } - } + Status = ConioLockConsole(ProcessData, + Request->Data.ConsoleWindowRequest.ConsoleHandle, + &Console); + if (! NT_SUCCESS(Status)) + { + return Reply->Status = Status; + } - UNLOCK; + Reply->Data.ConsoleWindowReply.WindowHandle = Console->hWindow; + ConioUnlockConsole(Console); - return Reply->Status; + return Reply->Status = STATUS_SUCCESS; } /* EOF */ diff --git a/reactos/subsys/csrss/win32csr/desktopbg.c b/reactos/subsys/csrss/win32csr/desktopbg.c index b94d50fe43a..76a5eef9927 100644 --- a/reactos/subsys/csrss/win32csr/desktopbg.c +++ b/reactos/subsys/csrss/win32csr/desktopbg.c @@ -1,4 +1,4 @@ -/* $Id: desktopbg.c,v 1.4 2003/12/27 15:09:51 navaraf Exp $ +/* $Id: desktopbg.c,v 1.5 2004/01/11 17:31:16 gvg Exp $ * * reactos/subsys/csrss/win32csr/desktopbg.c * @@ -32,6 +32,7 @@ typedef struct tagDTBG_THREAD_DATA } DTBG_THREAD_DATA, *PDTBG_THREAD_DATA; static BOOL Initialized = FALSE; +static HWND VisibleDesktopWindow = NULL; static LRESULT CALLBACK DtbgWindowProc(HWND Wnd, UINT Msg, WPARAM wParam, LPARAM lParam) @@ -68,6 +69,7 @@ DtbgWindowProc(HWND Wnd, UINT Msg, WPARAM wParam, LPARAM lParam) (int)(short) HIWORD(lParam), SWP_NOACTIVATE | SWP_NOZORDER | SWP_SHOWWINDOW | SWP_NOREDRAW); UpdateWindow(Wnd); + VisibleDesktopWindow = Wnd; break; case PM_HIDE_DESKTOP: Result = ! SetWindowPos(Wnd, @@ -75,6 +77,7 @@ DtbgWindowProc(HWND Wnd, UINT Msg, WPARAM wParam, LPARAM lParam) SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOMOVE | SWP_NOSIZE | SWP_HIDEWINDOW); UpdateWindow(Wnd); + VisibleDesktopWindow = NULL; break; default: Result = 0; @@ -95,12 +98,12 @@ DtbgInit() WindowStation = OpenWindowStationW(L"WinSta0", FALSE, GENERIC_ALL); if (NULL == WindowStation) { - DPRINT1("Win32Csr: failed to open window station\n"); + DPRINT1("Failed to open window station\n"); return FALSE; } if (! SetProcessWindowStation(WindowStation)) { - DPRINT1("Win32Csr: failed to set process window station\n"); + DPRINT1("Failed to set process window station\n"); return FALSE; } @@ -121,10 +124,11 @@ DtbgInit() ClassAtom = RegisterClassExW(&Class); if ((ATOM) 0 == ClassAtom) { - DPRINT1("Win32Csr: Unable to register desktop background class (error %d)\n", + DPRINT1("Unable to register desktop background class (error %d)\n", GetLastError()); return FALSE; } + VisibleDesktopWindow = NULL; return TRUE; } @@ -138,7 +142,7 @@ DtbgDesktopThread(PVOID Data) if (! SetThreadDesktop(ThreadData->Desktop)) { - DPRINT1("Win32Csr: failed to set thread desktop\n"); + DPRINT1("Failed to set thread desktop\n"); ThreadData->Status = STATUS_UNSUCCESSFUL; SetEvent(ThreadData->Event); return 1; @@ -156,7 +160,7 @@ DtbgDesktopThread(PVOID Data) NULL); if (NULL == BackgroundWnd) { - DPRINT1("Win32Csr: failed to create desktop background window\n"); + DPRINT1("Failed to create desktop background window\n"); ThreadData->Status = STATUS_UNSUCCESSFUL; SetEvent(ThreadData->Event); return 1; @@ -198,7 +202,7 @@ CSR_API(CsrCreateDesktop) 0, FALSE, GENERIC_ALL); if (NULL == Desktop) { - DPRINT1("Win32Csr: failed to open desktop %S\n", + DPRINT1("Failed to open desktop %S\n", Request->Data.CreateDesktopRequest.DesktopName); return Reply->Status = STATUS_UNSUCCESSFUL; } @@ -207,7 +211,7 @@ CSR_API(CsrCreateDesktop) ThreadData.Event = CreateEventW(NULL, FALSE, FALSE, NULL); if (NULL == ThreadData.Event) { - DPRINT1("Win32Csr: Failed to create event (error %d)\n", GetLastError()); + DPRINT1("Failed to create event (error %d)\n", GetLastError()); return Reply->Status = STATUS_UNSUCCESSFUL; } ThreadHandle = CreateThread(NULL, @@ -219,7 +223,7 @@ CSR_API(CsrCreateDesktop) if (NULL == ThreadHandle) { CloseHandle(ThreadData.Event); - DPRINT1("Win32Csr: Failed to create desktop window thread.\n"); + DPRINT1("Failed to create desktop window thread.\n"); return Reply->Status = STATUS_UNSUCCESSFUL; } CloseHandle(ThreadHandle); @@ -263,4 +267,15 @@ CSR_API(CsrHideDesktop) return Reply->Status; } +BOOL FASTCALL +DtbgIsDesktopVisible(VOID) +{ + if (NULL != VisibleDesktopWindow && ! IsWindowVisible(VisibleDesktopWindow)) + { + VisibleDesktopWindow = NULL; + } + + return NULL != VisibleDesktopWindow; +} + /* EOF */ diff --git a/reactos/subsys/csrss/win32csr/dllmain.c b/reactos/subsys/csrss/win32csr/dllmain.c index f1ecac91549..ad55275a052 100644 --- a/reactos/subsys/csrss/win32csr/dllmain.c +++ b/reactos/subsys/csrss/win32csr/dllmain.c @@ -1,4 +1,4 @@ -/* $Id: dllmain.c,v 1.2 2003/12/07 23:02:57 gvg Exp $ +/* $Id: dllmain.c,v 1.3 2004/01/11 17:31:16 gvg Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS system libraries @@ -82,9 +82,11 @@ DllMain(HANDLE hDll, NTSTATUS FASTCALL Win32CsrInsertObject(PCSRSS_PROCESS_DATA ProcessData, - PHANDLE Handle, - Object_t *Object) + PHANDLE Handle, + Object_t *Object) { + InitializeCriticalSection(&(Object->Lock)); + return (CsrExports.CsrInsertObjectProc)(ProcessData, Handle, Object); } @@ -96,6 +98,36 @@ Win32CsrGetObject(PCSRSS_PROCESS_DATA ProcessData, return (CsrExports.CsrGetObjectProc)(ProcessData, Handle, Object); } +NTSTATUS FASTCALL +Win32CsrLockObject(PCSRSS_PROCESS_DATA ProcessData, + HANDLE Handle, + Object_t **Object, + LONG Type) +{ + NTSTATUS Status; + + Status = (CsrExports.CsrGetObjectProc)(ProcessData, Handle, Object); + if (! NT_SUCCESS(Status)) + { + return Status; + } + + if ((*Object)->Type != Type) + { + return STATUS_INVALID_HANDLE; + } + + EnterCriticalSection(&((*Object)->Lock)); + + return STATUS_SUCCESS; +} + +VOID FASTCALL +Win32CsrUnlockObject(Object_t *Object) +{ + LeaveCriticalSection(&(Object->Lock)); +} + NTSTATUS FASTCALL Win32CsrReleaseObject(PCSRSS_PROCESS_DATA ProcessData, HANDLE Object) diff --git a/reactos/subsys/csrss/win32csr/guiconsole.c b/reactos/subsys/csrss/win32csr/guiconsole.c index c1eba1c847e..11924238d07 100644 --- a/reactos/subsys/csrss/win32csr/guiconsole.c +++ b/reactos/subsys/csrss/win32csr/guiconsole.c @@ -1,9 +1,9 @@ -/* $Id: guiconsole.c,v 1.6 2003/12/31 20:16:39 gvg Exp $ +/* $Id: guiconsole.c,v 1.7 2004/01/11 17:31:16 gvg Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS system libraries - * FILE: subsys/csrss/win32csr/dllmain.c - * PURPOSE: Initialization + * FILE: subsys/csrss/win32csr/guiconsole.c + * PURPOSE: Implementation of gui-mode consoles */ /* INCLUDES ******************************************************************/ @@ -13,6 +13,9 @@ #include "guiconsole.h" #include "win32csr.h" +#define NDEBUG +#include + /* Not defined in any header file */ extern VOID STDCALL PrivateCsrssManualGuiCheck(LONG Check); @@ -38,6 +41,7 @@ typedef struct GUI_CONSOLE_DATA_TAG #define CURSOR_BLINK_TIME 500 +static BOOL Initialized = FALSE; static HWND NotifyWnd; /* FUNCTIONS *****************************************************************/ @@ -46,7 +50,7 @@ static VOID FASTCALL GuiConsoleGetDataPointers(HWND hWnd, PCSRSS_CONSOLE *Console, PGUI_CONSOLE_DATA *GuiData) { *Console = (PCSRSS_CONSOLE) GetWindowLongW(hWnd, GWL_USERDATA); - *GuiData = (NULL == *Console ? NULL : (*Console)->GuiConsoleData); + *GuiData = (NULL == *Console ? NULL : (*Console)->PrivateData); } static BOOL FASTCALL @@ -64,7 +68,7 @@ GuiConsoleHandleNcCreate(HWND hWnd, CREATESTRUCTW *Create) (Console->Size.X + 1) * sizeof(WCHAR)); if (NULL == GuiData) { - DbgPrint("GuiConsoleNcCreate: HeapAlloc failed\n"); + DPRINT1("GuiConsoleNcCreate: HeapAlloc failed\n"); return FALSE; } GuiData->LineBuffer = (PWCHAR)(GuiData + 1); @@ -76,28 +80,28 @@ GuiConsoleHandleNcCreate(HWND hWnd, CREATESTRUCTW *Create) L"Bitstream Vera Sans Mono"); if (NULL == GuiData->Font) { - DbgPrint("GuiConsoleNcCreate: CreateFont failed\n"); + DPRINT1("GuiConsoleNcCreate: CreateFont failed\n"); HeapFree(Win32CsrApiHeap, 0, GuiData); return FALSE; } Dc = GetDC(hWnd); if (NULL == Dc) { - DbgPrint("GuiConsoleNcCreate: GetDC failed\n"); + DPRINT1("GuiConsoleNcCreate: GetDC failed\n"); HeapFree(Win32CsrApiHeap, 0, GuiData); return FALSE; } OldFont = SelectObject(Dc, GuiData->Font); if (NULL == OldFont) { - DbgPrint("GuiConsoleNcCreate: SelectObject failed\n"); + DPRINT1("GuiConsoleNcCreate: SelectObject failed\n"); ReleaseDC(hWnd, Dc); HeapFree(Win32CsrApiHeap, 0, GuiData); return FALSE; } if (! GetTextMetricsW(Dc, &Metrics)) { - DbgPrint("GuiConsoleNcCreate: GetTextMetrics failed\n"); + DPRINT1("GuiConsoleNcCreate: GetTextMetrics failed\n"); SelectObject(Dc, OldFont); ReleaseDC(hWnd, Dc); HeapFree(Win32CsrApiHeap, 0, GuiData); @@ -110,7 +114,7 @@ GuiConsoleHandleNcCreate(HWND hWnd, CREATESTRUCTW *Create) GuiData->CursorBlinkOn = TRUE; GuiData->ForceCursorOff = FALSE; - Console->GuiConsoleData = GuiData; + Console->PrivateData = GuiData; SetWindowLongW(hWnd, GWL_USERDATA, (LONG) Console); GetWindowRect(hWnd, &Rect); @@ -178,13 +182,13 @@ GuiConsoleHandlePaint(HWND hWnd) if (NULL != Console && NULL != GuiData && NULL != Console->ActiveBuffer) { Buff = Console->ActiveBuffer; - EnterCriticalSection(&(Buff->Lock)); + EnterCriticalSection(&(Buff->Header.Lock)); Dc = BeginPaint(hWnd, &Ps); if (Ps.rcPaint.right <= Ps.rcPaint.left || Ps.rcPaint.bottom <= Ps.rcPaint.top) { EndPaint(hWnd, &Ps); - LeaveCriticalSection(&(Buff->Lock)); + LeaveCriticalSection(&(Buff->Header.Lock)); return; } OldFont = SelectObject(Dc, GuiData->Font); @@ -220,7 +224,8 @@ GuiConsoleHandlePaint(HWND hWnd) Attribute = *(From + 1); if (Attribute != LastAttribute) { - GuiConsoleSetTextColors(Dc, LastAttribute); + GuiConsoleSetTextColors(Dc, Attribute); + LastAttribute = Attribute; } } *((PBYTE) To) = *From; @@ -258,7 +263,7 @@ GuiConsoleHandlePaint(HWND hWnd) } EndPaint(hWnd, &Ps); - LeaveCriticalSection(&(Buff->Lock)); + LeaveCriticalSection(&(Buff->Header.Lock)); } else { @@ -280,7 +285,7 @@ GuiConsoleHandleKey(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) Message.wParam = wParam; Message.lParam = lParam; - CsrProcessKey(&Message, Console); + ConioProcessKey(&Message, Console, FALSE); } static VOID FASTCALL @@ -377,23 +382,149 @@ GuiConsoleHandleCopyRegion(HWND hWnd, PRECT Source, PRECT Dest) } } +static VOID FASTCALL +GuiIntDrawRegion(PGUI_CONSOLE_DATA GuiData, HWND Wnd, RECT *Region) +{ + RECT RegionRect; + + RegionRect.left = Region->left * GuiData->CharWidth; + RegionRect.top = Region->top * GuiData->CharHeight; + RegionRect.right = (Region->right + 1) * GuiData->CharWidth; + RegionRect.bottom = (Region->bottom + 1) * GuiData->CharHeight; + + InvalidateRect(Wnd, &RegionRect, FALSE); +} + +static VOID STDCALL +GuiDrawRegion(PCSRSS_CONSOLE Console, RECT *Region) +{ + PGUI_CONSOLE_DATA GuiData = (PGUI_CONSOLE_DATA) Console->PrivateData; + + if (NULL == Console->hWindow || NULL == GuiData) + { + return; + } + + GuiIntDrawRegion(GuiData, Console->hWindow, Region); +} + +static VOID FASTCALL +GuiInvalidateCell(PGUI_CONSOLE_DATA GuiData, HWND Wnd, UINT x, UINT y) +{ + RECT CellRect; + + CellRect.left = x; + CellRect.top = y; + CellRect.right = x; + CellRect.bottom = y; + + GuiIntDrawRegion(GuiData, Wnd, &CellRect); +} + +static VOID STDCALL +GuiWriteStream(PCSRSS_CONSOLE Console, RECT *Region, UINT CursorStartX, UINT CursorStartY, + UINT ScrolledLines, CHAR *Buffer, UINT Length) +{ + PGUI_CONSOLE_DATA GuiData = (PGUI_CONSOLE_DATA) Console->PrivateData; + PCSRSS_SCREEN_BUFFER Buff = Console->ActiveBuffer; + LONG CursorEndX, CursorEndY; + RECT Source, Dest; + + if (NULL == Console->hWindow || NULL == GuiData) + { + return; + } + + if (0 != ScrolledLines) + { + Source.left = 0; + Source.top = ScrolledLines; + Source.right = Console->Size.X - 1; + Source.bottom = ScrolledLines + Region->top - 1; + Dest.left = 0; + Dest.top = 0; + Dest.right = Console->Size.X - 1; + Dest.bottom = Region->top - 1; + + GuiConsoleCopyRegion(Console, &Source, &Dest); + } + + GuiIntDrawRegion(GuiData, Console->hWindow, Region); + + if (CursorStartX < Region->left || Region->right < CursorStartX + || CursorStartY < Region->top || Region->bottom < CursorStartY) + { + GuiInvalidateCell(GuiData, Console->hWindow, CursorStartX, CursorStartY); + } + + ConioPhysicalToLogical(Buff, Buff->CurrentX, Buff->CurrentY, + &CursorEndX, &CursorEndY); + if ((CursorEndX < Region->left || Region->right < CursorEndX + || CursorEndY < Region->top || Region->bottom < CursorEndY) + && (CursorEndX != CursorStartX || CursorEndY != CursorStartY)) + { + GuiInvalidateCell(GuiData, Console->hWindow, CursorEndX, CursorEndY); + } +} + +static BOOL STDCALL +GuiSetCursorInfo(PCSRSS_CONSOLE Console, PCSRSS_SCREEN_BUFFER Buff) +{ + RECT UpdateRect; + + if (Console->ActiveBuffer == Buff) + { + ConioPhysicalToLogical(Buff, Buff->CurrentX, Buff->CurrentY, + &UpdateRect.left, &UpdateRect.top); + UpdateRect.right = UpdateRect.left; + UpdateRect.bottom = UpdateRect.top; + ConioDrawRegion(Console, &UpdateRect); + } + + return TRUE; +} + +static BOOL STDCALL +GuiSetScreenInfo(PCSRSS_CONSOLE Console, PCSRSS_SCREEN_BUFFER Buff, UINT OldCursorX, UINT OldCursorY) +{ + RECT UpdateRect; + + if (Console->ActiveBuffer == Buff) + { + /* Redraw char at old position (removes cursor) */ + UpdateRect.left = OldCursorX; + UpdateRect.top = OldCursorY; + UpdateRect.right = OldCursorX; + UpdateRect.bottom = OldCursorY; + ConioDrawRegion(Console, &UpdateRect); + /* Redraw char at new position (shows cursor) */ + ConioPhysicalToLogical(Buff, Buff->CurrentX, Buff->CurrentY, + &(UpdateRect.left), &(UpdateRect.top)); + UpdateRect.right = UpdateRect.left; + UpdateRect.bottom = UpdateRect.top; + ConioDrawRegion(Console, &UpdateRect); + } + + return TRUE; +} + static VOID FASTCALL GuiConsoleHandleTimer(HWND hWnd) { PCSRSS_CONSOLE Console; PGUI_CONSOLE_DATA GuiData; - SMALL_RECT CursorRect; + RECT CursorRect; ULONG CursorX, CursorY; GuiConsoleGetDataPointers(hWnd, &Console, &GuiData); GuiData->CursorBlinkOn = ! GuiData->CursorBlinkOn; GuiConsoleGetLogicalCursorPos(Console->ActiveBuffer, &CursorX, &CursorY); - CursorRect.Left = CursorX; - CursorRect.Top = CursorY; - CursorRect.Right = CursorX; - CursorRect.Bottom = CursorY; - GuiConsoleDrawRegion(Console, CursorRect); + CursorRect.left = CursorX; + CursorRect.top = CursorY; + CursorRect.right = CursorX; + CursorRect.bottom = CursorY; + GuiDrawRegion(Console, &CursorRect); } static VOID FASTCALL @@ -410,7 +541,7 @@ GuiConsoleHandleNcDestroy(HWND hWnd) GuiConsoleGetDataPointers(hWnd, &Console, &GuiData); KillTimer(hWnd, 1); - Console->GuiConsoleData = NULL; + Console->PrivateData = NULL; HeapFree(Win32CsrApiHeap, 0, GuiData); } @@ -546,8 +677,8 @@ GuiConsoleGuiThread(PVOID Data) return 1; } -VOID FASTCALL -GuiConsoleInitConsoleSupport(VOID) +static BOOL FASTCALL +GuiInit(VOID) { HDESK Desktop; NTSTATUS Status; @@ -556,8 +687,8 @@ GuiConsoleInitConsoleSupport(VOID) Desktop = OpenDesktopW(L"Default", 0, FALSE, GENERIC_ALL); if (NULL == Desktop) { - DbgPrint("Win32Csr: failed to open desktop\n"); - return; + DPRINT1("Failed to open desktop\n"); + return FALSE; } Status = NtSetInformationProcess(NtCurrentProcess(), ProcessDesktop, @@ -565,13 +696,13 @@ GuiConsoleInitConsoleSupport(VOID) sizeof(Desktop)); if (!NT_SUCCESS(Status)) { - DbgPrint("Win32Csr: cannot set default desktop.\n"); - return; + DPRINT1("Cannot set default desktop.\n"); + return FALSE; } if (! SetThreadDesktop(Desktop)) { - DbgPrint("Win32Csr: failed to set thread desktop\n"); - return; + DPRINT1("Failed to set thread desktop\n"); + return FALSE; } wc.lpszClassName = L"Win32CsrCreateNotify"; @@ -586,7 +717,8 @@ GuiConsoleInitConsoleSupport(VOID) wc.cbWndExtra = 0; if (RegisterClassW(&wc) == 0) { - return; + DPRINT1("Failed to register notify wndproc\n"); + return FALSE; } wc.lpszClassName = L"Win32CsrConsole"; @@ -601,16 +733,61 @@ GuiConsoleInitConsoleSupport(VOID) wc.cbWndExtra = 0; if (RegisterClassW(&wc) == 0) { - return; + DPRINT1("Failed to register console wndproc\n"); + return FALSE; } + + return TRUE; } -BOOL STDCALL -GuiConsoleInitConsole(PCSRSS_CONSOLE Console) +static VOID STDCALL +GuiInitScreenBuffer(PCSRSS_CONSOLE Console, PCSRSS_SCREEN_BUFFER Buffer) +{ + Buffer->DefaultAttrib = 0x0f; +} + +STATIC BOOL STDCALL +GuiChangeTitle(PCSRSS_CONSOLE Console) +{ + SendMessageW(Console->hWindow, WM_SETTEXT, 0, (LPARAM) Console->Title.Buffer); + + return TRUE; +} + +static VOID STDCALL +GuiCleanupConsole(PCSRSS_CONSOLE Console) +{ + SendMessageW(NotifyWnd, PM_DESTROY_CONSOLE, 0, (LPARAM) Console); +} + +static CSRSS_CONSOLE_VTBL GuiVtbl = +{ + GuiInitScreenBuffer, + GuiWriteStream, + GuiDrawRegion, + GuiSetCursorInfo, + GuiSetScreenInfo, + GuiChangeTitle, + GuiCleanupConsole +}; + +NTSTATUS FASTCALL +GuiInitConsole(PCSRSS_CONSOLE Console) { HANDLE GraphicsStartupEvent; HANDLE ThreadHandle; + if (! Initialized) + { + Initialized = TRUE; + if (! GuiInit()) + { + Initialized = FALSE; + return STATUS_UNSUCCESSFUL; + } + } + + Console->Vtbl = &GuiVtbl; Console->Size.X = 80; Console->Size.Y = 25; if (NULL == NotifyWnd) @@ -618,7 +795,7 @@ GuiConsoleInitConsole(PCSRSS_CONSOLE Console) GraphicsStartupEvent = CreateEventW(NULL, FALSE, FALSE, NULL); if (NULL == GraphicsStartupEvent) { - return FALSE; + return STATUS_UNSUCCESSFUL; } ThreadHandle = CreateThread(NULL, @@ -630,8 +807,8 @@ GuiConsoleInitConsole(PCSRSS_CONSOLE Console) if (NULL == ThreadHandle) { NtClose(GraphicsStartupEvent); - DbgPrint("Win32Csr: Failed to create graphics console thread. Expect problems\n"); - return FALSE; + DPRINT1("Win32Csr: Failed to create graphics console thread. Expect problems\n"); + return STATUS_UNSUCCESSFUL; } CloseHandle(ThreadHandle); @@ -640,33 +817,14 @@ GuiConsoleInitConsole(PCSRSS_CONSOLE Console) if (NULL == NotifyWnd) { - DbgPrint("Win32Csr: Failed to create notification window.\n"); - return FALSE; + DPRINT1("Win32Csr: Failed to create notification window.\n"); + return STATUS_UNSUCCESSFUL; } } PostMessageW(NotifyWnd, PM_CREATE_CONSOLE, 0, (LPARAM) Console); - return TRUE; -} - -VOID STDCALL -GuiConsoleDrawRegion(PCSRSS_CONSOLE Console, SMALL_RECT Region) -{ - PGUI_CONSOLE_DATA GuiData = (PGUI_CONSOLE_DATA) Console->GuiConsoleData; - RECT RegionRect; - - if (NULL == Console->hWindow || NULL == GuiData) - { - return; - } - - RegionRect.left = Region.Left * GuiData->CharWidth; - RegionRect.top = Region.Top * GuiData->CharHeight; - RegionRect.right = (Region.Right + 1) * GuiData->CharWidth; - RegionRect.bottom = (Region.Bottom + 1) * GuiData->CharHeight; - - InvalidateRect(Console->hWindow, &RegionRect, FALSE); + return STATUS_SUCCESS; } VOID STDCALL @@ -674,21 +832,9 @@ GuiConsoleCopyRegion(PCSRSS_CONSOLE Console, RECT *Source, RECT *Dest) { - LeaveCriticalSection(&(Console->ActiveBuffer->Lock)); + LeaveCriticalSection(&(Console->ActiveBuffer->Header.Lock)); SendMessageW(Console->hWindow, PM_COPY_REGION, (WPARAM) Source, (LPARAM) Dest); - EnterCriticalSection(&(Console->ActiveBuffer->Lock)); -} - -VOID STDCALL -GuiConsoleChangeTitle(PCSRSS_CONSOLE Console) -{ - SendMessageW(Console->hWindow, WM_SETTEXT, 0, (LPARAM) Console->Title.Buffer); -} - -VOID STDCALL -GuiConsoleDeleteConsole(PCSRSS_CONSOLE Console) -{ - SendMessageW(NotifyWnd, PM_DESTROY_CONSOLE, 0, (LPARAM) Console); + EnterCriticalSection(&(Console->ActiveBuffer->Header.Lock)); } /* EOF */ diff --git a/reactos/subsys/csrss/win32csr/guiconsole.h b/reactos/subsys/csrss/win32csr/guiconsole.h index 62bcb31f16f..578ab6625a4 100644 --- a/reactos/subsys/csrss/win32csr/guiconsole.h +++ b/reactos/subsys/csrss/win32csr/guiconsole.h @@ -1,4 +1,4 @@ -/* $Id: guiconsole.h,v 1.1 2003/12/02 11:38:46 gvg Exp $ +/* $Id: guiconsole.h,v 1.2 2004/01/11 17:31:16 gvg Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS system libraries @@ -8,7 +8,7 @@ #include "api.h" -extern BOOL STDCALL GuiConsoleInitConsole(PCSRSS_CONSOLE Console); +extern NTSTATUS FASTCALL GuiInitConsole(PCSRSS_CONSOLE Console); extern VOID STDCALL GuiConsoleDrawRegion(PCSRSS_CONSOLE Console, SMALL_RECT Region); extern VOID STDCALL GuiConsoleCopyRegion(PCSRSS_CONSOLE Console, RECT *Source, @@ -16,6 +16,4 @@ extern VOID STDCALL GuiConsoleCopyRegion(PCSRSS_CONSOLE Console, extern VOID STDCALL GuiConsoleChangeTitle(PCSRSS_CONSOLE Console); extern VOID STDCALL GuiConsoleDeleteConsole(PCSRSS_CONSOLE Console); -extern VOID FASTCALL GuiConsoleInitConsoleSupport(VOID); - /*EOF*/ diff --git a/reactos/subsys/csrss/win32csr/tuiconsole.c b/reactos/subsys/csrss/win32csr/tuiconsole.c new file mode 100644 index 00000000000..ac7bc99dc3d --- /dev/null +++ b/reactos/subsys/csrss/win32csr/tuiconsole.c @@ -0,0 +1,346 @@ +/* $Id: tuiconsole.c,v 1.1 2004/01/11 17:31:16 gvg Exp $ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: subsys/csrss/win32csr/tuiconsole.c + * PURPOSE: Implementation of text-mode consoles + */ + +#include +#include +#include +#include "api.h" +#include "conio.h" +#include "tuiconsole.h" +#include "win32csr.h" + +#define NDEBUG +#include + +CRITICAL_SECTION ActiveConsoleLock; +static COORD PhysicalConsoleSize; +static HANDLE ConsoleDeviceHandle; +static PCSRSS_CONSOLE ActiveConsole; + +static BOOL Initialized = FALSE; + +static BOOL FASTCALL +TuiInit(VOID) +{ + CONSOLE_SCREEN_BUFFER_INFO ScrInfo; + DWORD BytesReturned; + + ConsoleDeviceHandle = CreateFileW(L"\\\\.\\BlueScreen", FILE_ALL_ACCESS, 0, NULL, + OPEN_EXISTING, 0, NULL); + if (INVALID_HANDLE_VALUE == ConsoleDeviceHandle) + { + DPRINT1("Failed to open BlueScreen.\n"); + return FALSE; + } + + ActiveConsole = NULL; + InitializeCriticalSection(&ActiveConsoleLock); + if (! DeviceIoControl(ConsoleDeviceHandle, IOCTL_CONSOLE_GET_SCREEN_BUFFER_INFO, + NULL, 0, &ScrInfo, sizeof(ScrInfo), &BytesReturned, NULL)) + { + DPRINT1("Failed to get console info\n"); + return FALSE; + } + PhysicalConsoleSize = ScrInfo.dwSize; + + return TRUE; +} + +static VOID STDCALL +TuiInitScreenBuffer(PCSRSS_CONSOLE Console, PCSRSS_SCREEN_BUFFER Buffer) +{ + Buffer->DefaultAttrib = 0x17; +} + +static void FASTCALL +TuiCopyRect(char *Dest, PCSRSS_SCREEN_BUFFER Buff, RECT *Region) +{ + UINT SrcDelta, DestDelta, i; + char *Src, *SrcEnd; + + Src = Buff->Buffer + (((Region->top + Buff->ShowY) % Buff->MaxY) * Buff->MaxX + + Region->left + Buff->ShowX) * 2; + SrcDelta = Buff->MaxX * 2; + SrcEnd = Buff->Buffer + Buff->MaxY * Buff->MaxX * 2; + DestDelta = ConioRectWidth(Region) * 2; + for (i = Region->top; i <= Region->bottom; i++) + { + memcpy(Dest, Src, DestDelta); + Src += SrcDelta; + if (SrcEnd <= Src) + { + Src -= Buff->MaxY * Buff->MaxX * 2; + } + Dest += DestDelta; + } +} + +static VOID STDCALL +TuiDrawRegion(PCSRSS_CONSOLE Console, RECT *Region) +{ + DWORD BytesReturned; + PCSRSS_SCREEN_BUFFER Buff = Console->ActiveBuffer; + LONG CursorX, CursorY; + PCONSOLE_DRAW ConsoleDraw; + UINT ConsoleDrawSize; + + if (ActiveConsole != Console) + { + return; + } + + ConsoleDrawSize = sizeof(CONSOLE_DRAW) + + (ConioRectWidth(Region) * ConioRectHeight(Region)) * 2; + ConsoleDraw = HeapAlloc(Win32CsrApiHeap, 0, ConsoleDrawSize); + if (NULL == ConsoleDraw) + { + DPRINT1("HeapAlloc failed\n"); + return; + } + ConioPhysicalToLogical(Buff, Buff->CurrentX, Buff->CurrentY, &CursorX, &CursorY); + ConsoleDraw->X = Region->left; + ConsoleDraw->Y = Region->top; + ConsoleDraw->SizeX = ConioRectWidth(Region); + ConsoleDraw->SizeY = ConioRectHeight(Region); + ConsoleDraw->CursorX = CursorX; + ConsoleDraw->CursorY = CursorY; + + TuiCopyRect((char *) (ConsoleDraw + 1), Buff, Region); + + if (! DeviceIoControl(ConsoleDeviceHandle, IOCTL_CONSOLE_DRAW, + ConsoleDraw, ConsoleDrawSize, NULL, 0, &BytesReturned, NULL)) + { + DPRINT1("Failed to draw console\n"); + HeapFree(Win32CsrApiHeap, 0, ConsoleDraw); + return; + } + + HeapFree(Win32CsrApiHeap, 0, ConsoleDraw); +} + +static VOID STDCALL +TuiWriteStream(PCSRSS_CONSOLE Console, RECT *Region, UINT CursorStartX, UINT CursorStartY, + UINT ScrolledLines, CHAR *Buffer, UINT Length) +{ + DWORD BytesWritten; + PCSRSS_SCREEN_BUFFER Buff = Console->ActiveBuffer; + + if (ActiveConsole->ActiveBuffer != Buff) + { + return; + } + + if (! WriteFile(ConsoleDeviceHandle, Buffer, Length, &BytesWritten, NULL)) + { + DPRINT1("Error writing to BlueScreen\n"); + } +} + +static BOOL STDCALL +TuiSetCursorInfo(PCSRSS_CONSOLE Console, PCSRSS_SCREEN_BUFFER Buff) +{ + DWORD BytesReturned; + + if (ActiveConsole->ActiveBuffer != Buff) + { + return TRUE; + } + + if (! DeviceIoControl(ConsoleDeviceHandle, IOCTL_CONSOLE_SET_CURSOR_INFO, + &Buff->CursorInfo, sizeof(Buff->CursorInfo), NULL, 0, + &BytesReturned, NULL)) + { + DPRINT1( "Failed to set cursor info\n" ); + return FALSE; + } + + return TRUE; +} + +static BOOL STDCALL +TuiSetScreenInfo(PCSRSS_CONSOLE Console, PCSRSS_SCREEN_BUFFER Buff, UINT OldCursorX, UINT OldCursorY) +{ + CONSOLE_SCREEN_BUFFER_INFO Info; + LONG CursorX, CursorY; + DWORD BytesReturned; + + if (ActiveConsole->ActiveBuffer != Buff) + { + return TRUE; + } + + ConioPhysicalToLogical(Buff, Buff->CurrentX, Buff->CurrentY, &CursorX, &CursorY); + Info.dwCursorPosition.X = CursorX; + Info.dwCursorPosition.Y = CursorY; + Info.wAttributes = Buff->DefaultAttrib; + + if (! DeviceIoControl(ConsoleDeviceHandle, IOCTL_CONSOLE_SET_SCREEN_BUFFER_INFO, + &Info, sizeof(CONSOLE_SCREEN_BUFFER_INFO), NULL, 0, + &BytesReturned, NULL)) + { + DPRINT1( "Failed to set cursor position\n" ); + return FALSE; + } + + return TRUE; +} + +STATIC BOOL STDCALL +TuiChangeTitle(PCSRSS_CONSOLE Console) +{ + return TRUE; +} + +STATIC VOID STDCALL +TuiCleanupConsole(PCSRSS_CONSOLE Console) +{ + EnterCriticalSection(&ActiveConsoleLock); + + /* Switch to next console */ + if (ActiveConsole == Console) + { + ActiveConsole = Console->Next != Console ? Console->Next : NULL; + } + + if (Console->Next != Console) + { + Console->Prev->Next = Console->Next; + Console->Next->Prev = Console->Prev; + } + LeaveCriticalSection(&ActiveConsoleLock); + + if (NULL != ActiveConsole) + { + ConioDrawConsole(ActiveConsole); + } +} + +static CSRSS_CONSOLE_VTBL TuiVtbl = +{ + TuiInitScreenBuffer, + TuiWriteStream, + TuiDrawRegion, + TuiSetCursorInfo, + TuiSetScreenInfo, + TuiChangeTitle, + TuiCleanupConsole +}; + +NTSTATUS FASTCALL +TuiInitConsole(PCSRSS_CONSOLE Console) +{ + if (! Initialized) + { + Initialized = TRUE; + if (! TuiInit()) + { + Initialized = FALSE; + return STATUS_UNSUCCESSFUL; + } + } + + Console->Vtbl = &TuiVtbl; + Console->hWindow = (HWND) NULL; + Console->Size = PhysicalConsoleSize; + + EnterCriticalSection(&ActiveConsoleLock); + if (NULL != ActiveConsole) + { + Console->Prev = ActiveConsole; + Console->Next = ActiveConsole->Next; + ActiveConsole->Next->Prev = Console; + ActiveConsole->Next = Console; + } + else + { + Console->Prev = Console; + Console->Next = Console; + } + ActiveConsole = Console; + LeaveCriticalSection(&ActiveConsoleLock); + + return STATUS_SUCCESS; +} + +PCSRSS_CONSOLE FASTCALL +TuiGetFocusConsole(VOID) +{ + return ActiveConsole; +} + +BOOL FASTCALL +TuiSwapConsole(int Next) +{ + static PCSRSS_CONSOLE SwapConsole = NULL; /* console we are thinking about swapping with */ + DWORD BytesReturned; + ANSI_STRING Title; + void * Buffer; + COORD *pos; + + if (0 != Next) + { + /* alt-tab, swap consoles */ + /* move SwapConsole to next console, and print its title */ + EnterCriticalSection(&ActiveConsoleLock); + if (! SwapConsole) + { + SwapConsole = ActiveConsole; + } + + SwapConsole = (0 < Next ? SwapConsole->Next : SwapConsole->Prev); + Title.MaximumLength = RtlUnicodeStringToAnsiSize(&SwapConsole->Title); + Title.Length = 0; + Buffer = HeapAlloc(Win32CsrApiHeap, + 0, + sizeof(COORD) + Title.MaximumLength); + pos = (COORD *)Buffer; + Title.Buffer = Buffer + sizeof( COORD ); + + RtlUnicodeStringToAnsiString(&Title, &SwapConsole->Title, FALSE); + pos->Y = PhysicalConsoleSize.Y / 2; + pos->X = (PhysicalConsoleSize.X - Title.Length) / 2; + /* redraw the console to clear off old title */ + ConioDrawConsole(ActiveConsole); + if (! DeviceIoControl(ConsoleDeviceHandle, IOCTL_CONSOLE_WRITE_OUTPUT_CHARACTER, + Buffer, sizeof(COORD) + Title.Length, NULL, 0, + &BytesReturned, NULL)) + { + DPRINT1( "Error writing to console\n" ); + } + HeapFree(Win32CsrApiHeap, 0, Buffer); + LeaveCriticalSection(&ActiveConsoleLock); + + return TRUE; + } + else if (NULL != SwapConsole) + { + EnterCriticalSection(&ActiveConsoleLock); + if (SwapConsole != ActiveConsole) + { + /* first remove swapconsole from the list */ + SwapConsole->Prev->Next = SwapConsole->Next; + SwapConsole->Next->Prev = SwapConsole->Prev; + /* now insert before activeconsole */ + SwapConsole->Next = ActiveConsole; + SwapConsole->Prev = ActiveConsole->Prev; + ActiveConsole->Prev->Next = SwapConsole; + ActiveConsole->Prev = SwapConsole; + } + ActiveConsole = SwapConsole; + SwapConsole = NULL; + ConioDrawConsole(ActiveConsole); + LeaveCriticalSection(&ActiveConsoleLock); + return TRUE; + } + else + { + return FALSE; + } +} + +/* EOF */ diff --git a/reactos/subsys/csrss/win32csr/tuiconsole.h b/reactos/subsys/csrss/win32csr/tuiconsole.h new file mode 100644 index 00000000000..85302bb0e59 --- /dev/null +++ b/reactos/subsys/csrss/win32csr/tuiconsole.h @@ -0,0 +1,15 @@ +/* $Id: tuiconsole.h,v 1.1 2004/01/11 17:31:16 gvg Exp $ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: subsys/csrss/win32csr/tuiconsole.h + * PURPOSE: Interface to text-mode consoles + */ + +#include "api.h" + +extern NTSTATUS FASTCALL TuiInitConsole(PCSRSS_CONSOLE Console); +extern PCSRSS_CONSOLE FASTCALL TuiGetFocusConsole(VOID); +extern BOOL FASTCALL TuiSwapConsole(int Next); + +/* EOF */