|
|
#include <windows.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <malloc.h>
#include <ctype.h>
#include "demexp.h"
#include "softpc.h"
#include <cmdsvc.h>
#include <xmssvc.h>
#include <dbgexp.h>
#include "xwincon.h"
#include "fun.h"
#include <conapi.h>
#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<emulation file> [-D#] [<drive>:=<virtual disk>] [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; }
|