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