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