[KERNEL32][CONSRV]
[reactos.git] / win32ss / user / winsrv / consrv / conoutput.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Console Server DLL
4 * FILE: win32ss/user/winsrv/consrv/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 /* PUBLIC SERVER APIS *********************************************************/
18
19 NTSTATUS NTAPI
20 ConDrvInvalidateBitMapRect(IN PCONSOLE Console,
21 IN PCONSOLE_SCREEN_BUFFER Buffer,
22 IN PSMALL_RECT Region);
23 CSR_API(SrvInvalidateBitMapRect)
24 {
25 NTSTATUS Status;
26 PCONSOLE_INVALIDATEDIBITS InvalidateDIBitsRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.InvalidateDIBitsRequest;
27 PCONSOLE_SCREEN_BUFFER Buffer;
28
29 DPRINT("SrvInvalidateBitMapRect\n");
30
31 Status = ConSrvGetScreenBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
32 InvalidateDIBitsRequest->OutputHandle,
33 &Buffer, GENERIC_READ, TRUE);
34 if (!NT_SUCCESS(Status)) return Status;
35
36 Status = ConDrvInvalidateBitMapRect(Buffer->Header.Console,
37 Buffer,
38 &InvalidateDIBitsRequest->Region);
39
40 ConSrvReleaseScreenBuffer(Buffer, TRUE);
41 return Status;
42 }
43
44 NTSTATUS NTAPI
45 ConDrvSetConsolePalette(IN PCONSOLE Console,
46 // IN PGRAPHICS_SCREEN_BUFFER Buffer,
47 IN PCONSOLE_SCREEN_BUFFER Buffer,
48 IN HPALETTE PaletteHandle,
49 IN UINT PaletteUsage);
50 CSR_API(SrvSetConsolePalette)
51 {
52 NTSTATUS Status;
53 PCONSOLE_SETPALETTE SetPaletteRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.SetPaletteRequest;
54 // PGRAPHICS_SCREEN_BUFFER Buffer;
55 PCONSOLE_SCREEN_BUFFER Buffer;
56
57 DPRINT("SrvSetConsolePalette\n");
58
59 // NOTE: Tests show that this function is used only for graphics screen buffers
60 // and otherwise it returns FALSE + sets last error to invalid handle.
61 // I think it's ridiculous, because if you are in text mode, simulating
62 // a change of VGA palette via DAC registers (done by a call to SetConsolePalette)
63 // cannot be done... So I allow it in ReactOS !
64 /*
65 Status = ConSrvGetGraphicsBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
66 SetPaletteRequest->OutputHandle,
67 &Buffer, GENERIC_WRITE, TRUE);
68 */
69 Status = ConSrvGetScreenBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
70 SetPaletteRequest->OutputHandle,
71 &Buffer, GENERIC_WRITE, TRUE);
72 if (!NT_SUCCESS(Status)) return Status;
73
74 /*
75 * Make the palette handle public, so that it can be
76 * used by other threads calling GDI functions on it.
77 * Indeed, the palette handle comes from a console app
78 * calling ourselves, running in CSRSS.
79 */
80 NtUserConsoleControl(ConsoleMakePalettePublic,
81 &SetPaletteRequest->PaletteHandle,
82 sizeof(SetPaletteRequest->PaletteHandle));
83
84 Status = ConDrvSetConsolePalette(Buffer->Header.Console,
85 Buffer,
86 SetPaletteRequest->PaletteHandle,
87 SetPaletteRequest->Usage);
88
89 ConSrvReleaseScreenBuffer(Buffer, TRUE);
90 return Status;
91 }
92
93 NTSTATUS NTAPI
94 ConDrvGetConsoleCursorInfo(IN PCONSOLE Console,
95 IN PTEXTMODE_SCREEN_BUFFER Buffer,
96 OUT PCONSOLE_CURSOR_INFO CursorInfo);
97 CSR_API(SrvGetConsoleCursorInfo)
98 {
99 NTSTATUS Status;
100 PCONSOLE_GETSETCURSORINFO CursorInfoRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.CursorInfoRequest;
101 PTEXTMODE_SCREEN_BUFFER Buffer;
102
103 DPRINT("SrvGetConsoleCursorInfo\n");
104
105 Status = ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
106 CursorInfoRequest->OutputHandle,
107 &Buffer, GENERIC_READ, TRUE);
108 if (!NT_SUCCESS(Status)) return Status;
109
110 Status = ConDrvGetConsoleCursorInfo(Buffer->Header.Console,
111 Buffer,
112 &CursorInfoRequest->Info);
113
114 ConSrvReleaseScreenBuffer(Buffer, TRUE);
115 return Status;
116 }
117
118 NTSTATUS NTAPI
119 ConDrvSetConsoleCursorInfo(IN PCONSOLE Console,
120 IN PTEXTMODE_SCREEN_BUFFER Buffer,
121 IN PCONSOLE_CURSOR_INFO CursorInfo);
122 CSR_API(SrvSetConsoleCursorInfo)
123 {
124 NTSTATUS Status;
125 PCONSOLE_GETSETCURSORINFO CursorInfoRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.CursorInfoRequest;
126 PTEXTMODE_SCREEN_BUFFER Buffer;
127
128 DPRINT("SrvSetConsoleCursorInfo\n");
129
130 Status = ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
131 CursorInfoRequest->OutputHandle,
132 &Buffer, GENERIC_WRITE, TRUE);
133 if (!NT_SUCCESS(Status)) return Status;
134
135 Status = ConDrvSetConsoleCursorInfo(Buffer->Header.Console,
136 Buffer,
137 &CursorInfoRequest->Info);
138
139 ConSrvReleaseScreenBuffer(Buffer, TRUE);
140 return Status;
141 }
142
143 NTSTATUS NTAPI
144 ConDrvSetConsoleCursorPosition(IN PCONSOLE Console,
145 IN PTEXTMODE_SCREEN_BUFFER Buffer,
146 IN PCOORD Position);
147 CSR_API(SrvSetConsoleCursorPosition)
148 {
149 NTSTATUS Status;
150 PCONSOLE_SETCURSORPOSITION SetCursorPositionRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.SetCursorPositionRequest;
151 PTEXTMODE_SCREEN_BUFFER Buffer;
152
153 DPRINT("SrvSetConsoleCursorPosition\n");
154
155 Status = ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
156 SetCursorPositionRequest->OutputHandle,
157 &Buffer, GENERIC_WRITE, TRUE);
158 if (!NT_SUCCESS(Status)) return Status;
159
160 Status = ConDrvSetConsoleCursorPosition(Buffer->Header.Console,
161 Buffer,
162 &SetCursorPositionRequest->Position);
163
164 ConSrvReleaseScreenBuffer(Buffer, TRUE);
165 return Status;
166 }
167
168 CSR_API(SrvCreateConsoleScreenBuffer)
169 {
170 NTSTATUS Status = STATUS_INVALID_PARAMETER;
171 PCONSOLE_CREATESCREENBUFFER CreateScreenBufferRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.CreateScreenBufferRequest;
172 PCONSOLE_PROCESS_DATA ProcessData = ConsoleGetPerProcessData(CsrGetClientThread()->Process);
173 PCONSOLE Console;
174 PCONSOLE_SCREEN_BUFFER Buff;
175
176 PVOID ScreenBufferInfo = NULL;
177 TEXTMODE_BUFFER_INFO TextModeInfo = {{80, 25},
178 DEFAULT_SCREEN_ATTRIB,
179 DEFAULT_POPUP_ATTRIB ,
180 TRUE,
181 CSR_DEFAULT_CURSOR_SIZE};
182 GRAPHICS_BUFFER_INFO GraphicsInfo;
183 GraphicsInfo.Info = CreateScreenBufferRequest->GraphicsBufferInfo; // HACK for MSVC
184
185 DPRINT("SrvCreateConsoleScreenBuffer\n");
186
187 Status = ConSrvGetConsole(ProcessData, &Console, TRUE);
188 if (!NT_SUCCESS(Status)) return Status;
189
190 if (CreateScreenBufferRequest->ScreenBufferType == CONSOLE_TEXTMODE_BUFFER)
191 {
192 ScreenBufferInfo = &TextModeInfo;
193
194 /*
195 if (Console->ActiveBuffer)
196 {
197 TextModeInfo.ScreenBufferSize = Console->ActiveBuffer->ScreenBufferSize;
198 if (TextModeInfo.ScreenBufferSize.X == 0) TextModeInfo.ScreenBufferSize.X = 80;
199 if (TextModeInfo.ScreenBufferSize.Y == 0) TextModeInfo.ScreenBufferSize.Y = 25;
200
201 TextModeInfo.ScreenAttrib = Console->ActiveBuffer->ScreenBuffer.TextBuffer.ScreenDefaultAttrib;
202 TextModeInfo.PopupAttrib = Console->ActiveBuffer->ScreenBuffer.TextBuffer.PopupDefaultAttrib;
203
204 TextModeInfo.IsCursorVisible = Console->ActiveBuffer->CursorInfo.bVisible;
205 TextModeInfo.CursorSize = Console->ActiveBuffer->CursorInfo.dwSize;
206 }
207 */
208
209 /*
210 * This is Windows' behaviour
211 */
212
213 /* Use the current console size. Regularize it if needed. */
214 TextModeInfo.ScreenBufferSize = Console->ConsoleSize;
215 if (TextModeInfo.ScreenBufferSize.X == 0) TextModeInfo.ScreenBufferSize.X = 1;
216 if (TextModeInfo.ScreenBufferSize.Y == 0) TextModeInfo.ScreenBufferSize.Y = 1;
217
218 /* If we have an active screen buffer, use its attributes as the new ones */
219 if (Console->ActiveBuffer && GetType(Console->ActiveBuffer) == TEXTMODE_BUFFER)
220 {
221 PTEXTMODE_SCREEN_BUFFER Buffer = (PTEXTMODE_SCREEN_BUFFER)Console->ActiveBuffer;
222
223 TextModeInfo.ScreenAttrib = Buffer->ScreenDefaultAttrib;
224 TextModeInfo.PopupAttrib = Buffer->PopupDefaultAttrib;
225
226 TextModeInfo.IsCursorVisible = Buffer->CursorInfo.bVisible;
227 TextModeInfo.CursorSize = Buffer->CursorInfo.dwSize;
228 }
229 }
230 else if (CreateScreenBufferRequest->ScreenBufferType == CONSOLE_GRAPHICS_BUFFER)
231 {
232 /* Get infos from the graphics buffer information structure */
233 if (!CsrValidateMessageBuffer(ApiMessage,
234 (PVOID*)&CreateScreenBufferRequest->GraphicsBufferInfo.lpBitMapInfo,
235 CreateScreenBufferRequest->GraphicsBufferInfo.dwBitMapInfoLength,
236 sizeof(BYTE)))
237 {
238 Status = STATUS_INVALID_PARAMETER;
239 goto Quit;
240 }
241
242 ScreenBufferInfo = &GraphicsInfo;
243
244 /* Initialize shared variables */
245 // CreateScreenBufferRequest->GraphicsBufferInfo.hMutex
246 CreateScreenBufferRequest->hMutex = GraphicsInfo.Info.hMutex = INVALID_HANDLE_VALUE;
247 // CreateScreenBufferRequest->GraphicsBufferInfo.lpBitMap
248 CreateScreenBufferRequest->lpBitMap = GraphicsInfo.Info.lpBitMap = NULL;
249
250 /* A graphics screen buffer is never inheritable */
251 CreateScreenBufferRequest->InheritHandle = FALSE;
252 }
253
254 Status = ConDrvCreateScreenBuffer(&Buff,
255 Console,
256 CreateScreenBufferRequest->ScreenBufferType,
257 ScreenBufferInfo);
258 if (!NT_SUCCESS(Status)) goto Quit;
259
260 /* Insert the new handle inside the process handles table */
261 RtlEnterCriticalSection(&ProcessData->HandleTableLock);
262
263 Status = ConSrvInsertObject(ProcessData,
264 &CreateScreenBufferRequest->OutputHandle,
265 &Buff->Header,
266 CreateScreenBufferRequest->DesiredAccess,
267 CreateScreenBufferRequest->InheritHandle,
268 CreateScreenBufferRequest->ShareMode);
269
270 RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
271
272 if (!NT_SUCCESS(Status)) goto Quit;
273
274 if (CreateScreenBufferRequest->ScreenBufferType == CONSOLE_GRAPHICS_BUFFER)
275 {
276 PGRAPHICS_SCREEN_BUFFER Buffer = (PGRAPHICS_SCREEN_BUFFER)Buff;
277 /*
278 * Initialize the graphics buffer information structure
279 * and give it back to the client.
280 */
281 // CreateScreenBufferRequest->GraphicsBufferInfo.hMutex
282 CreateScreenBufferRequest->hMutex = Buffer->ClientMutex;
283 // CreateScreenBufferRequest->GraphicsBufferInfo.lpBitMap
284 CreateScreenBufferRequest->lpBitMap = Buffer->ClientBitMap;
285 }
286
287 Quit:
288 ConSrvReleaseConsole(Console, TRUE);
289 return Status;
290 }
291
292 NTSTATUS NTAPI
293 ConDrvSetConsoleActiveScreenBuffer(IN PCONSOLE Console,
294 IN PCONSOLE_SCREEN_BUFFER Buffer);
295 CSR_API(SrvSetConsoleActiveScreenBuffer)
296 {
297 NTSTATUS Status;
298 PCONSOLE_SETACTIVESCREENBUFFER SetScreenBufferRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.SetScreenBufferRequest;
299 PCONSOLE_SCREEN_BUFFER Buffer;
300
301 DPRINT("SrvSetConsoleActiveScreenBuffer\n");
302
303 Status = ConSrvGetScreenBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
304 SetScreenBufferRequest->OutputHandle,
305 &Buffer, GENERIC_WRITE, TRUE);
306 if (!NT_SUCCESS(Status)) return Status;
307
308 Status = ConDrvSetConsoleActiveScreenBuffer(Buffer->Header.Console,
309 Buffer);
310
311 ConSrvReleaseScreenBuffer(Buffer, TRUE);
312 return Status;
313 }
314
315
316 /* CSR THREADS FOR WriteConsole ***********************************************/
317
318 static NTSTATUS
319 DoWriteConsole(IN PCSR_API_MESSAGE ApiMessage,
320 IN PCSR_THREAD ClientThread,
321 IN BOOLEAN CreateWaitBlock OPTIONAL);
322
323 // Wait function CSR_WAIT_FUNCTION
324 static BOOLEAN
325 NTAPI
326 WriteConsoleThread(IN PLIST_ENTRY WaitList,
327 IN PCSR_THREAD WaitThread,
328 IN PCSR_API_MESSAGE WaitApiMessage,
329 IN PVOID WaitContext,
330 IN PVOID WaitArgument1,
331 IN PVOID WaitArgument2,
332 IN ULONG WaitFlags)
333 {
334 NTSTATUS Status;
335
336 DPRINT("WriteConsoleThread - WaitContext = 0x%p, WaitArgument1 = 0x%p, WaitArgument2 = 0x%p, WaitFlags = %lu\n", WaitContext, WaitArgument1, WaitArgument2, WaitFlags);
337
338 /*
339 * If we are notified of the process termination via a call
340 * to CsrNotifyWaitBlock triggered by CsrDestroyProcess or
341 * CsrDestroyThread, just return.
342 */
343 if (WaitFlags & CsrProcessTerminating)
344 {
345 Status = STATUS_THREAD_IS_TERMINATING;
346 goto Quit;
347 }
348
349 Status = DoWriteConsole(WaitApiMessage, WaitThread, FALSE);
350
351 Quit:
352 if (Status != STATUS_PENDING)
353 {
354 WaitApiMessage->Status = Status;
355 }
356
357 return (Status == STATUS_PENDING ? FALSE : TRUE);
358 }
359
360 NTSTATUS NTAPI
361 ConDrvWriteConsole(IN PCONSOLE Console,
362 IN PTEXTMODE_SCREEN_BUFFER ScreenBuffer,
363 IN BOOLEAN Unicode,
364 IN PVOID StringBuffer,
365 IN ULONG NumCharsToWrite,
366 OUT PULONG NumCharsWritten OPTIONAL);
367 static NTSTATUS
368 DoWriteConsole(IN PCSR_API_MESSAGE ApiMessage,
369 IN PCSR_THREAD ClientThread,
370 IN BOOLEAN CreateWaitBlock OPTIONAL)
371 {
372 NTSTATUS Status;
373 PCONSOLE_WRITECONSOLE WriteConsoleRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.WriteConsoleRequest;
374 PTEXTMODE_SCREEN_BUFFER ScreenBuffer;
375
376 Status = ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(ClientThread->Process),
377 WriteConsoleRequest->OutputHandle,
378 &ScreenBuffer, GENERIC_WRITE, FALSE);
379 if (!NT_SUCCESS(Status)) return Status;
380
381 Status = ConDrvWriteConsole(ScreenBuffer->Header.Console,
382 ScreenBuffer,
383 WriteConsoleRequest->Unicode,
384 WriteConsoleRequest->Buffer,
385 WriteConsoleRequest->NrCharactersToWrite,
386 &WriteConsoleRequest->NrCharactersWritten);
387
388 if (Status == STATUS_PENDING)
389 {
390 if (CreateWaitBlock)
391 {
392 if (!CsrCreateWait(&ScreenBuffer->Header.Console->WriteWaitQueue,
393 WriteConsoleThread,
394 ClientThread,
395 ApiMessage,
396 NULL))
397 {
398 /* Fail */
399 Status = STATUS_NO_MEMORY;
400 goto Quit;
401 }
402 }
403
404 /* Wait until we un-pause the console */
405 // Status = STATUS_PENDING;
406 }
407
408 Quit:
409 ConSrvReleaseScreenBuffer(ScreenBuffer, FALSE);
410 return Status;
411 }
412
413
414 /* TEXT OUTPUT APIS ***********************************************************/
415
416 NTSTATUS NTAPI
417 ConDrvReadConsoleOutput(IN PCONSOLE Console,
418 IN PTEXTMODE_SCREEN_BUFFER Buffer,
419 IN BOOLEAN Unicode,
420 OUT PCHAR_INFO CharInfo/*Buffer*/,
421 IN PCOORD BufferSize,
422 IN PCOORD BufferCoord,
423 IN OUT PSMALL_RECT ReadRegion);
424 CSR_API(SrvReadConsoleOutput)
425 {
426 NTSTATUS Status;
427 PCONSOLE_READOUTPUT ReadOutputRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.ReadOutputRequest;
428 PTEXTMODE_SCREEN_BUFFER Buffer;
429
430 DPRINT("SrvReadConsoleOutput\n");
431
432 if (!CsrValidateMessageBuffer(ApiMessage,
433 (PVOID*)&ReadOutputRequest->CharInfo,
434 ReadOutputRequest->BufferSize.X * ReadOutputRequest->BufferSize.Y,
435 sizeof(CHAR_INFO)))
436 {
437 return STATUS_INVALID_PARAMETER;
438 }
439
440 Status = ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
441 ReadOutputRequest->OutputHandle,
442 &Buffer, GENERIC_READ, TRUE);
443 if (!NT_SUCCESS(Status)) return Status;
444
445 Status = ConDrvReadConsoleOutput(Buffer->Header.Console,
446 Buffer,
447 ReadOutputRequest->Unicode,
448 ReadOutputRequest->CharInfo,
449 &ReadOutputRequest->BufferSize,
450 &ReadOutputRequest->BufferCoord,
451 &ReadOutputRequest->ReadRegion);
452
453 ConSrvReleaseScreenBuffer(Buffer, TRUE);
454 return Status;
455 }
456
457 NTSTATUS NTAPI
458 ConDrvWriteConsoleOutput(IN PCONSOLE Console,
459 IN PTEXTMODE_SCREEN_BUFFER Buffer,
460 IN BOOLEAN Unicode,
461 IN PCHAR_INFO CharInfo/*Buffer*/,
462 IN PCOORD BufferSize,
463 IN PCOORD BufferCoord,
464 IN OUT PSMALL_RECT WriteRegion);
465 CSR_API(SrvWriteConsoleOutput)
466 {
467 NTSTATUS Status;
468 PCONSOLE_WRITEOUTPUT WriteOutputRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.WriteOutputRequest;
469 PTEXTMODE_SCREEN_BUFFER Buffer;
470
471 DPRINT("SrvWriteConsoleOutput\n");
472
473 if (!CsrValidateMessageBuffer(ApiMessage,
474 (PVOID*)&WriteOutputRequest->CharInfo,
475 WriteOutputRequest->BufferSize.X * WriteOutputRequest->BufferSize.Y,
476 sizeof(CHAR_INFO)))
477 {
478 return STATUS_INVALID_PARAMETER;
479 }
480
481 Status = ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
482 WriteOutputRequest->OutputHandle,
483 &Buffer, GENERIC_WRITE, TRUE);
484 if (!NT_SUCCESS(Status)) return Status;
485
486 Status = ConDrvWriteConsoleOutput(Buffer->Header.Console,
487 Buffer,
488 WriteOutputRequest->Unicode,
489 WriteOutputRequest->CharInfo,
490 &WriteOutputRequest->BufferSize,
491 &WriteOutputRequest->BufferCoord,
492 &WriteOutputRequest->WriteRegion);
493
494 ConSrvReleaseScreenBuffer(Buffer, TRUE);
495 return Status;
496 }
497
498 CSR_API(SrvWriteConsole)
499 {
500 NTSTATUS Status;
501 PCONSOLE_WRITECONSOLE WriteConsoleRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.WriteConsoleRequest;
502
503 DPRINT("SrvWriteConsole\n");
504
505 if (!CsrValidateMessageBuffer(ApiMessage,
506 (PVOID)&WriteConsoleRequest->Buffer,
507 WriteConsoleRequest->BufferSize,
508 sizeof(BYTE)))
509 {
510 return STATUS_INVALID_PARAMETER;
511 }
512
513 Status = DoWriteConsole(ApiMessage, CsrGetClientThread(), TRUE);
514
515 if (Status == STATUS_PENDING) *ReplyCode = CsrReplyPending;
516
517 return Status;
518 }
519
520 NTSTATUS NTAPI
521 ConDrvReadConsoleOutputString(IN PCONSOLE Console,
522 IN PTEXTMODE_SCREEN_BUFFER Buffer,
523 IN CODE_TYPE CodeType,
524 OUT PVOID StringBuffer,
525 IN ULONG NumCodesToRead,
526 IN PCOORD ReadCoord,
527 // OUT PCOORD EndCoord,
528 OUT PULONG CodesRead);
529 CSR_API(SrvReadConsoleOutputString)
530 {
531 NTSTATUS Status;
532 PCONSOLE_READOUTPUTCODE ReadOutputCodeRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.ReadOutputCodeRequest;
533 PTEXTMODE_SCREEN_BUFFER Buffer;
534 ULONG CodeSize;
535
536 PVOID pCode;
537
538 DPRINT("SrvReadConsoleOutputString\n");
539
540 switch (ReadOutputCodeRequest->CodeType)
541 {
542 case CODE_ASCII:
543 CodeSize = sizeof(CHAR);
544 break;
545
546 case CODE_UNICODE:
547 CodeSize = sizeof(WCHAR);
548 break;
549
550 case CODE_ATTRIBUTE:
551 CodeSize = sizeof(WORD);
552 break;
553
554 default:
555 return STATUS_INVALID_PARAMETER;
556 }
557
558 /*
559 * For optimization purposes, Windows (and hence ReactOS, too, for
560 * compatibility reasons) uses a static buffer if no more than eighty
561 * bytes are read. Otherwise a new buffer is used.
562 * The client-side expects that we know this behaviour.
563 */
564 if (ReadOutputCodeRequest->NumCodes * CodeSize <= sizeof(ReadOutputCodeRequest->CodeStaticBuffer))
565 {
566 /*
567 * Adjust the internal pointer, because its old value points to
568 * the static buffer in the original ApiMessage structure.
569 */
570 // ReadOutputCodeRequest->pCode.pCode = ReadOutputCodeRequest->CodeStaticBuffer;
571 pCode = ReadOutputCodeRequest->CodeStaticBuffer;
572 }
573 else
574 {
575 if (!CsrValidateMessageBuffer(ApiMessage,
576 (PVOID*)&ReadOutputCodeRequest->pCode.pCode,
577 ReadOutputCodeRequest->NumCodes,
578 CodeSize))
579 {
580 return STATUS_INVALID_PARAMETER;
581 }
582
583 pCode = ReadOutputCodeRequest->pCode.pCode;
584 }
585
586 Status = ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
587 ReadOutputCodeRequest->OutputHandle,
588 &Buffer, GENERIC_READ, TRUE);
589 if (!NT_SUCCESS(Status)) return Status;
590
591 Status = ConDrvReadConsoleOutputString(Buffer->Header.Console,
592 Buffer,
593 ReadOutputCodeRequest->CodeType,
594 pCode,
595 ReadOutputCodeRequest->NumCodes,
596 &ReadOutputCodeRequest->Coord,
597 // &ReadOutputCodeRequest->EndCoord,
598 &ReadOutputCodeRequest->NumCodes);
599
600 ConSrvReleaseScreenBuffer(Buffer, TRUE);
601 return Status;
602 }
603
604 NTSTATUS NTAPI
605 ConDrvWriteConsoleOutputString(IN PCONSOLE Console,
606 IN PTEXTMODE_SCREEN_BUFFER Buffer,
607 IN CODE_TYPE CodeType,
608 IN PVOID StringBuffer,
609 IN ULONG NumCodesToWrite,
610 IN PCOORD WriteCoord /*,
611 OUT PCOORD EndCoord,
612 OUT PULONG CodesWritten */);
613 CSR_API(SrvWriteConsoleOutputString)
614 {
615 NTSTATUS Status;
616 PCONSOLE_WRITEOUTPUTCODE WriteOutputCodeRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.WriteOutputCodeRequest;
617 PTEXTMODE_SCREEN_BUFFER Buffer;
618 ULONG CodeSize;
619
620 PVOID pCode;
621
622 DPRINT("SrvWriteConsoleOutputString\n");
623
624 switch (WriteOutputCodeRequest->CodeType)
625 {
626 case CODE_ASCII:
627 CodeSize = sizeof(CHAR);
628 break;
629
630 case CODE_UNICODE:
631 CodeSize = sizeof(WCHAR);
632 break;
633
634 case CODE_ATTRIBUTE:
635 CodeSize = sizeof(WORD);
636 break;
637
638 default:
639 return STATUS_INVALID_PARAMETER;
640 }
641
642 /*
643 * For optimization purposes, Windows (and hence ReactOS, too, for
644 * compatibility reasons) uses a static buffer if no more than eighty
645 * bytes are written. Otherwise a new buffer is used.
646 * The client-side expects that we know this behaviour.
647 */
648 if (WriteOutputCodeRequest->NumCodes * CodeSize <= sizeof(WriteOutputCodeRequest->CodeStaticBuffer))
649 {
650 /*
651 * Adjust the internal pointer, because its old value points to
652 * the static buffer in the original ApiMessage structure.
653 */
654 // WriteOutputCodeRequest->pCode.pCode = WriteOutputCodeRequest->CodeStaticBuffer;
655 pCode = WriteOutputCodeRequest->CodeStaticBuffer;
656 }
657 else
658 {
659 if (!CsrValidateMessageBuffer(ApiMessage,
660 (PVOID*)&WriteOutputCodeRequest->pCode.pCode,
661 WriteOutputCodeRequest->NumCodes,
662 CodeSize))
663 {
664 return STATUS_INVALID_PARAMETER;
665 }
666
667 pCode = WriteOutputCodeRequest->pCode.pCode;
668 }
669
670 Status = ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
671 WriteOutputCodeRequest->OutputHandle,
672 &Buffer, GENERIC_WRITE, TRUE);
673 if (!NT_SUCCESS(Status)) return Status;
674
675 Status = ConDrvWriteConsoleOutputString(Buffer->Header.Console,
676 Buffer,
677 WriteOutputCodeRequest->CodeType,
678 pCode,
679 WriteOutputCodeRequest->NumCodes,
680 &WriteOutputCodeRequest->Coord /*,
681 &WriteOutputCodeRequest->EndCoord,
682 &WriteOutputCodeRequest->NrCharactersWritten */);
683
684 // WriteOutputCodeRequest->NrCharactersWritten = Written;
685
686 ConSrvReleaseScreenBuffer(Buffer, TRUE);
687 return Status;
688 }
689
690 NTSTATUS NTAPI
691 ConDrvFillConsoleOutput(IN PCONSOLE Console,
692 IN PTEXTMODE_SCREEN_BUFFER Buffer,
693 IN CODE_TYPE CodeType,
694 IN PVOID Code,
695 IN ULONG NumCodesToWrite,
696 IN PCOORD WriteCoord /*,
697 OUT PULONG CodesWritten */);
698 CSR_API(SrvFillConsoleOutput)
699 {
700 NTSTATUS Status;
701 PCONSOLE_FILLOUTPUTCODE FillOutputRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.FillOutputRequest;
702 PTEXTMODE_SCREEN_BUFFER Buffer;
703 USHORT CodeType = FillOutputRequest->CodeType;
704
705 DPRINT("SrvFillConsoleOutput\n");
706
707 if ( (CodeType != CODE_ASCII ) &&
708 (CodeType != CODE_UNICODE ) &&
709 (CodeType != CODE_ATTRIBUTE) )
710 {
711 return STATUS_INVALID_PARAMETER;
712 }
713
714 Status = ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
715 FillOutputRequest->OutputHandle,
716 &Buffer, GENERIC_WRITE, TRUE);
717 if (!NT_SUCCESS(Status)) return Status;
718
719 Status = ConDrvFillConsoleOutput(Buffer->Header.Console,
720 Buffer,
721 CodeType,
722 &FillOutputRequest->Code,
723 FillOutputRequest->NumCodes,
724 &FillOutputRequest->WriteCoord /*,
725 &FillOutputRequest->NrCharactersWritten */);
726
727 // FillOutputRequest->NrCharactersWritten = Written;
728
729 ConSrvReleaseScreenBuffer(Buffer, TRUE);
730 return Status;
731 }
732
733 NTSTATUS NTAPI
734 ConDrvGetConsoleScreenBufferInfo(IN PCONSOLE Console,
735 IN PTEXTMODE_SCREEN_BUFFER Buffer,
736 OUT PCOORD ScreenBufferSize,
737 OUT PCOORD CursorPosition,
738 OUT PCOORD ViewOrigin,
739 OUT PCOORD ViewSize,
740 OUT PCOORD MaximumViewSize,
741 OUT PWORD Attributes);
742 CSR_API(SrvGetConsoleScreenBufferInfo)
743 {
744 NTSTATUS Status;
745 PCONSOLE_GETSCREENBUFFERINFO ScreenBufferInfoRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.ScreenBufferInfoRequest;
746 PTEXTMODE_SCREEN_BUFFER Buffer;
747
748 DPRINT("SrvGetConsoleScreenBufferInfo\n");
749
750 Status = ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
751 ScreenBufferInfoRequest->OutputHandle,
752 &Buffer, GENERIC_READ, TRUE);
753 if (!NT_SUCCESS(Status)) return Status;
754
755 Status = ConDrvGetConsoleScreenBufferInfo(Buffer->Header.Console,
756 Buffer,
757 &ScreenBufferInfoRequest->ScreenBufferSize,
758 &ScreenBufferInfoRequest->CursorPosition,
759 &ScreenBufferInfoRequest->ViewOrigin,
760 &ScreenBufferInfoRequest->ViewSize,
761 &ScreenBufferInfoRequest->MaximumViewSize,
762 &ScreenBufferInfoRequest->Attributes);
763
764 ConSrvReleaseScreenBuffer(Buffer, TRUE);
765 return Status;
766 }
767
768 NTSTATUS NTAPI
769 ConDrvSetConsoleTextAttribute(IN PCONSOLE Console,
770 IN PTEXTMODE_SCREEN_BUFFER Buffer,
771 IN WORD Attributes);
772 CSR_API(SrvSetConsoleTextAttribute)
773 {
774 NTSTATUS Status;
775 PCONSOLE_SETTEXTATTRIB SetTextAttribRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.SetTextAttribRequest;
776 PTEXTMODE_SCREEN_BUFFER Buffer;
777
778 DPRINT("SrvSetConsoleTextAttribute\n");
779
780 Status = ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
781 SetTextAttribRequest->OutputHandle,
782 &Buffer, GENERIC_WRITE, TRUE);
783 if (!NT_SUCCESS(Status)) return Status;
784
785 Status = ConDrvSetConsoleTextAttribute(Buffer->Header.Console,
786 Buffer,
787 SetTextAttribRequest->Attributes);
788
789 ConSrvReleaseScreenBuffer(Buffer, TRUE);
790 return Status;
791 }
792
793 NTSTATUS NTAPI
794 ConDrvSetConsoleScreenBufferSize(IN PCONSOLE Console,
795 IN PTEXTMODE_SCREEN_BUFFER Buffer,
796 IN PCOORD Size);
797 CSR_API(SrvSetConsoleScreenBufferSize)
798 {
799 NTSTATUS Status;
800 PCONSOLE_SETSCREENBUFFERSIZE SetScreenBufferSizeRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.SetScreenBufferSizeRequest;
801 PTEXTMODE_SCREEN_BUFFER Buffer;
802
803 DPRINT("SrvSetConsoleScreenBufferSize\n");
804
805 Status = ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
806 SetScreenBufferSizeRequest->OutputHandle,
807 &Buffer, GENERIC_WRITE, TRUE);
808 if (!NT_SUCCESS(Status)) return Status;
809
810 Status = ConDrvSetConsoleScreenBufferSize(Buffer->Header.Console,
811 Buffer,
812 &SetScreenBufferSizeRequest->Size);
813
814 ConSrvReleaseScreenBuffer(Buffer, TRUE);
815 return Status;
816 }
817
818 NTSTATUS NTAPI
819 ConDrvScrollConsoleScreenBuffer(IN PCONSOLE Console,
820 IN PTEXTMODE_SCREEN_BUFFER Buffer,
821 IN BOOLEAN Unicode,
822 IN PSMALL_RECT ScrollRectangle,
823 IN BOOLEAN UseClipRectangle,
824 IN PSMALL_RECT ClipRectangle OPTIONAL,
825 IN PCOORD DestinationOrigin,
826 IN CHAR_INFO FillChar);
827 CSR_API(SrvScrollConsoleScreenBuffer)
828 {
829 NTSTATUS Status;
830 PCONSOLE_SCROLLSCREENBUFFER ScrollScreenBufferRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.ScrollScreenBufferRequest;
831 PTEXTMODE_SCREEN_BUFFER Buffer;
832
833 DPRINT("SrvScrollConsoleScreenBuffer\n");
834
835 Status = ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
836 ScrollScreenBufferRequest->OutputHandle,
837 &Buffer, GENERIC_WRITE, TRUE);
838 if (!NT_SUCCESS(Status)) return Status;
839
840 Status = ConDrvScrollConsoleScreenBuffer(Buffer->Header.Console,
841 Buffer,
842 ScrollScreenBufferRequest->Unicode,
843 &ScrollScreenBufferRequest->ScrollRectangle,
844 ScrollScreenBufferRequest->UseClipRectangle,
845 &ScrollScreenBufferRequest->ClipRectangle,
846 &ScrollScreenBufferRequest->DestinationOrigin,
847 ScrollScreenBufferRequest->Fill);
848
849 ConSrvReleaseScreenBuffer(Buffer, TRUE);
850 return Status;
851 }
852
853 NTSTATUS NTAPI
854 ConDrvSetConsoleWindowInfo(IN PCONSOLE Console,
855 IN PTEXTMODE_SCREEN_BUFFER Buffer,
856 IN BOOLEAN Absolute,
857 IN PSMALL_RECT WindowRect);
858 CSR_API(SrvSetConsoleWindowInfo)
859 {
860 NTSTATUS Status;
861 PCONSOLE_SETWINDOWINFO SetWindowInfoRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.SetWindowInfoRequest;
862 // PCONSOLE_SCREEN_BUFFER Buffer;
863 PTEXTMODE_SCREEN_BUFFER Buffer;
864
865 DPRINT1("SrvSetConsoleWindowInfo(0x%08x, %d, {L%d, T%d, R%d, B%d}) called\n",
866 SetWindowInfoRequest->OutputHandle, SetWindowInfoRequest->Absolute,
867 SetWindowInfoRequest->WindowRect.Left ,
868 SetWindowInfoRequest->WindowRect.Top ,
869 SetWindowInfoRequest->WindowRect.Right,
870 SetWindowInfoRequest->WindowRect.Bottom);
871
872 // ConSrvGetScreenBuffer
873 Status = ConSrvGetTextModeBuffer(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
874 SetWindowInfoRequest->OutputHandle,
875 &Buffer, GENERIC_READ, TRUE);
876 if (!NT_SUCCESS(Status)) return Status;
877
878 Status = ConDrvSetConsoleWindowInfo(Buffer->Header.Console,
879 Buffer,
880 SetWindowInfoRequest->Absolute,
881 &SetWindowInfoRequest->WindowRect);
882
883 ConSrvReleaseScreenBuffer(Buffer, TRUE);
884 return Status;
885 }
886
887 /* EOF */