ReactOS  0.4.15-dev-341-g17c5fb8
conoutput.c
Go to the documentation of this file.
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 /*
20  * FIXME: This function MUST be moved from condrv/conoutput.c because only
21  * consrv knows how to manipulate VDM screenbuffers.
22  */
26  IN PCHAR_CELL CharInfo/*Buffer*/,
27  IN COORD CharInfoSize,
28  IN PSMALL_RECT WriteRegion);
33 /* API_NUMBER: ConsolepInvalidateBitMapRect */
34 CON_API(SrvInvalidateBitMapRect,
35  CONSOLE_INVALIDATEDIBITS, InvalidateDIBitsRequest)
36 {
39 
40  Status = ConSrvGetScreenBuffer(ProcessData,
41  InvalidateDIBitsRequest->OutputHandle,
43  if (!NT_SUCCESS(Status))
44  return Status;
45 
46  ASSERT((PCONSOLE)Console == Buffer->Header.Console);
47 
48  /* In text-mode only, draw the VDM buffer if present */
49  if (GetType(Buffer) == TEXTMODE_BUFFER && Console->VDMBuffer)
50  {
52 
54  TextBuffer,
55  Console->VDMBuffer,
56  Console->VDMBufferSize,
57  &InvalidateDIBitsRequest->Region);
58  }
59 
61  Buffer,
62  &InvalidateDIBitsRequest->Region);
63 
65  return Status;
66 }
67 
70  // IN PGRAPHICS_SCREEN_BUFFER Buffer,
72  IN HPALETTE PaletteHandle,
73  IN UINT PaletteUsage);
74 /* API_NUMBER: ConsolepSetPalette */
75 CON_API(SrvSetConsolePalette,
76  CONSOLE_SETPALETTE, SetPaletteRequest)
77 {
79  // PGRAPHICS_SCREEN_BUFFER Buffer;
81 
82  // NOTE: Tests show that this function is used only for graphics screen buffers
83  // and otherwise it returns FALSE + sets last error to invalid handle.
84  // I think it's ridiculous, because if you are in text mode, simulating
85  // a change of VGA palette via DAC registers (done by a call to SetConsolePalette)
86  // cannot be done... So I allow it in ReactOS !
87  /*
88  Status = ConSrvGetGraphicsBuffer(ProcessData,
89  SetPaletteRequest->OutputHandle,
90  &Buffer, GENERIC_WRITE, TRUE);
91  */
92  Status = ConSrvGetScreenBuffer(ProcessData,
93  SetPaletteRequest->OutputHandle,
95  if (!NT_SUCCESS(Status))
96  return Status;
97 
98  ASSERT((PCONSOLE)Console == Buffer->Header.Console);
99 
100  /*
101  * Make the palette handle public, so that it can be
102  * used by other threads calling GDI functions on it.
103  * Indeed, the palette handle comes from a console app
104  * calling ourselves, running in CSRSS.
105  */
107  &SetPaletteRequest->PaletteHandle,
108  sizeof(SetPaletteRequest->PaletteHandle));
109 
111  Buffer,
112  SetPaletteRequest->PaletteHandle,
113  SetPaletteRequest->Usage);
114 
116  return Status;
117 }
118 
122  OUT PCONSOLE_CURSOR_INFO CursorInfo);
123 /* API_NUMBER: ConsolepGetCursorInfo */
124 CON_API(SrvGetConsoleCursorInfo,
125  CONSOLE_GETSETCURSORINFO, CursorInfoRequest)
126 {
129 
130  Status = ConSrvGetTextModeBuffer(ProcessData,
131  CursorInfoRequest->OutputHandle,
133  if (!NT_SUCCESS(Status))
134  return Status;
135 
136  ASSERT((PCONSOLE)Console == Buffer->Header.Console);
137 
139  Buffer,
140  &CursorInfoRequest->Info);
141 
143  return Status;
144 }
145 
149  IN PCONSOLE_CURSOR_INFO CursorInfo);
150 /* API_NUMBER: ConsolepSetCursorInfo */
151 CON_API(SrvSetConsoleCursorInfo,
152  CONSOLE_GETSETCURSORINFO, CursorInfoRequest)
153 {
156 
157  Status = ConSrvGetTextModeBuffer(ProcessData,
158  CursorInfoRequest->OutputHandle,
160  if (!NT_SUCCESS(Status))
161  return Status;
162 
163  ASSERT((PCONSOLE)Console == Buffer->Header.Console);
164 
166  Buffer,
167  &CursorInfoRequest->Info);
168 
170  return Status;
171 }
172 
176  IN PCOORD Position);
177 /* API_NUMBER: ConsolepSetCursorPosition */
178 CON_API(SrvSetConsoleCursorPosition,
179  CONSOLE_SETCURSORPOSITION, SetCursorPositionRequest)
180 {
183 
184  Status = ConSrvGetTextModeBuffer(ProcessData,
185  SetCursorPositionRequest->OutputHandle,
187  if (!NT_SUCCESS(Status))
188  return Status;
189 
190  ASSERT((PCONSOLE)Console == Buffer->Header.Console);
191 
193  Buffer,
194  &SetCursorPositionRequest->Position);
195 
197  return Status;
198 }
199 
200 /* API_NUMBER: ConsolepCreateScreenBuffer */
201 CON_API(SrvCreateConsoleScreenBuffer,
202  CONSOLE_CREATESCREENBUFFER, CreateScreenBufferRequest)
203 {
206  // PCONSOLE_PROCESS_DATA ProcessData = ConsoleGetPerProcessData(Process);
208 
210  TEXTMODE_BUFFER_INFO TextModeInfo = {{80, 25},
211  {80, 25},
214  TRUE,
216  GRAPHICS_BUFFER_INFO GraphicsInfo;
217  GraphicsInfo.Info = CreateScreenBufferRequest->GraphicsBufferInfo; // HACK for MSVC
218 
219  if (CreateScreenBufferRequest->ScreenBufferType == CONSOLE_TEXTMODE_BUFFER)
220  {
221  ScreenBufferInfo = &TextModeInfo;
222 
223  /*
224  * This is Windows behaviour, as described by MSDN and verified manually:
225  *
226  * The newly created screen buffer will copy some properties from the
227  * active screen buffer at the time that this function is called.
228  * The behavior is as follows:
229  * Font - copied from active screen buffer.
230  * Display Window Size - copied from active screen buffer.
231  * Buffer Size - matched to Display Window Size (NOT copied).
232  * Default Attributes (colors) - copied from active screen buffer.
233  * Default Popup Attributes (colors) - copied from active screen buffer.
234  */
235 
236  /* If we have an active screen buffer, use its attributes as the new ones */
237  if (Console->ActiveBuffer && GetType(Console->ActiveBuffer) == TEXTMODE_BUFFER)
238  {
240 
241  TextModeInfo.ScreenAttrib = Buffer->ScreenDefaultAttrib;
242  TextModeInfo.PopupAttrib = Buffer->PopupDefaultAttrib;
243 
244  TextModeInfo.CursorSize = Buffer->CursorInfo.dwSize;
245  TextModeInfo.IsCursorVisible = Buffer->CursorInfo.bVisible;
246 
247  /* Use the current view size */
248  TextModeInfo.ScreenBufferSize = Buffer->ViewSize;
249  TextModeInfo.ViewSize = Buffer->ViewSize;
250  }
251  else
252  {
253  /* Use the current console size */
254  TextModeInfo.ScreenBufferSize = Console->ConsoleSize;
255  TextModeInfo.ViewSize = Console->ConsoleSize;
256  }
257 
258  /* Normalize the screen buffer size if needed */
259  if (TextModeInfo.ScreenBufferSize.X == 0) TextModeInfo.ScreenBufferSize.X = 1;
260  if (TextModeInfo.ScreenBufferSize.Y == 0) TextModeInfo.ScreenBufferSize.Y = 1;
261  }
262  else if (CreateScreenBufferRequest->ScreenBufferType == CONSOLE_GRAPHICS_BUFFER)
263  {
264  /* Get information from the graphics buffer information structure */
265  if (!CsrValidateMessageBuffer(ApiMessage,
266  (PVOID*)&CreateScreenBufferRequest->GraphicsBufferInfo.lpBitMapInfo,
267  CreateScreenBufferRequest->GraphicsBufferInfo.dwBitMapInfoLength,
268  sizeof(BYTE)))
269  {
271  }
272 
273  ScreenBufferInfo = &GraphicsInfo;
274 
275  /* Initialize shared variables */
276  // CreateScreenBufferRequest->GraphicsBufferInfo.hMutex
277  CreateScreenBufferRequest->hMutex = GraphicsInfo.Info.hMutex = INVALID_HANDLE_VALUE;
278  // CreateScreenBufferRequest->GraphicsBufferInfo.lpBitMap
279  CreateScreenBufferRequest->lpBitMap = GraphicsInfo.Info.lpBitMap = NULL;
280 
281  /* A graphics screen buffer is never inheritable */
282  CreateScreenBufferRequest->InheritHandle = FALSE;
283  }
284  else
285  {
286  DPRINT1("Invalid ScreenBuffer type %lu\n", CreateScreenBufferRequest->ScreenBufferType);
288  }
289 
291  (PCONSOLE)Console,
292  Process->ProcessHandle,
293  CreateScreenBufferRequest->ScreenBufferType,
295  if (!NT_SUCCESS(Status))
296  return Status;
297 
298  /* Insert the new handle inside the process handles table */
299  RtlEnterCriticalSection(&ProcessData->HandleTableLock);
300 
301  Status = ConSrvInsertObject(ProcessData,
302  &CreateScreenBufferRequest->OutputHandle,
303  &Buff->Header,
304  CreateScreenBufferRequest->DesiredAccess,
305  CreateScreenBufferRequest->InheritHandle,
306  CreateScreenBufferRequest->ShareMode);
307 
308  RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
309 
310  if (!NT_SUCCESS(Status))
311  {
313  return Status;
314  }
315 
316  if (CreateScreenBufferRequest->ScreenBufferType == CONSOLE_GRAPHICS_BUFFER)
317  {
319  /*
320  * Initialize the graphics buffer information structure
321  * and give it back to the client.
322  */
323  // CreateScreenBufferRequest->GraphicsBufferInfo.hMutex
324  CreateScreenBufferRequest->hMutex = Buffer->ClientMutex;
325  // CreateScreenBufferRequest->GraphicsBufferInfo.lpBitMap
326  CreateScreenBufferRequest->lpBitMap = Buffer->ClientBitMap;
327  }
328 
329  return Status;
330 }
331 
335 /* API_NUMBER: ConsolepSetActiveScreenBuffer */
336 CON_API(SrvSetConsoleActiveScreenBuffer,
337  CONSOLE_SETACTIVESCREENBUFFER, SetScreenBufferRequest)
338 {
341 
342  Status = ConSrvGetScreenBuffer(ProcessData,
343  SetScreenBufferRequest->OutputHandle,
345  if (!NT_SUCCESS(Status))
346  return Status;
347 
348  ASSERT((PCONSOLE)Console == Buffer->Header.Console);
349 
351 
353  return Status;
354 }
355 
356 
357 /* CSR THREADS FOR WriteConsole ***********************************************/
358 
359 static NTSTATUS
362  IN BOOLEAN CreateWaitBlock OPTIONAL);
363 
364 // Wait function CSR_WAIT_FUNCTION
365 static BOOLEAN
366 NTAPI
368  IN PCSR_THREAD WaitThread,
369  IN PCSR_API_MESSAGE WaitApiMessage,
370  IN PVOID WaitContext,
371  IN PVOID WaitArgument1,
372  IN PVOID WaitArgument2,
373  IN ULONG WaitFlags)
374 {
376 
377  DPRINT("WriteConsoleThread - WaitContext = 0x%p, WaitArgument1 = 0x%p, WaitArgument2 = 0x%p, WaitFlags = %lu\n", WaitContext, WaitArgument1, WaitArgument2, WaitFlags);
378 
379  /*
380  * If we are notified of the process termination via a call
381  * to CsrNotifyWaitBlock triggered by CsrDestroyProcess or
382  * CsrDestroyThread, just return.
383  */
384  if (WaitFlags & CsrProcessTerminating)
385  {
387  goto Quit;
388  }
389 
390  Status = DoWriteConsole(WaitApiMessage, WaitThread, FALSE);
391 
392 Quit:
393  if (Status != STATUS_PENDING)
394  {
395  WaitApiMessage->Status = Status;
396  }
397 
398  return (Status == STATUS_PENDING ? FALSE : TRUE);
399 }
400 
404  IN BOOLEAN Unicode,
406  IN ULONG NumCharsToWrite,
407  OUT PULONG NumCharsWritten OPTIONAL);
408 static NTSTATUS
411  IN BOOLEAN CreateWaitBlock OPTIONAL)
412 {
414  PCONSOLE_WRITECONSOLE WriteConsoleRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.WriteConsoleRequest;
416 
417  PVOID Buffer;
418  ULONG NrCharactersWritten = 0;
419  ULONG CharSize = (WriteConsoleRequest->Unicode ? sizeof(WCHAR) : sizeof(CHAR));
420 
422  WriteConsoleRequest->OutputHandle,
424  if (!NT_SUCCESS(Status)) return Status;
425 
426  /*
427  * For optimization purposes, Windows (and hence ReactOS, too, for
428  * compatibility reasons) uses a static buffer if no more than eighty
429  * bytes are written. Otherwise a new buffer is used.
430  * The client-side expects that we know this behaviour.
431  */
432  if (WriteConsoleRequest->UsingStaticBuffer &&
433  WriteConsoleRequest->NumBytes <= sizeof(WriteConsoleRequest->StaticBuffer))
434  {
435  /*
436  * Adjust the internal pointer, because its old value points to
437  * the static buffer in the original ApiMessage structure.
438  */
439  // WriteConsoleRequest->Buffer = WriteConsoleRequest->StaticBuffer;
440  Buffer = WriteConsoleRequest->StaticBuffer;
441  }
442  else
443  {
444  Buffer = WriteConsoleRequest->Buffer;
445  }
446 
447  DPRINT("Calling ConDrvWriteConsole\n");
448  Status = ConDrvWriteConsole(ScreenBuffer->Header.Console,
449  ScreenBuffer,
450  WriteConsoleRequest->Unicode,
451  Buffer,
452  WriteConsoleRequest->NumBytes / CharSize, // NrCharactersToWrite
453  &NrCharactersWritten);
454  DPRINT("ConDrvWriteConsole returned (%d ; Status = 0x%08x)\n",
455  NrCharactersWritten, Status);
456 
457  if (Status == STATUS_PENDING)
458  {
459  if (CreateWaitBlock)
460  {
462 
463  if (!CsrCreateWait(&Console->WriteWaitQueue,
465  ClientThread,
466  ApiMessage,
467  NULL))
468  {
469  /* Fail */
471  goto Quit;
472  }
473  }
474 
475  /* Wait until we un-pause the console */
476  // Status = STATUS_PENDING;
477  }
478  else
479  {
480  /* We read all what we wanted. Set the number of bytes written. */
481  WriteConsoleRequest->NumBytes = NrCharactersWritten * CharSize;
482  }
483 
484 Quit:
486  return Status;
487 }
488 
489 
490 /* TEXT OUTPUT APIS ***********************************************************/
491 
495  IN BOOLEAN Unicode,
496  OUT PCHAR_INFO CharInfo/*Buffer*/,
497  IN OUT PSMALL_RECT ReadRegion);
498 /* API_NUMBER: ConsolepReadConsoleOutput */
499 CON_API(SrvReadConsoleOutput,
500  CONSOLE_READOUTPUT, ReadOutputRequest)
501 {
504  ULONG NumCells;
505  PCHAR_INFO CharInfo;
506 
507  NumCells = ConioRectWidth(&ReadOutputRequest->ReadRegion) *
508  ConioRectHeight(&ReadOutputRequest->ReadRegion);
509 
510  /*
511  * For optimization purposes, Windows (and hence ReactOS, too, for
512  * compatibility reasons) uses a static buffer if no more than one
513  * cell is read. Otherwise a new buffer is used.
514  * The client-side expects that we know this behaviour.
515  */
516  if (NumCells <= 1)
517  {
518  /*
519  * Adjust the internal pointer, because its old value points to
520  * the static buffer in the original ApiMessage structure.
521  */
522  // ReadOutputRequest->CharInfo = &ReadOutputRequest->StaticBuffer;
523  CharInfo = &ReadOutputRequest->StaticBuffer;
524  }
525  else
526  {
527  if (!CsrValidateMessageBuffer(ApiMessage,
528  (PVOID*)&ReadOutputRequest->CharInfo,
529  NumCells,
530  sizeof(CHAR_INFO)))
531  {
533  }
534 
535  CharInfo = ReadOutputRequest->CharInfo;
536  }
537 
538  Status = ConSrvGetTextModeBuffer(ProcessData,
539  ReadOutputRequest->OutputHandle,
541  if (!NT_SUCCESS(Status))
542  return Status;
543 
544  ASSERT((PCONSOLE)Console == Buffer->Header.Console);
545 
547  Buffer,
548  ReadOutputRequest->Unicode,
549  CharInfo,
550  &ReadOutputRequest->ReadRegion);
551 
553  return Status;
554 }
555 
559  IN BOOLEAN Unicode,
560  IN PCHAR_INFO CharInfo/*Buffer*/,
561  IN OUT PSMALL_RECT WriteRegion);
562 /* API_NUMBER: ConsolepWriteConsoleOutput */
563 CON_API(SrvWriteConsoleOutput,
564  CONSOLE_WRITEOUTPUT, WriteOutputRequest)
565 {
568  // PCONSOLE_PROCESS_DATA ProcessData = ConsoleGetPerProcessData(Process);
570  ULONG NumCells;
571  PCHAR_INFO CharInfo;
572 
573  NumCells = ConioRectWidth(&WriteOutputRequest->WriteRegion) *
574  ConioRectHeight(&WriteOutputRequest->WriteRegion);
575 
576  Status = ConSrvGetTextModeBuffer(ProcessData,
577  WriteOutputRequest->OutputHandle,
579  if (!NT_SUCCESS(Status))
580  return Status;
581 
582  ASSERT((PCONSOLE)Console == Buffer->Header.Console);
583 
584  /*
585  * Validate the message buffer if we do not use a process' heap buffer
586  * (CsrAllocateCaptureBuffer succeeded because we haven't allocated
587  * a too large (>= 64 kB, size of the CSR heap) data buffer).
588  */
589  if (!WriteOutputRequest->UseVirtualMemory)
590  {
591  /*
592  * For optimization purposes, Windows (and hence ReactOS, too, for
593  * compatibility reasons) uses a static buffer if no more than one
594  * cell is written. Otherwise a new buffer is used.
595  * The client-side expects that we know this behaviour.
596  */
597  if (NumCells <= 1)
598  {
599  /*
600  * Adjust the internal pointer, because its old value points to
601  * the static buffer in the original ApiMessage structure.
602  */
603  // WriteOutputRequest->CharInfo = &WriteOutputRequest->StaticBuffer;
604  CharInfo = &WriteOutputRequest->StaticBuffer;
605  }
606  else
607  {
608  if (!CsrValidateMessageBuffer(ApiMessage,
609  (PVOID*)&WriteOutputRequest->CharInfo,
610  NumCells,
611  sizeof(CHAR_INFO)))
612  {
614  goto Quit;
615  }
616 
617  CharInfo = WriteOutputRequest->CharInfo;
618  }
619  }
620  else
621  {
622  /*
623  * This was not the case: we use a heap buffer. Retrieve its contents.
624  */
625  ULONG Size = NumCells * sizeof(CHAR_INFO);
626 
628  if (CharInfo == NULL)
629  {
631  goto Quit;
632  }
633 
634  Status = NtReadVirtualMemory(Process->ProcessHandle,
635  WriteOutputRequest->CharInfo,
636  CharInfo,
637  Size,
638  NULL);
639  if (!NT_SUCCESS(Status))
640  {
641  ConsoleFreeHeap(CharInfo);
642  // Status = STATUS_NO_MEMORY;
643  goto Quit;
644  }
645  }
646 
648  Buffer,
649  WriteOutputRequest->Unicode,
650  CharInfo,
651  &WriteOutputRequest->WriteRegion);
652 
653  /* Free the temporary buffer if we used the process' heap buffer */
654  if (WriteOutputRequest->UseVirtualMemory && CharInfo)
655  ConsoleFreeHeap(CharInfo);
656 
657 Quit:
659  return Status;
660 }
661 
662 /* API_NUMBER: ConsolepWriteConsole */
663 CON_API(SrvWriteConsole,
664  CONSOLE_WRITECONSOLE, WriteConsoleRequest)
665 {
667 
668  DPRINT("SrvWriteConsole\n");
669 
670  /*
671  * For optimization purposes, Windows (and hence ReactOS, too, for
672  * compatibility reasons) uses a static buffer if no more than eighty
673  * bytes are written. Otherwise a new buffer is used.
674  * The client-side expects that we know this behaviour.
675  */
676  if (WriteConsoleRequest->UsingStaticBuffer &&
677  WriteConsoleRequest->NumBytes <= sizeof(WriteConsoleRequest->StaticBuffer))
678  {
679  /*
680  * Adjust the internal pointer, because its old value points to
681  * the static buffer in the original ApiMessage structure.
682  */
683  // WriteConsoleRequest->Buffer = WriteConsoleRequest->StaticBuffer;
684  }
685  else
686  {
687  if (!CsrValidateMessageBuffer(ApiMessage,
688  (PVOID)&WriteConsoleRequest->Buffer,
689  WriteConsoleRequest->NumBytes,
690  sizeof(BYTE)))
691  {
693  }
694  }
695 
696  Status = DoWriteConsole(ApiMessage, CsrGetClientThread(), TRUE);
697 
698  if (Status == STATUS_PENDING) *ReplyCode = CsrReplyPending;
699 
700  return Status;
701 }
702 
706  IN CODE_TYPE CodeType,
708  IN ULONG NumCodesToRead,
709  IN PCOORD ReadCoord,
710  // OUT PCOORD EndCoord,
711  OUT PULONG NumCodesRead OPTIONAL);
712 /* API_NUMBER: ConsolepReadConsoleOutputString */
713 CON_API(SrvReadConsoleOutputString,
714  CONSOLE_READOUTPUTCODE, ReadOutputCodeRequest)
715 {
718  ULONG CodeSize;
719  PVOID pCode;
720 
721  switch (ReadOutputCodeRequest->CodeType)
722  {
723  case CODE_ASCII:
724  CodeSize = RTL_FIELD_SIZE(CODE_ELEMENT, AsciiChar);
725  break;
726 
727  case CODE_UNICODE:
728  CodeSize = RTL_FIELD_SIZE(CODE_ELEMENT, UnicodeChar);
729  break;
730 
731  case CODE_ATTRIBUTE:
732  CodeSize = RTL_FIELD_SIZE(CODE_ELEMENT, Attribute);
733  break;
734 
735  default:
737  }
738 
739  /*
740  * For optimization purposes, Windows (and hence ReactOS, too, for
741  * compatibility reasons) uses a static buffer if no more than eighty
742  * bytes are read. Otherwise a new buffer is used.
743  * The client-side expects that we know this behaviour.
744  */
745  if (ReadOutputCodeRequest->NumCodes * CodeSize <= sizeof(ReadOutputCodeRequest->CodeStaticBuffer))
746  {
747  /*
748  * Adjust the internal pointer, because its old value points to
749  * the static buffer in the original ApiMessage structure.
750  */
751  // ReadOutputCodeRequest->pCode = ReadOutputCodeRequest->CodeStaticBuffer;
752  pCode = ReadOutputCodeRequest->CodeStaticBuffer;
753  }
754  else
755  {
756  if (!CsrValidateMessageBuffer(ApiMessage,
757  (PVOID*)&ReadOutputCodeRequest->pCode,
758  ReadOutputCodeRequest->NumCodes,
759  CodeSize))
760  {
762  }
763 
764  pCode = ReadOutputCodeRequest->pCode;
765  }
766 
767  Status = ConSrvGetTextModeBuffer(ProcessData,
768  ReadOutputCodeRequest->OutputHandle,
770  if (!NT_SUCCESS(Status))
771  {
772  ReadOutputCodeRequest->NumCodes = 0;
773  return Status;
774  }
775 
776  ASSERT((PCONSOLE)Console == Buffer->Header.Console);
777 
779  Buffer,
780  ReadOutputCodeRequest->CodeType,
781  pCode,
782  ReadOutputCodeRequest->NumCodes,
783  &ReadOutputCodeRequest->Coord,
784  // &ReadOutputCodeRequest->EndCoord,
785  &ReadOutputCodeRequest->NumCodes);
786 
788  return Status;
789 }
790 
794  IN CODE_TYPE CodeType,
796  IN ULONG NumCodesToWrite,
797  IN PCOORD WriteCoord,
798  // OUT PCOORD EndCoord,
799  OUT PULONG NumCodesWritten OPTIONAL);
800 /* API_NUMBER: ConsolepWriteConsoleOutputString */
801 CON_API(SrvWriteConsoleOutputString,
802  CONSOLE_WRITEOUTPUTCODE, WriteOutputCodeRequest)
803 {
806  ULONG CodeSize;
807  PVOID pCode;
808 
809  switch (WriteOutputCodeRequest->CodeType)
810  {
811  case CODE_ASCII:
812  CodeSize = RTL_FIELD_SIZE(CODE_ELEMENT, AsciiChar);
813  break;
814 
815  case CODE_UNICODE:
816  CodeSize = RTL_FIELD_SIZE(CODE_ELEMENT, UnicodeChar);
817  break;
818 
819  case CODE_ATTRIBUTE:
820  CodeSize = RTL_FIELD_SIZE(CODE_ELEMENT, Attribute);
821  break;
822 
823  default:
825  }
826 
827  /*
828  * For optimization purposes, Windows (and hence ReactOS, too, for
829  * compatibility reasons) uses a static buffer if no more than eighty
830  * bytes are written. Otherwise a new buffer is used.
831  * The client-side expects that we know this behaviour.
832  */
833  if (WriteOutputCodeRequest->NumCodes * CodeSize <= sizeof(WriteOutputCodeRequest->CodeStaticBuffer))
834  {
835  /*
836  * Adjust the internal pointer, because its old value points to
837  * the static buffer in the original ApiMessage structure.
838  */
839  // WriteOutputCodeRequest->pCode = WriteOutputCodeRequest->CodeStaticBuffer;
840  pCode = WriteOutputCodeRequest->CodeStaticBuffer;
841  }
842  else
843  {
844  if (!CsrValidateMessageBuffer(ApiMessage,
845  (PVOID*)&WriteOutputCodeRequest->pCode,
846  WriteOutputCodeRequest->NumCodes,
847  CodeSize))
848  {
850  }
851 
852  pCode = WriteOutputCodeRequest->pCode;
853  }
854 
855  Status = ConSrvGetTextModeBuffer(ProcessData,
856  WriteOutputCodeRequest->OutputHandle,
858  if (!NT_SUCCESS(Status))
859  {
860  WriteOutputCodeRequest->NumCodes = 0;
861  return Status;
862  }
863 
864  ASSERT((PCONSOLE)Console == Buffer->Header.Console);
865 
867  Buffer,
868  WriteOutputCodeRequest->CodeType,
869  pCode,
870  WriteOutputCodeRequest->NumCodes,
871  &WriteOutputCodeRequest->Coord,
872  // &WriteOutputCodeRequest->EndCoord,
873  &WriteOutputCodeRequest->NumCodes);
874 
876  return Status;
877 }
878 
882  IN CODE_TYPE CodeType,
884  IN ULONG NumCodesToWrite,
885  IN PCOORD WriteCoord,
886  OUT PULONG NumCodesWritten OPTIONAL);
887 /* API_NUMBER: ConsolepFillConsoleOutput */
888 CON_API(SrvFillConsoleOutput,
889  CONSOLE_FILLOUTPUTCODE, FillOutputRequest)
890 {
893  CODE_TYPE CodeType = FillOutputRequest->CodeType;
894 
895  if ( (CodeType != CODE_ASCII ) &&
896  (CodeType != CODE_UNICODE ) &&
897  (CodeType != CODE_ATTRIBUTE) )
898  {
900  }
901 
902  Status = ConSrvGetTextModeBuffer(ProcessData,
903  FillOutputRequest->OutputHandle,
905  if (!NT_SUCCESS(Status))
906  {
907  FillOutputRequest->NumCodes = 0;
908  return Status;
909  }
910 
911  ASSERT((PCONSOLE)Console == Buffer->Header.Console);
912 
914  Buffer,
915  CodeType,
916  FillOutputRequest->Code,
917  FillOutputRequest->NumCodes,
918  &FillOutputRequest->WriteCoord,
919  &FillOutputRequest->NumCodes);
920 
922  return Status;
923 }
924 
928  OUT PCOORD ScreenBufferSize,
930  OUT PCOORD ViewOrigin,
932  OUT PCOORD MaximumViewSize,
934 /* API_NUMBER: ConsolepGetScreenBufferInfo */
935 CON_API(SrvGetConsoleScreenBufferInfo,
936  CONSOLE_GETSCREENBUFFERINFO, ScreenBufferInfoRequest)
937 {
940 
941  Status = ConSrvGetTextModeBuffer(ProcessData,
942  ScreenBufferInfoRequest->OutputHandle,
944  if (!NT_SUCCESS(Status))
945  return Status;
946 
947  ASSERT((PCONSOLE)Console == Buffer->Header.Console);
948 
950  Buffer,
951  &ScreenBufferInfoRequest->ScreenBufferSize,
952  &ScreenBufferInfoRequest->CursorPosition,
953  &ScreenBufferInfoRequest->ViewOrigin,
954  &ScreenBufferInfoRequest->ViewSize,
955  &ScreenBufferInfoRequest->MaximumViewSize,
956  &ScreenBufferInfoRequest->Attributes);
957 
959  return Status;
960 }
961 
965  IN WORD Attributes);
966 /* API_NUMBER: ConsolepSetTextAttribute */
967 CON_API(SrvSetConsoleTextAttribute,
968  CONSOLE_SETTEXTATTRIB, SetTextAttribRequest)
969 {
972 
973  Status = ConSrvGetTextModeBuffer(ProcessData,
974  SetTextAttribRequest->OutputHandle,
976  if (!NT_SUCCESS(Status))
977  return Status;
978 
979  ASSERT((PCONSOLE)Console == Buffer->Header.Console);
980 
982  Buffer,
983  SetTextAttribRequest->Attributes);
984 
986  return Status;
987 }
988 
992  IN PCOORD Size);
993 /* API_NUMBER: ConsolepSetScreenBufferSize */
994 CON_API(SrvSetConsoleScreenBufferSize,
995  CONSOLE_SETSCREENBUFFERSIZE, SetScreenBufferSizeRequest)
996 {
999 
1000  Status = ConSrvGetTextModeBuffer(ProcessData,
1001  SetScreenBufferSizeRequest->OutputHandle,
1003  if (!NT_SUCCESS(Status))
1004  return Status;
1005 
1006  ASSERT((PCONSOLE)Console == Buffer->Header.Console);
1007 
1009  Buffer,
1010  &SetScreenBufferSizeRequest->Size);
1011 
1013  return Status;
1014 }
1015 
1019  IN BOOLEAN Unicode,
1020  IN PSMALL_RECT ScrollRectangle,
1021  IN BOOLEAN UseClipRectangle,
1022  IN PSMALL_RECT ClipRectangle OPTIONAL,
1023  IN PCOORD DestinationOrigin,
1024  IN CHAR_INFO FillChar);
1025 /* API_NUMBER: ConsolepScrollScreenBuffer */
1026 CON_API(SrvScrollConsoleScreenBuffer,
1027  CONSOLE_SCROLLSCREENBUFFER, ScrollScreenBufferRequest)
1028 {
1029  NTSTATUS Status;
1031 
1032  Status = ConSrvGetTextModeBuffer(ProcessData,
1033  ScrollScreenBufferRequest->OutputHandle,
1035  if (!NT_SUCCESS(Status))
1036  return Status;
1037 
1038  ASSERT((PCONSOLE)Console == Buffer->Header.Console);
1039 
1041  Buffer,
1042  ScrollScreenBufferRequest->Unicode,
1043  &ScrollScreenBufferRequest->ScrollRectangle,
1044  ScrollScreenBufferRequest->UseClipRectangle,
1045  &ScrollScreenBufferRequest->ClipRectangle,
1046  &ScrollScreenBufferRequest->DestinationOrigin,
1047  ScrollScreenBufferRequest->Fill);
1048 
1050  return Status;
1051 }
1052 
1056  IN BOOLEAN Absolute,
1057  IN PSMALL_RECT WindowRect);
1058 /* API_NUMBER: ConsolepSetWindowInfo */
1059 CON_API(SrvSetConsoleWindowInfo,
1060  CONSOLE_SETWINDOWINFO, SetWindowInfoRequest)
1061 {
1062  NTSTATUS Status;
1063  // PCONSOLE_SCREEN_BUFFER Buffer;
1065 
1066  DPRINT("SrvSetConsoleWindowInfo(0x%08x, %d, {L%d, T%d, R%d, B%d}) called\n",
1067  SetWindowInfoRequest->OutputHandle, SetWindowInfoRequest->Absolute,
1068  SetWindowInfoRequest->WindowRect.Left ,
1069  SetWindowInfoRequest->WindowRect.Top ,
1070  SetWindowInfoRequest->WindowRect.Right,
1071  SetWindowInfoRequest->WindowRect.Bottom);
1072 
1073  // ConSrvGetScreenBuffer
1074  Status = ConSrvGetTextModeBuffer(ProcessData,
1075  SetWindowInfoRequest->OutputHandle,
1076  &Buffer, GENERIC_READ, TRUE);
1077  if (!NT_SUCCESS(Status))
1078  return Status;
1079 
1080  ASSERT((PCONSOLE)Console == Buffer->Header.Console);
1081 
1083  Buffer,
1084  SetWindowInfoRequest->Absolute,
1085  &SetWindowInfoRequest->WindowRect);
1086 
1088  return Status;
1089 }
1090 
1091 /* EOF */
CONSOLE_GRAPHICS_BUFFER_INFO Info
Definition: conio.h:142
#define RTL_FIELD_SIZE(type, field)
Definition: kdb_expr.c:84
#define DEFAULT_SCREEN_ATTRIB
Definition: settings.c:29
#define IN
Definition: typedefs.h:39
NTSTATUS NTAPI ConDrvSetConsoleActiveScreenBuffer(IN PCONSOLE Console, IN PCONSOLE_SCREEN_BUFFER Buffer)
Definition: conoutput.c:177
#define CsrGetClientThread()
Definition: csrsrv.h:77
#define TRUE
Definition: types.h:120
static NTSTATUS DoWriteConsole(IN PCSR_API_MESSAGE ApiMessage, IN PCSR_THREAD ClientThread, IN BOOLEAN CreateWaitBlock OPTIONAL)
Definition: conoutput.c:409
VOID NTAPI ConDrvDeleteScreenBuffer(PCONSOLE_SCREEN_BUFFER Buffer)
Definition: conoutput.c:130
CONSOLE_SCREEN_BUFFER_INFO ScreenBufferInfo
Definition: notevil.c:38
static BOOLEAN NTAPI WriteConsoleThread(IN PLIST_ENTRY WaitList, IN PCSR_THREAD WaitThread, IN PCSR_API_MESSAGE WaitApiMessage, IN PVOID WaitContext, IN PVOID WaitArgument1, IN PVOID WaitArgument2, IN ULONG WaitFlags)
Definition: conoutput.c:367
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define STATUS_THREAD_IS_TERMINATING
Definition: ntstatus.h:297
static COORD Position
Definition: mouse.c:34
char CHAR
Definition: xmlstorage.h:175
struct _CONSOLE_API_MESSAGE * PCONSOLE_API_MESSAGE
LONG NTSTATUS
Definition: precomp.h:26
BOOLEAN NTAPI CsrValidateMessageBuffer(IN PCSR_API_MESSAGE ApiMessage, IN PVOID *Buffer, IN ULONG ElementCount, IN ULONG ElementSize)
Definition: api.c:1426
#define ConsoleAllocHeap(Flags, Size)
Definition: heap.h:14
NTSYSAPI NTSTATUS NTAPI RtlEnterCriticalSection(_In_ PRTL_CRITICAL_SECTION CriticalSection)
#define INVALID_HANDLE_VALUE
Definition: compat.h:400
BOOLEAN IsCursorVisible
Definition: conio.h:121
NTSTATUS ConDrvCreateScreenBuffer(OUT PCONSOLE_SCREEN_BUFFER *Buffer, IN PCONSOLE Console, IN HANDLE ProcessHandle OPTIONAL, IN ULONG BufferType, IN PVOID ScreenBufferInfo)
Definition: conoutput.c:85
static HPALETTE PaletteHandle
Definition: svga.c:215
NTSTATUS NTAPI ConDrvGetConsoleCursorInfo(IN PCONSOLE Console, IN PTEXTMODE_SCREEN_BUFFER Buffer, OUT PCONSOLE_CURSOR_INFO CursorInfo)
Definition: conoutput.c:270
CONSOLE_IO_OBJECT Header
Definition: conio.h:58
NTSTATUS NTAPI ConDrvWriteConsoleOutputVDM(IN PCONSOLE Console, IN PTEXTMODE_SCREEN_BUFFER Buffer, IN PCHAR_CELL CharInfo, IN COORD CharInfoSize, IN PSMALL_RECT WriteRegion)
Definition: text.c:708
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
NTSYSAPI NTSTATUS NTAPI RtlLeaveCriticalSection(_In_ PRTL_CRITICAL_SECTION CriticalSection)
#define ConioRectWidth(Rect)
Definition: readwrite.c:24
#define GENERIC_WRITE
Definition: nt_native.h:90
NTSTATUS APIENTRY NtUserConsoleControl(IN CONSOLECONTROL ConsoleCtrl, IN PVOID ConsoleCtrlInfo, IN ULONG ConsoleCtrlInfoLength)
Definition: console.c:14
unsigned char BOOLEAN
struct _CHAR_INFO CHAR_INFO
smooth NULL
Definition: ftsmooth.c:416
NTSTATUS NTAPI ConDrvWriteConsoleOutputString(IN PCONSOLE Console, IN PTEXTMODE_SCREEN_BUFFER Buffer, IN CODE_TYPE CodeType, IN PVOID StringBuffer, IN ULONG NumCodesToWrite, IN PCOORD WriteCoord, OUT PULONG NumCodesWritten OPTIONAL)
Definition: text.c:1161
#define ConioRectHeight(Rect)
Definition: readwrite.c:22
UINT CALLBACK ClientThread(_Inout_ PVOID Parameter)
void DPRINT(...)
Definition: polytest.cpp:61
Definition: bufpool.h:45
NTSTATUS NTAPI ConDrvWriteConsoleOutput(IN PCONSOLE Console, IN PTEXTMODE_SCREEN_BUFFER Buffer, IN BOOLEAN Unicode, IN PCHAR_INFO CharInfo, IN OUT PSMALL_RECT WriteRegion)
Definition: text.c:638
ULONG X
Definition: bl.h:1340
WORD * PWORD
Definition: pedump.c:67
#define Code
Definition: deflate.h:80
NTSTATUS NTAPI ConDrvSetConsolePalette(IN PCONSOLE Console, IN PCONSOLE_SCREEN_BUFFER Buffer, IN HPALETTE PaletteHandle, IN UINT PaletteUsage)
Definition: conoutput.c:226
#define ConSrvGetTextModeBuffer(ProcessData, Handle, Ptr, Access, LockConsole)
Definition: conoutput.h:12
if(!(yy_init))
Definition: macro.lex.yy.c:714
__wchar_t WCHAR
Definition: xmlstorage.h:180
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define STATUS_PENDING
Definition: ntstatus.h:82
NTSTATUS NTAPI ConDrvSetConsoleTextAttribute(IN PCONSOLE Console, IN PTEXTMODE_SCREEN_BUFFER Buffer, IN WORD Attributes)
Definition: text.c:1420
#define ConsoleGetPerProcessData(Process)
Definition: consrv.h:37
unsigned short WORD
Definition: ntddk_ex.h:93
#define CSR_DEFAULT_CURSOR_SIZE
Definition: settings.c:26
NTSTATUS NTAPI ConDrvSetConsoleCursorPosition(IN PCONSOLE Console, IN PTEXTMODE_SCREEN_BUFFER Buffer, IN PCOORD Position)
Definition: conoutput.c:318
#define ConSrvReleaseScreenBuffer(Buff, IsConsoleLocked)
Definition: conoutput.h:33
NTSTATUS NTAPI NtReadVirtualMemory(IN HANDLE ProcessHandle, IN PVOID BaseAddress, OUT PVOID Buffer, IN SIZE_T NumberOfBytesToRead, OUT PSIZE_T NumberOfBytesRead OPTIONAL)
Definition: virtual.c:2691
#define ConSrvGetScreenBuffer(ProcessData, Handle, Ptr, Access, LockConsole)
Definition: conoutput.h:26
struct _GRAPHICS_SCREEN_BUFFER * PGRAPHICS_SCREEN_BUFFER
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
INT GetType(BOOL bLocal, LPOSVERSIONINFOEX osvi, LPSERVER_INFO_102 pBuf102)
Definition: gettype.c:129
NTSTATUS NTAPI ConDrvSetConsoleCursorInfo(IN PCONSOLE Console, IN PTEXTMODE_SCREEN_BUFFER Buffer, IN PCONSOLE_CURSOR_INFO CursorInfo)
Definition: conoutput.c:288
#define GENERIC_READ
Definition: compat.h:124
Definition: typedefs.h:118
struct _CONSRV_CONSOLE * PCONSRV_CONSOLE
IN PVOID IN PVOID IN USHORT IN USHORT Size
Definition: pci.h:361
Definition: bl.h:1338
unsigned char BYTE
Definition: xxhash.c:193
USHORT PopupAttrib
Definition: conio.h:119
Status
Definition: gdiplustypes.h:24
BOOLEAN UsingStaticBuffer
Definition: conmsg.h:246
#define DEFAULT_POPUP_ATTRIB
Definition: settings.c:30
_Must_inspect_result_ _In_ USHORT _In_ PHIDP_PREPARSED_DATA _Out_writes_to_ LengthAttributes PHIDP_EXTENDED_ATTRIBUTES Attributes
Definition: hidpi.h:348
#define CONSOLE_TEXTMODE_BUFFER
Definition: wincon.h:62
#define STATUS_NO_MEMORY
Definition: ntstatus.h:246
#define CONSOLE_GRAPHICS_BUFFER
Definition: wincon.h:63
unsigned int * PULONG
Definition: retypes.h:1
unsigned int UINT
Definition: ndis.h:50
#define HEAP_ZERO_MEMORY
Definition: compat.h:123
NTSTATUS NTAPI ConDrvInvalidateBitMapRect(IN PCONSOLE Console, IN PCONSOLE_SCREEN_BUFFER Buffer, IN PSMALL_RECT Region)
Definition: conoutput.c:209
NTSTATUS NTAPI ConDrvSetConsoleWindowInfo(IN PCONSOLE Console, IN PTEXTMODE_SCREEN_BUFFER Buffer, IN BOOLEAN Absolute, IN PSMALL_RECT WindowRect)
Definition: text.c:1579
CConsole Console
#define DPRINT1
Definition: precomp.h:8
#define ConsoleFreeHeap(HeapBase)
Definition: heap.h:15
_Must_inspect_result_ _In_ PLARGE_INTEGER _In_ PLARGE_INTEGER _In_ ULONG _In_ PFILE_OBJECT _In_ PVOID Process
Definition: fsrtlfuncs.h:219
char TextBuffer[BUFFERLEN]
Definition: combotst.c:45
HANDLE ScreenBuffer
Definition: notevil.c:37
#define OUT
Definition: typedefs.h:40
_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
NTSTATUS NTAPI ConDrvScrollConsoleScreenBuffer(IN PCONSOLE Console, IN PTEXTMODE_SCREEN_BUFFER Buffer, IN BOOLEAN Unicode, IN PSMALL_RECT ScrollRectangle, IN BOOLEAN UseClipRectangle, IN PSMALL_RECT ClipRectangle OPTIONAL, IN PCOORD DestinationOrigin, IN CHAR_INFO FillChar)
Definition: text.c:1454
CHAR StaticBuffer[80]
Definition: conmsg.h:239
unsigned int ULONG
Definition: retypes.h:1
NTSTATUS NTAPI ConDrvGetConsoleScreenBufferInfo(IN PCONSOLE Console, IN PTEXTMODE_SCREEN_BUFFER Buffer, OUT PCOORD ScreenBufferSize, OUT PCOORD CursorPosition, OUT PCOORD ViewOrigin, OUT PCOORD ViewSize, OUT PCOORD MaximumViewSize, OUT PWORD Attributes)
Definition: text.c:1380
NTSTATUS NTAPI ConDrvSetConsoleScreenBufferSize(IN PCONSOLE Console, IN PTEXTMODE_SCREEN_BUFFER Buffer, IN PCOORD Size)
Definition: text.c:1435
NTSTATUS ConSrvInsertObject(IN PCONSOLE_PROCESS_DATA ProcessData, OUT PHANDLE Handle, IN PCONSOLE_IO_OBJECT Object, IN ULONG Access, IN BOOLEAN Inheritable, IN ULONG ShareMode)
Definition: handle.c:227
NTSTATUS NTAPI ConDrvReadConsoleOutput(IN PCONSOLE Console, IN PTEXTMODE_SCREEN_BUFFER Buffer, IN BOOLEAN Unicode, OUT PCHAR_INFO CharInfo, IN OUT PSMALL_RECT ReadRegion)
Definition: text.c:569
NTSTATUS NTAPI ConDrvReadConsoleOutputString(IN PCONSOLE Console, IN PTEXTMODE_SCREEN_BUFFER Buffer, IN CODE_TYPE CodeType, OUT PVOID StringBuffer, IN ULONG NumCodesToRead, IN PCOORD ReadCoord, OUT PULONG NumCodesRead OPTIONAL)
Definition: text.c:942
BOOLEAN NTAPI CsrCreateWait(IN PLIST_ENTRY WaitList, IN CSR_WAIT_FUNCTION WaitFunction, IN PCSR_THREAD CsrWaitThread, IN OUT PCSR_API_MESSAGE WaitApiMessage, IN PVOID WaitContext)
Definition: wait.c:209
IN BOOLEAN OUT PSTR Buffer
Definition: progress.h:34
ULONG Y
Definition: bl.h:1341
static USHORT CursorPosition
Definition: pc98cons.c:20
WCHAR StringBuffer[156]
Definition: ldrinit.c:41
struct _TEXTMODE_SCREEN_BUFFER * PTEXTMODE_SCREEN_BUFFER
COORD ScreenBufferSize
Definition: conio.h:116
CON_API(SrvInvalidateBitMapRect, CONSOLE_INVALIDATEDIBITS, InvalidateDIBitsRequest)
Definition: conoutput.c:34
enum _CODE_TYPE CODE_TYPE
NTSTATUS NTAPI ConDrvWriteConsole(IN PCONSOLE Console, IN PTEXTMODE_SCREEN_BUFFER ScreenBuffer, IN BOOLEAN Unicode, IN PVOID StringBuffer, IN ULONG NumCharsToWrite, OUT PULONG NumCharsWritten OPTIONAL)
Definition: text.c:763
NTSTATUS NTAPI ConDrvFillConsoleOutput(IN PCONSOLE Console, IN PTEXTMODE_SCREEN_BUFFER Buffer, IN CODE_TYPE CodeType, IN CODE_ELEMENT Code, IN ULONG NumCodesToWrite, IN PCOORD WriteCoord, OUT PULONG NumCodesWritten OPTIONAL)
Definition: text.c:1251
USHORT ScreenAttrib
Definition: conio.h:118
PULONG MinorVersion OPTIONAL
Definition: CrossNt.h:68