ReactOS  0.4.14-dev-376-gaedba84
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_new/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 #include "include/conio.h"
16 #include "include/conio2.h"
17 #include "conoutput.h"
18 #include "handle.h"
19 
20 #define NDEBUG
21 #include <debug.h>
22 
23 
24 /* PRIVATE FUNCTIONS **********************************************************/
25 
28 {
29  // return This->Header.Type;
30  return GRAPHICS_BUFFER;
31 }
32 
34 {
36 };
37 
38 
42  IN SIZE_T Size);
43 VOID
45 
46 
50  IN PGRAPHICS_BUFFER_INFO GraphicsInfo)
51 {
53  PGRAPHICS_SCREEN_BUFFER NewBuffer = NULL;
54 
55  LARGE_INTEGER SectionSize;
56  ULONG ViewSize = 0;
58 
59  if (Buffer == NULL || Console == NULL || GraphicsInfo == NULL)
61 
62  *Buffer = NULL;
63 
65  Console,
66  sizeof(GRAPHICS_SCREEN_BUFFER));
67  if (!NT_SUCCESS(Status)) return Status;
68  NewBuffer->Header.Type = GRAPHICS_BUFFER;
69  NewBuffer->Vtbl = &GraphicsVtbl;
70 
71  /*
72  * Remember the handle to the process so that we can close or unmap
73  * correctly the allocated resources when the client releases the
74  * screen buffer.
75  */
76  ProcessHandle = CsrGetClientThread()->Process->ProcessHandle;
77  NewBuffer->ClientProcess = ProcessHandle;
78 
79  /* Get infos from the graphics buffer information structure */
80  NewBuffer->BitMapInfoLength = GraphicsInfo->Info.dwBitMapInfoLength;
81 
82  NewBuffer->BitMapInfo = ConsoleAllocHeap(HEAP_ZERO_MEMORY, NewBuffer->BitMapInfoLength);
83  if (NewBuffer->BitMapInfo == NULL)
84  {
87  }
88 
89  /* Adjust the bitmap height if needed (bottom-top vs. top-bottom). Use always bottom-up. */
90  if (GraphicsInfo->Info.lpBitMapInfo->bmiHeader.biHeight > 0)
91  GraphicsInfo->Info.lpBitMapInfo->bmiHeader.biHeight = -GraphicsInfo->Info.lpBitMapInfo->bmiHeader.biHeight;
92 
93  /* We do not use anything else than uncompressed bitmaps */
94  if (GraphicsInfo->Info.lpBitMapInfo->bmiHeader.biCompression != BI_RGB)
95  {
96  DPRINT1("biCompression == %d != BI_RGB, correct that!\n", GraphicsInfo->Info.lpBitMapInfo->bmiHeader.biCompression);
97  GraphicsInfo->Info.lpBitMapInfo->bmiHeader.biCompression = BI_RGB;
98  }
99 
100  RtlCopyMemory(NewBuffer->BitMapInfo,
101  GraphicsInfo->Info.lpBitMapInfo,
102  GraphicsInfo->Info.dwBitMapInfoLength);
103 
104  NewBuffer->BitMapUsage = GraphicsInfo->Info.dwUsage;
105 
106  /* Set the screen buffer size. Fight against overflows. */
107  if ( GraphicsInfo->Info.lpBitMapInfo->bmiHeader.biWidth <= 0xFFFF &&
108  -GraphicsInfo->Info.lpBitMapInfo->bmiHeader.biHeight <= 0xFFFF )
109  {
110  /* Be careful about the sign of biHeight */
111  NewBuffer->ScreenBufferSize.X = (SHORT)GraphicsInfo->Info.lpBitMapInfo->bmiHeader.biWidth ;
112  NewBuffer->ScreenBufferSize.Y = (SHORT)-GraphicsInfo->Info.lpBitMapInfo->bmiHeader.biHeight;
113 
114  NewBuffer->OldViewSize = NewBuffer->ViewSize =
115  NewBuffer->OldScreenBufferSize = NewBuffer->ScreenBufferSize;
116  }
117  else
118  {
120  ConsoleFreeHeap(NewBuffer->BitMapInfo);
122  goto Quit;
123  }
124 
125  /*
126  * Create a mutex to synchronize bitmap memory access
127  * between ourselves and the client.
128  */
129  Status = NtCreateMutant(&NewBuffer->Mutex, MUTANT_ALL_ACCESS, NULL, FALSE);
130  if (!NT_SUCCESS(Status))
131  {
132  DPRINT1("NtCreateMutant() failed: %lu\n", Status);
133  ConsoleFreeHeap(NewBuffer->BitMapInfo);
135  goto Quit;
136  }
137 
138  /*
139  * Duplicate the Mutex for the client. We must keep a trace of it
140  * so that we can close it when the client releases the screen buffer.
141  */
143  NewBuffer->Mutex,
145  &NewBuffer->ClientMutex,
146  0, 0, DUPLICATE_SAME_ACCESS);
147  if (!NT_SUCCESS(Status))
148  {
149  DPRINT1("NtDuplicateObject() failed: %lu\n", Status);
150  NtClose(NewBuffer->Mutex);
151  ConsoleFreeHeap(NewBuffer->BitMapInfo);
153  goto Quit;
154  }
155 
156  /*
157  * Create a memory section for the bitmap area, to share with the client.
158  */
159  SectionSize.QuadPart = NewBuffer->BitMapInfo->bmiHeader.biSizeImage;
160  Status = NtCreateSection(&NewBuffer->hSection,
162  NULL,
163  &SectionSize,
165  SEC_COMMIT,
166  NULL);
167  if (!NT_SUCCESS(Status))
168  {
169  DPRINT1("Error: Impossible to create a shared section ; Status = %lu\n", Status);
170  NtClose(NewBuffer->ClientMutex);
171  NtClose(NewBuffer->Mutex);
172  ConsoleFreeHeap(NewBuffer->BitMapInfo);
174  goto Quit;
175  }
176 
177  /*
178  * Create a view for our needs.
179  */
180  ViewSize = 0;
181  NewBuffer->BitMap = NULL;
182  Status = NtMapViewOfSection(NewBuffer->hSection,
184  (PVOID*)&NewBuffer->BitMap,
185  0,
186  0,
187  NULL,
188  &ViewSize,
189  ViewUnmap,
190  0,
192  if (!NT_SUCCESS(Status))
193  {
194  DPRINT1("Error: Impossible to map the shared section ; Status = %lu\n", Status);
195  NtClose(NewBuffer->hSection);
196  NtClose(NewBuffer->ClientMutex);
197  NtClose(NewBuffer->Mutex);
198  ConsoleFreeHeap(NewBuffer->BitMapInfo);
200  goto Quit;
201  }
202 
203  /*
204  * Create a view for the client. We must keep a trace of it so that
205  * we can unmap it when the client releases the screen buffer.
206  */
207  ViewSize = 0;
208  NewBuffer->ClientBitMap = NULL;
209  Status = NtMapViewOfSection(NewBuffer->hSection,
211  (PVOID*)&NewBuffer->ClientBitMap,
212  0,
213  0,
214  NULL,
215  &ViewSize,
216  ViewUnmap,
217  0,
219  if (!NT_SUCCESS(Status))
220  {
221  DPRINT1("Error: Impossible to map the shared section ; Status = %lu\n", Status);
222  NtUnmapViewOfSection(NtCurrentProcess(), NewBuffer->BitMap);
223  NtClose(NewBuffer->hSection);
224  NtClose(NewBuffer->ClientMutex);
225  NtClose(NewBuffer->Mutex);
226  ConsoleFreeHeap(NewBuffer->BitMapInfo);
228  goto Quit;
229  }
230 
231  NewBuffer->ViewOrigin.X = NewBuffer->ViewOrigin.Y = 0;
232  NewBuffer->VirtualY = 0;
233 
234  NewBuffer->CursorBlinkOn = FALSE;
235  NewBuffer->ForceCursorOff = TRUE;
236  NewBuffer->CursorInfo.bVisible = FALSE;
237  NewBuffer->CursorInfo.dwSize = 0;
238  NewBuffer->CursorPosition.X = NewBuffer->CursorPosition.Y = 0;
239 
240  NewBuffer->Mode = 0;
241 
242  *Buffer = (PCONSOLE_SCREEN_BUFFER)NewBuffer;
244 
245 Quit:
246  return Status;
247 }
248 
249 VOID
251 {
253 
254  /*
255  * IMPORTANT !! Reinitialize the type so that we don't enter a recursive
256  * infinite loop when calling CONSOLE_SCREEN_BUFFER_Destroy.
257  */
258  Buffer->Header.Type = SCREEN_BUFFER;
259 
260  /*
261  * Uninitialize the graphics screen buffer
262  * in the reverse way we initialized it.
263  */
266  NtClose(Buff->hSection);
267  NtClose(Buff->ClientMutex);
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 CsrGetClientThread()
Definition: csrsrv.h:77
NTSTATUS NTAPI NtUnmapViewOfSection(IN HANDLE ProcessHandle, IN PVOID BaseAddress)
Definition: section.c:3782
#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:3373
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:3554
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
static CONSOLE_SCREEN_BUFFER_VTBL GraphicsVtbl
Definition: graphics.c:33
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
#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
unsigned int ULONG
Definition: retypes.h:1
PCONSOLE_SCREEN_BUFFER_VTBL Vtbl
Definition: conio.h:83
_In_ HANDLE ProcessHandle
Definition: mmfuncs.h:403
return STATUS_SUCCESS
Definition: btrfs.c:2938
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:34
LONGLONG QuadPart
Definition: typedefs.h:112
#define PAGE_READWRITE
Definition: nt_native.h:1304