1 /* 2 * ReactOS kernel 3 * Copyright (C) 2002 ReactOS Team 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License as published by 7 * the Free Software Foundation; either version 2 of the License, or 8 * (at your option) any later version. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License along 16 * with this program; if not, write to the Free Software Foundation, Inc., 17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 18 */ 19 /* 20 * COPYRIGHT: See COPYING in the top level directory 21 * PROJECT: ReactOS text-mode setup 22 * FILE: base/setup/usetup/console.c 23 * PURPOSE: Console support functions 24 * PROGRAMMER: 25 */ 26 27 /* INCLUDES ******************************************************************/ 28 29 #include <usetup.h> 30 /* Blue Driver Header */ 31 #include <blue/ntddblue.h> 32 #include "keytrans.h" 33 34 #define NDEBUG 35 #include <debug.h> 36 37 /* DATA **********************************************************************/ 38 39 static BOOLEAN InputQueueEmpty; 40 static BOOLEAN WaitForInput; 41 static KEYBOARD_INPUT_DATA InputDataQueue; // Only one element! 42 static IO_STATUS_BLOCK InputIosb; 43 44 /* FUNCTIONS *****************************************************************/ 45 46 BOOL 47 WINAPI 48 AllocConsole(VOID) 49 { 50 UNICODE_STRING ScreenName = RTL_CONSTANT_STRING(L"\\??\\BlueScreen"); 51 UNICODE_STRING KeyboardName = RTL_CONSTANT_STRING(L"\\Device\\KeyboardClass0"); 52 OBJECT_ATTRIBUTES ObjectAttributes; 53 IO_STATUS_BLOCK IoStatusBlock; 54 NTSTATUS Status; 55 56 /* Open the screen */ 57 InitializeObjectAttributes(&ObjectAttributes, 58 &ScreenName, 59 0, 60 NULL, 61 NULL); 62 Status = NtOpenFile(&StdOutput, 63 FILE_ALL_ACCESS, 64 &ObjectAttributes, 65 &IoStatusBlock, 66 FILE_OPEN, 67 FILE_SYNCHRONOUS_IO_ALERT); 68 if (!NT_SUCCESS(Status)) 69 return FALSE; 70 71 /* Open the keyboard */ 72 InitializeObjectAttributes(&ObjectAttributes, 73 &KeyboardName, 74 0, 75 NULL, 76 NULL); 77 Status = NtOpenFile(&StdInput, 78 FILE_ALL_ACCESS, 79 &ObjectAttributes, 80 &IoStatusBlock, 81 FILE_OPEN, 82 0); 83 if (!NT_SUCCESS(Status)) 84 return FALSE; 85 86 /* Reset the queue state */ 87 InputQueueEmpty = TRUE; 88 WaitForInput = FALSE; 89 90 return TRUE; 91 } 92 93 94 BOOL 95 WINAPI 96 AttachConsole( 97 IN DWORD dwProcessId) 98 { 99 return FALSE; 100 } 101 102 103 BOOL 104 WINAPI 105 FreeConsole(VOID) 106 { 107 /* Reset the queue state */ 108 InputQueueEmpty = TRUE; 109 WaitForInput = FALSE; 110 111 if (StdInput != INVALID_HANDLE_VALUE) 112 NtClose(StdInput); 113 114 if (StdOutput != INVALID_HANDLE_VALUE) 115 NtClose(StdOutput); 116 117 return TRUE; 118 } 119 120 121 BOOL 122 WINAPI 123 WriteConsole( 124 IN HANDLE hConsoleOutput, 125 IN const VOID *lpBuffer, 126 IN DWORD nNumberOfCharsToWrite, 127 OUT LPDWORD lpNumberOfCharsWritten, 128 IN LPVOID lpReserved) 129 { 130 IO_STATUS_BLOCK IoStatusBlock; 131 NTSTATUS Status; 132 133 Status = NtWriteFile(hConsoleOutput, 134 NULL, 135 NULL, 136 NULL, 137 &IoStatusBlock, 138 (PVOID)lpBuffer, 139 nNumberOfCharsToWrite, 140 NULL, 141 NULL); 142 if (!NT_SUCCESS(Status)) 143 return FALSE; 144 145 *lpNumberOfCharsWritten = IoStatusBlock.Information; 146 return TRUE; 147 } 148 149 150 HANDLE 151 WINAPI 152 GetStdHandle( 153 IN DWORD nStdHandle) 154 { 155 switch (nStdHandle) 156 { 157 case STD_INPUT_HANDLE: 158 return StdInput; 159 case STD_OUTPUT_HANDLE: 160 return StdOutput; 161 default: 162 return INVALID_HANDLE_VALUE; 163 } 164 } 165 166 167 BOOL 168 WINAPI 169 FlushConsoleInputBuffer( 170 IN HANDLE hConsoleInput) 171 { 172 NTSTATUS Status; 173 LARGE_INTEGER Offset, Timeout; 174 IO_STATUS_BLOCK IoStatusBlock; 175 KEYBOARD_INPUT_DATA InputData; 176 177 /* Cancel any pending read */ 178 if (WaitForInput) 179 NtCancelIoFile(hConsoleInput, &IoStatusBlock); 180 181 /* Reset the queue state */ 182 InputQueueEmpty = TRUE; 183 WaitForInput = FALSE; 184 185 /* Flush the keyboard buffer */ 186 do 187 { 188 Offset.QuadPart = 0; 189 Status = NtReadFile(hConsoleInput, 190 NULL, 191 NULL, 192 NULL, 193 &IoStatusBlock, 194 &InputData, 195 sizeof(InputData), 196 &Offset, 197 NULL); 198 if (Status == STATUS_PENDING) 199 { 200 Timeout.QuadPart = -100; 201 Status = NtWaitForSingleObject(hConsoleInput, FALSE, &Timeout); 202 if (Status == STATUS_TIMEOUT) 203 { 204 NtCancelIoFile(hConsoleInput, &IoStatusBlock); 205 return TRUE; 206 } 207 } 208 } while (NT_SUCCESS(Status)); 209 return FALSE; 210 } 211 212 213 BOOL 214 WINAPI 215 PeekConsoleInput( 216 IN HANDLE hConsoleInput, 217 OUT PINPUT_RECORD lpBuffer, 218 IN DWORD nLength, 219 OUT LPDWORD lpNumberOfEventsRead) 220 { 221 NTSTATUS Status; 222 LARGE_INTEGER Offset, Timeout; 223 KEYBOARD_INPUT_DATA InputData; 224 225 if (InputQueueEmpty) 226 { 227 /* Read the keyboard for an event, without waiting */ 228 if (!WaitForInput) 229 { 230 Offset.QuadPart = 0; 231 Status = NtReadFile(hConsoleInput, 232 NULL, 233 NULL, 234 NULL, 235 &InputIosb, 236 &InputDataQueue, 237 sizeof(InputDataQueue), 238 &Offset, 239 NULL); 240 if (!NT_SUCCESS(Status)) 241 return FALSE; 242 if (Status == STATUS_PENDING) 243 { 244 /* No input yet, we will have to wait next time */ 245 *lpNumberOfEventsRead = 0; 246 WaitForInput = TRUE; 247 return TRUE; 248 } 249 } 250 else 251 { 252 /* 253 * We already tried to read from the keyboard and are 254 * waiting for data, check whether something showed up. 255 */ 256 Timeout.QuadPart = -100; // Wait just a little bit. 257 Status = NtWaitForSingleObject(hConsoleInput, FALSE, &Timeout); 258 if (Status == STATUS_TIMEOUT) 259 { 260 /* Nothing yet, continue waiting next time */ 261 *lpNumberOfEventsRead = 0; 262 WaitForInput = TRUE; 263 return TRUE; 264 } 265 WaitForInput = FALSE; 266 if (!NT_SUCCESS(Status)) 267 return FALSE; 268 } 269 270 /* We got something in the queue */ 271 InputQueueEmpty = FALSE; 272 WaitForInput = FALSE; 273 } 274 275 /* Fetch from the queue but keep it inside */ 276 InputData = InputDataQueue; 277 278 lpBuffer->EventType = KEY_EVENT; 279 Status = IntTranslateKey(hConsoleInput, &InputData, &lpBuffer->Event.KeyEvent); 280 if (!NT_SUCCESS(Status)) 281 return FALSE; 282 283 *lpNumberOfEventsRead = 1; 284 return TRUE; 285 } 286 287 288 BOOL 289 WINAPI 290 ReadConsoleInput( 291 IN HANDLE hConsoleInput, 292 OUT PINPUT_RECORD lpBuffer, 293 IN DWORD nLength, 294 OUT LPDWORD lpNumberOfEventsRead) 295 { 296 NTSTATUS Status; 297 LARGE_INTEGER Offset; 298 KEYBOARD_INPUT_DATA InputData; 299 300 if (InputQueueEmpty) 301 { 302 /* Read the keyboard and wait for an event, skipping the queue */ 303 if (!WaitForInput) 304 { 305 Offset.QuadPart = 0; 306 Status = NtReadFile(hConsoleInput, 307 NULL, 308 NULL, 309 NULL, 310 &InputIosb, 311 &InputDataQueue, 312 sizeof(InputDataQueue), 313 &Offset, 314 NULL); 315 if (Status == STATUS_PENDING) 316 { 317 /* Block and wait for input */ 318 WaitForInput = TRUE; 319 Status = NtWaitForSingleObject(hConsoleInput, FALSE, NULL); 320 WaitForInput = FALSE; 321 Status = InputIosb.Status; 322 } 323 if (!NT_SUCCESS(Status)) 324 return FALSE; 325 } 326 else 327 { 328 /* 329 * We already tried to read from the keyboard and are 330 * waiting for data, block and wait for input. 331 */ 332 Status = NtWaitForSingleObject(hConsoleInput, FALSE, NULL); 333 WaitForInput = FALSE; 334 Status = InputIosb.Status; 335 if (!NT_SUCCESS(Status)) 336 return FALSE; 337 } 338 } 339 340 /* Fetch from the queue and empty it */ 341 InputData = InputDataQueue; 342 InputQueueEmpty = TRUE; 343 344 lpBuffer->EventType = KEY_EVENT; 345 Status = IntTranslateKey(hConsoleInput, &InputData, &lpBuffer->Event.KeyEvent); 346 if (!NT_SUCCESS(Status)) 347 return FALSE; 348 349 *lpNumberOfEventsRead = 1; 350 return TRUE; 351 } 352 353 354 BOOL 355 WINAPI 356 WriteConsoleOutputCharacterA( 357 HANDLE hConsoleOutput, 358 IN LPCSTR lpCharacter, 359 IN DWORD nLength, 360 IN COORD dwWriteCoord, 361 OUT LPDWORD lpNumberOfCharsWritten) 362 { 363 IO_STATUS_BLOCK IoStatusBlock; 364 PCHAR Buffer; 365 COORD *pCoord; 366 PCHAR pText; 367 NTSTATUS Status; 368 369 Buffer = (CHAR*)RtlAllocateHeap(ProcessHeap, 370 0, 371 nLength + sizeof(COORD)); 372 pCoord = (COORD *)Buffer; 373 pText = (PCHAR)(pCoord + 1); 374 375 *pCoord = dwWriteCoord; 376 memcpy(pText, lpCharacter, nLength); 377 378 Status = NtDeviceIoControlFile(hConsoleOutput, 379 NULL, 380 NULL, 381 NULL, 382 &IoStatusBlock, 383 IOCTL_CONSOLE_WRITE_OUTPUT_CHARACTER, 384 NULL, 385 0, 386 Buffer, 387 nLength + sizeof(COORD)); 388 389 RtlFreeHeap(ProcessHeap, 0, Buffer); 390 if (!NT_SUCCESS(Status)) 391 return FALSE; 392 393 *lpNumberOfCharsWritten = IoStatusBlock.Information; 394 return TRUE; 395 } 396 397 398 BOOL 399 WINAPI 400 WriteConsoleOutputCharacterW( 401 HANDLE hConsoleOutput, 402 IN LPCWSTR lpCharacter, 403 IN DWORD nLength, 404 IN COORD dwWriteCoord, 405 OUT LPDWORD lpNumberOfCharsWritten) 406 { 407 IO_STATUS_BLOCK IoStatusBlock; 408 PCHAR Buffer; 409 COORD *pCoord; 410 PCHAR pText; 411 NTSTATUS Status; 412 // ULONG i; 413 414 UNICODE_STRING UnicodeString; 415 OEM_STRING OemString; 416 ULONG OemLength; 417 418 UnicodeString.Length = nLength * sizeof(WCHAR); 419 UnicodeString.MaximumLength = nLength * sizeof(WCHAR); 420 UnicodeString.Buffer = (PWSTR)lpCharacter; 421 422 OemLength = RtlUnicodeStringToOemSize(&UnicodeString); 423 424 425 Buffer = (CHAR*)RtlAllocateHeap(ProcessHeap, 426 0, 427 OemLength + sizeof(COORD)); 428 // nLength + sizeof(COORD)); 429 if (Buffer== NULL) 430 return FALSE; 431 432 pCoord = (COORD *)Buffer; 433 pText = (PCHAR)(pCoord + 1); 434 435 *pCoord = dwWriteCoord; 436 437 OemString.Length = 0; 438 OemString.MaximumLength = OemLength; 439 OemString.Buffer = pText; 440 441 Status = RtlUnicodeStringToOemString(&OemString, 442 &UnicodeString, 443 FALSE); 444 if (!NT_SUCCESS(Status)) 445 goto done; 446 447 /* FIXME: use real unicode->oem conversion */ 448 // for (i = 0; i < nLength; i++) 449 // pText[i] = (CHAR)lpCharacter[i]; 450 451 Status = NtDeviceIoControlFile(hConsoleOutput, 452 NULL, 453 NULL, 454 NULL, 455 &IoStatusBlock, 456 IOCTL_CONSOLE_WRITE_OUTPUT_CHARACTER, 457 NULL, 458 0, 459 Buffer, 460 nLength + sizeof(COORD)); 461 462 done: 463 RtlFreeHeap(ProcessHeap, 0, Buffer); 464 if (!NT_SUCCESS(Status)) 465 return FALSE; 466 467 *lpNumberOfCharsWritten = IoStatusBlock.Information; 468 return TRUE; 469 } 470 471 472 BOOL 473 WINAPI 474 FillConsoleOutputAttribute( 475 IN HANDLE hConsoleOutput, 476 IN WORD wAttribute, 477 IN DWORD nLength, 478 IN COORD dwWriteCoord, 479 OUT LPDWORD lpNumberOfAttrsWritten) 480 { 481 IO_STATUS_BLOCK IoStatusBlock; 482 OUTPUT_ATTRIBUTE Buffer; 483 NTSTATUS Status; 484 485 Buffer.wAttribute = wAttribute; 486 Buffer.nLength = nLength; 487 Buffer.dwCoord = dwWriteCoord; 488 489 Status = NtDeviceIoControlFile(hConsoleOutput, 490 NULL, 491 NULL, 492 NULL, 493 &IoStatusBlock, 494 IOCTL_CONSOLE_FILL_OUTPUT_ATTRIBUTE, 495 &Buffer, 496 sizeof(OUTPUT_ATTRIBUTE), 497 &Buffer, 498 sizeof(OUTPUT_ATTRIBUTE)); 499 if (!NT_SUCCESS(Status)) 500 return FALSE; 501 502 *lpNumberOfAttrsWritten = Buffer.dwTransfered; 503 return TRUE; 504 } 505 506 507 BOOL 508 WINAPI 509 FillConsoleOutputCharacterA( 510 IN HANDLE hConsoleOutput, 511 IN CHAR cCharacter, 512 IN DWORD nLength, 513 IN COORD dwWriteCoord, 514 OUT LPDWORD lpNumberOfCharsWritten) 515 { 516 IO_STATUS_BLOCK IoStatusBlock; 517 OUTPUT_CHARACTER Buffer; 518 NTSTATUS Status; 519 520 Buffer.cCharacter = cCharacter; 521 Buffer.nLength = nLength; 522 Buffer.dwCoord = dwWriteCoord; 523 524 Status = NtDeviceIoControlFile(hConsoleOutput, 525 NULL, 526 NULL, 527 NULL, 528 &IoStatusBlock, 529 IOCTL_CONSOLE_FILL_OUTPUT_CHARACTER, 530 &Buffer, 531 sizeof(OUTPUT_CHARACTER), 532 &Buffer, 533 sizeof(OUTPUT_CHARACTER)); 534 if (!NT_SUCCESS(Status)) 535 return FALSE; 536 537 *lpNumberOfCharsWritten = Buffer.dwTransfered; 538 return TRUE; 539 } 540 541 542 BOOL 543 WINAPI 544 GetConsoleScreenBufferInfo( 545 IN HANDLE hConsoleOutput, 546 OUT PCONSOLE_SCREEN_BUFFER_INFO lpConsoleScreenBufferInfo) 547 { 548 IO_STATUS_BLOCK IoStatusBlock; 549 NTSTATUS Status; 550 551 Status = NtDeviceIoControlFile(hConsoleOutput, 552 NULL, 553 NULL, 554 NULL, 555 &IoStatusBlock, 556 IOCTL_CONSOLE_GET_SCREEN_BUFFER_INFO, 557 NULL, 558 0, 559 lpConsoleScreenBufferInfo, 560 sizeof(CONSOLE_SCREEN_BUFFER_INFO)); 561 return NT_SUCCESS(Status); 562 } 563 564 565 BOOL 566 WINAPI 567 SetConsoleCursorInfo( 568 IN HANDLE hConsoleOutput, 569 IN const CONSOLE_CURSOR_INFO *lpConsoleCursorInfo) 570 { 571 IO_STATUS_BLOCK IoStatusBlock; 572 NTSTATUS Status; 573 574 Status = NtDeviceIoControlFile(hConsoleOutput, 575 NULL, 576 NULL, 577 NULL, 578 &IoStatusBlock, 579 IOCTL_CONSOLE_SET_CURSOR_INFO, 580 (PCONSOLE_CURSOR_INFO)lpConsoleCursorInfo, 581 sizeof(CONSOLE_CURSOR_INFO), 582 NULL, 583 0); 584 return NT_SUCCESS(Status); 585 } 586 587 588 BOOL 589 WINAPI 590 SetConsoleCursorPosition( 591 IN HANDLE hConsoleOutput, 592 IN COORD dwCursorPosition) 593 { 594 CONSOLE_SCREEN_BUFFER_INFO ConsoleScreenBufferInfo; 595 IO_STATUS_BLOCK IoStatusBlock; 596 NTSTATUS Status; 597 598 Status = GetConsoleScreenBufferInfo(hConsoleOutput, &ConsoleScreenBufferInfo); 599 if (!NT_SUCCESS(Status)) 600 return FALSE; 601 602 ConsoleScreenBufferInfo.dwCursorPosition.X = dwCursorPosition.X; 603 ConsoleScreenBufferInfo.dwCursorPosition.Y = dwCursorPosition.Y; 604 605 Status = NtDeviceIoControlFile(hConsoleOutput, 606 NULL, 607 NULL, 608 NULL, 609 &IoStatusBlock, 610 IOCTL_CONSOLE_SET_SCREEN_BUFFER_INFO, 611 &ConsoleScreenBufferInfo, 612 sizeof(CONSOLE_SCREEN_BUFFER_INFO), 613 NULL, 614 0); 615 return NT_SUCCESS(Status); 616 } 617 618 619 BOOL 620 WINAPI 621 SetConsoleTextAttribute( 622 IN HANDLE hConsoleOutput, 623 IN WORD wAttributes) 624 { 625 IO_STATUS_BLOCK IoStatusBlock; 626 NTSTATUS Status; 627 628 Status = NtDeviceIoControlFile(hConsoleOutput, 629 NULL, 630 NULL, 631 NULL, 632 &IoStatusBlock, 633 IOCTL_CONSOLE_SET_TEXT_ATTRIBUTE, 634 &wAttributes, 635 sizeof(USHORT), 636 NULL, 637 0); 638 return NT_SUCCESS(Status); 639 } 640 641 642 BOOL 643 WINAPI 644 SetConsoleOutputCP( 645 IN UINT wCodepage) 646 { 647 HANDLE hConsoleOutput; 648 IO_STATUS_BLOCK IoStatusBlock; 649 NTSTATUS Status; 650 651 hConsoleOutput = GetStdHandle(STD_OUTPUT_HANDLE); 652 653 Status = NtDeviceIoControlFile(hConsoleOutput, 654 NULL, 655 NULL, 656 NULL, 657 &IoStatusBlock, 658 IOCTL_CONSOLE_LOADFONT, 659 &wCodepage, 660 sizeof(ULONG), 661 NULL, 662 0); 663 return NT_SUCCESS(Status); 664 } 665 666 667 /* EOF */ 668