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 static UINT LastLoadedCodepage;
44
45 /* FUNCTIONS *****************************************************************/
46
47 typedef struct _CONSOLE_CABINET_CONTEXT
48 {
49 CABINET_CONTEXT CabinetContext;
50 PVOID Data;
51 ULONG Size;
52 } CONSOLE_CABINET_CONTEXT, *PCONSOLE_CABINET_CONTEXT;
53
54 static PVOID
ConsoleCreateFileHandler(IN PCABINET_CONTEXT CabinetContext,IN ULONG FileSize)55 ConsoleCreateFileHandler(
56 IN PCABINET_CONTEXT CabinetContext,
57 IN ULONG FileSize)
58 {
59 PCONSOLE_CABINET_CONTEXT ConsoleCabinetContext;
60
61 ConsoleCabinetContext = (PCONSOLE_CABINET_CONTEXT)CabinetContext;
62 ConsoleCabinetContext->Data = RtlAllocateHeap(ProcessHeap, 0, FileSize);
63 if (!ConsoleCabinetContext->Data)
64 {
65 DPRINT("Failed to allocate %d bytes\n", FileSize);
66 return NULL;
67 }
68 ConsoleCabinetContext->Size = FileSize;
69 return ConsoleCabinetContext->Data;
70 }
71
72 BOOL
73 WINAPI
AllocConsole(VOID)74 AllocConsole(VOID)
75 {
76 NTSTATUS Status;
77 UNICODE_STRING ScreenName = RTL_CONSTANT_STRING(L"\\??\\BlueScreen");
78 UNICODE_STRING KeyboardName = RTL_CONSTANT_STRING(L"\\Device\\KeyboardClass0");
79 OBJECT_ATTRIBUTES ObjectAttributes;
80 IO_STATUS_BLOCK IoStatusBlock;
81 ULONG Enable;
82
83 /* Open the screen */
84 InitializeObjectAttributes(&ObjectAttributes,
85 &ScreenName,
86 0,
87 NULL,
88 NULL);
89 Status = NtOpenFile(&StdOutput,
90 FILE_ALL_ACCESS,
91 &ObjectAttributes,
92 &IoStatusBlock,
93 FILE_OPEN,
94 FILE_SYNCHRONOUS_IO_ALERT);
95 if (!NT_SUCCESS(Status))
96 return FALSE;
97
98 /* Enable it */
99 Enable = TRUE;
100 Status = NtDeviceIoControlFile(StdOutput,
101 NULL,
102 NULL,
103 NULL,
104 &IoStatusBlock,
105 IOCTL_CONSOLE_RESET_SCREEN,
106 &Enable,
107 sizeof(Enable),
108 NULL,
109 0);
110 if (!NT_SUCCESS(Status))
111 {
112 NtClose(StdOutput);
113 return FALSE;
114 }
115
116 /* Default to en-US output codepage */
117 SetConsoleOutputCP(437);
118
119 /* Open the keyboard */
120 InitializeObjectAttributes(&ObjectAttributes,
121 &KeyboardName,
122 0,
123 NULL,
124 NULL);
125 Status = NtOpenFile(&StdInput,
126 FILE_ALL_ACCESS,
127 &ObjectAttributes,
128 &IoStatusBlock,
129 FILE_OPEN,
130 0);
131 if (!NT_SUCCESS(Status))
132 {
133 NtClose(StdOutput);
134 return FALSE;
135 }
136
137 /* Reset the queue state */
138 InputQueueEmpty = TRUE;
139 WaitForInput = FALSE;
140
141 return TRUE;
142 }
143
144
145 BOOL
146 WINAPI
AttachConsole(IN DWORD dwProcessId)147 AttachConsole(
148 IN DWORD dwProcessId)
149 {
150 return FALSE;
151 }
152
153
154 BOOL
155 WINAPI
FreeConsole(VOID)156 FreeConsole(VOID)
157 {
158 /* Reset the queue state */
159 InputQueueEmpty = TRUE;
160 WaitForInput = FALSE;
161
162 if (StdInput != INVALID_HANDLE_VALUE)
163 NtClose(StdInput);
164
165 if (StdOutput != INVALID_HANDLE_VALUE)
166 NtClose(StdOutput);
167
168 return TRUE;
169 }
170
171
172 BOOL
173 WINAPI
WriteConsole(IN HANDLE hConsoleOutput,IN const VOID * lpBuffer,IN DWORD nNumberOfCharsToWrite,OUT LPDWORD lpNumberOfCharsWritten,IN LPVOID lpReserved)174 WriteConsole(
175 IN HANDLE hConsoleOutput,
176 IN const VOID *lpBuffer,
177 IN DWORD nNumberOfCharsToWrite,
178 OUT LPDWORD lpNumberOfCharsWritten,
179 IN LPVOID lpReserved)
180 {
181 IO_STATUS_BLOCK IoStatusBlock;
182 NTSTATUS Status;
183
184 Status = NtWriteFile(hConsoleOutput,
185 NULL,
186 NULL,
187 NULL,
188 &IoStatusBlock,
189 (PVOID)lpBuffer,
190 nNumberOfCharsToWrite,
191 NULL,
192 NULL);
193 if (!NT_SUCCESS(Status))
194 return FALSE;
195
196 *lpNumberOfCharsWritten = IoStatusBlock.Information;
197 return TRUE;
198 }
199
200
201 HANDLE
202 WINAPI
GetStdHandle(IN DWORD nStdHandle)203 GetStdHandle(
204 IN DWORD nStdHandle)
205 {
206 switch (nStdHandle)
207 {
208 case STD_INPUT_HANDLE:
209 return StdInput;
210 case STD_OUTPUT_HANDLE:
211 return StdOutput;
212 default:
213 return INVALID_HANDLE_VALUE;
214 }
215 }
216
217
218 BOOL
219 WINAPI
FlushConsoleInputBuffer(IN HANDLE hConsoleInput)220 FlushConsoleInputBuffer(
221 IN HANDLE hConsoleInput)
222 {
223 NTSTATUS Status;
224 LARGE_INTEGER Offset, Timeout;
225 IO_STATUS_BLOCK IoStatusBlock;
226 KEYBOARD_INPUT_DATA InputData;
227
228 /* Cancel any pending read */
229 if (WaitForInput)
230 NtCancelIoFile(hConsoleInput, &IoStatusBlock);
231
232 /* Reset the queue state */
233 InputQueueEmpty = TRUE;
234 WaitForInput = FALSE;
235
236 /* Flush the keyboard buffer */
237 do
238 {
239 Offset.QuadPart = 0;
240 Status = NtReadFile(hConsoleInput,
241 NULL,
242 NULL,
243 NULL,
244 &IoStatusBlock,
245 &InputData,
246 sizeof(InputData),
247 &Offset,
248 NULL);
249 if (Status == STATUS_PENDING)
250 {
251 Timeout.QuadPart = -100;
252 Status = NtWaitForSingleObject(hConsoleInput, FALSE, &Timeout);
253 if (Status == STATUS_TIMEOUT)
254 {
255 NtCancelIoFile(hConsoleInput, &IoStatusBlock);
256 return TRUE;
257 }
258 }
259 } while (NT_SUCCESS(Status));
260 return FALSE;
261 }
262
263
264 BOOL
265 WINAPI
PeekConsoleInput(IN HANDLE hConsoleInput,OUT PINPUT_RECORD lpBuffer,IN DWORD nLength,OUT LPDWORD lpNumberOfEventsRead)266 PeekConsoleInput(
267 IN HANDLE hConsoleInput,
268 OUT PINPUT_RECORD lpBuffer,
269 IN DWORD nLength,
270 OUT LPDWORD lpNumberOfEventsRead)
271 {
272 NTSTATUS Status;
273 LARGE_INTEGER Offset, Timeout;
274 KEYBOARD_INPUT_DATA InputData;
275
276 if (InputQueueEmpty)
277 {
278 /* Read the keyboard for an event, without waiting */
279 if (!WaitForInput)
280 {
281 Offset.QuadPart = 0;
282 Status = NtReadFile(hConsoleInput,
283 NULL,
284 NULL,
285 NULL,
286 &InputIosb,
287 &InputDataQueue,
288 sizeof(InputDataQueue),
289 &Offset,
290 NULL);
291 if (!NT_SUCCESS(Status))
292 return FALSE;
293 if (Status == STATUS_PENDING)
294 {
295 /* No input yet, we will have to wait next time */
296 *lpNumberOfEventsRead = 0;
297 WaitForInput = TRUE;
298 return TRUE;
299 }
300 }
301 else
302 {
303 /*
304 * We already tried to read from the keyboard and are
305 * waiting for data, check whether something showed up.
306 */
307 Timeout.QuadPart = -100; // Wait just a little bit.
308 Status = NtWaitForSingleObject(hConsoleInput, FALSE, &Timeout);
309 if (Status == STATUS_TIMEOUT)
310 {
311 /* Nothing yet, continue waiting next time */
312 *lpNumberOfEventsRead = 0;
313 WaitForInput = TRUE;
314 return TRUE;
315 }
316 WaitForInput = FALSE;
317 if (!NT_SUCCESS(Status))
318 return FALSE;
319 }
320
321 /* We got something in the queue */
322 InputQueueEmpty = FALSE;
323 WaitForInput = FALSE;
324 }
325
326 /* Fetch from the queue but keep it inside */
327 InputData = InputDataQueue;
328
329 lpBuffer->EventType = KEY_EVENT;
330 Status = IntTranslateKey(hConsoleInput, &InputData, &lpBuffer->Event.KeyEvent);
331 if (!NT_SUCCESS(Status))
332 return FALSE;
333
334 *lpNumberOfEventsRead = 1;
335 return TRUE;
336 }
337
338
339 BOOL
340 WINAPI
ReadConsoleInput(IN HANDLE hConsoleInput,OUT PINPUT_RECORD lpBuffer,IN DWORD nLength,OUT LPDWORD lpNumberOfEventsRead)341 ReadConsoleInput(
342 IN HANDLE hConsoleInput,
343 OUT PINPUT_RECORD lpBuffer,
344 IN DWORD nLength,
345 OUT LPDWORD lpNumberOfEventsRead)
346 {
347 NTSTATUS Status;
348 LARGE_INTEGER Offset;
349 KEYBOARD_INPUT_DATA InputData;
350
351 if (InputQueueEmpty)
352 {
353 /* Read the keyboard and wait for an event, skipping the queue */
354 if (!WaitForInput)
355 {
356 Offset.QuadPart = 0;
357 Status = NtReadFile(hConsoleInput,
358 NULL,
359 NULL,
360 NULL,
361 &InputIosb,
362 &InputDataQueue,
363 sizeof(InputDataQueue),
364 &Offset,
365 NULL);
366 if (Status == STATUS_PENDING)
367 {
368 /* Block and wait for input */
369 WaitForInput = TRUE;
370 Status = NtWaitForSingleObject(hConsoleInput, FALSE, NULL);
371 WaitForInput = FALSE;
372 Status = InputIosb.Status;
373 }
374 if (!NT_SUCCESS(Status))
375 return FALSE;
376 }
377 else
378 {
379 /*
380 * We already tried to read from the keyboard and are
381 * waiting for data, block and wait for input.
382 */
383 Status = NtWaitForSingleObject(hConsoleInput, FALSE, NULL);
384 WaitForInput = FALSE;
385 Status = InputIosb.Status;
386 if (!NT_SUCCESS(Status))
387 return FALSE;
388 }
389 }
390
391 /* Fetch from the queue and empty it */
392 InputData = InputDataQueue;
393 InputQueueEmpty = TRUE;
394
395 lpBuffer->EventType = KEY_EVENT;
396 Status = IntTranslateKey(hConsoleInput, &InputData, &lpBuffer->Event.KeyEvent);
397 if (!NT_SUCCESS(Status))
398 return FALSE;
399
400 *lpNumberOfEventsRead = 1;
401 return TRUE;
402 }
403
404
405 BOOL
406 WINAPI
WriteConsoleOutputCharacterA(HANDLE hConsoleOutput,IN LPCSTR lpCharacter,IN DWORD nLength,IN COORD dwWriteCoord,OUT LPDWORD lpNumberOfCharsWritten)407 WriteConsoleOutputCharacterA(
408 HANDLE hConsoleOutput,
409 IN LPCSTR lpCharacter,
410 IN DWORD nLength,
411 IN COORD dwWriteCoord,
412 OUT LPDWORD lpNumberOfCharsWritten)
413 {
414 IO_STATUS_BLOCK IoStatusBlock;
415 PCHAR Buffer;
416 COORD *pCoord;
417 PCHAR pText;
418 NTSTATUS Status;
419
420 Buffer = (CHAR*)RtlAllocateHeap(ProcessHeap,
421 0,
422 nLength + sizeof(COORD));
423 pCoord = (COORD *)Buffer;
424 pText = (PCHAR)(pCoord + 1);
425
426 *pCoord = dwWriteCoord;
427 memcpy(pText, lpCharacter, nLength);
428
429 Status = NtDeviceIoControlFile(hConsoleOutput,
430 NULL,
431 NULL,
432 NULL,
433 &IoStatusBlock,
434 IOCTL_CONSOLE_WRITE_OUTPUT_CHARACTER,
435 NULL,
436 0,
437 Buffer,
438 nLength + sizeof(COORD));
439
440 RtlFreeHeap(ProcessHeap, 0, Buffer);
441 if (!NT_SUCCESS(Status))
442 return FALSE;
443
444 *lpNumberOfCharsWritten = IoStatusBlock.Information;
445 return TRUE;
446 }
447
448
449 BOOL
450 WINAPI
WriteConsoleOutputCharacterW(HANDLE hConsoleOutput,IN LPCWSTR lpCharacter,IN DWORD nLength,IN COORD dwWriteCoord,OUT LPDWORD lpNumberOfCharsWritten)451 WriteConsoleOutputCharacterW(
452 HANDLE hConsoleOutput,
453 IN LPCWSTR lpCharacter,
454 IN DWORD nLength,
455 IN COORD dwWriteCoord,
456 OUT LPDWORD lpNumberOfCharsWritten)
457 {
458 IO_STATUS_BLOCK IoStatusBlock;
459 PCHAR Buffer;
460 COORD *pCoord;
461 PCHAR pText;
462 NTSTATUS Status;
463 // ULONG i;
464
465 UNICODE_STRING UnicodeString;
466 OEM_STRING OemString;
467 ULONG OemLength;
468
469 UnicodeString.Length = nLength * sizeof(WCHAR);
470 UnicodeString.MaximumLength = nLength * sizeof(WCHAR);
471 UnicodeString.Buffer = (PWSTR)lpCharacter;
472
473 OemLength = RtlUnicodeStringToOemSize(&UnicodeString);
474
475
476 Buffer = (CHAR*)RtlAllocateHeap(ProcessHeap,
477 0,
478 OemLength + sizeof(COORD));
479 // nLength + sizeof(COORD));
480 if (Buffer== NULL)
481 return FALSE;
482
483 pCoord = (COORD *)Buffer;
484 pText = (PCHAR)(pCoord + 1);
485
486 *pCoord = dwWriteCoord;
487
488 OemString.Length = 0;
489 OemString.MaximumLength = OemLength;
490 OemString.Buffer = pText;
491
492 Status = RtlUnicodeStringToOemString(&OemString,
493 &UnicodeString,
494 FALSE);
495 if (!NT_SUCCESS(Status))
496 goto done;
497
498 /* FIXME: use real unicode->oem conversion */
499 // for (i = 0; i < nLength; i++)
500 // pText[i] = (CHAR)lpCharacter[i];
501
502 Status = NtDeviceIoControlFile(hConsoleOutput,
503 NULL,
504 NULL,
505 NULL,
506 &IoStatusBlock,
507 IOCTL_CONSOLE_WRITE_OUTPUT_CHARACTER,
508 NULL,
509 0,
510 Buffer,
511 nLength + sizeof(COORD));
512
513 done:
514 RtlFreeHeap(ProcessHeap, 0, Buffer);
515 if (!NT_SUCCESS(Status))
516 return FALSE;
517
518 *lpNumberOfCharsWritten = IoStatusBlock.Information;
519 return TRUE;
520 }
521
522
523 BOOL
524 WINAPI
FillConsoleOutputAttribute(IN HANDLE hConsoleOutput,IN WORD wAttribute,IN DWORD nLength,IN COORD dwWriteCoord,OUT LPDWORD lpNumberOfAttrsWritten)525 FillConsoleOutputAttribute(
526 IN HANDLE hConsoleOutput,
527 IN WORD wAttribute,
528 IN DWORD nLength,
529 IN COORD dwWriteCoord,
530 OUT LPDWORD lpNumberOfAttrsWritten)
531 {
532 IO_STATUS_BLOCK IoStatusBlock;
533 OUTPUT_ATTRIBUTE Buffer;
534 NTSTATUS Status;
535
536 Buffer.wAttribute = wAttribute;
537 Buffer.nLength = nLength;
538 Buffer.dwCoord = dwWriteCoord;
539
540 Status = NtDeviceIoControlFile(hConsoleOutput,
541 NULL,
542 NULL,
543 NULL,
544 &IoStatusBlock,
545 IOCTL_CONSOLE_FILL_OUTPUT_ATTRIBUTE,
546 &Buffer,
547 sizeof(OUTPUT_ATTRIBUTE),
548 &Buffer,
549 sizeof(OUTPUT_ATTRIBUTE));
550 if (!NT_SUCCESS(Status))
551 return FALSE;
552
553 *lpNumberOfAttrsWritten = Buffer.dwTransfered;
554 return TRUE;
555 }
556
557
558 BOOL
559 WINAPI
FillConsoleOutputCharacterA(IN HANDLE hConsoleOutput,IN CHAR cCharacter,IN DWORD nLength,IN COORD dwWriteCoord,OUT LPDWORD lpNumberOfCharsWritten)560 FillConsoleOutputCharacterA(
561 IN HANDLE hConsoleOutput,
562 IN CHAR cCharacter,
563 IN DWORD nLength,
564 IN COORD dwWriteCoord,
565 OUT LPDWORD lpNumberOfCharsWritten)
566 {
567 IO_STATUS_BLOCK IoStatusBlock;
568 OUTPUT_CHARACTER Buffer;
569 NTSTATUS Status;
570
571 Buffer.cCharacter = cCharacter;
572 Buffer.nLength = nLength;
573 Buffer.dwCoord = dwWriteCoord;
574
575 Status = NtDeviceIoControlFile(hConsoleOutput,
576 NULL,
577 NULL,
578 NULL,
579 &IoStatusBlock,
580 IOCTL_CONSOLE_FILL_OUTPUT_CHARACTER,
581 &Buffer,
582 sizeof(OUTPUT_CHARACTER),
583 &Buffer,
584 sizeof(OUTPUT_CHARACTER));
585 if (!NT_SUCCESS(Status))
586 return FALSE;
587
588 *lpNumberOfCharsWritten = Buffer.dwTransfered;
589 return TRUE;
590 }
591
592
593 BOOL
594 WINAPI
GetConsoleScreenBufferInfo(IN HANDLE hConsoleOutput,OUT PCONSOLE_SCREEN_BUFFER_INFO lpConsoleScreenBufferInfo)595 GetConsoleScreenBufferInfo(
596 IN HANDLE hConsoleOutput,
597 OUT PCONSOLE_SCREEN_BUFFER_INFO lpConsoleScreenBufferInfo)
598 {
599 IO_STATUS_BLOCK IoStatusBlock;
600 NTSTATUS Status;
601
602 Status = NtDeviceIoControlFile(hConsoleOutput,
603 NULL,
604 NULL,
605 NULL,
606 &IoStatusBlock,
607 IOCTL_CONSOLE_GET_SCREEN_BUFFER_INFO,
608 NULL,
609 0,
610 lpConsoleScreenBufferInfo,
611 sizeof(CONSOLE_SCREEN_BUFFER_INFO));
612 return NT_SUCCESS(Status);
613 }
614
615
616 BOOL
617 WINAPI
SetConsoleCursorInfo(IN HANDLE hConsoleOutput,IN const CONSOLE_CURSOR_INFO * lpConsoleCursorInfo)618 SetConsoleCursorInfo(
619 IN HANDLE hConsoleOutput,
620 IN const CONSOLE_CURSOR_INFO *lpConsoleCursorInfo)
621 {
622 IO_STATUS_BLOCK IoStatusBlock;
623 NTSTATUS Status;
624
625 Status = NtDeviceIoControlFile(hConsoleOutput,
626 NULL,
627 NULL,
628 NULL,
629 &IoStatusBlock,
630 IOCTL_CONSOLE_SET_CURSOR_INFO,
631 (PCONSOLE_CURSOR_INFO)lpConsoleCursorInfo,
632 sizeof(CONSOLE_CURSOR_INFO),
633 NULL,
634 0);
635 return NT_SUCCESS(Status);
636 }
637
638
639 BOOL
640 WINAPI
SetConsoleCursorPosition(IN HANDLE hConsoleOutput,IN COORD dwCursorPosition)641 SetConsoleCursorPosition(
642 IN HANDLE hConsoleOutput,
643 IN COORD dwCursorPosition)
644 {
645 CONSOLE_SCREEN_BUFFER_INFO ConsoleScreenBufferInfo;
646 IO_STATUS_BLOCK IoStatusBlock;
647 NTSTATUS Status;
648
649 Status = GetConsoleScreenBufferInfo(hConsoleOutput, &ConsoleScreenBufferInfo);
650 if (!NT_SUCCESS(Status))
651 return FALSE;
652
653 ConsoleScreenBufferInfo.dwCursorPosition.X = dwCursorPosition.X;
654 ConsoleScreenBufferInfo.dwCursorPosition.Y = dwCursorPosition.Y;
655
656 Status = NtDeviceIoControlFile(hConsoleOutput,
657 NULL,
658 NULL,
659 NULL,
660 &IoStatusBlock,
661 IOCTL_CONSOLE_SET_SCREEN_BUFFER_INFO,
662 &ConsoleScreenBufferInfo,
663 sizeof(CONSOLE_SCREEN_BUFFER_INFO),
664 NULL,
665 0);
666 return NT_SUCCESS(Status);
667 }
668
669
670 BOOL
671 WINAPI
SetConsoleTextAttribute(IN HANDLE hConsoleOutput,IN WORD wAttributes)672 SetConsoleTextAttribute(
673 IN HANDLE hConsoleOutput,
674 IN WORD wAttributes)
675 {
676 IO_STATUS_BLOCK IoStatusBlock;
677 NTSTATUS Status;
678
679 Status = NtDeviceIoControlFile(hConsoleOutput,
680 NULL,
681 NULL,
682 NULL,
683 &IoStatusBlock,
684 IOCTL_CONSOLE_SET_TEXT_ATTRIBUTE,
685 &wAttributes,
686 sizeof(USHORT),
687 NULL,
688 0);
689 return NT_SUCCESS(Status);
690 }
691
692
693 BOOL
694 WINAPI
SetConsoleOutputCP(IN UINT wCodepage)695 SetConsoleOutputCP(
696 IN UINT wCodepage)
697 {
698 static PCWSTR FontFile = L"\\SystemRoot\\vgafonts.cab";
699 WCHAR FontName[20];
700 CONSOLE_CABINET_CONTEXT ConsoleCabinetContext;
701 PCABINET_CONTEXT CabinetContext = &ConsoleCabinetContext.CabinetContext;
702 CAB_SEARCH Search;
703 ULONG CabStatus;
704 HANDLE hConsoleOutput;
705 IO_STATUS_BLOCK IoStatusBlock;
706 NTSTATUS Status;
707
708 if (wCodepage == LastLoadedCodepage)
709 return TRUE;
710
711 hConsoleOutput = GetStdHandle(STD_OUTPUT_HANDLE);
712
713 CabinetInitialize(CabinetContext);
714 CabinetSetEventHandlers(CabinetContext,
715 NULL, NULL, NULL, ConsoleCreateFileHandler);
716 CabinetSetCabinetName(CabinetContext, FontFile);
717
718 CabStatus = CabinetOpen(CabinetContext);
719 if (CabStatus != CAB_STATUS_SUCCESS)
720 {
721 DPRINT("CabinetOpen('%S') returned 0x%08x\n", FontFile, CabStatus);
722 return FALSE;
723 }
724
725 RtlStringCbPrintfW(FontName, sizeof(FontName),
726 L"%u-8x8.bin", wCodepage);
727 CabStatus = CabinetFindFirst(CabinetContext, FontName, &Search);
728 if (CabStatus != CAB_STATUS_SUCCESS)
729 {
730 DPRINT("CabinetFindFirst('%S', '%S') returned 0x%08x\n", FontFile, FontName, CabStatus);
731 CabinetClose(CabinetContext);
732 return FALSE;
733 }
734
735 CabStatus = CabinetExtractFile(CabinetContext, &Search);
736 CabinetClose(CabinetContext);
737 if (CabStatus != CAB_STATUS_SUCCESS)
738 {
739 DPRINT("CabinetExtractFile('%S', '%S') returned 0x%08x\n", FontFile, FontName, CabStatus);
740 if (ConsoleCabinetContext.Data)
741 RtlFreeHeap(ProcessHeap, 0, ConsoleCabinetContext.Data);
742 return FALSE;
743 }
744 ASSERT(ConsoleCabinetContext.Data);
745
746 Status = NtDeviceIoControlFile(hConsoleOutput,
747 NULL,
748 NULL,
749 NULL,
750 &IoStatusBlock,
751 IOCTL_CONSOLE_LOADFONT,
752 ConsoleCabinetContext.Data,
753 ConsoleCabinetContext.Size,
754 NULL,
755 0);
756
757 RtlFreeHeap(ProcessHeap, 0, ConsoleCabinetContext.Data);
758
759 if (!NT_SUCCESS(Status))
760 return FALSE;
761
762 LastLoadedCodepage = wCodepage;
763 return TRUE;
764 }
765
766
767 /* EOF */
768