https://git.reactos.org/?p=reactos.git;a=commitdiff;h=2693a26e3e9ae7cf22b96…
commit 2693a26e3e9ae7cf22b96da7391612df80b14be7
Author:     Hermès Bélusca-Maïto <hermes.belusca-maito(a)reactos.org>
AuthorDate: Fri Nov 26 20:13:58 2021 +0100
Commit:     Hermès Bélusca-Maïto <hermes.belusca-maito(a)reactos.org>
CommitDate: Sun Nov 28 00:26:46 2021 +0100
    [NTVDM] Create the CMOS ram file in NTVDM's own directory, instead of in whatever
current directory we are running.
    This fixes the age-long annoyance that wherever you ran a DOS program
    with NTVDM, its cmos.ram file would be created in the same current
    directory the DOS program was being started.
    This created at least two problems:
    - useless pollution of directories with cmos.ram files;
    - for installers, e.g. of Turbo C 1.x that enumerate the install files
      from their directories to be copied/extracted somewhere, the cmos.ram
      file could then be enumerated along and cause the installation to
      interrupt and/or fail.
    Now the cmos.ram file is created in the same directory NTVDM resides
    (usually in System32...).
    Also, debug-print out only loading errors instead of successes as well.
---
 subsystems/mvdm/ntvdm/hardware/cmos.c | 121 ++++++++++++++++++++++++----------
 subsystems/mvdm/ntvdm/ntvdm.h         |   5 ++
 2 files changed, 93 insertions(+), 33 deletions(-)
diff --git a/subsystems/mvdm/ntvdm/hardware/cmos.c b/subsystems/mvdm/ntvdm/hardware/cmos.c
index 8482553c08e..60abb6ffef9 100644
--- a/subsystems/mvdm/ntvdm/hardware/cmos.c
+++ b/subsystems/mvdm/ntvdm/hardware/cmos.c
@@ -22,6 +22,8 @@
 /* PRIVATE VARIABLES **********************************************************/
+#define CMOS_RAM_FILE   "cmos.ram"
+
 static HANDLE hCmosRam = INVALID_HANDLE_VALUE;
 static CMOS_MEMORY CmosMemory;
@@ -438,41 +440,88 @@ BOOLEAN IsNmiEnabled(VOID)
     return NmiEnabled;
 }
