windows-nt/Source/XPSP1/NT/base/mvdm/v86/scaffold/i386/softpc.c
2020-09-26 16:20:57 +08:00

443 lines
9.8 KiB
C

#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;
}