[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 CODE_ELEMENT Code,
775 DWORD nLength,
776 COORD dwWriteCoord,
777 LPDWORD lpNumberOfCodesWritten)
778 {
779 CONSOLE_API_MESSAGE ApiMessage;
780 PCONSOLE_FILLOUTPUTCODE FillOutputRequest = &ApiMessage.Data.FillOutputRequest;
781
782 if ( (CodeType != CODE_ASCII ) &&
783 (CodeType != CODE_UNICODE ) &&
784 (CodeType != CODE_ATTRIBUTE) )
785 {
786 SetLastError(ERROR_INVALID_PARAMETER);
787 return FALSE;
788 }
789
790 /* Set up the data to send to the Console Server */
791 FillOutputRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
792 FillOutputRequest->OutputHandle = hConsoleOutput;
793 FillOutputRequest->WriteCoord = dwWriteCoord;
794 FillOutputRequest->CodeType = CodeType;
795 FillOutputRequest->Code = Code;
796 FillOutputRequest->NumCodes = nLength;
797
798 /* Call the server */
799 CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
800 NULL,
801 CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepFillConsoleOutput),
802 sizeof(*FillOutputRequest));
803
804 /* Check for success */
805 if (NT_SUCCESS(ApiMessage.Status))
806 {
807 if (lpNumberOfCodesWritten != NULL)
808 *lpNumberOfCodesWritten = FillOutputRequest->NumCodes;
809 }
810 else
811 {
812 if (lpNumberOfCodesWritten != NULL)
813 *lpNumberOfCodesWritten = 0;
814
815 BaseSetLastNTError(ApiMessage.Status);
816 }
817
818 /* Return TRUE or FALSE */
819 return NT_SUCCESS(ApiMessage.Status);
820 }
821
822
823 /* FUNCTIONS ******************************************************************/
824
825 /******************
826 * Read functions *
827 ******************/
828
829 /*--------------------------------------------------------------
830 * ReadConsoleW
831 *
832 * @implemented
833 */
834 BOOL
835 WINAPI
836 ReadConsoleW(HANDLE hConsoleInput,
837 LPVOID lpBuffer,
838 DWORD nNumberOfCharsToRead,
839 LPDWORD lpNumberOfCharsRead,
840 PCONSOLE_READCONSOLE_CONTROL pInputControl)
841 {
842 return IntReadConsole(hConsoleInput,
843 lpBuffer,
844 nNumberOfCharsToRead,
845 lpNumberOfCharsRead,
846 pInputControl,
847 TRUE);
848 }
849
850
851 /*--------------------------------------------------------------
852 * ReadConsoleA
853 *
854 * @implemented
855 */
856 BOOL
857 WINAPI
858 ReadConsoleA(HANDLE hConsoleInput,
859 LPVOID lpBuffer,
860 DWORD nNumberOfCharsToRead,
861 LPDWORD lpNumberOfCharsRead,
862 PCONSOLE_READCONSOLE_CONTROL pInputControl)
863 {
864 return IntReadConsole(hConsoleInput,
865 lpBuffer,
866 nNumberOfCharsToRead,
867 lpNumberOfCharsRead,
868 NULL,
869 FALSE);
870 }
871
872
873 /*--------------------------------------------------------------
874 * PeekConsoleInputW
875 *
876 * @implemented
877 */
878 BOOL
879 WINAPI
880 PeekConsoleInputW(HANDLE hConsoleInput,
881 PINPUT_RECORD lpBuffer,
882 DWORD nLength,
883 LPDWORD lpNumberOfEventsRead)
884 {
885 return IntGetConsoleInput(hConsoleInput,
886 lpBuffer,
887 nLength,
888 lpNumberOfEventsRead,
889 CONSOLE_READ_KEEPEVENT | CONSOLE_READ_CONTINUE,
890 TRUE);
891 }
892
893
894 /*--------------------------------------------------------------
895 * PeekConsoleInputA
896 *
897 * @implemented
898 */
899 BOOL
900 WINAPI
901 PeekConsoleInputA(HANDLE hConsoleInput,
902 PINPUT_RECORD lpBuffer,
903 DWORD nLength,
904 LPDWORD lpNumberOfEventsRead)
905 {
906 return IntGetConsoleInput(hConsoleInput,
907 lpBuffer,
908 nLength,
909 lpNumberOfEventsRead,
910 CONSOLE_READ_KEEPEVENT | CONSOLE_READ_CONTINUE,
911 FALSE);
912 }
913
914
915 /*--------------------------------------------------------------
916 * ReadConsoleInputW
917 *
918 * @implemented
919 */
920 BOOL
921 WINAPI
922 ReadConsoleInputW(HANDLE hConsoleInput,
923 PINPUT_RECORD lpBuffer,
924 DWORD nLength,
925 LPDWORD lpNumberOfEventsRead)
926 {
927 return IntGetConsoleInput(hConsoleInput,
928 lpBuffer,
929 nLength,
930 lpNumberOfEventsRead,
931 0,
932 TRUE);
933 }
934
935
936 /*--------------------------------------------------------------
937 * ReadConsoleInputA
938 *
939 * @implemented
940 */
941 BOOL
942 WINAPI
943 ReadConsoleInputA(HANDLE hConsoleInput,
944 PINPUT_RECORD lpBuffer,
945 DWORD nLength,
946 LPDWORD lpNumberOfEventsRead)
947 {
948 return IntGetConsoleInput(hConsoleInput,
949 lpBuffer,
950 nLength,
951 lpNumberOfEventsRead,
952 0,
953 FALSE);
954 }
955
956
957 /*--------------------------------------------------------------
958 * ReadConsoleInputExW
959 *
960 * @implemented
961 */
962 BOOL
963 WINAPI
964 ReadConsoleInputExW(HANDLE hConsoleInput,
965 PINPUT_RECORD lpBuffer,
966 DWORD nLength,
967 LPDWORD lpNumberOfEventsRead,
968 WORD wFlags)
969 {
970 return IntGetConsoleInput(hConsoleInput,
971 lpBuffer,
972 nLength,
973 lpNumberOfEventsRead,
974 wFlags,
975 TRUE);
976 }
977
978
979 /*--------------------------------------------------------------
980 * ReadConsoleInputExA
981 *
982 * @implemented
983 */
984 BOOL
985 WINAPI
986 ReadConsoleInputExA(HANDLE hConsoleInput,
987 PINPUT_RECORD lpBuffer,
988 DWORD nLength,
989 LPDWORD lpNumberOfEventsRead,
990 WORD wFlags)
991 {
992 return IntGetConsoleInput(hConsoleInput,
993 lpBuffer,
994 nLength,
995 lpNumberOfEventsRead,
996 wFlags,
997 FALSE);
998 }
999
1000
1001 /*--------------------------------------------------------------
1002 * ReadConsoleOutputW
1003 *
1004 * @implemented
1005 */
1006 BOOL
1007 WINAPI
1008 ReadConsoleOutputW(HANDLE hConsoleOutput,
1009 PCHAR_INFO lpBuffer,
1010 COORD dwBufferSize,
1011 COORD dwBufferCoord,
1012 PSMALL_RECT lpReadRegion)
1013 {
1014 return IntReadConsoleOutput(hConsoleOutput,
1015 lpBuffer,
1016 dwBufferSize,
1017 dwBufferCoord,
1018 lpReadRegion,
1019 TRUE);
1020 }
1021
1022
1023 /*--------------------------------------------------------------
1024 * ReadConsoleOutputA
1025 *
1026 * @implemented
1027 */
1028 BOOL
1029 WINAPI
1030 ReadConsoleOutputA(HANDLE hConsoleOutput,
1031 PCHAR_INFO lpBuffer,
1032 COORD dwBufferSize,
1033 COORD dwBufferCoord,
1034 PSMALL_RECT lpReadRegion)
1035 {
1036 return IntReadConsoleOutput(hConsoleOutput,
1037 lpBuffer,
1038 dwBufferSize,
1039 dwBufferCoord,
1040 lpReadRegion,
1041 FALSE);
1042 }
1043
1044
1045 /*--------------------------------------------------------------
1046 * ReadConsoleOutputCharacterW
1047 *
1048 * @implemented
1049 */
1050 BOOL
1051 WINAPI
1052 ReadConsoleOutputCharacterW(HANDLE hConsoleOutput,
1053 LPWSTR lpCharacter,
1054 DWORD nLength,
1055 COORD dwReadCoord,
1056 LPDWORD lpNumberOfCharsRead)
1057 {
1058 return IntReadConsoleOutputCode(hConsoleOutput,
1059 CODE_UNICODE,
1060 lpCharacter,
1061 nLength,
1062 dwReadCoord,
1063 lpNumberOfCharsRead);
1064 }
1065
1066
1067 /*--------------------------------------------------------------
1068 * ReadConsoleOutputCharacterA
1069 *
1070 * @implemented
1071 */
1072 BOOL
1073 WINAPI
1074 ReadConsoleOutputCharacterA(HANDLE hConsoleOutput,
1075 LPSTR lpCharacter,
1076 DWORD nLength,
1077 COORD dwReadCoord,
1078 LPDWORD lpNumberOfCharsRead)
1079 {
1080 return IntReadConsoleOutputCode(hConsoleOutput,
1081 CODE_ASCII,
1082 lpCharacter,
1083 nLength,
1084 dwReadCoord,
1085 lpNumberOfCharsRead);
1086 }
1087
1088
1089 /*--------------------------------------------------------------
1090 * ReadConsoleOutputAttribute
1091 *
1092 * @implemented
1093 */
1094 BOOL
1095 WINAPI
1096 ReadConsoleOutputAttribute(HANDLE hConsoleOutput,
1097 LPWORD lpAttribute,
1098 DWORD nLength,
1099 COORD dwReadCoord,
1100 LPDWORD lpNumberOfAttrsRead)
1101 {
1102 return IntReadConsoleOutputCode(hConsoleOutput,
1103 CODE_ATTRIBUTE,
1104 lpAttribute,
1105 nLength,
1106 dwReadCoord,
1107 lpNumberOfAttrsRead);
1108 }
1109
1110
1111 /*******************
1112 * Write functions *
1113 *******************/
1114
1115 /*--------------------------------------------------------------
1116 * WriteConsoleW
1117 *
1118 * @implemented
1119 */
1120 BOOL
1121 WINAPI
1122 WriteConsoleW(HANDLE hConsoleOutput,
1123 CONST VOID *lpBuffer,
1124 DWORD nNumberOfCharsToWrite,
1125 LPDWORD lpNumberOfCharsWritten,
1126 LPVOID lpReserved)
1127 {
1128 return IntWriteConsole(hConsoleOutput,
1129 (PVOID)lpBuffer,
1130 nNumberOfCharsToWrite,
1131 lpNumberOfCharsWritten,
1132 lpReserved,
1133 TRUE);
1134 }
1135
1136
1137 /*--------------------------------------------------------------
1138 * WriteConsoleA
1139 *
1140 * @implemented
1141 */
1142 BOOL
1143 WINAPI
1144 WriteConsoleA(HANDLE hConsoleOutput,
1145 CONST VOID *lpBuffer,
1146 DWORD nNumberOfCharsToWrite,
1147 LPDWORD lpNumberOfCharsWritten,
1148 LPVOID lpReserved)
1149 {
1150 return IntWriteConsole(hConsoleOutput,
1151 (PVOID)lpBuffer,
1152 nNumberOfCharsToWrite,
1153 lpNumberOfCharsWritten,
1154 lpReserved,
1155 FALSE);
1156 }
1157
1158
1159 /*--------------------------------------------------------------
1160 * WriteConsoleInputW
1161 *
1162 * @implemented
1163 */
1164 BOOL
1165 WINAPI
1166 WriteConsoleInputW(HANDLE hConsoleInput,
1167 CONST INPUT_RECORD *lpBuffer,
1168 DWORD nLength,
1169 LPDWORD lpNumberOfEventsWritten)
1170 {
1171 return IntWriteConsoleInput(hConsoleInput,
1172 (PINPUT_RECORD)lpBuffer,
1173 nLength,
1174 lpNumberOfEventsWritten,
1175 TRUE,
1176 TRUE);
1177 }
1178
1179
1180 /*--------------------------------------------------------------
1181 * WriteConsoleInputA
1182 *
1183 * @implemented
1184 */
1185 BOOL
1186 WINAPI
1187 WriteConsoleInputA(HANDLE hConsoleInput,
1188 CONST INPUT_RECORD *lpBuffer,
1189 DWORD nLength,
1190 LPDWORD lpNumberOfEventsWritten)
1191 {
1192 return IntWriteConsoleInput(hConsoleInput,
1193 (PINPUT_RECORD)lpBuffer,
1194 nLength,
1195 lpNumberOfEventsWritten,
1196 FALSE,
1197 TRUE);
1198 }
1199
1200
1201 /*--------------------------------------------------------------
1202 * WriteConsoleInputVDMW
1203 *
1204 * @implemented
1205 */
1206 BOOL
1207 WINAPI
1208 WriteConsoleInputVDMW(HANDLE hConsoleInput,
1209 CONST INPUT_RECORD *lpBuffer,
1210 DWORD nLength,
1211 LPDWORD lpNumberOfEventsWritten)
1212 {
1213 return IntWriteConsoleInput(hConsoleInput,
1214 (PINPUT_RECORD)lpBuffer,
1215 nLength,
1216 lpNumberOfEventsWritten,
1217 TRUE,
1218 FALSE);
1219 }
1220
1221
1222 /*--------------------------------------------------------------
1223 * WriteConsoleInputVDMA
1224 *
1225 * @implemented
1226 */
1227 BOOL
1228 WINAPI
1229 WriteConsoleInputVDMA(HANDLE hConsoleInput,
1230 CONST INPUT_RECORD *lpBuffer,
1231 DWORD nLength,
1232 LPDWORD lpNumberOfEventsWritten)
1233 {
1234 return IntWriteConsoleInput(hConsoleInput,
1235 (PINPUT_RECORD)lpBuffer,
1236 nLength,
1237 lpNumberOfEventsWritten,
1238 FALSE,
1239 FALSE);
1240 }
1241
1242
1243 /*--------------------------------------------------------------
1244 * WriteConsoleOutputW
1245 *
1246 * @implemented
1247 */
1248 BOOL
1249 WINAPI
1250 WriteConsoleOutputW(HANDLE hConsoleOutput,
1251 CONST CHAR_INFO *lpBuffer,
1252 COORD dwBufferSize,
1253 COORD dwBufferCoord,
1254 PSMALL_RECT lpWriteRegion)
1255 {
1256 return IntWriteConsoleOutput(hConsoleOutput,
1257 lpBuffer,
1258 dwBufferSize,
1259 dwBufferCoord,
1260 lpWriteRegion,
1261 TRUE);
1262 }
1263
1264
1265 /*--------------------------------------------------------------
1266 * WriteConsoleOutputA
1267 *
1268 * @implemented
1269 */
1270 BOOL
1271 WINAPI
1272 WriteConsoleOutputA(HANDLE hConsoleOutput,
1273 CONST CHAR_INFO *lpBuffer,
1274 COORD dwBufferSize,
1275 COORD dwBufferCoord,
1276 PSMALL_RECT lpWriteRegion)
1277 {
1278 return IntWriteConsoleOutput(hConsoleOutput,
1279 lpBuffer,
1280 dwBufferSize,
1281 dwBufferCoord,
1282 lpWriteRegion,
1283 FALSE);
1284 }
1285
1286
1287 /*--------------------------------------------------------------
1288 * WriteConsoleOutputCharacterW
1289 *
1290 * @implemented
1291 */
1292 BOOL
1293 WINAPI
1294 WriteConsoleOutputCharacterW(HANDLE hConsoleOutput,
1295 LPCWSTR lpCharacter,
1296 DWORD nLength,
1297 COORD dwWriteCoord,
1298 LPDWORD lpNumberOfCharsWritten)
1299 {
1300 return IntWriteConsoleOutputCode(hConsoleOutput,
1301 CODE_UNICODE,
1302 lpCharacter,
1303 nLength,
1304 dwWriteCoord,
1305 lpNumberOfCharsWritten);
1306 }
1307
1308
1309 /*--------------------------------------------------------------
1310 * WriteConsoleOutputCharacterA
1311 *
1312 * @implemented
1313 */
1314 BOOL
1315 WINAPI
1316 WriteConsoleOutputCharacterA(HANDLE hConsoleOutput,
1317 LPCSTR lpCharacter,
1318 DWORD nLength,
1319 COORD dwWriteCoord,
1320 LPDWORD lpNumberOfCharsWritten)
1321 {
1322 return IntWriteConsoleOutputCode(hConsoleOutput,
1323 CODE_ASCII,
1324 lpCharacter,
1325 nLength,
1326 dwWriteCoord,
1327 lpNumberOfCharsWritten);
1328 }
1329
1330
1331 /*--------------------------------------------------------------
1332 * WriteConsoleOutputAttribute
1333 *
1334 * @implemented
1335 */
1336 BOOL
1337 WINAPI
1338 WriteConsoleOutputAttribute(HANDLE hConsoleOutput,
1339 CONST WORD *lpAttribute,
1340 DWORD nLength,
1341 COORD dwWriteCoord,
1342 LPDWORD lpNumberOfAttrsWritten)
1343 {
1344 return IntWriteConsoleOutputCode(hConsoleOutput,
1345 CODE_ATTRIBUTE,
1346 lpAttribute,
1347 nLength,
1348 dwWriteCoord,
1349 lpNumberOfAttrsWritten);
1350 }
1351
1352
1353 /*--------------------------------------------------------------
1354 * FillConsoleOutputCharacterW
1355 *
1356 * @implemented
1357 */
1358 BOOL
1359 WINAPI
1360 FillConsoleOutputCharacterW(HANDLE hConsoleOutput,
1361 WCHAR cCharacter,
1362 DWORD nLength,
1363 COORD dwWriteCoord,
1364 LPDWORD lpNumberOfCharsWritten)
1365 {
1366 CODE_ELEMENT Code;
1367 Code.UnicodeChar = cCharacter;
1368 return IntFillConsoleOutputCode(hConsoleOutput,
1369 CODE_UNICODE,
1370 Code,
1371 nLength,
1372 dwWriteCoord,
1373 lpNumberOfCharsWritten);
1374 }
1375
1376
1377 /*--------------------------------------------------------------
1378 * FillConsoleOutputCharacterA
1379 *
1380 * @implemented
1381 */
1382 BOOL
1383 WINAPI
1384 FillConsoleOutputCharacterA(HANDLE hConsoleOutput,
1385 CHAR cCharacter,
1386 DWORD nLength,
1387 COORD dwWriteCoord,
1388 LPDWORD lpNumberOfCharsWritten)
1389 {
1390 CODE_ELEMENT Code;
1391 Code.AsciiChar = cCharacter;
1392 return IntFillConsoleOutputCode(hConsoleOutput,
1393 CODE_ASCII,
1394 Code,
1395 nLength,
1396 dwWriteCoord,
1397 lpNumberOfCharsWritten);
1398 }
1399
1400
1401 /*--------------------------------------------------------------
1402 * FillConsoleOutputAttribute
1403 *
1404 * @implemented
1405 */
1406 BOOL
1407 WINAPI
1408 FillConsoleOutputAttribute(HANDLE hConsoleOutput,
1409 WORD wAttribute,
1410 DWORD nLength,
1411 COORD dwWriteCoord,
1412 LPDWORD lpNumberOfAttrsWritten)
1413 {
1414 CODE_ELEMENT Code;
1415 Code.Attribute = wAttribute;
1416 return IntFillConsoleOutputCode(hConsoleOutput,
1417 CODE_ATTRIBUTE,
1418 Code,
1419 nLength,
1420 dwWriteCoord,
1421 lpNumberOfAttrsWritten);
1422 }
1423
1424 /* EOF */