+static inline BOOL
+CmosWriteFile(
+    _In_ HANDLE FileHandle,
+    _In_ PVOID Buffer,
+    _In_ ULONG BufferSize,
+    _Out_opt_ PULONG BytesWritten)
+{
+    BOOL Success;
+    ULONG Written;
+
+    SetFilePointer(FileHandle, 0, NULL, FILE_BEGIN);
+    Success = WriteFile(FileHandle, Buffer, BufferSize, &Written, NULL);
+    if (BytesWritten)
+        *BytesWritten = (Success ? Written : 0);
+    return Success;
+}
+
 VOID CmosInitialize(VOID)
 {
-    DWORD CmosSize = sizeof(CmosMemory);
+    BOOL Success;
+    WCHAR CmosPath[_countof(NtVdmPath) + _countof("\\" CMOS_RAM_FILE)];
-    /* File must not be opened before */
+    /* CMOS file must not be opened before */
     ASSERT(hCmosRam == INVALID_HANDLE_VALUE);
+    /* Always open (and if needed, create) a RAM file with shared access */
+    Success = NT_SUCCESS(RtlStringCbPrintfW(CmosPath,
+                                            sizeof(CmosPath),
+                                            L"%s\\" L(CMOS_RAM_FILE),
+                                            NtVdmPath));
+    if (!Success)
+        DPRINT1("Could not create CMOS file path!\n");
+
+    if (Success)
+    {
+        SetLastError(ERROR_SUCCESS);
+        hCmosRam = CreateFileW(CmosPath,
+                               GENERIC_READ | GENERIC_WRITE,
+                               FILE_SHARE_READ | FILE_SHARE_WRITE,
+                               NULL,
+                               OPEN_ALWAYS,
+                               FILE_ATTRIBUTE_NORMAL,
+                               NULL);
+        Success = (hCmosRam != INVALID_HANDLE_VALUE);
+        if (!Success)
+            DPRINT1("CMOS opening failed (Error: %u)\n", GetLastError());
+    }
+
     /* Clear the CMOS memory */
     RtlZeroMemory(&CmosMemory, sizeof(CmosMemory));
-    /* Always open (and if needed, create) a RAM file with shared access */
-    SetLastError(0); // For debugging purposes
-    hCmosRam = CreateFileW(L"cmos.ram",
-                           GENERIC_READ | GENERIC_WRITE,
-                           FILE_SHARE_READ | FILE_SHARE_WRITE,
-                           NULL,
-                           OPEN_ALWAYS,
-                           FILE_ATTRIBUTE_NORMAL,
-                           NULL);
-    DPRINT1("CMOS opening %s (Error: %u)\n", hCmosRam != INVALID_HANDLE_VALUE ?
"succeeded" : "failed", GetLastError());
-
-    if (hCmosRam != INVALID_HANDLE_VALUE)
+    /* Load the file only if it already existed and was opened, not newly created */
+    if (Success)
     {
-        BOOL Success;
-
-        /* Attempt to fill the CMOS memory with the RAM file */
-        SetLastError(0); // For debugging purposes
-        Success = ReadFile(hCmosRam, &CmosMemory, CmosSize, &CmosSize, NULL);
-        if (CmosSize != sizeof(CmosMemory))
+        if ((GetLastError() == ERROR_ALREADY_EXISTS) /* || (GetLastError() ==
ERROR_FILE_EXISTS) */)
+        {
+            /* Attempt to load the CMOS memory from the RAM file */
+            DWORD CmosSize = sizeof(CmosMemory);
+            Success = ReadFile(hCmosRam, &CmosMemory, CmosSize, &CmosSize, NULL);
+            if (!Success)
+            {
+                DPRINT1("CMOS loading failed (Error: %u)\n", GetLastError());
+            }
+            else if (CmosSize != sizeof(CmosMemory))
+            {
+                /* Invalid CMOS RAM file; reinitialize the CMOS memory */
+                DPRINT1("Invalid CMOS file, read %u bytes, expected %u
bytes\n",
+                        CmosSize, sizeof(CmosMemory));
+                Success = FALSE;
+            }
+            if (!Success)
+            {
+                /* Reset the CMOS memory and its RAM file */
+                RtlZeroMemory(&CmosMemory, sizeof(CmosMemory));
+                CmosWriteFile(hCmosRam, &CmosMemory, sizeof(CmosMemory), NULL);
+            }
+        }
+        else
         {
-            /* Bad CMOS RAM file. Reinitialize the CMOS memory. */
-            DPRINT1("Invalid CMOS file, read bytes %u, expected bytes %u\n",
CmosSize, sizeof(CmosMemory));
-            RtlZeroMemory(&CmosMemory, sizeof(CmosMemory));
+            /* Reset the CMOS RAM file */
+            CmosWriteFile(hCmosRam, &CmosMemory, sizeof(CmosMemory), NULL);
         }
-        DPRINT1("CMOS loading %s (Error: %u)\n", Success ?
"succeeded" : "failed", GetLastError());
         SetFilePointer(hCmosRam, 0, NULL, FILE_BEGIN);
     }
@@ -518,19 +567,25 @@ VOID CmosInitialize(VOID)
 VOID CmosCleanup(VOID)
 {
-    DWORD CmosSize = sizeof(CmosMemory);
-
-    if (hCmosRam == INVALID_HANDLE_VALUE) return;
-
     DestroyHardwareTimer(PeriodicTimer);
     DestroyHardwareTimer(ClockTimer);
-    /* Flush the CMOS memory back to the RAM file and close it */
-    SetFilePointer(hCmosRam, 0, NULL, FILE_BEGIN);
-    WriteFile(hCmosRam, &CmosMemory, CmosSize, &CmosSize, NULL);
+    if (hCmosRam != INVALID_HANDLE_VALUE)
+    {
+        /* Flush the CMOS memory back to the RAM file and close it */
+        BOOL Success;
+        DWORD CmosSize = sizeof(CmosMemory);
-    CloseHandle(hCmosRam);
-    hCmosRam = INVALID_HANDLE_VALUE;
+        Success = CmosWriteFile(hCmosRam, &CmosMemory, CmosSize, &CmosSize);
+        if (!Success || (CmosSize != sizeof(CmosMemory)))
+        {
+            DPRINT1("CMOS saving failed (Error: %u), written %u bytes, expected %u
bytes\n",
+                    GetLastError(), CmosSize, sizeof(CmosMemory));
+        }
+
+        CloseHandle(hCmosRam);
+        hCmosRam = INVALID_HANDLE_VALUE;
+    }
 }
 /* EOF */
diff --git a/subsystems/mvdm/ntvdm/ntvdm.h b/subsystems/mvdm/ntvdm/ntvdm.h
index b3876fb9a98..1c99f2a0011 100644
--- a/subsystems/mvdm/ntvdm/ntvdm.h
+++ b/subsystems/mvdm/ntvdm/ntvdm.h
@@ -44,6 +44,11 @@
 #define _countof(_Array) (sizeof(_Array) / sizeof(_Array[0]))
 #endif
+/* String widening macro */
+#define __L(x)  L ## x
+#define _L(x)   __L(x)
+#define L(x)    _L(x)
+
 /* PSDK/NDK Headers */
 #define WIN32_NO_STATUS
 #include <windef.h>