Merge r68232 to get Windows' rpcrt4.dll to work under ReactOS.
[reactos.git] / reactos / base / setup / usetup / cmdcons.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS text-mode setup
4 * FILE: subsys/system/usetup/cmdcons.c
5 * PURPOSE: Recovery console
6 * PROGRAMMER: Eric Kohl
7 */
8
9 #include "usetup.h"
10
11 #define NDEBUG
12 #include <debug.h>
13
14
15 //#define FEATURE_HISTORY
16
17 typedef struct _CONSOLE_STATE
18 {
19 SHORT maxx;
20 SHORT maxy;
21 BOOLEAN bInsert;
22 BOOLEAN bExit;
23 } CONSOLE_STATE, *PCONSOLE_STATE;
24
25 typedef struct tagCOMMAND
26 {
27 LPSTR name;
28 INT flags;
29 INT (*func)(PCONSOLE_STATE, LPSTR);
30 } COMMAND, *LPCOMMAND;
31
32
33 static
34 INT
35 CommandCls(
36 PCONSOLE_STATE State,
37 LPSTR param);
38
39 static
40 INT
41 CommandDumpSector(
42 PCONSOLE_STATE State,
43 LPSTR param);
44
45 static
46 INT
47 CommandExit(
48 PCONSOLE_STATE State,
49 LPSTR param);
50
51 static
52 INT
53 CommandHelp(
54 PCONSOLE_STATE State,
55 LPSTR param);
56
57 COMMAND
58 Commands[] =
59 {
60 {"cls", 0, CommandCls},
61 {"dumpsector", 0, CommandDumpSector},
62 {"exit", 0, CommandExit},
63 {"help", 0, CommandHelp},
64 {NULL, 0, NULL}
65 };
66
67
68 static
69 VOID
70 freep(
71 LPSTR *p)
72 {
73 LPSTR *q;
74
75 if (!p)
76 return;
77
78 q = p;
79 while (*q)
80 RtlFreeHeap(ProcessHeap, 0, *q++);
81
82 RtlFreeHeap(ProcessHeap, 0, p);
83 }
84
85
86 static
87 VOID
88 StripQuotes(
89 LPSTR in)
90 {
91 LPSTR out = in;
92
93 for (; *in; in++)
94 {
95 if (*in != '"')
96 *out++ = *in;
97 }
98
99 *out = '\0';
100 }
101
102
103 BOOL
104 add_entry(
105 LPINT ac,
106 LPSTR **arg,
107 LPCSTR entry)
108 {
109 LPSTR q;
110 LPSTR *oldarg;
111
112 q = RtlAllocateHeap(ProcessHeap, 0, strlen(entry) + 1);
113 if (q == NULL)
114 return FALSE;
115
116 strcpy(q, entry);
117 oldarg = *arg;
118 *arg = RtlReAllocateHeap(ProcessHeap, 0, oldarg, (*ac + 2) * sizeof(LPSTR));
119 if (*arg == NULL)
120 {
121 RtlFreeHeap(ProcessHeap, 0, q);
122 *arg = oldarg;
123 return FALSE;
124 }
125
126 /* save new entry */
127 (*arg)[*ac] = q;
128 (*arg)[++(*ac)] = NULL;
129
130 return TRUE;
131 }
132
133 static
134 LPSTR *
135 split(
136 LPSTR s,
137 LPINT args)
138 {
139 LPSTR *arg;
140 LPSTR start;
141 LPSTR q;
142 INT ac;
143 INT_PTR len;
144 BOOL bQuoted;
145
146 arg = RtlAllocateHeap(ProcessHeap, 0 , sizeof(LPTSTR));
147 if (arg == NULL)
148 return NULL;
149
150 *arg = NULL;
151
152 ac = 0;
153 while (*s)
154 {
155 bQuoted = FALSE;
156
157 /* skip leading spaces */
158 while (*s && (isspace(*s) || iscntrl(*s)))
159 ++s;
160
161 start = s;
162
163 /* the first character can be '/' */
164 if (*s == '/')
165 s++;
166
167 /* skip to next word delimiter or start of next option */
168 while (isprint(*s))
169 {
170 /* if quote (") then set bQuoted */
171 bQuoted ^= (*s == '\"');
172
173 /* Check if we have unquoted text */
174 if (!bQuoted)
175 {
176 /* check for separators */
177 if (isspace(*s) || (*s == '/'))
178 {
179 /* Make length at least one character */
180 if (s == start)
181 s++;
182 break;
183 }
184 }
185
186 s++;
187 }
188
189 /* a word was found */
190 if (s != start)
191 {
192 len = s - start;
193 q = RtlAllocateHeap(ProcessHeap, 0, len + 1);
194 if (q == NULL)
195 {
196 freep(arg);
197 return NULL;
198 }
199
200 memcpy(q, start, len);
201 q[len] = '\0';
202
203 StripQuotes(q);
204
205 if (!add_entry(&ac, &arg, q))
206 {
207 RtlFreeHeap(ProcessHeap, 0, q);
208 freep(arg);
209 return NULL;
210 }
211
212 RtlFreeHeap(ProcessHeap, 0, q);
213 }
214 }
215
216 *args = ac;
217
218 return arg;
219 }
220
221
222 static
223 INT
224 CommandCls(
225 PCONSOLE_STATE State,
226 LPSTR param)
227 {
228 #if 0
229 HANDLE hOutput;
230 COORD coPos;
231 DWORD dwWritten;
232
233 #if 0
234 if (!strncmp(param, "/?", 2))
235 {
236 ConOutResPaging(TRUE,STRING_CLS_HELP);
237 return 0;
238 }
239 #endif
240
241 coPos.X = 0;
242 coPos.Y = 0;
243
244 hOutput = GetStdHandle(STD_OUTPUT_HANDLE);
245 FillConsoleOutputAttribute(hOutput, csbi.wAttributes,
246 State->maxx * State->maxy,
247 coPos, &dwWritten);
248 FillConsoleOutputCharacter(hOutput, ' ',
249 State->maxx * State->maxy,
250 coPos, &dwWritten);
251 SetConsoleCursorPosition(hOutput, coPos);
252 #endif
253
254 CONSOLE_ClearScreen();
255 CONSOLE_SetCursorXY(0, 0);
256
257 return 0;
258 }
259
260
261 void HexDump(PUCHAR buffer, ULONG size)
262 {
263 ULONG offset = 0;
264 PUCHAR ptr;
265
266 while (offset < (size & ~15))
267 {
268 ptr = (PUCHAR)((ULONG_PTR)buffer + offset);
269 CONSOLE_ConOutPrintf("%04lx %02hx %02hx %02hx %02hx %02hx %02hx %02hx %02hx %02hx %02hx %02hx %02hx %02hx %02hx %02hx %02hx\n",
270 offset,
271 ptr[0],
272 ptr[1],
273 ptr[2],
274 ptr[3],
275 ptr[4],
276 ptr[5],
277 ptr[6],
278 ptr[7],
279 ptr[8],
280 ptr[9],
281 ptr[10],
282 ptr[11],
283 ptr[12],
284 ptr[13],
285 ptr[14],
286 ptr[15]);
287 offset += 16;
288 }
289
290 if (offset < size)
291 {
292 ptr = (PUCHAR)((ULONG_PTR)buffer + offset);
293 CONSOLE_ConOutPrintf("%04lx ", offset);
294 while (offset < size)
295 {
296 CONSOLE_ConOutPrintf(" %02hx", *ptr);
297 offset++;
298 ptr++;
299 }
300
301 CONSOLE_ConOutPrintf("\n");
302 }
303
304 CONSOLE_ConOutPrintf("\n");
305 }
306
307 static
308 INT
309 CommandDumpSector(
310 PCONSOLE_STATE State,
311 LPSTR param)
312 {
313 OBJECT_ATTRIBUTES ObjectAttributes;
314 IO_STATUS_BLOCK IoStatusBlock;
315 UNICODE_STRING PathName;
316 HANDLE hDisk = NULL;
317 DISK_GEOMETRY DiskGeometry;
318 NTSTATUS Status;
319
320 LPTSTR *argv = NULL;
321 INT argc = 0;
322 WCHAR DriveName[40];
323 ULONG ulDrive;
324 // ULONG ulSector;
325 LARGE_INTEGER Sector, SectorCount, Offset;
326 PUCHAR Buffer = NULL;
327
328 DPRINT1("param: %s\n", param);
329
330 if (!strncmp(param, "/?", 2))
331 {
332 CONSOLE_ConOutPrintf("DUMPSECT DiskNumber Sector\n\nDumps a disk sector to the screen.\n\n");
333 return 0;
334 }
335
336 argv = split(param, &argc);
337
338 DPRINT1("argc: %d\n", argc);
339 DPRINT1("argv: %p\n", argv);
340
341 if (argc != 2)
342 {
343 goto done;
344 }
345
346 DPRINT1("Device: %s\n", argv[0]);
347 DPRINT1("Sector: %s\n", argv[1]);
348
349 ulDrive = strtoul(argv[0], NULL, 0);
350 // ulSector = strtoul(argv[1], NULL, 0);
351 Sector.QuadPart = _atoi64(argv[1]);
352
353 /* Build full drive name */
354 // swprintf(DriveName, L"\\\\.\\PHYSICALDRIVE%lu", ulDrive);
355 swprintf(DriveName, L"\\Device\\Harddisk%lu\\Partition0", ulDrive);
356
357 RtlInitUnicodeString(&PathName,
358 DriveName);
359
360 InitializeObjectAttributes(&ObjectAttributes,
361 &PathName,
362 OBJ_CASE_INSENSITIVE | OBJ_INHERIT,
363 NULL,
364 NULL);
365
366 Status = NtOpenFile(&hDisk,
367 GENERIC_READ | SYNCHRONIZE,
368 &ObjectAttributes,
369 &IoStatusBlock,
370 FILE_SHARE_READ,
371 FILE_SYNCHRONOUS_IO_NONALERT | FILE_NON_DIRECTORY_FILE | FILE_RANDOM_ACCESS);
372 if (!NT_SUCCESS(Status))
373 {
374 DPRINT1("NtCreateFile failed (Status 0x%08lx)\n", Status);
375 goto done;
376 }
377
378 Status = NtDeviceIoControlFile(hDisk,
379 NULL,
380 NULL,
381 NULL,
382 &IoStatusBlock,
383 IOCTL_DISK_GET_DRIVE_GEOMETRY,
384 NULL,
385 0,
386 &DiskGeometry,
387 sizeof(DISK_GEOMETRY));
388 if (!NT_SUCCESS(Status))
389 {
390 DPRINT1("NtDeviceIoControlFile failed (Status 0x%08lx)\n", Status);
391 goto done;
392 }
393
394 DPRINT1("Drive number: %lu\n", ulDrive);
395 DPRINT1("Cylinders: %I64u\nMediaType: %x\nTracksPerCylinder: %lu\n"
396 "SectorsPerTrack: %lu\nBytesPerSector: %lu\n\n",
397 DiskGeometry.Cylinders.QuadPart,
398 DiskGeometry.MediaType,
399 DiskGeometry.TracksPerCylinder,
400 DiskGeometry.SectorsPerTrack,
401 DiskGeometry.BytesPerSector);
402
403 DPRINT1("Sector: %I64u\n", Sector.QuadPart);
404
405 SectorCount.QuadPart = DiskGeometry.Cylinders.QuadPart *
406 DiskGeometry.TracksPerCylinder,
407 DiskGeometry.SectorsPerTrack;
408 if (Sector.QuadPart >= SectorCount.QuadPart)
409 {
410 CONSOLE_ConOutPrintf("Invalid sector number! Valid range: [0 - %I64u]\n", SectorCount.QuadPart - 1);
411 goto done;
412 }
413
414 Buffer = RtlAllocateHeap(ProcessHeap, 0, DiskGeometry.BytesPerSector);
415 if (Buffer == NULL)
416 {
417 DPRINT1("Buffer allocation failed\n");
418 goto done;
419 }
420
421
422 Offset.QuadPart = Sector.QuadPart * DiskGeometry.BytesPerSector;
423 DPRINT1("Offset: %I64u\n", Offset.QuadPart);
424
425 Status = NtReadFile(hDisk,
426 NULL,
427 NULL,
428 NULL,
429 &IoStatusBlock,
430 Buffer,
431 DiskGeometry.BytesPerSector,
432 &Offset,
433 NULL);
434 if (!NT_SUCCESS(Status))
435 {
436 DPRINT1("NtReadFile failed (Status 0x%08lx)\n", Status);
437 goto done;
438 }
439
440 HexDump(Buffer, DiskGeometry.BytesPerSector);
441
442 done:
443 if (Buffer != NULL)
444 RtlFreeHeap(ProcessHeap, 0, Buffer);
445
446 if (hDisk != NULL)
447 NtClose(hDisk);
448
449 freep(argv);
450
451 return 0;
452 }
453
454
455 static
456 INT
457 CommandExit(
458 PCONSOLE_STATE State,
459 LPSTR param)
460 {
461 #if 0
462 if (!strncmp(param, "/?", 2))
463 {
464 ConOutResPaging(TRUE,STRING_EXIT_HELP);
465 /* Just make sure */
466 bExit = FALSE;
467 /* Dont exit */
468 return 0;
469 }
470 #endif
471
472 State->bExit = TRUE;
473
474 return 0;
475 }
476
477
478 static
479 INT
480 CommandHelp(
481 PCONSOLE_STATE State,
482 LPSTR param)
483 {
484 CONSOLE_ConOutPrintf("CLS\n");
485 CONSOLE_ConOutPrintf("DUMPSECTOR\n");
486 CONSOLE_ConOutPrintf("EXIT\n");
487 CONSOLE_ConOutPrintf("HELP\n");
488 CONSOLE_ConOutPrintf("\n");
489
490 return 0;
491 }
492
493
494 static
495 VOID
496 ClearCommandLine(
497 LPSTR str,
498 INT maxlen,
499 SHORT orgx,
500 SHORT orgy)
501 {
502 INT count;
503
504 CONSOLE_SetCursorXY(orgx, orgy);
505 for (count = 0; count < (INT)strlen(str); count++)
506 CONSOLE_ConOutChar(' ');
507 memset(str, 0, maxlen);
508 CONSOLE_SetCursorXY(orgx, orgy);
509 }
510
511
512 static
513 BOOL
514 ReadCommand(
515 PCONSOLE_STATE State,
516 LPSTR str,
517 INT maxlen)
518 {
519 SHORT orgx; /* origin x/y */
520 SHORT orgy;
521 SHORT curx; /*current x/y cursor position*/
522 SHORT cury;
523 SHORT tempscreen;
524 INT count; /*used in some for loops*/
525 INT current = 0; /*the position of the cursor in the string (str)*/
526 INT charcount = 0;/*chars in the string (str)*/
527 INPUT_RECORD ir;
528 CHAR ch;
529 BOOL bReturn = FALSE;
530 BOOL bCharInput;
531 #ifdef FEATURE_HISTORY
532 //BOOL bContinue=FALSE;/*is TRUE the second case will not be executed*/
533 CHAR PreviousChar;
534 #endif
535
536
537 CONSOLE_GetCursorXY(&orgx, &orgy);
538 curx = orgx;
539 cury = orgy;
540
541 memset(str, 0, maxlen * sizeof(CHAR));
542
543 CONSOLE_SetCursorType(State->bInsert, TRUE);
544
545 do
546 {
547 bReturn = FALSE;
548 CONSOLE_ConInKey(&ir);
549
550 if (ir.Event.KeyEvent.dwControlKeyState &
551 (RIGHT_ALT_PRESSED |LEFT_ALT_PRESSED|
552 RIGHT_CTRL_PRESSED|LEFT_CTRL_PRESSED) )
553 {
554 switch (ir.Event.KeyEvent.wVirtualKeyCode)
555 {
556 #ifdef FEATURE_HISTORY
557 case 'K':
558 /*add the current command line to the history*/
559 if (ir.Event.KeyEvent.dwControlKeyState &
560 (LEFT_CTRL_PRESSED|RIGHT_CTRL_PRESSED))
561 {
562 if (str[0])
563 History(0,str);
564
565 ClearCommandLine (str, maxlen, orgx, orgy);
566 current = charcount = 0;
567 curx = orgx;
568 cury = orgy;
569 //bContinue=TRUE;
570 break;
571 }
572
573 case 'D':
574 /*delete current history entry*/
575 if (ir.Event.KeyEvent.dwControlKeyState &
576 (LEFT_CTRL_PRESSED|RIGHT_CTRL_PRESSED))
577 {
578 ClearCommandLine (str, maxlen, orgx, orgy);
579 History_del_current_entry(str);
580 current = charcount = strlen (str);
581 ConOutPrintf("%s", str);
582 GetCursorXY(&curx, &cury);
583 //bContinue=TRUE;
584 break;
585 }
586
587 #endif /*FEATURE_HISTORY*/
588 }
589 }
590
591 bCharInput = FALSE;
592
593 switch (ir.Event.KeyEvent.wVirtualKeyCode)
594 {
595 case VK_BACK:
596 /* <BACKSPACE> - delete character to left of cursor */
597 if (current > 0 && charcount > 0)
598 {
599 if (current == charcount)
600 {
601 /* if at end of line */
602 str[current - 1] = L'\0';
603 if (CONSOLE_GetCursorX () != 0)
604 {
605 CONSOLE_ConOutPrintf("\b \b");
606 curx--;
607 }
608 else
609 {
610 CONSOLE_SetCursorXY((SHORT)(State->maxx - 1), (SHORT)(CONSOLE_GetCursorY () - 1));
611 CONSOLE_ConOutChar(' ');
612 CONSOLE_SetCursorXY((SHORT)(State->maxx - 1), (SHORT)(CONSOLE_GetCursorY () - 1));
613 cury--;
614 curx = State->maxx - 1;
615 }
616 }
617 else
618 {
619 for (count = current - 1; count < charcount; count++)
620 str[count] = str[count + 1];
621 if (CONSOLE_GetCursorX () != 0)
622 {
623 CONSOLE_SetCursorXY ((SHORT)(CONSOLE_GetCursorX () - 1), CONSOLE_GetCursorY ());
624 curx--;
625 }
626 else
627 {
628 CONSOLE_SetCursorXY ((SHORT)(State->maxx - 1), (SHORT)(CONSOLE_GetCursorY () - 1));
629 cury--;
630 curx = State->maxx - 1;
631 }
632 CONSOLE_GetCursorXY(&curx, &cury);
633 CONSOLE_ConOutPrintf("%s ", &str[current - 1]);
634 CONSOLE_SetCursorXY(curx, cury);
635 }
636 charcount--;
637 current--;
638 }
639 break;
640
641 case VK_INSERT:
642 /* toggle insert/overstrike mode */
643 State->bInsert ^= TRUE;
644 CONSOLE_SetCursorType(State->bInsert, TRUE);
645 break;
646
647 case VK_DELETE:
648 /* delete character under cursor */
649 if (current != charcount && charcount > 0)
650 {
651 for (count = current; count < charcount; count++)
652 str[count] = str[count + 1];
653 charcount--;
654 CONSOLE_GetCursorXY(&curx, &cury);
655 CONSOLE_ConOutPrintf("%s ", &str[current]);
656 CONSOLE_SetCursorXY(curx, cury);
657 }
658 break;
659
660 case VK_HOME:
661 /* goto beginning of string */
662 if (current != 0)
663 {
664 CONSOLE_SetCursorXY(orgx, orgy);
665 curx = orgx;
666 cury = orgy;
667 current = 0;
668 }
669 break;
670
671 case VK_END:
672 /* goto end of string */
673 if (current != charcount)
674 {
675 CONSOLE_SetCursorXY(orgx, orgy);
676 CONSOLE_ConOutPrintf("%s", str);
677 CONSOLE_GetCursorXY(&curx, &cury);
678 current = charcount;
679 }
680 break;
681
682 case 'M':
683 case 'C':
684 /* ^M does the same as return */
685 bCharInput = TRUE;
686 if (!(ir.Event.KeyEvent.dwControlKeyState &
687 (RIGHT_CTRL_PRESSED|LEFT_CTRL_PRESSED)))
688 {
689 break;
690 }
691
692 case VK_RETURN:
693 /* end input, return to main */
694 #ifdef FEATURE_HISTORY
695 /* add to the history */
696 if (str[0])
697 History (0, str);
698 #endif
699 str[charcount++] = '\n';
700 str[charcount] = '\0';
701 CONSOLE_ConOutChar('\n');
702 bReturn = TRUE;
703 break;
704
705 case VK_ESCAPE:
706 /* clear str Make this callable! */
707 ClearCommandLine (str, maxlen, orgx, orgy);
708 curx = orgx;
709 cury = orgy;
710 current = charcount = 0;
711 break;
712
713 #ifdef FEATURE_HISTORY
714 case VK_F3:
715 History_move_to_bottom();
716 #endif
717 case VK_UP:
718 #ifdef FEATURE_HISTORY
719 /* get previous command from buffer */
720 ClearCommandLine (str, maxlen, orgx, orgy);
721 History (-1, str);
722 current = charcount = strlen (str);
723 if (((charcount + orgx) / maxx) + orgy > maxy - 1)
724 orgy += maxy - ((charcount + orgx) / maxx + orgy + 1);
725 CONSOLE_ConOutPrintf("%s", str);
726 CONSOLE_GetCursorXY(&curx, &cury);
727 #endif
728 break;
729
730 case VK_DOWN:
731 #ifdef FEATURE_HISTORY
732 /* get next command from buffer */
733 ClearCommandLine (str, maxlen, orgx, orgy);
734 History (1, str);
735 current = charcount = strlen (str);
736 if (((charcount + orgx) / maxx) + orgy > maxy - 1)
737 orgy += maxy - ((charcount + orgx) / maxx + orgy + 1);
738 CONSOLE_ConOutPrintf("%s", str);
739 CONSOLE_GetCursorXY(&curx, &cury);
740 #endif
741 break;
742
743 case VK_LEFT:
744 /* move cursor left */
745 if (current > 0)
746 {
747 current--;
748 if (CONSOLE_GetCursorX() == 0)
749 {
750 CONSOLE_SetCursorXY((SHORT)(State->maxx - 1), (SHORT)(CONSOLE_GetCursorY () - 1));
751 curx = State->maxx - 1;
752 cury--;
753 }
754 else
755 {
756 CONSOLE_SetCursorXY((SHORT)(CONSOLE_GetCursorX () - 1), CONSOLE_GetCursorY ());
757 curx--;
758 }
759 }
760 break;
761
762 case VK_RIGHT:
763 /* move cursor right */
764 if (current != charcount)
765 {
766 current++;
767 if (CONSOLE_GetCursorX() == State->maxx - 1)
768 {
769 CONSOLE_SetCursorXY(0, (SHORT)(CONSOLE_GetCursorY () + 1));
770 curx = 0;
771 cury++;
772 }
773 else
774 {
775 CONSOLE_SetCursorXY((SHORT)(CONSOLE_GetCursorX () + 1), CONSOLE_GetCursorY ());
776 curx++;
777 }
778 }
779 #ifdef FEATURE_HISTORY
780 else
781 {
782 LPCSTR last = PeekHistory(-1);
783 if (last && charcount < (INT)strlen (last))
784 {
785 PreviousChar = last[current];
786 CONSOLE_ConOutChar(PreviousChar);
787 CONSOLE_GetCursorXY(&curx, &cury);
788 str[current++] = PreviousChar;
789 charcount++;
790 }
791 }
792 #endif
793 break;
794
795 default:
796 /* This input is just a normal char */
797 bCharInput = TRUE;
798
799 }
800
801 ch = ir.Event.KeyEvent.uChar.UnicodeChar;
802 if (ch >= 32 && (charcount != (maxlen - 2)) && bCharInput)
803 {
804 /* insert character into string... */
805 if (State->bInsert && current != charcount)
806 {
807 /* If this character insertion will cause screen scrolling,
808 * adjust the saved origin of the command prompt. */
809 tempscreen = strlen(str + current) + curx;
810 if ((tempscreen % State->maxx) == (State->maxx - 1) &&
811 (tempscreen / State->maxx) + cury == (State->maxy - 1))
812 {
813 orgy--;
814 cury--;
815 }
816
817 for (count = charcount; count > current; count--)
818 str[count] = str[count - 1];
819 str[current++] = ch;
820 if (curx == State->maxx - 1)
821 curx = 0, cury++;
822 else
823 curx++;
824 CONSOLE_ConOutPrintf("%s", &str[current - 1]);
825 CONSOLE_SetCursorXY(curx, cury);
826 charcount++;
827 }
828 else
829 {
830 if (current == charcount)
831 charcount++;
832 str[current++] = ch;
833 if (CONSOLE_GetCursorX () == State->maxx - 1 && CONSOLE_GetCursorY () == State->maxy - 1)
834 orgy--, cury--;
835 if (CONSOLE_GetCursorX () == State->maxx - 1)
836 curx = 0, cury++;
837 else
838 curx++;
839 CONSOLE_ConOutChar(ch);
840 }
841 }
842 }
843 while (!bReturn);
844
845 CONSOLE_SetCursorType(State->bInsert, TRUE);
846
847 return TRUE;
848 }
849
850
851 static
852 BOOL
853 IsDelimiter(
854 CHAR c)
855 {
856 return (c == '/' || c == '=' || c == '\0' || isspace(c));
857 }
858
859
860 static
861 VOID
862 DoCommand(
863 PCONSOLE_STATE State,
864 LPSTR line)
865 {
866 CHAR com[MAX_PATH]; /* the first word in the command */
867 LPSTR cp = com;
868 // LPSTR cstart;
869 LPSTR rest = line; /* pointer to the rest of the command line */
870 // INT cl;
871 LPCOMMAND cmdptr;
872
873 DPRINT1("DoCommand: (\'%s\')\n", line);
874
875 /* Skip over initial white space */
876 while (isspace(*rest))
877 rest++;
878
879 // cstart = rest;
880
881 /* Anything to do ? */
882 if (*rest)
883 {
884 /* Copy over 1st word as lower case */
885 while (!IsDelimiter(*rest))
886 *cp++ = tolower(*rest++);
887
888 /* Terminate first word */
889 *cp = '\0';
890
891 /* Skip over whitespace to rest of line */
892 while (isspace (*rest))
893 rest++;
894
895 /* Scan internal command table */
896 for (cmdptr = Commands; ; cmdptr++)
897 {
898 /* If end of table execute ext cmd */
899 if (cmdptr->name == NULL)
900 {
901 CONSOLE_ConOutPuts("Unknown command. Enter HELP to get a list of commands.");
902 break;
903 }
904
905 if (strcmp(com, cmdptr->name) == 0)
906 {
907 cmdptr->func(State, rest);
908 break;
909 }
910
911 #if 0
912 /* The following code handles the case of commands like CD which
913 * are recognised even when the command name and parameter are
914 * not space separated.
915 *
916 * e.g dir..
917 * cd\freda
918 */
919
920 /* Get length of command name */
921 cl = strlen(cmdptr->name);
922
923 if ((cmdptr->flags & CMD_SPECIAL) &&
924 (!strncmp (cmdptr->name, com, cl)) &&
925 (strchr("\\.-", *(com + cl))))
926 {
927 /* OK its one of the specials...*/
928
929 /* Call with new rest */
930 cmdptr->func(State, cstart + cl);
931 break;
932 }
933 #endif
934 }
935 }
936 }
937
938
939 VOID
940 RecoveryConsole(VOID)
941 {
942 CHAR szInputBuffer[256];
943 CONSOLE_SCREEN_BUFFER_INFO csbi;
944 CONSOLE_STATE State;
945
946 GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi);
947
948 /* get screen size */
949 State.maxx = csbi.dwSize.X;
950 State.maxy = csbi.dwSize.Y;
951 State.bInsert = TRUE;
952 State.bExit = FALSE;
953
954 CONSOLE_ClearScreen();
955 CONSOLE_SetCursorXY(0, 0);
956
957 CONSOLE_ConOutPrintf("ReactOS Recovery Console\n\nEnter HELP to get a list of commands.\n\n");
958
959 while (!State.bExit)
960 {
961 /* Prompt */
962 CONSOLE_ConOutPrintf(">");
963
964 ReadCommand(&State, szInputBuffer, 256);
965 DPRINT1("%s\n", szInputBuffer);
966
967 DoCommand(&State, szInputBuffer);
968
969 // Cmd = ParseCommand(NULL);
970 // if (!Cmd)
971 // continue;
972
973 // ExecuteCommand(Cmd);
974 // FreeCommand(Cmd);
975 }
976 }
977
978 /* EOF */