[KERNEL32] lpNumberOfCharsWritten is optional for WriteConsole (#1079)
[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 /* See consrv/include/rect.h */
22 #define ConioRectHeight(Rect) \
23 (((Rect)->Top > (Rect)->Bottom) ? 0 : ((Rect)->Bottom - (Rect)->Top + 1))
24 #define ConioRectWidth(Rect) \
25 (((Rect)->Left > (Rect)->Right) ? 0 : ((Rect)->Right - (Rect)->Left + 1))
26
27
28 /* PRIVATE FUNCTIONS **********************************************************/
29
30 /******************
31 * Read functions *
32 ******************/
33
34 static
35 BOOL
36 IntReadConsole(IN HANDLE hConsoleInput,
37 OUT PVOID lpBuffer,
38 IN DWORD nNumberOfCharsToRead,
39 OUT LPDWORD lpNumberOfCharsRead,
40 IN PCONSOLE_READCONSOLE_CONTROL pInputControl OPTIONAL,
41 IN BOOLEAN bUnicode)
42 {
43 BOOL Success;
44 CONSOLE_API_MESSAGE ApiMessage;
45 PCONSOLE_READCONSOLE ReadConsoleRequest = &ApiMessage.Data.ReadConsoleRequest;
46 PCSR_CAPTURE_BUFFER CaptureBuffer = NULL;
47 ULONG CharSize, SizeBytes;
48
49 DPRINT("IntReadConsole\n");
50
51 /* Set up the data to send to the Console Server */
52 ReadConsoleRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
53 ReadConsoleRequest->InputHandle = hConsoleInput;
54 ReadConsoleRequest->Unicode = bUnicode;
55
56 /*
57 * Retrieve the (current) Input EXE name string and length,
58 * not NULL-terminated (always in UNICODE format).
59 */
60 ReadConsoleRequest->ExeLength =
61 GetCurrentExeName((PWCHAR)ReadConsoleRequest->StaticBuffer,
62 sizeof(ReadConsoleRequest->StaticBuffer));
63
64 /*** For DEBUGGING purposes ***/
65 {
66 UNICODE_STRING ExeName;
67 ExeName.Length = ExeName.MaximumLength = ReadConsoleRequest->ExeLength;
68 ExeName.Buffer = (PWCHAR)ReadConsoleRequest->StaticBuffer;
69 DPRINT("IntReadConsole(ExeName = %wZ)\n", &ExeName);
70 }
71 /******************************/
72
73 /* Determine the needed size */
74 CharSize = (bUnicode ? sizeof(WCHAR) : sizeof(CHAR));
75 SizeBytes = nNumberOfCharsToRead * CharSize;
76
77 ReadConsoleRequest->CaptureBufferSize =
78 ReadConsoleRequest->NumBytes = SizeBytes;
79
80 /*
81 * For optimization purposes, Windows (and hence ReactOS, too, for
82 * compatibility reasons) uses a static buffer if no more than eighty
83 * bytes are read. Otherwise a new buffer is allocated.
84 * This behaviour is also expected in the server-side.
85 */
86 if (SizeBytes <= sizeof(ReadConsoleRequest->StaticBuffer))
87 {
88 ReadConsoleRequest->Buffer = ReadConsoleRequest->StaticBuffer;
89 // CaptureBuffer = NULL;
90 }
91 else
92 {
93 /* Allocate a Capture Buffer */
94 CaptureBuffer = CsrAllocateCaptureBuffer(1, SizeBytes);
95 if (CaptureBuffer == NULL)
96 {
97 DPRINT1("CsrAllocateCaptureBuffer failed!\n");
98 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
99 return FALSE;
100 }
101
102 /* Allocate space in the Buffer */
103 CsrAllocateMessagePointer(CaptureBuffer,
104 SizeBytes,
105 (PVOID*)&ReadConsoleRequest->Buffer);
106 }
107
108 ReadConsoleRequest->InitialNumBytes = 0;
109 ReadConsoleRequest->CtrlWakeupMask = 0;
110 ReadConsoleRequest->ControlKeyState = 0;
111
112 /*
113 * From MSDN (ReadConsole function), the description
114 * for pInputControl says:
115 * "This parameter requires Unicode input by default.
116 * For ANSI mode, set this parameter to NULL."
117 */
118 _SEH2_TRY
119 {
120 if (bUnicode && pInputControl &&
121 pInputControl->nLength == sizeof(CONSOLE_READCONSOLE_CONTROL))
122 {
123 /* Sanity check */
124 if (pInputControl->nInitialChars <= nNumberOfCharsToRead)
125 {
126 ReadConsoleRequest->InitialNumBytes =
127 pInputControl->nInitialChars * sizeof(WCHAR); // CharSize
128
129 if (pInputControl->nInitialChars != 0)
130 {
131 /*
132 * It is possible here to overwrite the static buffer, in case
133 * the number of bytes to read was smaller than the static buffer.
134 * In this case, this means we are continuing a pending read,
135 * and we do not need in fact the executable name that was
136 * stored in the static buffer because it was first grabbed when
137 * we started the first read.
138 */
139 RtlCopyMemory(ReadConsoleRequest->Buffer,
140 lpBuffer,
141 ReadConsoleRequest->InitialNumBytes);
142 }
143
144 ReadConsoleRequest->CtrlWakeupMask = pInputControl->dwCtrlWakeupMask;
145 }
146 else
147 {
148 // Status = STATUS_INVALID_PARAMETER;
149 }
150 }
151 else
152 {
153 /* We are in a situation where pInputControl has no meaning */
154 pInputControl = NULL;
155 }
156 }
157 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
158 {
159 // HACK
160 if (CaptureBuffer) CsrFreeCaptureBuffer(CaptureBuffer);
161 SetLastError(ERROR_INVALID_ACCESS);
162 _SEH2_YIELD(return FALSE);
163 }
164 _SEH2_END;
165
166 /* FIXME: Check for sanity */
167 /*
168 if (!NT_SUCCESS(Status) && pInputControl)
169 {
170 // Free CaptureBuffer if needed
171 // Set last error to last status
172 // Return FALSE
173 }
174 */
175
176 /* Call the server */
177 CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
178 CaptureBuffer,
179 CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepReadConsole),
180 sizeof(*ReadConsoleRequest));
181
182 /* Check for success */
183 Success = NT_SUCCESS(ApiMessage.Status);
184
185 /* Retrieve the results */
186 if (Success)
187 {
188 _SEH2_TRY
189 {
190 *lpNumberOfCharsRead = ReadConsoleRequest->NumBytes / CharSize;
191
192 if (bUnicode && pInputControl)
193 pInputControl->dwControlKeyState = ReadConsoleRequest->ControlKeyState;
194
195 RtlCopyMemory(lpBuffer,
196 ReadConsoleRequest->Buffer,
197 ReadConsoleRequest->NumBytes);
198 }
199 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
200 {
201 SetLastError(ERROR_INVALID_ACCESS);
202 Success = FALSE;
203 }
204 _SEH2_END;
205 }
206 else
207 {
208 BaseSetLastNTError(ApiMessage.Status);
209 }
210
211 /* Release the capture buffer if needed */
212 if (CaptureBuffer) CsrFreeCaptureBuffer(CaptureBuffer);
213
214 if (Success)
215 {
216 /* Yield execution to another thread if Ctrl-C or Ctrl-Break happened */
217 if (ApiMessage.Status == STATUS_ALERTED /* || ApiMessage.Status == STATUS_CANCELLED */)
218 {
219 NtYieldExecution();
220 SetLastError(ERROR_OPERATION_ABORTED); // STATUS_CANCELLED
221 }
222 }
223
224 /* Return success status */
225 return Success;
226 }
227
228
229 static
230 BOOL
231 IntGetConsoleInput(IN HANDLE hConsoleInput,
232 OUT PINPUT_RECORD lpBuffer,
233 IN DWORD nLength,
234 OUT LPDWORD lpNumberOfEventsRead,
235 IN WORD wFlags,
236 IN BOOLEAN bUnicode)
237 {
238 BOOL Success;
239 CONSOLE_API_MESSAGE ApiMessage;
240 PCONSOLE_GETINPUT GetInputRequest = &ApiMessage.Data.GetInputRequest;
241 PCSR_CAPTURE_BUFFER CaptureBuffer = NULL;
242
243 if (!IsConsoleHandle(hConsoleInput))
244 {
245 _SEH2_TRY
246 {
247 *lpNumberOfEventsRead = 0;
248 SetLastError(ERROR_INVALID_HANDLE);
249 }
250 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
251 {
252 SetLastError(ERROR_INVALID_ACCESS);
253 }
254 _SEH2_END;
255
256 return FALSE;
257 }
258
259 DPRINT("IntGetConsoleInput: %lx %p\n", nLength, lpNumberOfEventsRead);
260
261 /* Set up the data to send to the Console Server */
262 GetInputRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
263 GetInputRequest->InputHandle = hConsoleInput;
264 GetInputRequest->NumRecords = nLength;
265 GetInputRequest->Flags = wFlags;
266 GetInputRequest->Unicode = bUnicode;
267
268 /*
269 * For optimization purposes, Windows (and hence ReactOS, too, for
270 * compatibility reasons) uses a static buffer if no more than five
271 * input records are read. Otherwise a new buffer is allocated.
272 * This behaviour is also expected in the server-side.
273 */
274 if (nLength <= sizeof(GetInputRequest->RecordStaticBuffer)/sizeof(INPUT_RECORD))
275 {
276 GetInputRequest->RecordBufPtr = GetInputRequest->RecordStaticBuffer;
277 // CaptureBuffer = NULL;
278 }
279 else
280 {
281 ULONG Size = nLength * sizeof(INPUT_RECORD);
282
283 /* Allocate a Capture Buffer */
284 CaptureBuffer = CsrAllocateCaptureBuffer(1, Size);
285 if (CaptureBuffer == NULL)
286 {
287 DPRINT1("CsrAllocateCaptureBuffer failed!\n");
288 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
289 return FALSE;
290 }
291
292 /* Allocate space in the Buffer */
293 CsrAllocateMessagePointer(CaptureBuffer,
294 Size,
295 (PVOID*)&GetInputRequest->RecordBufPtr);
296 }
297
298 /* Call the server */
299 CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
300 CaptureBuffer,
301 CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepGetConsoleInput),
302 sizeof(*GetInputRequest));
303
304 /* Check for success */
305 Success = NT_SUCCESS(ApiMessage.Status);
306
307 /* Retrieve the results */
308 _SEH2_TRY
309 {
310 DPRINT("Events read: %lx\n", GetInputRequest->NumRecords);
311 *lpNumberOfEventsRead = GetInputRequest->NumRecords;
312
313 if (Success)
314 {
315 RtlCopyMemory(lpBuffer,
316 GetInputRequest->RecordBufPtr,
317 GetInputRequest->NumRecords * sizeof(INPUT_RECORD));
318 }
319 else
320 {
321 BaseSetLastNTError(ApiMessage.Status);
322 }
323 }
324 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
325 {
326 SetLastError(ERROR_INVALID_ACCESS);
327 Success = FALSE;
328 }
329 _SEH2_END;
330
331 /* Release the capture buffer if needed */
332 if (CaptureBuffer) CsrFreeCaptureBuffer(CaptureBuffer);
333
334 /* Return success status */
335 return Success;
336 }
337
338
339 static
340 BOOL
341 IntReadConsoleOutput(IN HANDLE hConsoleOutput,
342 OUT PCHAR_INFO lpBuffer,
343 IN COORD dwBufferSize,
344 IN COORD dwBufferCoord,
345 IN OUT PSMALL_RECT lpReadRegion,
346 IN BOOLEAN bUnicode)
347 {
348 BOOL Success;
349 CONSOLE_API_MESSAGE ApiMessage;
350 PCONSOLE_READOUTPUT ReadOutputRequest = &ApiMessage.Data.ReadOutputRequest;
351 PCSR_CAPTURE_BUFFER CaptureBuffer = NULL;
352
353 SHORT SizeX, SizeY;
354 ULONG NumCells;
355
356 /* Set up the data to send to the Console Server */
357 ReadOutputRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
358 ReadOutputRequest->OutputHandle = hConsoleOutput;
359 ReadOutputRequest->Unicode = bUnicode;
360
361 /* Update lpReadRegion */
362 _SEH2_TRY
363 {
364 SizeX = min(dwBufferSize.X - dwBufferCoord.X, ConioRectWidth(lpReadRegion));
365 SizeY = min(dwBufferSize.Y - dwBufferCoord.Y, ConioRectHeight(lpReadRegion));
366 if (SizeX <= 0 || SizeY <= 0)
367 {
368 SetLastError(ERROR_INVALID_PARAMETER);
369 _SEH2_YIELD(return FALSE);
370 }
371 lpReadRegion->Right = lpReadRegion->Left + SizeX - 1;
372 lpReadRegion->Bottom = lpReadRegion->Top + SizeY - 1;
373
374 ReadOutputRequest->ReadRegion = *lpReadRegion;
375 }
376 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
377 {
378 SetLastError(ERROR_INVALID_ACCESS);
379 _SEH2_YIELD(return FALSE);
380 }
381 _SEH2_END;
382
383 NumCells = SizeX * SizeY;
384 DPRINT("IntReadConsoleOutput: (%d x %d)\n", SizeX, SizeY);
385
386 /*
387 * For optimization purposes, Windows (and hence ReactOS, too, for
388 * compatibility reasons) uses a static buffer if no more than one
389 * cell is read. Otherwise a new buffer is allocated.
390 * This behaviour is also expected in the server-side.
391 */
392 if (NumCells <= 1)
393 {
394 ReadOutputRequest->CharInfo = &ReadOutputRequest->StaticBuffer;
395 // CaptureBuffer = NULL;
396 }
397 else
398 {
399 ULONG Size = NumCells * sizeof(CHAR_INFO);
400
401 /* Allocate a Capture Buffer */
402 CaptureBuffer = CsrAllocateCaptureBuffer(1, Size);
403 if (CaptureBuffer == NULL)
404 {
405 DPRINT1("CsrAllocateCaptureBuffer failed with size %ld!\n", Size);
406 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
407 return FALSE;
408 }
409
410 /* Allocate space in the Buffer */
411 CsrAllocateMessagePointer(CaptureBuffer,
412 Size,
413 (PVOID*)&ReadOutputRequest->CharInfo);
414 }
415
416 /* Call the server */
417 CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
418 CaptureBuffer,
419 CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepReadConsoleOutput),
420 sizeof(*ReadOutputRequest));
421
422 /* Check for success */
423 Success = NT_SUCCESS(ApiMessage.Status);
424
425 /* Retrieve the results */
426 _SEH2_TRY
427 {
428 *lpReadRegion = ReadOutputRequest->ReadRegion;
429
430 if (Success)
431 {
432 #if 0
433 SHORT x, X;
434 #endif
435 SHORT y, Y;
436
437 /* Copy into the buffer */
438
439 SizeX = ConioRectWidth(&ReadOutputRequest->ReadRegion);
440
441 for (y = 0, Y = ReadOutputRequest->ReadRegion.Top; Y <= ReadOutputRequest->ReadRegion.Bottom; ++y, ++Y)
442 {
443 RtlCopyMemory(lpBuffer + (y + dwBufferCoord.Y) * dwBufferSize.X + dwBufferCoord.X,
444 ReadOutputRequest->CharInfo + y * SizeX,
445 SizeX * sizeof(CHAR_INFO));
446 #if 0
447 for (x = 0, X = ReadOutputRequest->ReadRegion.Left; X <= ReadOutputRequest->ReadRegion.Right; ++x, ++X)
448 {
449 *(lpBuffer + (y + dwBufferCoord.Y) * dwBufferSize.X + (x + dwBufferCoord.X)) =
450 *(ReadOutputRequest->CharInfo + y * SizeX + x);
451 }
452 #endif
453 }
454 }
455 else
456 {
457 BaseSetLastNTError(ApiMessage.Status);
458 }
459 }
460 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
461 {
462 SetLastError(ERROR_INVALID_ACCESS);
463 Success = FALSE;
464 }
465 _SEH2_END;
466
467 /* Release the capture buffer if needed */
468 if (CaptureBuffer) CsrFreeCaptureBuffer(CaptureBuffer);
469
470 /* Return success status */
471 return Success;
472 }
473
474
475 static
476 BOOL
477 IntReadConsoleOutputCode(IN HANDLE hConsoleOutput,
478 IN CODE_TYPE CodeType,
479 OUT PVOID pCode,
480 IN DWORD nLength,
481 IN COORD dwReadCoord,
482 OUT LPDWORD lpNumberOfCodesRead)
483 {
484 BOOL Success;
485 CONSOLE_API_MESSAGE ApiMessage;
486 PCONSOLE_READOUTPUTCODE ReadOutputCodeRequest = &ApiMessage.Data.ReadOutputCodeRequest;
487 PCSR_CAPTURE_BUFFER CaptureBuffer = NULL;
488 ULONG CodeSize, SizeBytes;
489
490 DPRINT("IntReadConsoleOutputCode\n");
491
492 if ( (CodeType != CODE_ASCII ) &&
493 (CodeType != CODE_UNICODE ) &&
494 (CodeType != CODE_ATTRIBUTE) )
495 {
496 SetLastError(ERROR_INVALID_PARAMETER);
497 return FALSE;
498 }
499
500 /* Set up the data to send to the Console Server */
501 ReadOutputCodeRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
502 ReadOutputCodeRequest->OutputHandle = hConsoleOutput;
503 ReadOutputCodeRequest->Coord = dwReadCoord;
504 ReadOutputCodeRequest->NumCodes = nLength;
505
506 /* Determine the needed size */
507 ReadOutputCodeRequest->CodeType = CodeType;
508 switch (CodeType)
509 {
510 case CODE_ASCII:
511 CodeSize = RTL_FIELD_SIZE(CODE_ELEMENT, AsciiChar);
512 break;
513
514 case CODE_UNICODE:
515 CodeSize = RTL_FIELD_SIZE(CODE_ELEMENT, UnicodeChar);
516 break;
517
518 case CODE_ATTRIBUTE:
519 CodeSize = RTL_FIELD_SIZE(CODE_ELEMENT, Attribute);
520 break;
521 }
522 SizeBytes = nLength * CodeSize;
523
524 /*
525 * For optimization purposes, Windows (and hence ReactOS, too, for
526 * compatibility reasons) uses a static buffer if no more than eighty
527 * bytes are read. Otherwise a new buffer is allocated.
528 * This behaviour is also expected in the server-side.
529 */
530 if (SizeBytes <= sizeof(ReadOutputCodeRequest->CodeStaticBuffer))
531 {
532 ReadOutputCodeRequest->pCode = ReadOutputCodeRequest->CodeStaticBuffer;
533 // CaptureBuffer = NULL;
534 }
535 else
536 {
537 /* Allocate a Capture Buffer */
538 CaptureBuffer = CsrAllocateCaptureBuffer(1, SizeBytes);
539 if (CaptureBuffer == NULL)
540 {
541 DPRINT1("CsrAllocateCaptureBuffer failed!\n");
542 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
543 return FALSE;
544 }
545
546 /* Allocate space in the Buffer */
547 CsrAllocateMessagePointer(CaptureBuffer,
548 SizeBytes,
549 (PVOID*)&ReadOutputCodeRequest->pCode);
550 }
551
552 /* Call the server */
553 CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
554 CaptureBuffer,
555 CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepReadConsoleOutputString),
556 sizeof(*ReadOutputCodeRequest));
557
558 /* Check for success */
559 Success = NT_SUCCESS(ApiMessage.Status);
560
561 /* Retrieve the results */
562 _SEH2_TRY
563 {
564 *lpNumberOfCodesRead = ReadOutputCodeRequest->NumCodes;
565
566 if (Success)
567 {
568 RtlCopyMemory(pCode,
569 ReadOutputCodeRequest->pCode,
570 ReadOutputCodeRequest->NumCodes * CodeSize);
571 }
572 else
573 {
574 BaseSetLastNTError(ApiMessage.Status);
575 }
576 }
577 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
578 {
579 SetLastError(ERROR_INVALID_ACCESS);
580 Success = FALSE;
581 }
582 _SEH2_END;
583
584 /* Release the capture buffer if needed */
585 if (CaptureBuffer) CsrFreeCaptureBuffer(CaptureBuffer);
586
587 /* Return success status */
588 return Success;
589 }
590
591
592 /*******************
593 * Write functions *
594 *******************/
595
596 static
597 BOOL
598 IntWriteConsole(IN HANDLE hConsoleOutput,
599 IN PVOID lpBuffer,
600 IN DWORD nNumberOfCharsToWrite,
601 OUT LPDWORD lpNumberOfCharsWritten,
602 LPVOID lpReserved,
603 IN BOOLEAN bUnicode)
604 {
605 BOOL Success;
606 CONSOLE_API_MESSAGE ApiMessage;
607 PCONSOLE_WRITECONSOLE WriteConsoleRequest = &ApiMessage.Data.WriteConsoleRequest;
608 PCSR_CAPTURE_BUFFER CaptureBuffer = NULL;
609 ULONG CharSize, SizeBytes;
610
611 DPRINT("IntWriteConsole\n");
612
613 /* Set up the data to send to the Console Server */
614 WriteConsoleRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
615 WriteConsoleRequest->OutputHandle = hConsoleOutput;
616 WriteConsoleRequest->Unicode = bUnicode;
617
618 /* Those members are unused by the client, on Windows */
619 WriteConsoleRequest->Reserved1 = 0;
620 // WriteConsoleRequest->Reserved2 = {0};
621
622 /* Determine the needed size */
623 CharSize = (bUnicode ? sizeof(WCHAR) : sizeof(CHAR));
624 SizeBytes = nNumberOfCharsToWrite * CharSize;
625
626 WriteConsoleRequest->NumBytes = SizeBytes;
627
628 /*
629 * For optimization purposes, Windows (and hence ReactOS, too, for
630 * compatibility reasons) uses a static buffer if no more than eighty
631 * bytes are written. Otherwise a new buffer is allocated.
632 * This behaviour is also expected in the server-side.
633 */
634 if (SizeBytes <= sizeof(WriteConsoleRequest->StaticBuffer))
635 {
636 WriteConsoleRequest->Buffer = WriteConsoleRequest->StaticBuffer;
637 // CaptureBuffer = NULL;
638 WriteConsoleRequest->UsingStaticBuffer = TRUE;
639
640 _SEH2_TRY
641 {
642 RtlCopyMemory(WriteConsoleRequest->Buffer,
643 lpBuffer,
644 SizeBytes);
645 }
646 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
647 {
648 SetLastError(ERROR_INVALID_ACCESS);
649 _SEH2_YIELD(return FALSE);
650 }
651 _SEH2_END;
652 }
653 else
654 {
655 /* Allocate a Capture Buffer */
656 CaptureBuffer = CsrAllocateCaptureBuffer(1, SizeBytes);
657 if (CaptureBuffer == NULL)
658 {
659 DPRINT1("CsrAllocateCaptureBuffer failed!\n");
660 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
661 return FALSE;
662 }
663
664 /* Capture the buffer to write */
665 CsrCaptureMessageBuffer(CaptureBuffer,
666 (PVOID)lpBuffer,
667 SizeBytes,
668 (PVOID*)&WriteConsoleRequest->Buffer);
669 WriteConsoleRequest->UsingStaticBuffer = FALSE;
670 }
671
672 /* Call the server */
673 CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
674 CaptureBuffer,
675 CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepWriteConsole),
676 sizeof(*WriteConsoleRequest));
677
678 /* Check for success */
679 Success = NT_SUCCESS(ApiMessage.Status);
680
681 /* Release the capture buffer if needed */
682 if (CaptureBuffer) CsrFreeCaptureBuffer(CaptureBuffer);
683
684 /* Retrieve the results. NOTE: lpNumberOfCharsWritten optional since Vista+ */
685 if (Success && lpNumberOfCharsWritten)
686 {
687 _SEH2_TRY
688 {
689 *lpNumberOfCharsWritten = WriteConsoleRequest->NumBytes / CharSize;
690 }
691 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
692 {
693 SetLastError(ERROR_INVALID_ACCESS);
694 Success = FALSE;
695 }
696 _SEH2_END;
697 }
698 else if (!Success)
699 {
700 BaseSetLastNTError(ApiMessage.Status);
701 }
702
703 /* Return success status */
704 return Success;
705 }
706
707
708 static
709 BOOL
710 IntWriteConsoleInput(IN HANDLE hConsoleInput,
711 IN PINPUT_RECORD lpBuffer,
712 IN DWORD nLength,
713 OUT LPDWORD lpNumberOfEventsWritten,
714 IN BOOLEAN bUnicode,
715 IN BOOLEAN bAppendToEnd)
716 {
717 BOOL Success;
718 CONSOLE_API_MESSAGE ApiMessage;
719 PCONSOLE_WRITEINPUT WriteInputRequest = &ApiMessage.Data.WriteInputRequest;
720 PCSR_CAPTURE_BUFFER CaptureBuffer = NULL;
721
722 DPRINT("IntWriteConsoleInput: %lx %p\n", nLength, lpNumberOfEventsWritten);
723
724 /* Set up the data to send to the Console Server */
725 WriteInputRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
726 WriteInputRequest->InputHandle = hConsoleInput;
727 WriteInputRequest->NumRecords = nLength;
728 WriteInputRequest->Unicode = bUnicode;
729 WriteInputRequest->AppendToEnd = bAppendToEnd;
730
731 /*
732 * For optimization purposes, Windows (and hence ReactOS, too, for
733 * compatibility reasons) uses a static buffer if no more than five
734 * input records are written. Otherwise a new buffer is allocated.
735 * This behaviour is also expected in the server-side.
736 */
737 if (nLength <= sizeof(WriteInputRequest->RecordStaticBuffer)/sizeof(INPUT_RECORD))
738 {
739 WriteInputRequest->RecordBufPtr = WriteInputRequest->RecordStaticBuffer;
740 // CaptureBuffer = NULL;
741
742 _SEH2_TRY
743 {
744 RtlCopyMemory(WriteInputRequest->RecordBufPtr,
745 lpBuffer,
746 nLength * sizeof(INPUT_RECORD));
747 }
748 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
749 {
750 SetLastError(ERROR_INVALID_ACCESS);
751 _SEH2_YIELD(return FALSE);
752 }
753 _SEH2_END;
754 }
755 else
756 {
757 ULONG Size = nLength * sizeof(INPUT_RECORD);
758
759 /* Allocate a Capture Buffer */
760 CaptureBuffer = CsrAllocateCaptureBuffer(1, Size);
761 if (CaptureBuffer == NULL)
762 {
763 DPRINT1("CsrAllocateCaptureBuffer failed!\n");
764 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
765 return FALSE;
766 }
767
768 /* Capture the user buffer */
769 CsrCaptureMessageBuffer(CaptureBuffer,
770 lpBuffer,
771 Size,
772 (PVOID*)&WriteInputRequest->RecordBufPtr);
773 }
774
775 /* Call the server */
776 CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
777 CaptureBuffer,
778 CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepWriteConsoleInput),
779 sizeof(*WriteInputRequest));
780
781 /* Check for success */
782 Success = NT_SUCCESS(ApiMessage.Status);
783
784 /* Release the capture buffer if needed */
785 if (CaptureBuffer) CsrFreeCaptureBuffer(CaptureBuffer);
786
787 /* Retrieve the results */
788 _SEH2_TRY
789 {
790 DPRINT("Events written: %lx\n", WriteInputRequest->NumRecords);
791 *lpNumberOfEventsWritten = WriteInputRequest->NumRecords;
792
793 if (!Success)
794 BaseSetLastNTError(ApiMessage.Status);
795 }
796 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
797 {
798 SetLastError(ERROR_INVALID_ACCESS);
799 Success = FALSE;
800 }
801 _SEH2_END;
802
803 /* Return success status */
804 return Success;
805 }
806
807
808 static
809 BOOL
810 IntWriteConsoleOutput(IN HANDLE hConsoleOutput,
811 IN CONST CHAR_INFO *lpBuffer,
812 IN COORD dwBufferSize,
813 IN COORD dwBufferCoord,
814 IN OUT PSMALL_RECT lpWriteRegion,
815 IN BOOLEAN bUnicode)
816 {
817 BOOL Success;
818 CONSOLE_API_MESSAGE ApiMessage;
819 PCONSOLE_WRITEOUTPUT WriteOutputRequest = &ApiMessage.Data.WriteOutputRequest;
820 PCSR_CAPTURE_BUFFER CaptureBuffer = NULL;
821
822 SHORT SizeX, SizeY;
823 ULONG NumCells;
824
825 /* Set up the data to send to the Console Server */
826 WriteOutputRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
827 WriteOutputRequest->OutputHandle = hConsoleOutput;
828 WriteOutputRequest->Unicode = bUnicode;
829
830 /* Update lpWriteRegion */
831 _SEH2_TRY
832 {
833 SizeX = min(dwBufferSize.X - dwBufferCoord.X, ConioRectWidth(lpWriteRegion));
834 SizeY = min(dwBufferSize.Y - dwBufferCoord.Y, ConioRectHeight(lpWriteRegion));
835 if (SizeX <= 0 || SizeY <= 0)
836 {
837 SetLastError(ERROR_INVALID_PARAMETER);
838 _SEH2_YIELD(return FALSE);
839 }
840 lpWriteRegion->Right = lpWriteRegion->Left + SizeX - 1;
841 lpWriteRegion->Bottom = lpWriteRegion->Top + SizeY - 1;
842
843 WriteOutputRequest->WriteRegion = *lpWriteRegion;
844 }
845 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
846 {
847 SetLastError(ERROR_INVALID_ACCESS);
848 _SEH2_YIELD(return FALSE);
849 }
850 _SEH2_END;
851
852 NumCells = SizeX * SizeY;
853 DPRINT("IntWriteConsoleOutput: (%d x %d)\n", SizeX, SizeY);
854
855 /*
856 * For optimization purposes, Windows (and hence ReactOS, too, for
857 * compatibility reasons) uses a static buffer if no more than one
858 * cell is written. Otherwise a new buffer is allocated.
859 * This behaviour is also expected in the server-side.
860 */
861 if (NumCells <= 1)
862 {
863 WriteOutputRequest->CharInfo = &WriteOutputRequest->StaticBuffer;
864 // CaptureBuffer = NULL;
865 WriteOutputRequest->UseVirtualMemory = FALSE;
866 }
867 else
868 {
869 ULONG Size = NumCells * sizeof(CHAR_INFO);
870
871 /* Allocate a Capture Buffer */
872 CaptureBuffer = CsrAllocateCaptureBuffer(1, Size);
873 if (CaptureBuffer)
874 {
875 /* Allocate space in the Buffer */
876 CsrAllocateMessagePointer(CaptureBuffer,
877 Size,
878 (PVOID*)&WriteOutputRequest->CharInfo);
879 WriteOutputRequest->UseVirtualMemory = FALSE;
880 }
881 else
882 {
883 /*
884 * CsrAllocateCaptureBuffer failed because we tried to allocate
885 * a too large (>= 64 kB, size of the CSR heap) data buffer.
886 * To circumvent this, Windows uses a trick (that we reproduce for
887 * compatibility reasons): we allocate a heap buffer in the process'
888 * memory, and CSR will read it via NtReadVirtualMemory.
889 */
890 DPRINT1("CsrAllocateCaptureBuffer failed with size %ld, let's use local heap buffer...\n", Size);
891
892 WriteOutputRequest->CharInfo = RtlAllocateHeap(RtlGetProcessHeap(), 0, Size);
893 WriteOutputRequest->UseVirtualMemory = TRUE;
894
895 /* Bail out if we still cannot allocate memory */
896 if (WriteOutputRequest->CharInfo == NULL)
897 {
898 DPRINT1("Failed to allocate heap buffer with size %ld!\n", Size);
899 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
900 return FALSE;
901 }
902 }
903 }
904
905 /* Capture the user buffer contents */
906 _SEH2_TRY
907 {
908 #if 0
909 SHORT x, X;
910 #endif
911 SHORT y, Y;
912
913 /* Copy into the buffer */
914
915 SizeX = ConioRectWidth(&WriteOutputRequest->WriteRegion);
916
917 for (y = 0, Y = WriteOutputRequest->WriteRegion.Top; Y <= WriteOutputRequest->WriteRegion.Bottom; ++y, ++Y)
918 {
919 RtlCopyMemory(WriteOutputRequest->CharInfo + y * SizeX,
920 lpBuffer + (y + dwBufferCoord.Y) * dwBufferSize.X + dwBufferCoord.X,
921 SizeX * sizeof(CHAR_INFO));
922 #if 0
923 for (x = 0, X = WriteOutputRequest->WriteRegion.Left; X <= WriteOutputRequest->WriteRegion.Right; ++x, ++X)
924 {
925 *(WriteOutputRequest->CharInfo + y * SizeX + x) =
926 *(lpBuffer + (y + dwBufferCoord.Y) * dwBufferSize.X + (x + dwBufferCoord.X));
927 }
928 #endif
929 }
930 }
931 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
932 {
933 SetLastError(ERROR_INVALID_ACCESS);
934 _SEH2_YIELD(return FALSE);
935 }
936 _SEH2_END;
937
938 /* Call the server */
939 CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
940 CaptureBuffer,
941 CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepWriteConsoleOutput),
942 sizeof(*WriteOutputRequest));
943
944 /* Check for success */
945 Success = NT_SUCCESS(ApiMessage.Status);
946
947 /* Release the capture buffer if needed */
948 if (CaptureBuffer)
949 {
950 CsrFreeCaptureBuffer(CaptureBuffer);
951 }
952 else
953 {
954 /* If we used a heap buffer, free it */
955 if (WriteOutputRequest->UseVirtualMemory)
956 RtlFreeHeap(RtlGetProcessHeap(), 0, WriteOutputRequest->CharInfo);
957 }
958
959 /* Retrieve the results */
960 _SEH2_TRY
961 {
962 *lpWriteRegion = WriteOutputRequest->WriteRegion;
963
964 if (!Success)
965 BaseSetLastNTError(ApiMessage.Status);
966 }
967 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
968 {
969 SetLastError(ERROR_INVALID_ACCESS);
970 Success = FALSE;
971 }
972 _SEH2_END;
973
974 /* Return success status */
975 return Success;
976 }
977
978
979 static
980 BOOL
981 IntWriteConsoleOutputCode(IN HANDLE hConsoleOutput,
982 IN CODE_TYPE CodeType,
983 IN CONST VOID *pCode,
984 IN DWORD nLength,
985 IN COORD dwWriteCoord,
986 OUT LPDWORD lpNumberOfCodesWritten)
987 {
988 BOOL Success;
989 CONSOLE_API_MESSAGE ApiMessage;
990 PCONSOLE_WRITEOUTPUTCODE WriteOutputCodeRequest = &ApiMessage.Data.WriteOutputCodeRequest;
991 PCSR_CAPTURE_BUFFER CaptureBuffer = NULL;
992 ULONG CodeSize, SizeBytes;
993
994 if ( (CodeType != CODE_ASCII ) &&
995 (CodeType != CODE_UNICODE ) &&
996 (CodeType != CODE_ATTRIBUTE) )
997 {
998 SetLastError(ERROR_INVALID_PARAMETER);
999 return FALSE;
1000 }
1001
1002 DPRINT("IntWriteConsoleOutputCode\n");
1003
1004 /* Set up the data to send to the Console Server */
1005 WriteOutputCodeRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
1006 WriteOutputCodeRequest->OutputHandle = hConsoleOutput;
1007 WriteOutputCodeRequest->Coord = dwWriteCoord;
1008 WriteOutputCodeRequest->NumCodes = nLength;
1009
1010 /* Determine the needed size */
1011 WriteOutputCodeRequest->CodeType = CodeType;
1012 switch (CodeType)
1013 {
1014 case CODE_ASCII:
1015 CodeSize = RTL_FIELD_SIZE(CODE_ELEMENT, AsciiChar);
1016 break;
1017
1018 case CODE_UNICODE:
1019 CodeSize = RTL_FIELD_SIZE(CODE_ELEMENT, UnicodeChar);
1020 break;
1021
1022 case CODE_ATTRIBUTE:
1023 CodeSize = RTL_FIELD_SIZE(CODE_ELEMENT, Attribute);
1024 break;
1025 }
1026 SizeBytes = nLength * CodeSize;
1027
1028 /*
1029 * For optimization purposes, Windows (and hence ReactOS, too, for
1030 * compatibility reasons) uses a static buffer if no more than eighty
1031 * bytes are written. Otherwise a new buffer is allocated.
1032 * This behaviour is also expected in the server-side.
1033 */
1034 if (SizeBytes <= sizeof(WriteOutputCodeRequest->CodeStaticBuffer))
1035 {
1036 WriteOutputCodeRequest->pCode = WriteOutputCodeRequest->CodeStaticBuffer;
1037 // CaptureBuffer = NULL;
1038
1039 _SEH2_TRY
1040 {
1041 RtlCopyMemory(WriteOutputCodeRequest->pCode,
1042 pCode,
1043 SizeBytes);
1044 }
1045 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1046 {
1047 SetLastError(ERROR_INVALID_ACCESS);
1048 _SEH2_YIELD(return FALSE);
1049 }
1050 _SEH2_END;
1051 }
1052 else
1053 {
1054 /* Allocate a Capture Buffer */
1055 CaptureBuffer = CsrAllocateCaptureBuffer(1, SizeBytes);
1056 if (CaptureBuffer == NULL)
1057 {
1058 DPRINT1("CsrAllocateCaptureBuffer failed!\n");
1059 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1060 return FALSE;
1061 }
1062
1063 /* Capture the buffer to write */
1064 CsrCaptureMessageBuffer(CaptureBuffer,
1065 (PVOID)pCode,
1066 SizeBytes,
1067 (PVOID*)&WriteOutputCodeRequest->pCode);
1068 }
1069
1070 /* Call the server */
1071 CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
1072 CaptureBuffer,
1073 CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepWriteConsoleOutputString),
1074 sizeof(*WriteOutputCodeRequest));
1075
1076 /* Check for success */
1077 Success = NT_SUCCESS(ApiMessage.Status);
1078
1079 /* Release the capture buffer if needed */
1080 if (CaptureBuffer) CsrFreeCaptureBuffer(CaptureBuffer);
1081
1082 /* Retrieve the results */
1083 _SEH2_TRY
1084 {
1085 *lpNumberOfCodesWritten = WriteOutputCodeRequest->NumCodes;
1086
1087 if (!Success)
1088 BaseSetLastNTError(ApiMessage.Status);
1089 }
1090 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1091 {
1092 SetLastError(ERROR_INVALID_ACCESS);
1093 Success = FALSE;
1094 }
1095 _SEH2_END;
1096
1097 /* Return success status */
1098 return Success;
1099 }
1100
1101
1102 static
1103 BOOL
1104 IntFillConsoleOutputCode(IN HANDLE hConsoleOutput,
1105 IN CODE_TYPE CodeType,
1106 IN CODE_ELEMENT Code,
1107 IN DWORD nLength,
1108 IN COORD dwWriteCoord,
1109 OUT LPDWORD lpNumberOfCodesWritten)
1110 {
1111 BOOL Success;
1112 CONSOLE_API_MESSAGE ApiMessage;
1113 PCONSOLE_FILLOUTPUTCODE FillOutputRequest = &ApiMessage.Data.FillOutputRequest;
1114
1115 DPRINT("IntFillConsoleOutputCode\n");
1116
1117 if ( (CodeType != CODE_ASCII ) &&
1118 (CodeType != CODE_UNICODE ) &&
1119 (CodeType != CODE_ATTRIBUTE) )
1120 {
1121 SetLastError(ERROR_INVALID_PARAMETER);
1122 return FALSE;
1123 }
1124
1125 /* Set up the data to send to the Console Server */
1126 FillOutputRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
1127 FillOutputRequest->OutputHandle = hConsoleOutput;
1128 FillOutputRequest->WriteCoord = dwWriteCoord;
1129 FillOutputRequest->CodeType = CodeType;
1130 FillOutputRequest->Code = Code;
1131 FillOutputRequest->NumCodes = nLength;
1132
1133 /* Call the server */
1134 CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
1135 NULL,
1136 CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepFillConsoleOutput),
1137 sizeof(*FillOutputRequest));
1138
1139 /* Check for success */
1140 Success = NT_SUCCESS(ApiMessage.Status);
1141
1142 /* Retrieve the results */
1143 _SEH2_TRY
1144 {
1145 *lpNumberOfCodesWritten = FillOutputRequest->NumCodes;
1146
1147 if (!Success)
1148 BaseSetLastNTError(ApiMessage.Status);
1149 }
1150 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1151 {
1152 SetLastError(ERROR_INVALID_ACCESS);
1153 Success = FALSE;
1154 }
1155 _SEH2_END;
1156
1157 /* Return success status */
1158 return Success;
1159 }
1160
1161
1162 /* FUNCTIONS ******************************************************************/
1163
1164 /******************
1165 * Read functions *
1166 ******************/
1167
1168 /*
1169 * @implemented
1170 */
1171 BOOL
1172 WINAPI
1173 DECLSPEC_HOTPATCH
1174 ReadConsoleW(IN HANDLE hConsoleInput,
1175 OUT LPVOID lpBuffer,
1176 IN DWORD nNumberOfCharsToRead,
1177 OUT LPDWORD lpNumberOfCharsRead,
1178 IN PCONSOLE_READCONSOLE_CONTROL pInputControl OPTIONAL)
1179 {
1180 return IntReadConsole(hConsoleInput,
1181 lpBuffer,
1182 nNumberOfCharsToRead,
1183 lpNumberOfCharsRead,
1184 pInputControl,
1185 TRUE);
1186 }
1187
1188
1189 /*
1190 * @implemented
1191 */
1192 BOOL
1193 WINAPI
1194 DECLSPEC_HOTPATCH
1195 ReadConsoleA(IN HANDLE hConsoleInput,
1196 OUT LPVOID lpBuffer,
1197 IN DWORD nNumberOfCharsToRead,
1198 OUT LPDWORD lpNumberOfCharsRead,
1199 IN PCONSOLE_READCONSOLE_CONTROL pInputControl OPTIONAL)
1200 {
1201 return IntReadConsole(hConsoleInput,
1202 lpBuffer,
1203 nNumberOfCharsToRead,
1204 lpNumberOfCharsRead,
1205 NULL,
1206 FALSE);
1207 }
1208
1209
1210 /*
1211 * @implemented
1212 */
1213 BOOL
1214 WINAPI
1215 DECLSPEC_HOTPATCH
1216 PeekConsoleInputW(IN HANDLE hConsoleInput,
1217 OUT PINPUT_RECORD lpBuffer,
1218 IN DWORD nLength,
1219 OUT LPDWORD lpNumberOfEventsRead)
1220 {
1221 return IntGetConsoleInput(hConsoleInput,
1222 lpBuffer,
1223 nLength,
1224 lpNumberOfEventsRead,
1225 CONSOLE_READ_KEEPEVENT | CONSOLE_READ_CONTINUE,
1226 TRUE);
1227 }
1228
1229
1230 /*
1231 * @implemented
1232 */
1233 BOOL
1234 WINAPI
1235 DECLSPEC_HOTPATCH
1236 PeekConsoleInputA(IN HANDLE hConsoleInput,
1237 OUT PINPUT_RECORD lpBuffer,
1238 IN DWORD nLength,
1239 OUT LPDWORD lpNumberOfEventsRead)
1240 {
1241 return IntGetConsoleInput(hConsoleInput,
1242 lpBuffer,
1243 nLength,
1244 lpNumberOfEventsRead,
1245 CONSOLE_READ_KEEPEVENT | CONSOLE_READ_CONTINUE,
1246 FALSE);
1247 }
1248
1249
1250 /*
1251 * @implemented
1252 */
1253 BOOL
1254 WINAPI
1255 DECLSPEC_HOTPATCH
1256 ReadConsoleInputW(IN HANDLE hConsoleInput,
1257 OUT PINPUT_RECORD lpBuffer,
1258 IN DWORD nLength,
1259 OUT LPDWORD lpNumberOfEventsRead)
1260 {
1261 return IntGetConsoleInput(hConsoleInput,
1262 lpBuffer,
1263 nLength,
1264 lpNumberOfEventsRead,
1265 0,
1266 TRUE);
1267 }
1268
1269
1270 /*
1271 * @implemented
1272 */
1273 BOOL
1274 WINAPI
1275 DECLSPEC_HOTPATCH
1276 ReadConsoleInputA(IN HANDLE hConsoleInput,
1277 OUT PINPUT_RECORD lpBuffer,
1278 IN DWORD nLength,
1279 OUT LPDWORD lpNumberOfEventsRead)
1280 {
1281 return IntGetConsoleInput(hConsoleInput,
1282 lpBuffer,
1283 nLength,
1284 lpNumberOfEventsRead,
1285 0,
1286 FALSE);
1287 }
1288
1289
1290 /*
1291 * @implemented
1292 */
1293 BOOL
1294 WINAPI
1295 DECLSPEC_HOTPATCH
1296 ReadConsoleInputExW(IN HANDLE hConsoleInput,
1297 OUT PINPUT_RECORD lpBuffer,
1298 IN DWORD nLength,
1299 OUT LPDWORD lpNumberOfEventsRead,
1300 IN WORD wFlags)
1301 {
1302 return IntGetConsoleInput(hConsoleInput,
1303 lpBuffer,
1304 nLength,
1305 lpNumberOfEventsRead,
1306 wFlags,
1307 TRUE);
1308 }
1309
1310
1311 /*
1312 * @implemented
1313 */
1314 BOOL
1315 WINAPI
1316 DECLSPEC_HOTPATCH
1317 ReadConsoleInputExA(IN HANDLE hConsoleInput,
1318 OUT PINPUT_RECORD lpBuffer,
1319 IN DWORD nLength,
1320 OUT LPDWORD lpNumberOfEventsRead,
1321 IN WORD wFlags)
1322 {
1323 return IntGetConsoleInput(hConsoleInput,
1324 lpBuffer,
1325 nLength,
1326 lpNumberOfEventsRead,
1327 wFlags,
1328 FALSE);
1329 }
1330
1331
1332 /*
1333 * @implemented
1334 */
1335 BOOL
1336 WINAPI
1337 DECLSPEC_HOTPATCH
1338 ReadConsoleOutputW(IN HANDLE hConsoleOutput,
1339 OUT PCHAR_INFO lpBuffer,
1340 IN COORD dwBufferSize,
1341 IN COORD dwBufferCoord,
1342 IN OUT PSMALL_RECT lpReadRegion)
1343 {
1344 return IntReadConsoleOutput(hConsoleOutput,
1345 lpBuffer,
1346 dwBufferSize,
1347 dwBufferCoord,
1348 lpReadRegion,
1349 TRUE);
1350 }
1351
1352
1353 /*
1354 * @implemented
1355 */
1356 BOOL
1357 WINAPI
1358 DECLSPEC_HOTPATCH
1359 ReadConsoleOutputA(IN HANDLE hConsoleOutput,
1360 OUT PCHAR_INFO lpBuffer,
1361 IN COORD dwBufferSize,
1362 IN COORD dwBufferCoord,
1363 IN OUT PSMALL_RECT lpReadRegion)
1364 {
1365 return IntReadConsoleOutput(hConsoleOutput,
1366 lpBuffer,
1367 dwBufferSize,
1368 dwBufferCoord,
1369 lpReadRegion,
1370 FALSE);
1371 }
1372
1373
1374 /*
1375 * @implemented
1376 */
1377 BOOL
1378 WINAPI
1379 DECLSPEC_HOTPATCH
1380 ReadConsoleOutputCharacterW(IN HANDLE hConsoleOutput,
1381 OUT LPWSTR lpCharacter,
1382 IN DWORD nLength,
1383 IN COORD dwReadCoord,
1384 OUT LPDWORD lpNumberOfCharsRead)
1385 {
1386 return IntReadConsoleOutputCode(hConsoleOutput,
1387 CODE_UNICODE,
1388 lpCharacter,
1389 nLength,
1390 dwReadCoord,
1391 lpNumberOfCharsRead);
1392 }
1393
1394
1395 /*
1396 * @implemented
1397 */
1398 BOOL
1399 WINAPI
1400 DECLSPEC_HOTPATCH
1401 ReadConsoleOutputCharacterA(IN HANDLE hConsoleOutput,
1402 OUT LPSTR lpCharacter,
1403 IN DWORD nLength,
1404 IN COORD dwReadCoord,
1405 OUT LPDWORD lpNumberOfCharsRead)
1406 {
1407 return IntReadConsoleOutputCode(hConsoleOutput,
1408 CODE_ASCII,
1409 lpCharacter,
1410 nLength,
1411 dwReadCoord,
1412 lpNumberOfCharsRead);
1413 }
1414
1415
1416 /*
1417 * @implemented
1418 */
1419 BOOL
1420 WINAPI
1421 DECLSPEC_HOTPATCH
1422 ReadConsoleOutputAttribute(IN HANDLE hConsoleOutput,
1423 OUT LPWORD lpAttribute,
1424 IN DWORD nLength,
1425 IN COORD dwReadCoord,
1426 OUT LPDWORD lpNumberOfAttrsRead)
1427 {
1428 return IntReadConsoleOutputCode(hConsoleOutput,
1429 CODE_ATTRIBUTE,
1430 lpAttribute,
1431 nLength,
1432 dwReadCoord,
1433 lpNumberOfAttrsRead);
1434 }
1435
1436
1437 /*******************
1438 * Write functions *
1439 *******************/
1440
1441 /*
1442 * @implemented
1443 */
1444 BOOL
1445 WINAPI
1446 DECLSPEC_HOTPATCH
1447 WriteConsoleW(IN HANDLE hConsoleOutput,
1448 IN CONST VOID *lpBuffer,
1449 IN DWORD nNumberOfCharsToWrite,
1450 OUT LPDWORD lpNumberOfCharsWritten,
1451 LPVOID lpReserved)
1452 {
1453 return IntWriteConsole(hConsoleOutput,
1454 (PVOID)lpBuffer,
1455 nNumberOfCharsToWrite,
1456 lpNumberOfCharsWritten,
1457 lpReserved,
1458 TRUE);
1459 }
1460
1461
1462 /*
1463 * @implemented
1464 */
1465 BOOL
1466 WINAPI
1467 DECLSPEC_HOTPATCH
1468 WriteConsoleA(IN HANDLE hConsoleOutput,
1469 IN CONST VOID *lpBuffer,
1470 IN DWORD nNumberOfCharsToWrite,
1471 OUT LPDWORD lpNumberOfCharsWritten,
1472 LPVOID lpReserved)
1473 {
1474 return IntWriteConsole(hConsoleOutput,
1475 (PVOID)lpBuffer,
1476 nNumberOfCharsToWrite,
1477 lpNumberOfCharsWritten,
1478 lpReserved,
1479 FALSE);
1480 }
1481
1482
1483 /*
1484 * @implemented
1485 */
1486 BOOL
1487 WINAPI
1488 DECLSPEC_HOTPATCH
1489 WriteConsoleInputW(IN HANDLE hConsoleInput,
1490 IN CONST INPUT_RECORD *lpBuffer,
1491 IN DWORD nLength,
1492 OUT LPDWORD lpNumberOfEventsWritten)
1493 {
1494 return IntWriteConsoleInput(hConsoleInput,
1495 (PINPUT_RECORD)lpBuffer,
1496 nLength,
1497 lpNumberOfEventsWritten,
1498 TRUE,
1499 TRUE);
1500 }
1501
1502
1503 /*
1504 * @implemented
1505 */
1506 BOOL
1507 WINAPI
1508 DECLSPEC_HOTPATCH
1509 WriteConsoleInputA(IN HANDLE hConsoleInput,
1510 IN CONST INPUT_RECORD *lpBuffer,
1511 IN DWORD nLength,
1512 OUT LPDWORD lpNumberOfEventsWritten)
1513 {
1514 return IntWriteConsoleInput(hConsoleInput,
1515 (PINPUT_RECORD)lpBuffer,
1516 nLength,
1517 lpNumberOfEventsWritten,
1518 FALSE,
1519 TRUE);
1520 }
1521
1522
1523 /*
1524 * @implemented
1525 */
1526 BOOL
1527 WINAPI
1528 DECLSPEC_HOTPATCH
1529 WriteConsoleInputVDMW(IN HANDLE hConsoleInput,
1530 IN CONST INPUT_RECORD *lpBuffer,
1531 IN DWORD nLength,
1532 OUT LPDWORD lpNumberOfEventsWritten)
1533 {
1534 return IntWriteConsoleInput(hConsoleInput,
1535 (PINPUT_RECORD)lpBuffer,
1536 nLength,
1537 lpNumberOfEventsWritten,
1538 TRUE,
1539 FALSE);
1540 }
1541
1542
1543 /*
1544 * @implemented
1545 */
1546 BOOL
1547 WINAPI
1548 DECLSPEC_HOTPATCH
1549 WriteConsoleInputVDMA(IN HANDLE hConsoleInput,
1550 IN CONST INPUT_RECORD *lpBuffer,
1551 IN DWORD nLength,
1552 OUT LPDWORD lpNumberOfEventsWritten)
1553 {
1554 return IntWriteConsoleInput(hConsoleInput,
1555 (PINPUT_RECORD)lpBuffer,
1556 nLength,
1557 lpNumberOfEventsWritten,
1558 FALSE,
1559 FALSE);
1560 }
1561
1562
1563 /*
1564 * @implemented
1565 */
1566 BOOL
1567 WINAPI
1568 DECLSPEC_HOTPATCH
1569 WriteConsoleOutputW(IN HANDLE hConsoleOutput,
1570 IN CONST CHAR_INFO *lpBuffer,
1571 IN COORD dwBufferSize,
1572 IN COORD dwBufferCoord,
1573 IN OUT PSMALL_RECT lpWriteRegion)
1574 {
1575 return IntWriteConsoleOutput(hConsoleOutput,
1576 lpBuffer,
1577 dwBufferSize,
1578 dwBufferCoord,
1579 lpWriteRegion,
1580 TRUE);
1581 }
1582
1583
1584 /*
1585 * @implemented
1586 */
1587 BOOL
1588 WINAPI
1589 DECLSPEC_HOTPATCH
1590 WriteConsoleOutputA(IN HANDLE hConsoleOutput,
1591 IN CONST CHAR_INFO *lpBuffer,
1592 IN COORD dwBufferSize,
1593 IN COORD dwBufferCoord,
1594 IN OUT PSMALL_RECT lpWriteRegion)
1595 {
1596 return IntWriteConsoleOutput(hConsoleOutput,
1597 lpBuffer,
1598 dwBufferSize,
1599 dwBufferCoord,
1600 lpWriteRegion,
1601 FALSE);
1602 }
1603
1604
1605 /*
1606 * @implemented
1607 */
1608 BOOL
1609 WINAPI
1610 DECLSPEC_HOTPATCH
1611 WriteConsoleOutputCharacterW(IN HANDLE hConsoleOutput,
1612 IN LPCWSTR lpCharacter,
1613 IN DWORD nLength,
1614 IN COORD dwWriteCoord,
1615 OUT LPDWORD lpNumberOfCharsWritten)
1616 {
1617 return IntWriteConsoleOutputCode(hConsoleOutput,
1618 CODE_UNICODE,
1619 lpCharacter,
1620 nLength,
1621 dwWriteCoord,
1622 lpNumberOfCharsWritten);
1623 }
1624
1625
1626 /*
1627 * @implemented
1628 */
1629 BOOL
1630 WINAPI
1631 DECLSPEC_HOTPATCH
1632 WriteConsoleOutputCharacterA(IN HANDLE hConsoleOutput,
1633 IN LPCSTR lpCharacter,
1634 IN DWORD nLength,
1635 IN COORD dwWriteCoord,
1636 OUT LPDWORD lpNumberOfCharsWritten)
1637 {
1638 return IntWriteConsoleOutputCode(hConsoleOutput,
1639 CODE_ASCII,
1640 lpCharacter,
1641 nLength,
1642 dwWriteCoord,
1643 lpNumberOfCharsWritten);
1644 }
1645
1646
1647 /*
1648 * @implemented
1649 */
1650 BOOL
1651 WINAPI
1652 DECLSPEC_HOTPATCH
1653 WriteConsoleOutputAttribute(IN HANDLE hConsoleOutput,
1654 IN CONST WORD *lpAttribute,
1655 IN DWORD nLength,
1656 IN COORD dwWriteCoord,
1657 OUT LPDWORD lpNumberOfAttrsWritten)
1658 {
1659 return IntWriteConsoleOutputCode(hConsoleOutput,
1660 CODE_ATTRIBUTE,
1661 lpAttribute,
1662 nLength,
1663 dwWriteCoord,
1664 lpNumberOfAttrsWritten);
1665 }
1666
1667
1668 /*
1669 * @implemented
1670 */
1671 BOOL
1672 WINAPI
1673 DECLSPEC_HOTPATCH
1674 FillConsoleOutputCharacterW(IN HANDLE hConsoleOutput,
1675 IN WCHAR cCharacter,
1676 IN DWORD nLength,
1677 IN COORD dwWriteCoord,
1678 OUT LPDWORD lpNumberOfCharsWritten)
1679 {
1680 CODE_ELEMENT Code;
1681 Code.UnicodeChar = cCharacter;
1682 return IntFillConsoleOutputCode(hConsoleOutput,
1683 CODE_UNICODE,
1684 Code,
1685 nLength,
1686 dwWriteCoord,
1687 lpNumberOfCharsWritten);
1688 }
1689
1690
1691 /*
1692 * @implemented
1693 */
1694 BOOL
1695 WINAPI
1696 DECLSPEC_HOTPATCH
1697 FillConsoleOutputCharacterA(IN HANDLE hConsoleOutput,
1698 IN CHAR cCharacter,
1699 IN DWORD nLength,
1700 IN COORD dwWriteCoord,
1701 LPDWORD lpNumberOfCharsWritten)
1702 {
1703 CODE_ELEMENT Code;
1704 Code.AsciiChar = cCharacter;
1705 return IntFillConsoleOutputCode(hConsoleOutput,
1706 CODE_ASCII,
1707 Code,
1708 nLength,
1709 dwWriteCoord,
1710 lpNumberOfCharsWritten);
1711 }
1712
1713
1714 /*
1715 * @implemented
1716 */
1717 BOOL
1718 WINAPI
1719 DECLSPEC_HOTPATCH
1720 FillConsoleOutputAttribute(IN HANDLE hConsoleOutput,
1721 IN WORD wAttribute,
1722 IN DWORD nLength,
1723 IN COORD dwWriteCoord,
1724 OUT LPDWORD lpNumberOfAttrsWritten)
1725 {
1726 CODE_ELEMENT Code;
1727 Code.Attribute = wAttribute;
1728 return IntFillConsoleOutputCode(hConsoleOutput,
1729 CODE_ATTRIBUTE,
1730 Code,
1731 nLength,
1732 dwWriteCoord,
1733 lpNumberOfAttrsWritten);
1734 }
1735
1736 /* EOF */