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