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 WriteConsoleOutputCharactersW(LPCWSTR lpCharacter,
374 IO_STATUS_BLOCK IoStatusBlock;
381 Buffer = RtlAllocateHeap(ProcessHeap,
383 nLength + sizeof(COORD));
384 pCoord = (COORD *)Buffer;
385 pText = (PCHAR)(pCoord + 1);
387 *pCoord = dwWriteCoord;
389 /* FIXME: use real unicode->oem conversion */
390 for (i = 0; i < nLength; i++)
391 pText[i] = (CHAR)lpCharacter[i];
394 Status = NtDeviceIoControlFile(StdOutput,
399 IOCTL_CONSOLE_WRITE_OUTPUT_CHARACTER,
403 nLength + sizeof(COORD));
404 if (Status == STATUS_PENDING)
406 NtWaitForSingleObject(StdOutput,
409 Status = IoStatusBlock.Status;
412 RtlFreeHeap(ProcessHeap,
421 WriteConsoleOutputAttributes(CONST USHORT *lpAttribute,
424 PULONG lpNumberOfAttrsWritten)
426 IO_STATUS_BLOCK IoStatusBlock;
432 Buffer = RtlAllocateHeap(ProcessHeap,
434 nLength * sizeof(USHORT) + sizeof(COORD));
435 pCoord = (COORD *)Buffer;
436 pAttrib = (PUSHORT)(pCoord + 1);
438 *pCoord = dwWriteCoord;
439 memcpy(pAttrib, lpAttribute, nLength * sizeof(USHORT));
441 Status = NtDeviceIoControlFile(StdOutput,
446 IOCTL_CONSOLE_WRITE_OUTPUT_ATTRIBUTE,
450 nLength * sizeof(USHORT) + sizeof(COORD));
451 if (Status == STATUS_PENDING)
453 NtWaitForSingleObject(StdOutput,
456 Status = IoStatusBlock.Status;
459 RtlFreeHeap(ProcessHeap,
468 FillConsoleOutputAttribute(USHORT wAttribute,
471 PULONG lpNumberOfAttrsWritten)
473 IO_STATUS_BLOCK IoStatusBlock;
474 OUTPUT_ATTRIBUTE Buffer;
475 ULONG dwBytesReturned;
478 Buffer.wAttribute = wAttribute;
479 Buffer.nLength = nLength;
480 Buffer.dwCoord = dwWriteCoord;
482 Status = NtDeviceIoControlFile(StdOutput,
487 IOCTL_CONSOLE_FILL_OUTPUT_ATTRIBUTE,
489 sizeof(OUTPUT_ATTRIBUTE),
491 sizeof(OUTPUT_ATTRIBUTE));
492 if (Status == STATUS_PENDING)
494 NtWaitForSingleObject(StdOutput,
497 Status = IoStatusBlock.Status;
499 if (NT_SUCCESS(Status))
501 *lpNumberOfAttrsWritten = Buffer.dwTransfered;
509 FillConsoleOutputCharacter(CHAR Character,
512 PULONG NumberOfCharsWritten)
514 IO_STATUS_BLOCK IoStatusBlock;
515 OUTPUT_CHARACTER Buffer;
516 ULONG dwBytesReturned;
519 Buffer.cCharacter = Character;
520 Buffer.nLength = Length;
521 Buffer.dwCoord = WriteCoord;
523 Status = NtDeviceIoControlFile(StdOutput,
528 IOCTL_CONSOLE_FILL_OUTPUT_CHARACTER,
530 sizeof(OUTPUT_CHARACTER),
532 sizeof(OUTPUT_CHARACTER));
533 if (Status == STATUS_PENDING)
535 NtWaitForSingleObject(StdOutput,
538 Status = IoStatusBlock.Status;
540 if (NT_SUCCESS(Status))
542 *NumberOfCharsWritten = Buffer.dwTransfered;
550 /*--------------------------------------------------------------
557 HANDLE hConsoleHandle,
562 DWORD dwBytesReturned;
564 if (DeviceIoControl (hConsoleHandle,
565 IOCTL_CONSOLE_GET_MODE,
569 sizeof(CONSOLE_MODE),
573 *lpMode = Buffer.dwMode;
574 SetLastError (ERROR_SUCCESS);
578 SetLastError(0); /* FIXME: What error code? */
583 /*--------------------------------------------------------------
584 * GetConsoleCursorInfo
589 GetConsoleCursorInfo(
590 HANDLE hConsoleOutput,
591 PCONSOLE_CURSOR_INFO lpConsoleCursorInfo
594 DWORD dwBytesReturned;
596 if (DeviceIoControl (hConsoleOutput,
597 IOCTL_CONSOLE_GET_CURSOR_INFO,
601 sizeof(CONSOLE_CURSOR_INFO),
611 SetConsoleMode(HANDLE hConsoleHandle,
614 IO_STATUS_BLOCK IoStatusBlock;
618 Buffer.dwMode = dwMode;
620 Status = NtDeviceIoControlFile(hConsoleHandle,
625 IOCTL_CONSOLE_SET_MODE,
627 sizeof(CONSOLE_MODE),
630 if (Status == STATUS_PENDING)
632 NtWaitForSingleObject(hConsoleHandle,
635 Status = IoStatusBlock.Status;
643 GetConsoleScreenBufferInfo(PCONSOLE_SCREEN_BUFFER_INFO ConsoleScreenBufferInfo)
645 IO_STATUS_BLOCK IoStatusBlock;
648 Status = NtDeviceIoControlFile(StdOutput,
653 IOCTL_CONSOLE_GET_SCREEN_BUFFER_INFO,
656 ConsoleScreenBufferInfo,
657 sizeof(CONSOLE_SCREEN_BUFFER_INFO));
658 if (Status == STATUS_PENDING)
660 NtWaitForSingleObject(StdOutput,
663 Status = IoStatusBlock.Status;
671 SetConsoleCursorInfo(PCONSOLE_CURSOR_INFO lpConsoleCursorInfo)
673 IO_STATUS_BLOCK IoStatusBlock;
676 Status = NtDeviceIoControlFile(StdOutput,
681 IOCTL_CONSOLE_SET_CURSOR_INFO,
682 (PCONSOLE_CURSOR_INFO)lpConsoleCursorInfo,
683 sizeof(CONSOLE_CURSOR_INFO),
686 if (Status == STATUS_PENDING)
688 NtWaitForSingleObject(StdOutput,
691 Status = IoStatusBlock.Status;
698 SetConsoleCursorPosition(COORD dwCursorPosition)
700 CONSOLE_SCREEN_BUFFER_INFO ConsoleScreenBufferInfo;
701 IO_STATUS_BLOCK IoStatusBlock;
704 Status = GetConsoleScreenBufferInfo(&ConsoleScreenBufferInfo);
705 if (!NT_SUCCESS(Status))
708 ConsoleScreenBufferInfo.dwCursorPosition.X = dwCursorPosition.X;
709 ConsoleScreenBufferInfo.dwCursorPosition.Y = dwCursorPosition.Y;
711 Status = NtDeviceIoControlFile(StdOutput,
716 IOCTL_CONSOLE_SET_SCREEN_BUFFER_INFO,
717 &ConsoleScreenBufferInfo,
718 sizeof(CONSOLE_SCREEN_BUFFER_INFO),
721 if (Status == STATUS_PENDING)
723 NtWaitForSingleObject(StdOutput,
726 Status = IoStatusBlock.Status;
733 SetConsoleTextAttribute(WORD wAttributes)
735 IO_STATUS_BLOCK IoStatusBlock;
738 Status = NtDeviceIoControlFile(StdOutput,
743 IOCTL_CONSOLE_SET_TEXT_ATTRIBUTE,
748 if (Status == STATUS_PENDING)
750 NtWaitForSingleObject(StdOutput,
753 Status = IoStatusBlock.Status;
762 ConInKey(PINPUT_RECORD Buffer)
768 ReadConsoleInput(Buffer);
770 if ((Buffer->EventType == KEY_EVENT) &&
771 (Buffer->Event.KeyEvent.bKeyDown == TRUE))
789 ConOutPuts(LPSTR szText)
803 ConOutPrintf(LPSTR szFormat, ...)
809 va_start(arg_ptr, szFormat);
810 vsprintf(szOut, szFormat, arg_ptr);
825 CONSOLE_SCREEN_BUFFER_INFO csbi;
827 GetConsoleScreenBufferInfo(&csbi);
829 return(csbi.dwCursorPosition.X);
836 CONSOLE_SCREEN_BUFFER_INFO csbi;
838 GetConsoleScreenBufferInfo(&csbi);
840 return(csbi.dwCursorPosition.Y);
845 GetScreenSize(SHORT *maxx,
848 CONSOLE_SCREEN_BUFFER_INFO csbi;
850 GetConsoleScreenBufferInfo(&csbi);
853 *maxx = csbi.dwSize.X;
856 *maxy = csbi.dwSize.Y;
861 SetCursorType(BOOL bInsert,
864 CONSOLE_CURSOR_INFO cci;
866 cci.dwSize = bInsert ? 10 : 99;
867 cci.bVisible = bVisible;
869 SetConsoleCursorInfo(&cci);
881 SetConsoleCursorPosition(coPos);
894 FillConsoleOutputAttribute(0x17,
899 FillConsoleOutputCharacter(' ',
907 SetStatusText(PCHAR Text)
913 coPos.Y = yScreen - 1;
915 FillConsoleOutputAttribute(0x70,
920 FillConsoleOutputCharacter(' ',
925 WriteConsoleOutputCharacters(Text,
932 SetTextXY(SHORT x, SHORT y, PCHAR Text)
939 WriteConsoleOutputCharacters(Text,
946 SetInputTextXY(SHORT x, SHORT y, SHORT len, PWCHAR Text)
955 Length = wcslen(Text);
956 if (Length > len - 1)
961 FillConsoleOutputAttribute(0x70,
966 WriteConsoleOutputCharactersW(Text,
971 FillConsoleOutputCharacter('_',
976 if (len > Length + 1)
979 FillConsoleOutputCharacter(' ',
988 SetUnderlinedTextXY(SHORT x, SHORT y, PCHAR Text)
997 Length = strlen(Text);
999 WriteConsoleOutputCharacters(Text,
1004 FillConsoleOutputCharacter(0xCD,
1012 SetInvertedTextXY(SHORT x, SHORT y, PCHAR Text)
1021 Length = strlen(Text);
1023 FillConsoleOutputAttribute(0x71,
1028 WriteConsoleOutputCharacters(Text,
1035 SetHighlightedTextXY(SHORT x, SHORT y, PCHAR Text)
1044 Length = strlen(Text);
1046 FillConsoleOutputAttribute(0x1F,
1051 WriteConsoleOutputCharacters(Text,
1058 PrintTextXY(SHORT x, SHORT y, char* fmt, ...)
1065 vsprintf(buffer, fmt, ap);
1071 WriteConsoleOutputCharacters(buffer,
1078 PrintTextXYN(SHORT x, SHORT y, SHORT len, char* fmt, ...)
1087 vsprintf(buffer, fmt, ap);
1093 Length = strlen(buffer);
1094 if (Length > len - 1)
1099 WriteConsoleOutputCharacters(buffer,
1107 FillConsoleOutputCharacter(' ',