[KERNEL32]
[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 DPRINT1("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 DPRINT1("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 }
885 else
886 {
887 ULONG Size = NumCells * sizeof(CHAR_INFO);
888
889 /* Allocate a Capture Buffer */
890 CaptureBuffer = CsrAllocateCaptureBuffer(1, Size);
891 if (CaptureBuffer == NULL)
892 {
893 DPRINT1("CsrAllocateCaptureBuffer failed with size %ld!\n", Size);
894 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
895 return FALSE;
896 }
897
898 /* Allocate space in the Buffer */
899 CsrAllocateMessagePointer(CaptureBuffer,
900 Size,
901 (PVOID*)&WriteOutputRequest->CharInfo);
902 }
903
904 /* Capture the user buffer contents */
905 _SEH2_TRY
906 {
907 #if 0
908 SHORT x, X;
909 #endif
910 SHORT y, Y;
911
912 /* Copy into the buffer */
913
914 SizeX = WriteOutputRequest->WriteRegion.Right -
915 WriteOutputRequest->WriteRegion.Left + 1;
916
917 for (y = 0, Y = WriteOutputRequest->WriteRegion.Top; Y <= WriteOutputRequest->WriteRegion.Bottom; ++y, ++Y)
918 {
919 RtlCopyMemory(WriteOutputRequest->CharInfo + y * SizeX,
920 lpBuffer + (y + dwBufferCoord.Y) * dwBufferSize.X + dwBufferCoord.X,
921 SizeX * sizeof(CHAR_INFO));
922 #if 0
923 for (x = 0, X = WriteOutputRequest->WriteRegion.Left; X <= WriteOutputRequest->WriteRegion.Right; ++x, ++X)
924 {
925 *(WriteOutputRequest->CharInfo + y * SizeX + x) =
926 *(lpBuffer + (y + dwBufferCoord.Y) * dwBufferSize.X + (x + dwBufferCoord.X));
927 }
928 #endif
929 }
930 }
931 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
932 {
933 SetLastError(ERROR_INVALID_ACCESS);
934 _SEH2_YIELD(return FALSE);
935 }
936 _SEH2_END;
937
938 /* Call the server */
939 CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
940 CaptureBuffer,
941 CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepWriteConsoleOutput),
942 sizeof(*WriteOutputRequest));
943
944 /* Check for success */
945 Success = NT_SUCCESS(ApiMessage.Status);
946
947 /* Release the capture buffer if needed */
948 if (CaptureBuffer) CsrFreeCaptureBuffer(CaptureBuffer);
949
950 /* Retrieve the results */
951 _SEH2_TRY
952 {
953 *lpWriteRegion = WriteOutputRequest->WriteRegion;
954
955 if (!Success)
956 BaseSetLastNTError(ApiMessage.Status);
957 }
958 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
959 {
960 SetLastError(ERROR_INVALID_ACCESS);
961 Success = FALSE;
962 }
963 _SEH2_END;
964
965 /* Return success status */
966 return Success;
967 }
968
969
970 static
971 BOOL
972 IntWriteConsoleOutputCode(IN HANDLE hConsoleOutput,
973 IN CODE_TYPE CodeType,
974 IN CONST VOID *pCode,
975 IN DWORD nLength,
976 IN COORD dwWriteCoord,
977 OUT LPDWORD lpNumberOfCodesWritten)
978 {
979 BOOL Success;
980 CONSOLE_API_MESSAGE ApiMessage;
981 PCONSOLE_WRITEOUTPUTCODE WriteOutputCodeRequest = &ApiMessage.Data.WriteOutputCodeRequest;
982 PCSR_CAPTURE_BUFFER CaptureBuffer = NULL;
983 ULONG CodeSize, SizeBytes;
984
985 if ( (CodeType != CODE_ASCII ) &&
986 (CodeType != CODE_UNICODE ) &&
987 (CodeType != CODE_ATTRIBUTE) )
988 {
989 SetLastError(ERROR_INVALID_PARAMETER);
990 return FALSE;
991 }
992
993 DPRINT("IntWriteConsoleOutputCode\n");
994
995 /* Set up the data to send to the Console Server */
996 WriteOutputCodeRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
997 WriteOutputCodeRequest->OutputHandle = hConsoleOutput;
998 WriteOutputCodeRequest->Coord = dwWriteCoord;
999 WriteOutputCodeRequest->NumCodes = nLength;
1000
1001 /* Determine the needed size */
1002 WriteOutputCodeRequest->CodeType = CodeType;
1003 switch (CodeType)
1004 {
1005 case CODE_ASCII:
1006 CodeSize = RTL_FIELD_SIZE(CODE_ELEMENT, AsciiChar);
1007 break;
1008
1009 case CODE_UNICODE:
1010 CodeSize = RTL_FIELD_SIZE(CODE_ELEMENT, UnicodeChar);
1011 break;
1012
1013 case CODE_ATTRIBUTE:
1014 CodeSize = RTL_FIELD_SIZE(CODE_ELEMENT, Attribute);
1015 break;
1016 }
1017 SizeBytes = nLength * CodeSize;
1018
1019 /*
1020 * For optimization purposes, Windows (and hence ReactOS, too, for
1021 * compatibility reasons) uses a static buffer if no more than eighty
1022 * bytes are written. Otherwise a new buffer is allocated.
1023 * This behaviour is also expected in the server-side.
1024 */
1025 if (SizeBytes <= sizeof(WriteOutputCodeRequest->CodeStaticBuffer))
1026 {
1027 WriteOutputCodeRequest->pCode = WriteOutputCodeRequest->CodeStaticBuffer;
1028 // CaptureBuffer = NULL;
1029
1030 _SEH2_TRY
1031 {
1032 RtlCopyMemory(WriteOutputCodeRequest->pCode,
1033 pCode,
1034 SizeBytes);
1035 }
1036 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1037 {
1038 SetLastError(ERROR_INVALID_ACCESS);
1039 _SEH2_YIELD(return FALSE);
1040 }
1041 _SEH2_END;
1042 }
1043 else
1044 {
1045 /* Allocate a Capture Buffer */
1046 CaptureBuffer = CsrAllocateCaptureBuffer(1, SizeBytes);
1047 if (CaptureBuffer == NULL)
1048 {
1049 DPRINT1("CsrAllocateCaptureBuffer failed!\n");
1050 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1051 return FALSE;
1052 }
1053
1054 /* Capture the buffer to write */
1055 CsrCaptureMessageBuffer(CaptureBuffer,
1056 (PVOID)pCode,
1057 SizeBytes,
1058 (PVOID*)&WriteOutputCodeRequest->pCode);
1059 }
1060
1061 /* Call the server */
1062 CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
1063 CaptureBuffer,
1064 CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepWriteConsoleOutputString),
1065 sizeof(*WriteOutputCodeRequest));
1066
1067 /* Check for success */
1068 Success = NT_SUCCESS(ApiMessage.Status);
1069
1070 /* Release the capture buffer if needed */
1071 if (CaptureBuffer) CsrFreeCaptureBuffer(CaptureBuffer);
1072
1073 /* Retrieve the results */
1074 _SEH2_TRY
1075 {
1076 *lpNumberOfCodesWritten = WriteOutputCodeRequest->NumCodes;
1077
1078 if (!Success)
1079 BaseSetLastNTError(ApiMessage.Status);
1080 }
1081 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1082 {
1083 SetLastError(ERROR_INVALID_ACCESS);
1084 Success = FALSE;
1085 }
1086 _SEH2_END;
1087
1088 /* Return success status */
1089 return Success;
1090 }
1091
1092
1093 static
1094 BOOL
1095 IntFillConsoleOutputCode(IN HANDLE hConsoleOutput,
1096 IN CODE_TYPE CodeType,
1097 IN CODE_ELEMENT Code,
1098 IN DWORD nLength,
1099 IN COORD dwWriteCoord,
1100 OUT LPDWORD lpNumberOfCodesWritten)
1101 {
1102 BOOL Success;
1103 CONSOLE_API_MESSAGE ApiMessage;
1104 PCONSOLE_FILLOUTPUTCODE FillOutputRequest = &ApiMessage.Data.FillOutputRequest;
1105
1106 DPRINT("IntFillConsoleOutputCode\n");
1107
1108 if ( (CodeType != CODE_ASCII ) &&
1109 (CodeType != CODE_UNICODE ) &&
1110 (CodeType != CODE_ATTRIBUTE) )
1111 {
1112 SetLastError(ERROR_INVALID_PARAMETER);
1113 return FALSE;
1114 }
1115
1116 /* Set up the data to send to the Console Server */
1117 FillOutputRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle;
1118 FillOutputRequest->OutputHandle = hConsoleOutput;
1119 FillOutputRequest->WriteCoord = dwWriteCoord;
1120 FillOutputRequest->CodeType = CodeType;
1121 FillOutputRequest->Code = Code;
1122 FillOutputRequest->NumCodes = nLength;
1123
1124 /* Call the server */
1125 CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
1126 NULL,
1127 CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepFillConsoleOutput),
1128 sizeof(*FillOutputRequest));
1129
1130 /* Check for success */
1131 Success = NT_SUCCESS(ApiMessage.Status);
1132
1133 /* Retrieve the results */
1134 _SEH2_TRY
1135 {
1136 *lpNumberOfCodesWritten = FillOutputRequest->NumCodes;
1137
1138 if (!Success)
1139 BaseSetLastNTError(ApiMessage.Status);
1140 }
1141 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1142 {
1143 SetLastError(ERROR_INVALID_ACCESS);
1144 Success = FALSE;
1145 }
1146 _SEH2_END;
1147
1148 /* Return success status */
1149 return Success;
1150 }
1151
1152
1153 /* FUNCTIONS ******************************************************************/
1154
1155 /******************
1156 * Read functions *
1157 ******************/
1158
1159 /*--------------------------------------------------------------
1160 * ReadConsoleW
1161 *
1162 * @implemented
1163 */
1164 BOOL
1165 WINAPI
1166 ReadConsoleW(IN HANDLE hConsoleInput,
1167 OUT LPVOID lpBuffer,
1168 IN DWORD nNumberOfCharsToRead,
1169 OUT LPDWORD lpNumberOfCharsRead,
1170 IN PCONSOLE_READCONSOLE_CONTROL pInputControl OPTIONAL)
1171 {
1172 return IntReadConsole(hConsoleInput,
1173 lpBuffer,
1174 nNumberOfCharsToRead,
1175 lpNumberOfCharsRead,
1176 pInputControl,
1177 TRUE);
1178 }
1179
1180
1181 /*--------------------------------------------------------------
1182 * ReadConsoleA
1183 *
1184 * @implemented
1185 */
1186 BOOL
1187 WINAPI
1188 ReadConsoleA(IN HANDLE hConsoleInput,
1189 OUT LPVOID lpBuffer,
1190 IN DWORD nNumberOfCharsToRead,
1191 OUT LPDWORD lpNumberOfCharsRead,
1192 IN PCONSOLE_READCONSOLE_CONTROL pInputControl OPTIONAL)
1193 {
1194 return IntReadConsole(hConsoleInput,
1195 lpBuffer,
1196 nNumberOfCharsToRead,
1197 lpNumberOfCharsRead,
1198 NULL,
1199 FALSE);
1200 }
1201
1202
1203 /*--------------------------------------------------------------
1204 * PeekConsoleInputW
1205 *
1206 * @implemented
1207 */
1208 BOOL
1209 WINAPI
1210 PeekConsoleInputW(IN HANDLE hConsoleInput,
1211 OUT PINPUT_RECORD lpBuffer,
1212 IN DWORD nLength,
1213 OUT LPDWORD lpNumberOfEventsRead)
1214 {
1215 return IntGetConsoleInput(hConsoleInput,
1216 lpBuffer,
1217 nLength,
1218 lpNumberOfEventsRead,
1219 CONSOLE_READ_KEEPEVENT | CONSOLE_READ_CONTINUE,
1220 TRUE);
1221 }
1222
1223
1224 /*--------------------------------------------------------------
1225 * PeekConsoleInputA
1226 *
1227 * @implemented
1228 */
1229 BOOL
1230 WINAPI
1231 PeekConsoleInputA(IN HANDLE hConsoleInput,
1232 OUT PINPUT_RECORD lpBuffer,
1233 IN DWORD nLength,
1234 OUT LPDWORD lpNumberOfEventsRead)
1235 {
1236 return IntGetConsoleInput(hConsoleInput,
1237 lpBuffer,
1238 nLength,
1239 lpNumberOfEventsRead,
1240 CONSOLE_READ_KEEPEVENT | CONSOLE_READ_CONTINUE,
1241 FALSE);
1242 }
1243
1244
1245 /*--------------------------------------------------------------
1246 * ReadConsoleInputW
1247 *
1248 * @implemented
1249 */
1250 BOOL
1251 WINAPI
1252 ReadConsoleInputW(IN HANDLE hConsoleInput,
1253 OUT PINPUT_RECORD lpBuffer,
1254 IN DWORD nLength,
1255 OUT LPDWORD lpNumberOfEventsRead)
1256 {
1257 return IntGetConsoleInput(hConsoleInput,
1258 lpBuffer,
1259 nLength,
1260 lpNumberOfEventsRead,
1261 0,
1262 TRUE);
1263 }
1264
1265
1266 /*--------------------------------------------------------------
1267 * ReadConsoleInputA
1268 *
1269 * @implemented
1270 */
1271 BOOL
1272 WINAPI
1273 ReadConsoleInputA(IN HANDLE hConsoleInput,
1274 OUT PINPUT_RECORD lpBuffer,
1275 IN DWORD nLength,
1276 OUT LPDWORD lpNumberOfEventsRead)
1277 {
1278 return IntGetConsoleInput(hConsoleInput,
1279 lpBuffer,
1280 nLength,
1281 lpNumberOfEventsRead,
1282 0,
1283 FALSE);
1284 }
1285
1286
1287 /*--------------------------------------------------------------
1288 * ReadConsoleInputExW
1289 *
1290 * @implemented
1291 */
1292 BOOL
1293 WINAPI
1294 ReadConsoleInputExW(IN HANDLE hConsoleInput,
1295 OUT PINPUT_RECORD lpBuffer,
1296 IN DWORD nLength,
1297 OUT LPDWORD lpNumberOfEventsRead,
1298 IN WORD wFlags)
1299 {
1300 return IntGetConsoleInput(hConsoleInput,
1301 lpBuffer,
1302 nLength,
1303 lpNumberOfEventsRead,
1304 wFlags,
1305 TRUE);
1306 }
1307
1308
1309 /*--------------------------------------------------------------
1310 * ReadConsoleInputExA
1311 *
1312 * @implemented
1313 */
1314 BOOL
1315 WINAPI
1316 ReadConsoleInputExA(IN HANDLE hConsoleInput,
1317 OUT PINPUT_RECORD lpBuffer,
1318 IN DWORD nLength,
1319 OUT LPDWORD lpNumberOfEventsRead,
1320 IN WORD wFlags)
1321 {
1322 return IntGetConsoleInput(hConsoleInput,
1323 lpBuffer,
1324 nLength,
1325 lpNumberOfEventsRead,
1326 wFlags,
1327 FALSE);
1328 }
1329
1330
1331 /*--------------------------------------------------------------
1332 * ReadConsoleOutputW
1333 *
1334 * @implemented
1335 */
1336 BOOL
1337 WINAPI
1338 ReadConsoleOutputW(IN HANDLE hConsoleOutput,
1339 OUT PCHAR_INFO lpBuffer,
1340 IN COORD dwBufferSize,
1341 IN COORD dwBufferCoord,
1342 IN OUT PSMALL_RECT lpReadRegion)
1343 {
1344 return IntReadConsoleOutput(hConsoleOutput,
1345 lpBuffer,
1346 dwBufferSize,
1347 dwBufferCoord,
1348 lpReadRegion,
1349 TRUE);
1350 }
1351
1352
1353 /*--------------------------------------------------------------
1354 * ReadConsoleOutputA
1355 *
1356 * @implemented
1357 */
1358 BOOL
1359 WINAPI
1360 ReadConsoleOutputA(IN HANDLE hConsoleOutput,
1361 OUT PCHAR_INFO lpBuffer,
1362 IN COORD dwBufferSize,
1363 IN COORD dwBufferCoord,
1364 IN OUT PSMALL_RECT lpReadRegion)
1365 {
1366 return IntReadConsoleOutput(hConsoleOutput,
1367 lpBuffer,
1368 dwBufferSize,
1369 dwBufferCoord,
1370 lpReadRegion,
1371 FALSE);
1372 }
1373
1374
1375 /*--------------------------------------------------------------
1376 * ReadConsoleOutputCharacterW
1377 *
1378 * @implemented
1379 */
1380 BOOL
1381 WINAPI
1382 ReadConsoleOutputCharacterW(IN HANDLE hConsoleOutput,
1383 OUT LPWSTR lpCharacter,
1384 IN DWORD nLength,
1385 IN COORD dwReadCoord,
1386 OUT LPDWORD lpNumberOfCharsRead)
1387 {
1388 return IntReadConsoleOutputCode(hConsoleOutput,
1389 CODE_UNICODE,
1390 lpCharacter,
1391 nLength,
1392 dwReadCoord,
1393 lpNumberOfCharsRead);
1394 }
1395
1396
1397 /*--------------------------------------------------------------
1398 * ReadConsoleOutputCharacterA
1399 *
1400 * @implemented
1401 */
1402 BOOL
1403 WINAPI
1404 ReadConsoleOutputCharacterA(IN HANDLE hConsoleOutput,
1405 OUT LPSTR lpCharacter,
1406 IN DWORD nLength,
1407 IN COORD dwReadCoord,
1408 OUT LPDWORD lpNumberOfCharsRead)
1409 {
1410 return IntReadConsoleOutputCode(hConsoleOutput,
1411 CODE_ASCII,
1412 lpCharacter,
1413 nLength,
1414 dwReadCoord,
1415 lpNumberOfCharsRead);
1416 }
1417
1418
1419 /*--------------------------------------------------------------
1420 * ReadConsoleOutputAttribute
1421 *
1422 * @implemented
1423 */
1424 BOOL
1425 WINAPI
1426 ReadConsoleOutputAttribute(IN HANDLE hConsoleOutput,
1427 OUT LPWORD lpAttribute,
1428 IN DWORD nLength,
1429 IN COORD dwReadCoord,
1430 OUT LPDWORD lpNumberOfAttrsRead)
1431 {
1432 return IntReadConsoleOutputCode(hConsoleOutput,
1433 CODE_ATTRIBUTE,
1434 lpAttribute,
1435 nLength,
1436 dwReadCoord,
1437 lpNumberOfAttrsRead);
1438 }
1439
1440
1441 /*******************
1442 * Write functions *
1443 *******************/
1444
1445 /*--------------------------------------------------------------
1446 * WriteConsoleW
1447 *
1448 * @implemented
1449 */
1450 BOOL
1451 WINAPI
1452 WriteConsoleW(IN HANDLE hConsoleOutput,
1453 IN CONST VOID *lpBuffer,
1454 IN DWORD nNumberOfCharsToWrite,
1455 OUT LPDWORD lpNumberOfCharsWritten,
1456 LPVOID lpReserved)
1457 {
1458 return IntWriteConsole(hConsoleOutput,
1459 (PVOID)lpBuffer,
1460 nNumberOfCharsToWrite,
1461 lpNumberOfCharsWritten,
1462 lpReserved,
1463 TRUE);
1464 }
1465
1466
1467 /*--------------------------------------------------------------
1468 * WriteConsoleA
1469 *
1470 * @implemented
1471 */
1472 BOOL
1473 WINAPI
1474 WriteConsoleA(IN HANDLE hConsoleOutput,
1475 IN CONST VOID *lpBuffer,
1476 IN DWORD nNumberOfCharsToWrite,
1477 OUT LPDWORD lpNumberOfCharsWritten,
1478 LPVOID lpReserved)
1479 {
1480 return IntWriteConsole(hConsoleOutput,
1481 (PVOID)lpBuffer,
1482 nNumberOfCharsToWrite,
1483 lpNumberOfCharsWritten,
1484 lpReserved,
1485 FALSE);
1486 }
1487
1488
1489 /*--------------------------------------------------------------
1490 * WriteConsoleInputW
1491 *
1492 * @implemented
1493 */
1494 BOOL
1495 WINAPI
1496 WriteConsoleInputW(IN HANDLE hConsoleInput,
1497 IN CONST INPUT_RECORD *lpBuffer,
1498 IN DWORD nLength,
1499 OUT LPDWORD lpNumberOfEventsWritten)
1500 {
1501 return IntWriteConsoleInput(hConsoleInput,
1502 (PINPUT_RECORD)lpBuffer,
1503 nLength,
1504 lpNumberOfEventsWritten,
1505 TRUE,
1506 TRUE);
1507 }
1508
1509
1510 /*--------------------------------------------------------------
1511 * WriteConsoleInputA
1512 *
1513 * @implemented
1514 */
1515 BOOL
1516 WINAPI
1517 WriteConsoleInputA(IN HANDLE hConsoleInput,
1518 IN CONST INPUT_RECORD *lpBuffer,
1519 IN DWORD nLength,
1520 OUT LPDWORD lpNumberOfEventsWritten)
1521 {
1522 return IntWriteConsoleInput(hConsoleInput,
1523 (PINPUT_RECORD)lpBuffer,
1524 nLength,
1525 lpNumberOfEventsWritten,
1526 FALSE,
1527 TRUE);
1528 }
1529
1530
1531 /*--------------------------------------------------------------
1532 * WriteConsoleInputVDMW
1533 *
1534 * @implemented
1535 */
1536 BOOL
1537 WINAPI
1538 WriteConsoleInputVDMW(IN HANDLE hConsoleInput,
1539 IN CONST INPUT_RECORD *lpBuffer,
1540 IN DWORD nLength,
1541 OUT LPDWORD lpNumberOfEventsWritten)
1542 {
1543 return IntWriteConsoleInput(hConsoleInput,
1544 (PINPUT_RECORD)lpBuffer,
1545 nLength,
1546 lpNumberOfEventsWritten,
1547 TRUE,
1548 FALSE);
1549 }
1550
1551
1552 /*--------------------------------------------------------------
1553 * WriteConsoleInputVDMA
1554 *
1555 * @implemented
1556 */
1557 BOOL
1558 WINAPI
1559 WriteConsoleInputVDMA(IN HANDLE hConsoleInput,
1560 IN CONST INPUT_RECORD *lpBuffer,
1561 IN DWORD nLength,
1562 OUT LPDWORD lpNumberOfEventsWritten)
1563 {
1564 return IntWriteConsoleInput(hConsoleInput,
1565 (PINPUT_RECORD)lpBuffer,
1566 nLength,
1567 lpNumberOfEventsWritten,
1568 FALSE,
1569 FALSE);
1570 }
1571
1572
1573 /*--------------------------------------------------------------
1574 * WriteConsoleOutputW
1575 *
1576 * @implemented
1577 */
1578 BOOL
1579 WINAPI
1580 WriteConsoleOutputW(IN HANDLE hConsoleOutput,
1581 IN CONST CHAR_INFO *lpBuffer,
1582 IN COORD dwBufferSize,
1583 IN COORD dwBufferCoord,
1584 IN OUT PSMALL_RECT lpWriteRegion)
1585 {
1586 return IntWriteConsoleOutput(hConsoleOutput,
1587 lpBuffer,
1588 dwBufferSize,
1589 dwBufferCoord,
1590 lpWriteRegion,
1591 TRUE);
1592 }
1593
1594
1595 /*--------------------------------------------------------------
1596 * WriteConsoleOutputA
1597 *
1598 * @implemented
1599 */
1600 BOOL
1601 WINAPI
1602 WriteConsoleOutputA(IN HANDLE hConsoleOutput,
1603 IN CONST CHAR_INFO *lpBuffer,
1604 IN COORD dwBufferSize,
1605 IN COORD dwBufferCoord,
1606 IN OUT PSMALL_RECT lpWriteRegion)
1607 {
1608 return IntWriteConsoleOutput(hConsoleOutput,
1609 lpBuffer,
1610 dwBufferSize,
1611 dwBufferCoord,
1612 lpWriteRegion,
1613 FALSE);
1614 }
1615
1616
1617 /*--------------------------------------------------------------
1618 * WriteConsoleOutputCharacterW
1619 *
1620 * @implemented
1621 */
1622 BOOL
1623 WINAPI
1624 WriteConsoleOutputCharacterW(IN HANDLE hConsoleOutput,
1625 IN LPCWSTR lpCharacter,
1626 IN DWORD nLength,
1627 IN COORD dwWriteCoord,
1628 OUT LPDWORD lpNumberOfCharsWritten)
1629 {
1630 return IntWriteConsoleOutputCode(hConsoleOutput,
1631 CODE_UNICODE,
1632 lpCharacter,
1633 nLength,
1634 dwWriteCoord,
1635 lpNumberOfCharsWritten);
1636 }
1637
1638
1639 /*--------------------------------------------------------------
1640 * WriteConsoleOutputCharacterA
1641 *
1642 * @implemented
1643 */
1644 BOOL
1645 WINAPI
1646 WriteConsoleOutputCharacterA(IN HANDLE hConsoleOutput,
1647 IN LPCSTR lpCharacter,
1648 IN DWORD nLength,
1649 IN COORD dwWriteCoord,
1650 OUT LPDWORD lpNumberOfCharsWritten)
1651 {
1652 return IntWriteConsoleOutputCode(hConsoleOutput,
1653 CODE_ASCII,
1654 lpCharacter,
1655 nLength,
1656 dwWriteCoord,
1657 lpNumberOfCharsWritten);
1658 }
1659
1660
1661 /*--------------------------------------------------------------
1662 * WriteConsoleOutputAttribute
1663 *
1664 * @implemented
1665 */
1666 BOOL
1667 WINAPI
1668 WriteConsoleOutputAttribute(IN HANDLE hConsoleOutput,
1669 IN CONST WORD *lpAttribute,
1670 IN DWORD nLength,
1671 IN COORD dwWriteCoord,
1672 OUT LPDWORD lpNumberOfAttrsWritten)
1673 {
1674 return IntWriteConsoleOutputCode(hConsoleOutput,
1675 CODE_ATTRIBUTE,
1676 lpAttribute,
1677 nLength,
1678 dwWriteCoord,
1679 lpNumberOfAttrsWritten);
1680 }
1681
1682
1683 /*--------------------------------------------------------------
1684 * FillConsoleOutputCharacterW
1685 *
1686 * @implemented
1687 */
1688 BOOL
1689 WINAPI
1690 FillConsoleOutputCharacterW(IN HANDLE hConsoleOutput,
1691 IN WCHAR cCharacter,
1692 IN DWORD nLength,
1693 IN COORD dwWriteCoord,
1694 OUT LPDWORD lpNumberOfCharsWritten)
1695 {
1696 CODE_ELEMENT Code;
1697 Code.UnicodeChar = cCharacter;
1698 return IntFillConsoleOutputCode(hConsoleOutput,
1699 CODE_UNICODE,
1700 Code,
1701 nLength,
1702 dwWriteCoord,
1703 lpNumberOfCharsWritten);
1704 }
1705
1706
1707 /*--------------------------------------------------------------
1708 * FillConsoleOutputCharacterA
1709 *
1710 * @implemented
1711 */
1712 BOOL
1713 WINAPI
1714 FillConsoleOutputCharacterA(IN HANDLE hConsoleOutput,
1715 IN CHAR cCharacter,
1716 IN DWORD nLength,
1717 IN COORD dwWriteCoord,
1718 LPDWORD lpNumberOfCharsWritten)
1719 {
1720 CODE_ELEMENT Code;
1721 Code.AsciiChar = cCharacter;
1722 return IntFillConsoleOutputCode(hConsoleOutput,
1723 CODE_ASCII,
1724 Code,
1725 nLength,
1726 dwWriteCoord,
1727 lpNumberOfCharsWritten);
1728 }
1729
1730
1731 /*--------------------------------------------------------------
1732 * FillConsoleOutputAttribute
1733 *
1734 * @implemented
1735 */
1736 BOOL
1737 WINAPI
1738 FillConsoleOutputAttribute(IN HANDLE hConsoleOutput,
1739 IN WORD wAttribute,
1740 IN DWORD nLength,
1741 IN COORD dwWriteCoord,
1742 OUT LPDWORD lpNumberOfAttrsWritten)
1743 {
1744 CODE_ELEMENT Code;
1745 Code.Attribute = wAttribute;
1746 return IntFillConsoleOutputCode(hConsoleOutput,
1747 CODE_ATTRIBUTE,
1748 Code,
1749 nLength,
1750 dwWriteCoord,
1751 lpNumberOfAttrsWritten);
1752 }
1753
1754 /* EOF */