[KERNEL32][CONSRV]
[reactos.git] / dll / win32 / kernel32 / client / console / readwrite.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS system libraries
4 * FILE: dll/win32/kernel32/client/console/readwrite.c
5 * PURPOSE: Win32 Console Client read-write functions
6 * PROGRAMMERS: Emanuele Aliberti
7 * Marty Dill
8 * Filip Navara (xnavara@volny.cz)
9 * Thomas Weidenmueller (w3seek@reactos.org)
10 * Jeffrey Morlan
11 */
12
13 /* INCLUDES *******************************************************************/
14
15 #include <k32.h>
16
17 #define NDEBUG
18 #include <debug.h>
19
20
21 /* PRIVATE FUNCTIONS **********************************************************/
22
23 /******************
24 * Read functions *
25 ******************/
26
27 static
28 BOOL
29 IntReadConsole(HANDLE hConsoleInput,
30 PVOID lpBuffer,
31 DWORD nNumberOfCharsToRead,
32 LPDWORD lpNumberOfCharsRead,
33 PCONSOLE_READCONSOLE_CONTROL pInputControl,
34 BOOL bUnicode)
35 {
36 CONSOLE_API_MESSAGE ApiMessage;
37 PCONSOLE_READCONSOLE ReadConsoleRequest = &ApiMessage.Data.ReadConsoleRequest;
38 PCSR_CAPTURE_BUFFER CaptureBuffer;
39 ULONG CharSize;
40
41 /* Determine the needed size */
42 CharSize = (bUnicode ? sizeof(WCHAR) : sizeof(CHAR));
43 ReadConsoleRequest->BufferSize = nNumberOfCharsToRead * CharSize;
44
45 /* Allocate a Capture Buffer */
46 CaptureBuffer = CsrAllocateCaptureBuffer(1, ReadConsoleRequest->BufferSize);
47 if (CaptureBuffer == NULL)
48 {
49 DPRINT1("CsrAllocateCaptureBuffer failed!\n");
50 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
51 return FALSE;
52 }
53
54 /* Allocate space in the Buffer */
55 CsrAllocateMessagePointer(CaptureBuffer,
56 ReadConsoleRequest->BufferSize,
57 (PVOID*)&ReadConsoleRequest->Buffer);
58
59 /* Set up the data to send to the Console Server */
60 ReadConsoleRequest->InputHandle = hConsoleInput;
61 ReadConsoleRequest->Unicode = bUnicode;
62 ReadConsoleRequest->NrCharactersToRead = nNumberOfCharsToRead;
63 ReadConsoleRequest->NrCharactersRead = 0;
64 ReadConsoleRequest->CtrlWakeupMask = 0;
65 if (pInputControl && pInputControl->nLength == sizeof(CONSOLE_READCONSOLE_CONTROL))
66 {
67 /*
68 * From MSDN (ReadConsole function), the description
69 * for pInputControl says:
70 * "This parameter requires Unicode input by default.
71 * For ANSI mode, set this parameter to NULL."
72 */
73 ReadConsoleRequest->NrCharactersRead = pInputControl->nInitialChars;
74 RtlCopyMemory(ReadConsoleRequest->Buffer,
75 lpBuffer,
76 pInputControl->nInitialChars * sizeof(WCHAR));
77 ReadConsoleRequest->CtrlWakeupMask = pInputControl->dwCtrlWakeupMask;
78 }
79
80 /* Call the server */
81 CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
82 CaptureBuffer,
83 CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepReadConsole),
84 sizeof(*ReadConsoleRequest));
85
86 /* Check for success */
87 if (NT_SUCCESS(ApiMessage.Status))
88 {
89 RtlCopyMemory(lpBuffer,
90 ReadConsoleRequest->Buffer,
91 ReadConsoleRequest->NrCharactersRead * CharSize);
92
93 if (lpNumberOfCharsRead != NULL)
94 *lpNumberOfCharsRead = ReadConsoleRequest->NrCharactersRead;
95
96 if (pInputControl && pInputControl->nLength == sizeof(CONSOLE_READCONSOLE_CONTROL))
97 pInputControl->dwControlKeyState = ReadConsoleRequest->ControlKeyState;
98 }
99 else
100 {
101 DPRINT1("CSR returned error in ReadConsole\n");
102
103 if (lpNumberOfCharsRead != NULL)
104 *lpNumberOfCharsRead = 0;
105
106 /* Error out */
107 BaseSetLastNTError(ApiMessage.Status);
108 }
109
110 CsrFreeCaptureBuffer(CaptureBuffer);
111
112 /* Return TRUE or FALSE */
113 // return TRUE;
114 return (ReadConsoleRequest->NrCharactersRead > 0);
115 // return NT_SUCCESS(ApiMessage.Status);
116 }
117
118
119 static
120 BOOL
121 IntGetConsoleInput(HANDLE hConsoleInput,
122 PINPUT_RECORD lpBuffer,
123 DWORD nLength,
124 LPDWORD lpNumberOfEventsRead,
125 WORD wFlags,
126 BOOLEAN bUnicode)
127 {
128 CONSOLE_API_MESSAGE ApiMessage;
129 PCONSOLE_GETINPUT GetInputRequest = &ApiMessage.Data.GetInputRequest;
130 PCSR_CAPTURE_BUFFER CaptureBuffer = NULL;
131
132 if (lpBuffer == NULL)
133 {
134 SetLastError(ERROR_INVALID_ACCESS);
135 return FALSE;
136 }
137
138 if (!IsConsoleHandle(hConsoleInput))
139 {
140 SetLastError(ERROR_INVALID_HANDLE);
141
142 if (lpNumberOfEventsRead != NULL)
143 *lpNumberOfEventsRead = 0;
144
145 return FALSE;
146 }
147
148 DPRINT("IntGetConsoleInput: %lx %p\n", nLength, lpNumberOfEventsRead);
149
150 /* Set up the data to send to the Console Server */
151 GetInputRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
152 GetInputRequest->InputHandle = hConsoleInput;
153 GetInputRequest->NumRecords = nLength;
154 GetInputRequest->Flags = wFlags;
155 GetInputRequest->Unicode = bUnicode;
156
157 /*
158 * For optimization purposes, Windows (and hence ReactOS, too, for
159 * compatibility reasons) uses a static buffer if no more than five
160 * input records are read. Otherwise a new buffer is allocated.
161 * This behaviour is also expected in the server-side.
162 */
163 if (nLength <= sizeof(GetInputRequest->RecordStaticBuffer)/sizeof(INPUT_RECORD))
164 {
165 GetInputRequest->RecordBufPtr = GetInputRequest->RecordStaticBuffer;
166 // CaptureBuffer = NULL;
167 }
168 else
169 {
170 ULONG Size = nLength * sizeof(INPUT_RECORD);
171
172 /* Allocate a Capture Buffer */
173 CaptureBuffer = CsrAllocateCaptureBuffer(1, Size);
174 if (CaptureBuffer == NULL)
175 {
176 DPRINT1("CsrAllocateCaptureBuffer failed!\n");
177 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
178 return FALSE;
179 }
180
181 /* Allocate space in the Buffer */
182 CsrAllocateMessagePointer(CaptureBuffer,
183 Size,
184 (PVOID*)&GetInputRequest->RecordBufPtr);
185 }
186
187 /* Call the server */
188 CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
189 CaptureBuffer,
190 CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepGetConsoleInput),
191 sizeof(*GetInputRequest));
192
193 /* Check for success */
194 if (NT_SUCCESS(ApiMessage.Status))
195 {
196 /* Return the number of events read */
197 DPRINT("Events read: %lx\n", GetInputRequest->NumRecords);
198
199 if (lpNumberOfEventsRead != NULL)
200 *lpNumberOfEventsRead = GetInputRequest->NumRecords;
201
202 /* Copy into the buffer */
203 RtlCopyMemory(lpBuffer,
204 GetInputRequest->RecordBufPtr,
205 GetInputRequest->NumRecords * sizeof(INPUT_RECORD));
206 }
207 else
208 {
209 if (lpNumberOfEventsRead != NULL)
210 *lpNumberOfEventsRead = 0;
211
212 /* Error out */
213 BaseSetLastNTError(ApiMessage.Status);
214 }
215
216 /* Release the capture buffer if needed */
217 if (CaptureBuffer) CsrFreeCaptureBuffer(CaptureBuffer);
218
219 /* Return TRUE or FALSE */
220 return NT_SUCCESS(ApiMessage.Status);
221 }
222
223
224 static
225 BOOL
226 IntReadConsoleOutput(HANDLE hConsoleOutput,
227 PCHAR_INFO lpBuffer,
228 COORD dwBufferSize,
229 COORD dwBufferCoord,
230 PSMALL_RECT lpReadRegion,
231 BOOL bUnicode)
232 {
233 CONSOLE_API_MESSAGE ApiMessage;
234 PCONSOLE_READOUTPUT ReadOutputRequest = &ApiMessage.Data.ReadOutputRequest;
235 PCSR_CAPTURE_BUFFER CaptureBuffer;
236 DWORD Size, SizeX, SizeY;
237
238 if (lpBuffer == NULL)
239 {
240 SetLastError(ERROR_INVALID_ACCESS);
241 return FALSE;
242 }
243
244 Size = dwBufferSize.X * dwBufferSize.Y * sizeof(CHAR_INFO);
245
246 DPRINT("IntReadConsoleOutput: %lx %p\n", Size, lpReadRegion);
247
248 /* Allocate a Capture Buffer */
249 CaptureBuffer = CsrAllocateCaptureBuffer(1, Size);
250 if (CaptureBuffer == NULL)
251 {
252 DPRINT1("CsrAllocateCaptureBuffer failed with size 0x%x!\n", Size);
253 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
254 return FALSE;
255 }
256
257 /* Allocate space in the Buffer */
258 CsrAllocateMessagePointer(CaptureBuffer,
259 Size,
260 (PVOID*)&ReadOutputRequest->CharInfo);
261
262 /* Set up the data to send to the Console Server */
263 ReadOutputRequest->OutputHandle = hConsoleOutput;
264 ReadOutputRequest->Unicode = bUnicode;
265 ReadOutputRequest->BufferSize = dwBufferSize;
266 ReadOutputRequest->BufferCoord = dwBufferCoord;
267 ReadOutputRequest->ReadRegion = *lpReadRegion;
268
269 /* Call the server */
270 CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
271 CaptureBuffer,
272 CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepReadConsoleOutput),
273 sizeof(*ReadOutputRequest));
274
275 /* Check for success */
276 if (NT_SUCCESS(ApiMessage.Status))
277 {
278 /* Copy into the buffer */
279 DPRINT("Copying to buffer\n");
280 SizeX = ReadOutputRequest->ReadRegion.Right -
281 ReadOutputRequest->ReadRegion.Left + 1;
282 SizeY = ReadOutputRequest->ReadRegion.Bottom -
283 ReadOutputRequest->ReadRegion.Top + 1;
284 RtlCopyMemory(lpBuffer,
285 ReadOutputRequest->CharInfo,
286 sizeof(CHAR_INFO) * SizeX * SizeY);
287 }
288 else
289 {
290 /* Error out */
291 BaseSetLastNTError(ApiMessage.Status);
292 }
293
294 /* Return the read region */
295 DPRINT("read region: %p\n", ReadOutputRequest->ReadRegion);
296 *lpReadRegion = ReadOutputRequest->ReadRegion;
297
298 /* Release the capture buffer */
299 CsrFreeCaptureBuffer(CaptureBuffer);
300
301 /* Return TRUE or FALSE */
302 return NT_SUCCESS(ApiMessage.Status);
303 }
304
305
306 static
307 BOOL
308 IntReadConsoleOutputCode(HANDLE hConsoleOutput,
309 CODE_TYPE CodeType,
310 PVOID pCode,
311 DWORD nLength,
312 COORD dwReadCoord,
313 LPDWORD lpNumberOfCodesRead)
314 {
315 CONSOLE_API_MESSAGE ApiMessage;
316 PCONSOLE_READOUTPUTCODE ReadOutputCodeRequest = &ApiMessage.Data.ReadOutputCodeRequest;
317 PCSR_CAPTURE_BUFFER CaptureBuffer = NULL;
318 ULONG SizeBytes, CodeSize;
319
320 DPRINT("IntReadConsoleOutputCode\n");
321
322 /* Set up the data to send to the Console Server */
323 ReadOutputCodeRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
324 ReadOutputCodeRequest->OutputHandle = hConsoleOutput;
325 ReadOutputCodeRequest->Coord = dwReadCoord;
326 ReadOutputCodeRequest->NumCodes = nLength;
327
328 /* Determine the needed size */
329 ReadOutputCodeRequest->CodeType = CodeType;
330 switch (CodeType)
331 {
332 case CODE_ASCII:
333 CodeSize = sizeof(CHAR);
334 break;
335
336 case CODE_UNICODE:
337 CodeSize = sizeof(WCHAR);
338 break;
339
340 case CODE_ATTRIBUTE:
341 CodeSize = sizeof(WORD);
342 break;
343
344 default:
345 SetLastError(ERROR_INVALID_PARAMETER);
346 return FALSE;
347 }
348 SizeBytes = nLength * CodeSize;
349
350 /*
351 * For optimization purposes, Windows (and hence ReactOS, too, for
352 * compatibility reasons) uses a static buffer if no more than eighty
353 * bytes are read. Otherwise a new buffer is allocated.
354 * This behaviour is also expected in the server-side.
355 */
356 if (SizeBytes <= sizeof(ReadOutputCodeRequest->CodeStaticBuffer))
357 {
358 ReadOutputCodeRequest->pCode.pCode = ReadOutputCodeRequest->CodeStaticBuffer;
359 // CaptureBuffer = NULL;
360 }
361 else
362 {
363 /* Allocate a Capture Buffer */
364 CaptureBuffer = CsrAllocateCaptureBuffer(1, SizeBytes);
365 if (CaptureBuffer == NULL)
366 {
367 DPRINT1("CsrAllocateCaptureBuffer failed!\n");
368 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
369 return FALSE;
370 }
371
372 /* Allocate space in the Buffer */
373 CsrAllocateMessagePointer(CaptureBuffer,
374 SizeBytes,
375 (PVOID*)&ReadOutputCodeRequest->pCode.pCode);
376 }
377
378 /* Call the server */
379 CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
380 CaptureBuffer,
381 CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepReadConsoleOutputString),
382 sizeof(*ReadOutputCodeRequest));
383
384 /* Check for success */
385 if (NT_SUCCESS(ApiMessage.Status))
386 {
387 DWORD NumCodes = ReadOutputCodeRequest->NumCodes;
388 RtlCopyMemory(pCode,
389 ReadOutputCodeRequest->pCode.pCode,
390 NumCodes * CodeSize);
391
392 if (lpNumberOfCodesRead != NULL)
393 *lpNumberOfCodesRead = NumCodes;
394 }
395 else
396 {
397 if (lpNumberOfCodesRead != NULL)
398 *lpNumberOfCodesRead = 0;
399
400 /* Error out */
401 BaseSetLastNTError(ApiMessage.Status);
402 }
403
404 /* Release the capture buffer if needed */
405 if (CaptureBuffer) CsrFreeCaptureBuffer(CaptureBuffer);
406
407 /* Return TRUE or FALSE */
408 return NT_SUCCESS(ApiMessage.Status);
409 }
410
411
412 /*******************
413 * Write functions *
414 *******************/
415
416 static
417 BOOL
418 IntWriteConsole(HANDLE hConsoleOutput,
419 PVOID lpBuffer,
420 DWORD nNumberOfCharsToWrite,
421 LPDWORD lpNumberOfCharsWritten,
422 LPVOID lpReserved,
423 BOOL bUnicode)
424 {
425 BOOL bRet = TRUE;
426 CONSOLE_API_MESSAGE ApiMessage;
427 PCONSOLE_WRITECONSOLE WriteConsoleRequest = &ApiMessage.Data.WriteConsoleRequest;
428 PCSR_CAPTURE_BUFFER CaptureBuffer;
429 ULONG CharSize;
430
431 /* Determine the needed size */
432 CharSize = (bUnicode ? sizeof(WCHAR) : sizeof(CHAR));
433 WriteConsoleRequest->BufferSize = nNumberOfCharsToWrite * CharSize;
434
435 /* Allocate a Capture Buffer */
436 CaptureBuffer = CsrAllocateCaptureBuffer(1, WriteConsoleRequest->BufferSize);
437 if (CaptureBuffer == NULL)
438 {
439 DPRINT1("CsrAllocateCaptureBuffer failed!\n");
440 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
441 return FALSE;
442 }
443
444 /* Capture the buffer to write */
445 CsrCaptureMessageBuffer(CaptureBuffer,
446 (PVOID)lpBuffer,
447 WriteConsoleRequest->BufferSize,
448 (PVOID*)&WriteConsoleRequest->Buffer);
449
450 /* Start writing */
451 WriteConsoleRequest->NrCharactersToWrite = nNumberOfCharsToWrite;
452 WriteConsoleRequest->OutputHandle = hConsoleOutput;
453 WriteConsoleRequest->Unicode = bUnicode;
454
455 /* Call the server */
456 CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
457 CaptureBuffer,
458 CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepWriteConsole),
459 sizeof(*WriteConsoleRequest));
460
461 /* Check for success */
462 if (NT_SUCCESS(ApiMessage.Status))
463 {
464 if (lpNumberOfCharsWritten != NULL)
465 *lpNumberOfCharsWritten = WriteConsoleRequest->NrCharactersWritten;
466
467 bRet = TRUE;
468 }
469 else
470 {
471 if (lpNumberOfCharsWritten != NULL)
472 *lpNumberOfCharsWritten = 0;
473
474 /* Error out */
475 BaseSetLastNTError(ApiMessage.Status);
476 bRet = FALSE;
477 }
478
479 CsrFreeCaptureBuffer(CaptureBuffer);
480
481 return bRet;
482 }
483
484
485 static
486 BOOL
487 IntWriteConsoleInput(HANDLE hConsoleInput,
488 PINPUT_RECORD lpBuffer,
489 DWORD nLength,
490 LPDWORD lpNumberOfEventsWritten,
491 BOOLEAN bUnicode,
492 BOOLEAN bAppendToEnd)
493 {
494 CONSOLE_API_MESSAGE ApiMessage;
495 PCONSOLE_WRITEINPUT WriteInputRequest = &ApiMessage.Data.WriteInputRequest;
496 PCSR_CAPTURE_BUFFER CaptureBuffer = NULL;
497
498 if (lpBuffer == NULL)
499 {
500 SetLastError(ERROR_INVALID_ACCESS);
501 return FALSE;
502 }
503
504 DPRINT("IntWriteConsoleInput: %lx %p\n", nLength, lpNumberOfEventsWritten);
505
506 /* Set up the data to send to the Console Server */
507 WriteInputRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
508 WriteInputRequest->InputHandle = hConsoleInput;
509 WriteInputRequest->NumRecords = nLength;
510 WriteInputRequest->Unicode = bUnicode;
511 WriteInputRequest->AppendToEnd = bAppendToEnd;
512
513 /*
514 * For optimization purposes, Windows (and hence ReactOS, too, for
515 * compatibility reasons) uses a static buffer if no more than five
516 * input records are written. Otherwise a new buffer is allocated.
517 * This behaviour is also expected in the server-side.
518 */
519 if (nLength <= sizeof(WriteInputRequest->RecordStaticBuffer)/sizeof(INPUT_RECORD))
520 {
521 WriteInputRequest->RecordBufPtr = WriteInputRequest->RecordStaticBuffer;
522 // CaptureBuffer = NULL;
523
524 RtlCopyMemory(WriteInputRequest->RecordBufPtr,
525 lpBuffer,
526 nLength * sizeof(INPUT_RECORD));
527 }
528 else
529 {
530 ULONG Size = nLength * sizeof(INPUT_RECORD);
531
532 /* Allocate a Capture Buffer */
533 CaptureBuffer = CsrAllocateCaptureBuffer(1, Size);
534 if (CaptureBuffer == NULL)
535 {
536 DPRINT1("CsrAllocateCaptureBuffer failed!\n");
537 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
538 return FALSE;
539 }
540
541 /* Capture the user buffer */
542 CsrCaptureMessageBuffer(CaptureBuffer,
543 lpBuffer,
544 Size,
545 (PVOID*)&WriteInputRequest->RecordBufPtr);
546 }
547
548 /* Call the server */
549 CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
550 CaptureBuffer,
551 CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepWriteConsoleInput),
552 sizeof(*WriteInputRequest));
553
554 /* Release the capture buffer if needed */
555 if (CaptureBuffer) CsrFreeCaptureBuffer(CaptureBuffer);
556
557 /* Check for success */
558 if (NT_SUCCESS(ApiMessage.Status))
559 {
560 /* Return the number of events written */
561 DPRINT("Events written: %lx\n", WriteInputRequest->NumRecords);
562
563 if (lpNumberOfEventsWritten != NULL)
564 *lpNumberOfEventsWritten = WriteInputRequest->NumRecords;
565 }
566 else
567 {
568 if (lpNumberOfEventsWritten != NULL)
569 *lpNumberOfEventsWritten = 0;
570
571 /* Error out */
572 BaseSetLastNTError(ApiMessage.Status);
573 }
574
575 /* Return TRUE or FALSE */
576 return NT_SUCCESS(ApiMessage.Status);
577 }
578
579
580 static
581 BOOL
582 IntWriteConsoleOutput(HANDLE hConsoleOutput,
583 CONST CHAR_INFO *lpBuffer,
584 COORD dwBufferSize,
585 COORD dwBufferCoord,
586 PSMALL_RECT lpWriteRegion,
587 BOOL bUnicode)
588 {
589 CONSOLE_API_MESSAGE ApiMessage;
590 PCONSOLE_WRITEOUTPUT WriteOutputRequest = &ApiMessage.Data.WriteOutputRequest;
591 PCSR_CAPTURE_BUFFER CaptureBuffer;
592 ULONG Size;
593
594 if ((lpBuffer == NULL) || (lpWriteRegion == NULL))
595 {
596 SetLastError(ERROR_INVALID_ACCESS);
597 return FALSE;
598 }
599 /*
600 if (lpWriteRegion == NULL)
601 {
602 SetLastError(ERROR_INVALID_PARAMETER);
603 return FALSE;
604 }
605 */
606
607 Size = dwBufferSize.Y * dwBufferSize.X * sizeof(CHAR_INFO);
608
609 DPRINT("IntWriteConsoleOutput: %lx %p\n", Size, lpWriteRegion);
610
611 /* Allocate a Capture Buffer */
612 CaptureBuffer = CsrAllocateCaptureBuffer(1, Size);
613 if (CaptureBuffer == NULL)
614 {
615 DPRINT1("CsrAllocateCaptureBuffer failed!\n");
616 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
617 return FALSE;
618 }
619
620 /* Capture the user buffer */
621 CsrCaptureMessageBuffer(CaptureBuffer,
622 (PVOID)lpBuffer,
623 Size,
624 (PVOID*)&WriteOutputRequest->CharInfo);
625
626 /* Set up the data to send to the Console Server */
627 WriteOutputRequest->OutputHandle = hConsoleOutput;
628 WriteOutputRequest->Unicode = bUnicode;
629 WriteOutputRequest->BufferSize = dwBufferSize;
630 WriteOutputRequest->BufferCoord = dwBufferCoord;
631 WriteOutputRequest->WriteRegion = *lpWriteRegion;
632
633 /* Call the server */
634 CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
635 CaptureBuffer,
636 CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepWriteConsoleOutput),
637 sizeof(*WriteOutputRequest));
638
639 /* Check for success */
640 if (!NT_SUCCESS(ApiMessage.Status))
641 {
642 /* Error out */
643 BaseSetLastNTError(ApiMessage.Status);
644 }
645
646 /* Return the read region */
647 DPRINT("read region: %p\n", WriteOutputRequest->WriteRegion);
648 *lpWriteRegion = WriteOutputRequest->WriteRegion;
649
650 /* Release the capture buffer */
651 CsrFreeCaptureBuffer(CaptureBuffer);
652
653 /* Return TRUE or FALSE */
654 return NT_SUCCESS(ApiMessage.Status);
655 }
656
657
658 static
659 BOOL
660 IntWriteConsoleOutputCode(HANDLE hConsoleOutput,
661 CODE_TYPE CodeType,
662 CONST VOID *pCode,
663 DWORD nLength,
664 COORD dwWriteCoord,
665 LPDWORD lpNumberOfCodesWritten)
666 {
667 CONSOLE_API_MESSAGE ApiMessage;
668 PCONSOLE_WRITEOUTPUTCODE WriteOutputCodeRequest = &ApiMessage.Data.WriteOutputCodeRequest;
669 PCSR_CAPTURE_BUFFER CaptureBuffer = NULL;
670 ULONG SizeBytes, CodeSize;
671
672 if (pCode == NULL)
673 {
674 SetLastError(ERROR_INVALID_ACCESS);
675 return FALSE;
676 }
677
678 DPRINT("IntWriteConsoleOutputCode\n");
679
680 /* Set up the data to send to the Console Server */
681 WriteOutputCodeRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
682 WriteOutputCodeRequest->OutputHandle = hConsoleOutput;
683 WriteOutputCodeRequest->Coord = dwWriteCoord;
684 WriteOutputCodeRequest->NumCodes = nLength;
685
686 /* Determine the needed size */
687 WriteOutputCodeRequest->CodeType = CodeType;
688 switch (CodeType)
689 {
690 case CODE_ASCII:
691 CodeSize = sizeof(CHAR);
692 break;
693
694 case CODE_UNICODE:
695 CodeSize = sizeof(WCHAR);
696 break;
697
698 case CODE_ATTRIBUTE:
699 CodeSize = sizeof(WORD);
700 break;
701
702 default:
703 SetLastError(ERROR_INVALID_PARAMETER);
704 return FALSE;
705 }
706 SizeBytes = nLength * CodeSize;
707
708 /*
709 * For optimization purposes, Windows (and hence ReactOS, too, for
710 * compatibility reasons) uses a static buffer if no more than eighty
711 * bytes are written. Otherwise a new buffer is allocated.
712 * This behaviour is also expected in the server-side.
713 */
714 if (SizeBytes <= sizeof(WriteOutputCodeRequest->CodeStaticBuffer))
715 {
716 WriteOutputCodeRequest->pCode.pCode = WriteOutputCodeRequest->CodeStaticBuffer;
717 // CaptureBuffer = NULL;
718
719 RtlCopyMemory(WriteOutputCodeRequest->pCode.pCode,
720 pCode,
721 SizeBytes);
722 }
723 else
724 {
725 /* Allocate a Capture Buffer */
726 CaptureBuffer = CsrAllocateCaptureBuffer(1, SizeBytes);
727 if (CaptureBuffer == NULL)
728 {
729 DPRINT1("CsrAllocateCaptureBuffer failed!\n");
730 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
731 return FALSE;
732 }
733
734 /* Capture the buffer to write */
735 CsrCaptureMessageBuffer(CaptureBuffer,
736 (PVOID)pCode,
737 SizeBytes,
738 (PVOID*)&WriteOutputCodeRequest->pCode.pCode);
739 }
740
741 /* Call the server */
742 CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
743 CaptureBuffer,
744 CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepWriteConsoleOutputString),
745 sizeof(*WriteOutputCodeRequest));
746
747 /* Release the capture buffer if needed */
748 if (CaptureBuffer) CsrFreeCaptureBuffer(CaptureBuffer);
749
750 /* Check for success */
751 if (NT_SUCCESS(ApiMessage.Status))
752 {
753 if (lpNumberOfCodesWritten != NULL)
754 *lpNumberOfCodesWritten = WriteOutputCodeRequest->NumCodes;
755 }
756 else
757 {
758 if (lpNumberOfCodesWritten != NULL)
759 *lpNumberOfCodesWritten = 0;
760
761 /* Error out */
762 BaseSetLastNTError(ApiMessage.Status);
763 }
764
765 /* Return TRUE or FALSE */
766 return NT_SUCCESS(ApiMessage.Status);
767 }
768
769
770 static
771 BOOL
772 IntFillConsoleOutputCode(HANDLE hConsoleOutput,
773 CODE_TYPE CodeType,
774 PVOID pCode,
775 DWORD nLength,
776 COORD dwWriteCoord,
777 LPDWORD lpNumberOfCodesWritten)
778 {
779 CONSOLE_API_MESSAGE ApiMessage;
780 PCONSOLE_FILLOUTPUTCODE FillOutputRequest = &ApiMessage.Data.FillOutputRequest;
781
782 /* Set up the data to send to the Console Server */
783 FillOutputRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
784 FillOutputRequest->OutputHandle = hConsoleOutput;
785 FillOutputRequest->WriteCoord = dwWriteCoord;
786 FillOutputRequest->NumCodes = nLength;
787
788 FillOutputRequest->CodeType = CodeType;
789 switch (CodeType)
790 {
791 case CODE_ASCII:
792 FillOutputRequest->Code.AsciiChar = *(PCHAR)pCode;
793 break;
794
795 case CODE_UNICODE:
796 FillOutputRequest->Code.UnicodeChar = *(PWCHAR)pCode;
797 break;
798
799 case CODE_ATTRIBUTE:
800 FillOutputRequest->Code.Attribute = *(PWORD)pCode;
801 break;
802
803 default:
804 SetLastError(ERROR_INVALID_PARAMETER);
805 return FALSE;
806 }
807
808 /* Call the server */
809 CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
810 NULL,
811 CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepFillConsoleOutput),
812 sizeof(*FillOutputRequest));
813
814 /* Check for success */
815 if (NT_SUCCESS(ApiMessage.Status))
816 {
817 if (lpNumberOfCodesWritten != NULL)
818 *lpNumberOfCodesWritten = FillOutputRequest->NumCodes;
819 }
820 else
821 {
822 if (lpNumberOfCodesWritten != NULL)
823 *lpNumberOfCodesWritten = 0;
824
825 BaseSetLastNTError(ApiMessage.Status);
826 }
827
828 /* Return TRUE or FALSE */
829 return NT_SUCCESS(ApiMessage.Status);
830 }
831
832
833 /* FUNCTIONS ******************************************************************/
834
835 /******************
836 * Read functions *
837 ******************/
838
839 /*--------------------------------------------------------------
840 * ReadConsoleW
841 *
842 * @implemented
843 */
844 BOOL
845 WINAPI
846 ReadConsoleW(HANDLE hConsoleInput,
847 LPVOID lpBuffer,
848 DWORD nNumberOfCharsToRead,
849 LPDWORD lpNumberOfCharsRead,
850 PCONSOLE_READCONSOLE_CONTROL pInputControl)
851 {
852 return IntReadConsole(hConsoleInput,
853 lpBuffer,
854 nNumberOfCharsToRead,
855 lpNumberOfCharsRead,
856 pInputControl,
857 TRUE);
858 }
859
860
861 /*--------------------------------------------------------------
862 * ReadConsoleA
863 *
864 * @implemented
865 */
866 BOOL
867 WINAPI
868 ReadConsoleA(HANDLE hConsoleInput,
869 LPVOID lpBuffer,
870 DWORD nNumberOfCharsToRead,
871 LPDWORD lpNumberOfCharsRead,
872 PCONSOLE_READCONSOLE_CONTROL pInputControl)
873 {
874 return IntReadConsole(hConsoleInput,
875 lpBuffer,
876 nNumberOfCharsToRead,
877 lpNumberOfCharsRead,
878 NULL,
879 FALSE);
880 }
881
882
883 /*--------------------------------------------------------------
884 * PeekConsoleInputW
885 *
886 * @implemented
887 */
888 BOOL
889 WINAPI
890 PeekConsoleInputW(HANDLE hConsoleInput,
891 PINPUT_RECORD lpBuffer,
892 DWORD nLength,
893 LPDWORD lpNumberOfEventsRead)
894 {
895 return IntGetConsoleInput(hConsoleInput,
896 lpBuffer,
897 nLength,
898 lpNumberOfEventsRead,
899 CONSOLE_READ_KEEPEVENT | CONSOLE_READ_CONTINUE,
900 TRUE);
901 }
902
903
904 /*--------------------------------------------------------------
905 * PeekConsoleInputA
906 *
907 * @implemented
908 */
909 BOOL
910 WINAPI
911 PeekConsoleInputA(HANDLE hConsoleInput,
912 PINPUT_RECORD lpBuffer,
913 DWORD nLength,
914 LPDWORD lpNumberOfEventsRead)
915 {
916 return IntGetConsoleInput(hConsoleInput,
917 lpBuffer,
918 nLength,
919 lpNumberOfEventsRead,
920 CONSOLE_READ_KEEPEVENT | CONSOLE_READ_CONTINUE,
921 FALSE);
922 }
923
924
925 /*--------------------------------------------------------------
926 * ReadConsoleInputW
927 *
928 * @implemented
929 */
930 BOOL
931 WINAPI
932 ReadConsoleInputW(HANDLE hConsoleInput,
933 PINPUT_RECORD lpBuffer,
934 DWORD nLength,
935 LPDWORD lpNumberOfEventsRead)
936 {
937 return IntGetConsoleInput(hConsoleInput,
938 lpBuffer,
939 nLength,
940 lpNumberOfEventsRead,
941 0,
942 TRUE);
943 }
944
945
946 /*--------------------------------------------------------------
947 * ReadConsoleInputA
948 *
949 * @implemented
950 */
951 BOOL
952 WINAPI
953 ReadConsoleInputA(HANDLE hConsoleInput,
954 PINPUT_RECORD lpBuffer,
955 DWORD nLength,
956 LPDWORD lpNumberOfEventsRead)
957 {
958 return IntGetConsoleInput(hConsoleInput,
959 lpBuffer,
960 nLength,
961 lpNumberOfEventsRead,
962 0,
963 FALSE);
964 }
965
966
967 /*--------------------------------------------------------------
968 * ReadConsoleInputExW
969 *
970 * @implemented
971 */
972 BOOL
973 WINAPI
974 ReadConsoleInputExW(HANDLE hConsoleInput,
975 PINPUT_RECORD lpBuffer,
976 DWORD nLength,
977 LPDWORD lpNumberOfEventsRead,
978 WORD wFlags)
979 {
980 return IntGetConsoleInput(hConsoleInput,
981 lpBuffer,
982 nLength,
983 lpNumberOfEventsRead,
984 wFlags,
985 TRUE);
986 }
987
988
989 /*--------------------------------------------------------------
990 * ReadConsoleInputExA
991 *
992 * @implemented
993 */
994 BOOL
995 WINAPI
996 ReadConsoleInputExA(HANDLE hConsoleInput,
997 PINPUT_RECORD lpBuffer,
998 DWORD nLength,
999 LPDWORD lpNumberOfEventsRead,
1000 WORD wFlags)
1001 {
1002 return IntGetConsoleInput(hConsoleInput,
1003 lpBuffer,
1004 nLength,
1005 lpNumberOfEventsRead,
1006 wFlags,
1007 FALSE);
1008 }
1009
1010
1011 /*--------------------------------------------------------------
1012 * ReadConsoleOutputW
1013 *
1014 * @implemented
1015 */
1016 BOOL
1017 WINAPI
1018 ReadConsoleOutputW(HANDLE hConsoleOutput,
1019 PCHAR_INFO lpBuffer,
1020 COORD dwBufferSize,
1021 COORD dwBufferCoord,
1022 PSMALL_RECT lpReadRegion)
1023 {
1024 return IntReadConsoleOutput(hConsoleOutput,
1025 lpBuffer,
1026 dwBufferSize,
1027 dwBufferCoord,
1028 lpReadRegion,
1029 TRUE);
1030 }
1031
1032
1033 /*--------------------------------------------------------------
1034 * ReadConsoleOutputA
1035 *
1036 * @implemented
1037 */
1038 BOOL
1039 WINAPI
1040 ReadConsoleOutputA(HANDLE hConsoleOutput,
1041 PCHAR_INFO lpBuffer,
1042 COORD dwBufferSize,
1043 COORD dwBufferCoord,
1044 PSMALL_RECT lpReadRegion)
1045 {
1046 return IntReadConsoleOutput(hConsoleOutput,
1047 lpBuffer,
1048 dwBufferSize,
1049 dwBufferCoord,
1050 lpReadRegion,
1051 FALSE);
1052 }
1053
1054
1055 /*--------------------------------------------------------------
1056 * ReadConsoleOutputCharacterW
1057 *
1058 * @implemented
1059 */
1060 BOOL
1061 WINAPI
1062 ReadConsoleOutputCharacterW(HANDLE hConsoleOutput,
1063 LPWSTR lpCharacter,
1064 DWORD nLength,
1065 COORD dwReadCoord,
1066 LPDWORD lpNumberOfCharsRead)
1067 {
1068 return IntReadConsoleOutputCode(hConsoleOutput,
1069 CODE_UNICODE,
1070 lpCharacter,
1071 nLength,
1072 dwReadCoord,
1073 lpNumberOfCharsRead);
1074 }
1075
1076
1077 /*--------------------------------------------------------------
1078 * ReadConsoleOutputCharacterA
1079 *
1080 * @implemented
1081 */
1082 BOOL
1083 WINAPI
1084 ReadConsoleOutputCharacterA(HANDLE hConsoleOutput,
1085 LPSTR lpCharacter,
1086 DWORD nLength,
1087 COORD dwReadCoord,
1088 LPDWORD lpNumberOfCharsRead)
1089 {
1090 return IntReadConsoleOutputCode(hConsoleOutput,
1091 CODE_ASCII,
1092 lpCharacter,
1093 nLength,
1094 dwReadCoord,
1095 lpNumberOfCharsRead);
1096 }
1097
1098
1099 /*--------------------------------------------------------------
1100 * ReadConsoleOutputAttribute
1101 *
1102 * @implemented
1103 */
1104 BOOL
1105 WINAPI
1106 ReadConsoleOutputAttribute(HANDLE hConsoleOutput,
1107 LPWORD lpAttribute,
1108 DWORD nLength,
1109 COORD dwReadCoord,
1110 LPDWORD lpNumberOfAttrsRead)
1111 {
1112 return IntReadConsoleOutputCode(hConsoleOutput,
1113 CODE_ATTRIBUTE,
1114 lpAttribute,
1115 nLength,
1116 dwReadCoord,
1117 lpNumberOfAttrsRead);
1118 }
1119
1120
1121 /*******************
1122 * Write functions *
1123 *******************/
1124
1125 /*--------------------------------------------------------------
1126 * WriteConsoleW
1127 *
1128 * @implemented
1129 */
1130 BOOL
1131 WINAPI
1132 WriteConsoleW(HANDLE hConsoleOutput,
1133 CONST VOID *lpBuffer,
1134 DWORD nNumberOfCharsToWrite,
1135 LPDWORD lpNumberOfCharsWritten,
1136 LPVOID lpReserved)
1137 {
1138 return IntWriteConsole(hConsoleOutput,
1139 (PVOID)lpBuffer,
1140 nNumberOfCharsToWrite,
1141 lpNumberOfCharsWritten,
1142 lpReserved,
1143 TRUE);
1144 }
1145
1146
1147 /*--------------------------------------------------------------
1148 * WriteConsoleA
1149 *
1150 * @implemented
1151 */
1152 BOOL
1153 WINAPI
1154 WriteConsoleA(HANDLE hConsoleOutput,
1155 CONST VOID *lpBuffer,
1156 DWORD nNumberOfCharsToWrite,
1157 LPDWORD lpNumberOfCharsWritten,
1158 LPVOID lpReserved)
1159 {
1160 return IntWriteConsole(hConsoleOutput,
1161 (PVOID)lpBuffer,
1162 nNumberOfCharsToWrite,
1163 lpNumberOfCharsWritten,
1164 lpReserved,
1165 FALSE);
1166 }
1167
1168
1169 /*--------------------------------------------------------------
1170 * WriteConsoleInputW
1171 *
1172 * @implemented
1173 */
1174 BOOL
1175 WINAPI
1176 WriteConsoleInputW(HANDLE hConsoleInput,
1177 CONST INPUT_RECORD *lpBuffer,
1178 DWORD nLength,
1179 LPDWORD lpNumberOfEventsWritten)
1180 {
1181 return IntWriteConsoleInput(hConsoleInput,
1182 (PINPUT_RECORD)lpBuffer,
1183 nLength,
1184 lpNumberOfEventsWritten,
1185 TRUE,
1186 TRUE);
1187 }
1188
1189
1190 /*--------------------------------------------------------------
1191 * WriteConsoleInputA
1192 *
1193 * @implemented
1194 */
1195 BOOL
1196 WINAPI
1197 WriteConsoleInputA(HANDLE hConsoleInput,
1198 CONST INPUT_RECORD *lpBuffer,
1199 DWORD nLength,
1200 LPDWORD lpNumberOfEventsWritten)
1201 {
1202 return IntWriteConsoleInput(hConsoleInput,
1203 (PINPUT_RECORD)lpBuffer,
1204 nLength,
1205 lpNumberOfEventsWritten,
1206 FALSE,
1207 TRUE);
1208 }
1209
1210
1211 /*--------------------------------------------------------------
1212 * WriteConsoleInputVDMW
1213 *
1214 * @implemented
1215 */
1216 BOOL
1217 WINAPI
1218 WriteConsoleInputVDMW(HANDLE hConsoleInput,
1219 CONST INPUT_RECORD *lpBuffer,
1220 DWORD nLength,
1221 LPDWORD lpNumberOfEventsWritten)
1222 {
1223 return IntWriteConsoleInput(hConsoleInput,
1224 (PINPUT_RECORD)lpBuffer,
1225 nLength,
1226 lpNumberOfEventsWritten,
1227 TRUE,
1228 FALSE);
1229 }
1230
1231
1232 /*--------------------------------------------------------------
1233 * WriteConsoleInputVDMA
1234 *
1235 * @implemented
1236 */
1237 BOOL
1238 WINAPI
1239 WriteConsoleInputVDMA(HANDLE hConsoleInput,
1240 CONST INPUT_RECORD *lpBuffer,
1241 DWORD nLength,
1242 LPDWORD lpNumberOfEventsWritten)
1243 {
1244 return IntWriteConsoleInput(hConsoleInput,
1245 (PINPUT_RECORD)lpBuffer,
1246 nLength,
1247 lpNumberOfEventsWritten,
1248 FALSE,
1249 FALSE);
1250 }
1251
1252
1253 /*--------------------------------------------------------------
1254 * WriteConsoleOutputW
1255 *
1256 * @implemented
1257 */
1258 BOOL
1259 WINAPI
1260 WriteConsoleOutputW(HANDLE hConsoleOutput,
1261 CONST CHAR_INFO *lpBuffer,
1262 COORD dwBufferSize,
1263 COORD dwBufferCoord,
1264 PSMALL_RECT lpWriteRegion)
1265 {
1266 return IntWriteConsoleOutput(hConsoleOutput,
1267 lpBuffer,
1268 dwBufferSize,
1269 dwBufferCoord,
1270 lpWriteRegion,
1271 TRUE);
1272 }
1273
1274
1275 /*--------------------------------------------------------------
1276 * WriteConsoleOutputA
1277 *
1278 * @implemented
1279 */
1280 BOOL
1281 WINAPI
1282 WriteConsoleOutputA(HANDLE hConsoleOutput,
1283 CONST CHAR_INFO *lpBuffer,
1284 COORD dwBufferSize,
1285 COORD dwBufferCoord,
1286 PSMALL_RECT lpWriteRegion)
1287 {
1288 return IntWriteConsoleOutput(hConsoleOutput,
1289 lpBuffer,
1290 dwBufferSize,
1291 dwBufferCoord,
1292 lpWriteRegion,
1293 FALSE);
1294 }
1295
1296
1297 /*--------------------------------------------------------------
1298 * WriteConsoleOutputCharacterW
1299 *
1300 * @implemented
1301 */
1302 BOOL
1303 WINAPI
1304 WriteConsoleOutputCharacterW(HANDLE hConsoleOutput,
1305 LPCWSTR lpCharacter,
1306 DWORD nLength,
1307 COORD dwWriteCoord,
1308 LPDWORD lpNumberOfCharsWritten)
1309 {
1310 return IntWriteConsoleOutputCode(hConsoleOutput,
1311 CODE_UNICODE,
1312 lpCharacter,
1313 nLength,
1314 dwWriteCoord,
1315 lpNumberOfCharsWritten);
1316 }
1317
1318
1319 /*--------------------------------------------------------------
1320 * WriteConsoleOutputCharacterA
1321 *
1322 * @implemented
1323 */
1324 BOOL
1325 WINAPI
1326 WriteConsoleOutputCharacterA(HANDLE hConsoleOutput,
1327 LPCSTR lpCharacter,
1328 DWORD nLength,
1329 COORD dwWriteCoord,
1330 LPDWORD lpNumberOfCharsWritten)
1331 {
1332 return IntWriteConsoleOutputCode(hConsoleOutput,
1333 CODE_ASCII,
1334 lpCharacter,
1335 nLength,
1336 dwWriteCoord,
1337 lpNumberOfCharsWritten);
1338 }
1339
1340
1341 /*--------------------------------------------------------------
1342 * WriteConsoleOutputAttribute
1343 *
1344 * @implemented
1345 */
1346 BOOL
1347 WINAPI
1348 WriteConsoleOutputAttribute(HANDLE hConsoleOutput,
1349 CONST WORD *lpAttribute,
1350 DWORD nLength,
1351 COORD dwWriteCoord,
1352 LPDWORD lpNumberOfAttrsWritten)
1353 {
1354 return IntWriteConsoleOutputCode(hConsoleOutput,
1355 CODE_ATTRIBUTE,
1356 lpAttribute,
1357 nLength,
1358 dwWriteCoord,
1359 lpNumberOfAttrsWritten);
1360 }
1361
1362
1363 /*--------------------------------------------------------------
1364 * FillConsoleOutputCharacterW
1365 *
1366 * @implemented
1367 */
1368 BOOL
1369 WINAPI
1370 FillConsoleOutputCharacterW(HANDLE hConsoleOutput,
1371 WCHAR cCharacter,
1372 DWORD nLength,
1373 COORD dwWriteCoord,
1374 LPDWORD lpNumberOfCharsWritten)
1375 {
1376 return IntFillConsoleOutputCode(hConsoleOutput,
1377 CODE_UNICODE,
1378 &cCharacter,
1379 nLength,
1380 dwWriteCoord,
1381 lpNumberOfCharsWritten);
1382 }
1383
1384
1385 /*--------------------------------------------------------------
1386 * FillConsoleOutputCharacterA
1387 *
1388 * @implemented
1389 */
1390 BOOL
1391 WINAPI
1392 FillConsoleOutputCharacterA(HANDLE hConsoleOutput,
1393 CHAR cCharacter,
1394 DWORD nLength,
1395 COORD dwWriteCoord,
1396 LPDWORD lpNumberOfCharsWritten)
1397 {
1398 return IntFillConsoleOutputCode(hConsoleOutput,
1399 CODE_ASCII,
1400 &cCharacter,
1401 nLength,
1402 dwWriteCoord,
1403 lpNumberOfCharsWritten);
1404 }
1405
1406
1407 /*--------------------------------------------------------------
1408 * FillConsoleOutputAttribute
1409 *
1410 * @implemented
1411 */
1412 BOOL
1413 WINAPI
1414 FillConsoleOutputAttribute(HANDLE hConsoleOutput,
1415 WORD wAttribute,
1416 DWORD nLength,
1417 COORD dwWriteCoord,
1418 LPDWORD lpNumberOfAttrsWritten)
1419 {
1420 return IntFillConsoleOutputCode(hConsoleOutput,
1421 CODE_ATTRIBUTE,
1422 &wAttribute,
1423 nLength,
1424 dwWriteCoord,
1425 lpNumberOfAttrsWritten);
1426 }
1427
1428 /* EOF */