Skip to content

Commit 2693a26

Browse files
committed
[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.
1 parent e0a272c commit 2693a26

File tree

2 files changed

+93
-33
lines changed

2 files changed

+93
-33
lines changed

subsystems/mvdm/ntvdm/hardware/cmos.c

Lines changed: 88 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222

2323
/* PRIVATE VARIABLES **********************************************************/
2424

25+
#define CMOS_RAM_FILE "cmos.ram"
26+
2527
static HANDLE hCmosRam = INVALID_HANDLE_VALUE;
2628
static CMOS_MEMORY CmosMemory;
2729

@@ -438,41 +440,88 @@ BOOLEAN IsNmiEnabled(VOID)
438440
return NmiEnabled;
439441
}
440442

443+
static inline BOOL
444+
CmosWriteFile(
445+
_In_ HANDLE FileHandle,
446+
_In_ PVOID Buffer,
447+
_In_ ULONG BufferSize,
448+
_Out_opt_ PULONG BytesWritten)
449+
{
450+
BOOL Success;
451+
ULONG Written;
452+
453+
SetFilePointer(FileHandle, 0, NULL, FILE_BEGIN);
454+
Success = WriteFile(FileHandle, Buffer, BufferSize, &Written, NULL);
455+
if (BytesWritten)
456+
*BytesWritten = (Success ? Written : 0);
457+
return Success;
458+
}
459+
441460
VOID CmosInitialize(VOID)
442461
{
443-
DWORD CmosSize = sizeof(CmosMemory);
462+
BOOL Success;
463+
WCHAR CmosPath[_countof(NtVdmPath) + _countof("\\" CMOS_RAM_FILE)];
444464

445-
/* File must not be opened before */
465+
/* CMOS file must not be opened before */
446466
ASSERT(hCmosRam == INVALID_HANDLE_VALUE);
447467

468+
/* Always open (and if needed, create) a RAM file with shared access */
469+
Success = NT_SUCCESS(RtlStringCbPrintfW(CmosPath,
470+
sizeof(CmosPath),
471+
L"%s\\" L(CMOS_RAM_FILE),
472+
NtVdmPath));
473+
if (!Success)
474+
DPRINT1("Could not create CMOS file path!\n");
475+
476+
if (Success)
477+
{
478+
SetLastError(ERROR_SUCCESS);
479+
hCmosRam = CreateFileW(CmosPath,
480+
GENERIC_READ | GENERIC_WRITE,
481+
FILE_SHARE_READ | FILE_SHARE_WRITE,
482+
NULL,
483+
OPEN_ALWAYS,
484+
FILE_ATTRIBUTE_NORMAL,
485+
NULL);
486+
Success = (hCmosRam != INVALID_HANDLE_VALUE);
487+
if (!Success)
488+
DPRINT1("CMOS opening failed (Error: %u)\n", GetLastError());
489+
}
490+
448491
/* Clear the CMOS memory */
449492
RtlZeroMemory(&CmosMemory, sizeof(CmosMemory));
450493

451-
/* Always open (and if needed, create) a RAM file with shared access */
452-
SetLastError(0); // For debugging purposes
453-
hCmosRam = CreateFileW(L"cmos.ram",
454-
GENERIC_READ | GENERIC_WRITE,
455-
FILE_SHARE_READ | FILE_SHARE_WRITE,
456-
NULL,
457-
OPEN_ALWAYS,
458-
FILE_ATTRIBUTE_NORMAL,
459-
NULL);
460-
DPRINT1("CMOS opening %s (Error: %u)\n", hCmosRam != INVALID_HANDLE_VALUE ? "succeeded" : "failed", GetLastError());
461-
462-
if (hCmosRam != INVALID_HANDLE_VALUE)
494+
/* Load the file only if it already existed and was opened, not newly created */
495+
if (Success)
463496
{
464-
BOOL Success;
465-
466-
/* Attempt to fill the CMOS memory with the RAM file */
467-
SetLastError(0); // For debugging purposes
468-
Success = ReadFile(hCmosRam, &CmosMemory, CmosSize, &CmosSize, NULL);
469-
if (CmosSize != sizeof(CmosMemory))
497+
if ((GetLastError() == ERROR_ALREADY_EXISTS) /* || (GetLastError() == ERROR_FILE_EXISTS) */)
498+
{
499+
/* Attempt to load the CMOS memory from the RAM file */
500+
DWORD CmosSize = sizeof(CmosMemory);
501+
Success = ReadFile(hCmosRam, &CmosMemory, CmosSize, &CmosSize, NULL);
502+
if (!Success)
503+
{
504+
DPRINT1("CMOS loading failed (Error: %u)\n", GetLastError());
505+
}
506+
else if (CmosSize != sizeof(CmosMemory))
507+
{
508+
/* Invalid CMOS RAM file; reinitialize the CMOS memory */
509+
DPRINT1("Invalid CMOS file, read %u bytes, expected %u bytes\n",
510+
CmosSize, sizeof(CmosMemory));
511+
Success = FALSE;
512+
}
513+
if (!Success)
514+
{
515+
/* Reset the CMOS memory and its RAM file */
516+
RtlZeroMemory(&CmosMemory, sizeof(CmosMemory));
517+
CmosWriteFile(hCmosRam, &CmosMemory, sizeof(CmosMemory), NULL);
518+
}
519+
}
520+
else
470521
{
471-
/* Bad CMOS RAM file. Reinitialize the CMOS memory. */
472-
DPRINT1("Invalid CMOS file, read bytes %u, expected bytes %u\n", CmosSize, sizeof(CmosMemory));
473-
RtlZeroMemory(&CmosMemory, sizeof(CmosMemory));
522+
/* Reset the CMOS RAM file */
523+
CmosWriteFile(hCmosRam, &CmosMemory, sizeof(CmosMemory), NULL);
474524
}
475-
DPRINT1("CMOS loading %s (Error: %u)\n", Success ? "succeeded" : "failed", GetLastError());
476525
SetFilePointer(hCmosRam, 0, NULL, FILE_BEGIN);
477526
}
478527

@@ -518,19 +567,25 @@ VOID CmosInitialize(VOID)
518567

519568
VOID CmosCleanup(VOID)
520569
{
521-
DWORD CmosSize = sizeof(CmosMemory);
522-
523-
if (hCmosRam == INVALID_HANDLE_VALUE) return;
524-
525570
DestroyHardwareTimer(PeriodicTimer);
526571
DestroyHardwareTimer(ClockTimer);
527572

528-
/* Flush the CMOS memory back to the RAM file and close it */
529-
SetFilePointer(hCmosRam, 0, NULL, FILE_BEGIN);
530-
WriteFile(hCmosRam, &CmosMemory, CmosSize, &CmosSize, NULL);
573+
if (hCmosRam != INVALID_HANDLE_VALUE)
574+
{
575+
/* Flush the CMOS memory back to the RAM file and close it */
576+
BOOL Success;
577+
DWORD CmosSize = sizeof(CmosMemory);
531578

532-
CloseHandle(hCmosRam);
533-
hCmosRam = INVALID_HANDLE_VALUE;
579+
Success = CmosWriteFile(hCmosRam, &CmosMemory, CmosSize, &CmosSize);
580+
if (!Success || (CmosSize != sizeof(CmosMemory)))
581+
{
582+
DPRINT1("CMOS saving failed (Error: %u), written %u bytes, expected %u bytes\n",
583+
GetLastError(), CmosSize, sizeof(CmosMemory));
584+
}
585+
586+
CloseHandle(hCmosRam);
587+
hCmosRam = INVALID_HANDLE_VALUE;
588+
}
534589
}
535590

536591
/* EOF */

subsystems/mvdm/ntvdm/ntvdm.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,11 @@
4444
#define _countof(_Array) (sizeof(_Array) / sizeof(_Array[0]))
4545
#endif
4646

47+
/* String widening macro */
48+
#define __L(x) L ## x
49+
#define _L(x) __L(x)
50+
#define L(x) _L(x)
51+
4752
/* PSDK/NDK Headers */
4853
#define WIN32_NO_STATUS
4954
#include <windef.h>

0 commit comments

Comments
 (0)