/*++ Copyright (c) 1998 Microsoft Corporation Module Name: main.c Abstract: This module implements the main startup code. Author: Wesley Witt (wesw) 21-Oct-1998 Revision History: --*/ #include "cmdcons.h" #pragma hdrstop BOOLEAN RcOpenSoftwareHive( VOID ); // // Pointer to block of interesting values and other stuff // passed to us by setupdd.sys. // PCMDCON_BLOCK _CmdConsBlock; // // Address where we were loaded. // PVOID ImageBase; VOID RcPrintPrompt( VOID ); ULONG GetTimestampForDriver( ULONG_PTR Module ) { PIMAGE_DOS_HEADER DosHdr; ULONG dwTimeStamp; __try { DosHdr = (PIMAGE_DOS_HEADER) Module; if (DosHdr->e_magic == IMAGE_DOS_SIGNATURE) { dwTimeStamp = ((PIMAGE_NT_HEADERS32) ((LPBYTE)Module + DosHdr->e_lfanew))->FileHeader.TimeDateStamp; } else if (DosHdr->e_magic == IMAGE_NT_SIGNATURE) { dwTimeStamp = ((PIMAGE_NT_HEADERS32) DosHdr)->FileHeader.TimeDateStamp; } else { dwTimeStamp = 0; } } __except (EXCEPTION_EXECUTE_HANDLER) { dwTimeStamp = 0; } return dwTimeStamp; } void FormatTime( ULONG TimeStamp, LPWSTR TimeBuf ) { static WCHAR mnames[] = { L"JanFebMarAprMayJunJulAugSepOctNovDec" }; LARGE_INTEGER MyTime; TIME_FIELDS TimeFields; RtlSecondsSince1970ToTime( TimeStamp, &MyTime ); ExSystemTimeToLocalTime( &MyTime, &MyTime ); RtlTimeToTimeFields( &MyTime, &TimeFields ); wcsncpy( TimeBuf, &mnames[(TimeFields.Month - 1) * 3], 3 ); swprintf( &TimeBuf[3], L" %02d, %04d @ %02d:%02d:%02d", TimeFields.Day, TimeFields.Year, TimeFields.Hour, TimeFields.Minute, TimeFields.Second ); } BOOLEAN LoadNonDefaultLayout( IN LPCWSTR BootDevicePath, IN LPCWSTR DirOnBootDevice, IN PVOID SifHandle ) /*++ Routine Description: Loads the non-default keyboard layout at users request Arguments: BootDevicePath - NT/Arc boot device path DirOnBootDevice - Directory on boot device (e.g. i386) SifHandle - Handle to txtsetup.sif Return Value: TRUE, if user selected a keyboard layout and its was loaded. Otherwise FALSE --*/ { BOOLEAN ShowMenu = FALSE; ULONG KeyPressed = 0; LARGE_INTEGER Delay; LONG SecondsToDelay = 5; WCHAR DevicePath[MAX_PATH] = {0}; if (BootDevicePath) { wcscpy(DevicePath, BootDevicePath); SpStringToLower(DevicePath); // // All KBD dlls are not present on floppies // if (!wcsstr(DevicePath, L"floppy")) { SpInputDrain(); SpCmdConsEnableStatusText(TRUE); Delay.HighPart = -1; Delay.LowPart = -10000000; do { // // prompt the user // SpDisplayStatusText(SP_KBDLAYOUT_PROMPT, (UCHAR)(ATT_FG_BLACK | ATT_BG_WHITE), SecondsToDelay); // // sleep for a second // KeDelayExecutionThread(ExGetPreviousMode(), FALSE, &Delay); SecondsToDelay--; if (SpInputIsKeyWaiting()) KeyPressed = SpInputGetKeypress(); } while (SecondsToDelay && KeyPressed != ASCI_CR && KeyPressed != ASCI_ESC); if (KeyPressed == ASCI_CR) ShowMenu = TRUE; if (!ShowMenu) { // // clear status text // SpDisplayStatusOptions(DEFAULT_ATTRIBUTE, 0); } else { // // allow the user to select a particular layout dll and load it // pRcCls(); SpSelectAndLoadLayoutDll((PWSTR)DirOnBootDevice, SifHandle, TRUE); } SpCmdConsEnableStatusText(FALSE); } } return ShowMenu; } ULONG CommandConsole( IN PCMDCON_BLOCK CmdConsBlock ) /*++ Routine Description: Top-level entry point for the command interpreter. Initializes global data and then goes into the processing loop. When the processing loop terminates, cleans up and exits. Arguments: CmdConsBlock - supplies interesting values from setupdd.sys. Return Value: None. --*/ { PTOKENIZED_LINE TokenizedLine; BOOLEAN b = FALSE; ULONG rVal; WCHAR buf[64]; NTSTATUS Status; SpdInitialize(); _CmdConsBlock = CmdConsBlock; // // Make sure temporary buffer is large enough to hold a line of input // from the console. // ASSERT(_CmdConsBlock->TemporaryBufferSize > ((RC_MAX_LINE_LEN+1) * sizeof(WCHAR))); RcConsoleInit(); RcInitializeCurrentDirectories(); FormatTime( GetTimestampForDriver( (ULONG_PTR)ImageBase ), buf ); RcMessageOut( MSG_SIGNON ); if (LoadNonDefaultLayout(_CmdConsBlock->BootDevicePath, _CmdConsBlock->DirectoryOnBootDevice, _CmdConsBlock->SifHandle)){ pRcCls(); RcMessageOut( MSG_SIGNON ); } RedirectToNULL = TRUE; rVal = pRcExecuteBatchFile( L"\\cmdcons\\cmdcons.txt", L"\\cmdcons\\cmdcons.log", TRUE ); RedirectToNULL = FALSE; if(0 == rVal || 2 == rVal) { goto exit; } if (SelectedInstall == NULL) { if (RcCmdLogon( NULL ) == FALSE) { rVal = 0; goto exit; } } Status = RcIsNetworkDrive((PWSTR)(_CmdConsBlock->BootDevicePath)); if (!NT_SUCCESS(Status)) { RcDisableCommand(RcCmdNet); } // // Disable non ARC commands // if (RcIsArc()) { RcDisableCommand(RcCmdFixBootSect); RcDisableCommand(RcCmdFixMBR); } do { RcPrintPrompt(); RcLineIn(_CmdConsBlock->TemporaryBuffer,RC_MAX_LINE_LEN); TokenizedLine = RcTokenizeLine(_CmdConsBlock->TemporaryBuffer); if(TokenizedLine->TokenCount) { rVal = RcDispatchCommand(TokenizedLine); if (rVal == 0 || rVal == 2) { b = FALSE; } else { b = TRUE; } RcTextOut(L"\r\n"); } else { b = TRUE; } RcFreeTokenizedLine(&TokenizedLine); } while(b); exit: SpdTerminate(); RcTerminateCurrentDirectories(); RcConsoleTerminate(); return rVal == 2 ? 1 : 0; } VOID RcPrintPrompt( VOID ) { RcGetCurrentDriveAndDir(_CmdConsBlock->TemporaryBuffer); wcscat(_CmdConsBlock->TemporaryBuffer,L">"); RcRawTextOut(_CmdConsBlock->TemporaryBuffer,-1); } VOID RcNtError( IN NTSTATUS Status, IN ULONG FallbackMessageId, ... ) { va_list arglist; // // Some NT errors receive special treatment. // switch(Status) { case STATUS_NO_SUCH_FILE: RcMessageOut(MSG_NO_FILES); return; case STATUS_NO_MEDIA_IN_DEVICE: RcMessageOut(MSG_NO_MEDIA_IN_DEVICE); return; case STATUS_ACCESS_DENIED: case STATUS_CANNOT_DELETE: RcMessageOut(MSG_ACCESS_DENIED); return; case STATUS_OBJECT_NAME_COLLISION: va_start(arglist,FallbackMessageId); vRcMessageOut(MSG_ALREADY_EXISTS,&arglist); va_end(arglist); return; case STATUS_OBJECT_NAME_INVALID: RcMessageOut(MSG_INVALID_NAME); return; case STATUS_OBJECT_NAME_NOT_FOUND: case STATUS_OBJECT_PATH_NOT_FOUND: RcMessageOut(MSG_FILE_NOT_FOUND); return; case STATUS_DIRECTORY_NOT_EMPTY: RcMessageOut(MSG_DIR_NOT_EMPTY); return; case STATUS_NOT_A_DIRECTORY: RcMessageOut(MSG_NOT_DIRECTORY); return; case STATUS_SHARING_VIOLATION: RcMessageOut(MSG_SHARING_VIOLATION); return; case STATUS_CONNECTION_IN_USE: RcMessageOut(MSG_CONNECTION_IN_USE); return; } // // Not a apecial case, print backup message. // va_start(arglist,FallbackMessageId); vRcMessageOut(FallbackMessageId,&arglist); va_end(arglist); } VOID RcDriverUnLoad( IN PDRIVER_OBJECT DriverObject ) { } ULONG DriverEntry( IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath ) { // // All we do here is to call back into setupdd.sys, providing the address // of our main entry point, which it will call later. We also save away // our image base. // DriverObject->DriverUnload = RcDriverUnLoad; CommandConsoleInterface(CommandConsole); ImageBase = DriverObject->DriverStart; return(0); }