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
IntReadConsole(IN HANDLE hConsoleInput,OUT PVOID lpBuffer,IN DWORD nNumberOfCharsToRead,OUT LPDWORD lpNumberOfCharsRead,IN PCONSOLE_READCONSOLE_CONTROL pInputControl OPTIONAL,IN BOOLEAN bUnicode)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
IntGetConsoleInput(IN HANDLE hConsoleInput,OUT PINPUT_RECORD lpBuffer,IN DWORD nLength,OUT LPDWORD lpNumberOfEventsRead,IN WORD wFlags,IN BOOLEAN bUnicode)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
IntReadConsoleOutput(IN HANDLE hConsoleOutput,OUT PCHAR_INFO lpBuffer,IN COORD dwBufferSize,IN COORD dwBufferCoord,IN OUT PSMALL_RECT lpReadRegion,IN BOOLEAN bUnicode)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
IntReadConsoleOutputCode(IN HANDLE hConsoleOutput,IN CODE_TYPE CodeType,OUT PVOID pCode,IN DWORD nLength,IN COORD dwReadCoord,OUT LPDWORD lpNumberOfCodesRead)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
IntWriteConsole(IN HANDLE hConsoleOutput,IN PVOID lpBuffer,IN DWORD nNumberOfCharsToWrite,OUT LPDWORD lpNumberOfCharsWritten,LPVOID lpReserved,IN BOOLEAN bUnicode)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
IntWriteConsoleInput(IN HANDLE hConsoleInput,IN PINPUT_RECORD lpBuffer,IN DWORD nLength,OUT LPDWORD lpNumberOfEventsWritten,IN BOOLEAN bUnicode,IN BOOLEAN bAppendToEnd)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
IntWriteConsoleOutput(IN HANDLE hConsoleOutput,IN CONST CHAR_INFO * lpBuffer,IN COORD dwBufferSize,IN COORD dwBufferCoord,IN OUT PSMALL_RECT lpWriteRegion,IN BOOLEAN bUnicode)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
IntWriteConsoleOutputCode(IN HANDLE hConsoleOutput,IN CODE_TYPE CodeType,IN CONST VOID * pCode,IN DWORD nLength,IN COORD dwWriteCoord,OUT LPDWORD lpNumberOfCodesWritten)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
IntFillConsoleOutputCode(IN HANDLE hConsoleOutput,IN CODE_TYPE CodeType,IN CODE_ELEMENT Code,IN DWORD nLength,IN COORD dwWriteCoord,OUT LPDWORD lpNumberOfCodesWritten)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
ReadConsoleW(IN HANDLE hConsoleInput,OUT LPVOID lpBuffer,IN DWORD nNumberOfCharsToRead,OUT LPDWORD lpNumberOfCharsRead,IN PCONSOLE_READCONSOLE_CONTROL pInputControl OPTIONAL)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
ReadConsoleA(IN HANDLE hConsoleInput,OUT LPVOID lpBuffer,IN DWORD nNumberOfCharsToRead,OUT LPDWORD lpNumberOfCharsRead,IN PCONSOLE_READCONSOLE_CONTROL pInputControl OPTIONAL)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
PeekConsoleInputW(IN HANDLE hConsoleInput,OUT PINPUT_RECORD lpBuffer,IN DWORD nLength,OUT LPDWORD lpNumberOfEventsRead)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_NOREMOVE | CONSOLE_READ_NOWAIT,
1226 TRUE);
1227 }
1228
1229
1230 /*
1231 * @implemented
1232 */
1233 BOOL
1234 WINAPI
1235 DECLSPEC_HOTPATCH
PeekConsoleInputA(IN HANDLE hConsoleInput,OUT PINPUT_RECORD lpBuffer,IN DWORD nLength,OUT LPDWORD lpNumberOfEventsRead)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_NOREMOVE | CONSOLE_READ_NOWAIT,
1246 FALSE);
1247 }
1248
1249
1250 /*
1251 * @implemented
1252 */
1253 BOOL
1254 WINAPI
1255 DECLSPEC_HOTPATCH
ReadConsoleInputW(IN HANDLE hConsoleInput,OUT PINPUT_RECORD lpBuffer,IN DWORD nLength,OUT LPDWORD lpNumberOfEventsRead)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
ReadConsoleInputA(IN HANDLE hConsoleInput,OUT PINPUT_RECORD lpBuffer,IN DWORD nLength,OUT LPDWORD lpNumberOfEventsRead)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
ReadConsoleInputExW(IN HANDLE hConsoleInput,OUT PINPUT_RECORD lpBuffer,IN DWORD nLength,OUT LPDWORD lpNumberOfEventsRead,IN WORD wFlags)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
ReadConsoleInputExA(IN HANDLE hConsoleInput,OUT PINPUT_RECORD lpBuffer,IN DWORD nLength,OUT LPDWORD lpNumberOfEventsRead,IN WORD wFlags)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
ReadConsoleOutputW(IN HANDLE hConsoleOutput,OUT PCHAR_INFO lpBuffer,IN COORD dwBufferSize,IN COORD dwBufferCoord,IN OUT PSMALL_RECT lpReadRegion)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
ReadConsoleOutputA(IN HANDLE hConsoleOutput,OUT PCHAR_INFO lpBuffer,IN COORD dwBufferSize,IN COORD dwBufferCoord,IN OUT PSMALL_RECT lpReadRegion)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
ReadConsoleOutputCharacterW(IN HANDLE hConsoleOutput,OUT LPWSTR lpCharacter,IN DWORD nLength,IN COORD dwReadCoord,OUT LPDWORD lpNumberOfCharsRead)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
ReadConsoleOutputCharacterA(IN HANDLE hConsoleOutput,OUT LPSTR lpCharacter,IN DWORD nLength,IN COORD dwReadCoord,OUT LPDWORD lpNumberOfCharsRead)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
ReadConsoleOutputAttribute(IN HANDLE hConsoleOutput,OUT LPWORD lpAttribute,IN DWORD nLength,IN COORD dwReadCoord,OUT LPDWORD lpNumberOfAttrsRead)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
WriteConsoleW(IN HANDLE hConsoleOutput,IN CONST VOID * lpBuffer,IN DWORD nNumberOfCharsToWrite,OUT LPDWORD lpNumberOfCharsWritten,LPVOID lpReserved)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
WriteConsoleA(IN HANDLE hConsoleOutput,IN CONST VOID * lpBuffer,IN DWORD nNumberOfCharsToWrite,OUT LPDWORD lpNumberOfCharsWritten,LPVOID lpReserved)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
WriteConsoleInputW(IN HANDLE hConsoleInput,IN CONST INPUT_RECORD * lpBuffer,IN DWORD nLength,OUT LPDWORD lpNumberOfEventsWritten)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
WriteConsoleInputA(IN HANDLE hConsoleInput,IN CONST INPUT_RECORD * lpBuffer,IN DWORD nLength,OUT LPDWORD lpNumberOfEventsWritten)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
WriteConsoleInputVDMW(IN HANDLE hConsoleInput,IN CONST INPUT_RECORD * lpBuffer,IN DWORD nLength,OUT LPDWORD lpNumberOfEventsWritten)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
WriteConsoleInputVDMA(IN HANDLE hConsoleInput,IN CONST INPUT_RECORD * lpBuffer,IN DWORD nLength,OUT LPDWORD lpNumberOfEventsWritten)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
WriteConsoleOutputW(IN HANDLE hConsoleOutput,IN CONST CHAR_INFO * lpBuffer,IN COORD dwBufferSize,IN COORD dwBufferCoord,IN OUT PSMALL_RECT lpWriteRegion)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
WriteConsoleOutputA(IN HANDLE hConsoleOutput,IN CONST CHAR_INFO * lpBuffer,IN COORD dwBufferSize,IN COORD dwBufferCoord,IN OUT PSMALL_RECT lpWriteRegion)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
WriteConsoleOutputCharacterW(IN HANDLE hConsoleOutput,IN LPCWSTR lpCharacter,IN DWORD nLength,IN COORD dwWriteCoord,OUT LPDWORD lpNumberOfCharsWritten)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
WriteConsoleOutputCharacterA(IN HANDLE hConsoleOutput,IN LPCSTR lpCharacter,IN DWORD nLength,IN COORD dwWriteCoord,OUT LPDWORD lpNumberOfCharsWritten)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
WriteConsoleOutputAttribute(IN HANDLE hConsoleOutput,IN CONST WORD * lpAttribute,IN DWORD nLength,IN COORD dwWriteCoord,OUT LPDWORD lpNumberOfAttrsWritten)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
FillConsoleOutputCharacterW(IN HANDLE hConsoleOutput,IN WCHAR cCharacter,IN DWORD nLength,IN COORD dwWriteCoord,OUT LPDWORD lpNumberOfCharsWritten)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
FillConsoleOutputCharacterA(IN HANDLE hConsoleOutput,IN CHAR cCharacter,IN DWORD nLength,IN COORD dwWriteCoord,LPDWORD lpNumberOfCharsWritten)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
FillConsoleOutputAttribute(IN HANDLE hConsoleOutput,IN WORD wAttribute,IN DWORD nLength,IN COORD dwWriteCoord,OUT LPDWORD lpNumberOfAttrsWritten)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 */
1737