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