/*
* COPYRIGHT: GPL - See COPYING in the top level directory
* PROJECT: ReactOS Virtual DOS Machine
- * FILE: ntvdm.c
+ * FILE: subsystems/mvdm/ntvdm/ntvdm.c
* PURPOSE: Virtual DOS Machine
* PROGRAMMERS: Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
*/
#include "bios/bios.h"
#include "cpu/cpu.h"
+#include "dos/dem.h"
+
#include "resource.h"
/* VARIABLES ******************************************************************/
static HANDLE ConsoleOutput = INVALID_HANDLE_VALUE;
static DWORD OrgConsoleInputMode, OrgConsoleOutputMode;
-HANDLE VdmTaskEvent = NULL;
+NTVDM_SETTINGS GlobalSettings;
// Command line of NTVDM
INT NtVdmArgc;
WCHAR** NtVdmArgv;
-
+HWND hConsoleWnd = NULL;
static HMENU hConsoleMenu = NULL;
static INT VdmMenuPos = -1;
static BOOLEAN ShowPointer = FALSE;
{
UINT uID;
const struct _VDM_MENUITEM *SubMenu;
- WORD wCmdID;
+ UINT_PTR uCmdID;
} VDM_MENUITEM, *PVDM_MENUITEM;
static const VDM_MENUITEM VdmMenuItems[] =
{
{ IDS_VDM_DUMPMEM_TXT, NULL, ID_VDM_DUMPMEM_TXT },
{ IDS_VDM_DUMPMEM_BIN, NULL, ID_VDM_DUMPMEM_BIN },
+ { -1, NULL, 0 }, /* Separator */
+ // { IDS_VDM_MOUNT_FLOPPY, NULL, ID_VDM_DRIVES },
+ // { IDS_VDM_EJECT_FLOPPY, NULL, ID_VDM_DRIVES },
+ { -1, NULL, 0 }, /* Separator */
{ IDS_VDM_QUIT , NULL, ID_VDM_QUIT },
{ 0, NULL, 0 } /* End of list */
static const VDM_MENUITEM VdmMainMenuItems[] =
{
{ -1, NULL, 0 }, /* Separator */
- { IDS_HIDE_MOUSE, NULL, ID_SHOWHIDE_MOUSE }, /* Hide mouse; can be renamed to Show mouse */
+ { IDS_HIDE_MOUSE, NULL, ID_SHOWHIDE_MOUSE }, /* "Hide mouse"; can be renamed to "Show mouse" */
{ IDS_VDM_MENU , VdmMenuItems, 0 }, /* ReactOS VDM Menu */
{ 0, NULL, 0 } /* End of list */
const VDM_MENUITEM *Items)
{
UINT i = 0;
- WCHAR szMenuString[255];
+ WCHAR szMenuString[256];
HMENU hSubMenu;
do
{
AppendMenuW(hMenu,
MF_STRING,
- Items[i].wCmdID,
+ Items[i].uCmdID,
szMenuString);
}
}
NULL);
}
i++;
- } while (!(Items[i].uID == 0 && Items[i].SubMenu == NULL && Items[i].wCmdID == 0));
+ } while (!(Items[i].uID == 0 && Items[i].SubMenu == NULL && Items[i].uCmdID == 0));
}
BOOL
{
if (GetMenuItemID(hConsoleMenu, i) == ID_SHOWHIDE_MOUSE)
{
- /* set VdmMenuPos to the position of the existing menu */
+ /* Set VdmMenuPos to the position of the existing menu */
VdmMenuPos = i - 1;
return TRUE;
}
/*static*/ VOID
CreateVdmMenu(HANDLE ConOutHandle)
{
+ HMENU hVdmSubMenu;
+ UINT_PTR ItemID = ID_VDM_DRIVES;
+ UINT Pos;
+ WCHAR szNoMedia[100];
+ WCHAR szMenuString1[256], szMenuString2[256];
+
hConsoleMenu = ConsoleMenuControl(ConOutHandle,
ID_SHOWHIDE_MOUSE,
- ID_VDM_QUIT);
+ ID_VDM_DRIVES + 4);
if (hConsoleMenu == NULL) return;
/* Get the position where we are going to insert our menu items */
/* Really add the menu if it doesn't already exist (in case eg. NTVDM crashed) */
if (!VdmMenuExists(hConsoleMenu))
{
+ /* Add all the menu entries */
AppendMenuItems(hConsoleMenu, VdmMainMenuItems);
- DrawMenuBar(GetConsoleWindow());
+
+ /* Add the removable drives menu entries */
+ hVdmSubMenu = GetSubMenu(hConsoleMenu, VdmMenuPos + 2); // VdmMenuItems
+ Pos = 3; // After the 2 items and the separator in VdmMenuItems
+
+ LoadStringW(GetModuleHandle(NULL),
+ IDS_NO_MEDIA,
+ szNoMedia,
+ ARRAYSIZE(szNoMedia));
+
+ LoadStringW(GetModuleHandle(NULL),
+ IDS_VDM_MOUNT_FLOPPY,
+ szMenuString1,
+ ARRAYSIZE(szMenuString1));
+
+ /* Drive 0 -- Mount */
+ _snwprintf(szMenuString2, ARRAYSIZE(szMenuString2), szMenuString1, 0, szNoMedia);
+ szMenuString2[ARRAYSIZE(szMenuString2) - 1] = UNICODE_NULL;
+ InsertMenuW(hVdmSubMenu, Pos++, MF_STRING | MF_BYPOSITION, ItemID + 0, szMenuString2);
+
+ /* Drive 1 -- Mount */
+ _snwprintf(szMenuString2, ARRAYSIZE(szMenuString2), szMenuString1, 1, szNoMedia);
+ szMenuString2[ARRAYSIZE(szMenuString2) - 1] = UNICODE_NULL;
+ InsertMenuW(hVdmSubMenu, Pos++, MF_STRING | MF_BYPOSITION, ItemID + 2, szMenuString2);
+
+ LoadStringW(GetModuleHandle(NULL),
+ IDS_VDM_EJECT_FLOPPY,
+ szMenuString1,
+ ARRAYSIZE(szMenuString1));
+
+ /* Drive 0 -- Eject */
+ _snwprintf(szMenuString2, ARRAYSIZE(szMenuString2), szMenuString1, 0);
+ szMenuString2[ARRAYSIZE(szMenuString2) - 1] = UNICODE_NULL;
+ InsertMenuW(hVdmSubMenu, Pos++, MF_STRING | MF_BYPOSITION, ItemID + 1, szMenuString2);
+
+ /* Drive 1 -- Eject */
+ _snwprintf(szMenuString2, ARRAYSIZE(szMenuString2), szMenuString1, 1);
+ szMenuString2[ARRAYSIZE(szMenuString2) - 1] = UNICODE_NULL;
+ InsertMenuW(hVdmSubMenu, Pos++, MF_STRING | MF_BYPOSITION, ItemID + 3, szMenuString2);
+
+ // TODO: Refresh the menu state
+
+ /* Refresh the menu */
+ DrawMenuBar(hConsoleWnd);
}
}
{
DeleteMenu(hConsoleMenu, VdmMenuPos, MF_BYPOSITION);
i++;
- } while (!(Items[i].uID == 0 && Items[i].SubMenu == NULL && Items[i].wCmdID == 0));
+ } while (!(Items[i].uID == 0 && Items[i].SubMenu == NULL && Items[i].uCmdID == 0));
- DrawMenuBar(GetConsoleWindow());
+ DrawMenuBar(hConsoleWnd);
}
static VOID ShowHideMousePointer(HANDLE ConOutHandle, BOOLEAN ShowPtr)
{
- WCHAR szMenuString[255] = L"";
+ WCHAR szMenuString[256];
if (ShowPtr)
{
}
}
+
+static NTSTATUS
+NTAPI
+NtVdmConfigureBios(IN PWSTR ValueName,
+ IN ULONG ValueType,
+ IN PVOID ValueData,
+ IN ULONG ValueLength,
+ IN PVOID Context,
+ IN PVOID EntryContext)
+{
+ PNTVDM_SETTINGS Settings = (PNTVDM_SETTINGS)Context;
+ UNICODE_STRING ValueString;
+
+ /* Check for the type of the value */
+ if (ValueType != REG_SZ)
+ {
+ RtlInitEmptyAnsiString(&Settings->BiosFileName, NULL, 0);
+ return STATUS_SUCCESS;
+ }
+
+ /* Convert the UNICODE string to ANSI and store it */
+ RtlInitEmptyUnicodeString(&ValueString, (PWCHAR)ValueData, ValueLength);
+ ValueString.Length = ValueString.MaximumLength;
+ RtlUnicodeStringToAnsiString(&Settings->BiosFileName, &ValueString, TRUE);
+
+ return STATUS_SUCCESS;
+}
+
+static NTSTATUS
+NTAPI
+NtVdmConfigureRom(IN PWSTR ValueName,
+ IN ULONG ValueType,
+ IN PVOID ValueData,
+ IN ULONG ValueLength,
+ IN PVOID Context,
+ IN PVOID EntryContext)
+{
+ PNTVDM_SETTINGS Settings = (PNTVDM_SETTINGS)Context;
+ UNICODE_STRING ValueString;
+
+ /* Check for the type of the value */
+ if (ValueType != REG_MULTI_SZ)
+ {
+ RtlInitEmptyAnsiString(&Settings->RomFiles, NULL, 0);
+ return STATUS_SUCCESS;
+ }
+
+ /* Convert the UNICODE string to ANSI and store it */
+ RtlInitEmptyUnicodeString(&ValueString, (PWCHAR)ValueData, ValueLength);
+ ValueString.Length = ValueString.MaximumLength;
+ RtlUnicodeStringToAnsiString(&Settings->RomFiles, &ValueString, TRUE);
+
+ return STATUS_SUCCESS;
+}
+
+static NTSTATUS
+NTAPI
+NtVdmConfigureFloppy(IN PWSTR ValueName,
+ IN ULONG ValueType,
+ IN PVOID ValueData,
+ IN ULONG ValueLength,
+ IN PVOID Context,
+ IN PVOID EntryContext)
+{
+ PNTVDM_SETTINGS Settings = (PNTVDM_SETTINGS)Context;
+ UNICODE_STRING ValueString;
+ ULONG DiskNumber = (ULONG)EntryContext;
+
+ ASSERT(DiskNumber < ARRAYSIZE(Settings->FloppyDisks));
+
+ /* Check whether the Hard Disk entry was not already configured */
+ if (Settings->FloppyDisks[DiskNumber].Buffer != NULL)
+ {
+ DPRINT1("Floppy Disk %d -- '%Z' already configured\n", DiskNumber, &Settings->FloppyDisks[DiskNumber]);
+ return STATUS_SUCCESS;
+ }
+
+ /* Check for the type of the value */
+ if (ValueType != REG_SZ)
+ {
+ RtlInitEmptyAnsiString(&Settings->FloppyDisks[DiskNumber], NULL, 0);
+ return STATUS_SUCCESS;
+ }
+
+ /* Convert the UNICODE string to ANSI and store it */
+ RtlInitEmptyUnicodeString(&ValueString, (PWCHAR)ValueData, ValueLength);
+ ValueString.Length = ValueString.MaximumLength;
+ RtlUnicodeStringToAnsiString(&Settings->FloppyDisks[DiskNumber], &ValueString, TRUE);
+
+ return STATUS_SUCCESS;
+}
+
+static NTSTATUS
+NTAPI
+NtVdmConfigureHDD(IN PWSTR ValueName,
+ IN ULONG ValueType,
+ IN PVOID ValueData,
+ IN ULONG ValueLength,
+ IN PVOID Context,
+ IN PVOID EntryContext)
+{
+ PNTVDM_SETTINGS Settings = (PNTVDM_SETTINGS)Context;
+ UNICODE_STRING ValueString;
+ ULONG DiskNumber = (ULONG)EntryContext;
+
+ ASSERT(DiskNumber < ARRAYSIZE(Settings->HardDisks));
+
+ /* Check whether the Hard Disk entry was not already configured */
+ if (Settings->HardDisks[DiskNumber].Buffer != NULL)
+ {
+ DPRINT1("Hard Disk %d -- '%Z' already configured\n", DiskNumber, &Settings->HardDisks[DiskNumber]);
+ return STATUS_SUCCESS;
+ }
+
+ /* Check for the type of the value */
+ if (ValueType != REG_SZ)
+ {
+ RtlInitEmptyAnsiString(&Settings->HardDisks[DiskNumber], NULL, 0);
+ return STATUS_SUCCESS;
+ }
+
+ /* Convert the UNICODE string to ANSI and store it */
+ RtlInitEmptyUnicodeString(&ValueString, (PWCHAR)ValueData, ValueLength);
+ ValueString.Length = ValueString.MaximumLength;
+ RtlUnicodeStringToAnsiString(&Settings->HardDisks[DiskNumber], &ValueString, TRUE);
+
+ return STATUS_SUCCESS;
+}
+
+static RTL_QUERY_REGISTRY_TABLE
+NtVdmConfigurationTable[] =
+{
+ {
+ NtVdmConfigureBios,
+ 0,
+ L"BiosFile",
+ NULL,
+ REG_NONE,
+ NULL,
+ 0
+ },
+
+ {
+ NtVdmConfigureRom,
+ RTL_QUERY_REGISTRY_NOEXPAND,
+ L"RomFiles",
+ NULL,
+ REG_NONE,
+ NULL,
+ 0
+ },
+
+ {
+ NtVdmConfigureFloppy,
+ 0,
+ L"FloppyDisk0",
+ (PVOID)0,
+ REG_NONE,
+ NULL,
+ 0
+ },
+
+ {
+ NtVdmConfigureFloppy,
+ 0,
+ L"FloppyDisk1",
+ (PVOID)1,
+ REG_NONE,
+ NULL,
+ 0
+ },
+
+ {
+ NtVdmConfigureHDD,
+ 0,
+ L"HardDisk0",
+ (PVOID)0,
+ REG_NONE,
+ NULL,
+ 0
+ },
+
+ {
+ NtVdmConfigureHDD,
+ 0,
+ L"HardDisk1",
+ (PVOID)1,
+ REG_NONE,
+ NULL,
+ 0
+ },
+
+ {
+ NtVdmConfigureHDD,
+ 0,
+ L"HardDisk2",
+ (PVOID)2,
+ REG_NONE,
+ NULL,
+ 0
+ },
+
+ {
+ NtVdmConfigureHDD,
+ 0,
+ L"HardDisk3",
+ (PVOID)3,
+ REG_NONE,
+ NULL,
+ 0
+ },
+
+ /* End of table */
+ {0}
+};
+
+static BOOL
+LoadGlobalSettings(IN PNTVDM_SETTINGS Settings)
+{
+ NTSTATUS Status;
+
+ ASSERT(Settings);
+
+ /*
+ * Now we can do:
+ * - CPU core choice
+ * - Video choice
+ * - Sound choice
+ * - Mem?
+ * - ...
+ * - Standalone mode?
+ * - Debug settings
+ */
+ Status = RtlQueryRegistryValues(RTL_REGISTRY_CONTROL,
+ L"NTVDM",
+ NtVdmConfigurationTable,
+ Settings,
+ NULL);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("NTVDM registry settings cannot be fully initialized, using default ones. Status = 0x%08lx\n", Status);
+ }
+
+ return NT_SUCCESS(Status);
+}
+
+static VOID
+FreeGlobalSettings(IN PNTVDM_SETTINGS Settings)
+{
+ USHORT i;
+
+ ASSERT(Settings);
+
+ if (Settings->BiosFileName.Buffer)
+ RtlFreeAnsiString(&Settings->BiosFileName);
+
+ if (Settings->RomFiles.Buffer)
+ RtlFreeAnsiString(&Settings->RomFiles);
+
+ for (i = 0; i < ARRAYSIZE(Settings->FloppyDisks); ++i)
+ {
+ if (Settings->FloppyDisks[i].Buffer)
+ RtlFreeAnsiString(&Settings->FloppyDisks[i]);
+ }
+
+ for (i = 0; i < ARRAYSIZE(Settings->HardDisks); ++i)
+ {
+ if (Settings->HardDisks[i].Buffer)
+ RtlFreeAnsiString(&Settings->HardDisks[i]);
+ }
+}
+
/* PUBLIC FUNCTIONS ***********************************************************/
VOID
-DisplayMessage(LPCWSTR Format, ...)
+DisplayMessage(IN LPCWSTR Format, ...)
{
#ifndef WIN2K_COMPLIANT
WCHAR StaticBuffer[256];
/*
* Retrieve the message length and if it is too long, allocate
* an auxiliary buffer; otherwise use the static buffer.
+ * The string is built to be NULL-terminated.
*/
- MsgLen = _vscwprintf(Format, Parameters) + 1; // NULL-terminated
- if (MsgLen > ARRAYSIZE(StaticBuffer))
+ MsgLen = _vscwprintf(Format, Parameters);
+ if (MsgLen >= ARRAYSIZE(StaticBuffer))
{
- Buffer = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, MsgLen * sizeof(WCHAR));
+ Buffer = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, (MsgLen + 1) * sizeof(WCHAR));
if (Buffer == NULL)
{
/* Allocation failed, use the static buffer and display a suitable error message */
}
}
#else
- MsgLen = ARRAYSIZE(Buffer);
+ MsgLen = ARRAYSIZE(Buffer) - 1;
#endif
- /* Display the message */
+ RtlZeroMemory(Buffer, (MsgLen + 1) * sizeof(WCHAR));
_vsnwprintf(Buffer, MsgLen, Format, Parameters);
+
+ va_end(Parameters);
+
+ /* Display the message */
DPRINT1("\n\nNTVDM Subsystem\n%S\n\n", Buffer);
- MessageBoxW(NULL, Buffer, L"NTVDM Subsystem", MB_OK);
+ MessageBoxW(hConsoleWnd, Buffer, L"NTVDM Subsystem", MB_OK);
#ifndef WIN2K_COMPLIANT
/* Free the buffer if needed */
if (Buffer != StaticBuffer) RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer);
#endif
+}
- va_end(Parameters);
+static VOID
+ConsoleCleanup(VOID);
+
+static VOID
+VdmShutdown(BOOLEAN Immediate)
+{
+ /*
+ * Immediate = TRUE: Immediate shutdown;
+ * FALSE: Delayed shutdown.
+ */
+ static BOOLEAN MustShutdown = FALSE;
+
+ /* If a shutdown is ongoing, just return */
+ if (MustShutdown)
+ {
+ DPRINT1("Shutdown is ongoing...\n");
+ Sleep(INFINITE);
+ return;
+ }
+
+ /* First notify DOS to see whether we can shut down now */
+ MustShutdown = DosShutdown(Immediate);
+ /*
+ * In case we perform an immediate shutdown, or the DOS says
+ * we can shut down, do it now.
+ */
+ MustShutdown = MustShutdown || Immediate;
+
+ if (MustShutdown)
+ {
+ EmulatorTerminate();
+
+ BiosCleanup();
+ EmulatorCleanup();
+ ConsoleCleanup();
+
+ FreeGlobalSettings(&GlobalSettings);
+
+ DPRINT1("\n\n\nNTVDM - Exiting...\n\n\n");
+ /* Some VDDs rely on the fact that NTVDM calls ExitProcess on Windows */
+ ExitProcess(0);
+ }
}
static BOOL
WINAPI
ConsoleCtrlHandler(DWORD ControlType)
{
-// HACK: Should be removed!
-#ifndef STANDALONE
-extern BOOLEAN AcceptCommands;
-extern HANDLE CommandThread;
-#endif
-
switch (ControlType)
{
case CTRL_LAST_CLOSE_EVENT:
{
- if (WaitForSingleObject(VdmTaskEvent, 0) == WAIT_TIMEOUT)
- {
- /* Nothing runs, so exit immediately */
-#ifndef STANDALONE
- if (CommandThread) TerminateThread(CommandThread, 0);
-#endif
- EmulatorTerminate();
- }
-#ifndef STANDALONE
- else
- {
- /* A command is running, let it run, but stop accepting new commands */
- AcceptCommands = FALSE;
- }
-#endif
-
+ /* Delayed shutdown */
+ DPRINT1("NTVDM delayed killing in the CTRL_LAST_CLOSE_EVENT CtrlHandler!\n");
+ VdmShutdown(FALSE);
break;
}
default:
{
/* Stop the VDM if the user logs out or closes the console */
- EmulatorTerminate();
+ DPRINT1("Killing NTVDM in the 'default' CtrlHandler!\n");
+ VdmShutdown(TRUE);
}
}
return TRUE;
static VOID
ConsoleInitUI(VOID)
{
+ hConsoleWnd = GetConsoleWindow();
CreateVdmMenu(ConsoleOutput);
}
CloseHandle(ConsoleOutput);
CloseHandle(ConsoleInput);
wprintf(L"FATAL: Cannot save console in/out modes\n");
- // return FALSE;
+ return FALSE;
}
/* Set the console input mode */
VOID
ConsoleDetach(VOID)
{
+ /* Cleanup the UI */
+ ConsoleCleanupUI();
+
/* Restore the original input and output console modes */
SetConsoleMode(ConsoleOutput, OrgConsoleOutputMode);
SetConsoleMode(ConsoleInput , OrgConsoleInputMode );
-
- /* Cleanup the UI */
- ConsoleCleanupUI();
}
static BOOL
DumpMemory(FALSE);
break;
+ /* Drive 0 -- Mount */
+ /* Drive 1 -- Mount */
+ case ID_VDM_DRIVES + 0:
+ case ID_VDM_DRIVES + 2:
+ {
+ ULONG DiskNumber = (MenuEvent->dwCommandId - ID_VDM_DRIVES) / 2;
+ MountFloppy(DiskNumber);
+ break;
+ }
+
+ /* Drive 0 -- Eject */
+ /* Drive 1 -- Eject */
+ case ID_VDM_DRIVES + 1:
+ case ID_VDM_DRIVES + 3:
+ {
+ ULONG DiskNumber = (MenuEvent->dwCommandId - ID_VDM_DRIVES - 1) / 2;
+ EjectFloppy(DiskNumber);
+ break;
+ }
+
case ID_VDM_QUIT:
/* Stop the VDM */
- EmulatorTerminate();
+ // EmulatorTerminate();
+
+ /* Nothing runs, so exit immediately */
+ DPRINT1("Killing NTVDM via console menu!\n");
+ VdmShutdown(TRUE);
break;
default:
DPRINT1("Focus events not handled\n");
}
-static BOOL
-LoadGlobalSettings(VOID)
-{
-// FIXME: These strings should be localized.
-#define ERROR_MEMORYVDD L"Insufficient memory to load installable Virtual Device Drivers."
-#define ERROR_REGVDD L"Virtual Device Driver format in the registry is invalid."
-#define ERROR_LOADVDD L"An installable Virtual Device Driver failed Dll initialization."
-
- BOOL Success = TRUE;
- LONG Error = 0;
-
- HKEY hNTVDMKey;
- LPCWSTR NTVDMKeyName = L"SYSTEM\\CurrentControlSet\\Control\\NTVDM";
-
- /* Try to open the NTVDM registry key */
- Error = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
- NTVDMKeyName,
- 0,
- KEY_QUERY_VALUE,
- &hNTVDMKey);
- if (Error == ERROR_FILE_NOT_FOUND)
- {
- /* If the key just doesn't exist, don't do anything else */
- return TRUE;
- }
- else if (Error != ERROR_SUCCESS)
- {
- /* The key exists but there was an access error: display an error and quit */
- DisplayMessage(ERROR_REGVDD);
- return FALSE;
- }
-
- /*
- * Now we can do:
- * - CPU core choice
- * - Video choice
- * - Sound choice
- * - Mem?
- * - ...
- * - Standalone mode?
- * - Debug settings
- */
-
-// Quit:
- RegCloseKey(hNTVDMKey);
- return Success;
-}
INT
wmain(INT argc, WCHAR *argv[])
#endif
+#ifdef ADVANCED_DEBUGGING
+ {
+ INT i = 20;
+
+ printf("Waiting for debugger (10 secs)..");
+ while (i--)
+ {
+ printf(".");
+ if (IsDebuggerPresent())
+ {
+ DbgBreakPoint();
+ break;
+ }
+ Sleep(500);
+ }
+ printf("Continue\n");
+ }
+#endif
+
/* Load global VDM settings */
- LoadGlobalSettings();
+ LoadGlobalSettings(&GlobalSettings);
DPRINT1("\n\n\nNTVDM - Starting...\n\n\n");
- /* Create the task event */
- VdmTaskEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
- ASSERT(VdmTaskEvent != NULL);
-
/* Initialize the console */
if (!ConsoleInit())
{
goto Cleanup;
}
- /* Initialize the system BIOS */
- if (!BiosInitialize(NULL))
+ /* Initialize the system BIOS and option ROMs */
+ if (!BiosInitialize(GlobalSettings.BiosFileName.Buffer,
+ GlobalSettings.RomFiles.Buffer))
{
wprintf(L"FATAL: Failed to initialize the VDM BIOS.\n");
goto Cleanup;
/* Let's go! Start simulation */
CpuSimulate();
-Cleanup:
- BiosCleanup();
- EmulatorCleanup();
- ConsoleCleanup();
-
-#ifndef STANDALONE
- ExitVDM(FALSE, 0);
-#endif
-
/* Quit the VDM */
- DPRINT1("\n\n\nNTVDM - Exiting...\n\n\n");
- /* Some VDDs rely on the fact that NTVDM calls ExitProcess on Windows */
- ExitProcess(0);
+Cleanup:
+ VdmShutdown(TRUE);
return 0;
}