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 = ReadOutputRequest->ReadRegion.Right - 440 ReadOutputRequest->ReadRegion.Left + 1; 441 442 for (y = 0, Y = ReadOutputRequest->ReadRegion.Top; Y <= ReadOutputRequest->ReadRegion.Bottom; ++y, ++Y) 443 { 444 RtlCopyMemory(lpBuffer + (y + dwBufferCoord.Y) * dwBufferSize.X + dwBufferCoord.X, 445 ReadOutputRequest->CharInfo + y * SizeX, 446 SizeX * sizeof(CHAR_INFO)); 447 #if 0 448 for (x = 0, X = ReadOutputRequest->ReadRegion.Left; X <= ReadOutputRequest->ReadRegion.Right; ++x, ++X) 449 { 450 *(lpBuffer + (y + dwBufferCoord.Y) * dwBufferSize.X + (x + dwBufferCoord.X)) = 451 *(ReadOutputRequest->CharInfo + y * SizeX + x); 452 } 453 #endif 454 } 455 } 456 else 457 { 458 BaseSetLastNTError(ApiMessage.Status); 459 } 460 } 461 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 462 { 463 SetLastError(ERROR_INVALID_ACCESS); 464 Success = FALSE; 465 } 466 _SEH2_END; 467 468 /* Release the capture buffer if needed */ 469 if (CaptureBuffer) CsrFreeCaptureBuffer(CaptureBuffer); 470 471 /* Return success status */ 472 return Success; 473 } 474 475 476 static 477 BOOL 478 IntReadConsoleOutputCode(IN HANDLE hConsoleOutput, 479 IN CODE_TYPE CodeType, 480 OUT PVOID pCode, 481 IN DWORD nLength, 482 IN COORD dwReadCoord, 483 OUT LPDWORD lpNumberOfCodesRead) 484 { 485 BOOL Success; 486 CONSOLE_API_MESSAGE ApiMessage; 487 PCONSOLE_READOUTPUTCODE ReadOutputCodeRequest = &ApiMessage.Data.ReadOutputCodeRequest; 488 PCSR_CAPTURE_BUFFER CaptureBuffer = NULL; 489 ULONG CodeSize, SizeBytes; 490 491 DPRINT("IntReadConsoleOutputCode\n"); 492 493 if ( (CodeType != CODE_ASCII ) && 494 (CodeType != CODE_UNICODE ) && 495 (CodeType != CODE_ATTRIBUTE) ) 496 { 497 SetLastError(ERROR_INVALID_PARAMETER); 498 return FALSE; 499 } 500 501 /* Set up the data to send to the Console Server */ 502 ReadOutputCodeRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle; 503 ReadOutputCodeRequest->OutputHandle = hConsoleOutput; 504 ReadOutputCodeRequest->Coord = dwReadCoord; 505 ReadOutputCodeRequest->NumCodes = nLength; 506 507 /* Determine the needed size */ 508 ReadOutputCodeRequest->CodeType = CodeType; 509 switch (CodeType) 510 { 511 case CODE_ASCII: 512 CodeSize = RTL_FIELD_SIZE(CODE_ELEMENT, AsciiChar); 513 break; 514 515 case CODE_UNICODE: 516 CodeSize = RTL_FIELD_SIZE(CODE_ELEMENT, UnicodeChar); 517 break; 518 519 case CODE_ATTRIBUTE: 520 CodeSize = RTL_FIELD_SIZE(CODE_ELEMENT, Attribute); 521 break; 522 } 523 SizeBytes = nLength * CodeSize; 524 525 /* 526 * For optimization purposes, Windows (and hence ReactOS, too, for 527 * compatibility reasons) uses a static buffer if no more than eighty 528 * bytes are read. Otherwise a new buffer is allocated. 529 * This behaviour is also expected in the server-side. 530 */ 531 if (SizeBytes <= sizeof(ReadOutputCodeRequest->CodeStaticBuffer)) 532 { 533 ReadOutputCodeRequest->pCode = ReadOutputCodeRequest->CodeStaticBuffer; 534 // CaptureBuffer = NULL; 535 } 536 else 537 { 538 /* Allocate a Capture Buffer */ 539 CaptureBuffer = CsrAllocateCaptureBuffer(1, SizeBytes); 540 if (CaptureBuffer == NULL) 541 { 542 DPRINT1("CsrAllocateCaptureBuffer failed!\n"); 543 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 544 return FALSE; 545 } 546 547 /* Allocate space in the Buffer */ 548 CsrAllocateMessagePointer(CaptureBuffer, 549 SizeBytes, 550 (PVOID*)&ReadOutputCodeRequest->pCode); 551 } 552 553 /* Call the server */ 554 CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage, 555 CaptureBuffer, 556 CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepReadConsoleOutputString), 557 sizeof(*ReadOutputCodeRequest)); 558 559 /* Check for success */ 560 Success = NT_SUCCESS(ApiMessage.Status); 561 562 /* Retrieve the results */ 563 _SEH2_TRY 564 { 565 *lpNumberOfCodesRead = ReadOutputCodeRequest->NumCodes; 566 567 if (Success) 568 { 569 RtlCopyMemory(pCode, 570 ReadOutputCodeRequest->pCode, 571 ReadOutputCodeRequest->NumCodes * CodeSize); 572 } 573 else 574 { 575 BaseSetLastNTError(ApiMessage.Status); 576 } 577 } 578 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 579 { 580 SetLastError(ERROR_INVALID_ACCESS); 581 Success = FALSE; 582 } 583 _SEH2_END; 584 585 /* Release the capture buffer if needed */ 586 if (CaptureBuffer) CsrFreeCaptureBuffer(CaptureBuffer); 587 588 /* Return success status */ 589 return Success; 590 } 591 592 593 /******************* 594 * Write functions * 595 *******************/ 596 597 static 598 BOOL 599 IntWriteConsole(IN HANDLE hConsoleOutput, 600 IN PVOID lpBuffer, 601 IN DWORD nNumberOfCharsToWrite, 602 OUT LPDWORD lpNumberOfCharsWritten, 603 LPVOID lpReserved, 604 IN BOOLEAN bUnicode) 605 { 606 BOOL Success; 607 CONSOLE_API_MESSAGE ApiMessage; 608 PCONSOLE_WRITECONSOLE WriteConsoleRequest = &ApiMessage.Data.WriteConsoleRequest; 609 PCSR_CAPTURE_BUFFER CaptureBuffer = NULL; 610 ULONG CharSize, SizeBytes; 611 612 DPRINT("IntWriteConsole\n"); 613 614 /* Set up the data to send to the Console Server */ 615 WriteConsoleRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle; 616 WriteConsoleRequest->OutputHandle = hConsoleOutput; 617 WriteConsoleRequest->Unicode = bUnicode; 618 619 /* Those members are unused by the client, on Windows */ 620 WriteConsoleRequest->Reserved1 = 0; 621 // WriteConsoleRequest->Reserved2 = {0}; 622 623 /* Determine the needed size */ 624 CharSize = (bUnicode ? sizeof(WCHAR) : sizeof(CHAR)); 625 SizeBytes = nNumberOfCharsToWrite * CharSize; 626 627 WriteConsoleRequest->NumBytes = SizeBytes; 628 629 /* 630 * For optimization purposes, Windows (and hence ReactOS, too, for 631 * compatibility reasons) uses a static buffer if no more than eighty 632 * bytes are written. Otherwise a new buffer is allocated. 633 * This behaviour is also expected in the server-side. 634 */ 635 if (SizeBytes <= sizeof(WriteConsoleRequest->StaticBuffer)) 636 { 637 WriteConsoleRequest->Buffer = WriteConsoleRequest->StaticBuffer; 638 // CaptureBuffer = NULL; 639 WriteConsoleRequest->UsingStaticBuffer = TRUE; 640 641 _SEH2_TRY 642 { 643 RtlCopyMemory(WriteConsoleRequest->Buffer, 644 lpBuffer, 645 SizeBytes); 646 } 647 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 648 { 649 SetLastError(ERROR_INVALID_ACCESS); 650 _SEH2_YIELD(return FALSE); 651 } 652 _SEH2_END; 653 } 654 else 655 { 656 /* Allocate a Capture Buffer */ 657 CaptureBuffer = CsrAllocateCaptureBuffer(1, SizeBytes); 658 if (CaptureBuffer == NULL) 659 { 660 DPRINT1("CsrAllocateCaptureBuffer failed!\n"); 661 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 662 return FALSE; 663 } 664 665 /* Capture the buffer to write */ 666 CsrCaptureMessageBuffer(CaptureBuffer, 667 (PVOID)lpBuffer, 668 SizeBytes, 669 (PVOID*)&WriteConsoleRequest->Buffer); 670 WriteConsoleRequest->UsingStaticBuffer = FALSE; 671 } 672 673 /* Call the server */ 674 CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage, 675 CaptureBuffer, 676 CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepWriteConsole), 677 sizeof(*WriteConsoleRequest)); 678 679 /* Check for success */ 680 Success = NT_SUCCESS(ApiMessage.Status); 681 682 /* Release the capture buffer if needed */ 683 if (CaptureBuffer) CsrFreeCaptureBuffer(CaptureBuffer); 684 685 /* Retrieve the results */ 686 if (Success) 687 { 688 _SEH2_TRY 689 { 690 *lpNumberOfCharsWritten = WriteConsoleRequest->NumBytes / CharSize; 691 } 692 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 693 { 694 SetLastError(ERROR_INVALID_ACCESS); 695 Success = FALSE; 696 } 697 _SEH2_END; 698 } 699 else 700 { 701 BaseSetLastNTError(ApiMessage.Status); 702 } 703 704 /* Return success status */ 705 return Success; 706 } 707 708 709 static 710 BOOL 711 IntWriteConsoleInput(IN HANDLE hConsoleInput, 712 IN PINPUT_RECORD lpBuffer, 713 IN DWORD nLength, 714 OUT LPDWORD lpNumberOfEventsWritten, 715 IN BOOLEAN bUnicode, 716 IN BOOLEAN bAppendToEnd) 717 { 718 BOOL Success; 719 CONSOLE_API_MESSAGE ApiMessage; 720 PCONSOLE_WRITEINPUT WriteInputRequest = &ApiMessage.Data.WriteInputRequest; 721 PCSR_CAPTURE_BUFFER CaptureBuffer = NULL; 722 723 DPRINT("IntWriteConsoleInput: %lx %p\n", nLength, lpNumberOfEventsWritten); 724 725 /* Set up the data to send to the Console Server */ 726 WriteInputRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle; 727 WriteInputRequest->InputHandle = hConsoleInput; 728 WriteInputRequest->NumRecords = nLength; 729 WriteInputRequest->Unicode = bUnicode; 730 WriteInputRequest->AppendToEnd = bAppendToEnd; 731 732 /* 733 * For optimization purposes, Windows (and hence ReactOS, too, for 734 * compatibility reasons) uses a static buffer if no more than five 735 * input records are written. Otherwise a new buffer is allocated. 736 * This behaviour is also expected in the server-side. 737 */ 738 if (nLength <= sizeof(WriteInputRequest->RecordStaticBuffer)/sizeof(INPUT_RECORD)) 739 { 740 WriteInputRequest->RecordBufPtr = WriteInputRequest->RecordStaticBuffer; 741 // CaptureBuffer = NULL; 742 743 _SEH2_TRY 744 { 745 RtlCopyMemory(WriteInputRequest->RecordBufPtr, 746 lpBuffer, 747 nLength * sizeof(INPUT_RECORD)); 748 } 749 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 750 { 751 SetLastError(ERROR_INVALID_ACCESS); 752 _SEH2_YIELD(return FALSE); 753 } 754 _SEH2_END; 755 } 756 else 757 { 758 ULONG Size = nLength * sizeof(INPUT_RECORD); 759 760 /* Allocate a Capture Buffer */ 761 CaptureBuffer = CsrAllocateCaptureBuffer(1, Size); 762 if (CaptureBuffer == NULL) 763 { 764 DPRINT1("CsrAllocateCaptureBuffer failed!\n"); 765 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 766 return FALSE; 767 } 768 769 /* Capture the user buffer */ 770 CsrCaptureMessageBuffer(CaptureBuffer, 771 lpBuffer, 772 Size, 773 (PVOID*)&WriteInputRequest->RecordBufPtr); 774 } 775 776 /* Call the server */ 777 CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage, 778 CaptureBuffer, 779 CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepWriteConsoleInput), 780 sizeof(*WriteInputRequest)); 781 782 /* Check for success */ 783 Success = NT_SUCCESS(ApiMessage.Status); 784 785 /* Release the capture buffer if needed */ 786 if (CaptureBuffer) CsrFreeCaptureBuffer(CaptureBuffer); 787 788 /* Retrieve the results */ 789 _SEH2_TRY 790 { 791 DPRINT("Events written: %lx\n", WriteInputRequest->NumRecords); 792 *lpNumberOfEventsWritten = WriteInputRequest->NumRecords; 793 794 if (!Success) 795 BaseSetLastNTError(ApiMessage.Status); 796 } 797 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 798 { 799 SetLastError(ERROR_INVALID_ACCESS); 800 Success = FALSE; 801 } 802 _SEH2_END; 803 804 /* Return success status */ 805 return Success; 806 } 807 808 809 static 810 BOOL 811 IntWriteConsoleOutput(IN HANDLE hConsoleOutput, 812 IN CONST CHAR_INFO *lpBuffer, 813 IN COORD dwBufferSize, 814 IN COORD dwBufferCoord, 815 IN OUT PSMALL_RECT lpWriteRegion, 816 IN BOOLEAN bUnicode) 817 { 818 BOOL Success; 819 CONSOLE_API_MESSAGE ApiMessage; 820 PCONSOLE_WRITEOUTPUT WriteOutputRequest = &ApiMessage.Data.WriteOutputRequest; 821 PCSR_CAPTURE_BUFFER CaptureBuffer = NULL; 822 823 SHORT SizeX, SizeY; 824 ULONG NumCells; 825 826 /* Set up the data to send to the Console Server */ 827 WriteOutputRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle; 828 WriteOutputRequest->OutputHandle = hConsoleOutput; 829 WriteOutputRequest->Unicode = bUnicode; 830 831 /* Update lpWriteRegion */ 832 _SEH2_TRY 833 { 834 SizeX = min(dwBufferSize.X - dwBufferCoord.X, ConioRectWidth(lpWriteRegion)); 835 SizeY = min(dwBufferSize.Y - dwBufferCoord.Y, ConioRectHeight(lpWriteRegion)); 836 if (SizeX <= 0 || SizeY <= 0) 837 { 838 SetLastError(ERROR_INVALID_PARAMETER); 839 _SEH2_YIELD(return FALSE); 840 } 841 lpWriteRegion->Right = lpWriteRegion->Left + SizeX - 1; 842 lpWriteRegion->Bottom = lpWriteRegion->Top + SizeY - 1; 843 844 WriteOutputRequest->WriteRegion = *lpWriteRegion; 845 } 846 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 847 { 848 SetLastError(ERROR_INVALID_ACCESS); 849 _SEH2_YIELD(return FALSE); 850 } 851 _SEH2_END; 852 853 NumCells = SizeX * SizeY; 854 DPRINT("IntWriteConsoleOutput: (%d x %d)\n", SizeX, SizeY); 855 856 /* 857 * For optimization purposes, Windows (and hence ReactOS, too, for 858 * compatibility reasons) uses a static buffer if no more than one 859 * cell is written. Otherwise a new buffer is allocated. 860 * This behaviour is also expected in the server-side. 861 */ 862 if (NumCells <= 1) 863 { 864 WriteOutputRequest->CharInfo = &WriteOutputRequest->StaticBuffer; 865 // CaptureBuffer = NULL; 866 WriteOutputRequest->UseVirtualMemory = FALSE; 867 } 868 else 869 { 870 ULONG Size = NumCells * sizeof(CHAR_INFO); 871 872 /* Allocate a Capture Buffer */ 873 CaptureBuffer = CsrAllocateCaptureBuffer(1, Size); 874 if (CaptureBuffer) 875 { 876 /* Allocate space in the Buffer */ 877 CsrAllocateMessagePointer(CaptureBuffer, 878 Size, 879 (PVOID*)&WriteOutputRequest->CharInfo); 880 WriteOutputRequest->UseVirtualMemory = FALSE; 881 } 882 else 883 { 884 /* 885 * CsrAllocateCaptureBuffer failed because we tried to allocate 886 * a too large (>= 64 kB, size of the CSR heap) data buffer. 887 * To circumvent this, Windows uses a trick (that we reproduce for 888 * compatibility reasons): we allocate a heap buffer in the process' 889 * memory, and CSR will read it via NtReadVirtualMemory. 890 */ 891 DPRINT1("CsrAllocateCaptureBuffer failed with size %ld, let's use local heap buffer...\n", Size); 892 893 WriteOutputRequest->CharInfo = RtlAllocateHeap(RtlGetProcessHeap(), 0, Size); 894 WriteOutputRequest->UseVirtualMemory = TRUE; 895 896 /* Bail out if we still cannot allocate memory */ 897 if (WriteOutputRequest->CharInfo == NULL) 898 { 899 DPRINT1("Failed to allocate heap buffer with size %ld!\n", Size); 900 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 901 return FALSE; 902 } 903 } 904 } 905 906 /* Capture the user buffer contents */ 907 _SEH2_TRY 908 { 909 #if 0 910 SHORT x, X; 911 #endif 912 SHORT y, Y; 913 914 /* Copy into the buffer */ 915 916 SizeX = WriteOutputRequest->WriteRegion.Right - 917 WriteOutputRequest->WriteRegion.Left + 1; 918 919 for (y = 0, Y = WriteOutputRequest->WriteRegion.Top; Y <= WriteOutputRequest->WriteRegion.Bottom; ++y, ++Y) 920 { 921 RtlCopyMemory(WriteOutputRequest->CharInfo + y * SizeX, 922 lpBuffer + (y + dwBufferCoord.Y) * dwBufferSize.X + dwBufferCoord.X, 923 SizeX * sizeof(CHAR_INFO)); 924 #if 0 925 for (x = 0, X = WriteOutputRequest->WriteRegion.Left; X <= WriteOutputRequest->WriteRegion.Right; ++x, ++X) 926 { 927 *(WriteOutputRequest->CharInfo + y * SizeX + x) = 928 *(lpBuffer + (y + dwBufferCoord.Y) * dwBufferSize.X + (x + dwBufferCoord.X)); 929 } 930 #endif 931 } 932 } 933 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 934 { 935 SetLastError(ERROR_INVALID_ACCESS); 936 _SEH2_YIELD(return FALSE); 937 } 938 _SEH2_END; 939 940 /* Call the server */ 941 CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage, 942 CaptureBuffer, 943 CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepWriteConsoleOutput), 944 sizeof(*WriteOutputRequest)); 945 946 /* Check for success */ 947 Success = NT_SUCCESS(ApiMessage.Status); 948 949 /* Release the capture buffer if needed */ 950 if (CaptureBuffer) 951 { 952 CsrFreeCaptureBuffer(CaptureBuffer); 953 } 954 else 955 { 956 /* If we used a heap buffer, free it */ 957 if (WriteOutputRequest->UseVirtualMemory) 958 RtlFreeHeap(RtlGetProcessHeap(), 0, WriteOutputRequest->CharInfo); 959 } 960 961 /* Retrieve the results */ 962 _SEH2_TRY 963 { 964 *lpWriteRegion = WriteOutputRequest->WriteRegion; 965 966 if (!Success) 967 BaseSetLastNTError(ApiMessage.Status); 968 } 969 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 970 { 971 SetLastError(ERROR_INVALID_ACCESS); 972 Success = FALSE; 973 } 974 _SEH2_END; 975 976 /* Return success status */ 977 return Success; 978 } 979 980 981 static 982 BOOL 983 IntWriteConsoleOutputCode(IN HANDLE hConsoleOutput, 984 IN CODE_TYPE CodeType, 985 IN CONST VOID *pCode, 986 IN DWORD nLength, 987 IN COORD dwWriteCoord, 988 OUT LPDWORD lpNumberOfCodesWritten) 989 { 990 BOOL Success; 991 CONSOLE_API_MESSAGE ApiMessage; 992 PCONSOLE_WRITEOUTPUTCODE WriteOutputCodeRequest = &ApiMessage.Data.WriteOutputCodeRequest; 993 PCSR_CAPTURE_BUFFER CaptureBuffer = NULL; 994 ULONG CodeSize, SizeBytes; 995 996 if ( (CodeType != CODE_ASCII ) && 997 (CodeType != CODE_UNICODE ) && 998 (CodeType != CODE_ATTRIBUTE) ) 999 { 1000 SetLastError(ERROR_INVALID_PARAMETER); 1001 return FALSE; 1002 } 1003 1004 DPRINT("IntWriteConsoleOutputCode\n"); 1005 1006 /* Set up the data to send to the Console Server */ 1007 WriteOutputCodeRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle; 1008 WriteOutputCodeRequest->OutputHandle = hConsoleOutput; 1009 WriteOutputCodeRequest->Coord = dwWriteCoord; 1010 WriteOutputCodeRequest->NumCodes = nLength; 1011 1012 /* Determine the needed size */ 1013 WriteOutputCodeRequest->CodeType = CodeType; 1014 switch (CodeType) 1015 { 1016 case CODE_ASCII: 1017 CodeSize = RTL_FIELD_SIZE(CODE_ELEMENT, AsciiChar); 1018 break; 1019 1020 case CODE_UNICODE: 1021 CodeSize = RTL_FIELD_SIZE(CODE_ELEMENT, UnicodeChar); 1022 break; 1023 1024 case CODE_ATTRIBUTE: 1025 CodeSize = RTL_FIELD_SIZE(CODE_ELEMENT, Attribute); 1026 break; 1027 } 1028 SizeBytes = nLength * CodeSize; 1029 1030 /* 1031 * For optimization purposes, Windows (and hence ReactOS, too, for 1032 * compatibility reasons) uses a static buffer if no more than eighty 1033 * bytes are written. Otherwise a new buffer is allocated. 1034 * This behaviour is also expected in the server-side. 1035 */ 1036 if (SizeBytes <= sizeof(WriteOutputCodeRequest->CodeStaticBuffer)) 1037 { 1038 WriteOutputCodeRequest->pCode = WriteOutputCodeRequest->CodeStaticBuffer; 1039 // CaptureBuffer = NULL; 1040 1041 _SEH2_TRY 1042 { 1043 RtlCopyMemory(WriteOutputCodeRequest->pCode, 1044 pCode, 1045 SizeBytes); 1046 } 1047 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 1048 { 1049 SetLastError(ERROR_INVALID_ACCESS); 1050 _SEH2_YIELD(return FALSE); 1051 } 1052 _SEH2_END; 1053 } 1054 else 1055 { 1056 /* Allocate a Capture Buffer */ 1057 CaptureBuffer = CsrAllocateCaptureBuffer(1, SizeBytes); 1058 if (CaptureBuffer == NULL) 1059 { 1060 DPRINT1("CsrAllocateCaptureBuffer failed!\n"); 1061 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 1062 return FALSE; 1063 } 1064 1065 /* Capture the buffer to write */ 1066 CsrCaptureMessageBuffer(CaptureBuffer, 1067 (PVOID)pCode, 1068 SizeBytes, 1069 (PVOID*)&WriteOutputCodeRequest->pCode); 1070 } 1071 1072 /* Call the server */ 1073 CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage, 1074 CaptureBuffer, 1075 CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepWriteConsoleOutputString), 1076 sizeof(*WriteOutputCodeRequest)); 1077 1078 /* Check for success */ 1079 Success = NT_SUCCESS(ApiMessage.Status); 1080 1081 /* Release the capture buffer if needed */ 1082 if (CaptureBuffer) CsrFreeCaptureBuffer(CaptureBuffer); 1083 1084 /* Retrieve the results */ 1085 _SEH2_TRY 1086 { 1087 *lpNumberOfCodesWritten = WriteOutputCodeRequest->NumCodes; 1088 1089 if (!Success) 1090 BaseSetLastNTError(ApiMessage.Status); 1091 } 1092 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 1093 { 1094 SetLastError(ERROR_INVALID_ACCESS); 1095 Success = FALSE; 1096 } 1097 _SEH2_END; 1098 1099 /* Return success status */ 1100 return Success; 1101 } 1102 1103 1104 static 1105 BOOL 1106 IntFillConsoleOutputCode(IN HANDLE hConsoleOutput, 1107 IN CODE_TYPE CodeType, 1108 IN CODE_ELEMENT Code, 1109 IN DWORD nLength, 1110 IN COORD dwWriteCoord, 1111 OUT LPDWORD lpNumberOfCodesWritten) 1112 { 1113 BOOL Success; 1114 CONSOLE_API_MESSAGE ApiMessage; 1115 PCONSOLE_FILLOUTPUTCODE FillOutputRequest = &ApiMessage.Data.FillOutputRequest; 1116 1117 DPRINT("IntFillConsoleOutputCode\n"); 1118 1119 if ( (CodeType != CODE_ASCII ) && 1120 (CodeType != CODE_UNICODE ) && 1121 (CodeType != CODE_ATTRIBUTE) ) 1122 { 1123 SetLastError(ERROR_INVALID_PARAMETER); 1124 return FALSE; 1125 } 1126 1127 /* Set up the data to send to the Console Server */ 1128 FillOutputRequest->ConsoleHandle = NtCurrentPeb()->ProcessParameters->ConsoleHandle; 1129 FillOutputRequest->OutputHandle = hConsoleOutput; 1130 FillOutputRequest->WriteCoord = dwWriteCoord; 1131 FillOutputRequest->CodeType = CodeType; 1132 FillOutputRequest->Code = Code; 1133 FillOutputRequest->NumCodes = nLength; 1134 1135 /* Call the server */ 1136 CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage, 1137 NULL, 1138 CSR_CREATE_API_NUMBER(CONSRV_SERVERDLL_INDEX, ConsolepFillConsoleOutput), 1139 sizeof(*FillOutputRequest)); 1140 1141 /* Check for success */ 1142 Success = NT_SUCCESS(ApiMessage.Status); 1143 1144 /* Retrieve the results */ 1145 _SEH2_TRY 1146 { 1147 *lpNumberOfCodesWritten = FillOutputRequest->NumCodes; 1148 1149 if (!Success) 1150 BaseSetLastNTError(ApiMessage.Status); 1151 } 1152 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 1153 { 1154 SetLastError(ERROR_INVALID_ACCESS); 1155 Success = FALSE; 1156 } 1157 _SEH2_END; 1158 1159 /* Return success status */ 1160 return Success; 1161 } 1162 1163 1164 /* FUNCTIONS ******************************************************************/ 1165 1166 /****************** 1167 * Read functions * 1168 ******************/ 1169 1170 /* 1171 * @implemented 1172 */ 1173 BOOL 1174 WINAPI 1175 DECLSPEC_HOTPATCH 1176 ReadConsoleW(IN HANDLE hConsoleInput, 1177 OUT LPVOID lpBuffer, 1178 IN DWORD nNumberOfCharsToRead, 1179 OUT LPDWORD lpNumberOfCharsRead, 1180 IN PCONSOLE_READCONSOLE_CONTROL pInputControl OPTIONAL) 1181 { 1182 return IntReadConsole(hConsoleInput, 1183 lpBuffer, 1184 nNumberOfCharsToRead, 1185 lpNumberOfCharsRead, 1186 pInputControl, 1187 TRUE); 1188 } 1189 1190 1191 /* 1192 * @implemented 1193 */ 1194 BOOL 1195 WINAPI 1196 DECLSPEC_HOTPATCH 1197 ReadConsoleA(IN HANDLE hConsoleInput, 1198 OUT LPVOID lpBuffer, 1199 IN DWORD nNumberOfCharsToRead, 1200 OUT LPDWORD lpNumberOfCharsRead, 1201 IN PCONSOLE_READCONSOLE_CONTROL pInputControl OPTIONAL) 1202 { 1203 return IntReadConsole(hConsoleInput, 1204 lpBuffer, 1205 nNumberOfCharsToRead, 1206 lpNumberOfCharsRead, 1207 NULL, 1208 FALSE); 1209 } 1210 1211 1212 /* 1213 * @implemented 1214 */ 1215 BOOL 1216 WINAPI 1217 DECLSPEC_HOTPATCH 1218 PeekConsoleInputW(IN HANDLE hConsoleInput, 1219 OUT PINPUT_RECORD lpBuffer, 1220 IN DWORD nLength, 1221 OUT LPDWORD lpNumberOfEventsRead) 1222 { 1223 return IntGetConsoleInput(hConsoleInput, 1224 lpBuffer, 1225 nLength, 1226 lpNumberOfEventsRead, 1227 CONSOLE_READ_KEEPEVENT | CONSOLE_READ_CONTINUE, 1228 TRUE); 1229 } 1230 1231 1232 /* 1233 * @implemented 1234 */ 1235 BOOL 1236 WINAPI 1237 DECLSPEC_HOTPATCH 1238 PeekConsoleInputA(IN HANDLE hConsoleInput, 1239 OUT PINPUT_RECORD lpBuffer, 1240 IN DWORD nLength, 1241 OUT LPDWORD lpNumberOfEventsRead) 1242 { 1243 return IntGetConsoleInput(hConsoleInput, 1244 lpBuffer, 1245 nLength, 1246 lpNumberOfEventsRead, 1247 CONSOLE_READ_KEEPEVENT | CONSOLE_READ_CONTINUE, 1248 FALSE); 1249 } 1250 1251 1252 /* 1253 * @implemented 1254 */ 1255 BOOL 1256 WINAPI 1257 DECLSPEC_HOTPATCH 1258 ReadConsoleInputW(IN HANDLE hConsoleInput, 1259 OUT PINPUT_RECORD lpBuffer, 1260 IN DWORD nLength, 1261 OUT LPDWORD lpNumberOfEventsRead) 1262 { 1263 return IntGetConsoleInput(hConsoleInput, 1264 lpBuffer, 1265 nLength, 1266 lpNumberOfEventsRead, 1267 0, 1268 TRUE); 1269 } 1270 1271 1272 /* 1273 * @implemented 1274 */ 1275 BOOL 1276 WINAPI 1277 DECLSPEC_HOTPATCH 1278 ReadConsoleInputA(IN HANDLE hConsoleInput, 1279 OUT PINPUT_RECORD lpBuffer, 1280 IN DWORD nLength, 1281 OUT LPDWORD lpNumberOfEventsRead) 1282 { 1283 return IntGetConsoleInput(hConsoleInput, 1284 lpBuffer, 1285 nLength, 1286 lpNumberOfEventsRead, 1287 0, 1288 FALSE); 1289 } 1290 1291 1292 /* 1293 * @implemented 1294 */ 1295 BOOL 1296 WINAPI 1297 DECLSPEC_HOTPATCH 1298 ReadConsoleInputExW(IN HANDLE hConsoleInput, 1299 OUT PINPUT_RECORD lpBuffer, 1300 IN DWORD nLength, 1301 OUT LPDWORD lpNumberOfEventsRead, 1302 IN WORD wFlags) 1303 { 1304 return IntGetConsoleInput(hConsoleInput, 1305 lpBuffer, 1306 nLength, 1307 lpNumberOfEventsRead, 1308 wFlags, 1309 TRUE); 1310 } 1311 1312 1313 /* 1314 * @implemented 1315 */ 1316 BOOL 1317 WINAPI 1318 DECLSPEC_HOTPATCH 1319 ReadConsoleInputExA(IN HANDLE hConsoleInput, 1320 OUT PINPUT_RECORD lpBuffer, 1321 IN DWORD nLength, 1322 OUT LPDWORD lpNumberOfEventsRead, 1323 IN WORD wFlags) 1324 { 1325 return IntGetConsoleInput(hConsoleInput, 1326 lpBuffer, 1327 nLength, 1328 lpNumberOfEventsRead, 1329 wFlags, 1330 FALSE); 1331 } 1332 1333 1334 /* 1335 * @implemented 1336 */ 1337 BOOL 1338 WINAPI 1339 DECLSPEC_HOTPATCH 1340 ReadConsoleOutputW(IN HANDLE hConsoleOutput, 1341 OUT PCHAR_INFO lpBuffer, 1342 IN COORD dwBufferSize, 1343 IN COORD dwBufferCoord, 1344 IN OUT PSMALL_RECT lpReadRegion) 1345 { 1346 return IntReadConsoleOutput(hConsoleOutput, 1347 lpBuffer, 1348 dwBufferSize, 1349 dwBufferCoord, 1350 lpReadRegion, 1351 TRUE); 1352 } 1353 1354 1355 /* 1356 * @implemented 1357 */ 1358 BOOL 1359 WINAPI 1360 DECLSPEC_HOTPATCH 1361 ReadConsoleOutputA(IN HANDLE hConsoleOutput, 1362 OUT PCHAR_INFO lpBuffer, 1363 IN COORD dwBufferSize, 1364 IN COORD dwBufferCoord, 1365 IN OUT PSMALL_RECT lpReadRegion) 1366 { 1367 return IntReadConsoleOutput(hConsoleOutput, 1368 lpBuffer, 1369 dwBufferSize, 1370 dwBufferCoord, 1371 lpReadRegion, 1372 FALSE); 1373 } 1374 1375 1376 /* 1377 * @implemented 1378 */ 1379 BOOL 1380 WINAPI 1381 DECLSPEC_HOTPATCH 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 * @implemented 1399 */ 1400 BOOL 1401 WINAPI 1402 DECLSPEC_HOTPATCH 1403 ReadConsoleOutputCharacterA(IN HANDLE hConsoleOutput, 1404 OUT LPSTR lpCharacter, 1405 IN DWORD nLength, 1406 IN COORD dwReadCoord, 1407 OUT LPDWORD lpNumberOfCharsRead) 1408 { 1409 return IntReadConsoleOutputCode(hConsoleOutput, 1410 CODE_ASCII, 1411 lpCharacter, 1412 nLength, 1413 dwReadCoord, 1414 lpNumberOfCharsRead); 1415 } 1416 1417 1418 /* 1419 * @implemented 1420 */ 1421 BOOL 1422 WINAPI 1423 DECLSPEC_HOTPATCH 1424 ReadConsoleOutputAttribute(IN HANDLE hConsoleOutput, 1425 OUT LPWORD lpAttribute, 1426 IN DWORD nLength, 1427 IN COORD dwReadCoord, 1428 OUT LPDWORD lpNumberOfAttrsRead) 1429 { 1430 return IntReadConsoleOutputCode(hConsoleOutput, 1431 CODE_ATTRIBUTE, 1432 lpAttribute, 1433 nLength, 1434 dwReadCoord, 1435 lpNumberOfAttrsRead); 1436 } 1437 1438 1439 /******************* 1440 * Write functions * 1441 *******************/ 1442 1443 /* 1444 * @implemented 1445 */ 1446 BOOL 1447 WINAPI 1448 DECLSPEC_HOTPATCH 1449 WriteConsoleW(IN HANDLE hConsoleOutput, 1450 IN CONST VOID *lpBuffer, 1451 IN DWORD nNumberOfCharsToWrite, 1452 OUT LPDWORD lpNumberOfCharsWritten, 1453 LPVOID lpReserved) 1454 { 1455 return IntWriteConsole(hConsoleOutput, 1456 (PVOID)lpBuffer, 1457 nNumberOfCharsToWrite, 1458 lpNumberOfCharsWritten, 1459 lpReserved, 1460 TRUE); 1461 } 1462 1463 1464 /* 1465 * @implemented 1466 */ 1467 BOOL 1468 WINAPI 1469 DECLSPEC_HOTPATCH 1470 WriteConsoleA(IN HANDLE hConsoleOutput, 1471 IN CONST VOID *lpBuffer, 1472 IN DWORD nNumberOfCharsToWrite, 1473 OUT LPDWORD lpNumberOfCharsWritten, 1474 LPVOID lpReserved) 1475 { 1476 return IntWriteConsole(hConsoleOutput, 1477 (PVOID)lpBuffer, 1478 nNumberOfCharsToWrite, 1479 lpNumberOfCharsWritten, 1480 lpReserved, 1481 FALSE); 1482 } 1483 1484 1485 /* 1486 * @implemented 1487 */ 1488 BOOL 1489 WINAPI 1490 DECLSPEC_HOTPATCH 1491 WriteConsoleInputW(IN HANDLE hConsoleInput, 1492 IN CONST INPUT_RECORD *lpBuffer, 1493 IN DWORD nLength, 1494 OUT LPDWORD lpNumberOfEventsWritten) 1495 { 1496 return IntWriteConsoleInput(hConsoleInput, 1497 (PINPUT_RECORD)lpBuffer, 1498 nLength, 1499 lpNumberOfEventsWritten, 1500 TRUE, 1501 TRUE); 1502 } 1503 1504 1505 /* 1506 * @implemented 1507 */ 1508 BOOL 1509 WINAPI 1510 DECLSPEC_HOTPATCH 1511 WriteConsoleInputA(IN HANDLE hConsoleInput, 1512 IN CONST INPUT_RECORD *lpBuffer, 1513 IN DWORD nLength, 1514 OUT LPDWORD lpNumberOfEventsWritten) 1515 { 1516 return IntWriteConsoleInput(hConsoleInput, 1517 (PINPUT_RECORD)lpBuffer, 1518 nLength, 1519 lpNumberOfEventsWritten, 1520 FALSE, 1521 TRUE); 1522 } 1523 1524 1525 /* 1526 * @implemented 1527 */ 1528 BOOL 1529 WINAPI 1530 DECLSPEC_HOTPATCH 1531 WriteConsoleInputVDMW(IN HANDLE hConsoleInput, 1532 IN CONST INPUT_RECORD *lpBuffer, 1533 IN DWORD nLength, 1534 OUT LPDWORD lpNumberOfEventsWritten) 1535 { 1536 return IntWriteConsoleInput(hConsoleInput, 1537 (PINPUT_RECORD)lpBuffer, 1538 nLength, 1539 lpNumberOfEventsWritten, 1540 TRUE, 1541 FALSE); 1542 } 1543 1544 1545 /* 1546 * @implemented 1547 */ 1548 BOOL 1549 WINAPI 1550 DECLSPEC_HOTPATCH 1551 WriteConsoleInputVDMA(IN HANDLE hConsoleInput, 1552 IN CONST INPUT_RECORD *lpBuffer, 1553 IN DWORD nLength, 1554 OUT LPDWORD lpNumberOfEventsWritten) 1555 { 1556 return IntWriteConsoleInput(hConsoleInput, 1557 (PINPUT_RECORD)lpBuffer, 1558 nLength, 1559 lpNumberOfEventsWritten, 1560 FALSE, 1561 FALSE); 1562 } 1563 1564 1565 /* 1566 * @implemented 1567 */ 1568 BOOL 1569 WINAPI 1570 DECLSPEC_HOTPATCH 1571 WriteConsoleOutputW(IN HANDLE hConsoleOutput, 1572 IN CONST CHAR_INFO *lpBuffer, 1573 IN COORD dwBufferSize, 1574 IN COORD dwBufferCoord, 1575 IN OUT PSMALL_RECT lpWriteRegion) 1576 { 1577 return IntWriteConsoleOutput(hConsoleOutput, 1578 lpBuffer, 1579 dwBufferSize, 1580 dwBufferCoord, 1581 lpWriteRegion, 1582 TRUE); 1583 } 1584 1585 1586 /* 1587 * @implemented 1588 */ 1589 BOOL 1590 WINAPI 1591 DECLSPEC_HOTPATCH 1592 WriteConsoleOutputA(IN HANDLE hConsoleOutput, 1593 IN CONST CHAR_INFO *lpBuffer, 1594 IN COORD dwBufferSize, 1595 IN COORD dwBufferCoord, 1596 IN OUT PSMALL_RECT lpWriteRegion) 1597 { 1598 return IntWriteConsoleOutput(hConsoleOutput, 1599 lpBuffer, 1600 dwBufferSize, 1601 dwBufferCoord, 1602 lpWriteRegion, 1603 FALSE); 1604 } 1605 1606 1607 /* 1608 * @implemented 1609 */ 1610 BOOL 1611 WINAPI 1612 DECLSPEC_HOTPATCH 1613 WriteConsoleOutputCharacterW(IN HANDLE hConsoleOutput, 1614 IN LPCWSTR lpCharacter, 1615 IN DWORD nLength, 1616 IN COORD dwWriteCoord, 1617 OUT LPDWORD lpNumberOfCharsWritten) 1618 { 1619 return IntWriteConsoleOutputCode(hConsoleOutput, 1620 CODE_UNICODE, 1621 lpCharacter, 1622 nLength, 1623 dwWriteCoord, 1624 lpNumberOfCharsWritten); 1625 } 1626 1627 1628 /* 1629 * @implemented 1630 */ 1631 BOOL 1632 WINAPI 1633 DECLSPEC_HOTPATCH 1634 WriteConsoleOutputCharacterA(IN HANDLE hConsoleOutput, 1635 IN LPCSTR lpCharacter, 1636 IN DWORD nLength, 1637 IN COORD dwWriteCoord, 1638 OUT LPDWORD lpNumberOfCharsWritten) 1639 { 1640 return IntWriteConsoleOutputCode(hConsoleOutput, 1641 CODE_ASCII, 1642 lpCharacter, 1643 nLength, 1644 dwWriteCoord, 1645 lpNumberOfCharsWritten); 1646 } 1647 1648 1649 /* 1650 * @implemented 1651 */ 1652 BOOL 1653 WINAPI 1654 DECLSPEC_HOTPATCH 1655 WriteConsoleOutputAttribute(IN HANDLE hConsoleOutput, 1656 IN CONST WORD *lpAttribute, 1657 IN DWORD nLength, 1658 IN COORD dwWriteCoord, 1659 OUT LPDWORD lpNumberOfAttrsWritten) 1660 { 1661 return IntWriteConsoleOutputCode(hConsoleOutput, 1662 CODE_ATTRIBUTE, 1663 lpAttribute, 1664 nLength, 1665 dwWriteCoord, 1666 lpNumberOfAttrsWritten); 1667 } 1668 1669 1670 /* 1671 * @implemented 1672 */ 1673 BOOL 1674 WINAPI 1675 DECLSPEC_HOTPATCH 1676 FillConsoleOutputCharacterW(IN HANDLE hConsoleOutput, 1677 IN WCHAR cCharacter, 1678 IN DWORD nLength, 1679 IN COORD dwWriteCoord, 1680 OUT LPDWORD lpNumberOfCharsWritten) 1681 { 1682 CODE_ELEMENT Code; 1683 Code.UnicodeChar = cCharacter; 1684 return IntFillConsoleOutputCode(hConsoleOutput, 1685 CODE_UNICODE, 1686 Code, 1687 nLength, 1688 dwWriteCoord, 1689 lpNumberOfCharsWritten); 1690 } 1691 1692 1693 /* 1694 * @implemented 1695 */ 1696 BOOL 1697 WINAPI 1698 DECLSPEC_HOTPATCH 1699 FillConsoleOutputCharacterA(IN HANDLE hConsoleOutput, 1700 IN CHAR cCharacter, 1701 IN DWORD nLength, 1702 IN COORD dwWriteCoord, 1703 LPDWORD lpNumberOfCharsWritten) 1704 { 1705 CODE_ELEMENT Code; 1706 Code.AsciiChar = cCharacter; 1707 return IntFillConsoleOutputCode(hConsoleOutput, 1708 CODE_ASCII, 1709 Code, 1710 nLength, 1711 dwWriteCoord, 1712 lpNumberOfCharsWritten); 1713 } 1714 1715 1716 /* 1717 * @implemented 1718 */ 1719 BOOL 1720 WINAPI 1721 DECLSPEC_HOTPATCH 1722 FillConsoleOutputAttribute(IN HANDLE hConsoleOutput, 1723 IN WORD wAttribute, 1724 IN DWORD nLength, 1725 IN COORD dwWriteCoord, 1726 OUT LPDWORD lpNumberOfAttrsWritten) 1727 { 1728 CODE_ELEMENT Code; 1729 Code.Attribute = wAttribute; 1730 return IntFillConsoleOutputCode(hConsoleOutput, 1731 CODE_ATTRIBUTE, 1732 Code, 1733 nLength, 1734 dwWriteCoord, 1735 lpNumberOfAttrsWritten); 1736 } 1737 1738 /* EOF */ 1739