[USETUP] Implement most of the "upgrade" page, where existing NTOS installations...
[reactos.git] / base / setup / usetup / console.c
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 = (LPWSTR)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 */