+++ /dev/null
-/*
- * COPYRIGHT: See COPYING in the top level directory
- * PROJECT: ReactOS Console Driver DLL
- * FILE: win32ss/user/winsrv/consrv_new/condrv/graphics.c
- * PURPOSE: Console Output Functions for graphics-mode screen-buffers
- * PROGRAMMERS: Hermes Belusca-Maito (hermes.belusca@sfr.fr)
- *
- * NOTE: See http://blog.airesoft.co.uk/2012/10/things-ms-can-do-that-they-dont-tell-you-about-console-graphics/
- * for more information.
- */
-
-/* INCLUDES *******************************************************************/
-
-#include "consrv.h"
-#include "include/conio.h"
-#include "include/conio2.h"
-#include "conoutput.h"
-#include "handle.h"
-
-#define NDEBUG
-#include <debug.h>
-
-
-/* PRIVATE FUNCTIONS **********************************************************/
-
-CONSOLE_IO_OBJECT_TYPE
-GRAPHICS_BUFFER_GetType(PCONSOLE_SCREEN_BUFFER This)
-{
- // return This->Header.Type;
- return GRAPHICS_BUFFER;
-}
-
-static CONSOLE_SCREEN_BUFFER_VTBL GraphicsVtbl =
-{
- GRAPHICS_BUFFER_GetType,
-};
-
-
-NTSTATUS
-CONSOLE_SCREEN_BUFFER_Initialize(OUT PCONSOLE_SCREEN_BUFFER* Buffer,
- IN OUT PCONSOLE Console,
- IN SIZE_T Size);
-VOID
-CONSOLE_SCREEN_BUFFER_Destroy(IN OUT PCONSOLE_SCREEN_BUFFER Buffer);
-
-
-NTSTATUS
-GRAPHICS_BUFFER_Initialize(OUT PCONSOLE_SCREEN_BUFFER* Buffer,
- IN OUT PCONSOLE Console,
- IN PGRAPHICS_BUFFER_INFO GraphicsInfo)
-{
- NTSTATUS Status = STATUS_SUCCESS;
- PGRAPHICS_SCREEN_BUFFER NewBuffer = NULL;
-
- LARGE_INTEGER SectionSize;
- ULONG ViewSize = 0;
- HANDLE ProcessHandle;
-
- if (Buffer == NULL || Console == NULL || GraphicsInfo == NULL)
- return STATUS_INVALID_PARAMETER;
-
- *Buffer = NULL;
-
- Status = CONSOLE_SCREEN_BUFFER_Initialize((PCONSOLE_SCREEN_BUFFER*)&NewBuffer,
- Console,
- sizeof(GRAPHICS_SCREEN_BUFFER));
- if (!NT_SUCCESS(Status)) return Status;
- NewBuffer->Header.Type = GRAPHICS_BUFFER;
- NewBuffer->Vtbl = &GraphicsVtbl;
-
- /*
- * Remember the handle to the process so that we can close or unmap
- * correctly the allocated resources when the client releases the
- * screen buffer.
- */
- ProcessHandle = CsrGetClientThread()->Process->ProcessHandle;
- NewBuffer->ClientProcess = ProcessHandle;
-
- /* Get infos from the graphics buffer information structure */
- NewBuffer->BitMapInfoLength = GraphicsInfo->Info.dwBitMapInfoLength;
-
- NewBuffer->BitMapInfo = ConsoleAllocHeap(HEAP_ZERO_MEMORY, NewBuffer->BitMapInfoLength);
- if (NewBuffer->BitMapInfo == NULL)
- {
- CONSOLE_SCREEN_BUFFER_Destroy((PCONSOLE_SCREEN_BUFFER)NewBuffer);
- return STATUS_INSUFFICIENT_RESOURCES;
- }
-
- /* Adjust the bitmap height if needed (bottom-top vs. top-bottom). Use always bottom-up. */
- if (GraphicsInfo->Info.lpBitMapInfo->bmiHeader.biHeight > 0)
- GraphicsInfo->Info.lpBitMapInfo->bmiHeader.biHeight = -GraphicsInfo->Info.lpBitMapInfo->bmiHeader.biHeight;
-
- /* We do not use anything else than uncompressed bitmaps */
- if (GraphicsInfo->Info.lpBitMapInfo->bmiHeader.biCompression != BI_RGB)
- {
- DPRINT1("biCompression == %d != BI_RGB, correct that!\n", GraphicsInfo->Info.lpBitMapInfo->bmiHeader.biCompression);
- GraphicsInfo->Info.lpBitMapInfo->bmiHeader.biCompression = BI_RGB;
- }
-
- RtlCopyMemory(NewBuffer->BitMapInfo,
- GraphicsInfo->Info.lpBitMapInfo,
- GraphicsInfo->Info.dwBitMapInfoLength);
-
- NewBuffer->BitMapUsage = GraphicsInfo->Info.dwUsage;
-
- /* Set the screen buffer size. Fight against overflows. */
- if ( GraphicsInfo->Info.lpBitMapInfo->bmiHeader.biWidth <= 0xFFFF &&
- -GraphicsInfo->Info.lpBitMapInfo->bmiHeader.biHeight <= 0xFFFF )
- {
- /* Be careful about the sign of biHeight */
- NewBuffer->ScreenBufferSize.X = (SHORT)GraphicsInfo->Info.lpBitMapInfo->bmiHeader.biWidth ;
- NewBuffer->ScreenBufferSize.Y = (SHORT)-GraphicsInfo->Info.lpBitMapInfo->bmiHeader.biHeight;
-
- NewBuffer->OldViewSize = NewBuffer->ViewSize =
- NewBuffer->OldScreenBufferSize = NewBuffer->ScreenBufferSize;
- }
- else
- {
- Status = STATUS_INSUFFICIENT_RESOURCES;
- ConsoleFreeHeap(NewBuffer->BitMapInfo);
- CONSOLE_SCREEN_BUFFER_Destroy((PCONSOLE_SCREEN_BUFFER)NewBuffer);
- goto Quit;
- }
-
- /*
- * Create a mutex to synchronize bitmap memory access
- * between ourselves and the client.
- */
- Status = NtCreateMutant(&NewBuffer->Mutex, MUTANT_ALL_ACCESS, NULL, FALSE);
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("NtCreateMutant() failed: %lu\n", Status);
- ConsoleFreeHeap(NewBuffer->BitMapInfo);
- CONSOLE_SCREEN_BUFFER_Destroy((PCONSOLE_SCREEN_BUFFER)NewBuffer);
- goto Quit;
- }
-
- /*
- * Duplicate the Mutex for the client. We must keep a trace of it
- * so that we can close it when the client releases the screen buffer.
- */
- Status = NtDuplicateObject(NtCurrentProcess(),
- NewBuffer->Mutex,
- ProcessHandle,
- &NewBuffer->ClientMutex,
- 0, 0, DUPLICATE_SAME_ACCESS);
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("NtDuplicateObject() failed: %lu\n", Status);
- NtClose(NewBuffer->Mutex);
- ConsoleFreeHeap(NewBuffer->BitMapInfo);
- CONSOLE_SCREEN_BUFFER_Destroy((PCONSOLE_SCREEN_BUFFER)NewBuffer);
- goto Quit;
- }
-
- /*
- * Create a memory section for the bitmap area, to share with the client.
- */
- SectionSize.QuadPart = NewBuffer->BitMapInfo->bmiHeader.biSizeImage;
- Status = NtCreateSection(&NewBuffer->hSection,
- SECTION_ALL_ACCESS,
- NULL,
- &SectionSize,
- PAGE_READWRITE,
- SEC_COMMIT,
- NULL);
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("Error: Impossible to create a shared section ; Status = %lu\n", Status);
- NtClose(NewBuffer->ClientMutex);
- NtClose(NewBuffer->Mutex);
- ConsoleFreeHeap(NewBuffer->BitMapInfo);
- CONSOLE_SCREEN_BUFFER_Destroy((PCONSOLE_SCREEN_BUFFER)NewBuffer);
- goto Quit;
- }
-
- /*
- * Create a view for our needs.
- */
- ViewSize = 0;
- NewBuffer->BitMap = NULL;
- Status = NtMapViewOfSection(NewBuffer->hSection,
- NtCurrentProcess(),
- (PVOID*)&NewBuffer->BitMap,
- 0,
- 0,
- NULL,
- &ViewSize,
- ViewUnmap,
- 0,
- PAGE_READWRITE);
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("Error: Impossible to map the shared section ; Status = %lu\n", Status);
- NtClose(NewBuffer->hSection);
- NtClose(NewBuffer->ClientMutex);
- NtClose(NewBuffer->Mutex);
- ConsoleFreeHeap(NewBuffer->BitMapInfo);
- CONSOLE_SCREEN_BUFFER_Destroy((PCONSOLE_SCREEN_BUFFER)NewBuffer);
- goto Quit;
- }
-
- /*
- * Create a view for the client. We must keep a trace of it so that
- * we can unmap it when the client releases the screen buffer.
- */
- ViewSize = 0;
- NewBuffer->ClientBitMap = NULL;
- Status = NtMapViewOfSection(NewBuffer->hSection,
- ProcessHandle,
- (PVOID*)&NewBuffer->ClientBitMap,
- 0,
- 0,
- NULL,
- &ViewSize,
- ViewUnmap,
- 0,
- PAGE_READWRITE);
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("Error: Impossible to map the shared section ; Status = %lu\n", Status);
- NtUnmapViewOfSection(NtCurrentProcess(), NewBuffer->BitMap);
- NtClose(NewBuffer->hSection);
- NtClose(NewBuffer->ClientMutex);
- NtClose(NewBuffer->Mutex);
- ConsoleFreeHeap(NewBuffer->BitMapInfo);
- CONSOLE_SCREEN_BUFFER_Destroy((PCONSOLE_SCREEN_BUFFER)NewBuffer);
- goto Quit;
- }
-
- NewBuffer->ViewOrigin.X = NewBuffer->ViewOrigin.Y = 0;
- NewBuffer->VirtualY = 0;
-
- NewBuffer->CursorBlinkOn = FALSE;
- NewBuffer->ForceCursorOff = TRUE;
- NewBuffer->CursorInfo.bVisible = FALSE;
- NewBuffer->CursorInfo.dwSize = 0;
- NewBuffer->CursorPosition.X = NewBuffer->CursorPosition.Y = 0;
-
- NewBuffer->Mode = 0;
-
- *Buffer = (PCONSOLE_SCREEN_BUFFER)NewBuffer;
- Status = STATUS_SUCCESS;
-
-Quit:
- return Status;
-}
-
-VOID
-GRAPHICS_BUFFER_Destroy(IN OUT PCONSOLE_SCREEN_BUFFER Buffer)
-{
- PGRAPHICS_SCREEN_BUFFER Buff = (PGRAPHICS_SCREEN_BUFFER)Buffer;
-
- /*
- * IMPORTANT !! Reinitialize the type so that we don't enter a recursive
- * infinite loop when calling CONSOLE_SCREEN_BUFFER_Destroy.
- */
- Buffer->Header.Type = SCREEN_BUFFER;
-
- /*
- * Uninitialize the graphics screen buffer
- * in the reverse way we initialized it.
- */
- NtUnmapViewOfSection(Buff->ClientProcess, Buff->ClientBitMap);
- NtUnmapViewOfSection(NtCurrentProcess(), Buff->BitMap);
- NtClose(Buff->hSection);
- NtClose(Buff->ClientMutex);
- NtClose(Buff->Mutex);
- ConsoleFreeHeap(Buff->BitMapInfo);
-
- CONSOLE_SCREEN_BUFFER_Destroy(Buffer);
-}
-
-/* EOF */