From 597a383e60c57df8df1c84c702fdb6dd20dc54e4 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Herm=C3=A8s=20B=C3=A9lusca-Ma=C3=AFto?= Date: Mon, 13 Jul 2015 01:21:46 +0000 Subject: [PATCH] [NTVDM]: Commit some local changes that can be committed now: - Whitespace fixes. - Improve some DPRINTs. - hardcoded_values--; - Fix DisplayMessage() for NULL-terminated strings. - Free the allocated block of memory in the mouse driver cleanup procedure. - Properly inherit the parent process environment block if needed. - Return the correct last error if DosCopyEnvironmentBlock fails. - Big ifs turned into switch. - Implement some INT 2Fh DOS multiplex functions (AX=1200h "Installation check", AX=1203h "Get DOS data segment", AX=1214h "Compare FAR pointers", AX=122Fh "Set DOS version to return"); remove the DPRINT for AX=1680h "Release Current Virtual Machine Time-slice". - Stubplement INT 2Ah "DOS critical sections / network" (it just monitors calls to itself at the moment). - Use the boot drive root path as the current directory if we failed retrieving a valid one. - Offsetize the DOS_SYSVARS members (so that I don't have to compute by head the offsets, especially when some of the members is a structure from which I don't know in advance its size); add some C_ASSERTs on the size of DOS standard structures. - Move the NullDriverRoutine buffer outside the sysvars buffer (because it has nothing to do inside it). - In ConDrvReadInput: do not echo the first part of an extended character. - Add basic support for changing the reported DosVersion. svn path=/trunk/; revision=68395 --- .../mvdm/ntvdm/dos/dos32krnl/bios.c | 15 +- .../mvdm/ntvdm/dos/dos32krnl/condrv.c | 4 +- .../mvdm/ntvdm/dos/dos32krnl/country.c | 14 +- .../mvdm/ntvdm/dos/dos32krnl/device.h | 1 + .../subsystems/mvdm/ntvdm/dos/dos32krnl/dos.c | 260 +++++++++++++----- .../subsystems/mvdm/ntvdm/dos/dos32krnl/dos.h | 39 +-- .../mvdm/ntvdm/dos/dos32krnl/memory.c | 6 +- .../mvdm/ntvdm/dos/dos32krnl/memory.h | 1 + .../mvdm/ntvdm/dos/dos32krnl/process.c | 22 +- reactos/subsystems/mvdm/ntvdm/dos/mouse32.c | 8 +- reactos/subsystems/mvdm/ntvdm/hardware/cmos.c | 4 +- reactos/subsystems/mvdm/ntvdm/ntvdm.c | 21 +- reactos/subsystems/mvdm/ntvdm/ntvdm.h | 2 +- 13 files changed, 266 insertions(+), 131 deletions(-) diff --git a/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/bios.c b/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/bios.c index f384cd1ad85..689b7cf50d7 100644 --- a/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/bios.c +++ b/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/bios.c @@ -32,9 +32,6 @@ /* PRIVATE VARIABLES **********************************************************/ -// static BYTE CurrentDrive; -// static CHAR CurrentDirectories[NUM_DRIVES][DOS_DIR_LENGTH]; - /* PRIVATE FUNCTIONS **********************************************************/ /* PUBLIC FUNCTIONS ***********************************************************/ @@ -105,7 +102,13 @@ BOOLEAN DosBuildSysEnvBlock(VOID) LPSTR SourcePtr, Environment; LPSTR DestPtr = (LPSTR)SEG_OFF_TO_PTR(SYSTEM_ENV_BLOCK, 0); - /* Get the environment strings */ + /* + * Get the environment strings + * + * NOTE: On non-STANDALONE builds, this corresponds to the VDM environment + * as created by BaseVDM for NTVDM. On STANDALONE builds this is the Win32 + * environment. In this last case we need to convert it to a proper VDM env. + */ SourcePtr = Environment = GetEnvironmentStrings(); if (Environment == NULL) return FALSE; @@ -231,10 +234,6 @@ BOOLEAN DosBIOSInitialize(VOID) #endif - - /* Register the DOS 32-bit Interrupts */ - // RegisterDosInt32(0x20, DosInt20h); - /* Initialize the DOS kernel */ return DosKRNLInitialize(); } diff --git a/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/condrv.c b/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/condrv.c index fe9908b8a54..790177976ba 100644 --- a/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/condrv.c +++ b/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/condrv.c @@ -61,9 +61,11 @@ WORD NTAPI ConDrvReadInput(PDOS_DEVICE_NODE Device, DWORD Buffer, PWORD Length) /* Check if this is a special character */ if (Character == 0) ExtendedCode = getAH(); - if (DoEcho) DosPrintCharacter(DOS_OUTPUT_HANDLE, Character); Pointer[BytesRead++] = Character; + if (Character != 0 && DoEcho) + DosPrintCharacter(DOS_OUTPUT_HANDLE, Character); + /* Stop on first carriage return */ if (Character == '\r') { diff --git a/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/country.c b/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/country.c index 921bac00564..b47bab9d0fa 100644 --- a/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/country.c +++ b/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/country.c @@ -98,30 +98,30 @@ DosGetCountryInfo(IN OUT PWORD CountryId, (LPSTR)&CountryInfo->DecimalSep, sizeof(CountryInfo->DecimalSep)); if (Return == 0) return LOWORD(GetLastError()); - + Return = GetLocaleInfoA(LOCALE_USER_DEFAULT, LOCALE_SDATE, (LPSTR)&CountryInfo->DateSep, sizeof(CountryInfo->DateSep)); if (Return == 0) return LOWORD(GetLastError()); - + Return = GetLocaleInfoA(LOCALE_USER_DEFAULT, LOCALE_STIME, (LPSTR)&CountryInfo->TimeSep, sizeof(CountryInfo->TimeSep)); if (Return == 0) return LOWORD(GetLastError()); - + // NOTE: '4: Symbol replace decimal separator' is unsupported. Return = GetLocaleInfoA(LOCALE_USER_DEFAULT, LOCALE_ICURRENCY | LOCALE_RETURN_NUMBER, (LPSTR)&NumVal, sizeof(NumVal)); if (Return == 0) return LOWORD(GetLastError()); CountryInfo->CurrencyFormat = (BYTE)NumVal; - + Return = GetLocaleInfoA(LOCALE_USER_DEFAULT, LOCALE_ICURRDIGITS | LOCALE_RETURN_NUMBER, // LOCALE_IDIGITS | LOCALE_RETURN_NUMBER (LPSTR)&NumVal, sizeof(NumVal)); if (Return == 0) return LOWORD(GetLastError()); CountryInfo->CurrencyDigitsNum = (BYTE)NumVal; - + Return = GetLocaleInfoA(LOCALE_USER_DEFAULT, LOCALE_ITIME | LOCALE_RETURN_NUMBER, (LPSTR)&NumVal, sizeof(NumVal)); @@ -129,7 +129,7 @@ DosGetCountryInfo(IN OUT PWORD CountryId, CountryInfo->TimeFormat = (BYTE)NumVal; CountryInfo->CaseMapPtr = MAKELONG(FIELD_OFFSET(COUNTRY_DATA, CaseMapRoutine), CountryDataSegment); - + // CountryInfo->DataListSep; return ERROR_SUCCESS; @@ -240,7 +240,7 @@ BOOLEAN DosCountryInitialize(VOID) CountryDataSegment = DosAllocateMemory(sizeof(COUNTRY_DATA), NULL); if (CountryDataSegment == 0) return FALSE; CountryData = (PCOUNTRY_DATA)SEG_OFF_TO_PTR(CountryDataSegment, 0x0000); - + RtlMoveMemory(CountryData->CaseMapRoutine, CaseMapRoutine, sizeof(CaseMapRoutine)); diff --git a/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/device.h b/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/device.h index 9f163b924b7..c125b1a731c 100644 --- a/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/device.h +++ b/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/device.h @@ -123,6 +123,7 @@ typedef struct _DOS_DRIVER }; }; } DOS_DRIVER, *PDOS_DRIVER; +C_ASSERT(sizeof(DOS_DRIVER) == 0x12); typedef struct _DOS_REQUEST_HEADER { diff --git a/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/dos.c b/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/dos.c index 99354e4ec1d..efa1ea6ed02 100644 --- a/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/dos.c +++ b/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/dos.c @@ -91,7 +91,7 @@ static BOOLEAN DosChangeDirectory(LPSTR Directory) return FALSE; } - /* Check whether the directory string is of format "?:..." */ + /* Check whether the directory string is of format "X:..." */ if (strlen(Directory) >= 2 && Directory[1] == ':') { /* Get the drive number */ @@ -114,8 +114,8 @@ static BOOLEAN DosChangeDirectory(LPSTR Directory) Attributes = GetFileAttributesA(Directory); /* Make sure the path exists and is a directory */ - if ((Attributes == INVALID_FILE_ATTRIBUTES) - || !(Attributes & FILE_ATTRIBUTE_DIRECTORY)) + if ((Attributes == INVALID_FILE_ATTRIBUTES) || + !(Attributes & FILE_ATTRIBUTE_DIRECTORY)) { Sda->LastErrorCode = ERROR_PATH_NOT_FOUND; return FALSE; @@ -146,17 +146,11 @@ static BOOLEAN DosChangeDirectory(LPSTR Directory) return FALSE; } - /* Get the directory part of the path */ + /* Get the directory part of the path and set the current directory for the drive */ Path = strchr(DosDirectory, '\\'); if (Path != NULL) { - /* Skip the backslash */ - Path++; - } - - /* Set the directory for the drive */ - if (Path != NULL) - { + Path++; // Skip the backslash strncpy(DosData->CurrentDirectories[DriveNumber], Path, DOS_DIR_LENGTH); } else @@ -829,8 +823,10 @@ VOID WINAPI DosInt21h(LPWORD Stack) DWORD NumberOfFreeClusters; DWORD TotalNumberOfClusters; - if (getDL() == 0x00) RootPath[0] = 'A' + Sda->CurrentDrive; - else RootPath[0] = 'A' + getDL() - 1; + if (getDL() == 0x00) + RootPath[0] = 'A' + Sda->CurrentDrive; + else + RootPath[0] = 'A' + getDL() - 1; if (GetDiskFreeSpaceA(RootPath, &SectorsPerCluster, @@ -914,7 +910,7 @@ VOID WINAPI DosInt21h(LPWORD Stack) { WORD CountryId = getAL() < 0xFF ? getAL() : getBX(); WORD ErrorCode; - + ErrorCode = DosGetCountryInfo(&CountryId, (PDOS_COUNTRY_INFO)SEG_OFF_TO_PTR(getDS(), getDX())); @@ -1110,7 +1106,7 @@ VOID WINAPI DosInt21h(LPWORD Stack) * See Ralf Brown: http://www.ctyme.com/intr/rb-2797.htm * "AX destroyed (DOS 3.3) AL seems to be drive of deleted file." */ - setAL(FileName[0] - 'A'); + setAL(RtlUpperChar(FileName[0]) - 'A'); } else { @@ -1519,54 +1515,68 @@ VOID WINAPI DosInt21h(LPWORD Stack) /* Get/Set Memory Management Options */ case 0x58: { - if (getAL() == 0x00) + switch (getAL()) { /* Get allocation strategy */ - Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF; - setAX(Sda->AllocStrategy); - } - else if (getAL() == 0x01) - { - /* Set allocation strategy */ - - if ((getBL() & (DOS_ALLOC_HIGH | DOS_ALLOC_HIGH_LOW)) - == (DOS_ALLOC_HIGH | DOS_ALLOC_HIGH_LOW)) + case 0x00: { - /* Can't set both */ - Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF; - setAX(ERROR_INVALID_PARAMETER); + Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF; + setAX(Sda->AllocStrategy); break; } - if ((getBL() & 0x3F) > DOS_ALLOC_LAST_FIT) + /* Set allocation strategy */ + case 0x01: { - /* Invalid allocation strategy */ - Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF; - setAX(ERROR_INVALID_PARAMETER); + if ((getBL() & (DOS_ALLOC_HIGH | DOS_ALLOC_HIGH_LOW)) + == (DOS_ALLOC_HIGH | DOS_ALLOC_HIGH_LOW)) + { + /* Can't set both */ + Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF; + setAX(ERROR_INVALID_PARAMETER); + break; + } + + if ((getBL() & ~(DOS_ALLOC_HIGH | DOS_ALLOC_HIGH_LOW)) + > DOS_ALLOC_LAST_FIT) + { + /* Invalid allocation strategy */ + Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF; + setAX(ERROR_INVALID_PARAMETER); + break; + } + + Sda->AllocStrategy = getBL(); + Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF; break; } - Sda->AllocStrategy = getBL(); - Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF; - } - else if (getAL() == 0x02) - { /* Get UMB link state */ - Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF; - setAL(DosUmbLinked ? 0x01 : 0x00); - } - else if (getAL() == 0x03) - { + case 0x02: + { + Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF; + setAL(DosUmbLinked ? 0x01 : 0x00); + break; + } + /* Set UMB link state */ - if (getBX()) DosLinkUmb(); - else DosUnlinkUmb(); - Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF; - } - else - { + case 0x03: + { + if (getBX()) + DosLinkUmb(); + else + DosUnlinkUmb(); + + Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF; + break; + } + /* Invalid or unsupported function */ - Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF; - setAX(ERROR_INVALID_FUNCTION); + default: + { + Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF; + setAX(ERROR_INVALID_FUNCTION); + } } break; @@ -2021,10 +2031,77 @@ VOID WINAPI DosFastConOut(LPWORD Stack) setAX(AX); } +VOID WINAPI DosInt2Ah(LPWORD Stack) +{ + DPRINT1("INT 2Ah, AX=%4xh called\n", getAX()); +} + VOID WINAPI DosInt2Fh(LPWORD Stack) { switch (getAH()) { + /* DOS 3+ Internal Utility Functions */ + case 0x12: + { + DPRINT1("INT 2Fh, AX=%4xh DOS Internal Utility Function called\n", getAX()); + + switch (getAL()) + { + /* Installation Check */ + case 0x00: + { + setAL(0xFF); + break; + } + + /* Get DOS Data Segment */ + case 0x03: + { + setDS(DOS_DATA_SEGMENT); + break; + } + + /* Compare FAR Pointers */ + case 0x14: + { + PVOID PointerFromFarPointer1 = SEG_OFF_TO_PTR(getDS(), getSI()); + PVOID PointerFromFarPointer2 = SEG_OFF_TO_PTR(getES(), getDI()); + BOOLEAN AreEqual = (PointerFromFarPointer1 == PointerFromFarPointer2); + + setZF(AreEqual); + setCF(!AreEqual); + break; + } + + /* Set DOS Version Number to return */ + case 0x2F: + { + WORD DosVersion = getDX(); + + // Special case: return the true DOS version when DX=00h + if (DosVersion == 0x0000) + DosData->DosVersion = DOS_VERSION; + else + DosData->DosVersion = DosVersion; + + break; + } + } + + break; + } + + /* Mostly Windows 2.x/3.x/9x support */ + case 0x16: + { + /* + * AL=80h is DOS/Windows/DPMI "Release Current Virtual Machine Time-slice" + * Just do nothing in this case. + */ + if (getAL() != 0x80) goto Default; + break; + } + /* Extended Memory Specification */ case 0x43: { @@ -2057,7 +2134,7 @@ VOID WINAPI DosInt2Fh(LPWORD Stack) break; } - default: + default: Default: { DPRINT1("DOS Internal System Function INT 0x2F, AH = %xh, AL = %xh NOT IMPLEMENTED!\n", getAH(), getAL()); @@ -2073,6 +2150,8 @@ BOOLEAN DosKRNLInitialize(VOID) UCHAR i; PDOS_SFT Sft; LPSTR Path; + BOOLEAN Success = TRUE; + DWORD dwRet; CHAR CurrentDirectory[MAX_PATH]; CHAR DosDirectory[DOS_DIR_LENGTH]; @@ -2103,59 +2182,88 @@ BOOLEAN DosKRNLInitialize(VOID) SysVars->FirstSft = MAKELONG(DOS_DATA_OFFSET(Sft), DOS_DATA_SEGMENT); SysVars->CurrentDirs = MAKELONG(DOS_DATA_OFFSET(CurrentDirectories), DOS_DATA_SEGMENT); - /* The last drive can be redefined with the LASTDRIVE command. At the moment, set the real maximum possible, 'Z'. */ - SysVars->NumLocalDrives = 'Z' - 'A' + 1; + /* + * The last drive can be redefined with the LASTDRIVE command. + * At the moment, set the real maximum possible, 'Z'. + */ + SysVars->NumLocalDrives = 'Z' - 'A' + 1; // See #define NUM_DRIVES in dos.h /* The boot drive is initialized to the %SYSTEMDRIVE% value */ // NOTE: Using the NtSystemRoot system variable might be OS-specific... - SysVars->BootDrive = SharedUserData->NtSystemRoot[0] - 'A' + 1; + SysVars->BootDrive = RtlUpcaseUnicodeChar(SharedUserData->NtSystemRoot[0]) - 'A' + 1; /* Initialize the NUL device driver */ SysVars->NullDevice.Link = 0xFFFFFFFF; SysVars->NullDevice.DeviceAttributes = DOS_DEVATTR_NUL | DOS_DEVATTR_CHARACTER; - SysVars->NullDevice.StrategyRoutine = FIELD_OFFSET(DOS_SYSVARS, NullDriverRoutine); + // Offset from within the DOS data segment + SysVars->NullDevice.StrategyRoutine = DOS_DATA_OFFSET(NullDriverRoutine); + // Hardcoded to the RETF inside StrategyRoutine SysVars->NullDevice.InterruptRoutine = SysVars->NullDevice.StrategyRoutine + 6; RtlFillMemory(SysVars->NullDevice.DeviceName, sizeof(SysVars->NullDevice.DeviceName), ' '); RtlCopyMemory(SysVars->NullDevice.DeviceName, "NUL", strlen("NUL")); - RtlCopyMemory(SysVars->NullDriverRoutine, + RtlCopyMemory(DosData->NullDriverRoutine, NullDriverRoutine, sizeof(NullDriverRoutine)); + /* Default DOS version to report */ + DosData->DosVersion = DOS_VERSION; + /* Initialize the swappable data area */ Sda = &DosData->Sda; RtlZeroMemory(Sda, sizeof(*Sda)); - /* Get the current directory */ - if (!GetCurrentDirectoryA(sizeof(CurrentDirectory), CurrentDirectory)) + /* Get the current directory and convert it to a DOS path */ + dwRet = GetCurrentDirectoryA(sizeof(CurrentDirectory), CurrentDirectory); + if (dwRet == 0) { - // TODO: Use some kind of default path? - return FALSE; + Success = FALSE; + DPRINT1("GetCurrentDirectoryA failed (Error: %u)\n", GetLastError()); + } + else if (dwRet > sizeof(CurrentDirectory)) + { + Success = FALSE; + DPRINT1("Current directory too long (%d > MAX_PATH) for GetCurrentDirectoryA\n", dwRet); } - /* Convert it to a DOS path */ - if (!GetShortPathNameA(CurrentDirectory, DosDirectory, sizeof(DosDirectory))) + if (Success) { - // TODO: Use some kind of default path? - return FALSE; + dwRet = GetShortPathNameA(CurrentDirectory, DosDirectory, sizeof(DosDirectory)); + if (dwRet == 0) + { + Success = FALSE; + DPRINT1("GetShortPathNameA failed (Error: %u)\n", GetLastError()); + } + else if (dwRet > sizeof(DosDirectory)) + { + Success = FALSE; + DPRINT1("Short path too long (%d > DOS_DIR_LENGTH) for GetShortPathNameA\n", dwRet); + } + } + + if (!Success) + { + /* We failed, use the boot drive instead */ + DosDirectory[0] = SysVars->BootDrive + 'A' - 1; + DosDirectory[1] = ':'; + DosDirectory[2] = '\\'; + DosDirectory[3] = '\0'; } - /* Set the drive */ + /* Set the current drive */ Sda->CurrentDrive = RtlUpperChar(DosDirectory[0]) - 'A'; - /* Get the directory part of the path */ + /* Get the directory part of the path and set the current directory */ Path = strchr(DosDirectory, '\\'); if (Path != NULL) { - /* Skip the backslash */ - Path++; + Path++; // Skip the backslash + strncpy(DosData->CurrentDirectories[Sda->CurrentDrive], Path, DOS_DIR_LENGTH); } - - /* Set the directory */ - if (Path != NULL) + else { - strncpy(DosData->CurrentDirectories[Sda->CurrentDrive], Path, DOS_DIR_LENGTH); + DosData->CurrentDirectories[Sda->CurrentDrive][0] = '\0'; } /* Set the current PSP to the system PSP */ @@ -2205,7 +2313,13 @@ BOOLEAN DosKRNLInitialize(VOID) RegisterDosInt32(0x2F, DosInt2Fh ); // Multiplex Interrupt /* Unimplemented DOS interrupts */ - RegisterDosInt32(0x2A, NULL); // Network - Installation Check + RegisterDosInt32(0x2A, DosInt2Ah); // DOS Critical Sections / Network +// RegisterDosInt32(0x2E, NULL); // COMMAND.COM "Reload Transient" + + /* Reserved DOS interrupts */ + RegisterDosInt32(0x2B, NULL); + RegisterDosInt32(0x2C, NULL); + RegisterDosInt32(0x2D, NULL); /* Initialize country data */ DosCountryInitialize(); diff --git a/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/dos.h b/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/dos.h index 84cd42e70c4..964b6b6a400 100644 --- a/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/dos.h +++ b/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/dos.h @@ -80,21 +80,25 @@ typedef struct _DOS_SYSVARS WORD FirstMcb; /* This is where the SYSVARS really start */ - DWORD FirstDpb; - DWORD FirstSft; - DWORD ActiveClock; - DWORD ActiveCon; - BYTE Reserved0[6]; - DWORD CurrentDirs; - BYTE Reserved1[6]; - BYTE NumBlockDevices; - BYTE NumLocalDrives; // Set by LASTDRIVE - DOS_DRIVER NullDevice; - BYTE NullDriverRoutine[7]; - BYTE Reserved2[8]; - BYTE BootDrive; - BYTE UseDwordMoves; - WORD ExtMemSize; + DWORD FirstDpb; // 0x00 + DWORD FirstSft; // 0x04 + DWORD ActiveClock; // 0x08 + DWORD ActiveCon; // 0x0c + BYTE Reserved0[6]; // 0x10 + DWORD CurrentDirs; // 0x16 + BYTE Reserved1[6]; // 0x1a + BYTE NumBlockDevices; // 0x20 + BYTE NumLocalDrives; // 0x21 - Set by LASTDRIVE + DOS_DRIVER NullDevice; // 0x22 + BYTE Reserved2; // 0x34 + WORD ProgramVersionTable; // 0x35 + DWORD SetVerTable; // 0x37 + WORD Reserved3[2]; // 0x3b + WORD BuffersNumber; // 0x3f - 'x' parameter in "BUFFERS=x,y" command + WORD BuffersLookaheadNumber; // 0x41 - 'y' parameter in "BUFFERS=x,y" command + BYTE BootDrive; // 0x43 + BYTE UseDwordMoves; // 0x44 + WORD ExtMemSize; // 0x45 } DOS_SYSVARS, *PDOS_SYSVARS; typedef struct _DOS_CLOCK_TRANSFER_RECORD @@ -232,6 +236,8 @@ typedef struct _DOS_SDA typedef struct _DOS_DATA { DOS_SYSVARS SysVars; + BYTE NullDriverRoutine[7]; + WORD DosVersion; // DOS version to report to programs (can be different from the true one) DOS_SDA Sda; CHAR CurrentDirectories[NUM_DRIVES][DOS_DIR_LENGTH]; BYTE Sft[ANYSIZE_ARRAY]; @@ -242,8 +248,7 @@ typedef struct _DOS_DATA /* VARIABLES ******************************************************************/ extern BOOLEAN DoEcho; -extern WORD DosErrorLevel; -extern WORD DosLastError; +extern PDOS_DATA DosData; extern PDOS_SYSVARS SysVars; extern PDOS_SDA Sda; diff --git a/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/memory.c b/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/memory.c index 1e31b2fb941..5b8c1cba29f 100644 --- a/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/memory.c +++ b/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/memory.c @@ -77,7 +77,7 @@ WORD DosAllocateMemory(WORD Size, WORD *MaxAvailable) /* Make sure it's valid */ if (CurrentMcb->BlockType != 'M' && CurrentMcb->BlockType != 'Z') { - DPRINT("The DOS memory arena is corrupted!\n"); + DPRINT1("The DOS memory arena is corrupted!\n"); Sda->LastErrorCode = ERROR_ARENA_TRASHED; return 0; } @@ -94,7 +94,7 @@ WORD DosAllocateMemory(WORD Size, WORD *MaxAvailable) /* Check if this block is big enough */ if (CurrentMcb->Size < Size) goto Next; - switch (Sda->AllocStrategy & 0x3F) + switch (Sda->AllocStrategy & ~(DOS_ALLOC_HIGH | DOS_ALLOC_HIGH_LOW)) { case DOS_ALLOC_FIRST_FIT: { @@ -159,7 +159,7 @@ Done: if (CurrentMcb->Size > Size) { /* It is, split it into two blocks */ - if ((Sda->AllocStrategy & 0x3F) != DOS_ALLOC_LAST_FIT) + if ((Sda->AllocStrategy & ~(DOS_ALLOC_HIGH | DOS_ALLOC_HIGH_LOW)) != DOS_ALLOC_LAST_FIT) { PDOS_MCB NextMcb = SEGMENT_TO_MCB(Result + Size + 1); diff --git a/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/memory.h b/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/memory.h index bf3e61ae965..76ac6e2c8db 100644 --- a/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/memory.h +++ b/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/memory.h @@ -29,6 +29,7 @@ typedef struct _DOS_MCB BYTE Unused[3]; CHAR Name[8]; } DOS_MCB, *PDOS_MCB; +C_ASSERT(sizeof(DOS_MCB) == 0x10); #pragma pack(pop) /* VARIABLES ******************************************************************/ diff --git a/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/process.c b/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/process.c index 1a257420086..46c77c6f0a1 100644 --- a/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/process.c +++ b/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/process.c @@ -166,7 +166,7 @@ VOID DosClonePsp(WORD DestSegment, WORD SourceSegment) LPDWORD IntVecTable = (LPDWORD)((ULONG_PTR)BaseAddress); /* Literally copy the PSP first */ - RtlCopyMemory(DestPsp, SourcePsp, sizeof(DOS_PSP)); + RtlCopyMemory(DestPsp, SourcePsp, sizeof(*DestPsp)); /* Save the interrupt vectors */ DestPsp->TerminateAddress = IntVecTable[0x22]; @@ -222,7 +222,8 @@ VOID DosCreatePsp(WORD Segment, WORD ProgramSize) PspBlock->HandleTablePtr = MAKELONG(0x18, Segment); /* Set the DOS version */ - PspBlock->DosVersion = DOS_VERSION; + // FIXME: This is here that SETVER stuff enters into action! + PspBlock->DosVersion = DosData->DosVersion; /* Set the far call opcodes */ PspBlock->FarCall[0] = 0xCD; // int 0x21 @@ -377,16 +378,20 @@ DWORD DosLoadExecutable(IN DOS_EXEC_TYPE LoadType, /* If no optional environment is given... */ if (Environment == NULL) { - /* ... get the one from the parameter block */ ASSERT(Parameters); - Environment = (LPCSTR)SEG_OFF_TO_PTR(Parameters->Environment, 0); + /* ... get the one from the parameter block (if not NULL)... */ + if (Parameters->Environment) + Environment = (LPCSTR)SEG_OFF_TO_PTR(Parameters->Environment, 0); + /* ... or the one from the parent (otherwise) */ + else + Environment = (LPCSTR)SEG_OFF_TO_PTR(SEGMENT_TO_PSP(Sda->CurrentPsp)->EnvBlock, 0); } /* Copy the environment block to DOS memory */ EnvBlock = DosCopyEnvironmentBlock(Environment, ExecutablePath); if (EnvBlock == 0) { - Result = ERROR_NOT_ENOUGH_MEMORY; + Result = Sda->LastErrorCode; goto Cleanup; } } @@ -431,7 +436,6 @@ DWORD DosLoadExecutable(IN DOS_EXEC_TYPE LoadType, /* Try to allocate that much memory */ Segment = DosAllocateMemory((WORD)TotalSize, &MaxAllocSize); - if (Segment == 0) { /* Check if there's at least enough memory for the minimum size */ @@ -460,8 +464,10 @@ DWORD DosLoadExecutable(IN DOS_EXEC_TYPE LoadType, SEGMENT_TO_PSP(Segment)->EnvBlock = EnvBlock; /* Calculate the segment where the program should be loaded */ - if (!LoadHigh) LoadSegment = Segment + (sizeof(DOS_PSP) >> 4); - else LoadSegment = Segment + TotalSize - BaseSize; + if (!LoadHigh) + LoadSegment = Segment + (sizeof(DOS_PSP) >> 4); + else + LoadSegment = Segment + TotalSize - BaseSize; RelocFactor = LoadSegment; } diff --git a/reactos/subsystems/mvdm/ntvdm/dos/mouse32.c b/reactos/subsystems/mvdm/ntvdm/dos/mouse32.c index 9e8e081df87..7f8580ba810 100644 --- a/reactos/subsystems/mvdm/ntvdm/dos/mouse32.c +++ b/reactos/subsystems/mvdm/ntvdm/dos/mouse32.c @@ -1025,11 +1025,15 @@ BOOLEAN DosMouseInitialize(VOID) VOID DosMouseCleanup(VOID) { + if (DriverState.ShowCount > 0) EraseMouseCursor(); + DosMouseDisable(); + /* Restore the old mouse service interrupt handler */ ((PDWORD)BaseAddress)[DOS_MOUSE_INTERRUPT] = OldIntHandler; - if (DriverState.ShowCount > 0) EraseMouseCursor(); - DosMouseDisable(); + DosFreeMemory(MouseDataSegment); + MouseDataSegment = 0; + MouseData = 0; } /* EOF */ diff --git a/reactos/subsystems/mvdm/ntvdm/hardware/cmos.c b/reactos/subsystems/mvdm/ntvdm/hardware/cmos.c index ed72a507a5e..390c1d26b75 100644 --- a/reactos/subsystems/mvdm/ntvdm/hardware/cmos.c +++ b/reactos/subsystems/mvdm/ntvdm/hardware/cmos.c @@ -454,7 +454,7 @@ VOID CmosInitialize(VOID) OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); - DPRINT1("CMOS opening %s ; GetLastError() = %u\n", hCmosRam != INVALID_HANDLE_VALUE ? "succeeded" : "failed", GetLastError()); + DPRINT1("CMOS opening %s (Error: %u)\n", hCmosRam != INVALID_HANDLE_VALUE ? "succeeded" : "failed", GetLastError()); if (hCmosRam != INVALID_HANDLE_VALUE) { @@ -469,7 +469,7 @@ VOID CmosInitialize(VOID) DPRINT1("Invalid CMOS file, read bytes %u, expected bytes %u\n", CmosSize, sizeof(CmosMemory)); RtlZeroMemory(&CmosMemory, sizeof(CmosMemory)); } - DPRINT1("CMOS loading %s ; GetLastError() = %u\n", Success ? "succeeded" : "failed", GetLastError()); + DPRINT1("CMOS loading %s (Error: %u)\n", Success ? "succeeded" : "failed", GetLastError()); SetFilePointer(hCmosRam, 0, NULL, FILE_BEGIN); } diff --git a/reactos/subsystems/mvdm/ntvdm/ntvdm.c b/reactos/subsystems/mvdm/ntvdm/ntvdm.c index 7a00543d760..ac247dbb538 100644 --- a/reactos/subsystems/mvdm/ntvdm/ntvdm.c +++ b/reactos/subsystems/mvdm/ntvdm/ntvdm.c @@ -127,7 +127,7 @@ VdmMenuExists(HMENU hConsoleMenu) { if (GetMenuItemID(hConsoleMenu, i) == ID_SHOWHIDE_MOUSE) { - /* set VdmMenuPos to the position of the existing menu */ + /* Set VdmMenuPos to the position of the existing menu */ VdmMenuPos = i - 1; return TRUE; } @@ -225,7 +225,7 @@ static VOID EnableExtraHardware(HANDLE ConsoleInput) /* PUBLIC FUNCTIONS ***********************************************************/ VOID -DisplayMessage(LPCWSTR Format, ...) +DisplayMessage(IN LPCWSTR Format, ...) { #ifndef WIN2K_COMPLIANT WCHAR StaticBuffer[256]; @@ -242,11 +242,12 @@ DisplayMessage(LPCWSTR Format, ...) /* * 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 = _vscwprintf(Format, Parameters) + 1; // NULL-terminated - if (MsgLen > ARRAYSIZE(StaticBuffer)) + MsgLen = _vscwprintf(Format, Parameters); + if (MsgLen >= ARRAYSIZE(StaticBuffer)) { - Buffer = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, MsgLen * sizeof(WCHAR)); + Buffer = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, (MsgLen + 1) * sizeof(WCHAR)); if (Buffer == NULL) { /* Allocation failed, use the static buffer and display a suitable error message */ @@ -256,11 +257,15 @@ DisplayMessage(LPCWSTR Format, ...) } } #else - MsgLen = ARRAYSIZE(Buffer); + MsgLen = ARRAYSIZE(Buffer) - 1; #endif - /* Display the message */ + RtlZeroMemory(Buffer, (MsgLen + 1) * sizeof(WCHAR)); _vsnwprintf(Buffer, MsgLen, Format, Parameters); + + va_end(Parameters); + + /* Display the message */ DPRINT1("\n\nNTVDM Subsystem\n%S\n\n", Buffer); MessageBoxW(NULL, Buffer, L"NTVDM Subsystem", MB_OK); @@ -268,8 +273,6 @@ DisplayMessage(LPCWSTR Format, ...) /* Free the buffer if needed */ if (Buffer != StaticBuffer) RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer); #endif - - va_end(Parameters); } static BOOL diff --git a/reactos/subsystems/mvdm/ntvdm/ntvdm.h b/reactos/subsystems/mvdm/ntvdm/ntvdm.h index f5f774d2fa5..08044dd77b3 100644 --- a/reactos/subsystems/mvdm/ntvdm/ntvdm.h +++ b/reactos/subsystems/mvdm/ntvdm/ntvdm.h @@ -75,7 +75,7 @@ extern WCHAR** NtVdmArgv; /* * Interface functions */ -VOID DisplayMessage(LPCWSTR Format, ...); +VOID DisplayMessage(IN LPCWSTR Format, ...); /*static*/ VOID CreateVdmMenu(HANDLE ConOutHandle); -- 2.17.1