/* * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS Console Server DLL * FILE: win32ss/user/winsrv/consrv/conoutput.c * PURPOSE: General Console Output Functions * PROGRAMMERS: Jeffrey Morlan * Hermes Belusca-Maito (hermes.belusca@sfr.fr) */ /* INCLUDES *******************************************************************/ #include "consrv.h" #define NDEBUG #include /* PUBLIC SERVER APIS *********************************************************/ NTSTATUS NTAPI ConDrvInvalidateBitMapRect(IN PCONSOLE Console, IN PCONSOLE_SCREEN_BUFFER Buffer, IN PSMALL_RECT Region); CSR_API(SrvInvalidateBitMapRect) { NTSTATUS Status; PCONSOLE_INVALIDATEDIBITS InvalidateDIBitsRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.InvalidateDIBitsRequest; PCONSOLE_SCREEN_BUFFER Buffer; DPRINT("SrvInvalidateBitMapRect\n"); Status = ConSrvGetScreenBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process), InvalidateDIBitsRequest->OutputHandle, &Buffer, GENERIC_READ, TRUE); if (!NT_SUCCESS(Status)) return Status; Status = ConDrvInvalidateBitMapRect(Buffer->Header.Console, Buffer, &InvalidateDIBitsRequest->Region); ConSrvReleaseScreenBuffer(Buffer, TRUE); return Status; } NTSTATUS NTAPI ConDrvSetConsolePalette(IN PCONSOLE Console, // IN PGRAPHICS_SCREEN_BUFFER Buffer, IN PCONSOLE_SCREEN_BUFFER Buffer, IN HPALETTE PaletteHandle, IN UINT PaletteUsage); CSR_API(SrvSetConsolePalette) { NTSTATUS Status; PCONSOLE_SETPALETTE SetPaletteRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.SetPaletteRequest; // PGRAPHICS_SCREEN_BUFFER Buffer; PCONSOLE_SCREEN_BUFFER Buffer; DPRINT("SrvSetConsolePalette\n"); // NOTE: Tests show that this function is used only for graphics screen buffers // and otherwise it returns FALSE + sets last error to invalid handle. // I think it's ridiculous, because if you are in text mode, simulating // a change of VGA palette via DAC registers (done by a call to SetConsolePalette) // cannot be done... So I allow it in ReactOS ! /* Status = ConSrvGetGraphicsBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process), SetPaletteRequest->OutputHandle, &Buffer, GENERIC_WRITE, TRUE); */ Status = ConSrvGetScreenBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process), SetPaletteRequest->OutputHandle, &Buffer, GENERIC_WRITE, TRUE); if (!NT_SUCCESS(Status)) return Status; /* * Make the palette handle public, so that it can be * used by other threads calling GDI functions on it. * Indeed, the palette handle comes from a console app * calling ourselves, running in CSRSS. */ NtUserConsoleControl(ConsoleMakePalettePublic, &SetPaletteRequest->PaletteHandle, sizeof(SetPaletteRequest->PaletteHandle)); Status = ConDrvSetConsolePalette(Buffer->Header.Console, Buffer, SetPaletteRequest->PaletteHandle, SetPaletteRequest->Usage); ConSrvReleaseScreenBuffer(Buffer, TRUE); return Status; } NTSTATUS NTAPI ConDrvGetConsoleCursorInfo(IN PCONSOLE Console, IN PTEXTMODE_SCREEN_BUFFER Buffer, OUT PCONSOLE_CURSOR_INFO CursorInfo); CSR_API(SrvGetConsoleCursorInfo) { NTSTATUS Status; PCONSOLE_GETSETCURSORINFO CursorInfoRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.CursorInfoRequest; PTEXTMODE_SCREEN_BUFFER Buffer; DPRINT("SrvGetConsoleCursorInfo\n"); Status = ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process), CursorInfoRequest->OutputHandle, &Buffer, GENERIC_READ, TRUE); if (!NT_SUCCESS(Status)) return Status; Status = ConDrvGetConsoleCursorInfo(Buffer->Header.Console, Buffer, &CursorInfoRequest->Info); ConSrvReleaseScreenBuffer(Buffer, TRUE); return Status; } NTSTATUS NTAPI ConDrvSetConsoleCursorInfo(IN PCONSOLE Console, IN PTEXTMODE_SCREEN_BUFFER Buffer, IN PCONSOLE_CURSOR_INFO CursorInfo); CSR_API(SrvSetConsoleCursorInfo) { NTSTATUS Status; PCONSOLE_GETSETCURSORINFO CursorInfoRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.CursorInfoRequest; PTEXTMODE_SCREEN_BUFFER Buffer; DPRINT("SrvSetConsoleCursorInfo\n"); Status = ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process), CursorInfoRequest->OutputHandle, &Buffer, GENERIC_WRITE, TRUE); if (!NT_SUCCESS(Status)) return Status; Status = ConDrvSetConsoleCursorInfo(Buffer->Header.Console, Buffer, &CursorInfoRequest->Info); ConSrvReleaseScreenBuffer(Buffer, TRUE); return Status; } NTSTATUS NTAPI ConDrvSetConsoleCursorPosition(IN PCONSOLE Console, IN PTEXTMODE_SCREEN_BUFFER Buffer, IN PCOORD Position); CSR_API(SrvSetConsoleCursorPosition) { NTSTATUS Status; PCONSOLE_SETCURSORPOSITION SetCursorPositionRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.SetCursorPositionRequest; PTEXTMODE_SCREEN_BUFFER Buffer; DPRINT("SrvSetConsoleCursorPosition\n"); Status = ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process), SetCursorPositionRequest->OutputHandle, &Buffer, GENERIC_WRITE, TRUE); if (!NT_SUCCESS(Status)) return Status; Status = ConDrvSetConsoleCursorPosition(Buffer->Header.Console, Buffer, &SetCursorPositionRequest->Position); ConSrvReleaseScreenBuffer(Buffer, TRUE); return Status; } CSR_API(SrvCreateConsoleScreenBuffer) { NTSTATUS Status = STATUS_INVALID_PARAMETER; PCONSOLE_CREATESCREENBUFFER CreateScreenBufferRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.CreateScreenBufferRequest; PCONSOLE_PROCESS_DATA ProcessData = ConsoleGetPerProcessData(CsrGetClientThread()->Process); PCONSOLE Console; PCONSOLE_SCREEN_BUFFER Buff; PVOID ScreenBufferInfo = NULL; TEXTMODE_BUFFER_INFO TextModeInfo = {{80, 25}, DEFAULT_SCREEN_ATTRIB, DEFAULT_POPUP_ATTRIB , TRUE, CSR_DEFAULT_CURSOR_SIZE}; GRAPHICS_BUFFER_INFO GraphicsInfo; GraphicsInfo.Info = CreateScreenBufferRequest->GraphicsBufferInfo; // HACK for MSVC DPRINT("SrvCreateConsoleScreenBuffer\n"); Status = ConSrvGetConsole(ProcessData, &Console, TRUE); if (!NT_SUCCESS(Status)) return Status; if (CreateScreenBufferRequest->ScreenBufferType == CONSOLE_TEXTMODE_BUFFER) { ScreenBufferInfo = &TextModeInfo; /* if (Console->ActiveBuffer) { TextModeInfo.ScreenBufferSize = Console->ActiveBuffer->ScreenBufferSize; if (TextModeInfo.ScreenBufferSize.X == 0) TextModeInfo.ScreenBufferSize.X = 80; if (TextModeInfo.ScreenBufferSize.Y == 0) TextModeInfo.ScreenBufferSize.Y = 25; TextModeInfo.ScreenAttrib = Console->ActiveBuffer->ScreenBuffer.TextBuffer.ScreenDefaultAttrib; TextModeInfo.PopupAttrib = Console->ActiveBuffer->ScreenBuffer.TextBuffer.PopupDefaultAttrib; TextModeInfo.IsCursorVisible = Console->ActiveBuffer->CursorInfo.bVisible; TextModeInfo.CursorSize = Console->ActiveBuffer->CursorInfo.dwSize; } */ /* * This is Windows' behaviour */ /* Use the current console size. Regularize it if needed. */ TextModeInfo.ScreenBufferSize = Console->ConsoleSize; if (TextModeInfo.ScreenBufferSize.X == 0) TextModeInfo.ScreenBufferSize.X = 1; if (TextModeInfo.ScreenBufferSize.Y == 0) TextModeInfo.ScreenBufferSize.Y = 1; /* If we have an active screen buffer, use its attributes as the new ones */ if (Console->ActiveBuffer && GetType(Console->ActiveBuffer) == TEXTMODE_BUFFER) { PTEXTMODE_SCREEN_BUFFER Buffer = (PTEXTMODE_SCREEN_BUFFER)Console->ActiveBuffer; TextModeInfo.ScreenAttrib = Buffer->ScreenDefaultAttrib; TextModeInfo.PopupAttrib = Buffer->PopupDefaultAttrib; TextModeInfo.IsCursorVisible = Buffer->CursorInfo.bVisible; TextModeInfo.CursorSize = Buffer->CursorInfo.dwSize; } } else if (CreateScreenBufferRequest->ScreenBufferType == CONSOLE_GRAPHICS_BUFFER) { /* Get infos from the graphics buffer information structure */ if (!CsrValidateMessageBuffer(ApiMessage, (PVOID*)&CreateScreenBufferRequest->GraphicsBufferInfo.lpBitMapInfo, CreateScreenBufferRequest->GraphicsBufferInfo.dwBitMapInfoLength, sizeof(BYTE))) { Status = STATUS_INVALID_PARAMETER; goto Quit; } ScreenBufferInfo = &GraphicsInfo; /* Initialize shared variables */ // CreateScreenBufferRequest->GraphicsBufferInfo.hMutex CreateScreenBufferRequest->hMutex = GraphicsInfo.Info.hMutex = INVALID_HANDLE_VALUE; // CreateScreenBufferRequest->GraphicsBufferInfo.lpBitMap CreateScreenBufferRequest->lpBitMap = GraphicsInfo.Info.lpBitMap = NULL; /* A graphics screen buffer is never inheritable */ CreateScreenBufferRequest->InheritHandle = FALSE; } Status = ConDrvCreateScreenBuffer(&Buff, Console, CreateScreenBufferRequest->ScreenBufferType, ScreenBufferInfo); if (!NT_SUCCESS(Status)) goto Quit; /* Insert the new handle inside the process handles table */ RtlEnterCriticalSection(&ProcessData->HandleTableLock); Status = ConSrvInsertObject(ProcessData, &CreateScreenBufferRequest->OutputHandle, &Buff->Header, CreateScreenBufferRequest->DesiredAccess, CreateScreenBufferRequest->InheritHandle, CreateScreenBufferRequest->ShareMode); RtlLeaveCriticalSection(&ProcessData->HandleTableLock); if (!NT_SUCCESS(Status)) goto Quit; if (CreateScreenBufferRequest->ScreenBufferType == CONSOLE_GRAPHICS_BUFFER) { PGRAPHICS_SCREEN_BUFFER Buffer = (PGRAPHICS_SCREEN_BUFFER)Buff; /* * Initialize the graphics buffer information structure * and give it back to the client. */ // CreateScreenBufferRequest->GraphicsBufferInfo.hMutex CreateScreenBufferRequest->hMutex = Buffer->ClientMutex; // CreateScreenBufferRequest->GraphicsBufferInfo.lpBitMap CreateScreenBufferRequest->lpBitMap = Buffer->ClientBitMap; } Quit: ConSrvReleaseConsole(Console, TRUE); return Status; } NTSTATUS NTAPI ConDrvSetConsoleActiveScreenBuffer(IN PCONSOLE Console, IN PCONSOLE_SCREEN_BUFFER Buffer); CSR_API(SrvSetConsoleActiveScreenBuffer) { NTSTATUS Status; PCONSOLE_SETACTIVESCREENBUFFER SetScreenBufferRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.SetScreenBufferRequest; PCONSOLE_SCREEN_BUFFER Buffer; DPRINT("SrvSetConsoleActiveScreenBuffer\n"); Status = ConSrvGetScreenBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process), SetScreenBufferRequest->OutputHandle, &Buffer, GENERIC_WRITE, TRUE); if (!NT_SUCCESS(Status)) return Status; Status = ConDrvSetConsoleActiveScreenBuffer(Buffer->Header.Console, Buffer); ConSrvReleaseScreenBuffer(Buffer, TRUE); return Status; } /* CSR THREADS FOR WriteConsole ***********************************************/ static NTSTATUS DoWriteConsole(IN PCSR_API_MESSAGE ApiMessage, IN PCSR_THREAD ClientThread, IN BOOLEAN CreateWaitBlock OPTIONAL); // Wait function CSR_WAIT_FUNCTION static BOOLEAN NTAPI WriteConsoleThread(IN PLIST_ENTRY WaitList, IN PCSR_THREAD WaitThread, IN PCSR_API_MESSAGE WaitApiMessage, IN PVOID WaitContext, IN PVOID WaitArgument1, IN PVOID WaitArgument2, IN ULONG WaitFlags) { NTSTATUS Status; DPRINT("WriteConsoleThread - WaitContext = 0x%p, WaitArgument1 = 0x%p, WaitArgument2 = 0x%p, WaitFlags = %lu\n", WaitContext, WaitArgument1, WaitArgument2, WaitFlags); /* * If we are notified of the process termination via a call * to CsrNotifyWaitBlock triggered by CsrDestroyProcess or * CsrDestroyThread, just return. */ if (WaitFlags & CsrProcessTerminating) { Status = STATUS_THREAD_IS_TERMINATING; goto Quit; } Status = DoWriteConsole(WaitApiMessage, WaitThread, FALSE); Quit: if (Status != STATUS_PENDING) { WaitApiMessage->Status = Status; } return (Status == STATUS_PENDING ? FALSE : TRUE); } NTSTATUS NTAPI ConDrvWriteConsole(IN PCONSOLE Console, IN PTEXTMODE_SCREEN_BUFFER ScreenBuffer, IN BOOLEAN Unicode, IN PVOID StringBuffer, IN ULONG NumCharsToWrite, OUT PULONG NumCharsWritten OPTIONAL); static NTSTATUS DoWriteConsole(IN PCSR_API_MESSAGE ApiMessage, IN PCSR_THREAD ClientThread, IN BOOLEAN CreateWaitBlock OPTIONAL) { NTSTATUS Status; PCONSOLE_WRITECONSOLE WriteConsoleRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.WriteConsoleRequest; PTEXTMODE_SCREEN_BUFFER ScreenBuffer; Status = ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(ClientThread->Process), WriteConsoleRequest->OutputHandle, &ScreenBuffer, GENERIC_WRITE, FALSE); if (!NT_SUCCESS(Status)) return Status; Status = ConDrvWriteConsole(ScreenBuffer->Header.Console, ScreenBuffer, WriteConsoleRequest->Unicode, WriteConsoleRequest->Buffer, WriteConsoleRequest->NrCharactersToWrite, &WriteConsoleRequest->NrCharactersWritten); if (Status == STATUS_PENDING) { if (CreateWaitBlock) { if (!CsrCreateWait(&ScreenBuffer->Header.Console->WriteWaitQueue, WriteConsoleThread, ClientThread, ApiMessage, NULL)) { /* Fail */ Status = STATUS_NO_MEMORY; goto Quit; } } /* Wait until we un-pause the console */ // Status = STATUS_PENDING; } Quit: ConSrvReleaseScreenBuffer(ScreenBuffer, FALSE); return Status; } /* TEXT OUTPUT APIS ***********************************************************/ NTSTATUS NTAPI ConDrvReadConsoleOutput(IN PCONSOLE Console, IN PTEXTMODE_SCREEN_BUFFER Buffer, IN BOOLEAN Unicode, OUT PCHAR_INFO CharInfo/*Buffer*/, IN PCOORD BufferSize, IN PCOORD BufferCoord, IN OUT PSMALL_RECT ReadRegion); CSR_API(SrvReadConsoleOutput) { NTSTATUS Status; PCONSOLE_READOUTPUT ReadOutputRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.ReadOutputRequest; PTEXTMODE_SCREEN_BUFFER Buffer; DPRINT("SrvReadConsoleOutput\n"); if (!CsrValidateMessageBuffer(ApiMessage, (PVOID*)&ReadOutputRequest->CharInfo, ReadOutputRequest->BufferSize.X * ReadOutputRequest->BufferSize.Y, sizeof(CHAR_INFO))) { return STATUS_INVALID_PARAMETER; } Status = ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process), ReadOutputRequest->OutputHandle, &Buffer, GENERIC_READ, TRUE); if (!NT_SUCCESS(Status)) return Status; Status = ConDrvReadConsoleOutput(Buffer->Header.Console, Buffer, ReadOutputRequest->Unicode, ReadOutputRequest->CharInfo, &ReadOutputRequest->BufferSize, &ReadOutputRequest->BufferCoord, &ReadOutputRequest->ReadRegion); ConSrvReleaseScreenBuffer(Buffer, TRUE); return Status; } NTSTATUS NTAPI ConDrvWriteConsoleOutput(IN PCONSOLE Console, IN PTEXTMODE_SCREEN_BUFFER Buffer, IN BOOLEAN Unicode, IN PCHAR_INFO CharInfo/*Buffer*/, IN PCOORD BufferSize, IN PCOORD BufferCoord, IN OUT PSMALL_RECT WriteRegion); CSR_API(SrvWriteConsoleOutput) { NTSTATUS Status; PCONSOLE_WRITEOUTPUT WriteOutputRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.WriteOutputRequest; PTEXTMODE_SCREEN_BUFFER Buffer; DPRINT("SrvWriteConsoleOutput\n"); if (!CsrValidateMessageBuffer(ApiMessage, (PVOID*)&WriteOutputRequest->CharInfo, WriteOutputRequest->BufferSize.X * WriteOutputRequest->BufferSize.Y, sizeof(CHAR_INFO))) { return STATUS_INVALID_PARAMETER; } Status = ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process), WriteOutputRequest->OutputHandle, &Buffer, GENERIC_WRITE, TRUE); if (!NT_SUCCESS(Status)) return Status; Status = ConDrvWriteConsoleOutput(Buffer->Header.Console, Buffer, WriteOutputRequest->Unicode, WriteOutputRequest->CharInfo, &WriteOutputRequest->BufferSize, &WriteOutputRequest->BufferCoord, &WriteOutputRequest->WriteRegion); ConSrvReleaseScreenBuffer(Buffer, TRUE); return Status; } CSR_API(SrvWriteConsole) { NTSTATUS Status; PCONSOLE_WRITECONSOLE WriteConsoleRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.WriteConsoleRequest; DPRINT("SrvWriteConsole\n"); if (!CsrValidateMessageBuffer(ApiMessage, (PVOID)&WriteConsoleRequest->Buffer, WriteConsoleRequest->BufferSize, sizeof(BYTE))) { return STATUS_INVALID_PARAMETER; } Status = DoWriteConsole(ApiMessage, CsrGetClientThread(), TRUE); if (Status == STATUS_PENDING) *ReplyCode = CsrReplyPending; return Status; } NTSTATUS NTAPI ConDrvReadConsoleOutputString(IN PCONSOLE Console, IN PTEXTMODE_SCREEN_BUFFER Buffer, IN CODE_TYPE CodeType, OUT PVOID StringBuffer, IN ULONG NumCodesToRead, IN PCOORD ReadCoord, // OUT PCOORD EndCoord, OUT PULONG CodesRead); CSR_API(SrvReadConsoleOutputString) { NTSTATUS Status; PCONSOLE_READOUTPUTCODE ReadOutputCodeRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.ReadOutputCodeRequest; PTEXTMODE_SCREEN_BUFFER Buffer; ULONG CodeSize; PVOID pCode; DPRINT("SrvReadConsoleOutputString\n"); switch (ReadOutputCodeRequest->CodeType) { case CODE_ASCII: CodeSize = sizeof(CHAR); break; case CODE_UNICODE: CodeSize = sizeof(WCHAR); break; case CODE_ATTRIBUTE: CodeSize = sizeof(WORD); break; default: return STATUS_INVALID_PARAMETER; } /* * For optimization purposes, Windows (and hence ReactOS, too, for * compatibility reasons) uses a static buffer if no more than eighty * bytes are read. Otherwise a new buffer is used. * The client-side expects that we know this behaviour. */ if (ReadOutputCodeRequest->NumCodes * CodeSize <= sizeof(ReadOutputCodeRequest->CodeStaticBuffer)) { /* * Adjust the internal pointer, because its old value points to * the static buffer in the original ApiMessage structure. */ // ReadOutputCodeRequest->pCode.pCode = ReadOutputCodeRequest->CodeStaticBuffer; pCode = ReadOutputCodeRequest->CodeStaticBuffer; } else { if (!CsrValidateMessageBuffer(ApiMessage, (PVOID*)&ReadOutputCodeRequest->pCode.pCode, ReadOutputCodeRequest->NumCodes, CodeSize)) { return STATUS_INVALID_PARAMETER; } pCode = ReadOutputCodeRequest->pCode.pCode; } Status = ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process), ReadOutputCodeRequest->OutputHandle, &Buffer, GENERIC_READ, TRUE); if (!NT_SUCCESS(Status)) return Status; Status = ConDrvReadConsoleOutputString(Buffer->Header.Console, Buffer, ReadOutputCodeRequest->CodeType, pCode, ReadOutputCodeRequest->NumCodes, &ReadOutputCodeRequest->Coord, // &ReadOutputCodeRequest->EndCoord, &ReadOutputCodeRequest->NumCodes); ConSrvReleaseScreenBuffer(Buffer, TRUE); return Status; } NTSTATUS NTAPI ConDrvWriteConsoleOutputString(IN PCONSOLE Console, IN PTEXTMODE_SCREEN_BUFFER Buffer, IN CODE_TYPE CodeType, IN PVOID StringBuffer, IN ULONG NumCodesToWrite, IN PCOORD WriteCoord /*, OUT PCOORD EndCoord, OUT PULONG CodesWritten */); CSR_API(SrvWriteConsoleOutputString) { NTSTATUS Status; PCONSOLE_WRITEOUTPUTCODE WriteOutputCodeRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.WriteOutputCodeRequest; PTEXTMODE_SCREEN_BUFFER Buffer; ULONG CodeSize; PVOID pCode; DPRINT("SrvWriteConsoleOutputString\n"); switch (WriteOutputCodeRequest->CodeType) { case CODE_ASCII: CodeSize = sizeof(CHAR); break; case CODE_UNICODE: CodeSize = sizeof(WCHAR); break; case CODE_ATTRIBUTE: CodeSize = sizeof(WORD); break; default: return STATUS_INVALID_PARAMETER; } /* * For optimization purposes, Windows (and hence ReactOS, too, for * compatibility reasons) uses a static buffer if no more than eighty * bytes are written. Otherwise a new buffer is used. * The client-side expects that we know this behaviour. */ if (WriteOutputCodeRequest->NumCodes * CodeSize <= sizeof(WriteOutputCodeRequest->CodeStaticBuffer)) { /* * Adjust the internal pointer, because its old value points to * the static buffer in the original ApiMessage structure. */ // WriteOutputCodeRequest->pCode.pCode = WriteOutputCodeRequest->CodeStaticBuffer; pCode = WriteOutputCodeRequest->CodeStaticBuffer; } else { if (!CsrValidateMessageBuffer(ApiMessage, (PVOID*)&WriteOutputCodeRequest->pCode.pCode, WriteOutputCodeRequest->NumCodes, CodeSize)) { return STATUS_INVALID_PARAMETER; } pCode = WriteOutputCodeRequest->pCode.pCode; } Status = ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process), WriteOutputCodeRequest->OutputHandle, &Buffer, GENERIC_WRITE, TRUE); if (!NT_SUCCESS(Status)) return Status; Status = ConDrvWriteConsoleOutputString(Buffer->Header.Console, Buffer, WriteOutputCodeRequest->CodeType, pCode, WriteOutputCodeRequest->NumCodes, &WriteOutputCodeRequest->Coord /*, &WriteOutputCodeRequest->EndCoord, &WriteOutputCodeRequest->NrCharactersWritten */); // WriteOutputCodeRequest->NrCharactersWritten = Written; ConSrvReleaseScreenBuffer(Buffer, TRUE); return Status; } NTSTATUS NTAPI ConDrvFillConsoleOutput(IN PCONSOLE Console, IN PTEXTMODE_SCREEN_BUFFER Buffer, IN CODE_TYPE CodeType, IN PVOID Code, IN ULONG NumCodesToWrite, IN PCOORD WriteCoord /*, OUT PULONG CodesWritten */); CSR_API(SrvFillConsoleOutput) { NTSTATUS Status; PCONSOLE_FILLOUTPUTCODE FillOutputRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.FillOutputRequest; PTEXTMODE_SCREEN_BUFFER Buffer; USHORT CodeType = FillOutputRequest->CodeType; DPRINT("SrvFillConsoleOutput\n"); if ( (CodeType != CODE_ASCII ) && (CodeType != CODE_UNICODE ) && (CodeType != CODE_ATTRIBUTE) ) { return STATUS_INVALID_PARAMETER; } Status = ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process), FillOutputRequest->OutputHandle, &Buffer, GENERIC_WRITE, TRUE); if (!NT_SUCCESS(Status)) return Status; Status = ConDrvFillConsoleOutput(Buffer->Header.Console, Buffer, CodeType, &FillOutputRequest->Code, FillOutputRequest->NumCodes, &FillOutputRequest->WriteCoord /*, &FillOutputRequest->NrCharactersWritten */); // FillOutputRequest->NrCharactersWritten = Written; ConSrvReleaseScreenBuffer(Buffer, TRUE); return Status; } NTSTATUS NTAPI ConDrvGetConsoleScreenBufferInfo(IN PCONSOLE Console, IN PTEXTMODE_SCREEN_BUFFER Buffer, OUT PCOORD ScreenBufferSize, OUT PCOORD CursorPosition, OUT PCOORD ViewOrigin, OUT PCOORD ViewSize, OUT PCOORD MaximumViewSize, OUT PWORD Attributes); CSR_API(SrvGetConsoleScreenBufferInfo) { NTSTATUS Status; PCONSOLE_GETSCREENBUFFERINFO ScreenBufferInfoRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.ScreenBufferInfoRequest; PTEXTMODE_SCREEN_BUFFER Buffer; DPRINT("SrvGetConsoleScreenBufferInfo\n"); Status = ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process), ScreenBufferInfoRequest->OutputHandle, &Buffer, GENERIC_READ, TRUE); if (!NT_SUCCESS(Status)) return Status; Status = ConDrvGetConsoleScreenBufferInfo(Buffer->Header.Console, Buffer, &ScreenBufferInfoRequest->ScreenBufferSize, &ScreenBufferInfoRequest->CursorPosition, &ScreenBufferInfoRequest->ViewOrigin, &ScreenBufferInfoRequest->ViewSize, &ScreenBufferInfoRequest->MaximumViewSize, &ScreenBufferInfoRequest->Attributes); ConSrvReleaseScreenBuffer(Buffer, TRUE); return Status; } NTSTATUS NTAPI ConDrvSetConsoleTextAttribute(IN PCONSOLE Console, IN PTEXTMODE_SCREEN_BUFFER Buffer, IN WORD Attributes); CSR_API(SrvSetConsoleTextAttribute) { NTSTATUS Status; PCONSOLE_SETTEXTATTRIB SetTextAttribRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.SetTextAttribRequest; PTEXTMODE_SCREEN_BUFFER Buffer; DPRINT("SrvSetConsoleTextAttribute\n"); Status = ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process), SetTextAttribRequest->OutputHandle, &Buffer, GENERIC_WRITE, TRUE); if (!NT_SUCCESS(Status)) return Status; Status = ConDrvSetConsoleTextAttribute(Buffer->Header.Console, Buffer, SetTextAttribRequest->Attributes); ConSrvReleaseScreenBuffer(Buffer, TRUE); return Status; } NTSTATUS NTAPI ConDrvSetConsoleScreenBufferSize(IN PCONSOLE Console, IN PTEXTMODE_SCREEN_BUFFER Buffer, IN PCOORD Size); CSR_API(SrvSetConsoleScreenBufferSize) { NTSTATUS Status; PCONSOLE_SETSCREENBUFFERSIZE SetScreenBufferSizeRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.SetScreenBufferSizeRequest; PTEXTMODE_SCREEN_BUFFER Buffer; DPRINT("SrvSetConsoleScreenBufferSize\n"); Status = ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process), SetScreenBufferSizeRequest->OutputHandle, &Buffer, GENERIC_WRITE, TRUE); if (!NT_SUCCESS(Status)) return Status; Status = ConDrvSetConsoleScreenBufferSize(Buffer->Header.Console, Buffer, &SetScreenBufferSizeRequest->Size); ConSrvReleaseScreenBuffer(Buffer, TRUE); return Status; } NTSTATUS NTAPI ConDrvScrollConsoleScreenBuffer(IN PCONSOLE Console, IN PTEXTMODE_SCREEN_BUFFER Buffer, IN BOOLEAN Unicode, IN PSMALL_RECT ScrollRectangle, IN BOOLEAN UseClipRectangle, IN PSMALL_RECT ClipRectangle OPTIONAL, IN PCOORD DestinationOrigin, IN CHAR_INFO FillChar); CSR_API(SrvScrollConsoleScreenBuffer) { NTSTATUS Status; PCONSOLE_SCROLLSCREENBUFFER ScrollScreenBufferRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.ScrollScreenBufferRequest; PTEXTMODE_SCREEN_BUFFER Buffer; DPRINT("SrvScrollConsoleScreenBuffer\n"); Status = ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process), ScrollScreenBufferRequest->OutputHandle, &Buffer, GENERIC_WRITE, TRUE); if (!NT_SUCCESS(Status)) return Status; Status = ConDrvScrollConsoleScreenBuffer(Buffer->Header.Console, Buffer, ScrollScreenBufferRequest->Unicode, &ScrollScreenBufferRequest->ScrollRectangle, ScrollScreenBufferRequest->UseClipRectangle, &ScrollScreenBufferRequest->ClipRectangle, &ScrollScreenBufferRequest->DestinationOrigin, ScrollScreenBufferRequest->Fill); ConSrvReleaseScreenBuffer(Buffer, TRUE); return Status; } NTSTATUS NTAPI ConDrvSetConsoleWindowInfo(IN PCONSOLE Console, IN PTEXTMODE_SCREEN_BUFFER Buffer, IN BOOLEAN Absolute, IN PSMALL_RECT WindowRect); CSR_API(SrvSetConsoleWindowInfo) { NTSTATUS Status; PCONSOLE_SETWINDOWINFO SetWindowInfoRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.SetWindowInfoRequest; // PCONSOLE_SCREEN_BUFFER Buffer; PTEXTMODE_SCREEN_BUFFER Buffer; DPRINT1("SrvSetConsoleWindowInfo(0x%08x, %d, {L%d, T%d, R%d, B%d}) called\n", SetWindowInfoRequest->OutputHandle, SetWindowInfoRequest->Absolute, SetWindowInfoRequest->WindowRect.Left , SetWindowInfoRequest->WindowRect.Top , SetWindowInfoRequest->WindowRect.Right, SetWindowInfoRequest->WindowRect.Bottom); // ConSrvGetScreenBuffer Status = ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process), SetWindowInfoRequest->OutputHandle, &Buffer, GENERIC_READ, TRUE); if (!NT_SUCCESS(Status)) return Status; Status = ConDrvSetConsoleWindowInfo(Buffer->Header.Console, Buffer, SetWindowInfoRequest->Absolute, &SetWindowInfoRequest->WindowRect); ConSrvReleaseScreenBuffer(Buffer, TRUE); return Status; } /* EOF */