2013-03-14 21:04:13 +00:00
|
|
|
/*
|
2013-06-17 00:00:36 +00:00
|
|
|
* COPYRIGHT: GPL - See COPYING in the top level directory
|
|
|
|
* PROJECT: ReactOS Virtual DOS Machine
|
2015-09-18 17:01:49 +00:00
|
|
|
* FILE: subsystems/mvdm/ntvdm/ntvdm.c
|
2002-10-28 13:59:59 +00:00
|
|
|
* PURPOSE: Virtual DOS Machine
|
2013-06-17 00:00:36 +00:00
|
|
|
* PROGRAMMERS: Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
|
2002-10-28 13:59:59 +00:00
|
|
|
*/
|
|
|
|
|
2015-10-04 11:49:28 +00:00
|
|
|
/* INCLUDES *******************************************************************/
|
|
|
|
|
2015-10-03 19:17:55 +00:00
|
|
|
#include "ntvdm.h"
|
|
|
|
|
2013-07-22 13:51:26 +00:00
|
|
|
#define NDEBUG
|
2015-10-03 19:17:55 +00:00
|
|
|
#include <debug.h>
|
2013-07-22 13:51:26 +00:00
|
|
|
|
2015-10-04 11:49:28 +00:00
|
|
|
#include "emulator.h"
|
|
|
|
|
|
|
|
#include "bios/bios.h"
|
|
|
|
#include "cpu/cpu.h"
|
|
|
|
|
|
|
|
#include "dos/dem.h"
|
|
|
|
|
2021-11-27 00:06:21 +00:00
|
|
|
/* Extra PSDK/NDK Headers */
|
|
|
|
#include <ndk/psfuncs.h>
|
|
|
|
|
2014-02-01 16:32:20 +00:00
|
|
|
/* VARIABLES ******************************************************************/
|
2013-01-24 23:00:42 +00:00
|
|
|
|
2015-09-28 01:36:31 +00:00
|
|
|
NTVDM_SETTINGS GlobalSettings;
|
|
|
|
|
2014-10-04 13:36:17 +00:00
|
|
|
// Command line of NTVDM
|
|
|
|
INT NtVdmArgc;
|
|
|
|
WCHAR** NtVdmArgv;
|
|
|
|
|
2021-11-27 20:03:55 +00:00
|
|
|
/* Full directory where NTVDM resides, or the SystemRoot\System32 path */
|
|
|
|
WCHAR NtVdmPath[MAX_PATH];
|
|
|
|
ULONG NtVdmPathSize; // Length without NULL terminator.
|
|
|
|
|
2015-11-07 20:07:12 +00:00
|
|
|
/* PRIVATE FUNCTIONS **********************************************************/
|
2015-09-28 01:36:31 +00:00
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2015-09-28 22:15:06 +00:00
|
|
|
static NTSTATUS
|
|
|
|
NTAPI
|
|
|
|
NtVdmConfigureFloppy(IN PWSTR ValueName,
|
|
|
|
IN ULONG ValueType,
|
|
|
|
IN PVOID ValueData,
|
|
|
|
IN ULONG ValueLength,
|
|
|
|
IN PVOID Context,
|
|
|
|
IN PVOID EntryContext)
|
|
|
|
{
|
2015-11-07 20:19:32 +00:00
|
|
|
BOOLEAN Success;
|
2015-09-28 22:15:06 +00:00
|
|
|
PNTVDM_SETTINGS Settings = (PNTVDM_SETTINGS)Context;
|
2018-02-11 23:38:10 +00:00
|
|
|
ULONG DiskNumber = PtrToUlong(EntryContext);
|
2015-09-28 22:15:06 +00:00
|
|
|
|
|
|
|
ASSERT(DiskNumber < ARRAYSIZE(Settings->FloppyDisks));
|
|
|
|
|
|
|
|
/* Check whether the Hard Disk entry was not already configured */
|
|
|
|
if (Settings->FloppyDisks[DiskNumber].Buffer != NULL)
|
|
|
|
{
|
2015-11-07 20:19:32 +00:00
|
|
|
DPRINT1("Floppy Disk %d -- '%wZ' already configured\n", DiskNumber, &Settings->FloppyDisks[DiskNumber]);
|
2015-09-28 22:15:06 +00:00
|
|
|
return STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Check for the type of the value */
|
|
|
|
if (ValueType != REG_SZ)
|
|
|
|
{
|
2015-11-07 20:19:32 +00:00
|
|
|
RtlInitEmptyUnicodeString(&Settings->FloppyDisks[DiskNumber], NULL, 0);
|
2015-09-28 22:15:06 +00:00
|
|
|
return STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2015-11-07 20:19:32 +00:00
|
|
|
/* Initialize the string */
|
|
|
|
Success = RtlCreateUnicodeString(&Settings->FloppyDisks[DiskNumber], (PCWSTR)ValueData);
|
|
|
|
ASSERT(Success);
|
2015-09-28 22:15:06 +00:00
|
|
|
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2015-09-28 01:36:31 +00:00
|
|
|
static NTSTATUS
|
|
|
|
NTAPI
|
|
|
|
NtVdmConfigureHDD(IN PWSTR ValueName,
|
|
|
|
IN ULONG ValueType,
|
|
|
|
IN PVOID ValueData,
|
|
|
|
IN ULONG ValueLength,
|
|
|
|
IN PVOID Context,
|
|
|
|
IN PVOID EntryContext)
|
|
|
|
{
|
2015-11-07 20:19:32 +00:00
|
|
|
BOOLEAN Success;
|
2015-09-28 01:36:31 +00:00
|
|
|
PNTVDM_SETTINGS Settings = (PNTVDM_SETTINGS)Context;
|
2018-02-11 23:38:10 +00:00
|
|
|
ULONG DiskNumber = PtrToUlong(EntryContext);
|
2015-09-28 01:36:31 +00:00
|
|
|
|
|
|
|
ASSERT(DiskNumber < ARRAYSIZE(Settings->HardDisks));
|
|
|
|
|
|
|
|
/* Check whether the Hard Disk entry was not already configured */
|
|
|
|
if (Settings->HardDisks[DiskNumber].Buffer != NULL)
|
|
|
|
{
|
2015-11-07 20:19:32 +00:00
|
|
|
DPRINT1("Hard Disk %d -- '%wZ' already configured\n", DiskNumber, &Settings->HardDisks[DiskNumber]);
|
2015-09-28 01:36:31 +00:00
|
|
|
return STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Check for the type of the value */
|
|
|
|
if (ValueType != REG_SZ)
|
|
|
|
{
|
2015-11-07 20:19:32 +00:00
|
|
|
RtlInitEmptyUnicodeString(&Settings->HardDisks[DiskNumber], NULL, 0);
|
2015-09-28 01:36:31 +00:00
|
|
|
return STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2015-11-07 20:19:32 +00:00
|
|
|
/* Initialize the string */
|
|
|
|
Success = RtlCreateUnicodeString(&Settings->HardDisks[DiskNumber], (PCWSTR)ValueData);
|
|
|
|
ASSERT(Success);
|
2015-09-28 01:36:31 +00:00
|
|
|
|
|
|
|
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
|
|
|
|
},
|
|
|
|
|
2015-09-28 22:15:06 +00:00
|
|
|
{
|
|
|
|
NtVdmConfigureFloppy,
|
|
|
|
0,
|
|
|
|
L"FloppyDisk0",
|
|
|
|
(PVOID)0,
|
|
|
|
REG_NONE,
|
|
|
|
NULL,
|
|
|
|
0
|
|
|
|
},
|
|
|
|
|
|
|
|
{
|
|
|
|
NtVdmConfigureFloppy,
|
|
|
|
0,
|
|
|
|
L"FloppyDisk1",
|
|
|
|
(PVOID)1,
|
|
|
|
REG_NONE,
|
|
|
|
NULL,
|
|
|
|
0
|
|
|
|
},
|
|
|
|
|
2015-09-28 01:36:31 +00:00
|
|
|
{
|
|
|
|
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);
|
|
|
|
|
2015-09-28 22:15:06 +00:00
|
|
|
for (i = 0; i < ARRAYSIZE(Settings->FloppyDisks); ++i)
|
|
|
|
{
|
|
|
|
if (Settings->FloppyDisks[i].Buffer)
|
2015-11-07 20:19:32 +00:00
|
|
|
RtlFreeUnicodeString(&Settings->FloppyDisks[i]);
|
2015-09-28 22:15:06 +00:00
|
|
|
}
|
|
|
|
|
2015-09-28 01:36:31 +00:00
|
|
|
for (i = 0; i < ARRAYSIZE(Settings->HardDisks); ++i)
|
|
|
|
{
|
|
|
|
if (Settings->HardDisks[i].Buffer)
|
2015-11-07 20:19:32 +00:00
|
|
|
RtlFreeUnicodeString(&Settings->HardDisks[i]);
|
2015-09-28 01:36:31 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-11-07 20:07:12 +00:00
|
|
|
static VOID
|
|
|
|
ConsoleCleanup(VOID);
|
|
|
|
|
|
|
|
/** HACK!! **/
|
|
|
|
#include "./console/console.c"
|
|
|
|
/** HACK!! **/
|
|
|
|
|
|
|
|
/*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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-06-26 22:58:41 +00:00
|
|
|
/* PUBLIC FUNCTIONS ***********************************************************/
|
|
|
|
|
2014-05-11 19:25:09 +00:00
|
|
|
VOID
|
2015-07-13 01:21:46 +00:00
|
|
|
DisplayMessage(IN LPCWSTR Format, ...)
|
2003-01-12 01:54:40 +00:00
|
|
|
{
|
2014-11-09 01:46:31 +00:00
|
|
|
#ifndef WIN2K_COMPLIANT
|
|
|
|
WCHAR StaticBuffer[256];
|
|
|
|
LPWSTR Buffer = StaticBuffer; // Use the static buffer by default.
|
|
|
|
#else
|
|
|
|
WCHAR Buffer[2048]; // Large enough. If not, increase it by hand.
|
|
|
|
#endif
|
|
|
|
size_t MsgLen;
|
2015-10-01 00:09:24 +00:00
|
|
|
va_list args;
|
2003-01-12 01:54:40 +00:00
|
|
|
|
2015-10-01 00:09:24 +00:00
|
|
|
va_start(args, Format);
|
2014-11-09 01:46:31 +00:00
|
|
|
|
|
|
|
#ifndef WIN2K_COMPLIANT
|
|
|
|
/*
|
|
|
|
* Retrieve the message length and if it is too long, allocate
|
|
|
|
* an auxiliary buffer; otherwise use the static buffer.
|
2015-07-13 01:21:46 +00:00
|
|
|
* The string is built to be NULL-terminated.
|
2014-11-09 01:46:31 +00:00
|
|
|
*/
|
2015-10-01 00:09:24 +00:00
|
|
|
MsgLen = _vscwprintf(Format, args);
|
2015-07-13 01:21:46 +00:00
|
|
|
if (MsgLen >= ARRAYSIZE(StaticBuffer))
|
2014-11-09 01:46:31 +00:00
|
|
|
{
|
2015-07-13 01:21:46 +00:00
|
|
|
Buffer = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, (MsgLen + 1) * sizeof(WCHAR));
|
2014-11-09 01:46:31 +00:00
|
|
|
if (Buffer == NULL)
|
|
|
|
{
|
|
|
|
/* Allocation failed, use the static buffer and display a suitable error message */
|
|
|
|
Buffer = StaticBuffer;
|
|
|
|
Format = L"DisplayMessage()\nOriginal message is too long and allocating an auxiliary buffer failed.";
|
|
|
|
MsgLen = wcslen(Format);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#else
|
2015-07-13 01:21:46 +00:00
|
|
|
MsgLen = ARRAYSIZE(Buffer) - 1;
|
2014-11-09 01:46:31 +00:00
|
|
|
#endif
|
|
|
|
|
2015-07-13 01:21:46 +00:00
|
|
|
RtlZeroMemory(Buffer, (MsgLen + 1) * sizeof(WCHAR));
|
2015-10-01 00:09:24 +00:00
|
|
|
_vsnwprintf(Buffer, MsgLen, Format, args);
|
2015-07-13 01:21:46 +00:00
|
|
|
|
2015-10-01 00:09:24 +00:00
|
|
|
va_end(args);
|
2015-07-13 01:21:46 +00:00
|
|
|
|
|
|
|
/* Display the message */
|
2013-11-09 15:53:52 +00:00
|
|
|
DPRINT1("\n\nNTVDM Subsystem\n%S\n\n", Buffer);
|
2015-09-27 15:24:26 +00:00
|
|
|
MessageBoxW(hConsoleWnd, Buffer, L"NTVDM Subsystem", MB_OK);
|
2014-11-09 01:46:31 +00:00
|
|
|
|
|
|
|
#ifndef WIN2K_COMPLIANT
|
|
|
|
/* Free the buffer if needed */
|
2015-04-19 00:01:03 +00:00
|
|
|
if (Buffer != StaticBuffer) RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer);
|
2014-11-09 01:46:31 +00:00
|
|
|
#endif
|
2003-01-12 01:54:40 +00:00
|
|
|
}
|
|
|
|
|
2015-10-01 00:09:24 +00:00
|
|
|
/*
|
|
|
|
* This function, derived from DisplayMessage, is used by the BIOS and
|
|
|
|
* the DOS to display messages to an output device. A printer function
|
|
|
|
* is given for printing the characters.
|
|
|
|
*/
|
|
|
|
VOID
|
|
|
|
PrintMessageAnsi(IN CHAR_PRINT CharPrint,
|
|
|
|
IN LPCSTR Format, ...)
|
|
|
|
{
|
|
|
|
static CHAR CurChar = 0;
|
|
|
|
LPSTR str;
|
|
|
|
|
|
|
|
#ifndef WIN2K_COMPLIANT
|
|
|
|
CHAR StaticBuffer[256];
|
|
|
|
LPSTR Buffer = StaticBuffer; // Use the static buffer by default.
|
|
|
|
#else
|
|
|
|
CHAR Buffer[2048]; // Large enough. If not, increase it by hand.
|
|
|
|
#endif
|
|
|
|
size_t MsgLen;
|
|
|
|
va_list args;
|
|
|
|
|
|
|
|
va_start(args, Format);
|
|
|
|
|
|
|
|
#ifndef WIN2K_COMPLIANT
|
|
|
|
/*
|
|
|
|
* 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 = _vscprintf(Format, args);
|
|
|
|
if (MsgLen >= ARRAYSIZE(StaticBuffer))
|
|
|
|
{
|
|
|
|
Buffer = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, (MsgLen + 1) * sizeof(CHAR));
|
|
|
|
if (Buffer == NULL)
|
|
|
|
{
|
|
|
|
/* Allocation failed, use the static buffer and display a suitable error message */
|
|
|
|
Buffer = StaticBuffer;
|
|
|
|
Format = "DisplayMessageAnsi()\nOriginal message is too long and allocating an auxiliary buffer failed.";
|
|
|
|
MsgLen = strlen(Format);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
MsgLen = ARRAYSIZE(Buffer) - 1;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
RtlZeroMemory(Buffer, (MsgLen + 1) * sizeof(CHAR));
|
|
|
|
_vsnprintf(Buffer, MsgLen, Format, args);
|
|
|
|
|
|
|
|
va_end(args);
|
|
|
|
|
|
|
|
/* Display the message */
|
|
|
|
// DPRINT1("\n\nNTVDM DOS32\n%s\n\n", Buffer);
|
|
|
|
|
|
|
|
MsgLen = strlen(Buffer);
|
|
|
|
str = Buffer;
|
|
|
|
while (MsgLen--)
|
|
|
|
{
|
|
|
|
if (*str == '\n' && CurChar != '\r')
|
|
|
|
CharPrint('\r');
|
|
|
|
|
|
|
|
CurChar = *str++;
|
|
|
|
CharPrint(CurChar);
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifndef WIN2K_COMPLIANT
|
|
|
|
/* Free the buffer if needed */
|
|
|
|
if (Buffer != StaticBuffer) RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2014-05-11 19:25:09 +00:00
|
|
|
INT
|
|
|
|
wmain(INT argc, WCHAR *argv[])
|
2014-04-22 20:46:50 +00:00
|
|
|
{
|
2021-11-27 20:03:55 +00:00
|
|
|
BOOL Success;
|
|
|
|
|
2014-04-22 20:46:50 +00:00
|
|
|
#ifdef STANDALONE
|
2014-04-27 22:38:54 +00:00
|
|
|
|
2014-10-04 13:36:17 +00:00
|
|
|
if (argc < 2)
|
2013-07-18 00:17:04 +00:00
|
|
|
{
|
|
|
|
wprintf(L"\nReactOS Virtual DOS Machine\n\n"
|
2014-04-26 08:57:17 +00:00
|
|
|
L"Usage: NTVDM <executable> [<parameters>]\n");
|
2013-07-18 00:17:04 +00:00
|
|
|
return 0;
|
|
|
|
}
|
2005-05-08 04:07:56 +00:00
|
|
|
|
2021-11-27 00:06:21 +00:00
|
|
|
#else
|
|
|
|
|
|
|
|
/* For non-STANDALONE builds, we must be started as a VDM */
|
|
|
|
NTSTATUS Status;
|
|
|
|
ULONG VdmPower = 0;
|
|
|
|
Status = NtQueryInformationProcess(NtCurrentProcess(),
|
|
|
|
ProcessWx86Information,
|
|
|
|
&VdmPower,
|
|
|
|
sizeof(VdmPower),
|
|
|
|
NULL);
|
|
|
|
if (!NT_SUCCESS(Status) || (VdmPower == 0))
|
|
|
|
{
|
|
|
|
/* Not a VDM, bail out */
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2014-04-08 00:28:49 +00:00
|
|
|
#endif
|
|
|
|
|
2021-11-27 00:06:21 +00:00
|
|
|
NtVdmArgc = argc;
|
|
|
|
NtVdmArgv = argv;
|
|
|
|
|
[NTVDM]
- Add some level of "Advanced debugging" (see ntvdm.h) which one can adjust to enable/disable debugging features inside NTVDM (this can be useful as long as NTVDM is under heavy bugfixing. When it will be more perfect, this stuff will be removed).
- Add the possibility to load option ROMs at a given segment. Currently their list should be specified from inside ntvdm.c (in the BiosInitialize call), but I plan to make it available from a registry option (or via command-line for NTVDM-standalone mode).
- Start to separate the initialization of "static" BIOS data (stuff that lives in ROM space) and initialization of "dynamic" BIOS data (eg. initializing the interrupt vector table, the BIOS data area at segment 40h, ...) so that we may be able to reuse part of our code to be able to more-or-less run external (16-bit) BIOSes, or the Windows NTVDM BIOS that uses BOPs to run some of its stuff in ntvdm in 32-bit (as we do for our 32-bit BIOS, except that *all* of our bios is 32-bit, not just some parts). Also, some file reorganization will be in order there soon...
- Add video BIOS version information in memory so that tools such as Microsoft Diagnostics can correctly recognize our video BIOS (btw, we try to emulate the functionality of Cirrus' CL-GD5434).
- Correctly put video BIOS ROM header (+ checksum) in memory so that it is recognized as such by diagnostics tools.
- During BIOS POST, scan for ROMs starting segment 0xC000 (where video ROMs reside).
- Store statically the BIOS configuration table.
- Fix INT 16h, AH=12h "Get extended shift states" so that it correctly returns the state of right Ctrl and Alt keys.
- Fix bit-setting state; report that our keyboard is 101/102 enhanced keyboard.
- Correctly set the error return values (AH=86h and CF set) when a function of INT 15h is unsupported.
- Implement INT 15h, AH=C9h "Get CPU Type and Mask Revision"; INT 1Ah, AH=02h "Get Real-Time Clock Time" and Ah=04h "Get Real-Time Clock Date" by reading the CMOS.
- Implement CMOS century register support.
svn path=/trunk/; revision=68598
2015-08-04 20:17:05 +00:00
|
|
|
#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
|
|
|
|
|
2021-11-22 02:08:30 +00:00
|
|
|
DPRINT1("\n\n\n"
|
|
|
|
"NTVDM - Starting...\n"
|
|
|
|
"Command Line: '%s'\n"
|
|
|
|
"\n\n",
|
|
|
|
GetCommandLineA());
|
|
|
|
|
2021-11-27 20:03:55 +00:00
|
|
|
/*
|
|
|
|
* Retrieve the full directory of the current running NTVDM instance.
|
|
|
|
* In case of failure, use the default SystemRoot\System32 path.
|
|
|
|
*/
|
|
|
|
NtVdmPathSize = GetModuleFileNameW(NULL, NtVdmPath, _countof(NtVdmPath));
|
|
|
|
NtVdmPath[_countof(NtVdmPath) - 1] = UNICODE_NULL; // Ensure NULL-termination (see WinXP bug)
|
|
|
|
|
|
|
|
Success = ((NtVdmPathSize != 0) && (NtVdmPathSize < _countof(NtVdmPath)) &&
|
|
|
|
(GetLastError() != ERROR_INSUFFICIENT_BUFFER));
|
|
|
|
if (Success)
|
|
|
|
{
|
|
|
|
/* Find the last path separator, remove it as well as the file name */
|
|
|
|
PWCHAR pch = wcsrchr(NtVdmPath, L'\\');
|
|
|
|
if (pch)
|
|
|
|
*pch = UNICODE_NULL;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* We failed, use the default SystemRoot\System32 path */
|
|
|
|
NtVdmPathSize = GetSystemDirectoryW(NtVdmPath, _countof(NtVdmPath));
|
|
|
|
Success = ((NtVdmPathSize != 0) && (NtVdmPathSize < _countof(NtVdmPath)));
|
|
|
|
if (!Success)
|
|
|
|
{
|
|
|
|
/* We failed again, try to do it ourselves */
|
|
|
|
NtVdmPathSize = (ULONG)wcslen(SharedUserData->NtSystemRoot) + _countof("\\System32") - 1;
|
|
|
|
Success = (NtVdmPathSize < _countof(NtVdmPath));
|
|
|
|
if (Success)
|
|
|
|
{
|
|
|
|
Success = NT_SUCCESS(RtlStringCchPrintfW(NtVdmPath,
|
|
|
|
_countof(NtVdmPath),
|
|
|
|
L"%s\\System32",
|
|
|
|
SharedUserData->NtSystemRoot));
|
|
|
|
}
|
|
|
|
if (!Success)
|
|
|
|
{
|
|
|
|
wprintf(L"FATAL: Could not retrieve NTVDM path.\n");
|
|
|
|
goto Cleanup;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
NtVdmPathSize = (ULONG)wcslen(NtVdmPath);
|
|
|
|
|
2015-10-01 00:09:24 +00:00
|
|
|
/* Load the global VDM settings */
|
2015-09-28 01:36:31 +00:00
|
|
|
LoadGlobalSettings(&GlobalSettings);
|
2014-10-04 13:36:17 +00:00
|
|
|
|
2014-01-11 20:59:27 +00:00
|
|
|
/* Initialize the console */
|
|
|
|
if (!ConsoleInit())
|
|
|
|
{
|
2021-11-27 20:03:55 +00:00
|
|
|
wprintf(L"FATAL: A problem occurred when trying to initialize the console.\n");
|
2014-01-11 20:59:27 +00:00
|
|
|
goto Cleanup;
|
|
|
|
}
|
|
|
|
|
2013-11-26 20:20:51 +00:00
|
|
|
/* Initialize the emulator */
|
2014-01-25 00:21:51 +00:00
|
|
|
if (!EmulatorInitialize(ConsoleInput, ConsoleOutput))
|
2013-07-02 21:40:11 +00:00
|
|
|
{
|
2021-11-27 20:03:55 +00:00
|
|
|
wprintf(L"FATAL: Failed to initialize the emulator.\n");
|
2013-07-05 00:08:18 +00:00
|
|
|
goto Cleanup;
|
2013-07-02 21:40:11 +00:00
|
|
|
}
|
2013-11-17 20:44:23 +00:00
|
|
|
|
[NTVDM]
- Add some level of "Advanced debugging" (see ntvdm.h) which one can adjust to enable/disable debugging features inside NTVDM (this can be useful as long as NTVDM is under heavy bugfixing. When it will be more perfect, this stuff will be removed).
- Add the possibility to load option ROMs at a given segment. Currently their list should be specified from inside ntvdm.c (in the BiosInitialize call), but I plan to make it available from a registry option (or via command-line for NTVDM-standalone mode).
- Start to separate the initialization of "static" BIOS data (stuff that lives in ROM space) and initialization of "dynamic" BIOS data (eg. initializing the interrupt vector table, the BIOS data area at segment 40h, ...) so that we may be able to reuse part of our code to be able to more-or-less run external (16-bit) BIOSes, or the Windows NTVDM BIOS that uses BOPs to run some of its stuff in ntvdm in 32-bit (as we do for our 32-bit BIOS, except that *all* of our bios is 32-bit, not just some parts). Also, some file reorganization will be in order there soon...
- Add video BIOS version information in memory so that tools such as Microsoft Diagnostics can correctly recognize our video BIOS (btw, we try to emulate the functionality of Cirrus' CL-GD5434).
- Correctly put video BIOS ROM header (+ checksum) in memory so that it is recognized as such by diagnostics tools.
- During BIOS POST, scan for ROMs starting segment 0xC000 (where video ROMs reside).
- Store statically the BIOS configuration table.
- Fix INT 16h, AH=12h "Get extended shift states" so that it correctly returns the state of right Ctrl and Alt keys.
- Fix bit-setting state; report that our keyboard is 101/102 enhanced keyboard.
- Correctly set the error return values (AH=86h and CF set) when a function of INT 15h is unsupported.
- Implement INT 15h, AH=C9h "Get CPU Type and Mask Revision"; INT 1Ah, AH=02h "Get Real-Time Clock Time" and Ah=04h "Get Real-Time Clock Date" by reading the CMOS.
- Implement CMOS century register support.
svn path=/trunk/; revision=68598
2015-08-04 20:17:05 +00:00
|
|
|
/* Initialize the system BIOS and option ROMs */
|
2015-09-28 01:36:31 +00:00
|
|
|
if (!BiosInitialize(GlobalSettings.BiosFileName.Buffer,
|
|
|
|
GlobalSettings.RomFiles.Buffer))
|
2013-06-17 00:00:36 +00:00
|
|
|
{
|
|
|
|
wprintf(L"FATAL: Failed to initialize the VDM BIOS.\n");
|
|
|
|
goto Cleanup;
|
2003-01-12 01:54:40 +00:00
|
|
|
}
|
2002-10-28 13:59:59 +00:00
|
|
|
|
2014-10-04 13:36:17 +00:00
|
|
|
/* Let's go! Start simulation */
|
|
|
|
CpuSimulate();
|
2014-04-08 14:57:24 +00:00
|
|
|
|
2014-04-08 00:28:49 +00:00
|
|
|
/* Quit the VDM */
|
[NTVDM]
- Add support for DOS VDM reentry, i.e. the fact that a DOS app can start a 32-bit app, which in turn can start another DOS app, ad infinitum...
CORE-9711 CORE-9773 #resolve
- Add a small COMMAND.COM which is, for now, completely included in NTVDM. This COMMAND.COM is needed in order to support reentrancy. The fact that I chose to put it inside NTVDM is that any user can use instead his/her own COMMAND.COM, while retaining the possibility to perform VDM reentrancy (on Windows, if you remove the COMMAND.COM in windows\system32 and replace it with your own, you will break VDM reentrancy on windows' ntvdm).
CORE-5221 #resolve #comment I choose for the moment an internal COMMAND.COM, but you can recompile NTVDM to use it externally instead.
Global remarks:
- Quite a few DPRINTs were added for diagnostic purposes (since DOS reentrancy is a new feature), to be sure everything behaves as expected when being used with a large panel of applications. They will be removed when everything is OK.
- Support for current directories and 16/32-bit environment translation (in ntvdm + basevdm-side) remain to be implemented.
Other changes:
- Improve a bit the VDM shutdown code by gathering it at one place (there's still room for other improvements).
- Add suppport for properly pausing/resuming NTVDM.
- Bufferize some console events before dispatching.
Have fun ;^)
svn path=/trunk/; revision=69204
2015-09-12 20:09:25 +00:00
|
|
|
Cleanup:
|
|
|
|
VdmShutdown(TRUE);
|
2002-10-28 13:59:59 +00:00
|
|
|
return 0;
|
|
|
|
}
|
2013-06-17 00:00:36 +00:00
|
|
|
|
|
|
|
/* EOF */
|