mirror of
https://github.com/reactos/reactos.git
synced 2025-02-23 17:05:46 +00:00
[NTVDM]
- Move some #defines into their correct headers. - Fix some DPRINTs. - Add missing DOS SYSVars values (memory-related), confirmed by DOS undocumented & FreeDOS. - Implement INT 21h, AX=5700h and 5701h "Get/Set File last-written date & time". - Implement INT 2Fh, AH=13h "Set Disk Interrupt Handler" chain support, which is an obscure functionality (to make story short: allows inserting disk filter drivers): see the comments inside the code (dos.c/dos.h) for more information. svn path=/trunk/; revision=68418
This commit is contained in:
parent
7d277c43a9
commit
3d9861826c
4 changed files with 209 additions and 22 deletions
|
@ -785,10 +785,10 @@ VOID WINAPI DosInt21h(LPWORD Stack)
|
|||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
default: // goto Default;
|
||||
{
|
||||
DPRINT1("INT 21h, AH = 33h, subfunction AL = %Xh NOT IMPLEMENTED\n",
|
||||
getAL());
|
||||
DPRINT1("INT 21h, AH = %02Xh, subfunction AL = %02Xh NOT IMPLEMENTED\n",
|
||||
getAH(), getAL());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1512,6 +1512,110 @@ VOID WINAPI DosInt21h(LPWORD Stack)
|
|||
break;
|
||||
}
|
||||
|
||||
/* File Attributes */
|
||||
case 0x57:
|
||||
{
|
||||
switch (getAL())
|
||||
{
|
||||
/* Get File's last-written Date and Time */
|
||||
case 0x00:
|
||||
{
|
||||
PDOS_FILE_DESCRIPTOR Descriptor = DosGetHandleFileDescriptor(getBX());
|
||||
FILETIME LastWriteTime;
|
||||
WORD FileDate, FileTime;
|
||||
|
||||
if (Descriptor == NULL)
|
||||
{
|
||||
/* Invalid handle */
|
||||
Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
|
||||
// Sda->LastErrorCode = ERROR_INVALID_HANDLE;
|
||||
setAX(ERROR_INVALID_HANDLE);
|
||||
break;
|
||||
}
|
||||
|
||||
if (Descriptor->DeviceInfo & FILE_INFO_DEVICE)
|
||||
{
|
||||
/* Invalid for devices */
|
||||
Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
|
||||
// setAX(ERROR_INVALID_FUNCTION);
|
||||
setAX(ERROR_INVALID_HANDLE);
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Retrieve the last-written Win32 date and time,
|
||||
* and convert it to DOS format.
|
||||
*/
|
||||
if (!GetFileTime(Descriptor->Win32Handle,
|
||||
NULL, NULL, &LastWriteTime) ||
|
||||
!FileTimeToDosDateTime(&LastWriteTime,
|
||||
&FileDate, &FileTime))
|
||||
{
|
||||
Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
|
||||
setAX(GetLastError());
|
||||
break;
|
||||
}
|
||||
|
||||
Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
|
||||
setCX(FileTime);
|
||||
setDX(FileDate);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Set File's last-written Date and Time */
|
||||
case 0x01:
|
||||
{
|
||||
PDOS_FILE_DESCRIPTOR Descriptor = DosGetHandleFileDescriptor(getBX());
|
||||
FILETIME LastWriteTime;
|
||||
WORD FileDate = getDX();
|
||||
WORD FileTime = getCX();
|
||||
|
||||
if (Descriptor == NULL)
|
||||
{
|
||||
/* Invalid handle */
|
||||
Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
|
||||
// Sda->LastErrorCode = ERROR_INVALID_HANDLE;
|
||||
setAX(ERROR_INVALID_HANDLE);
|
||||
break;
|
||||
}
|
||||
|
||||
if (Descriptor->DeviceInfo & FILE_INFO_DEVICE)
|
||||
{
|
||||
/* Invalid for devices */
|
||||
Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
|
||||
// setAX(ERROR_INVALID_FUNCTION);
|
||||
setAX(ERROR_INVALID_HANDLE);
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert the new last-written DOS date and time
|
||||
* to Win32 format and set it.
|
||||
*/
|
||||
if (!DosDateTimeToFileTime(FileDate, FileTime,
|
||||
&LastWriteTime) ||
|
||||
!SetFileTime(Descriptor->Win32Handle,
|
||||
NULL, NULL, &LastWriteTime))
|
||||
{
|
||||
Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
|
||||
setAX(GetLastError());
|
||||
break;
|
||||
}
|
||||
|
||||
Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
|
||||
break;
|
||||
}
|
||||
|
||||
default: // goto Default;
|
||||
{
|
||||
DPRINT1("INT 21h, AH = %02Xh, subfunction AL = %02Xh NOT IMPLEMENTED\n",
|
||||
getAH(), getAL());
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
/* Get/Set Memory Management Options */
|
||||
case 0x58:
|
||||
{
|
||||
|
@ -1748,10 +1852,10 @@ VOID WINAPI DosInt21h(LPWORD Stack)
|
|||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
default: // goto Default;
|
||||
{
|
||||
DPRINT1("INT 21h, AH = 5Dh, subfunction AL = %Xh NOT IMPLEMENTED\n",
|
||||
getAL());
|
||||
DPRINT1("INT 21h, AH = %02Xh, subfunction AL = %02Xh NOT IMPLEMENTED\n",
|
||||
getAH(), getAL());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1833,10 +1937,10 @@ VOID WINAPI DosInt21h(LPWORD Stack)
|
|||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
default: // goto Default;
|
||||
{
|
||||
DPRINT1("INT 21h, AH = 65h, subfunction AL = %Xh NOT IMPLEMENTED\n",
|
||||
getAL());
|
||||
DPRINT1("INT 21h, AH = %02Xh, subfunction AL = %02Xh NOT IMPLEMENTED\n",
|
||||
getAH(), getAL());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1926,9 +2030,9 @@ VOID WINAPI DosInt21h(LPWORD Stack)
|
|||
}
|
||||
|
||||
/* Unsupported */
|
||||
default:
|
||||
default: // Default:
|
||||
{
|
||||
DPRINT1("DOS Function INT 0x21, AH = %xh, AL = %xh NOT IMPLEMENTED!\n",
|
||||
DPRINT1("DOS Function INT 21h, AH = %02Xh, AL = %02Xh NOT IMPLEMENTED!\n",
|
||||
getAH(), getAL());
|
||||
|
||||
setAL(0); // Some functions expect AL to be 0 when it's not supported.
|
||||
|
@ -2091,6 +2195,28 @@ VOID WINAPI DosInt2Fh(LPWORD Stack)
|
|||
break;
|
||||
}
|
||||
|
||||
/* Set Disk Interrupt Handler */
|
||||
case 0x13:
|
||||
{
|
||||
/* Save the old values of PrevInt13 and RomBiosInt13 */
|
||||
ULONG OldInt13 = DosData->PrevInt13;
|
||||
ULONG OldBiosInt13 = DosData->RomBiosInt13;
|
||||
|
||||
/* Set PrevInt13 and RomBiosInt13 to their new values */
|
||||
DosData->PrevInt13 = MAKELONG(getDX(), getDS());
|
||||
DosData->RomBiosInt13 = MAKELONG(getBX(), getES());
|
||||
|
||||
/* Return in DS:DX the old value of PrevInt13 */
|
||||
setDS(HIWORD(OldInt13));
|
||||
setDX(LOWORD(OldInt13));
|
||||
|
||||
/* Return in DS:DX the old value of RomBiosInt13 */
|
||||
setES(HIWORD(OldBiosInt13));
|
||||
setBX(LOWORD(OldBiosInt13));
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
/* Mostly Windows 2.x/3.x/9x support */
|
||||
case 0x16:
|
||||
{
|
||||
|
@ -2127,7 +2253,7 @@ VOID WINAPI DosInt2Fh(LPWORD Stack)
|
|||
}
|
||||
|
||||
default:
|
||||
DPRINT1("Unknown DOS XMS Function: INT 0x2F, AH = 43h, AL = %xh\n", getAL());
|
||||
DPRINT1("Unknown DOS XMS Function: INT 2Fh, AH = 43h, AL = %02Xh\n", getAL());
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -2136,7 +2262,7 @@ VOID WINAPI DosInt2Fh(LPWORD Stack)
|
|||
|
||||
default: Default:
|
||||
{
|
||||
DPRINT1("DOS Internal System Function INT 0x2F, AH = %xh, AL = %xh NOT IMPLEMENTED!\n",
|
||||
DPRINT1("DOS Internal System Function INT 2Fh, AH = %02Xh, AL = %02Xh NOT IMPLEMENTED!\n",
|
||||
getAH(), getAL());
|
||||
Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
|
||||
}
|
||||
|
@ -2315,12 +2441,37 @@ BOOLEAN DosKRNLInitialize(VOID)
|
|||
/* Unimplemented DOS interrupts */
|
||||
RegisterDosInt32(0x2A, DosInt2Ah); // DOS Critical Sections / Network
|
||||
// RegisterDosInt32(0x2E, NULL); // COMMAND.COM "Reload Transient"
|
||||
// COMMAND.COM adds support for INT 2Fh, AX=AE00h and AE01h "Installable Command - Installation Check & Execute"
|
||||
// COMMAND.COM adds support for INT 2Fh, AX=5500h "COMMAND.COM Interface"
|
||||
|
||||
/* Reserved DOS interrupts */
|
||||
RegisterDosInt32(0x2B, NULL);
|
||||
RegisterDosInt32(0x2C, NULL);
|
||||
RegisterDosInt32(0x2D, NULL);
|
||||
|
||||
/*
|
||||
* Initialize the INT 13h (BIOS Disk Services) handler chain support.
|
||||
*
|
||||
* The INT 13h handler chain is some functionality that allows DOS
|
||||
* to insert disk filter drivers in between the (hooked) INT 13h handler
|
||||
* and its original handler.
|
||||
* Typically, those are:
|
||||
* - filter for detecting disk changes (for floppy disks),
|
||||
* - filter for tracking formatting calls and correcting DMA boundary errors,
|
||||
* - a possible filter to work around a bug in a particular version of PC-AT's
|
||||
* IBM's ROM BIOS (on systems with model byte FCh and BIOS date "01/10/84" only)
|
||||
* (see http://www.ctyme.com/intr/rb-4453.htm for more details).
|
||||
*
|
||||
* This functionality is known to be used by some legitimate programs,
|
||||
* by Windows 3.x, as well as some illegitimate ones (aka. virii).
|
||||
*
|
||||
* See extra information about this support in dos.h
|
||||
*/
|
||||
// FIXME: Should be done by the DOS BIOS
|
||||
DosData->RomBiosInt13 = ((PULONG)BaseAddress)[0x13];
|
||||
DosData->PrevInt13 = DosData->RomBiosInt13;
|
||||
// RegisterDosInt32(0x13, DosInt13h); // Unused at the moment!
|
||||
|
||||
/* Initialize country data */
|
||||
DosCountryInitialize();
|
||||
|
||||
|
|
|
@ -26,8 +26,7 @@
|
|||
|
||||
#define DOS_CONFIG_PATH L"%SystemRoot%\\system32\\CONFIG.NT"
|
||||
#define DOS_COMMAND_INTERPRETER L"%SystemRoot%\\system32\\COMMAND.COM /k %SystemRoot%\\system32\\AUTOEXEC.NT"
|
||||
#define FIRST_MCB_SEGMENT 0x1000
|
||||
#define USER_MEMORY_SIZE (0x9FFE - FIRST_MCB_SEGMENT)
|
||||
|
||||
#define SYSTEM_PSP 0x08
|
||||
#define SYSTEM_ENV_BLOCK 0x800
|
||||
#define DOS_CODE_SEGMENT 0x70
|
||||
|
@ -41,17 +40,10 @@
|
|||
#define DOS_ERROR_HANDLE 2
|
||||
|
||||
#define DOS_SFT_SIZE 255
|
||||
#define UMB_START_SEGMENT 0xC000
|
||||
#define UMB_END_SEGMENT 0xDFFF
|
||||
#define DOS_ALLOC_HIGH 0x40
|
||||
#define DOS_ALLOC_HIGH_LOW 0x80
|
||||
#define DOS_DIR_LENGTH 64
|
||||
#define NUM_DRIVES ('Z' - 'A' + 1)
|
||||
#define DOS_CHAR_ATTRIBUTE 0x07
|
||||
|
||||
/* 16 MB of EMS memory */
|
||||
#define EMS_TOTAL_PAGES 1024
|
||||
|
||||
#pragma pack(push, 1)
|
||||
|
||||
typedef struct _DOS_FCB
|
||||
|
@ -99,6 +91,11 @@ typedef struct _DOS_SYSVARS
|
|||
BYTE BootDrive; // 0x43
|
||||
BYTE UseDwordMoves; // 0x44
|
||||
WORD ExtMemSize; // 0x45
|
||||
BYTE Reserved4[0x1C]; // 0x47
|
||||
BYTE ChainUMB; // 0x63 - 0/1: UMB chain (un)linked to MCB chain
|
||||
WORD Reserved5; // 0x64
|
||||
WORD UMBChainStart; // 0x66 - Segment of the first UMB MCB
|
||||
WORD MemAllocScanStart; // 0x68 - Segment where allocation scan starts
|
||||
} DOS_SYSVARS, *PDOS_SYSVARS;
|
||||
|
||||
typedef struct _DOS_CLOCK_TRANSFER_RECORD
|
||||
|
@ -235,6 +232,33 @@ typedef struct _DOS_SDA
|
|||
|
||||
typedef struct _DOS_DATA
|
||||
{
|
||||
/*
|
||||
* INT 13h (BIOS Disk Services) handler chain support.
|
||||
*
|
||||
* RomBiosInt13: The original INT 13h vector (normally from ROM BIOS).
|
||||
* PrevInt13 : The previous INT 13h vector in the handler chain (initially
|
||||
* initialized with the RomBiosInt13 value; each time some
|
||||
* program calls INT 2Fh, AH=13h, PrevInt13 is updated).
|
||||
*
|
||||
* DOS hooks INT 13h with its own code, then (in normal circumstances) calls
|
||||
* PrevInt13, so that when a program calls INT 13h, the DOS hook is first called,
|
||||
* followed by the previous INT 13h (be it the original or some other hooked one).
|
||||
* DOS may call PrevInt13 directly in some internal operations too.
|
||||
* RomBiosInt13 is intended to be the original INT 13h vector that existed
|
||||
* before DOS was loaded. A particular version of PC-AT's IBM's ROM BIOS
|
||||
* (on systems with model byte FCh and BIOS date "01/10/84" only, see
|
||||
* http://www.ctyme.com/intr/rb-4453.htm for more details) had a bug on disk
|
||||
* reads so that it was patched by DOS, and therefore PrevInt13 was the fixed
|
||||
* INT 13 interrupt (for the other cases, a direct call to RomBiosInt13 is done).
|
||||
*
|
||||
* NOTE: For compatibility with some programs (including virii), PrevInt13 should
|
||||
* be at 0070:00B4, see for more details:
|
||||
* http://repo.hackerzvoice.net/depot_madchat/vxdevl/vdat/tuvd0001.htm
|
||||
* http://vxheaven.org/lib/vsm01.html
|
||||
*/
|
||||
DWORD RomBiosInt13;
|
||||
DWORD PrevInt13; // FIXME: Put it at 0070:00B4
|
||||
|
||||
DOS_SYSVARS SysVars;
|
||||
BYTE NullDriverRoutine[7];
|
||||
WORD DosVersion; // DOS version to report to programs (can be different from the true one)
|
||||
|
|
|
@ -19,6 +19,9 @@
|
|||
#define EMS_PAGE_SIZE (1 << EMS_PAGE_BITS)
|
||||
#define EMS_PHYSICAL_PAGES 4
|
||||
|
||||
/* 16 MB of EMS memory */
|
||||
#define EMS_TOTAL_PAGES 1024
|
||||
|
||||
#define EMS_STATUS_OK 0x00
|
||||
#define EMS_STATUS_INTERNAL_ERROR 0x80
|
||||
#define EMS_STATUS_INVALID_HANDLE 0x83
|
||||
|
|
|
@ -13,6 +13,15 @@
|
|||
|
||||
#define SEGMENT_TO_MCB(seg) ((PDOS_MCB)SEG_OFF_TO_PTR((seg), 0))
|
||||
|
||||
#define FIRST_MCB_SEGMENT 0x1000
|
||||
#define USER_MEMORY_SIZE (0x9FFE - FIRST_MCB_SEGMENT)
|
||||
|
||||
#define UMB_START_SEGMENT 0xC000
|
||||
#define UMB_END_SEGMENT 0xDFFF
|
||||
|
||||
#define DOS_ALLOC_HIGH 0x40
|
||||
#define DOS_ALLOC_HIGH_LOW 0x80
|
||||
|
||||
enum DOS_ALLOC_STRATEGY
|
||||
{
|
||||
DOS_ALLOC_FIRST_FIT,
|
||||
|
|
Loading…
Reference in a new issue