ReactOS  0.4.13-dev-247-g0f29b3f
graphics.c
Go to the documentation of this file.
1 /*
2  * COPYRIGHT: See COPYING in the top level directory
3  * PROJECT: ReactOS Console Driver DLL
4  * FILE: win32ss/user/winsrv/consrv/condrv/graphics.c
5  * PURPOSE: Console Output Functions for graphics-mode screen-buffers
6  * PROGRAMMERS: Hermes Belusca-Maito (hermes.belusca@sfr.fr)
7  *
8  * NOTE: See http://blog.airesoft.co.uk/2012/10/things-ms-can-do-that-they-dont-tell-you-about-console-graphics/
9  * for more information.
10  */
11 
12 /* INCLUDES *******************************************************************/
13 
14 #include <consrv.h>
15 
16 #define NDEBUG
17 #include <debug.h>
18 
19 /* PRIVATE FUNCTIONS **********************************************************/
20 
23 {
24  // return This->Header.Type;
25  return GRAPHICS_BUFFER;
26 }
27 
29 {
31 };
32 
33 
38  IN SIZE_T Size);
39 VOID
41 
42 
47  IN PGRAPHICS_BUFFER_INFO GraphicsInfo)
48 {
50  PGRAPHICS_SCREEN_BUFFER NewBuffer = NULL;
51 
52  LARGE_INTEGER SectionSize;
53  SIZE_T ViewSize = 0;
54 
55  if (Buffer == NULL || Console == NULL || GraphicsInfo == NULL)
57 
58  *Buffer = NULL;
59 
61  Console,
62  &GraphicsVtbl,
63  sizeof(GRAPHICS_SCREEN_BUFFER));
64  if (!NT_SUCCESS(Status)) return Status;
65  NewBuffer->Header.Type = GRAPHICS_BUFFER;
66 
67  /*
68  * Remember the handle to the process so that we can close or unmap
69  * correctly the allocated resources when the client releases the
70  * screen buffer.
71  */
72  NewBuffer->ClientProcess = ProcessHandle;
73 
74  /* Get infos from the graphics buffer information structure */
75  NewBuffer->BitMapInfoLength = GraphicsInfo->Info.dwBitMapInfoLength;
76 
77  NewBuffer->BitMapInfo = ConsoleAllocHeap(HEAP_ZERO_MEMORY, NewBuffer->BitMapInfoLength);
78  if (NewBuffer->BitMapInfo == NULL)
79  {
82  }
83 
84  /* Adjust the bitmap height if needed (bottom-top vs. top-bottom). Use always bottom-up. */
85  if (GraphicsInfo->Info.lpBitMapInfo->bmiHeader.biHeight > 0)
86  GraphicsInfo->Info.lpBitMapInfo->bmiHeader.biHeight = -GraphicsInfo->Info.lpBitMapInfo->bmiHeader.biHeight;
87 
88  /* We do not use anything else than uncompressed bitmaps */
89  if (GraphicsInfo->Info.lpBitMapInfo->bmiHeader.biCompression != BI_RGB)
90  {
91  DPRINT1("biCompression == %d != BI_RGB, fix that!\n",
92  GraphicsInfo->Info.lpBitMapInfo->bmiHeader.biCompression);
93  GraphicsInfo->Info.lpBitMapInfo->bmiHeader.biCompression = BI_RGB;
94  }
95 
96  RtlCopyMemory(NewBuffer->BitMapInfo,
97  GraphicsInfo->Info.lpBitMapInfo,
98  GraphicsInfo->Info.dwBitMapInfoLength);
99 
100  NewBuffer->BitMapUsage = GraphicsInfo->Info.dwUsage;
101 
102  /* Set the screen buffer size. Fight against overflows. */
103  if ( GraphicsInfo->Info.lpBitMapInfo->bmiHeader.biWidth <= 0xFFFF &&
104  -GraphicsInfo->Info.lpBitMapInfo->bmiHeader.biHeight <= 0xFFFF )
105  {
106  /* Be careful about the sign of biHeight */
107  NewBuffer->ScreenBufferSize.X = (SHORT)GraphicsInfo->Info.lpBitMapInfo->bmiHeader.biWidth ;
108  NewBuffer->ScreenBufferSize.Y = (SHORT)-GraphicsInfo->Info.lpBitMapInfo->bmiHeader.biHeight;
109 
110  NewBuffer->OldViewSize = NewBuffer->ViewSize =
111  NewBuffer->OldScreenBufferSize = NewBuffer->ScreenBufferSize;
112  }
113  else
114  {
116  ConsoleFreeHeap(NewBuffer->BitMapInfo);
118  goto Quit;
119  }
120 
121  /*
122  * Create a mutex to synchronize bitmap memory access
123  * between ourselves and the client.
124  */
125  Status = NtCreateMutant(&NewBuffer->Mutex, MUTANT_ALL_ACCESS, NULL, FALSE);
126  if (!NT_SUCCESS(Status))
127  {
128  DPRINT1("NtCreateMutant() failed: %lu\n", Status);
129  ConsoleFreeHeap(NewBuffer->BitMapInfo);
131  goto Quit;
132  }
133 
134  /*
135  * Duplicate the Mutex for the client. We must keep a trace of it
136  * so that we can close it when the client releases the screen buffer.
137  */
139  NewBuffer->Mutex,
141  &NewBuffer->ClientMutex,
142  0, 0, DUPLICATE_SAME_ACCESS);
143  if (!NT_SUCCESS(Status))
144  {
145  DPRINT1("NtDuplicateObject() failed: %lu\n", Status);
146  NtClose(NewBuffer->Mutex);
147  ConsoleFreeHeap(NewBuffer->BitMapInfo);
149  goto Quit;
150  }
151 
152  /*
153  * Create a memory section for the bitmap area, to share with the client.
154  */
155  SectionSize.QuadPart = NewBuffer->BitMapInfo->bmiHeader.biSizeImage;
156  Status = NtCreateSection(&NewBuffer->hSection,
158  NULL,
159  &SectionSize,
161  SEC_COMMIT,
162  NULL);
163  if (!NT_SUCCESS(Status))
164  {
165  DPRINT1("Error: Impossible to create a shared section, Status = 0x%08lx\n", Status);
166  NtDuplicateObject(ProcessHandle, NewBuffer->ClientMutex,
168  NtClose(NewBuffer->Mutex);
169  ConsoleFreeHeap(NewBuffer->BitMapInfo);
171  goto Quit;
172  }
173 
174  /*
175  * Create a view for our needs.
176  */
177  ViewSize = 0;
178  NewBuffer->BitMap = NULL;
179  Status = NtMapViewOfSection(NewBuffer->hSection,
181  (PVOID*)&NewBuffer->BitMap,
182  0,
183  0,
184  NULL,
185  &ViewSize,
186  ViewUnmap,
187  0,
189  if (!NT_SUCCESS(Status))
190  {
191  DPRINT1("Error: Impossible to map the shared section, Status = 0x%08lx\n", Status);
192  NtClose(NewBuffer->hSection);
193  NtDuplicateObject(ProcessHandle, NewBuffer->ClientMutex,
195  NtClose(NewBuffer->Mutex);
196  ConsoleFreeHeap(NewBuffer->BitMapInfo);
198  goto Quit;
199  }
200 
201  /*
202  * Create a view for the client. We must keep a trace of it so that
203  * we can unmap it when the client releases the screen buffer.
204  */
205  ViewSize = 0;
206  NewBuffer->ClientBitMap = NULL;
207  Status = NtMapViewOfSection(NewBuffer->hSection,
209  (PVOID*)&NewBuffer->ClientBitMap,
210  0,
211  0,
212  NULL,
213  &ViewSize,
214  ViewUnmap,
215  0,
217  if (!NT_SUCCESS(Status))
218  {
219  DPRINT1("Error: Impossible to map the shared section, Status = 0x%08lx\n", Status);
220  NtUnmapViewOfSection(NtCurrentProcess(), NewBuffer->BitMap);
221  NtClose(NewBuffer->hSection);
222  NtDuplicateObject(ProcessHandle, NewBuffer->ClientMutex,
224  NtClose(NewBuffer->Mutex);
225  ConsoleFreeHeap(NewBuffer->BitMapInfo);
227  goto Quit;
228  }
229 
230  NewBuffer->ViewOrigin.X = NewBuffer->ViewOrigin.Y = 0;
231  NewBuffer->VirtualY = 0;
232 
233  NewBuffer->CursorBlinkOn = FALSE;
234  NewBuffer->ForceCursorOff = TRUE;
235  NewBuffer->CursorInfo.bVisible = FALSE;
236  NewBuffer->CursorInfo.dwSize = 0;
237  NewBuffer->CursorPosition.X = NewBuffer->CursorPosition.Y = 0;
238 
239  NewBuffer->Mode = 0;
240 
241  *Buffer = (PCONSOLE_SCREEN_BUFFER)NewBuffer;
243 
244 Quit:
245  return Status;
246 }
247 
248 VOID
250 {
252 
253  /*
254  * IMPORTANT !! Reinitialize the type so that we don't enter a recursive
255  * infinite loop when calling CONSOLE_SCREEN_BUFFER_Destroy.
256  */
257  Buffer->Header.Type = SCREEN_BUFFER;
258 
259  /*
260  * Uninitialize the graphics screen buffer
261  * in the reverse way we initialized it.
262  */
265  NtClose(Buff->hSection);
268  NtClose(Buff->Mutex);
270 
272 }
273 
274 /* EOF */
CONSOLE_IO_OBJECT_TYPE GRAPHICS_BUFFER_GetType(PCONSOLE_SCREEN_BUFFER This)
Definition: graphics.c:22
#define IN
Definition: typedefs.h:38
#define DUPLICATE_CLOSE_SOURCE
NTSTATUS NTAPI NtUnmapViewOfSection(IN HANDLE ProcessHandle, IN PVOID BaseAddress)
Definition: section.c:3780
#define TRUE
Definition: types.h:120
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
NTSTATUS NTAPI NtCreateSection(OUT PHANDLE SectionHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, IN PLARGE_INTEGER MaximumSize OPTIONAL, IN ULONG SectionPageProtection OPTIONAL, IN ULONG AllocationAttributes, IN HANDLE FileHandle OPTIONAL)
Definition: section.c:3371
BOOLEAN CursorBlinkOn
Definition: conio.h:99
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
LONG NTSTATUS
Definition: precomp.h:26
COORD CursorPosition
Definition: conio.h:98
#define ConsoleAllocHeap(Flags, Size)
Definition: heap.h:14
COORD OldScreenBufferSize
Definition: conio.h:90
CONSOLE_IO_OBJECT Header
Definition: conio.h:82
NTSTATUS GRAPHICS_BUFFER_Initialize(OUT PCONSOLE_SCREEN_BUFFER *Buffer, IN PCONSOLE Console, IN HANDLE ProcessHandle, IN PGRAPHICS_BUFFER_INFO GraphicsInfo)
Definition: graphics.c:44
#define SECTION_ALL_ACCESS
Definition: nt_native.h:1293
#define DUPLICATE_SAME_ACCESS
#define SEC_COMMIT
Definition: mmtypes.h:99
LPBITMAPINFO BitMapInfo
Definition: conio.h:175
COORD ScreenBufferSize
Definition: conio.h:87
#define MUTANT_ALL_ACCESS
Definition: extypes.h:110
short SHORT
Definition: pedump.c:59
NTSTATUS NTAPI NtMapViewOfSection(IN HANDLE SectionHandle, IN HANDLE ProcessHandle, IN OUT PVOID *BaseAddress, IN ULONG_PTR ZeroBits, IN SIZE_T CommitSize, IN OUT PLARGE_INTEGER SectionOffset OPTIONAL, IN OUT PSIZE_T ViewSize, IN SECTION_INHERIT InheritDisposition, IN ULONG AllocationType, IN ULONG Protect)
Definition: section.c:3552
VOID CONSOLE_SCREEN_BUFFER_Destroy(IN OUT PCONSOLE_SCREEN_BUFFER Buffer)
Definition: conoutput.c:55
struct _CONSOLE_SCREEN_BUFFER * PCONSOLE_SCREEN_BUFFER
Definition: conio.h:70
smooth NULL
Definition: ftsmooth.c:416
Definition: bufpool.h:45
VOID GRAPHICS_BUFFER_Destroy(IN OUT PCONSOLE_SCREEN_BUFFER Buffer)
Definition: graphics.c:249
#define NtCurrentProcess()
Definition: nt_native.h:1657
ULONG X
Definition: bl.h:1340
BOOLEAN bVisible
Definition: blue.h:41
NTSTATUS CONSOLE_SCREEN_BUFFER_Initialize(OUT PCONSOLE_SCREEN_BUFFER *Buffer, IN PCONSOLE Console, IN PCONSOLE_SCREEN_BUFFER_VTBL Vtbl, IN SIZE_T Size)
Definition: conoutput.c:37
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
NTSTATUS NTAPI NtCreateMutant(OUT PHANDLE MutantHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, IN BOOLEAN InitialOwner)
Definition: mutant.c:83
NTSTATUS NTAPI NtClose(IN HANDLE Handle)
Definition: obhandle.c:3399
struct _GRAPHICS_SCREEN_BUFFER * PGRAPHICS_SCREEN_BUFFER
BOOLEAN ForceCursorOff
Definition: conio.h:100
IN PVOID IN PVOID IN USHORT IN USHORT Size
Definition: pci.h:359
Status
Definition: gdiplustypes.h:24
ULONG_PTR SIZE_T
Definition: typedefs.h:78
static CONSOLE_SCREEN_BUFFER_VTBL GraphicsVtbl
Definition: graphics.c:28
#define HEAP_ZERO_MEMORY
Definition: compat.h:123
CConsole Console
#define DPRINT1
Definition: precomp.h:8
#define ConsoleFreeHeap(HeapBase)
Definition: heap.h:15
NTSTATUS NTAPI NtDuplicateObject(IN HANDLE SourceProcessHandle, IN HANDLE SourceHandle, IN HANDLE TargetProcessHandle OPTIONAL, OUT PHANDLE TargetHandle OPTIONAL, IN ACCESS_MASK DesiredAccess, IN ULONG HandleAttributes, IN ULONG Options)
Definition: obhandle.c:3407
#define OUT
Definition: typedefs.h:39
_In_ HANDLE _Outptr_result_bytebuffer_ ViewSize PVOID _In_ ULONG_PTR _In_ SIZE_T _Inout_opt_ PLARGE_INTEGER _Inout_ PSIZE_T ViewSize
Definition: mmfuncs.h:404
CONSOLE_IO_OBJECT_TYPE Type
Definition: conio.h:50
_In_ HANDLE ProcessHandle
Definition: mmfuncs.h:403
return STATUS_SUCCESS
Definition: btrfs.c:2745
CONSOLE_CURSOR_INFO CursorInfo
Definition: conio.h:102
ULONG Y
Definition: bl.h:1341
enum _CONSOLE_IO_OBJECT_TYPE CONSOLE_IO_OBJECT_TYPE
#define BI_RGB
Definition: precomp.h:35
LONGLONG QuadPart
Definition: typedefs.h:112
#define PAGE_READWRITE
Definition: nt_native.h:1304