#include #include #include #include #include #include #include "demexp.h" #include "softpc.h" #include #include #include #include "xwincon.h" #include "fun.h" #include #define VDM_VIRTUAL_INTERRUPTS 0x00000200L extern CONTEXT IntelRegisters; VOID DumpIntelRegs(); VOID ParseSwitches( int, char**); VOID usage(); BOOL ConInit (VOID); extern VOID VDMCtrlCHandler(ULONG); INT flOptions; HANDLE OutputHandle; HANDLE InputHandle; HANDLE SCSCreateEvent; char *EmDirectory; BOOL scaffMin = FALSE; BOOL scaffWow = FALSE; BOOL VDMForWOW = FALSE; CHAR BootLetter; void main (argc, argv) int argc; char *argv[]; { PSZ psz,pszNULL; HANDLE hfile; DWORD BytesRead; int i; PCHAR FileAddress; BOOL IsFirst; int temp_argc = argc; char **temp_argv = argv; // DebugBreak(); if(SetConsoleCtrlHandler((PHANDLER_ROUTINE)VDMCtrlCHandler,TRUE) == FALSE) { VDprint( VDP_LEVEL_INFO, ("CtrlC Handler Could'nt be installed\n") ); } // Tell the console that we want the last event (i.e when the // window is just to be destroyed. SetLastConsoleEventActive(); // Check if the VDM Is for WOW while (--temp_argc > 0) { psz = *++temp_argv; if (*psz == '-' || *psz == '/') { psz++; if(tolower(*psz) == 'w'){ VDMForWOW = TRUE; break; } } } // This following API is required for recovery purposes. This // tells the basesrv that VDM has hooked ctrlc event. After // this it will always get the termination notification. If // the window is killed before we hook ctrl-c then basesrv // will know that data structures for this VDM has to be // freed. This should be the first call to base.dll. VDMOperationStarted (VDMForWOW); EmDirectory = NULL; // Hide the cmd window of WOWVDM if(VDMForWOW) VDMConsoleOperation((DWORD)VDM_HIDE_WINDOW); ParseSwitches( argc, argv ); IsFirst = GetNextVDMCommand(NULL); for (i = 0; i < argc; i++) { VDprint( VDP_LEVEL_INFO, ("%s\n", argv[i]) ); } VDbreak(VDB_LEVEL_INFO); if (EmDirectory == NULL) { usage(); TerminateVDM(); } // Sudeepb 26-Dec-1991 Temporary code to make // the life easy for WOW's internal users such that they dont have // to change the config.sys as per their setup. FixConfigFile (EmDirectory,IsFirst); pszNULL = strchr(EmDirectory,'\0'); psz = EmDirectory; while(*psz == ' ' || *psz == '\t') psz++; BootLetter = *psz; host_cpu_init(); sas_init(1024L * 1024L + 64L * 1024L); // Initialize ROM support BiosInit(argc, argv); // Initialize console support if (!ConInit()) { VDprint( VDP_LEVEL_ERROR, ("SoftPC: error initializing console\n") ); TerminateVDM(); } // Initialize WOW CMDInit (argc,argv); // Initialize DOSEm if(!DemInit (argc,argv,EmDirectory)) { VDprint( VDP_LEVEL_ERROR, ("SoftPC: error initializing DOSEm\n") ); TerminateVDM(); } // Initialize XMS if(!XMSInit (argc,argv)) { VDprint( VDP_LEVEL_ERROR, ("SoftPC: error initializing XMS\n") ); TerminateVDM(); } // Initialize DBG if(!DBGInit (argc,argv)) { VDprint( VDP_LEVEL_ERROR, ("SoftPC: error initializing DBG\n") ); TerminateVDM(); } // Prepare to load ntio.sys strcat (EmDirectory,"\\ntio.sys"); hfile = CreateFile(EmDirectory, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL ); if (hfile == (HANDLE)0xffffffff) { VDprint( VDP_LEVEL_ERROR, ("SoftPC: could not open file %s. Error %d\n", EmDirectory, GetLastError()) ); TerminateVDM(); } FileAddress = (PCHAR)0x700; BytesRead = 1; while (BytesRead) { if (!ReadFile(hfile, FileAddress, 16384, &BytesRead, NULL)) { VDprint( VDP_LEVEL_ERROR, ("SoftPC: read failure on file %s. Error %d\n", EmDirectory, GetLastError()) ); TerminateVDM(); } VDprint(VDP_LEVEL_INFO, ("SoftPC: read a block of file %s\n", EmDirectory) ); FileAddress = (PCHAR)FileAddress + BytesRead; } VDprint(VDP_LEVEL_WARNING, ("SoftPC: using Emulation file %s\n", EmDirectory) ); VDbreak(VDB_LEVEL_INFO); CloseHandle (hfile); // restore the emulation directory *pszNULL = 0; IntelRegisters.Eip = 0x0; IntelRegisters.SegCs = 0x70; IntelRegisters.EFlags = VDM_VIRTUAL_INTERRUPTS; host_simulate(); if (IntelRegisters.EFlags & VDM_VIRTUAL_INTERRUPTS) { VDprint(VDP_LEVEL_INFO, ("Virtual ints enabled\n")); } else { VDprint(VDP_LEVEL_INFO, ("Virtual ints disabled\n")); } DumpIntelRegs(); } #define MAX_CONFIG_SIZE 1024 VOID FixConfigFile (pszBin86Dir,IsFirstVDM) PSZ pszBin86Dir; BOOL IsFirstVDM; { // Temporary code. To be thrown out once we have full configuration // and installation. CHAR ConfigFile[]="?:\\config.vdm"; CHAR Buffer [MAX_CONFIG_SIZE]; DWORD len,i; DWORD BytesRead,BytesWritten; HANDLE hfile; if (IsFirstVDM == FALSE) return; ConfigFile[0] = *pszBin86Dir; hfile = CreateFile( ConfigFile, GENERIC_WRITE | GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL ); if (hfile == (HANDLE)0xffffffff) { DbgPrint ("config.vdm is'nt found on the root drive of yout NT trre\n"); return; } if (!ReadFile(hfile, Buffer, MAX_CONFIG_SIZE, &BytesRead, NULL)){ DbgPrint ("config.vdm could'nt be read\n, %x\n",GetLastError ()); CloseHandle (hfile); return; } if (BytesRead == MAX_CONFIG_SIZE) { DbgPrint ("config.vdm is too big, could'nt perform macro substitution\n"); CloseHandle (hfile); return; } SetFilePointer (hfile, 0, NULL, FILE_BEGIN); len = strlen (pszBin86Dir); for (i=0; i < BytesRead; i++) { if (Buffer [i] != '@'){ WriteFile (hfile, &Buffer[i], 1, &BytesWritten, NULL); } else { WriteFile (hfile, pszBin86Dir, len, &BytesWritten, NULL); } } CloseHandle (hfile); return; } VOID DumpIntelRegs() { VDprint(VDP_LEVEL_ERROR,("EAX = %lx\n",IntelRegisters.Eax)); VDprint(VDP_LEVEL_ERROR,("Ebx = %lx\n",IntelRegisters.Ebx)); VDprint(VDP_LEVEL_ERROR,("Ecx = %lx\n",IntelRegisters.Ecx)); VDprint(VDP_LEVEL_ERROR,("Edx = %lx\n",IntelRegisters.Edx)); VDprint(VDP_LEVEL_ERROR,("Esi = %lx\n",IntelRegisters.Esi)); VDprint(VDP_LEVEL_ERROR,("Edi = %lx\n",IntelRegisters.Edi)); VDprint(VDP_LEVEL_ERROR,("Ebp = %lx\n",IntelRegisters.Ebp)); VDprint(VDP_LEVEL_ERROR,("SegDs = %lx\n",IntelRegisters.SegDs)); VDprint(VDP_LEVEL_ERROR,("SegEs = %lx\n",IntelRegisters.SegEs)); VDprint(VDP_LEVEL_ERROR,("SegFs = %lx\n",IntelRegisters.SegFs)); VDprint(VDP_LEVEL_ERROR,("SegGs = %lx\n",IntelRegisters.SegGs)); VDprint(VDP_LEVEL_ERROR,("EFlags = %lx\n",IntelRegisters.EFlags)); VDprint(VDP_LEVEL_ERROR,("SS:Esp = %lx:",IntelRegisters.SegSs)); VDprint(VDP_LEVEL_ERROR,("%lx\n",IntelRegisters.Esp)); VDprint(VDP_LEVEL_ERROR,("CS:Eip = %lx:",IntelRegisters.SegCs)); VDprint(VDP_LEVEL_ERROR,("%lx\n",IntelRegisters.Eip)); } VOID ParseSwitches( int argc, char **argv ) { int i; for (i = 1; i < argc; i++){ if ((argv[i][0] == '-') || (argv[i][0] == '/')) { switch (argv[i][1]) { case 's' : case 'S' : sscanf(&argv[i][2], "%x", &VdmDebugLevel); VDprint( VDP_LEVEL_WARNING, ("VdmDebugLevel = %x\n", VdmDebugLevel) ); break; case 'f' : case 'F' : // Note this memory is freed by DEM. if((EmDirectory = (PCHAR)malloc (strlen (&argv[i][2]) + 1 + sizeof("\\ntdos.sys") + 1 )) == NULL){ DbgPrint("SoftPC: Not Enough Memory \n"); TerminateVDM(); } strcpy(EmDirectory,&argv[i][2]); break; case 't' : case 'T' : flOptions |= OPT_TERMINAL; break; case 'm' : case 'M' : scaffMin = TRUE; break; case 'w' : case 'W' : scaffWow = TRUE; } } else { break; } } } VOID usage() { DbgPrint("SoftPC Usage: softpc -F [-D#] [:=] [dos command line]\n"); } VOID TerminateVDM(void) { if(VDMForWOW) // Kill everything for WOW VDM ExitVDM(VDMForWOW,(ULONG)-1); else ExitVDM(FALSE,0); ExitProcess (0); } DWORD SCSConsoleThread(LPVOID lp) { SetEvent(SCSCreateEvent); BiosKbdReadLoop(); return TRUE; } BOOL ConInit (VOID) { DWORD SCSThreadId; HANDLE InputThread; OutputHandle = GetStdHandle(STD_OUTPUT_HANDLE); InputHandle = GetStdHandle(STD_INPUT_HANDLE); SCSCreateEvent = CreateEvent( NULL, TRUE, FALSE,NULL ); InputThread = CreateThread( (LPSECURITY_ATTRIBUTES)0, 8192, (LPTHREAD_START_ROUTINE)SCSConsoleThread, (LPVOID)0, STANDARD_RIGHTS_REQUIRED, &SCSThreadId ); WaitForSingleObject(SCSCreateEvent, -1); CloseHandle(SCSCreateEvent); return TRUE; }