Some STDCALL/FASTCALL added in Ex code.
[reactos.git] / reactos / apps / utils / shell / shell.c
1 /* $Id: shell.c,v 1.38 2000/05/01 14:15:01 ea Exp $
2 *
3 * PROJECT : ReactOS Operating System
4 * DESCRIPTION: ReactOS' Native Shell
5 * LICENSE : See top level directory
6 *
7 */
8 #define NTOS_MODE_USER
9 #include <ntos.h>
10 #include <windows.h>
11 #include <stdarg.h>
12 #include <string.h>
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <ctype.h>
16
17
18 HANDLE InputHandle, OutputHandle;
19 BOOL bCanExit = TRUE;
20
21
22 void debug_printf(char* fmt, ...)
23 {
24 va_list args;
25 char buffer[255];
26
27 va_start(args,fmt);
28 vsprintf(buffer,fmt,args);
29 va_end(args);
30 WriteConsoleA(OutputHandle, buffer, strlen(buffer), NULL, NULL);
31 }
32
33
34 void ExecuteVer(void)
35 {
36 debug_printf(
37 "Reactos Simple Shell\n(compiled on %s, at %s)\n",
38 __DATE__,
39 __TIME__
40 );
41 }
42
43 void ExecuteCd(char* cmdline)
44 {
45 if (!SetCurrentDirectoryA(cmdline))
46 {
47 debug_printf("Invalid directory\n");
48 }
49 }
50
51 void ExecuteMd (char *cmdline)
52 {
53 if (!CreateDirectoryA (cmdline, NULL))
54 {
55 debug_printf("Create Directory failed!\n");
56 }
57 }
58
59 void ExecuteDir(char* cmdline)
60 {
61 HANDLE shandle;
62 WIN32_FIND_DATA FindData;
63 int nFile=0, nRep=0;
64 FILETIME fTime;
65 SYSTEMTIME sTime;
66
67 shandle = FindFirstFile("*",&FindData);
68
69 if (shandle==INVALID_HANDLE_VALUE)
70 {
71 debug_printf("File not found\n\n");
72 return;
73 }
74 do
75 {
76 debug_printf("%-15.15s",FindData.cAlternateFileName);
77 if(FindData.dwFileAttributes &FILE_ATTRIBUTE_DIRECTORY)
78 debug_printf("<DIR> "),nRep++;
79 else
80 debug_printf(" %10d ",FindData.nFileSizeLow),nFile++;
81
82 FileTimeToLocalFileTime(&FindData.ftLastWriteTime ,&fTime);
83 FileTimeToSystemTime(&fTime, &sTime);
84 debug_printf("%02d/%02d/%04d %02d:%02d:%02d "
85 ,sTime.wMonth,sTime.wDay,sTime.wYear
86 ,sTime.wHour,sTime.wMinute,sTime.wSecond);
87
88 debug_printf("%s\n",FindData.cFileName);
89 } while(FindNextFile(shandle,&FindData));
90 debug_printf("\n %d files\n %d directories\n\n",nFile,nRep);
91 FindClose(shandle);
92 }
93
94
95 void ExecuteReboot(char* cmdline)
96 {
97 NtShutdownSystem (ShutdownReboot);
98 }
99
100
101 void ExecuteType(char* cmdline)
102 {
103 HANDLE FileHandle;
104 char c;
105 DWORD Result;
106
107 FileHandle = CreateFile(cmdline,
108 FILE_GENERIC_READ,
109 0,
110 NULL,
111 OPEN_EXISTING,
112 0,
113 NULL);
114 if (FileHandle == NULL)
115 {
116 debug_printf("Unknown file\n");
117 return;
118 }
119 while (ReadFile(FileHandle,
120 &c,
121 1,
122 &Result,
123 NULL))
124 {
125 debug_printf("%c",c);
126 c = 0;
127 }
128 CloseHandle(FileHandle);
129 }
130
131 int ExecuteProcess(char* name, char* cmdline, BOOL detached)
132 {
133 PROCESS_INFORMATION ProcessInformation;
134 STARTUPINFO StartupInfo;
135 BOOL ret;
136
137 memset(&StartupInfo, 0, sizeof(StartupInfo));
138 StartupInfo.cb = sizeof (STARTUPINFO);
139 StartupInfo.lpTitle = name;
140
141 ret = CreateProcessA(name,
142 cmdline,
143 NULL,
144 NULL,
145 FALSE,
146 ((TRUE == detached)
147 ? CREATE_NEW_CONSOLE
148 : 0
149 ),
150 NULL,
151 NULL,
152 & StartupInfo,
153 & ProcessInformation
154 );
155 if (TRUE == detached)
156 {
157 if (ret)
158 {
159 debug_printf("%s detached:\n"
160 "\thProcess = %08X\n"
161 "\thThread = %08X\n"
162 "\tPID = %d\n"
163 "\tTID = %d\n\n",
164 name,
165 ProcessInformation.hProcess,
166 ProcessInformation.hThread,
167 ProcessInformation.dwProcessId,
168 ProcessInformation.dwThreadId);
169 CloseHandle(ProcessInformation.hProcess);
170 CloseHandle(ProcessInformation.hThread);
171 }
172 else
173 {
174 debug_printf("Could not detach %s\n", name);
175 }
176 }
177 else
178 {
179 if (ret)
180 {
181 // debug_printf("ProcessInformation.hThread %x\n",
182 // ProcessInformation.hThread);
183 WaitForSingleObject(ProcessInformation.hProcess, INFINITE);
184 CloseHandle(ProcessInformation.hProcess);
185 // debug_printf("Thandle %x\n", ProcessInformation.hThread);
186 CloseHandle(ProcessInformation.hThread);
187 }
188 }
189 return(ret);
190 }
191
192 void ExecuteStart(char* CommandLine)
193 {
194 char *ImageName = CommandLine;
195
196 for ( ;
197 ( (*CommandLine)
198 && (*CommandLine != ' ')
199 && (*CommandLine != '\t')
200 );
201 CommandLine++
202 );
203 *CommandLine++ = '\0';
204 while ( (*CommandLine)
205 && ( (*CommandLine == ' ')
206 || (*CommandLine == '\t')
207 )
208 );
209 ExecuteProcess(
210 ImageName,
211 CommandLine,
212 TRUE
213 );
214 return;
215 }
216
217 void
218 ExecuteKill(char * lpPid)
219 {
220 HANDLE hProcess;
221 DWORD dwProcessId;
222
223 dwProcessId = (DWORD) atol(lpPid);
224 debug_printf("dwProcessId %d\n",dwProcessId);
225 hProcess = OpenProcess(
226 PROCESS_TERMINATE,
227 FALSE,
228 dwProcessId
229 );
230 if (NULL == hProcess)
231 {
232 debug_printf(
233 "Could not open the process with PID = %d\n",
234 dwProcessId
235 );
236 return;
237 }
238 if (FALSE == TerminateProcess(
239 hProcess,
240 0
241 )
242 ) {
243 debug_printf(
244 "Could not terminate the process with PID = %d\n",
245 dwProcessId
246 );
247 }
248 CloseHandle(hProcess);
249 return;
250 }
251
252 void ExecuteHelp (void * dummy)
253 {
254 debug_printf ("A:\t\t\tCurrent drive is A:\n");
255 debug_printf ("C:\t\t\tCurrent drive is C:\n");
256 debug_printf ("cd [directory]\t\tChange current directory\n");
257 debug_printf ("dir [directory]\t\tList directory\n");
258 debug_printf ("exit\t\t\tTerminate the shell\n");
259 debug_printf ("help\t\t\tPrint this help message\n");
260 debug_printf ("kill [pid]\t\tKill process which PID is pid\n");
261 debug_printf ("md [directory]\t\tCreate a new directory\n");
262 debug_printf ("reboot\t\t\tRestart the system\n");
263 debug_printf ("start [program.exe]\tDetach program.exe\n");
264 debug_printf ("type [file]\t\tPrint the file on console\n");
265 debug_printf ("validate\t\tValidate the process' heap\n");
266 debug_printf ("ver\t\t\tPrint version information\n");
267 debug_printf ("[program.exe]\t\tStart synchronously program.exe\n\n");
268 }
269
270 void ExecuteCommand(char* line)
271 {
272 char* cmd;
273 char* tail;
274
275 if (isalpha(line[0]) && line[1] == ':' && line[2] == 0)
276 {
277 char szPath[MAX_PATH];
278 char szVar[5];
279
280 /* save curent directory in environment variable */
281 GetCurrentDirectory (MAX_PATH, szPath);
282
283 strcpy (szVar, "=A:");
284 szVar[1] = toupper (szPath[0]);
285 SetEnvironmentVariable (szVar, szPath);
286
287 /* check for current directory of new drive */
288 strcpy (szVar, "=A:");
289 szVar[1] = toupper (line[0]);
290 if (GetEnvironmentVariable (szVar, szPath, MAX_PATH) == 0)
291 {
292 /* no environment variable found */
293 strcpy (szPath, "A:\\");
294 szPath[0] = toupper (line[0]);
295 }
296
297 /* set new current directory */
298 SetCurrentDirectory (szPath);
299 GetCurrentDirectory (MAX_PATH, szPath);
300 if (szPath[0] != (char)toupper (line[0]))
301 debug_printf("Invalid drive\n");
302
303 return;
304 }
305
306 tail = line;
307 while ((*tail)!=' ' && (*tail)!=0)
308 {
309 tail++;
310 }
311 if ((*tail)==' ')
312 {
313 *tail = 0;
314 tail++;
315 }
316 cmd = line;
317
318
319 if (cmd==NULL || *cmd == '\0' )
320 {
321 return;
322 }
323 if (strcmp(cmd,"cd")==0)
324 {
325 ExecuteCd(tail);
326 return;
327 }
328 if (strcmp(cmd,"dir")==0)
329 {
330 ExecuteDir(tail);
331 return;
332 }
333 if (strcmp(cmd,"kill")==0)
334 {
335 ExecuteKill(tail);
336 return;
337 }
338 if (strcmp(cmd,"md")==0)
339 {
340 ExecuteMd(tail);
341 return;
342 }
343 if (strcmp(cmd,"reboot")==0)
344 {
345 ExecuteReboot(tail);
346 return;
347 }
348 if (strcmp(cmd,"type")==0)
349 {
350 ExecuteType(tail);
351 return;
352 }
353 if (strcmp(cmd,"ver")==0)
354 {
355 ExecuteVer();
356 return;
357 }
358 if (strcmp(cmd,"validate")==0)
359 {
360 debug_printf("Validating heap...");
361 if (HeapValidate(GetProcessHeap(),0,NULL))
362 {
363 debug_printf("succeeded\n");
364 }
365 else
366 {
367 debug_printf("failed\n");
368 }
369 return;
370 }
371 if (strcmp(cmd,"start") == 0)
372 {
373 ExecuteStart(tail);
374 return;
375 }
376 if ((strcmp(cmd,"help") * strcmp(cmd,"?")) == 0)
377 {
378 ExecuteHelp(tail);
379 return;
380 }
381 if (strcmp(cmd,"exit")==0)
382 {
383 if (bCanExit == TRUE)
384 {
385 ExitProcess(0);
386 }
387 return;
388 }
389 if (ExecuteProcess(cmd,tail,FALSE))
390 {
391 return;
392 }
393 debug_printf("Unknown command '%s'\n", cmd);
394 }
395
396 void ReadLine(char* line)
397 {
398 DWORD Result;
399 UCHAR CurrentDir[255];
400 char ch;
401 int length = 0;
402
403 GetCurrentDirectoryA(255,CurrentDir);
404 debug_printf("%s>", CurrentDir);
405
406 do
407 {
408 if (!ReadConsoleA(InputHandle,
409 &ch,
410 1,
411 &Result,
412 NULL))
413 {
414 debug_printf("Failed to read from console\n");
415 for(;;);
416 }
417 switch (ch)
418 {
419 case '\b':
420 if (length > 0)
421 {
422 debug_printf("\b \b");
423 line--;
424 length--;
425 }
426 break;
427
428 default:
429 *line = ch;
430 debug_printf( "%c", ch );
431 line++;
432 length++;
433 }
434 } while (ch != '\n');
435 line--;
436 *line = 0;
437 }
438
439 void ParseCommandLine (void)
440 {
441 char *pszCommandLine;
442
443 pszCommandLine = GetCommandLineA ();
444 _strupr (pszCommandLine);
445 if (strstr (pszCommandLine, "/P") != NULL)
446 {
447 debug_printf("Permanent shell\n");
448 bCanExit = FALSE;
449 }
450 }
451
452 int main(void)
453 {
454 static char line[255];
455
456 AllocConsole();
457 InputHandle = GetStdHandle(STD_INPUT_HANDLE);
458 OutputHandle = GetStdHandle(STD_OUTPUT_HANDLE);
459
460 debug_printf("Shell Starting...\n");
461
462 ParseCommandLine ();
463
464 for(;;)
465 {
466 ReadLine(line);
467 ExecuteCommand(line);
468 }
469
470 return 0;
471 }
472
473 /* EOF */