[NTVDM] Retrieve the full directory of the current running NTVDM instance, to be...
authorHermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
Sat, 27 Nov 2021 20:03:55 +0000 (21:03 +0100)
committerHermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
Sat, 27 Nov 2021 23:26:45 +0000 (00:26 +0100)
subsystems/mvdm/ntvdm/ntvdm.c
subsystems/mvdm/ntvdm/ntvdm.h

index bedc20e..5214d81 100644 (file)
@@ -31,6 +31,10 @@ NTVDM_SETTINGS GlobalSettings;
 INT     NtVdmArgc;
 WCHAR** NtVdmArgv;
 
+/* Full directory where NTVDM resides, or the SystemRoot\System32 path */
+WCHAR NtVdmPath[MAX_PATH];
+ULONG NtVdmPathSize; // Length without NULL terminator.
+
 /* PRIVATE FUNCTIONS **********************************************************/
 
 static NTSTATUS
@@ -476,6 +480,8 @@ PrintMessageAnsi(IN CHAR_PRINT CharPrint,
 INT
 wmain(INT argc, WCHAR *argv[])
 {
+    BOOL Success;
+
 #ifdef STANDALONE
 
     if (argc < 2)
@@ -531,20 +537,62 @@ wmain(INT argc, WCHAR *argv[])
             "\n\n",
             GetCommandLineA());
 
+    /*
+     * 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);
+
     /* Load the global VDM settings */
     LoadGlobalSettings(&GlobalSettings);
 
     /* Initialize the console */
     if (!ConsoleInit())
     {
-        wprintf(L"FATAL: A problem occurred when trying to initialize the console\n");
+        wprintf(L"FATAL: A problem occurred when trying to initialize the console.\n");
         goto Cleanup;
     }
 
     /* Initialize the emulator */
     if (!EmulatorInitialize(ConsoleInput, ConsoleOutput))
     {
-        wprintf(L"FATAL: Failed to initialize the emulator\n");
+        wprintf(L"FATAL: Failed to initialize the emulator.\n");
         goto Cleanup;
     }
 
index 2b006c0..b3876fb 100644 (file)
 #include <stdarg.h>
 #include <wchar.h>
 
+#ifndef _countof
+#define _countof(_Array) (sizeof(_Array) / sizeof(_Array[0]))
+#endif
+
 /* PSDK/NDK Headers */
 #define WIN32_NO_STATUS
 #include <windef.h>
@@ -67,6 +71,8 @@ DWORD WINAPI SetLastConsoleEventActive(VOID);
 /* PSEH for SEH Support */
 #include <pseh/pseh2.h>
 
+#include <ntstrsafe.h>
+
 
 /* VARIABLES ******************************************************************/
 
@@ -84,6 +90,10 @@ extern NTVDM_SETTINGS GlobalSettings;
 extern INT     NtVdmArgc;
 extern WCHAR** NtVdmArgv;
 
+/* Full directory where NTVDM resides, or the SystemRoot\System32 path */
+extern WCHAR NtVdmPath[MAX_PATH];
+extern ULONG NtVdmPathSize; // Length without NULL terminator.
+
 extern HWND hConsoleWnd;