3 * Copyright (C) 2002 ReactOS Team
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.
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.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 * COPYRIGHT: See COPYING in the top level directory
21 * PROJECT: ReactOS text-mode setup
22 * FILE: subsys/system/usetup/console.c
23 * PURPOSE: Console support functions
24 * PROGRAMMER: Eric Kohl
27 /* INCLUDES ******************************************************************/
29 #include <ddk/ntddk.h>
30 #include <ddk/ntddblue.h>
36 /* GLOBALS ******************************************************************/
38 static HANDLE StdInput = INVALID_HANDLE_VALUE;
39 static HANDLE StdOutput = INVALID_HANDLE_VALUE;
40 static HANDLE InputEvent = INVALID_HANDLE_VALUE;
42 static SHORT xScreen = 0;
43 static SHORT yScreen = 0;
47 GetConsoleScreenBufferInfo(PCONSOLE_SCREEN_BUFFER_INFO ConsoleScreenBufferInfo);
50 /* FUNCTIONS *****************************************************************/
57 OBJECT_ATTRIBUTES ObjectAttributes;
58 IO_STATUS_BLOCK IoStatusBlock;
61 CONSOLE_SCREEN_BUFFER_INFO csbi;
64 RtlInitUnicodeString(&Name,
66 InitializeObjectAttributes(&ObjectAttributes,
71 Status = NtCreateFile(&StdOutput,
82 if (!NT_SUCCESS(Status))
85 /* Create input event */
86 Status = NtCreateEvent(&InputEvent,
91 if (!NT_SUCCESS(Status))
94 /* Open the keyboard */
95 RtlInitUnicodeString(&Name,
97 InitializeObjectAttributes(&ObjectAttributes,
102 Status = NtCreateFile(&StdInput,
114 GetConsoleScreenBufferInfo(&csbi);
116 xScreen = csbi.dwSize.X;
117 yScreen = csbi.dwSize.Y;
126 if (StdInput != INVALID_HANDLE_VALUE)
129 if (StdOutput != INVALID_HANDLE_VALUE)
132 if (InputEvent != INVALID_HANDLE_VALUE)
140 WriteConsole(PCHAR Buffer,
141 ULONG NumberOfCharsToWrite,
142 PULONG NumberOfCharsWritten)
144 IO_STATUS_BLOCK IoStatusBlock;
145 NTSTATUS Status = STATUS_SUCCESS;
148 Status = NtWriteFile(StdOutput,
154 NumberOfCharsToWrite,
157 if (Status == STATUS_PENDING)
159 NtWaitForSingleObject(StdOutput,
162 Status = IoStatusBlock.Status;
165 if (NumberOfCharsWritten != NULL)
167 *NumberOfCharsWritten = IoStatusBlock.Information;
175 /*--------------------------------------------------------------
180 ReadConsoleA(HANDLE hConsoleInput,
182 DWORD nNumberOfCharsToRead,
183 LPDWORD lpNumberOfCharsRead,
186 KEY_EVENT_RECORD KeyEventRecord;
188 PCHAR Buffer = (PCHAR)lpBuffer;
192 for (i=0; (stat && i<nNumberOfCharsToRead);)
194 stat = ReadFile(hConsoleInput,
196 sizeof(KEY_EVENT_RECORD),
199 if (stat && KeyEventRecord.bKeyDown && KeyEventRecord.uChar.AsciiChar != 0)
201 Buffer[i] = KeyEventRecord.uChar.AsciiChar;
205 if (lpNumberOfCharsRead != NULL)
207 *lpNumberOfCharsRead = i;
215 ReadConsoleInput(PINPUT_RECORD Buffer)
217 IO_STATUS_BLOCK Iosb;
220 Buffer->EventType = KEY_EVENT;
221 Status = NtReadFile(StdInput,
226 &Buffer->Event.KeyEvent, //&KeyEventRecord->InputEvent.Event.KeyEvent,
227 sizeof(KEY_EVENT_RECORD),
231 if( Status == STATUS_PENDING )
233 NtWaitForSingleObject(InputEvent,
236 Status = Iosb.Status;
244 ReadConsoleOutputCharacters(LPSTR lpCharacter,
247 PULONG lpNumberOfCharsRead)
249 IO_STATUS_BLOCK IoStatusBlock;
250 ULONG dwBytesReturned;
251 OUTPUT_CHARACTER Buffer;
254 Buffer.dwCoord = dwReadCoord;
256 Status = NtDeviceIoControlFile(StdOutput,
261 IOCTL_CONSOLE_READ_OUTPUT_CHARACTER,
263 sizeof(OUTPUT_CHARACTER),
266 if (Status == STATUS_PENDING)
268 NtWaitForSingleObject(StdOutput,
271 Status = IoStatusBlock.Status;
274 if (NT_SUCCESS(Status) && lpNumberOfCharsRead != NULL)
276 *lpNumberOfCharsRead = Buffer.dwTransfered;
284 ReadConsoleOutputAttributes(PUSHORT lpAttribute,
287 PULONG lpNumberOfAttrsRead)
289 IO_STATUS_BLOCK IoStatusBlock;
290 ULONG dwBytesReturned;
291 OUTPUT_ATTRIBUTE Buffer;
294 Buffer.dwCoord = dwReadCoord;
296 Status = NtDeviceIoControlFile(StdOutput,
301 IOCTL_CONSOLE_READ_OUTPUT_ATTRIBUTE,
303 sizeof(OUTPUT_ATTRIBUTE),
306 if (Status == STATUS_PENDING)
308 NtWaitForSingleObject(StdOutput,
311 Status = IoStatusBlock.Status;
314 if (NT_SUCCESS(Status) && lpNumberOfAttrsRead != NULL)
316 *lpNumberOfAttrsRead = Buffer.dwTransfered;
324 WriteConsoleOutputCharacters(LPCSTR lpCharacter,
328 IO_STATUS_BLOCK IoStatusBlock;
334 Buffer = RtlAllocateHeap(ProcessHeap,
336 nLength + sizeof(COORD));
337 pCoord = (COORD *)Buffer;
338 pText = (PCHAR)(pCoord + 1);
340 *pCoord = dwWriteCoord;
341 memcpy(pText, lpCharacter, nLength);
343 Status = NtDeviceIoControlFile(StdOutput,
348 IOCTL_CONSOLE_WRITE_OUTPUT_CHARACTER,
352 nLength + sizeof(COORD));
353 if (Status == STATUS_PENDING)
355 NtWaitForSingleObject(StdOutput,
358 Status = IoStatusBlock.Status;
361 RtlFreeHeap(ProcessHeap,
370 WriteConsoleOutputAttributes(CONST USHORT *lpAttribute,
373 PULONG lpNumberOfAttrsWritten)
375 IO_STATUS_BLOCK IoStatusBlock;
381 Buffer = RtlAllocateHeap(ProcessHeap,
383 nLength * sizeof(USHORT) + sizeof(COORD));
384 pCoord = (COORD *)Buffer;
385 pAttrib = (PUSHORT)(pCoord + 1);
387 *pCoord = dwWriteCoord;
388 memcpy(pAttrib, lpAttribute, nLength * sizeof(USHORT));
390 Status = NtDeviceIoControlFile(StdOutput,
395 IOCTL_CONSOLE_WRITE_OUTPUT_ATTRIBUTE,
399 nLength * sizeof(USHORT) + sizeof(COORD));
400 if (Status == STATUS_PENDING)
402 NtWaitForSingleObject(StdOutput,
405 Status = IoStatusBlock.Status;
408 RtlFreeHeap(ProcessHeap,
417 FillConsoleOutputAttribute(USHORT wAttribute,
420 PULONG lpNumberOfAttrsWritten)
422 IO_STATUS_BLOCK IoStatusBlock;
423 OUTPUT_ATTRIBUTE Buffer;
424 ULONG dwBytesReturned;
427 Buffer.wAttribute = wAttribute;
428 Buffer.nLength = nLength;
429 Buffer.dwCoord = dwWriteCoord;
431 Status = NtDeviceIoControlFile(StdOutput,
436 IOCTL_CONSOLE_FILL_OUTPUT_ATTRIBUTE,
438 sizeof(OUTPUT_ATTRIBUTE),
440 sizeof(OUTPUT_ATTRIBUTE));
441 if (Status == STATUS_PENDING)
443 NtWaitForSingleObject(StdOutput,
446 Status = IoStatusBlock.Status;
448 if (NT_SUCCESS(Status))
450 *lpNumberOfAttrsWritten = Buffer.dwTransfered;
458 FillConsoleOutputCharacter(CHAR Character,
461 PULONG NumberOfCharsWritten)
463 IO_STATUS_BLOCK IoStatusBlock;
464 OUTPUT_CHARACTER Buffer;
465 ULONG dwBytesReturned;
468 Buffer.cCharacter = Character;
469 Buffer.nLength = Length;
470 Buffer.dwCoord = WriteCoord;
472 Status = NtDeviceIoControlFile(StdOutput,
477 IOCTL_CONSOLE_FILL_OUTPUT_CHARACTER,
479 sizeof(OUTPUT_CHARACTER),
481 sizeof(OUTPUT_CHARACTER));
482 if (Status == STATUS_PENDING)
484 NtWaitForSingleObject(StdOutput,
487 Status = IoStatusBlock.Status;
489 if (NT_SUCCESS(Status))
491 *NumberOfCharsWritten = Buffer.dwTransfered;
499 /*--------------------------------------------------------------
506 HANDLE hConsoleHandle,
511 DWORD dwBytesReturned;
513 if (DeviceIoControl (hConsoleHandle,
514 IOCTL_CONSOLE_GET_MODE,
518 sizeof(CONSOLE_MODE),
522 *lpMode = Buffer.dwMode;
523 SetLastError (ERROR_SUCCESS);
527 SetLastError(0); /* FIXME: What error code? */
532 /*--------------------------------------------------------------
533 * GetConsoleCursorInfo
538 GetConsoleCursorInfo(
539 HANDLE hConsoleOutput,
540 PCONSOLE_CURSOR_INFO lpConsoleCursorInfo
543 DWORD dwBytesReturned;
545 if (DeviceIoControl (hConsoleOutput,
546 IOCTL_CONSOLE_GET_CURSOR_INFO,
550 sizeof(CONSOLE_CURSOR_INFO),
560 SetConsoleMode(HANDLE hConsoleHandle,
563 IO_STATUS_BLOCK IoStatusBlock;
567 Buffer.dwMode = dwMode;
569 Status = NtDeviceIoControlFile(hConsoleHandle,
574 IOCTL_CONSOLE_SET_MODE,
576 sizeof(CONSOLE_MODE),
579 if (Status == STATUS_PENDING)
581 NtWaitForSingleObject(hConsoleHandle,
584 Status = IoStatusBlock.Status;
592 GetConsoleScreenBufferInfo(PCONSOLE_SCREEN_BUFFER_INFO ConsoleScreenBufferInfo)
594 IO_STATUS_BLOCK IoStatusBlock;
597 Status = NtDeviceIoControlFile(StdOutput,
602 IOCTL_CONSOLE_GET_SCREEN_BUFFER_INFO,
605 ConsoleScreenBufferInfo,
606 sizeof(CONSOLE_SCREEN_BUFFER_INFO));
607 if (Status == STATUS_PENDING)
609 NtWaitForSingleObject(StdOutput,
612 Status = IoStatusBlock.Status;
620 SetConsoleCursorInfo(PCONSOLE_CURSOR_INFO lpConsoleCursorInfo)
622 IO_STATUS_BLOCK IoStatusBlock;
625 Status = NtDeviceIoControlFile(StdOutput,
630 IOCTL_CONSOLE_SET_CURSOR_INFO,
631 (PCONSOLE_CURSOR_INFO)lpConsoleCursorInfo,
632 sizeof(CONSOLE_CURSOR_INFO),
635 if (Status == STATUS_PENDING)
637 NtWaitForSingleObject(StdOutput,
640 Status = IoStatusBlock.Status;
647 SetConsoleCursorPosition(COORD dwCursorPosition)
649 CONSOLE_SCREEN_BUFFER_INFO ConsoleScreenBufferInfo;
650 IO_STATUS_BLOCK IoStatusBlock;
653 Status = GetConsoleScreenBufferInfo(&ConsoleScreenBufferInfo);
654 if (!NT_SUCCESS(Status))
657 ConsoleScreenBufferInfo.dwCursorPosition.X = dwCursorPosition.X;
658 ConsoleScreenBufferInfo.dwCursorPosition.Y = dwCursorPosition.Y;
660 Status = NtDeviceIoControlFile(StdOutput,
665 IOCTL_CONSOLE_SET_SCREEN_BUFFER_INFO,
666 &ConsoleScreenBufferInfo,
667 sizeof(CONSOLE_SCREEN_BUFFER_INFO),
670 if (Status == STATUS_PENDING)
672 NtWaitForSingleObject(StdOutput,
675 Status = IoStatusBlock.Status;
682 SetConsoleTextAttribute(WORD wAttributes)
684 IO_STATUS_BLOCK IoStatusBlock;
687 Status = NtDeviceIoControlFile(StdOutput,
692 IOCTL_CONSOLE_SET_TEXT_ATTRIBUTE,
697 if (Status == STATUS_PENDING)
699 NtWaitForSingleObject(StdOutput,
702 Status = IoStatusBlock.Status;
711 ConInKey(PINPUT_RECORD Buffer)
717 ReadConsoleInput(Buffer);
719 if ((Buffer->EventType == KEY_EVENT) &&
720 (Buffer->Event.KeyEvent.bKeyDown == TRUE))
738 ConOutPuts(LPSTR szText)
752 ConOutPrintf(LPSTR szFormat, ...)
758 va_start(arg_ptr, szFormat);
759 vsprintf(szOut, szFormat, arg_ptr);
774 CONSOLE_SCREEN_BUFFER_INFO csbi;
776 GetConsoleScreenBufferInfo(&csbi);
778 return(csbi.dwCursorPosition.X);
785 CONSOLE_SCREEN_BUFFER_INFO csbi;
787 GetConsoleScreenBufferInfo(&csbi);
789 return(csbi.dwCursorPosition.Y);
794 GetScreenSize(SHORT *maxx,
797 CONSOLE_SCREEN_BUFFER_INFO csbi;
799 GetConsoleScreenBufferInfo(&csbi);
802 *maxx = csbi.dwSize.X;
805 *maxy = csbi.dwSize.Y;
810 SetCursorType(BOOL bInsert,
813 CONSOLE_CURSOR_INFO cci;
815 cci.dwSize = bInsert ? 10 : 99;
816 cci.bVisible = bVisible;
818 SetConsoleCursorInfo(&cci);
830 SetConsoleCursorPosition(coPos);
843 FillConsoleOutputAttribute(0x17,
848 FillConsoleOutputCharacter(' ',
856 SetStatusText(PCHAR Text)
862 coPos.Y = yScreen - 1;
864 FillConsoleOutputAttribute(0x70,
869 FillConsoleOutputCharacter(' ',
874 WriteConsoleOutputCharacters(Text,
881 SetTextXY(SHORT x, SHORT y, PCHAR Text)
888 WriteConsoleOutputCharacters(Text,
895 SetInputTextXY(SHORT x, SHORT y, SHORT len, PCHAR Text)
904 Length = strlen(Text);
906 FillConsoleOutputAttribute(0x70,
911 WriteConsoleOutputCharacters(Text,
916 FillConsoleOutputCharacter('_',
921 if (len > Length + 1)
924 FillConsoleOutputCharacter(' ',
933 SetUnderlinedTextXY(SHORT x, SHORT y, PCHAR Text)
942 Length = strlen(Text);
944 WriteConsoleOutputCharacters(Text,
949 FillConsoleOutputCharacter(0xCD,
957 SetInvertedTextXY(SHORT x, SHORT y, PCHAR Text)
966 Length = strlen(Text);
968 FillConsoleOutputAttribute(0x71,
973 WriteConsoleOutputCharacters(Text,
980 SetHighlightedTextXY(SHORT x, SHORT y, PCHAR Text)
989 Length = strlen(Text);
991 FillConsoleOutputAttribute(0x1F,
996 WriteConsoleOutputCharacters(Text,
1003 PrintTextXY(SHORT x, SHORT y, char* fmt,...)
1010 vsprintf(buffer, fmt, ap);
1016 WriteConsoleOutputCharacters(buffer,