/* $Id$ * * PROJECT : ReactOS Operating System * DESCRIPTION: ReactOS' Native Shell * LICENSE : See top level directory * */ #define NTOS_MODE_USER #include #include #include #include #include #include #include HANDLE InputHandle, OutputHandle; BOOL bCanExit = TRUE, bCanLinespace = TRUE; void debug_printf(char* fmt, ...) { va_list args; char buffer[512]; DWORD nbChar; va_start(args,fmt); _vsnprintf(buffer,512,fmt,args); va_end(args); WriteConsoleA(OutputHandle, buffer, strlen(buffer), &nbChar, NULL); } void ExecuteCls(void) { DWORD dwWritten; CONSOLE_SCREEN_BUFFER_INFO csbi; COORD coPos; GetConsoleScreenBufferInfo (OutputHandle, &csbi); coPos.X = 0; coPos.Y = 0; FillConsoleOutputAttribute (OutputHandle, csbi.wAttributes, (csbi.dwSize.X)*(csbi.dwSize.Y), coPos, &dwWritten); FillConsoleOutputCharacter (OutputHandle, _T(' '), (csbi.dwSize.X)*(csbi.dwSize.Y), coPos, &dwWritten); SetConsoleCursorPosition (OutputHandle, coPos); } void ExecuteVer(void) { debug_printf( "Reactos Simple Shell\n(compiled on %s, at %s)\n", __DATE__, __TIME__ ); } void ExecuteCd(char* cmdline) { if (!SetCurrentDirectoryA(cmdline)) { debug_printf("Invalid directory\n"); } } void ExecuteMd (char *cmdline) { if (!CreateDirectoryA (cmdline, NULL)) { debug_printf("Create Directory failed!\n"); } } void ExecuteDir(char* cmdline) { HANDLE shandle; WIN32_FIND_DATA FindData; int nFile=0, nRep=0; FILETIME fTime; SYSTEMTIME sTime; shandle = FindFirstFile("*",&FindData); if (shandle==INVALID_HANDLE_VALUE) { debug_printf("File not found\n"); return; } do { debug_printf("%-15.15s",FindData.cAlternateFileName); if(FindData.dwFileAttributes &FILE_ATTRIBUTE_DIRECTORY) debug_printf(" "),nRep++; else debug_printf(" %10d ",FindData.nFileSizeLow),nFile++; FileTimeToLocalFileTime(&FindData.ftLastWriteTime ,&fTime); FileTimeToSystemTime(&fTime, &sTime); debug_printf("%02d/%02d/%04d %02d:%02d:%02d " ,sTime.wMonth,sTime.wDay,sTime.wYear ,sTime.wHour,sTime.wMinute,sTime.wSecond); debug_printf("%s\n",FindData.cFileName); } while(FindNextFile(shandle,&FindData)); debug_printf("\n %d files\n %d directories\n",nFile,nRep); FindClose(shandle); } void ExecuteReboot(char* cmdline) { NtShutdownSystem (ShutdownReboot); } void ExecuteShutdown(char* cmdline) { NtShutdownSystem (ShutdownNoReboot); } void ExecuteType(char* cmdline) { HANDLE FileHandle; char c; DWORD Result; BOOL Success; FileHandle = CreateFile(cmdline, FILE_GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL); if (FileHandle == NULL) { debug_printf("Unknown file\n"); return; } do { Success = ReadFile(FileHandle, &c, 1, &Result, NULL); if (Success) { debug_printf("%c",c); c = 0; } } while (Success && Result > 0); CloseHandle(FileHandle); } int ExecuteProcess(char* name, char* cmdline, BOOL detached) { PROCESS_INFORMATION ProcessInformation; STARTUPINFO StartupInfo; BOOL ret; CHAR fullname[260]; PCHAR p; /* append '.exe' if needed */ strcpy (fullname, name); p = strrchr (fullname, '.'); if ((p == NULL) || (_stricmp (p, ".exe") != 0)) { strcat (fullname, ".exe"); } memset(&StartupInfo, 0, sizeof(StartupInfo)); StartupInfo.cb = sizeof (STARTUPINFO); StartupInfo.lpTitle = name; if( cmdline && *cmdline ) *(cmdline-1) = ' '; // fix command line so it is the FULL command, including exe name ret = CreateProcessA(fullname, name, NULL, NULL, FALSE, ((TRUE == detached) ? CREATE_NEW_CONSOLE : 0 ), NULL, NULL, & StartupInfo, & ProcessInformation ); if (TRUE == detached) { if (ret) { debug_printf("\"%s\" detached:\n" "\thProcess = %08X\n" "\thThread = %08X\n" "\tPID = %d\n" "\tTID = %d\n\n", fullname, ProcessInformation.hProcess, ProcessInformation.hThread, ProcessInformation.dwProcessId, ProcessInformation.dwThreadId); CloseHandle(ProcessInformation.hProcess); CloseHandle(ProcessInformation.hThread); } else { debug_printf("Could not detach %s\n", name); } } else { if (ret) { // debug_printf("ProcessInformation.hThread %x\n", // ProcessInformation.hThread); WaitForSingleObject(ProcessInformation.hProcess, INFINITE); CloseHandle(ProcessInformation.hProcess); // debug_printf("Thandle %x\n", ProcessInformation.hThread); CloseHandle(ProcessInformation.hThread); } } return(ret); } void ExecuteStart(char* CommandLine) { char *ImageName = CommandLine; for ( ; ( (*CommandLine) && (*CommandLine != ' ') && (*CommandLine != '\t') ); CommandLine++ ); *CommandLine++ = '\0'; while ( (*CommandLine) && ( (*CommandLine == ' ') || (*CommandLine == '\t') ) ); ExecuteProcess( ImageName, CommandLine, TRUE ); return; } void ExecuteKill(char * lpPid) { HANDLE hProcess; DWORD dwProcessId; dwProcessId = (DWORD) atol(lpPid); debug_printf("Killing PID %d...\n",dwProcessId); hProcess = OpenProcess( PROCESS_TERMINATE, FALSE, dwProcessId ); if (NULL == hProcess) { debug_printf( "Could not open the process with PID = %d\n", dwProcessId ); return; } if (FALSE == TerminateProcess( hProcess, 0 ) ) { debug_printf( "Could not terminate the process with PID = %d\n", dwProcessId ); } CloseHandle(hProcess); return; } void ExecuteHelp (void * dummy) { debug_printf ( "A:\t\t\tCurrent drive is A:\n" "C:\t\t\tCurrent drive is C:\n" "cd [directory]\t\tChange current directory\n" "dir [directory]\t\tList directory\n" "exit\t\t\tTerminate the shell\n" "help\t\t\tPrint this help message\n" "kill [pid]\t\tKill process which PID is pid\n" "md [directory]\t\tCreate a new directory\n" "reboot\t\t\tRestart the system\n" "start [program.exe]\tDetach program.exe\n" "type [file]\t\tPrint the file on console\n" "validate\t\tValidate the process' heap\n" "ver\t\t\tPrint version information\n" "[program.exe]\t\tStart synchronously program.exe\n" ); } void ExecuteCommand(char* line) { char* cmd; char* tail; if (isalpha(line[0]) && line[1] == ':' && line[2] == 0) { char szPath[MAX_PATH]; char szVar[5]; /* save curent directory in environment variable */ GetCurrentDirectory (MAX_PATH, szPath); strcpy (szVar, "=A:"); szVar[1] = toupper (szPath[0]); SetEnvironmentVariable (szVar, szPath); /* check for current directory of new drive */ strcpy (szVar, "=A:"); szVar[1] = toupper (line[0]); if (GetEnvironmentVariable (szVar, szPath, MAX_PATH) == 0) { /* no environment variable found */ strcpy (szPath, "A:\\"); szPath[0] = toupper (line[0]); } /* set new current directory */ SetCurrentDirectory (szPath); GetCurrentDirectory (MAX_PATH, szPath); if (szPath[0] != (char)toupper (line[0])) debug_printf("Invalid drive\n"); return; } tail = line; while ((*tail)!=' ' && (*tail)!=0) { tail++; } if ((*tail)==' ') { *tail = 0; tail++; } cmd = line; if (cmd==NULL || *cmd == '\0' ) { return; } if (strcmp(cmd,"cd")==0) { ExecuteCd(tail); return; } if (strcmp(cmd,"dir")==0) { ExecuteDir(tail); return; } if (strcmp(cmd,"kill")==0) { ExecuteKill(tail); return; } if (strcmp(cmd,"md")==0) { ExecuteMd(tail); return; } if (strcmp(cmd,"reboot")==0) { ExecuteReboot(tail); return; } if (strcmp(cmd,"shutdown")==0) { ExecuteShutdown(tail); return; } if (strcmp(cmd,"type")==0) { ExecuteType(tail); return; } if (strcmp(cmd,"ver")==0) { ExecuteVer(); return; } if (strcmp(cmd,"validate")==0) { debug_printf("Validating heap..."); if (HeapValidate(GetProcessHeap(),0,NULL)) { debug_printf("succeeded\n"); } else { debug_printf("failed\n"); } return; } if (strcmp(cmd,"start") == 0) { ExecuteStart(tail); return; } if ((strcmp(cmd,"help") * strcmp(cmd,"?")) == 0) { ExecuteHelp(tail); return; } if (strcmp(cmd,"exit")==0) { if (bCanExit == TRUE) { ExitProcess(0); } return; } if (strcmp(cmd,"cls") == 0) { ExecuteCls(); bCanLinespace = FALSE; return; } if (ExecuteProcess(cmd,tail,FALSE)) { return; } debug_printf("Unknown command '%s'\n", cmd); } void ReadLine(char* line) { DWORD Result; UCHAR CurrentDir[255]; GetCurrentDirectoryA(255,CurrentDir); debug_printf("%s>", CurrentDir); if ( !ReadConsoleA(InputHandle, line, 252, &Result, NULL) ) { debug_printf("Failed to read from console\n"); for(;;); } // If the \n is in there, so is the \r so null it, otherwise, null the last char if( line[Result-1] == '\n' ) line[Result-2] = 0; else { line[Result] = 0; } } void ParseCommandLine (void) { char *pszCommandLine; pszCommandLine = GetCommandLineA (); _strupr (pszCommandLine); if (strstr (pszCommandLine, "/P") != NULL) { debug_printf("Permanent shell\n"); bCanExit = FALSE; } } int main(void) { static char line[256]; AllocConsole(); InputHandle = GetStdHandle(STD_INPUT_HANDLE); OutputHandle = GetStdHandle(STD_OUTPUT_HANDLE); ParseCommandLine (); for(;;) { ReadLine(line); ExecuteCommand(line); if(bCanLinespace) { printf("\n"); } else bCanLinespace = TRUE; } return 0; } /* EOF */