* Sync up to trunk head (r64894).
[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 ReadConsoleW(IN HANDLE hConsoleInput,
1176 OUT LPVOID lpBuffer,
1177 IN DWORD nNumberOfCharsToRead,
1178 OUT LPDWORD lpNumberOfCharsRead,
1179 IN PCONSOLE_READCONSOLE_CONTROL pInputControl OPTIONAL)
1180 {
1181 return IntReadConsole(hConsoleInput,
1182 lpBuffer,
1183 nNumberOfCharsToRead,
1184 lpNumberOfCharsRead,
1185 pInputControl,
1186 TRUE);
1187 }
1188
1189
1190 /*
1191 * @implemented
1192 */
1193 BOOL
1194 WINAPI
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 PeekConsoleInputW(IN HANDLE hConsoleInput,
1216 OUT PINPUT_RECORD lpBuffer,
1217 IN DWORD nLength,
1218 OUT LPDWORD lpNumberOfEventsRead)
1219 {
1220 return IntGetConsoleInput(hConsoleInput,
1221 lpBuffer,
1222 nLength,
1223 lpNumberOfEventsRead,
1224 CONSOLE_READ_KEEPEVENT | CONSOLE_READ_CONTINUE,
1225 TRUE);
1226 }
1227
1228
1229 /*
1230 * @implemented
1231 */
1232 BOOL
1233 WINAPI
1234 PeekConsoleInputA(IN HANDLE hConsoleInput,
1235 OUT PINPUT_RECORD lpBuffer,
1236 IN DWORD nLength,
1237 OUT LPDWORD lpNumberOfEventsRead)
1238 {
1239 return IntGetConsoleInput(hConsoleInput,
1240 lpBuffer,
1241 nLength,
1242 lpNumberOfEventsRead,
1243 CONSOLE_READ_KEEPEVENT | CONSOLE_READ_CONTINUE,
1244 FALSE);
1245 }
1246
1247
1248 /*
1249 * @implemented
1250 */
1251 BOOL
1252 WINAPI
1253 ReadConsoleInputW(IN HANDLE hConsoleInput,
1254 OUT PINPUT_RECORD lpBuffer,
1255 IN DWORD nLength,
1256 OUT LPDWORD lpNumberOfEventsRead)
1257 {
1258 return IntGetConsoleInput(hConsoleInput,
1259 lpBuffer,
1260 nLength,
1261 lpNumberOfEventsRead,
1262 0,
1263 TRUE);
1264 }
1265
1266
1267 /*
1268 * @implemented
1269 */
1270 BOOL
1271 WINAPI
1272 ReadConsoleInputA(IN HANDLE hConsoleInput,
1273 OUT PINPUT_RECORD lpBuffer,
1274 IN DWORD nLength,
1275 OUT LPDWORD lpNumberOfEventsRead)
1276 {
1277 return IntGetConsoleInput(hConsoleInput,
1278 lpBuffer,
1279 nLength,
1280 lpNumberOfEventsRead,
1281 0,
1282 FALSE);
1283 }
1284
1285
1286 /*
1287 * @implemented
1288 */
1289 BOOL
1290 WINAPI
1291 ReadConsoleInputExW(IN HANDLE hConsoleInput,
1292 OUT PINPUT_RECORD lpBuffer,
1293 IN DWORD nLength,
1294 OUT LPDWORD lpNumberOfEventsRead,
1295 IN WORD wFlags)
1296 {
1297 return IntGetConsoleInput(hConsoleInput,
1298 lpBuffer,
1299 nLength,
1300 lpNumberOfEventsRead,
1301 wFlags,
1302 TRUE);
1303 }
1304
1305
1306 /*
1307 * @implemented
1308 */
1309 BOOL
1310 WINAPI
1311 ReadConsoleInputExA(IN HANDLE hConsoleInput,
1312 OUT PINPUT_RECORD lpBuffer,
1313 IN DWORD nLength,
1314 OUT LPDWORD lpNumberOfEventsRead,
1315 IN WORD wFlags)
1316 {
1317 return IntGetConsoleInput(hConsoleInput,
1318 lpBuffer,
1319 nLength,
1320 lpNumberOfEventsRead,
1321 wFlags,
1322 FALSE);
1323 }
1324
1325
1326 /*
1327 * @implemented
1328 */
1329 BOOL
1330 WINAPI
1331 ReadConsoleOutputW(IN HANDLE hConsoleOutput,
1332 OUT PCHAR_INFO lpBuffer,
1333 IN COORD dwBufferSize,
1334 IN COORD dwBufferCoord,
1335 IN OUT PSMALL_RECT lpReadRegion)
1336 {
1337 return IntReadConsoleOutput(hConsoleOutput,
1338 lpBuffer,
1339 dwBufferSize,
1340 dwBufferCoord,
1341 lpReadRegion,
1342 TRUE);
1343 }
1344
1345
1346 /*
1347 * @implemented
1348 */
1349 BOOL
1350 WINAPI
1351 ReadConsoleOutputA(IN HANDLE hConsoleOutput,
1352 OUT PCHAR_INFO lpBuffer,
1353 IN COORD dwBufferSize,
1354 IN COORD dwBufferCoord,
1355 IN OUT PSMALL_RECT lpReadRegion)
1356 {
1357 return IntReadConsoleOutput(hConsoleOutput,
1358 lpBuffer,
1359 dwBufferSize,
1360 dwBufferCoord,
1361 lpReadRegion,
1362 FALSE);
1363 }
1364
1365
1366 /*
1367 * @implemented
1368 */
1369 BOOL
1370 WINAPI
1371 ReadConsoleOutputCharacterW(IN HANDLE hConsoleOutput,
1372 OUT LPWSTR lpCharacter,
1373 IN DWORD nLength,
1374 IN COORD dwReadCoord,
1375 OUT LPDWORD lpNumberOfCharsRead)
1376 {
1377 return IntReadConsoleOutputCode(hConsoleOutput,
1378 CODE_UNICODE,
1379 lpCharacter,
1380 nLength,
1381 dwReadCoord,
1382 lpNumberOfCharsRead);
1383 }
1384
1385
1386 /*
1387 * @implemented
1388 */
1389 BOOL
1390 WINAPI
1391 ReadConsoleOutputCharacterA(IN HANDLE hConsoleOutput,
1392 OUT LPSTR lpCharacter,
1393 IN DWORD nLength,
1394 IN COORD dwReadCoord,
1395 OUT LPDWORD lpNumberOfCharsRead)
1396 {
1397 return IntReadConsoleOutputCode(hConsoleOutput,
1398 CODE_ASCII,
1399 lpCharacter,
1400 nLength,
1401 dwReadCoord,
1402 lpNumberOfCharsRead);
1403 }
1404
1405
1406 /*
1407 * @implemented
1408 */
1409 BOOL
1410 WINAPI
1411 ReadConsoleOutputAttribute(IN HANDLE hConsoleOutput,
1412 OUT LPWORD lpAttribute,
1413 IN DWORD nLength,
1414 IN COORD dwReadCoord,
1415 OUT LPDWORD lpNumberOfAttrsRead)
1416 {
1417 return IntReadConsoleOutputCode(hConsoleOutput,
1418 CODE_ATTRIBUTE,
1419 lpAttribute,
1420 nLength,
1421 dwReadCoord,
1422 lpNumberOfAttrsRead);
1423 }
1424
1425
1426 /*******************
1427 * Write functions *
1428 *******************/
1429
1430 /*
1431 * @implemented
1432 */
1433 BOOL
1434 WINAPI
1435 WriteConsoleW(IN HANDLE hConsoleOutput,
1436 IN CONST VOID *lpBuffer,
1437 IN DWORD nNumberOfCharsToWrite,
1438 OUT LPDWORD lpNumberOfCharsWritten,
1439 LPVOID lpReserved)
1440 {
1441 return IntWriteConsole(hConsoleOutput,
1442 (PVOID)lpBuffer,
1443 nNumberOfCharsToWrite,
1444 lpNumberOfCharsWritten,
1445 lpReserved,
1446 TRUE);
1447 }
1448
1449
1450 /*
1451 * @implemented
1452 */
1453 BOOL
1454 WINAPI
1455 WriteConsoleA(IN HANDLE hConsoleOutput,
1456 IN CONST VOID *lpBuffer,
1457 IN DWORD nNumberOfCharsToWrite,
1458 OUT LPDWORD lpNumberOfCharsWritten,
1459 LPVOID lpReserved)
1460 {
1461 return IntWriteConsole(hConsoleOutput,
1462 (PVOID)lpBuffer,
1463 nNumberOfCharsToWrite,
1464 lpNumberOfCharsWritten,
1465 lpReserved,
1466 FALSE);
1467 }
1468
1469
1470 /*
1471 * @implemented
1472 */
1473 BOOL
1474 WINAPI
1475 WriteConsoleInputW(IN HANDLE hConsoleInput,
1476 IN CONST INPUT_RECORD *lpBuffer,
1477 IN DWORD nLength,
1478 OUT LPDWORD lpNumberOfEventsWritten)
1479 {
1480 return IntWriteConsoleInput(hConsoleInput,
1481 (PINPUT_RECORD)lpBuffer,
1482 nLength,
1483 lpNumberOfEventsWritten,
1484 TRUE,
1485 TRUE);
1486 }
1487
1488
1489 /*
1490 * @implemented
1491 */
1492 BOOL
1493 WINAPI
1494 WriteConsoleInputA(IN HANDLE hConsoleInput,
1495 IN CONST INPUT_RECORD *lpBuffer,
1496 IN DWORD nLength,
1497 OUT LPDWORD lpNumberOfEventsWritten)
1498 {
1499 return IntWriteConsoleInput(hConsoleInput,
1500 (PINPUT_RECORD)lpBuffer,
1501 nLength,
1502 lpNumberOfEventsWritten,
1503 FALSE,
1504 TRUE);
1505 }
1506
1507
1508 /*
1509 * @implemented
1510 */
1511 BOOL
1512 WINAPI
1513 WriteConsoleInputVDMW(IN HANDLE hConsoleInput,
1514 IN CONST INPUT_RECORD *lpBuffer,
1515 IN DWORD nLength,
1516 OUT LPDWORD lpNumberOfEventsWritten)
1517 {
1518 return IntWriteConsoleInput(hConsoleInput,
1519 (PINPUT_RECORD)lpBuffer,
1520 nLength,
1521 lpNumberOfEventsWritten,
1522 TRUE,
1523 FALSE);
1524 }
1525
1526
1527 /*
1528 * @implemented
1529 */
1530 BOOL
1531 WINAPI
1532 WriteConsoleInputVDMA(IN HANDLE hConsoleInput,
1533 IN CONST INPUT_RECORD *lpBuffer,
1534 IN DWORD nLength,
1535 OUT LPDWORD lpNumberOfEventsWritten)
1536 {
1537 return IntWriteConsoleInput(hConsoleInput,
1538 (PINPUT_RECORD)lpBuffer,
1539 nLength,
1540 lpNumberOfEventsWritten,
1541 FALSE,
1542 FALSE);
1543 }
1544
1545
1546 /*
1547 * @implemented
1548 */
1549 BOOL
1550 WINAPI
1551 WriteConsoleOutputW(IN HANDLE hConsoleOutput,
1552 IN CONST CHAR_INFO *lpBuffer,
1553 IN COORD dwBufferSize,
1554 IN COORD dwBufferCoord,
1555 IN OUT PSMALL_RECT lpWriteRegion)
1556 {
1557 return IntWriteConsoleOutput(hConsoleOutput,
1558 lpBuffer,
1559 dwBufferSize,
1560 dwBufferCoord,
1561 lpWriteRegion,
1562 TRUE);
1563 }
1564
1565
1566 /*
1567 * @implemented
1568 */
1569 BOOL
1570 WINAPI
1571 WriteConsoleOutputA(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 FALSE);
1583 }
1584
1585
1586 /*
1587 * @implemented
1588 */
1589 BOOL
1590 WINAPI
1591 WriteConsoleOutputCharacterW(IN HANDLE hConsoleOutput,
1592 IN LPCWSTR lpCharacter,
1593 IN DWORD nLength,
1594 IN COORD dwWriteCoord,
1595 OUT LPDWORD lpNumberOfCharsWritten)
1596 {
1597 return IntWriteConsoleOutputCode(hConsoleOutput,
1598 CODE_UNICODE,
1599 lpCharacter,
1600 nLength,
1601 dwWriteCoord,
1602 lpNumberOfCharsWritten);
1603 }
1604
1605
1606 /*
1607 * @implemented
1608 */
1609 BOOL
1610 WINAPI
1611 WriteConsoleOutputCharacterA(IN HANDLE hConsoleOutput,
1612 IN LPCSTR lpCharacter,
1613 IN DWORD nLength,
1614 IN COORD dwWriteCoord,
1615 OUT LPDWORD lpNumberOfCharsWritten)
1616 {
1617 return IntWriteConsoleOutputCode(hConsoleOutput,
1618 CODE_ASCII,
1619 lpCharacter,
1620 nLength,
1621 dwWriteCoord,
1622 lpNumberOfCharsWritten);
1623 }
1624
1625
1626 /*
1627 * @implemented
1628 */
1629 BOOL
1630 WINAPI
1631 WriteConsoleOutputAttribute(IN HANDLE hConsoleOutput,
1632 IN CONST WORD *lpAttribute,
1633 IN DWORD nLength,
1634 IN COORD dwWriteCoord,
1635 OUT LPDWORD lpNumberOfAttrsWritten)
1636 {
1637 return IntWriteConsoleOutputCode(hConsoleOutput,
1638 CODE_ATTRIBUTE,
1639 lpAttribute,
1640 nLength,
1641 dwWriteCoord,
1642 lpNumberOfAttrsWritten);
1643 }
1644
1645
1646 /*
1647 * @implemented
1648 */
1649 BOOL
1650 WINAPI
1651 FillConsoleOutputCharacterW(IN HANDLE hConsoleOutput,
1652 IN WCHAR cCharacter,
1653 IN DWORD nLength,
1654 IN COORD dwWriteCoord,
1655 OUT LPDWORD lpNumberOfCharsWritten)
1656 {
1657 CODE_ELEMENT Code;
1658 Code.UnicodeChar = cCharacter;
1659 return IntFillConsoleOutputCode(hConsoleOutput,
1660 CODE_UNICODE,
1661 Code,
1662 nLength,
1663 dwWriteCoord,
1664 lpNumberOfCharsWritten);
1665 }
1666
1667
1668 /*
1669 * @implemented
1670 */
1671 BOOL
1672 WINAPI
1673 FillConsoleOutputCharacterA(IN HANDLE hConsoleOutput,
1674 IN CHAR cCharacter,
1675 IN DWORD nLength,
1676 IN COORD dwWriteCoord,
1677 LPDWORD lpNumberOfCharsWritten)
1678 {
1679 CODE_ELEMENT Code;
1680 Code.AsciiChar = cCharacter;
1681 return IntFillConsoleOutputCode(hConsoleOutput,
1682 CODE_ASCII,
1683 Code,
1684 nLength,
1685 dwWriteCoord,
1686 lpNumberOfCharsWritten);
1687 }
1688
1689
1690 /*
1691 * @implemented
1692 */
1693 BOOL
1694 WINAPI
1695 FillConsoleOutputAttribute(IN HANDLE hConsoleOutput,
1696 IN WORD wAttribute,
1697 IN DWORD nLength,
1698 IN COORD dwWriteCoord,
1699 OUT LPDWORD lpNumberOfAttrsWritten)
1700 {
1701 CODE_ELEMENT Code;
1702 Code.Attribute = wAttribute;
1703 return IntFillConsoleOutputCode(hConsoleOutput,
1704 CODE_ATTRIBUTE,
1705 Code,
1706 nLength,
1707 dwWriteCoord,
1708 lpNumberOfAttrsWritten);
1709 }
1710
1711 /* EOF */