1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Console Driver DLL
4 * FILE: win32ss/user/winsrv/consrv/condrv/conoutput.c
5 * PURPOSE: General Console Output Functions
6 * PROGRAMMERS: Jeffrey Morlan
7 * Hermes Belusca-Maito (hermes.belusca@sfr.fr)
8 */
9
10 /* INCLUDES *******************************************************************/
11
12 #include <consrv.h>
13
14 #define NDEBUG
15 #include <debug.h>
16
17 /* PRIVATE FUNCTIONS **********************************************************/
18
19 NTSTATUS
20 TEXTMODE_BUFFER_Initialize(OUT PCONSOLE_SCREEN_BUFFER* Buffer,
21 IN PCONSOLE Console,
22 IN HANDLE ProcessHandle,
23 IN PTEXTMODE_BUFFER_INFO TextModeInfo);
24 NTSTATUS
25 GRAPHICS_BUFFER_Initialize(OUT PCONSOLE_SCREEN_BUFFER* Buffer,
26 IN PCONSOLE Console,
27 IN HANDLE ProcessHandle,
28 IN PGRAPHICS_BUFFER_INFO GraphicsInfo);
29
30 VOID
31 TEXTMODE_BUFFER_Destroy(IN OUT PCONSOLE_SCREEN_BUFFER Buffer);
32 VOID
33 GRAPHICS_BUFFER_Destroy(IN OUT PCONSOLE_SCREEN_BUFFER Buffer);
34
35
36 NTSTATUS
CONSOLE_SCREEN_BUFFER_Initialize(OUT PCONSOLE_SCREEN_BUFFER * Buffer,IN PCONSOLE Console,IN CONSOLE_IO_OBJECT_TYPE Type,IN SIZE_T Size)37 CONSOLE_SCREEN_BUFFER_Initialize(
38 OUT PCONSOLE_SCREEN_BUFFER* Buffer,
39 IN PCONSOLE Console,
40 IN CONSOLE_IO_OBJECT_TYPE Type,
41 IN SIZE_T Size)
42 {
43 if (Buffer == NULL || Console == NULL)
44 return STATUS_INVALID_PARAMETER;
45
46 *Buffer = ConsoleAllocHeap(HEAP_ZERO_MEMORY, max(sizeof(CONSOLE_SCREEN_BUFFER), Size));
47 if (*Buffer == NULL) return STATUS_INSUFFICIENT_RESOURCES;
48
49 /* Initialize the header with the default type */
50 ConSrvInitObject(&(*Buffer)->Header, Type /* SCREEN_BUFFER */, Console);
51 return STATUS_SUCCESS;
52 }
53
54 VOID
CONSOLE_SCREEN_BUFFER_Destroy(IN OUT PCONSOLE_SCREEN_BUFFER Buffer)55 CONSOLE_SCREEN_BUFFER_Destroy(IN OUT PCONSOLE_SCREEN_BUFFER Buffer)
56 {
57 switch (Buffer->Header.Type)
58 {
59 case TEXTMODE_BUFFER:
60 TEXTMODE_BUFFER_Destroy(Buffer);
61 break;
62
63 case GRAPHICS_BUFFER:
64 GRAPHICS_BUFFER_Destroy(Buffer);
65 break;
66
67 case SCREEN_BUFFER:
68 {
69 /* Free the palette handle */
70 if (Buffer->PaletteHandle != NULL)
71 DeleteObject(Buffer->PaletteHandle);
72
73 /* Free the screen buffer memory */
74 ConsoleFreeHeap(Buffer);
75 break;
76 }
77
78 default:
79 break;
80 }
81 }
82
83 // ConDrvCreateConsoleScreenBuffer
84 NTSTATUS
ConDrvCreateScreenBuffer(OUT PCONSOLE_SCREEN_BUFFER * Buffer,IN PCONSOLE Console,IN HANDLE ProcessHandle OPTIONAL,IN ULONG BufferType,IN PVOID ScreenBufferInfo)85 ConDrvCreateScreenBuffer(OUT PCONSOLE_SCREEN_BUFFER* Buffer,
86 IN PCONSOLE Console,
87 IN HANDLE ProcessHandle OPTIONAL,
88 IN ULONG BufferType,
89 IN PVOID ScreenBufferInfo)
90 {
91 NTSTATUS Status = STATUS_UNSUCCESSFUL;
92
93 if ( Console == NULL || Buffer == NULL ||
94 (BufferType != CONSOLE_TEXTMODE_BUFFER && BufferType != CONSOLE_GRAPHICS_BUFFER) )
95 {
96 return STATUS_INVALID_PARAMETER;
97 }
98
99 /* Use the current process if ProcessHandle is NULL */
100 if (ProcessHandle == NULL)
101 ProcessHandle = NtCurrentProcess();
102
103 switch (BufferType)
104 {
105 case CONSOLE_TEXTMODE_BUFFER:
106 Status = TEXTMODE_BUFFER_Initialize(Buffer, Console, ProcessHandle,
107 (PTEXTMODE_BUFFER_INFO)ScreenBufferInfo);
108 break;
109
110 case CONSOLE_GRAPHICS_BUFFER:
111 Status = GRAPHICS_BUFFER_Initialize(Buffer, Console, ProcessHandle,
112 (PGRAPHICS_BUFFER_INFO)ScreenBufferInfo);
113 break;
114
115 default:
116 /* Never ever go there!! */
117 ASSERT(FALSE);
118 }
119
120 /* Insert the newly created screen buffer into the list, if succeeded */
121 if (NT_SUCCESS(Status)) InsertHeadList(&Console->BufferList, &(*Buffer)->ListEntry);
122
123 return Status;
124 }
125
126 static VOID
127 ConioSetActiveScreenBuffer(PCONSOLE_SCREEN_BUFFER Buffer);
128
129 VOID NTAPI
ConDrvDeleteScreenBuffer(PCONSOLE_SCREEN_BUFFER Buffer)130 ConDrvDeleteScreenBuffer(PCONSOLE_SCREEN_BUFFER Buffer)
131 {
132 PCONSOLE Console = Buffer->Header.Console;
133 PCONSOLE_SCREEN_BUFFER NewBuffer;
134
135 /*
136 * We should notify temporarily the frontend because we are susceptible
137 * to delete the screen buffer it is using (which may be different from
138 * the active screen buffer in some cases), and because, if it actually
139 * uses the active screen buffer, we are going to nullify its pointer to
140 * change it.
141 */
142 TermReleaseScreenBuffer(Console, Buffer);
143
144 RemoveEntryList(&Buffer->ListEntry);
145 if (Buffer == Console->ActiveBuffer)
146 {
147 /* Delete active buffer; switch to most recently created */
148 if (!IsListEmpty(&Console->BufferList))
149 {
150 NewBuffer = CONTAINING_RECORD(Console->BufferList.Flink,
151 CONSOLE_SCREEN_BUFFER,
152 ListEntry);
153
154 /* Tie console to new buffer and signal the change to the frontend */
155 ConioSetActiveScreenBuffer(NewBuffer);
156 }
157 else
158 {
159 Console->ActiveBuffer = NULL;
160 // InterlockedExchangePointer(&Console->ActiveBuffer, NULL);
161 }
162 }
163
164 CONSOLE_SCREEN_BUFFER_Destroy(Buffer);
165 }
166
167 static VOID
ConioSetActiveScreenBuffer(PCONSOLE_SCREEN_BUFFER Buffer)168 ConioSetActiveScreenBuffer(PCONSOLE_SCREEN_BUFFER Buffer)
169 {
170 PCONSOLE Console = Buffer->Header.Console;
171 Console->ActiveBuffer = Buffer;
172 // InterlockedExchangePointer(&Console->ActiveBuffer, Buffer);
173 TermSetActiveScreenBuffer(Console);
174 }
175
176 NTSTATUS NTAPI
ConDrvSetConsoleActiveScreenBuffer(IN PCONSOLE Console,IN PCONSOLE_SCREEN_BUFFER Buffer)177 ConDrvSetConsoleActiveScreenBuffer(IN PCONSOLE Console,
178 IN PCONSOLE_SCREEN_BUFFER Buffer)
179 {
180 if (Console == NULL || Buffer == NULL)
181 return STATUS_INVALID_PARAMETER;
182
183 /* Validity check */
184 ASSERT(Console == Buffer->Header.Console);
185
186 if (Buffer == Console->ActiveBuffer) return STATUS_SUCCESS;
187
188 /* If old buffer has no handles, it's now unreferenced */
189 if (Console->ActiveBuffer->Header.ReferenceCount == 0)
190 {
191 ConDrvDeleteScreenBuffer(Console->ActiveBuffer);
192 }
193
194 /* Tie console to new buffer and signal the change to the frontend */
195 ConioSetActiveScreenBuffer(Buffer);
196
197 return STATUS_SUCCESS;
198 }
199
200 PCONSOLE_SCREEN_BUFFER
ConDrvGetActiveScreenBuffer(IN PCONSOLE Console)201 ConDrvGetActiveScreenBuffer(IN PCONSOLE Console)
202 {
203 return (Console ? Console->ActiveBuffer : NULL);
204 }
205
206 /* PUBLIC DRIVER APIS *********************************************************/
207
208 NTSTATUS NTAPI
ConDrvInvalidateBitMapRect(IN PCONSOLE Console,IN PCONSOLE_SCREEN_BUFFER Buffer,IN PSMALL_RECT Region)209 ConDrvInvalidateBitMapRect(IN PCONSOLE Console,
210 IN PCONSOLE_SCREEN_BUFFER Buffer,
211 IN PSMALL_RECT Region)
212 {
213 if (Console == NULL || Buffer == NULL || Region == NULL)
214 return STATUS_INVALID_PARAMETER;
215
216 /* Validity check */
217 ASSERT(Console == Buffer->Header.Console);
218
219 /* If the output buffer is the current one, redraw the correct portion of the screen */
220 if (Buffer == Console->ActiveBuffer) TermDrawRegion(Console, Region);
221
222 return STATUS_SUCCESS;
223 }
224
225 NTSTATUS NTAPI
ConDrvSetConsolePalette(IN PCONSOLE Console,IN PCONSOLE_SCREEN_BUFFER Buffer,IN HPALETTE PaletteHandle,IN UINT PaletteUsage)226 ConDrvSetConsolePalette(IN PCONSOLE Console,
227 // IN PGRAPHICS_SCREEN_BUFFER Buffer,
228 IN PCONSOLE_SCREEN_BUFFER Buffer,
229 IN HPALETTE PaletteHandle,
230 IN UINT PaletteUsage)
231 {
232 BOOL Success;
233
234 /*
235 * Parameters validation
236 */
237 if (Console == NULL || Buffer == NULL)
238 return STATUS_INVALID_PARAMETER;
239
240 if ( PaletteUsage != SYSPAL_STATIC &&
241 PaletteUsage != SYSPAL_NOSTATIC &&
242 PaletteUsage != SYSPAL_NOSTATIC256 )
243 {
244 return STATUS_INVALID_PARAMETER;
245 }
246
247 /* Validity check */
248 ASSERT(Console == Buffer->Header.Console);
249
250 /* Change the palette */
251 Success = TermSetPalette(Console, PaletteHandle, PaletteUsage);
252 if (Success)
253 {
254 /* Free the old palette handle if there was already one set */
255 if ( Buffer->PaletteHandle != NULL &&
256 Buffer->PaletteHandle != PaletteHandle )
257 {
258 DeleteObject(Buffer->PaletteHandle);
259 }
260
261 /* Save the new palette in the screen buffer */
262 Buffer->PaletteHandle = PaletteHandle;
263 Buffer->PaletteUsage = PaletteUsage;
264 }
265
266 return (Success ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL);
267 }
268
269 NTSTATUS NTAPI
ConDrvGetConsoleCursorInfo(IN PCONSOLE Console,IN PTEXTMODE_SCREEN_BUFFER Buffer,OUT PCONSOLE_CURSOR_INFO CursorInfo)270 ConDrvGetConsoleCursorInfo(IN PCONSOLE Console,
271 IN PTEXTMODE_SCREEN_BUFFER Buffer,
272 OUT PCONSOLE_CURSOR_INFO CursorInfo)
273 {
274 if (Console == NULL || Buffer == NULL || CursorInfo == NULL)
275 return STATUS_INVALID_PARAMETER;
276
277 /* Validity check */
278 ASSERT(Console == Buffer->Header.Console);
279
280 *CursorInfo = Buffer->CursorInfo;
281 // CursorInfo->bVisible = Buffer->CursorInfo.bVisible;
282 // CursorInfo->dwSize = Buffer->CursorInfo.dwSize;
283
284 return STATUS_SUCCESS;
285 }
286
287 NTSTATUS NTAPI
ConDrvSetConsoleCursorInfo(IN PCONSOLE Console,IN PTEXTMODE_SCREEN_BUFFER Buffer,IN PCONSOLE_CURSOR_INFO CursorInfo)288 ConDrvSetConsoleCursorInfo(IN PCONSOLE Console,
289 IN PTEXTMODE_SCREEN_BUFFER Buffer,
290 IN PCONSOLE_CURSOR_INFO CursorInfo)
291 {
292 ULONG Size;
293 BOOLEAN Visible, Success = TRUE;
294
295 if (Console == NULL || Buffer == NULL || CursorInfo == NULL)
296 return STATUS_INVALID_PARAMETER;
297
298 /* Validity check */
299 ASSERT(Console == Buffer->Header.Console);
300
301 Size = min(max(CursorInfo->dwSize, 1), 100);
302 Visible = CursorInfo->bVisible;
303
304 if ( (Size != Buffer->CursorInfo.dwSize) ||
305 (Visible && !Buffer->CursorInfo.bVisible) ||
306 (!Visible && Buffer->CursorInfo.bVisible) )
307 {
308 Buffer->CursorInfo.dwSize = Size;
309 Buffer->CursorInfo.bVisible = Visible;
310
311 Success = TermSetCursorInfo(Console, (PCONSOLE_SCREEN_BUFFER)Buffer);
312 }
313
314 return (Success ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL);
315 }
316
317 NTSTATUS NTAPI
ConDrvSetConsoleCursorPosition(IN PCONSOLE Console,IN PTEXTMODE_SCREEN_BUFFER Buffer,IN PCOORD Position)318 ConDrvSetConsoleCursorPosition(IN PCONSOLE Console,
319 IN PTEXTMODE_SCREEN_BUFFER Buffer,
320 IN PCOORD Position)
321 {
322 SHORT OldCursorX, OldCursorY;
323
324 if (Console == NULL || Buffer == NULL || Position == NULL)
325 return STATUS_INVALID_PARAMETER;
326
327 /* Validity check */
328 ASSERT(Console == Buffer->Header.Console);
329
330 if ( Position->X < 0 || Position->X >= Buffer->ScreenBufferSize.X ||
331 Position->Y < 0 || Position->Y >= Buffer->ScreenBufferSize.Y )
332 {
333 return STATUS_INVALID_PARAMETER;
334 }
335
336 OldCursorX = Buffer->CursorPosition.X;
337 OldCursorY = Buffer->CursorPosition.Y;
338 Buffer->CursorPosition = *Position;
339
340 if ( ((PCONSOLE_SCREEN_BUFFER)Buffer == Console->ActiveBuffer) &&
341 (!TermSetScreenInfo(Console, (PCONSOLE_SCREEN_BUFFER)Buffer, OldCursorX, OldCursorY)) )
342 {
343 return STATUS_UNSUCCESSFUL;
344 }
345
346 return STATUS_SUCCESS;
347 }
348
349 /* EOF */
350