mirror of
https://github.com/reactos/reactos.git
synced 2024-12-29 10:35:28 +00:00
[NTVDM]
- Move almost all the DOS command launch thread into dem.c, - Rework the code so that now, when we want to either load our BIOS32 or a custom one, we start their execution at F000:FFF0 as it should be, - For modularity purposes (ie. to be able one day to load real OSes in our ntvdm), implement INT 19h (bootstrap loader) so that it calls a (temporary) dos bootsector loader that writes some bootstrap code at 0000:7c00, then the INT 19h runs this code, that has as an effect to load our DOS32 (for a real OS, the MBR code goes to 0000:7c00 and is then run). svn path=/trunk/; revision=64521
This commit is contained in:
parent
38258d656e
commit
8d73d7c58a
7 changed files with 407 additions and 267 deletions
|
@ -25,7 +25,7 @@
|
||||||
/* DEFINES ********************************************************************/
|
/* DEFINES ********************************************************************/
|
||||||
|
|
||||||
/* BOP Identifiers */
|
/* BOP Identifiers */
|
||||||
#define BOP_BIOSINIT 0x00 // Windows NTVDM (SoftPC) BIOS calls BOP 0x00
|
#define BOP_RESET 0x00 // Windows NTVDM (SoftPC) BIOS calls BOP 0x00
|
||||||
// to let the virtual machine initialize itself
|
// to let the virtual machine initialize itself
|
||||||
// the IVT and its hardware.
|
// the IVT and its hardware.
|
||||||
#define BOP_EQUIPLIST 0x11
|
#define BOP_EQUIPLIST 0x11
|
||||||
|
@ -35,84 +35,11 @@
|
||||||
|
|
||||||
static BOOLEAN Bios32Loaded = FALSE;
|
static BOOLEAN Bios32Loaded = FALSE;
|
||||||
|
|
||||||
static CALLBACK16 __BiosContext;
|
|
||||||
PBIOS_DATA_AREA Bda;
|
PBIOS_DATA_AREA Bda;
|
||||||
PBIOS_CONFIG_TABLE Bct;
|
PBIOS_CONFIG_TABLE Bct;
|
||||||
|
|
||||||
/* PRIVATE FUNCTIONS **********************************************************/
|
/* PRIVATE FUNCTIONS **********************************************************/
|
||||||
|
|
||||||
static VOID WINAPI BiosInitBop(LPWORD Stack)
|
|
||||||
{
|
|
||||||
BOOLEAN Success;
|
|
||||||
|
|
||||||
/* Load the second part of the Windows NTVDM BIOS image */
|
|
||||||
LPCSTR BiosFileName = "bios1.rom";
|
|
||||||
PVOID BiosLocation = (PVOID)TO_LINEAR(BIOS_SEGMENT, 0x0000);
|
|
||||||
DWORD BiosSize = 0;
|
|
||||||
|
|
||||||
/* Disable interrupts */
|
|
||||||
setIF(0);
|
|
||||||
|
|
||||||
DisplayMessage(L"You are loading Windows NTVDM BIOS!\n");
|
|
||||||
|
|
||||||
/* Initialize a private callback context */
|
|
||||||
InitializeContext(&__BiosContext, BIOS_SEGMENT, 0x0000);
|
|
||||||
|
|
||||||
Success = LoadRom(BiosFileName, BiosLocation, &BiosSize);
|
|
||||||
DPRINT1("BIOS loading %s ; GetLastError() = %u\n", Success ? "succeeded" : "failed", GetLastError());
|
|
||||||
|
|
||||||
if (Success == FALSE)
|
|
||||||
{
|
|
||||||
/* Stop the VDM */
|
|
||||||
EmulatorTerminate();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// DisplayMessage(L"First bytes at 0x%p: 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n"
|
|
||||||
// L"3 last bytes at 0x%p: 0x%02x 0x%02x 0x%02x",
|
|
||||||
// BiosLocation,
|
|
||||||
// *(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + 0),
|
|
||||||
// *(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + 1),
|
|
||||||
// *(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + 2),
|
|
||||||
// *(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + 3),
|
|
||||||
// *(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + 4),
|
|
||||||
// *(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + 5),
|
|
||||||
// *(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + 6),
|
|
||||||
// *(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + 7),
|
|
||||||
// *(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + 8),
|
|
||||||
// *(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + 9),
|
|
||||||
|
|
||||||
// (PVOID)((ULONG_PTR)BiosLocation + BiosSize - 2),
|
|
||||||
// *(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + BiosSize - 2),
|
|
||||||
// *(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + BiosSize - 1),
|
|
||||||
// *(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + BiosSize - 0));
|
|
||||||
|
|
||||||
/* Initialize IVT and hardware */
|
|
||||||
|
|
||||||
/* Initialize the Keyboard and Video BIOS */
|
|
||||||
if (!KbdBiosInitialize() || !VidBiosInitialize())
|
|
||||||
{
|
|
||||||
/* Stop the VDM */
|
|
||||||
EmulatorTerminate();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Load VGA BIOS */
|
|
||||||
// Success = LoadRom("v7vga.rom", (PVOID)0xC0000, &BiosSize);
|
|
||||||
// DPRINT1("VGA BIOS loading %s ; GetLastError() = %u\n", Success ? "succeeded" : "failed", GetLastError());
|
|
||||||
|
|
||||||
/* Enable interrupts */
|
|
||||||
setIF(1);
|
|
||||||
|
|
||||||
///////////// MUST BE DONE AFTER IVT INITIALIZATION !! /////////////////////
|
|
||||||
|
|
||||||
/* Load some ROMs */
|
|
||||||
// Success = LoadRom("boot.bin", (PVOID)0xE0000, &BiosSize);
|
|
||||||
// DPRINT1("Test ROM loading %s ; GetLastError() = %u\n", Success ? "succeeded" : "failed", GetLastError());
|
|
||||||
|
|
||||||
SearchAndInitRoms(&__BiosContext);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* PUBLIC FUNCTIONS ***********************************************************/
|
/* PUBLIC FUNCTIONS ***********************************************************/
|
||||||
|
|
||||||
VOID WINAPI BiosEquipmentService(LPWORD Stack)
|
VOID WINAPI BiosEquipmentService(LPWORD Stack)
|
||||||
|
@ -140,12 +67,14 @@ BiosInitialize(IN LPCSTR BiosFileName)
|
||||||
// The BCT is found at F000:E6F5 for 100% compatible BIOSes.
|
// The BCT is found at F000:E6F5 for 100% compatible BIOSes.
|
||||||
Bct = (PBIOS_CONFIG_TABLE)SEG_OFF_TO_PTR(BIOS_SEGMENT, 0xE6F5);
|
Bct = (PBIOS_CONFIG_TABLE)SEG_OFF_TO_PTR(BIOS_SEGMENT, 0xE6F5);
|
||||||
|
|
||||||
/* Register the BIOS support BOPs */
|
/**** HACK! HACK! for Windows NTVDM BIOS ****/
|
||||||
RegisterBop(BOP_BIOSINIT , BiosInitBop);
|
// WinNtVdmBiosSupportInitialize();
|
||||||
RegisterBop(BOP_EQUIPLIST , BiosEquipmentService);
|
|
||||||
RegisterBop(BOP_GETMEMSIZE, BiosGetMemorySize);
|
|
||||||
|
|
||||||
if (BiosFileName)
|
// /* Register the BIOS support BOPs */
|
||||||
|
// RegisterBop(BOP_EQUIPLIST , BiosEquipmentService);
|
||||||
|
// RegisterBop(BOP_GETMEMSIZE, BiosGetMemorySize);
|
||||||
|
|
||||||
|
if (BiosFileName && BiosFileName[0] != '\0')
|
||||||
{
|
{
|
||||||
PVOID BiosLocation = NULL;
|
PVOID BiosLocation = NULL;
|
||||||
DWORD BiosSize = 0;
|
DWORD BiosSize = 0;
|
||||||
|
@ -199,8 +128,8 @@ BiosInitialize(IN LPCSTR BiosFileName)
|
||||||
Success = Bios32Loaded = Bios32Initialize();
|
Success = Bios32Loaded = Bios32Initialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Enable interrupts */
|
// /* Enable interrupts */
|
||||||
setIF(1);
|
// setIF(1);
|
||||||
|
|
||||||
return Success;
|
return Success;
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,16 @@
|
||||||
|
|
||||||
/* DEFINES ********************************************************************/
|
/* DEFINES ********************************************************************/
|
||||||
|
|
||||||
|
/* BOP Identifiers */
|
||||||
|
#define BOP_RESET 0x00 // Windows NTVDM (SoftPC) BIOS calls BOP 0x00
|
||||||
|
// to let the virtual machine initialize itself
|
||||||
|
// the IVT and its hardware.
|
||||||
|
#define BOP_EQUIPLIST 0x11
|
||||||
|
#define BOP_GETMEMSIZE 0x12
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#define BDA_SEGMENT 0x40
|
#define BDA_SEGMENT 0x40
|
||||||
#define BIOS_SEGMENT 0xF000
|
#define BIOS_SEGMENT 0xF000
|
||||||
|
|
||||||
|
|
|
@ -15,8 +15,8 @@
|
||||||
|
|
||||||
#include "emulator.h"
|
#include "emulator.h"
|
||||||
#include "cpu/cpu.h" // for EMULATOR_FLAG_CF
|
#include "cpu/cpu.h" // for EMULATOR_FLAG_CF
|
||||||
|
#include "cpu/bop.h"
|
||||||
#include "int32.h"
|
#include "int32.h"
|
||||||
// #include "bop.h"
|
|
||||||
|
|
||||||
#include "../bios.h"
|
#include "../bios.h"
|
||||||
#include "../rom.h"
|
#include "../rom.h"
|
||||||
|
@ -129,7 +129,8 @@ static BYTE Bootstrap[] =
|
||||||
*/
|
*/
|
||||||
static BYTE PostCode[] =
|
static BYTE PostCode[] =
|
||||||
{
|
{
|
||||||
0xCD, 0x19, // int 0x19, the bootstrap loader interrupt
|
LOBYTE(EMULATOR_BOP), HIBYTE(EMULATOR_BOP), BOP_RESET, // Call BIOS POST
|
||||||
|
0xCD, 0x19, // INT 0x19, the bootstrap loader interrupt
|
||||||
// LOBYTE(EMULATOR_BOP), HIBYTE(EMULATOR_BOP), BOP_UNSIMULATE
|
// LOBYTE(EMULATOR_BOP), HIBYTE(EMULATOR_BOP), BOP_UNSIMULATE
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -278,17 +279,26 @@ static VOID WINAPI BiosRomBasic(LPWORD Stack)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
VOID DosBootsectorInitialize(VOID);
|
||||||
|
|
||||||
static VOID WINAPI BiosBootstrapLoader(LPWORD Stack)
|
static VOID WINAPI BiosBootstrapLoader(LPWORD Stack)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* In real bioses one loads the bootsector read from a diskette
|
* In real BIOSes one loads the bootsector read from a diskette
|
||||||
* or from a disk, to 0000:7C00 and then one runs it.
|
* or from a disk, copy it to 0000:7C00 and then boot it.
|
||||||
* Since we are 32-bit VM and we hardcode our DOS at the moment,
|
* Since we are 32-bit VM and we hardcode our DOS at the moment,
|
||||||
* just call the DOS 32-bit initialization code.
|
* just call the DOS 32-bit initialization code.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
DPRINT1("BiosBootstrapLoader -->\n");
|
DPRINT1("BiosBootstrapLoader -->\n");
|
||||||
|
|
||||||
|
/* Load DOS */
|
||||||
|
DosBootsectorInitialize();
|
||||||
|
/* Position CPU to 0000:7C00 to boot the OS */
|
||||||
|
setCS(0x0000);
|
||||||
|
setIP(0x7C00);
|
||||||
|
|
||||||
DPRINT1("<-- BiosBootstrapLoader\n");
|
DPRINT1("<-- BiosBootstrapLoader\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -510,37 +520,10 @@ static VOID InitializeBiosInt32(VOID)
|
||||||
((PULONG)BaseAddress)[0x49] = (ULONG)NULL;
|
((PULONG)BaseAddress)[0x49] = (ULONG)NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static VOID InitializeBiosInfo(VOID)
|
|
||||||
{
|
|
||||||
RtlZeroMemory(Bct, sizeof(*Bct));
|
|
||||||
|
|
||||||
Bct->Length = sizeof(*Bct);
|
|
||||||
Bct->Model = BIOS_MODEL;
|
|
||||||
Bct->SubModel = BIOS_SUBMODEL;
|
|
||||||
Bct->Revision = BIOS_REVISION;
|
|
||||||
Bct->Feature[0] = 0x70; // At the moment we don't support "wait for external event (INT 15/AH=41h)", we also don't have any "extended BIOS area allocated (usually at top of RAM)"; see http://www.ctyme.com/intr/rb-1594.htm#Table510
|
|
||||||
Bct->Feature[1] = 0x00; // We don't support anything from here; see http://www.ctyme.com/intr/rb-1594.htm#Table511
|
|
||||||
Bct->Feature[2] = 0x00;
|
|
||||||
Bct->Feature[3] = 0x00;
|
|
||||||
Bct->Feature[4] = 0x00;
|
|
||||||
}
|
|
||||||
|
|
||||||
static VOID InitializeBiosData(VOID)
|
static VOID InitializeBiosData(VOID)
|
||||||
{
|
{
|
||||||
UCHAR Low, High;
|
UCHAR Low, High;
|
||||||
|
|
||||||
/* System BIOS Copyright */
|
|
||||||
RtlCopyMemory(SEG_OFF_TO_PTR(0xF000, 0xE000), BiosCopyright, sizeof(BiosCopyright)-1);
|
|
||||||
|
|
||||||
/* System BIOS Version */
|
|
||||||
RtlCopyMemory(SEG_OFF_TO_PTR(0xF000, 0xE080), BiosVersion, sizeof(BiosVersion)-1); // FIXME: or E061, or E100 ??
|
|
||||||
|
|
||||||
/* System BIOS Date */
|
|
||||||
RtlCopyMemory(SEG_OFF_TO_PTR(0xF000, 0xFFF5), BiosDate, sizeof(BiosDate)-1);
|
|
||||||
|
|
||||||
/* System BIOS Model (same as Bct->Model) */
|
|
||||||
*(PBYTE)(SEG_OFF_TO_PTR(0xF000, 0xFFFE)) = BIOS_MODEL;
|
|
||||||
|
|
||||||
/* Initialize the BDA contents */
|
/* Initialize the BDA contents */
|
||||||
RtlZeroMemory(Bda, sizeof(*Bda));
|
RtlZeroMemory(Bda, sizeof(*Bda));
|
||||||
Bda->EquipmentList = BIOS_EQUIPMENT_LIST;
|
Bda->EquipmentList = BIOS_EQUIPMENT_LIST;
|
||||||
|
@ -556,15 +539,33 @@ static VOID InitializeBiosData(VOID)
|
||||||
Bda->MemorySize = MAKEWORD(Low, High);
|
Bda->MemorySize = MAKEWORD(Low, High);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* PUBLIC FUNCTIONS ***********************************************************/
|
static VOID InitializeBiosInfo(VOID)
|
||||||
|
{
|
||||||
|
RtlZeroMemory(Bct, sizeof(*Bct));
|
||||||
|
|
||||||
|
Bct->Length = sizeof(*Bct);
|
||||||
|
Bct->Model = BIOS_MODEL;
|
||||||
|
Bct->SubModel = BIOS_SUBMODEL;
|
||||||
|
Bct->Revision = BIOS_REVISION;
|
||||||
|
Bct->Feature[0] = 0x70; // At the moment we don't support "wait for external event (INT 15/AH=41h)", we also don't have any "extended BIOS area allocated (usually at top of RAM)"; see http://www.ctyme.com/intr/rb-1594.htm#Table510
|
||||||
|
Bct->Feature[1] = 0x00; // We don't support anything from here; see http://www.ctyme.com/intr/rb-1594.htm#Table511
|
||||||
|
Bct->Feature[2] = 0x00;
|
||||||
|
Bct->Feature[3] = 0x00;
|
||||||
|
Bct->Feature[4] = 0x00;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The BIOS POST (Power On-Self Test)
|
* The BIOS POST (Power On-Self Test)
|
||||||
*/
|
*/
|
||||||
BOOLEAN Bios32Initialize(VOID)
|
VOID
|
||||||
|
Bios32Post(VOID)
|
||||||
{
|
{
|
||||||
BOOLEAN Success;
|
BOOLEAN Success;
|
||||||
|
|
||||||
|
DPRINT1("Bios32Post\n");
|
||||||
|
|
||||||
/* Initialize the stack */
|
/* Initialize the stack */
|
||||||
// That's what says IBM... (stack at 30:00FF going downwards)
|
// That's what says IBM... (stack at 30:00FF going downwards)
|
||||||
// setSS(0x0000);
|
// setSS(0x0000);
|
||||||
|
@ -587,7 +588,13 @@ BOOLEAN Bios32Initialize(VOID)
|
||||||
|
|
||||||
/* Initialize the Keyboard, Video and Mouse BIOS */
|
/* Initialize the Keyboard, Video and Mouse BIOS */
|
||||||
if (!KbdBios32Initialize() || !VidBios32Initialize() || !MouseBios32Initialize())
|
if (!KbdBios32Initialize() || !VidBios32Initialize() || !MouseBios32Initialize())
|
||||||
return FALSE;
|
{
|
||||||
|
// return FALSE;
|
||||||
|
|
||||||
|
/* Stop the VDM */
|
||||||
|
EmulatorTerminate();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
///////////// MUST BE DONE AFTER IVT INITIALIZATION !! /////////////////////
|
///////////// MUST BE DONE AFTER IVT INITIALIZATION !! /////////////////////
|
||||||
|
|
||||||
|
@ -597,10 +604,70 @@ BOOLEAN Bios32Initialize(VOID)
|
||||||
|
|
||||||
SearchAndInitRoms(&BiosContext);
|
SearchAndInitRoms(&BiosContext);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* End of the 32-bit POST portion. We then fall back into 16-bit where
|
||||||
|
* the rest of the POST code is executed, typically calling INT 19h
|
||||||
|
* to boot up the OS.
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
static VOID WINAPI Bios32ResetBop(LPWORD Stack)
|
||||||
|
{
|
||||||
|
DPRINT1("Bios32ResetBop\n");
|
||||||
|
|
||||||
|
/* Disable interrupts */
|
||||||
|
setIF(0);
|
||||||
|
|
||||||
|
// FIXME: Check the word at 0040h:0072h and do one of the following actions:
|
||||||
|
// - if the word is 1234h, perform a warm reboot (aka. Ctrl-Alt-Del);
|
||||||
|
// - if the word is 0000h, perform a cold reboot (aka. Reset).
|
||||||
|
|
||||||
|
/* Initialize IVT and hardware */
|
||||||
|
|
||||||
|
/* Initialize the Keyboard and Video BIOS */
|
||||||
|
if (!KbdBiosInitialize() || !VidBiosInitialize())
|
||||||
|
{
|
||||||
|
/* Stop the VDM */
|
||||||
|
EmulatorTerminate();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Do the POST */
|
||||||
|
Bios32Post();
|
||||||
|
|
||||||
|
/* Enable interrupts */
|
||||||
|
setIF(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* PUBLIC FUNCTIONS ***********************************************************/
|
||||||
|
|
||||||
|
BOOLEAN Bios32Initialize(VOID)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Initialize BIOS32 static data
|
||||||
|
*/
|
||||||
|
|
||||||
/* Bootstrap code */
|
/* Bootstrap code */
|
||||||
RtlCopyMemory(SEG_OFF_TO_PTR(0xF000, 0xE05B), PostCode , sizeof(PostCode ));
|
RtlCopyMemory(SEG_OFF_TO_PTR(0xF000, 0xE05B), PostCode , sizeof(PostCode ));
|
||||||
RtlCopyMemory(SEG_OFF_TO_PTR(0xF000, 0xFFF0), Bootstrap, sizeof(Bootstrap));
|
RtlCopyMemory(SEG_OFF_TO_PTR(0xF000, 0xFFF0), Bootstrap, sizeof(Bootstrap));
|
||||||
|
|
||||||
|
/* System BIOS Copyright */
|
||||||
|
RtlCopyMemory(SEG_OFF_TO_PTR(0xF000, 0xE000), BiosCopyright, sizeof(BiosCopyright)-1);
|
||||||
|
|
||||||
|
/* System BIOS Version */
|
||||||
|
RtlCopyMemory(SEG_OFF_TO_PTR(0xF000, 0xE080), BiosVersion, sizeof(BiosVersion)-1);
|
||||||
|
// FIXME: or E061, or E100 ??
|
||||||
|
|
||||||
|
/* System BIOS Date */
|
||||||
|
RtlCopyMemory(SEG_OFF_TO_PTR(0xF000, 0xFFF5), BiosDate, sizeof(BiosDate)-1);
|
||||||
|
|
||||||
|
/* System BIOS Model (same as Bct->Model) */
|
||||||
|
*(PBYTE)(SEG_OFF_TO_PTR(0xF000, 0xFFFE)) = BIOS_MODEL;
|
||||||
|
|
||||||
|
/* Redefine our POST function */
|
||||||
|
RegisterBop(BOP_RESET, Bios32ResetBop);
|
||||||
|
|
||||||
/* We are done */
|
/* We are done */
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,8 +33,10 @@
|
||||||
/* DEFINES ********************************************************************/
|
/* DEFINES ********************************************************************/
|
||||||
|
|
||||||
/* BOP Identifiers */
|
/* BOP Identifiers */
|
||||||
#define BOP_DOS 0x50 // DOS System BOP (for NTIO.SYS and NTDOS.SYS)
|
#define BOP_LOAD_DOS 0x2B // DOS Loading and Initializing BOP. In parameter (following bytes) we take a NULL-terminated string indicating the name of the DOS kernel file.
|
||||||
#define BOP_CMD 0x54 // DOS Command Interpreter BOP (for COMMAND.COM)
|
#define BOP_START_DOS 0x2C // DOS Starting BOP. In parameter (following bytes) we take a NULL-terminated string indicating the name of the DOS kernel file.
|
||||||
|
#define BOP_DOS 0x50 // DOS System BOP (for NTIO.SYS and NTDOS.SYS)
|
||||||
|
#define BOP_CMD 0x54 // DOS Command Interpreter BOP (for COMMAND.COM)
|
||||||
|
|
||||||
/* PRIVATE FUNCTIONS **********************************************************/
|
/* PRIVATE FUNCTIONS **********************************************************/
|
||||||
|
|
||||||
|
@ -185,17 +187,157 @@ static VOID WINAPI DosCmdInterpreterBop(LPWORD Stack)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef STANDALONE
|
||||||
|
static DWORD
|
||||||
|
WINAPI
|
||||||
|
CommandThreadProc(LPVOID Parameter)
|
||||||
|
{
|
||||||
|
BOOLEAN First = TRUE;
|
||||||
|
DWORD Result;
|
||||||
|
VDM_COMMAND_INFO CommandInfo;
|
||||||
|
CHAR CmdLine[MAX_PATH];
|
||||||
|
CHAR AppName[MAX_PATH];
|
||||||
|
CHAR PifFile[MAX_PATH];
|
||||||
|
CHAR Desktop[MAX_PATH];
|
||||||
|
CHAR Title[MAX_PATH];
|
||||||
|
ULONG EnvSize = 256;
|
||||||
|
PVOID Env = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, EnvSize);
|
||||||
|
|
||||||
|
UNREFERENCED_PARAMETER(Parameter);
|
||||||
|
ASSERT(Env != NULL);
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
/* Clear the structure */
|
||||||
|
ZeroMemory(&CommandInfo, sizeof(CommandInfo));
|
||||||
|
|
||||||
|
/* Initialize the structure members */
|
||||||
|
CommandInfo.TaskId = SessionId;
|
||||||
|
CommandInfo.VDMState = VDM_FLAG_DOS;
|
||||||
|
CommandInfo.CmdLine = CmdLine;
|
||||||
|
CommandInfo.CmdLen = sizeof(CmdLine);
|
||||||
|
CommandInfo.AppName = AppName;
|
||||||
|
CommandInfo.AppLen = sizeof(AppName);
|
||||||
|
CommandInfo.PifFile = PifFile;
|
||||||
|
CommandInfo.PifLen = sizeof(PifFile);
|
||||||
|
CommandInfo.Desktop = Desktop;
|
||||||
|
CommandInfo.DesktopLen = sizeof(Desktop);
|
||||||
|
CommandInfo.Title = Title;
|
||||||
|
CommandInfo.TitleLen = sizeof(Title);
|
||||||
|
CommandInfo.Env = Env;
|
||||||
|
CommandInfo.EnvLen = EnvSize;
|
||||||
|
|
||||||
|
if (First) CommandInfo.VDMState |= VDM_FLAG_FIRST_TASK;
|
||||||
|
|
||||||
|
Command:
|
||||||
|
if (!GetNextVDMCommand(&CommandInfo))
|
||||||
|
{
|
||||||
|
if (CommandInfo.EnvLen > EnvSize)
|
||||||
|
{
|
||||||
|
/* Expand the environment size */
|
||||||
|
EnvSize = CommandInfo.EnvLen;
|
||||||
|
Env = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, Env, EnvSize);
|
||||||
|
|
||||||
|
/* Repeat the request */
|
||||||
|
goto Command;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Start the process from the command line */
|
||||||
|
DPRINT1("Starting '%s' ('%s')...\n", AppName, CmdLine);
|
||||||
|
Result = DosStartProcess(AppName, CmdLine, Env);
|
||||||
|
if (Result != ERROR_SUCCESS)
|
||||||
|
{
|
||||||
|
DisplayMessage(L"Could not start '%S'. Error: %u", AppName, Result);
|
||||||
|
// break;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
First = FALSE;
|
||||||
|
}
|
||||||
|
while (AcceptCommands);
|
||||||
|
|
||||||
|
HeapFree(GetProcessHeap(), 0, Env);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* PUBLIC FUNCTIONS ***********************************************************/
|
/* PUBLIC FUNCTIONS ***********************************************************/
|
||||||
|
|
||||||
BOOLEAN DosInitialize(IN LPCSTR DosKernelFileName)
|
//
|
||||||
|
// This function (equivalent of the DOS bootsector) is called by the bootstrap
|
||||||
|
// loader *BEFORE* jumping at 0000:7C00. What we should do is to write at 0000:7C00
|
||||||
|
// a BOP call that calls DosInitialize back. Then the bootstrap loader jumps at
|
||||||
|
// 0000:7C00, our BOP gets called and then we can initialize the 32-bit part of the DOS.
|
||||||
|
//
|
||||||
|
|
||||||
|
/* 16-bit bootstrap code at 0000:7C00 */
|
||||||
|
/* Of course, this is not in real bootsector format, because we don't care */
|
||||||
|
static BYTE Bootsector1[] =
|
||||||
{
|
{
|
||||||
|
LOBYTE(EMULATOR_BOP), HIBYTE(EMULATOR_BOP), BOP_LOAD_DOS, // Call DOS Loading
|
||||||
|
};
|
||||||
|
/* This portion of code is run if we failed to load the DOS */
|
||||||
|
static BYTE Bootsector2[] =
|
||||||
|
{
|
||||||
|
0xEA, // jmp far ptr
|
||||||
|
0x5B, 0xE0, 0x00, 0xF0, // F000:E05B /** HACK! What to do instead?? **/
|
||||||
|
};
|
||||||
|
|
||||||
|
static VOID WINAPI DosInitialize(LPWORD Stack);
|
||||||
|
|
||||||
|
VOID DosBootsectorInitialize(VOID)
|
||||||
|
{
|
||||||
|
/* We write the bootsector at 0000:7C00 */
|
||||||
|
ULONG_PTR Address = (ULONG_PTR)SEG_OFF_TO_PTR(0x0000, 0x7C00);
|
||||||
|
CHAR DosKernelFileName[] = ""; // No DOS file name, therefore we'll load DOS32
|
||||||
|
|
||||||
|
DPRINT1("DosBootsectorInitialize\n");
|
||||||
|
|
||||||
|
/* Write the "bootsector" */
|
||||||
|
RtlCopyMemory((PVOID)Address, Bootsector1, sizeof(Bootsector1));
|
||||||
|
Address += sizeof(Bootsector1);
|
||||||
|
RtlCopyMemory((PVOID)Address, DosKernelFileName, sizeof(DosKernelFileName));
|
||||||
|
Address += sizeof(DosKernelFileName);
|
||||||
|
RtlCopyMemory((PVOID)Address, Bootsector2, sizeof(Bootsector2));
|
||||||
|
|
||||||
|
/* Register the DOS Loading BOP */
|
||||||
|
RegisterBop(BOP_LOAD_DOS, DosInitialize);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// This function is called by the DOS bootsector. We finish to load
|
||||||
|
// the DOS, then we jump to 0070:0000.
|
||||||
|
//
|
||||||
|
|
||||||
|
/* 16-bit startup code at 0070:0000 */
|
||||||
|
static BYTE Startup[] =
|
||||||
|
{
|
||||||
|
LOBYTE(EMULATOR_BOP), HIBYTE(EMULATOR_BOP), BOP_START_DOS, // Call DOS Start
|
||||||
|
};
|
||||||
|
|
||||||
|
static VOID WINAPI DosStart(LPWORD Stack);
|
||||||
|
|
||||||
|
static VOID WINAPI DosInitialize(LPWORD Stack)
|
||||||
|
{
|
||||||
|
BOOLEAN Success = FALSE;
|
||||||
|
|
||||||
|
/* Get the DOS kernel file name (NULL-terminated) */
|
||||||
|
// FIXME: Isn't it possible to use some DS:SI instead??
|
||||||
|
LPCSTR DosKernelFileName = (LPCSTR)SEG_OFF_TO_PTR(getCS(), getIP());
|
||||||
|
setIP(getIP() + strlen(DosKernelFileName) + 1); // Skip it
|
||||||
|
|
||||||
|
DPRINT1("DosInitialize('%s')\n", DosKernelFileName);
|
||||||
|
|
||||||
/* Register the DOS BOPs */
|
/* Register the DOS BOPs */
|
||||||
RegisterBop(BOP_DOS, DosSystemBop );
|
RegisterBop(BOP_DOS, DosSystemBop );
|
||||||
RegisterBop(BOP_CMD, DosCmdInterpreterBop);
|
RegisterBop(BOP_CMD, DosCmdInterpreterBop);
|
||||||
|
|
||||||
if (DosKernelFileName)
|
if (DosKernelFileName && DosKernelFileName[0] != '\0')
|
||||||
{
|
{
|
||||||
BOOLEAN Success;
|
|
||||||
HANDLE hDosBios;
|
HANDLE hDosBios;
|
||||||
ULONG ulDosBiosSize = 0;
|
ULONG ulDosBiosSize = 0;
|
||||||
|
|
||||||
|
@ -203,7 +345,7 @@ BOOLEAN DosInitialize(IN LPCSTR DosKernelFileName)
|
||||||
hDosBios = FileOpen(DosKernelFileName, &ulDosBiosSize);
|
hDosBios = FileOpen(DosKernelFileName, &ulDosBiosSize);
|
||||||
|
|
||||||
/* If we failed, bail out */
|
/* If we failed, bail out */
|
||||||
if (hDosBios == NULL) return FALSE;
|
if (hDosBios == NULL) goto QuitCustom;
|
||||||
|
|
||||||
/* Attempt to load the DOS BIOS into memory */
|
/* Attempt to load the DOS BIOS into memory */
|
||||||
Success = FileLoadByHandle(hDosBios,
|
Success = FileLoadByHandle(hDosBios,
|
||||||
|
@ -220,27 +362,122 @@ BOOLEAN DosInitialize(IN LPCSTR DosKernelFileName)
|
||||||
/* Close the DOS BIOS file */
|
/* Close the DOS BIOS file */
|
||||||
FileClose(hDosBios);
|
FileClose(hDosBios);
|
||||||
|
|
||||||
if (Success)
|
if (!Success) goto QuitCustom;
|
||||||
{
|
|
||||||
/* Position execution pointers and return */
|
|
||||||
setCS(0x0070);
|
|
||||||
setIP(0x0000);
|
|
||||||
}
|
|
||||||
|
|
||||||
return Success;
|
/* Position execution pointers and return */
|
||||||
|
setCS(0x0070);
|
||||||
|
setIP(0x0000);
|
||||||
|
|
||||||
|
/* Return control */
|
||||||
|
QuitCustom:
|
||||||
|
if (!Success)
|
||||||
|
DisplayMessage(L"Custom DOS '%S' loading failed, what to do??", DosKernelFileName);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
BOOLEAN Result;
|
Success = DosBIOSInitialize();
|
||||||
|
// Success &= DosKRNLInitialize();
|
||||||
|
|
||||||
Result = DosBIOSInitialize();
|
if (!Success) goto Quit32;
|
||||||
DosMouseInitialize(); // FIXME: Should be done by the DOS BIOS
|
|
||||||
// Result &= DosKRNLInitialize();
|
|
||||||
|
|
||||||
return Result;
|
/* Write the "bootsector" */
|
||||||
|
RtlCopyMemory(SEG_OFF_TO_PTR(0x0070, 0x0000), Startup, sizeof(Startup));
|
||||||
|
|
||||||
|
/* Register the DOS Starting BOP */
|
||||||
|
RegisterBop(BOP_START_DOS, DosStart);
|
||||||
|
|
||||||
|
/* Position execution pointers and return */
|
||||||
|
setCS(0x0070);
|
||||||
|
setIP(0x0000);
|
||||||
|
|
||||||
|
/* Return control */
|
||||||
|
Quit32:
|
||||||
|
if (!Success)
|
||||||
|
DisplayMessage(L"DOS32 loading failed, what to do??");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Success)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* We succeeded, deregister the DOS Loading BOP
|
||||||
|
* so that no app will be able to call us back.
|
||||||
|
*/
|
||||||
|
RegisterBop(BOP_LOAD_DOS, NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static VOID WINAPI DosStart(LPWORD Stack)
|
||||||
|
{
|
||||||
|
#ifdef STANDALONE
|
||||||
|
DWORD Result;
|
||||||
|
CHAR ApplicationName[MAX_PATH];
|
||||||
|
CHAR CommandLine[DOS_CMDLINE_LENGTH];
|
||||||
|
#endif
|
||||||
|
|
||||||
|
DPRINT1("DosStart\n");
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We succeeded, deregister the DOS Starting BOP
|
||||||
|
* so that no app will be able to call us back.
|
||||||
|
*/
|
||||||
|
RegisterBop(BOP_START_DOS, NULL);
|
||||||
|
|
||||||
|
/* Load the mouse driver */
|
||||||
|
DosMouseInitialize();
|
||||||
|
|
||||||
|
#ifndef STANDALONE
|
||||||
|
|
||||||
|
/* Create the GetNextVDMCommand thread */
|
||||||
|
CommandThread = CreateThread(NULL, 0, &CommandThreadProc, NULL, 0, NULL);
|
||||||
|
if (CommandThread == NULL)
|
||||||
|
{
|
||||||
|
wprintf(L"FATAL: Failed to create the command processing thread: %d\n", GetLastError());
|
||||||
|
goto Quit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Wait for the command thread to exit */
|
||||||
|
WaitForSingleObject(CommandThread, INFINITE);
|
||||||
|
|
||||||
|
/* Close the thread handle */
|
||||||
|
CloseHandle(CommandThread);
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
if (NtVdmArgc >= 2)
|
||||||
|
{
|
||||||
|
WideCharToMultiByte(CP_ACP, 0, NtVdmArgv[1], -1, ApplicationName, sizeof(ApplicationName), NULL, NULL);
|
||||||
|
|
||||||
|
if (NtVdmArgc >= 3)
|
||||||
|
WideCharToMultiByte(CP_ACP, 0, NtVdmArgv[2], -1, CommandLine, sizeof(CommandLine), NULL, NULL);
|
||||||
|
else
|
||||||
|
strcpy(CommandLine, "");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DisplayMessage(L"Invalid DOS command line\n");
|
||||||
|
goto Quit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Start the process from the command line */
|
||||||
|
DPRINT1("Starting '%s' ('%s')...\n", ApplicationName, CommandLine);
|
||||||
|
Result = DosStartProcess(ApplicationName,
|
||||||
|
CommandLine,
|
||||||
|
GetEnvironmentStrings());
|
||||||
|
if (Result != ERROR_SUCCESS)
|
||||||
|
{
|
||||||
|
DisplayMessage(L"Could not start '%S'. Error: %u", ApplicationName, Result);
|
||||||
|
goto Quit;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
Quit:
|
||||||
|
/* Stop the VDM */
|
||||||
|
EmulatorTerminate();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* PUBLIC EXPORTED APIS *******************************************************/
|
/* PUBLIC EXPORTED APIS *******************************************************/
|
||||||
|
|
||||||
// demLFNCleanup
|
// demLFNCleanup
|
||||||
|
|
|
@ -20,8 +20,6 @@
|
||||||
|
|
||||||
/* FUNCTIONS ******************************************************************/
|
/* FUNCTIONS ******************************************************************/
|
||||||
|
|
||||||
BOOLEAN DosInitialize(IN LPCSTR DosKernelFileNames);
|
|
||||||
|
|
||||||
DWORD
|
DWORD
|
||||||
WINAPI
|
WINAPI
|
||||||
demClientErrorEx
|
demClientErrorEx
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
|
|
||||||
#include "ntvdm.h"
|
#include "ntvdm.h"
|
||||||
#include "emulator.h"
|
#include "emulator.h"
|
||||||
|
#include "cpu/cpu.h"
|
||||||
|
|
||||||
#include "clock.h"
|
#include "clock.h"
|
||||||
#include "hardware/ps2.h"
|
#include "hardware/ps2.h"
|
||||||
|
@ -26,19 +27,25 @@
|
||||||
static HANDLE ConsoleInput = INVALID_HANDLE_VALUE;
|
static HANDLE ConsoleInput = INVALID_HANDLE_VALUE;
|
||||||
static HANDLE ConsoleOutput = INVALID_HANDLE_VALUE;
|
static HANDLE ConsoleOutput = INVALID_HANDLE_VALUE;
|
||||||
static DWORD OrgConsoleInputMode, OrgConsoleOutputMode;
|
static DWORD OrgConsoleInputMode, OrgConsoleOutputMode;
|
||||||
static BOOLEAN AcceptCommands = TRUE;
|
|
||||||
static HANDLE CommandThread = NULL;
|
|
||||||
|
|
||||||
static HMENU hConsoleMenu = NULL;
|
|
||||||
static INT VdmMenuPos = -1;
|
|
||||||
static BOOLEAN ShowPointer = FALSE;
|
|
||||||
|
|
||||||
|
// For DOS
|
||||||
#ifndef STANDALONE
|
#ifndef STANDALONE
|
||||||
|
BOOLEAN AcceptCommands = TRUE;
|
||||||
|
HANDLE CommandThread = NULL;
|
||||||
ULONG SessionId = 0;
|
ULONG SessionId = 0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
HANDLE VdmTaskEvent = NULL;
|
HANDLE VdmTaskEvent = NULL;
|
||||||
|
|
||||||
|
// Command line of NTVDM
|
||||||
|
INT NtVdmArgc;
|
||||||
|
WCHAR** NtVdmArgv;
|
||||||
|
|
||||||
|
|
||||||
|
static HMENU hConsoleMenu = NULL;
|
||||||
|
static INT VdmMenuPos = -1;
|
||||||
|
static BOOLEAN ShowPointer = FALSE;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Those menu helpers were taken from the GUI frontend in winsrv.dll
|
* Those menu helpers were taken from the GUI frontend in winsrv.dll
|
||||||
*/
|
*/
|
||||||
|
@ -198,6 +205,7 @@ ConsoleCtrlHandler(DWORD ControlType)
|
||||||
case CTRL_BREAK_EVENT:
|
case CTRL_BREAK_EVENT:
|
||||||
{
|
{
|
||||||
/* Call INT 23h */
|
/* Call INT 23h */
|
||||||
|
DPRINT1("Ctrl-C/Break: Call INT 23h\n");
|
||||||
EmulatorInterrupt(0x23);
|
EmulatorInterrupt(0x23);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -206,14 +214,18 @@ ConsoleCtrlHandler(DWORD ControlType)
|
||||||
if (WaitForSingleObject(VdmTaskEvent, 0) == WAIT_TIMEOUT)
|
if (WaitForSingleObject(VdmTaskEvent, 0) == WAIT_TIMEOUT)
|
||||||
{
|
{
|
||||||
/* Exit immediately */
|
/* Exit immediately */
|
||||||
|
#ifndef STANDALONE
|
||||||
if (CommandThread) TerminateThread(CommandThread, 0);
|
if (CommandThread) TerminateThread(CommandThread, 0);
|
||||||
|
#endif
|
||||||
EmulatorTerminate();
|
EmulatorTerminate();
|
||||||
}
|
}
|
||||||
|
#ifndef STANDALONE
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Stop accepting new commands */
|
/* Stop accepting new commands */
|
||||||
AcceptCommands = FALSE;
|
AcceptCommands = FALSE;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -361,100 +373,12 @@ VOID FocusEventHandler(PFOCUS_EVENT_RECORD FocusEvent)
|
||||||
DPRINT1("Focus events not handled\n");
|
DPRINT1("Focus events not handled\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef STANDALONE
|
|
||||||
static DWORD
|
|
||||||
WINAPI
|
|
||||||
CommandThreadProc(LPVOID Parameter)
|
|
||||||
{
|
|
||||||
BOOLEAN First = TRUE;
|
|
||||||
DWORD Result;
|
|
||||||
VDM_COMMAND_INFO CommandInfo;
|
|
||||||
CHAR CmdLine[MAX_PATH];
|
|
||||||
CHAR AppName[MAX_PATH];
|
|
||||||
CHAR PifFile[MAX_PATH];
|
|
||||||
CHAR Desktop[MAX_PATH];
|
|
||||||
CHAR Title[MAX_PATH];
|
|
||||||
ULONG EnvSize = 256;
|
|
||||||
PVOID Env = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, EnvSize);
|
|
||||||
|
|
||||||
UNREFERENCED_PARAMETER(Parameter);
|
|
||||||
ASSERT(Env != NULL);
|
|
||||||
|
|
||||||
do
|
|
||||||
{
|
|
||||||
/* Clear the structure */
|
|
||||||
ZeroMemory(&CommandInfo, sizeof(CommandInfo));
|
|
||||||
|
|
||||||
/* Initialize the structure members */
|
|
||||||
CommandInfo.TaskId = SessionId;
|
|
||||||
CommandInfo.VDMState = VDM_FLAG_DOS;
|
|
||||||
CommandInfo.CmdLine = CmdLine;
|
|
||||||
CommandInfo.CmdLen = sizeof(CmdLine);
|
|
||||||
CommandInfo.AppName = AppName;
|
|
||||||
CommandInfo.AppLen = sizeof(AppName);
|
|
||||||
CommandInfo.PifFile = PifFile;
|
|
||||||
CommandInfo.PifLen = sizeof(PifFile);
|
|
||||||
CommandInfo.Desktop = Desktop;
|
|
||||||
CommandInfo.DesktopLen = sizeof(Desktop);
|
|
||||||
CommandInfo.Title = Title;
|
|
||||||
CommandInfo.TitleLen = sizeof(Title);
|
|
||||||
CommandInfo.Env = Env;
|
|
||||||
CommandInfo.EnvLen = EnvSize;
|
|
||||||
|
|
||||||
if (First) CommandInfo.VDMState |= VDM_FLAG_FIRST_TASK;
|
|
||||||
|
|
||||||
Command:
|
|
||||||
if (!GetNextVDMCommand(&CommandInfo))
|
|
||||||
{
|
|
||||||
if (CommandInfo.EnvLen > EnvSize)
|
|
||||||
{
|
|
||||||
/* Expand the environment size */
|
|
||||||
EnvSize = CommandInfo.EnvLen;
|
|
||||||
Env = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, Env, EnvSize);
|
|
||||||
|
|
||||||
/* Repeat the request */
|
|
||||||
goto Command;
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Start the process from the command line */
|
|
||||||
DPRINT1("Starting '%s' ('%s')...\n", AppName, CmdLine);
|
|
||||||
Result = DosStartProcess(AppName, CmdLine, Env);
|
|
||||||
if (Result != ERROR_SUCCESS)
|
|
||||||
{
|
|
||||||
DisplayMessage(L"Could not start '%S'. Error: %u", AppName, Result);
|
|
||||||
// break;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
First = FALSE;
|
|
||||||
}
|
|
||||||
while (AcceptCommands);
|
|
||||||
|
|
||||||
HeapFree(GetProcessHeap(), 0, Env);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
INT
|
INT
|
||||||
wmain(INT argc, WCHAR *argv[])
|
wmain(INT argc, WCHAR *argv[])
|
||||||
{
|
{
|
||||||
#ifdef STANDALONE
|
#ifdef STANDALONE
|
||||||
|
|
||||||
DWORD Result;
|
if (argc < 2)
|
||||||
CHAR ApplicationName[MAX_PATH];
|
|
||||||
CHAR CommandLine[DOS_CMDLINE_LENGTH];
|
|
||||||
|
|
||||||
if (argc >= 2)
|
|
||||||
{
|
|
||||||
WideCharToMultiByte(CP_ACP, 0, argv[1], -1, ApplicationName, sizeof(ApplicationName), NULL, NULL);
|
|
||||||
|
|
||||||
if (argc >= 3) WideCharToMultiByte(CP_ACP, 0, argv[2], -1, CommandLine, sizeof(CommandLine), NULL, NULL);
|
|
||||||
else strcpy(CommandLine, "");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
wprintf(L"\nReactOS Virtual DOS Machine\n\n"
|
wprintf(L"\nReactOS Virtual DOS Machine\n\n"
|
||||||
L"Usage: NTVDM <executable> [<parameters>]\n");
|
L"Usage: NTVDM <executable> [<parameters>]\n");
|
||||||
|
@ -481,6 +405,9 @@ wmain(INT argc, WCHAR *argv[])
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
NtVdmArgc = argc;
|
||||||
|
NtVdmArgv = argv;
|
||||||
|
|
||||||
DPRINT1("\n\n\nNTVDM - Starting...\n\n\n");
|
DPRINT1("\n\n\nNTVDM - Starting...\n\n\n");
|
||||||
|
|
||||||
/* Create the task event */
|
/* Create the task event */
|
||||||
|
@ -508,43 +435,8 @@ wmain(INT argc, WCHAR *argv[])
|
||||||
goto Cleanup;
|
goto Cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Initialize the VDM DOS kernel */
|
/* Let's go! Start simulation */
|
||||||
if (!DosInitialize(NULL))
|
CpuSimulate();
|
||||||
{
|
|
||||||
wprintf(L"FATAL: Failed to initialize the VDM DOS kernel.\n");
|
|
||||||
goto Cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef STANDALONE
|
|
||||||
|
|
||||||
/* Create the GetNextVDMCommand thread */
|
|
||||||
CommandThread = CreateThread(NULL, 0, &CommandThreadProc, NULL, 0, NULL);
|
|
||||||
if (CommandThread == NULL)
|
|
||||||
{
|
|
||||||
wprintf(L"FATAL: Failed to create the command processing thread: %d\n", GetLastError());
|
|
||||||
goto Cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Wait for the command thread to exit */
|
|
||||||
WaitForSingleObject(CommandThread, INFINITE);
|
|
||||||
|
|
||||||
/* Close the thread handle */
|
|
||||||
CloseHandle(CommandThread);
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
/* Start the process from the command line */
|
|
||||||
DPRINT1("Starting '%s' ('%s')...\n", ApplicationName, CommandLine);
|
|
||||||
Result = DosStartProcess(ApplicationName,
|
|
||||||
CommandLine,
|
|
||||||
GetEnvironmentStrings());
|
|
||||||
if (Result != ERROR_SUCCESS)
|
|
||||||
{
|
|
||||||
DisplayMessage(L"Could not start '%S'. Error: %u", ApplicationName, Result);
|
|
||||||
goto Cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
Cleanup:
|
Cleanup:
|
||||||
BiosCleanup();
|
BiosCleanup();
|
||||||
|
|
|
@ -41,11 +41,18 @@ DWORD WINAPI SetLastConsoleEventActive(VOID);
|
||||||
/* FUNCTIONS ******************************************************************/
|
/* FUNCTIONS ******************************************************************/
|
||||||
|
|
||||||
#ifndef STANDALONE
|
#ifndef STANDALONE
|
||||||
|
extern BOOLEAN AcceptCommands;
|
||||||
|
extern HANDLE CommandThread;
|
||||||
extern ULONG SessionId;
|
extern ULONG SessionId;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
extern HANDLE VdmTaskEvent;
|
extern HANDLE VdmTaskEvent;
|
||||||
|
|
||||||
|
// Command line of NTVDM
|
||||||
|
extern INT NtVdmArgc;
|
||||||
|
extern WCHAR** NtVdmArgv;
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Interface functions
|
* Interface functions
|
||||||
*/
|
*/
|
||||||
|
|
Loading…
Reference in a new issue