Fix merge r65567.
[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 DPRINT1("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 = ReadOutputRequest->ReadRegion.Right -
440 ReadOutputRequest->ReadRegion.Left + 1;
441
442 for (y = 0, Y = ReadOutputRequest->ReadRegion.Top; Y <= ReadOutputRequest->ReadRegion.Bottom; ++y, ++Y)
443 {
444 RtlCopyMemory(lpBuffer + (y + dwBufferCoord.Y) * dwBufferSize.X + dwBufferCoord.X,
445 ReadOutputRequest->CharInfo + y * SizeX,
446 SizeX * sizeof(CHAR_INFO));
447 #if 0
448 for (x = 0, X = ReadOutputRequest->ReadRegion.Left; X <= ReadOutputRequest->ReadRegion.Right; ++x, ++X)
449 {
450 *(lpBuffer + (y + dwBufferCoord.Y) * dwBufferSize.X + (x + dwBufferCoord.X)) =
451 *(ReadOutputRequest->CharInfo + y * SizeX + x);
452 }
453 #endif
454 }
455 }
456 else
457 {
458 BaseSetLastNTError(ApiMessage.Status);
459 }
460 }
461 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
462 {
463 SetLastError(ERROR_INVALID_ACCESS);
464 Success = FALSE;
465 }
466 _SEH2_END;
467
468 /* Release the capture buffer if needed */
469 if (CaptureBuffer) CsrFreeCaptureBuffer(CaptureBuffer);
470
471 /* Return success status */
472 return Success;
473 }
474
475
476 static
477 BOOL
478 IntReadConsoleOutputCode(IN HANDLE hConsoleOutput,
479 IN CODE_TYPE CodeType,
480 OUT PVOID pCode,
481 IN DWORD nLength,
482 IN COORD dwReadCoord,
483 OUT LPDWORD lpNumberOfCodesRead)
484 {
485 BOOL Success;
486 CONSOLE_API_MESSAGE ApiMessage;
487 PCONSOLE_READOUTPUTCODE ReadOutputCodeRequest = &ApiMessage.Data.ReadOutputCodeRequest;
488 PCSR_CAPTURE_BUFFER CaptureBuffer = NULL;
489 ULONG CodeSize, SizeBytes;
490
491 DPRINT("IntReadConsoleOutputCode\n");
492
493 if ( (CodeType != CODE_ASCII ) &&
494 (CodeType != CODE_UNICODE ) &&
495 (CodeType != CODE_ATTRIBUTE) )
496 {
497 SetLastError(ERROR_INVALID_PARAMETER);
498 return FALSE;
499 }
500
501 /* Set up the data to send to the Console Server */
502 ReadOutputCodeRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
503 ReadOutputCodeRequest->OutputHandle = hConsoleOutput;
504 ReadOutputCodeRequest->Coord = dwReadCoord;
505 ReadOutputCodeRequest->NumCodes = nLength;
506
507 /* Determine the needed size */
508 ReadOutputCodeRequest->CodeType = CodeType;
509 switch (CodeType)
510 {
511 case CODE_ASCII:
512 CodeSize = RTL_FIELD_SIZE(CODE_ELEMENT, AsciiChar);
513 break;
514
515 case CODE_UNICODE:
516 CodeSize = RTL_FIELD_SIZE(CODE_ELEMENT, UnicodeChar);
517 break;
518
519 case CODE_ATTRIBUTE:
520 CodeSize = RTL_FIELD_SIZE(CODE_ELEMENT, Attribute);
521 break;
522 }
523 SizeBytes = nLength * CodeSize;
524
525 /*
526 * For optimization purposes, Windows (and hence ReactOS, too, for
527 * compatibility reasons) uses a static buffer if no more than eighty
528 * bytes are read. Otherwise a new buffer is allocated.
529 * This behaviour is also expected in the server-side.
530 */
531 if (SizeBytes <= sizeof(ReadOutputCodeRequest->CodeStaticBuffer))
532 {
533 ReadOutputCodeRequest->pCode = ReadOutputCodeRequest->CodeStaticBuffer;
534 // CaptureBuffer = NULL;
535 }
536 else
537 {
538 /* Allocate a Capture Buffer */
539 CaptureBuffer = CsrAllocateCaptureBuffer(1, SizeBytes);
540 if (CaptureBuffer == NULL)
541 {
542 DPRINT1("CsrAllocateCaptureBuffer failed!\n");
543 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
544 return FALSE;
545 }
546
547 /* Allocate space in the Buffer */
548 CsrAllocateMessagePointer(CaptureBuffer,
549 SizeBytes,
550 (PVOID*)&ReadOutputCodeRequest->pCode);
551 }
552
553 /* Call the server */
554 CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
555 CaptureBuffer,
556 CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepReadConsoleOutputString),
557 sizeof(*ReadOutputCodeRequest));
558
559 /* Check for success */
560 Success = NT_SUCCESS(ApiMessage.Status);
561
562 /* Retrieve the results */
563 _SEH2_TRY
564 {
565 *lpNumberOfCodesRead = ReadOutputCodeRequest->NumCodes;
566
567 if (Success)
568 {
569 RtlCopyMemory(pCode,
570 ReadOutputCodeRequest->pCode,
571 ReadOutputCodeRequest->NumCodes * CodeSize);
572 }
573 else
574 {
575 BaseSetLastNTError(ApiMessage.Status);
576 }
577 }
578 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
579 {
580 SetLastError(ERROR_INVALID_ACCESS);
581 Success = FALSE;
582 }
583 _SEH2_END;
584
585 /* Release the capture buffer if needed */
586 if (CaptureBuffer) CsrFreeCaptureBuffer(CaptureBuffer);
587
588 /* Return success status */
589 return Success;
590 }
591
592
593 /*******************
594 * Write functions *
595 *******************/
596
597 static
598 BOOL
599 IntWriteConsole(IN HANDLE hConsoleOutput,
600 IN PVOID lpBuffer,
601 IN DWORD nNumberOfCharsToWrite,
602 OUT LPDWORD lpNumberOfCharsWritten,
603 LPVOID lpReserved,
604 IN BOOLEAN bUnicode)
605 {
606 BOOL Success;
607 CONSOLE_API_MESSAGE ApiMessage;
608 PCONSOLE_WRITECONSOLE WriteConsoleRequest = &ApiMessage.Data.WriteConsoleRequest;
609 PCSR_CAPTURE_BUFFER CaptureBuffer = NULL;
610 ULONG CharSize, SizeBytes;
611
612 DPRINT("IntWriteConsole\n");
613
614 /* Set up the data to send to the Console Server */
615 WriteConsoleRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
616 WriteConsoleRequest->OutputHandle = hConsoleOutput;
617 WriteConsoleRequest->Unicode = bUnicode;
618
619 /* Those members are unused by the client, on Windows */
620 WriteConsoleRequest->Reserved1 = 0;
621 // WriteConsoleRequest->Reserved2 = {0};
622
623 /* Determine the needed size */
624 CharSize = (bUnicode ? sizeof(WCHAR) : sizeof(CHAR));
625 SizeBytes = nNumberOfCharsToWrite * CharSize;
626
627 WriteConsoleRequest->NumBytes = SizeBytes;
628
629 /*
630 * For optimization purposes, Windows (and hence ReactOS, too, for
631 * compatibility reasons) uses a static buffer if no more than eighty
632 * bytes are written. Otherwise a new buffer is allocated.
633 * This behaviour is also expected in the server-side.
634 */
635 if (SizeBytes <= sizeof(WriteConsoleRequest->StaticBuffer))
636 {
637 WriteConsoleRequest->Buffer = WriteConsoleRequest->StaticBuffer;
638 // CaptureBuffer = NULL;
639 WriteConsoleRequest->UsingStaticBuffer = TRUE;
640
641 _SEH2_TRY
642 {
643 RtlCopyMemory(WriteConsoleRequest->Buffer,
644 lpBuffer,
645 SizeBytes);
646 }
647 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
648 {
649 SetLastError(ERROR_INVALID_ACCESS);
650 _SEH2_YIELD(return FALSE);
651 }
652 _SEH2_END;
653 }
654 else
655 {
656 /* Allocate a Capture Buffer */
657 CaptureBuffer = CsrAllocateCaptureBuffer(1, SizeBytes);
658 if (CaptureBuffer == NULL)
659 {
660 DPRINT1("CsrAllocateCaptureBuffer failed!\n");
661 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
662 return FALSE;
663 }
664
665 /* Capture the buffer to write */
666 CsrCaptureMessageBuffer(CaptureBuffer,
667 (PVOID)lpBuffer,
668 SizeBytes,
669 (PVOID*)&WriteConsoleRequest->Buffer);
670 WriteConsoleRequest->UsingStaticBuffer = FALSE;
671 }
672
673 /* Call the server */
674 CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
675 CaptureBuffer,
676 CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepWriteConsole),
677 sizeof(*WriteConsoleRequest));
678
679 /* Check for success */
680 Success = NT_SUCCESS(ApiMessage.Status);
681
682 /* Release the capture buffer if needed */
683 if (CaptureBuffer) CsrFreeCaptureBuffer(CaptureBuffer);
684
685 /* Retrieve the results */
686 if (Success)
687 {
688 _SEH2_TRY
689 {
690 *lpNumberOfCharsWritten = WriteConsoleRequest->NumBytes / CharSize;
691 }
692 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
693 {
694 SetLastError(ERROR_INVALID_ACCESS);
695 Success = FALSE;
696 }
697 _SEH2_END;
698 }
699 else
700 {
701 BaseSetLastNTError(ApiMessage.Status);
702 }
703
704 /* Return success status */
705 return Success;
706 }
707
708
709 static
710 BOOL
711 IntWriteConsoleInput(IN HANDLE hConsoleInput,
712 IN PINPUT_RECORD lpBuffer,
713 IN DWORD nLength,
714 OUT LPDWORD lpNumberOfEventsWritten,
715 IN BOOLEAN bUnicode,
716 IN BOOLEAN bAppendToEnd)
717 {
718 BOOL Success;
719 CONSOLE_API_MESSAGE ApiMessage;
720 PCONSOLE_WRITEINPUT WriteInputRequest = &ApiMessage.Data.WriteInputRequest;
721 PCSR_CAPTURE_BUFFER CaptureBuffer = NULL;
722
723 DPRINT("IntWriteConsoleInput: %lx %p\n", nLength, lpNumberOfEventsWritten);
724
725 /* Set up the data to send to the Console Server */
726 WriteInputRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
727 WriteInputRequest->InputHandle = hConsoleInput;
728 WriteInputRequest->NumRecords = nLength;
729 WriteInputRequest->Unicode = bUnicode;
730 WriteInputRequest->AppendToEnd = bAppendToEnd;
731
732 /*
733 * For optimization purposes, Windows (and hence ReactOS, too, for
734 * compatibility reasons) uses a static buffer if no more than five
735 * input records are written. Otherwise a new buffer is allocated.
736 * This behaviour is also expected in the server-side.
737 */
738 if (nLength <= sizeof(WriteInputRequest->RecordStaticBuffer)/sizeof(INPUT_RECORD))
739 {
740 WriteInputRequest->RecordBufPtr = WriteInputRequest->RecordStaticBuffer;
741 // CaptureBuffer = NULL;
742
743 _SEH2_TRY
744 {
745 RtlCopyMemory(WriteInputRequest->RecordBufPtr,
746 lpBuffer,
747 nLength * sizeof(INPUT_RECORD));
748 }
749 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
750 {
751 SetLastError(ERROR_INVALID_ACCESS);
752 _SEH2_YIELD(return FALSE);
753 }
754 _SEH2_END;
755 }
756 else
757 {
758 ULONG Size = nLength * sizeof(INPUT_RECORD);
759
760 /* Allocate a Capture Buffer */
761 CaptureBuffer = CsrAllocateCaptureBuffer(1, Size);
762 if (CaptureBuffer == NULL)
763 {
764 DPRINT1("CsrAllocateCaptureBuffer failed!\n");
765 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
766 return FALSE;
767 }
768
769 /* Capture the user buffer */
770 CsrCaptureMessageBuffer(CaptureBuffer,
771 lpBuffer,
772 Size,
773 (PVOID*)&WriteInputRequest->RecordBufPtr);
774 }
775
776 /* Call the server */
777 CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
778 CaptureBuffer,
779 CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepWriteConsoleInput),
780 sizeof(*WriteInputRequest));
781
782 /* Check for success */
783 Success = NT_SUCCESS(ApiMessage.Status);
784
785 /* Release the capture buffer if needed */
786 if (CaptureBuffer) CsrFreeCaptureBuffer(CaptureBuffer);
787
788 /* Retrieve the results */
789 _SEH2_TRY
790 {
791 DPRINT("Events written: %lx\n", WriteInputRequest->NumRecords);
792 *lpNumberOfEventsWritten = WriteInputRequest->NumRecords;
793
794 if (!Success)
795 BaseSetLastNTError(ApiMessage.Status);
796 }
797 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
798 {
799 SetLastError(ERROR_INVALID_ACCESS);
800 Success = FALSE;
801 }
802 _SEH2_END;
803
804 /* Return success status */
805 return Success;
806 }
807
808
809 static
810 BOOL
811 IntWriteConsoleOutput(IN HANDLE hConsoleOutput,
812 IN CONST CHAR_INFO *lpBuffer,
813 IN COORD dwBufferSize,
814 IN COORD dwBufferCoord,
815 IN OUT PSMALL_RECT lpWriteRegion,
816 IN BOOLEAN bUnicode)
817 {
818 BOOL Success;
819 CONSOLE_API_MESSAGE ApiMessage;
820 PCONSOLE_WRITEOUTPUT WriteOutputRequest = &ApiMessage.Data.WriteOutputRequest;
821 PCSR_CAPTURE_BUFFER CaptureBuffer = NULL;
822
823 SHORT SizeX, SizeY;
824 ULONG NumCells;
825
826 /* Set up the data to send to the Console Server */
827 WriteOutputRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
828 WriteOutputRequest->OutputHandle = hConsoleOutput;
829 WriteOutputRequest->Unicode = bUnicode;
830
831 /* Update lpWriteRegion */
832 _SEH2_TRY
833 {
834 SizeX = min(dwBufferSize.X - dwBufferCoord.X, ConioRectWidth(lpWriteRegion));
835 SizeY = min(dwBufferSize.Y - dwBufferCoord.Y, ConioRectHeight(lpWriteRegion));
836 if (SizeX <= 0 || SizeY <= 0)
837 {
838 SetLastError(ERROR_INVALID_PARAMETER);
839 _SEH2_YIELD(return FALSE);
840 }
841 lpWriteRegion->Right = lpWriteRegion->Left + SizeX - 1;
842 lpWriteRegion->Bottom = lpWriteRegion->Top + SizeY - 1;
843
844 WriteOutputRequest->WriteRegion = *lpWriteRegion;
845 }
846 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
847 {
848 SetLastError(ERROR_INVALID_ACCESS);
849 _SEH2_YIELD(return FALSE);
850 }
851 _SEH2_END;
852
853 NumCells = SizeX * SizeY;
854 DPRINT("IntWriteConsoleOutput: (%d x %d)\n", SizeX, SizeY);
855
856 /*
857 * For optimization purposes, Windows (and hence ReactOS, too, for
858 * compatibility reasons) uses a static buffer if no more than one
859 * cell is written. Otherwise a new buffer is allocated.
860 * This behaviour is also expected in the server-side.
861 */
862 if (NumCells <= 1)
863 {
864 WriteOutputRequest->CharInfo = &WriteOutputRequest->StaticBuffer;
865 // CaptureBuffer = NULL;
866 WriteOutputRequest->UseVirtualMemory = FALSE;
867 }
868 else
869 {
870 ULONG Size = NumCells * sizeof(CHAR_INFO);
871
872 /* Allocate a Capture Buffer */
873 CaptureBuffer = CsrAllocateCaptureBuffer(1, Size);
874 if (CaptureBuffer)
875 {
876 /* Allocate space in the Buffer */
877 CsrAllocateMessagePointer(CaptureBuffer,
878 Size,
879 (PVOID*)&WriteOutputRequest->CharInfo);
880 WriteOutputRequest->UseVirtualMemory = FALSE;
881 }
882 else
883 {
884 /*
885 * CsrAllocateCaptureBuffer failed because we tried to allocate
886 * a too large (>= 64 kB, size of the CSR heap) data buffer.
887 * To circumvent this, Windows uses a trick (that we reproduce for
888 * compatibility reasons): we allocate a heap buffer in the process'
889 * memory, and CSR will read it via NtReadVirtualMemory.
890 */
891 DPRINT1("CsrAllocateCaptureBuffer failed with size %ld, let's use local heap buffer...\n", Size);
892
893 WriteOutputRequest->CharInfo = RtlAllocateHeap(RtlGetProcessHeap(), 0, Size);
894 WriteOutputRequest->UseVirtualMemory = TRUE;
895
896 /* Bail out if we still cannot allocate memory */
897 if (WriteOutputRequest->CharInfo == NULL)
898 {
899 DPRINT1("Failed to allocate heap buffer with size %ld!\n", Size);
900 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
901 return FALSE;
902 }
903 }
904 }
905
906 /* Capture the user buffer contents */
907 _SEH2_TRY
908 {
909 #if 0
910 SHORT x, X;
911 #endif
912 SHORT y, Y;
913
914 /* Copy into the buffer */
915
916 SizeX = WriteOutputRequest->WriteRegion.Right -
917 WriteOutputRequest->WriteRegion.Left + 1;
918
919 for (y = 0, Y = WriteOutputRequest->WriteRegion.Top; Y <= WriteOutputRequest->WriteRegion.Bottom; ++y, ++Y)
920 {
921 RtlCopyMemory(WriteOutputRequest->CharInfo + y * SizeX,
922 lpBuffer + (y + dwBufferCoord.Y) * dwBufferSize.X + dwBufferCoord.X,
923 SizeX * sizeof(CHAR_INFO));
924 #if 0
925 for (x = 0, X = WriteOutputRequest->WriteRegion.Left; X <= WriteOutputRequest->WriteRegion.Right; ++x, ++X)
926 {
927 *(WriteOutputRequest->CharInfo + y * SizeX + x) =
928 *(lpBuffer + (y + dwBufferCoord.Y) * dwBufferSize.X + (x + dwBufferCoord.X));
929 }
930 #endif
931 }
932 }
933 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
934 {
935 SetLastError(ERROR_INVALID_ACCESS);
936 _SEH2_YIELD(return FALSE);
937 }
938 _SEH2_END;
939
940 /* Call the server */
941 CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
942 CaptureBuffer,
943 CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepWriteConsoleOutput),
944 sizeof(*WriteOutputRequest));
945
946 /* Check for success */
947 Success = NT_SUCCESS(ApiMessage.Status);
948
949 /* Release the capture buffer if needed */
950 if (CaptureBuffer)
951 {
952 CsrFreeCaptureBuffer(CaptureBuffer);
953 }
954 else
955 {
956 /* If we used a heap buffer, free it */
957 if (WriteOutputRequest->UseVirtualMemory)
958 RtlFreeHeap(RtlGetProcessHeap(), 0, WriteOutputRequest->CharInfo);
959 }
960
961 /* Retrieve the results */
962 _SEH2_TRY
963 {
964 *lpWriteRegion = WriteOutputRequest->WriteRegion;
965
966 if (!Success)
967 BaseSetLastNTError(ApiMessage.Status);
968 }
969 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
970 {
971 SetLastError(ERROR_INVALID_ACCESS);
972 Success = FALSE;
973 }
974 _SEH2_END;
975
976 /* Return success status */
977 return Success;
978 }
979
980
981 static
982 BOOL
983 IntWriteConsoleOutputCode(IN HANDLE hConsoleOutput,
984 IN CODE_TYPE CodeType,
985 IN CONST VOID *pCode,
986 IN DWORD nLength,
987 IN COORD dwWriteCoord,
988 OUT LPDWORD lpNumberOfCodesWritten)
989 {
990 BOOL Success;
991 CONSOLE_API_MESSAGE ApiMessage;
992 PCONSOLE_WRITEOUTPUTCODE WriteOutputCodeRequest = &ApiMessage.Data.WriteOutputCodeRequest;
993 PCSR_CAPTURE_BUFFER CaptureBuffer = NULL;
994 ULONG CodeSize, SizeBytes;
995
996 if ( (CodeType != CODE_ASCII ) &&
997 (CodeType != CODE_UNICODE ) &&
998 (CodeType != CODE_ATTRIBUTE) )
999 {
1000 SetLastError(ERROR_INVALID_PARAMETER);
1001 return FALSE;
1002 }
1003
1004 DPRINT("IntWriteConsoleOutputCode\n");
1005
1006 /* Set up the data to send to the Console Server */
1007 WriteOutputCodeRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
1008 WriteOutputCodeRequest->OutputHandle = hConsoleOutput;
1009 WriteOutputCodeRequest->Coord = dwWriteCoord;
1010 WriteOutputCodeRequest->NumCodes = nLength;
1011
1012 /* Determine the needed size */
1013 WriteOutputCodeRequest->CodeType = CodeType;
1014 switch (CodeType)
1015 {
1016 case CODE_ASCII:
1017 CodeSize = RTL_FIELD_SIZE(CODE_ELEMENT, AsciiChar);
1018 break;
1019
1020 case CODE_UNICODE:
1021 CodeSize = RTL_FIELD_SIZE(CODE_ELEMENT, UnicodeChar);
1022 break;
1023
1024 case CODE_ATTRIBUTE:
1025 CodeSize = RTL_FIELD_SIZE(CODE_ELEMENT, Attribute);
1026 break;
1027 }
1028 SizeBytes = nLength * CodeSize;
1029
1030 /*
1031 * For optimization purposes, Windows (and hence ReactOS, too, for
1032 * compatibility reasons) uses a static buffer if no more than eighty
1033 * bytes are written. Otherwise a new buffer is allocated.
1034 * This behaviour is also expected in the server-side.
1035 */
1036 if (SizeBytes <= sizeof(WriteOutputCodeRequest->CodeStaticBuffer))
1037 {
1038 WriteOutputCodeRequest->pCode = WriteOutputCodeRequest->CodeStaticBuffer;
1039 // CaptureBuffer = NULL;
1040
1041 _SEH2_TRY
1042 {
1043 RtlCopyMemory(WriteOutputCodeRequest->pCode,
1044 pCode,
1045 SizeBytes);
1046 }
1047 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1048 {
1049 SetLastError(ERROR_INVALID_ACCESS);
1050 _SEH2_YIELD(return FALSE);
1051 }
1052 _SEH2_END;
1053 }
1054 else
1055 {
1056 /* Allocate a Capture Buffer */
1057 CaptureBuffer = CsrAllocateCaptureBuffer(1, SizeBytes);
1058 if (CaptureBuffer == NULL)
1059 {
1060 DPRINT1("CsrAllocateCaptureBuffer failed!\n");
1061 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1062 return FALSE;
1063 }
1064
1065 /* Capture the buffer to write */
1066 CsrCaptureMessageBuffer(CaptureBuffer,
1067 (PVOID)pCode,
1068 SizeBytes,
1069 (PVOID*)&WriteOutputCodeRequest->pCode);
1070 }
1071
1072 /* Call the server */
1073 CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
1074 CaptureBuffer,
1075 CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepWriteConsoleOutputString),
1076 sizeof(*WriteOutputCodeRequest));
1077
1078 /* Check for success */
1079 Success = NT_SUCCESS(ApiMessage.Status);
1080
1081 /* Release the capture buffer if needed */
1082 if (CaptureBuffer) CsrFreeCaptureBuffer(CaptureBuffer);
1083
1084 /* Retrieve the results */
1085 _SEH2_TRY
1086 {
1087 *lpNumberOfCodesWritten = WriteOutputCodeRequest->NumCodes;
1088
1089 if (!Success)
1090 BaseSetLastNTError(ApiMessage.Status);
1091 }
1092 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1093 {
1094 SetLastError(ERROR_INVALID_ACCESS);
1095 Success = FALSE;
1096 }
1097 _SEH2_END;
1098
1099 /* Return success status */
1100 return Success;
1101 }
1102
1103
1104 static
1105 BOOL
1106 IntFillConsoleOutputCode(IN HANDLE hConsoleOutput,
1107 IN CODE_TYPE CodeType,
1108 IN CODE_ELEMENT Code,
1109 IN DWORD nLength,
1110 IN COORD dwWriteCoord,
1111 OUT LPDWORD lpNumberOfCodesWritten)
1112 {
1113 BOOL Success;
1114 CONSOLE_API_MESSAGE ApiMessage;
1115 PCONSOLE_FILLOUTPUTCODE FillOutputRequest = &ApiMessage.Data.FillOutputRequest;
1116
1117 DPRINT("IntFillConsoleOutputCode\n");
1118
1119 if ( (CodeType != CODE_ASCII ) &&
1120 (CodeType != CODE_UNICODE ) &&
1121 (CodeType != CODE_ATTRIBUTE) )
1122 {
1123 SetLastError(ERROR_INVALID_PARAMETER);
1124 return FALSE;
1125 }
1126
1127 /* Set up the data to send to the Console Server */
1128 FillOutputRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
1129 FillOutputRequest->OutputHandle = hConsoleOutput;
1130 FillOutputRequest->WriteCoord = dwWriteCoord;
1131 FillOutputRequest->CodeType = CodeType;
1132 FillOutputRequest->Code = Code;
1133 FillOutputRequest->NumCodes = nLength;
1134
1135 /* Call the server */
1136 CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
1137 NULL,
1138 CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepFillConsoleOutput),
1139 sizeof(*FillOutputRequest));
1140
1141 /* Check for success */
1142 Success = NT_SUCCESS(ApiMessage.Status);
1143
1144 /* Retrieve the results */
1145 _SEH2_TRY
1146 {
1147 *lpNumberOfCodesWritten = FillOutputRequest->NumCodes;
1148
1149 if (!Success)
1150 BaseSetLastNTError(ApiMessage.Status);
1151 }
1152 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1153 {
1154 SetLastError(ERROR_INVALID_ACCESS);
1155 Success = FALSE;
1156 }
1157 _SEH2_END;
1158
1159 /* Return success status */
1160 return Success;
1161 }
1162
1163
1164 /* FUNCTIONS ******************************************************************/
1165
1166 /******************
1167 * Read functions *
1168 ******************/
1169
1170 /*
1171 * @implemented
1172 */
1173 BOOL
1174 WINAPI
1175 DECLSPEC_HOTPATCH
1176 ReadConsoleW(IN HANDLE hConsoleInput,
1177 OUT LPVOID lpBuffer,
1178 IN DWORD nNumberOfCharsToRead,
1179 OUT LPDWORD lpNumberOfCharsRead,
1180 IN PCONSOLE_READCONSOLE_CONTROL pInputControl OPTIONAL)
1181 {
1182 return IntReadConsole(hConsoleInput,
1183 lpBuffer,
1184 nNumberOfCharsToRead,
1185 lpNumberOfCharsRead,
1186 pInputControl,
1187 TRUE);
1188 }
1189
1190
1191 /*
1192 * @implemented
1193 */
1194 BOOL
1195 WINAPI
1196 DECLSPEC_HOTPATCH
1197 ReadConsoleA(IN HANDLE hConsoleInput,
1198 OUT LPVOID lpBuffer,
1199 IN DWORD nNumberOfCharsToRead,
1200 OUT LPDWORD lpNumberOfCharsRead,
1201 IN PCONSOLE_READCONSOLE_CONTROL pInputControl OPTIONAL)
1202 {
1203 return IntReadConsole(hConsoleInput,
1204 lpBuffer,
1205 nNumberOfCharsToRead,
1206 lpNumberOfCharsRead,
1207 NULL,
1208 FALSE);
1209 }
1210
1211
1212 /*
1213 * @implemented
1214 */
1215 BOOL
1216 WINAPI
1217 DECLSPEC_HOTPATCH
1218 PeekConsoleInputW(IN HANDLE hConsoleInput,
1219 OUT PINPUT_RECORD lpBuffer,
1220 IN DWORD nLength,
1221 OUT LPDWORD lpNumberOfEventsRead)
1222 {
1223 return IntGetConsoleInput(hConsoleInput,
1224 lpBuffer,
1225 nLength,
1226 lpNumberOfEventsRead,
1227 CONSOLE_READ_KEEPEVENT | CONSOLE_READ_CONTINUE,
1228 TRUE);
1229 }
1230
1231
1232 /*
1233 * @implemented
1234 */
1235 BOOL
1236 WINAPI
1237 DECLSPEC_HOTPATCH
1238 PeekConsoleInputA(IN HANDLE hConsoleInput,
1239 OUT PINPUT_RECORD lpBuffer,
1240 IN DWORD nLength,
1241 OUT LPDWORD lpNumberOfEventsRead)
1242 {
1243 return IntGetConsoleInput(hConsoleInput,
1244 lpBuffer,
1245 nLength,
1246 lpNumberOfEventsRead,
1247 CONSOLE_READ_KEEPEVENT | CONSOLE_READ_CONTINUE,
1248 FALSE);
1249 }
1250
1251
1252 /*
1253 * @implemented
1254 */
1255 BOOL
1256 WINAPI
1257 DECLSPEC_HOTPATCH
1258 ReadConsoleInputW(IN HANDLE hConsoleInput,
1259 OUT PINPUT_RECORD lpBuffer,
1260 IN DWORD nLength,
1261 OUT LPDWORD lpNumberOfEventsRead)
1262 {
1263 return IntGetConsoleInput(hConsoleInput,
1264 lpBuffer,
1265 nLength,
1266 lpNumberOfEventsRead,
1267 0,
1268 TRUE);
1269 }
1270
1271
1272 /*
1273 * @implemented
1274 */
1275 BOOL
1276 WINAPI
1277 DECLSPEC_HOTPATCH
1278 ReadConsoleInputA(IN HANDLE hConsoleInput,
1279 OUT PINPUT_RECORD lpBuffer,
1280 IN DWORD nLength,
1281 OUT LPDWORD lpNumberOfEventsRead)
1282 {
1283 return IntGetConsoleInput(hConsoleInput,
1284 lpBuffer,
1285 nLength,
1286 lpNumberOfEventsRead,
1287 0,
1288 FALSE);
1289 }
1290
1291
1292 /*
1293 * @implemented
1294 */
1295 BOOL
1296 WINAPI
1297 DECLSPEC_HOTPATCH
1298 ReadConsoleInputExW(IN HANDLE hConsoleInput,
1299 OUT PINPUT_RECORD lpBuffer,
1300 IN DWORD nLength,
1301 OUT LPDWORD lpNumberOfEventsRead,
1302 IN WORD wFlags)
1303 {
1304 return IntGetConsoleInput(hConsoleInput,
1305 lpBuffer,
1306 nLength,
1307 lpNumberOfEventsRead,
1308 wFlags,
1309 TRUE);
1310 }
1311
1312
1313 /*
1314 * @implemented
1315 */
1316 BOOL
1317 WINAPI
1318 DECLSPEC_HOTPATCH
1319 ReadConsoleInputExA(IN HANDLE hConsoleInput,
1320 OUT PINPUT_RECORD lpBuffer,
1321 IN DWORD nLength,
1322 OUT LPDWORD lpNumberOfEventsRead,
1323 IN WORD wFlags)
1324 {
1325 return IntGetConsoleInput(hConsoleInput,
1326 lpBuffer,
1327 nLength,
1328 lpNumberOfEventsRead,
1329 wFlags,
1330 FALSE);
1331 }
1332
1333
1334 /*
1335 * @implemented
1336 */
1337 BOOL
1338 WINAPI
1339 DECLSPEC_HOTPATCH
1340 ReadConsoleOutputW(IN HANDLE hConsoleOutput,
1341 OUT PCHAR_INFO lpBuffer,
1342 IN COORD dwBufferSize,
1343 IN COORD dwBufferCoord,
1344 IN OUT PSMALL_RECT lpReadRegion)
1345 {
1346 return IntReadConsoleOutput(hConsoleOutput,
1347 lpBuffer,
1348 dwBufferSize,
1349 dwBufferCoord,
1350 lpReadRegion,
1351 TRUE);
1352 }
1353
1354
1355 /*
1356 * @implemented
1357 */
1358 BOOL
1359 WINAPI
1360 DECLSPEC_HOTPATCH
1361 ReadConsoleOutputA(IN HANDLE hConsoleOutput,
1362 OUT PCHAR_INFO lpBuffer,
1363 IN COORD dwBufferSize,
1364 IN COORD dwBufferCoord,
1365 IN OUT PSMALL_RECT lpReadRegion)
1366 {
1367 return IntReadConsoleOutput(hConsoleOutput,
1368 lpBuffer,
1369 dwBufferSize,
1370 dwBufferCoord,
1371 lpReadRegion,
1372 FALSE);
1373 }
1374
1375
1376 /*
1377 * @implemented
1378 */
1379 BOOL
1380 WINAPI
1381 DECLSPEC_HOTPATCH
1382 ReadConsoleOutputCharacterW(IN HANDLE hConsoleOutput,
1383 OUT LPWSTR lpCharacter,
1384 IN DWORD nLength,
1385 IN COORD dwReadCoord,
1386 OUT LPDWORD lpNumberOfCharsRead)
1387 {
1388 return IntReadConsoleOutputCode(hConsoleOutput,
1389 CODE_UNICODE,
1390 lpCharacter,
1391 nLength,
1392 dwReadCoord,
1393 lpNumberOfCharsRead);
1394 }
1395
1396
1397 /*
1398 * @implemented
1399 */
1400 BOOL
1401 WINAPI
1402 DECLSPEC_HOTPATCH
1403 ReadConsoleOutputCharacterA(IN HANDLE hConsoleOutput,
1404 OUT LPSTR lpCharacter,
1405 IN DWORD nLength,
1406 IN COORD dwReadCoord,
1407 OUT LPDWORD lpNumberOfCharsRead)
1408 {
1409 return IntReadConsoleOutputCode(hConsoleOutput,
1410 CODE_ASCII,
1411 lpCharacter,
1412 nLength,
1413 dwReadCoord,
1414 lpNumberOfCharsRead);
1415 }
1416
1417
1418 /*
1419 * @implemented
1420 */
1421 BOOL
1422 WINAPI
1423 DECLSPEC_HOTPATCH
1424 ReadConsoleOutputAttribute(IN HANDLE hConsoleOutput,
1425 OUT LPWORD lpAttribute,
1426 IN DWORD nLength,
1427 IN COORD dwReadCoord,
1428 OUT LPDWORD lpNumberOfAttrsRead)
1429 {
1430 return IntReadConsoleOutputCode(hConsoleOutput,
1431 CODE_ATTRIBUTE,
1432 lpAttribute,
1433 nLength,
1434 dwReadCoord,
1435 lpNumberOfAttrsRead);
1436 }
1437
1438
1439 /*******************
1440 * Write functions *
1441 *******************/
1442
1443 /*
1444 * @implemented
1445 */
1446 BOOL
1447 WINAPI
1448 DECLSPEC_HOTPATCH
1449 WriteConsoleW(IN HANDLE hConsoleOutput,
1450 IN CONST VOID *lpBuffer,
1451 IN DWORD nNumberOfCharsToWrite,
1452 OUT LPDWORD lpNumberOfCharsWritten,
1453 LPVOID lpReserved)
1454 {
1455 return IntWriteConsole(hConsoleOutput,
1456 (PVOID)lpBuffer,
1457 nNumberOfCharsToWrite,
1458 lpNumberOfCharsWritten,
1459 lpReserved,
1460 TRUE);
1461 }
1462
1463
1464 /*
1465 * @implemented
1466 */
1467 BOOL
1468 WINAPI
1469 DECLSPEC_HOTPATCH
1470 WriteConsoleA(IN HANDLE hConsoleOutput,
1471 IN CONST VOID *lpBuffer,
1472 IN DWORD nNumberOfCharsToWrite,
1473 OUT LPDWORD lpNumberOfCharsWritten,
1474 LPVOID lpReserved)
1475 {
1476 return IntWriteConsole(hConsoleOutput,
1477 (PVOID)lpBuffer,
1478 nNumberOfCharsToWrite,
1479 lpNumberOfCharsWritten,
1480 lpReserved,
1481 FALSE);
1482 }
1483
1484
1485 /*
1486 * @implemented
1487 */
1488 BOOL
1489 WINAPI
1490 DECLSPEC_HOTPATCH
1491 WriteConsoleInputW(IN HANDLE hConsoleInput,
1492 IN CONST INPUT_RECORD *lpBuffer,
1493 IN DWORD nLength,
1494 OUT LPDWORD lpNumberOfEventsWritten)
1495 {
1496 return IntWriteConsoleInput(hConsoleInput,
1497 (PINPUT_RECORD)lpBuffer,
1498 nLength,
1499 lpNumberOfEventsWritten,
1500 TRUE,
1501 TRUE);
1502 }
1503
1504
1505 /*
1506 * @implemented
1507 */
1508 BOOL
1509 WINAPI
1510 DECLSPEC_HOTPATCH
1511 WriteConsoleInputA(IN HANDLE hConsoleInput,
1512 IN CONST INPUT_RECORD *lpBuffer,
1513 IN DWORD nLength,
1514 OUT LPDWORD lpNumberOfEventsWritten)
1515 {
1516 return IntWriteConsoleInput(hConsoleInput,
1517 (PINPUT_RECORD)lpBuffer,
1518 nLength,
1519 lpNumberOfEventsWritten,
1520 FALSE,
1521 TRUE);
1522 }
1523
1524
1525 /*
1526 * @implemented
1527 */
1528 BOOL
1529 WINAPI
1530 DECLSPEC_HOTPATCH
1531 WriteConsoleInputVDMW(IN HANDLE hConsoleInput,
1532 IN CONST INPUT_RECORD *lpBuffer,
1533 IN DWORD nLength,
1534 OUT LPDWORD lpNumberOfEventsWritten)
1535 {
1536 return IntWriteConsoleInput(hConsoleInput,
1537 (PINPUT_RECORD)lpBuffer,
1538 nLength,
1539 lpNumberOfEventsWritten,
1540 TRUE,
1541 FALSE);
1542 }
1543
1544
1545 /*
1546 * @implemented
1547 */
1548 BOOL
1549 WINAPI
1550 DECLSPEC_HOTPATCH
1551 WriteConsoleInputVDMA(IN HANDLE hConsoleInput,
1552 IN CONST INPUT_RECORD *lpBuffer,
1553 IN DWORD nLength,
1554 OUT LPDWORD lpNumberOfEventsWritten)
1555 {
1556 return IntWriteConsoleInput(hConsoleInput,
1557 (PINPUT_RECORD)lpBuffer,
1558 nLength,
1559 lpNumberOfEventsWritten,
1560 FALSE,
1561 FALSE);
1562 }
1563
1564
1565 /*
1566 * @implemented
1567 */
1568 BOOL
1569 WINAPI
1570 DECLSPEC_HOTPATCH
1571 WriteConsoleOutputW(IN HANDLE hConsoleOutput,
1572 IN CONST CHAR_INFO *lpBuffer,
1573 IN COORD dwBufferSize,
1574 IN COORD dwBufferCoord,
1575 IN OUT PSMALL_RECT lpWriteRegion)
1576 {
1577 return IntWriteConsoleOutput(hConsoleOutput,
1578 lpBuffer,
1579 dwBufferSize,
1580 dwBufferCoord,
1581 lpWriteRegion,
1582 TRUE);
1583 }
1584
1585
1586 /*
1587 * @implemented
1588 */
1589 BOOL
1590 WINAPI
1591 DECLSPEC_HOTPATCH
1592 WriteConsoleOutputA(IN HANDLE hConsoleOutput,
1593 IN CONST CHAR_INFO *lpBuffer,
1594 IN COORD dwBufferSize,
1595 IN COORD dwBufferCoord,
1596 IN OUT PSMALL_RECT lpWriteRegion)
1597 {
1598 return IntWriteConsoleOutput(hConsoleOutput,
1599 lpBuffer,
1600 dwBufferSize,
1601 dwBufferCoord,
1602 lpWriteRegion,
1603 FALSE);
1604 }
1605
1606
1607 /*
1608 * @implemented
1609 */
1610 BOOL
1611 WINAPI
1612 DECLSPEC_HOTPATCH
1613 WriteConsoleOutputCharacterW(IN HANDLE hConsoleOutput,
1614 IN LPCWSTR lpCharacter,
1615 IN DWORD nLength,
1616 IN COORD dwWriteCoord,
1617 OUT LPDWORD lpNumberOfCharsWritten)
1618 {
1619 return IntWriteConsoleOutputCode(hConsoleOutput,
1620 CODE_UNICODE,
1621 lpCharacter,
1622 nLength,
1623 dwWriteCoord,
1624 lpNumberOfCharsWritten);
1625 }
1626
1627
1628 /*
1629 * @implemented
1630 */
1631 BOOL
1632 WINAPI
1633 DECLSPEC_HOTPATCH
1634 WriteConsoleOutputCharacterA(IN HANDLE hConsoleOutput,
1635 IN LPCSTR lpCharacter,
1636 IN DWORD nLength,
1637 IN COORD dwWriteCoord,
1638 OUT LPDWORD lpNumberOfCharsWritten)
1639 {
1640 return IntWriteConsoleOutputCode(hConsoleOutput,
1641 CODE_ASCII,
1642 lpCharacter,
1643 nLength,
1644 dwWriteCoord,
1645 lpNumberOfCharsWritten);
1646 }
1647
1648
1649 /*
1650 * @implemented
1651 */
1652 BOOL
1653 WINAPI
1654 DECLSPEC_HOTPATCH
1655 WriteConsoleOutputAttribute(IN HANDLE hConsoleOutput,
1656 IN CONST WORD *lpAttribute,
1657 IN DWORD nLength,
1658 IN COORD dwWriteCoord,
1659 OUT LPDWORD lpNumberOfAttrsWritten)
1660 {
1661 return IntWriteConsoleOutputCode(hConsoleOutput,
1662 CODE_ATTRIBUTE,
1663 lpAttribute,
1664 nLength,
1665 dwWriteCoord,
1666 lpNumberOfAttrsWritten);
1667 }
1668
1669
1670 /*
1671 * @implemented
1672 */
1673 BOOL
1674 WINAPI
1675 DECLSPEC_HOTPATCH
1676 FillConsoleOutputCharacterW(IN HANDLE hConsoleOutput,
1677 IN WCHAR cCharacter,
1678 IN DWORD nLength,
1679 IN COORD dwWriteCoord,
1680 OUT LPDWORD lpNumberOfCharsWritten)
1681 {
1682 CODE_ELEMENT Code;
1683 Code.UnicodeChar = cCharacter;
1684 return IntFillConsoleOutputCode(hConsoleOutput,
1685 CODE_UNICODE,
1686 Code,
1687 nLength,
1688 dwWriteCoord,
1689 lpNumberOfCharsWritten);
1690 }
1691
1692
1693 /*
1694 * @implemented
1695 */
1696 BOOL
1697 WINAPI
1698 DECLSPEC_HOTPATCH
1699 FillConsoleOutputCharacterA(IN HANDLE hConsoleOutput,
1700 IN CHAR cCharacter,
1701 IN DWORD nLength,
1702 IN COORD dwWriteCoord,
1703 LPDWORD lpNumberOfCharsWritten)
1704 {
1705 CODE_ELEMENT Code;
1706 Code.AsciiChar = cCharacter;
1707 return IntFillConsoleOutputCode(hConsoleOutput,
1708 CODE_ASCII,
1709 Code,
1710 nLength,
1711 dwWriteCoord,
1712 lpNumberOfCharsWritten);
1713 }
1714
1715
1716 /*
1717 * @implemented
1718 */
1719 BOOL
1720 WINAPI
1721 DECLSPEC_HOTPATCH
1722 FillConsoleOutputAttribute(IN HANDLE hConsoleOutput,
1723 IN WORD wAttribute,
1724 IN DWORD nLength,
1725 IN COORD dwWriteCoord,
1726 OUT LPDWORD lpNumberOfAttrsWritten)
1727 {
1728 CODE_ELEMENT Code;
1729 Code.Attribute = wAttribute;
1730 return IntFillConsoleOutputCode(hConsoleOutput,
1731 CODE_ATTRIBUTE,
1732 Code,
1733 nLength,
1734 dwWriteCoord,
1735 lpNumberOfAttrsWritten);
1736 }
1737
1738 /* EOF */