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