[SHELL32] *.rc: Strip all unneeded WS_DISABLED in dlg style (#6675)
[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 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
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
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
147 AttachConsole(
148 IN DWORD dwProcessId)
149 {
150 return FALSE;
151 }
152
153
154 BOOL
155 WINAPI
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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 */