#include "ntvdm.h"
#include "emulator.h"
-#include "cpu/cpu.h"
#include "bios/bios.h"
+#include "cpu/cpu.h"
#include "resource.h"
static HANDLE ConsoleOutput = INVALID_HANDLE_VALUE;
static DWORD OrgConsoleInputMode, OrgConsoleOutputMode;
-// For DOS
-#ifndef STANDALONE
-BOOLEAN AcceptCommands = TRUE;
-HANDLE CommandThread = NULL;
-ULONG SessionId = 0;
-#endif
-
HANDLE VdmTaskEvent = NULL;
// Command line of NTVDM
if (LoadStringW(GetModuleHandle(NULL),
Items[i].uID,
szMenuString,
- sizeof(szMenuString) / sizeof(szMenuString[0])) > 0)
+ ARRAYSIZE(szMenuString)) > 0)
{
if (Items[i].SubMenu != NULL)
{
} while (!(Items[i].uID == 0 && Items[i].SubMenu == NULL && Items[i].wCmdID == 0));
}
+BOOL
+VdmMenuExists(HMENU hConsoleMenu)
+{
+ INT MenuPos, i;
+ MenuPos = GetMenuItemCount(hConsoleMenu);
+
+ /* Check for the presence of one of the VDM menu items */
+ for (i = 0; i <= MenuPos; i++)
+ {
+ if (GetMenuItemID(hConsoleMenu, i) == ID_SHOWHIDE_MOUSE)
+ return TRUE;
+ }
+ return FALSE;
+}
+
/*static*/ VOID
CreateVdmMenu(HANDLE ConOutHandle)
{
ID_VDM_QUIT);
if (hConsoleMenu == NULL) return;
+ /* Get the position where we are going to insert our menu items */
VdmMenuPos = GetMenuItemCount(hConsoleMenu);
- AppendMenuItems(hConsoleMenu, VdmMainMenuItems);
- DrawMenuBar(GetConsoleWindow());
+ // FIXME: What happens if the menu already exist?
+ // VdmMenuPos points *after* the already existing menu!
+
+ /* Really add the menu if it doesn't already exist (in case eg. NTVDM crashed) */
+ if (!VdmMenuExists(hConsoleMenu))
+ {
+ AppendMenuItems(hConsoleMenu, VdmMainMenuItems);
+ DrawMenuBar(GetConsoleWindow());
+ }
}
/*static*/ VOID
if (LoadStringW(GetModuleHandle(NULL),
(!ShowPtr ? IDS_SHOW_MOUSE : IDS_HIDE_MOUSE),
szMenuString,
- sizeof(szMenuString) / sizeof(szMenuString[0])) > 0)
+ ARRAYSIZE(szMenuString)) > 0)
{
ModifyMenu(hConsoleMenu, ID_SHOWHIDE_MOUSE,
MF_BYCOMMAND, ID_SHOWHIDE_MOUSE, szMenuString);
}
}
+static VOID EnableExtraHardware(HANDLE ConsoleInput)
+{
+ DWORD ConInMode;
+
+ if (GetConsoleMode(ConsoleInput, &ConInMode))
+ {
+#if 0
+ // GetNumberOfConsoleMouseButtons();
+ // GetSystemMetrics(SM_CMOUSEBUTTONS);
+ // GetSystemMetrics(SM_MOUSEPRESENT);
+ if (MousePresent)
+ {
+#endif
+ /* Support mouse input events if there is a mouse on the system */
+ ConInMode |= ENABLE_MOUSE_INPUT;
+#if 0
+ }
+ else
+ {
+ /* Do not support mouse input events if there is no mouse on the system */
+ ConInMode &= ~ENABLE_MOUSE_INPUT;
+ }
+#endif
+
+ SetConsoleMode(ConsoleInput, ConInMode);
+ }
+}
+
/* PUBLIC FUNCTIONS ***********************************************************/
VOID
* an auxiliary buffer; otherwise use the static buffer.
*/
MsgLen = _vscwprintf(Format, Parameters) + 1; // NULL-terminated
- if (MsgLen > sizeof(StaticBuffer)/sizeof(StaticBuffer[0]))
+ if (MsgLen > ARRAYSIZE(StaticBuffer))
{
- Buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, MsgLen * sizeof(WCHAR));
+ Buffer = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, MsgLen * sizeof(WCHAR));
if (Buffer == NULL)
{
/* Allocation failed, use the static buffer and display a suitable error message */
}
}
#else
- MsgLen = sizeof(Buffer)/sizeof(Buffer[0]);
+ MsgLen = ARRAYSIZE(Buffer);
#endif
/* Display the message */
#ifndef WIN2K_COMPLIANT
/* Free the buffer if needed */
- if (Buffer != StaticBuffer) HeapFree(GetProcessHeap(), 0, Buffer);
+ if (Buffer != StaticBuffer) RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer);
#endif
va_end(Parameters);
WINAPI
ConsoleCtrlHandler(DWORD ControlType)
{
+// HACK: Should be removed!
+#ifndef STANDALONE
+extern BOOLEAN AcceptCommands;
+extern HANDLE CommandThread;
+#endif
+
switch (ControlType)
{
- case CTRL_C_EVENT:
- case CTRL_BREAK_EVENT:
- {
- /* HACK: Stop the VDM */
- DPRINT1("Ctrl-C/Break: Stop the VDM\n");
- EmulatorTerminate();
- break;
- }
case CTRL_LAST_CLOSE_EVENT:
{
if (WaitForSingleObject(VdmTaskEvent, 0) == WAIT_TIMEOUT)
{
- /* Exit immediately */
+ /* Nothing runs, so exit immediately */
#ifndef STANDALONE
if (CommandThread) TerminateThread(CommandThread, 0);
#endif
#ifndef STANDALONE
else
{
- /* Stop accepting new commands */
+ /* A command is running, let it run, but stop accepting new commands */
AcceptCommands = FALSE;
}
#endif
break;
}
+
default:
{
/* Stop the VDM if the user logs out or closes the console */
DestroyVdmMenu();
}
-static BOOL
+BOOL
ConsoleAttach(VOID)
{
/* Save the original input and output console modes */
// return FALSE;
}
+ /* Set the console input mode */
+ // FIXME: Activate ENABLE_WINDOW_INPUT when we will want to perform actions
+ // upon console window events (screen buffer resize, ...).
+ SetConsoleMode(ConsoleInput, 0 /* | ENABLE_WINDOW_INPUT */);
+ EnableExtraHardware(ConsoleInput);
+
+ /* Set the console output mode */
+ // SetConsoleMode(ConsoleOutput, ENABLE_PROCESSED_OUTPUT | ENABLE_WRAP_AT_EOL_OUTPUT);
+
/* Initialize the UI */
ConsoleInitUI();
return TRUE;
}
-static VOID
+VOID
ConsoleDetach(VOID)
{
/* Restore the original input and output console modes */
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[])
{
+ NtVdmArgc = argc;
+ NtVdmArgv = argv;
+
#ifdef STANDALONE
if (argc < 2)
return 0;
}
-#else
-
- INT i;
- WCHAR *endptr;
-
- /* Parse the command line arguments */
- for (i = 1; i < argc; i++)
- {
- if (wcsncmp(argv[i], L"-i", 2) == 0)
- {
- /* This is the session ID */
- SessionId = wcstoul(argv[i] + 2, &endptr, 10);
-
- /* The VDM hasn't been started from a console, so quit when the task is done */
- AcceptCommands = FALSE;
- }
- }
-
#endif
- NtVdmArgc = argc;
- NtVdmArgv = argv;
+ /* Load global VDM settings */
+ LoadGlobalSettings();
DPRINT1("\n\n\nNTVDM - Starting...\n\n\n");
/* 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);
return 0;
}