|
|
/*++
Copyright (c) 1992 Microsoft Corporation
Module Name:
Int21Map.c
Abstract:
This module performs int 21 API translation for dpmi
Author:
Dave Hastings (daveh) 23-Nov-1992
Revision History:
Neil Sandlin (neilsa) 31-Jul-1995 - Updates for the 486 emulator
--*/ #include "precomp.h"
#pragma hdrstop
#include "int21map.h"
#include "softpc.h"
#include "xlathlp.h"
//
// Local constants
//
//#define Verbose 1
#define MAX_SUPPORTED_DOS_CALL 0x6d
#define DosxTranslated NULL
typedef VOID (*APIXLATFUNCTION)(VOID); APIXLATFUNCTION ApiXlatTable[MAX_SUPPORTED_DOS_CALL] = {
DosxTranslated , // 00h - Terminate process
NoTranslation , // 01h - Char input with echo
NoTranslation , // 02h - Character output
NoTranslation , // 03h - Auxiliary input
NoTranslation , // 04h - Auxiliary output
NoTranslation , // 05h - Print character
NoTranslation , // 06h - Direct console I/O
NoTranslation , // 07h - Unfiltered char input
NoTranslation , // 08h - Char input w/o echo
DisplayString , // 09h - Display "$" term string
BufferedKeyboardInput , // 0Ah - Buffered keyboard input
NoTranslation , // 0Bh - Check keyboard status
FlushBuffReadKbd , // 0Ch - Flush buff, Read kbd
NoTranslation , // 0Dh - Disk reset
NoTranslation , // 0Eh - Select disk
NotSupportedFCB , // 0Fh * Open file with FCB
NotSupportedFCB , // 10h * Close file with FCB
FindFileFCB , // 11h - Find First File
FindFileFCB , // 12h - Find Next File
MapFCB , // 13h - Delete File
NotSupportedFCB , // 14h * Sequential Read
NotSupportedFCB , // 15h * Sequential Write
NotSupportedFCB , // 16h * Create File With FCB
RenameFCB , // 17h - Rename File With FCB
NoTranslation , // 18h - UNUSED
NoTranslation , // 19h - Get Current Disk
SetDTA , // 1Ah - Set DTA Address
GetDriveData , // 1Bh - Get Default Drive Data
GetDriveData , // 1Ch - Get Drive Data
NoTranslation , // 1Dh - UNUSED
NoTranslation , // 1Eh - UNUSED
GetDriveData , // 1Fh - Get Drive Parameter Blk
NoTranslation , // 20h - UNUSED
NotSupportedFCB , // 21h * Random Read
NotSupportedFCB , // 22h * Random Write
NotSupportedFCB , // 23h * Get File Size
NotSupportedFCB , // 24h * Set Relative Record
SetVector , // 25h - Set interrupt vector
CreatePSP , // 26h - Create PSP
NotSupportedFCB , // 27h * Random block read
NotSupportedFCB , // 28h * Random block write
ParseFilename , // 29h - Parse filename
GetDate , // 2Ah - Get date
NoTranslation , // 2Bh - Set date
NoTranslation , // 2Ch - Get time
NoTranslation , // 2Dh - Set time
NoTranslation , // 2Eh - Set/Reset verify flag
GetDTA , // 2Fh - Get DTA address
NoTranslation , // 30h - Get DOS version
TSR , // 31h - Terminate and Stay Res
GetDevParamBlock , // 32h - Get device parameter blk
NoTranslation , // 33h - Get/Set Control-C Flag
ReturnESBX , // 34h - Get Address of InDOS
GetVector , // 35h - Get Interrupt Vector
NoTranslation , // 36h - Get Disk Free Space
NoTranslation , // 37h - Char Oper
GetSetCountry , // 38h - Get/Set Current Country
MapASCIIZDSDX , // 39h - Create Directory
MapASCIIZDSDX , // 3Ah - Remove Directory
MapASCIIZDSDX , // 3Bh - Change Current Directory
MapASCIIZDSDX , // 3Ch - Create File with Handle
MapASCIIZDSDX , // 3Dh - Open File with Handle
NoTranslation , // 3Eh - Close File with Handle
ReadWriteFile , // 3Fh - Read File or Device
ReadWriteFile , // 40h - Write File or Device
MapASCIIZDSDX , // 41h - Delete File
NoTranslation , // 42h - Move file pointer
MapASCIIZDSDX , // 43h - Get/Set File Attributes
IOCTL , // 44h - IOCTL
NoTranslation , // 45h - Duplicate File Handle
NoTranslation , // 46h - Force Duplicate Handle
GetCurDir , // 47h - Get Current Directory
AllocateMemoryBlock , // 48h - Allocate Memory Block
FreeMemoryBlock , // 49h - Free Memory Block
ResizeMemoryBlock , // 4Ah - Resize Memory Block
LoadExec , // 4Bh - Load and Exec Program
DosxTranslated , // 4Ch - Terminate with Ret Code
NoTranslation , // 4Dh - Get Ret Code Child Proc
FindFirstFileHandle , // 4Eh - Find First File
FindNextFileHandle , // 4Fh - Find Next File
SetPSP , // 50h - Set PSP Segment
GetPSP , // 51h - Get PSP Segment
ReturnESBX , // 52h - Get List of Lists (invars)
TranslateBPB , // 53h - Translate BPB
NoTranslation , // 54h - Get Verify Flag
CreatePSP , // 55h - Create PSP
RenameFile , // 56h - Rename File
NoTranslation , // 57h - Get/Set Date/Time File
NoTranslation , // 58h - Get/Set Alloc Strategy
NoTranslation , // 59h - Get Extended Error Info
CreateTempFile , // 5Ah - Create Temporary File
MapASCIIZDSDX , // 5Bh - Create New File
NoTranslation , // 5Ch - Lock/Unlock File Region
Func5Dh , // 5Dh - Server DOS call
Func5Eh , // 5Eh - Net Name/Printer Setup
Func5Fh , // 5Fh - Network redir stuff
NotSupportedBad , // 60h - NameTrans
NoTranslation , // 61h - UNUSED
GetPSP , // 62h - Get PSP Address
#ifdef DBCS
ReturnDSSI , // 63h - Get DBCS Vector
#else
NotSupportedBetter , // 63h - Hangool call
#endif
NotSupportedBad , // 64h - Set Prn Flag
GetExtendedCountryInfo , // 65h - Get Extended Country Info
NoTranslation , // 66h - Get/Set Global Code Page
NoTranslation , // 67h - Set Handle Count
NoTranslation , // 68h - Commit File
NoTranslation , // 69h -
NoTranslation , // 6Ah -
NoTranslation , // 6Bh -
MapASCIIZDSSI // 6Ch - Extended open
};
VOID DpmiXlatInt21Call( VOID ) /*++
Routine Description:
This routine dispatches to the appropriate routine to perform the actual translation of the api
Arguments:
None
Return Value:
None.
--*/ { DECLARE_LocalVdmContext; ULONG DosMajorCode; PUCHAR StackPointer;
//
// Pop ds from stack
//
StackPointer = Sim32GetVDMPointer( ((ULONG)getSS() << 16), 1, TRUE );
StackPointer += (*GetSPRegister)();
setDS(*(PWORD16)StackPointer);
(*SetSPRegister)((*GetSPRegister)() + 2);
DosMajorCode = getAH();
if (DosMajorCode >= MAX_SUPPORTED_DOS_CALL) { return; //bugbug find out what win31 does.
}
if (ApiXlatTable[DosMajorCode]) {
ULONG Eip, Esp; USHORT Cs, Ss;
Eip = getEIP(); Esp = getESP(); Cs = getCS(); Ss = getSS();
(*ApiXlatTable[DosMajorCode])();
setEIP(Eip); setESP(Esp); setCS(Cs); setSS(Ss);
SimulateIret(PASS_CARRY_FLAG_16); }
// put this back in after beta 2.5
DpmiFreeAllBuffers();
}
VOID NoTranslation( VOID ) /*++
Routine Description:
This routine handles int 21 functions which don't need any translation. It simply executes the int 21 in real/v86 mode
Arguments:
None
Return Value:
None.
--*/ { DECLARE_LocalVdmContext;
DpmiSwitchToRealMode(); DPMI_EXEC_INT(0x21); DpmiSwitchToProtectedMode(); }
VOID DisplayString( VOID ) /*++
Routine Description:
This routine translates the int 21 display string function.
N.B. Win 3.1 does this by calling int 21 function 2 repeatedly. We do it this way because Win 3.1 does. If this function is frequently used, we should actually buffer the string and call the dos display string function.
Arguments:
None
Return Value:
None.
--*/ { PUCHAR String; DECLARE_LocalVdmContext; USHORT ClientAX, ClientDX; USHORT ClientDS = getDS();
DpmiSwitchToRealMode();
String = Sim32GetVDMPointer(((ULONG)ClientDS << 16), 1, TRUE) + (*GetDXRegister)();
//
// Repeatedly call int 21 function 2 to display the characters
//
ClientAX = getAX(); ClientDX = getDX(); setAH(2); while (*(String) != '$') { setDL(*(String)); DPMI_EXEC_INT(0x21); String++; } setAX(ClientAX); setDX(ClientDX);
DpmiSwitchToProtectedMode(); }
VOID BufferedKeyboardInput( VOID ) /*++
Routine Description:
This routine performs the tranlation for the int 21 function Ah
Arguments:
None.
Return Value:
None.
--*/ { DECLARE_LocalVdmContext; PUCHAR PmInputBuffer, RmInputBuffer; USHORT BufferSeg, BufferOff, BufferLen; USHORT ClientDX; USHORT ClientDS = getDS();
DpmiSwitchToRealMode(); ClientDX = getDX();
//
// Get a pointer to the PM buffer
//
PmInputBuffer = Sim32GetVDMPointer(((ULONG)ClientDS << 16), 1, TRUE) + (*GetDXRegister)();
//
// Get the buffer length (there are two bytes in addition to the
// buffer)
//
BufferLen = *PmInputBuffer + 2;
//
// Move the buffer to low memory
//
RmInputBuffer = DpmiMapAndCopyBuffer(PmInputBuffer, BufferLen);
//
// Set up the registers for the int 21 call
//
DPMI_FLAT_TO_SEGMENTED(RmInputBuffer, &BufferSeg, &BufferOff); setDS(BufferSeg); setDX(BufferOff);
DPMI_EXEC_INT(0x21);
//
// Copy the data back
//
DpmiUnmapAndCopyBuffer(PmInputBuffer, RmInputBuffer, BufferLen);
setDX(ClientDX); DpmiSwitchToProtectedMode(); setDS(ClientDS);
}
VOID FlushBuffReadKbd( VOID ) /*++
Routine Description:
This routine performs translation for the flush keyboard routines. It calls the appropriate xlat routine.
Arguments:
None.
Return Value:
None.
--*/ { DECLARE_LocalVdmContext;
if (getAL() == 0x0a) { BufferedKeyboardInput(); } else { NoTranslation(); } }
VOID NotSupportedFCB( VOID ) /*++
Routine Description:
This routine does not do any translation. It prints a warning to the debugger
Arguments:
None.
Return Value:
None.
--*/ { #if DBG
DECLARE_LocalVdmContext;
DbgPrint( "WARNING: DOS INT 21 call AH = %x will not be translated.\n", getAH()); DbgPrint( " Protected mode applications should not be using\n"); DbgPrint( " this type of FCB call. Convert this application\n"); DbgPrint( " to use the handle calls.\n" ); #endif
NoTranslation(); }
VOID FindFileFCB( VOID ) /*++
Routine Description:
This function translates the find first/find next FCB calls.
Arguments:
None.
Return Value:
None.
--*/ { DECLARE_LocalVdmContext; PUCHAR FcbAddress, FcbBufferedAddress; USHORT FcbSegment, FcbOffset; USHORT ClientDX; USHORT FcbLength; USHORT ClientDS = getDS();
DpmiSwitchToRealMode(); SetDTAPointers(); ClientDX = getDX();
FcbAddress = Sim32GetVDMPointer(((ULONG)ClientDS << 16), 1, TRUE) + (*GetDXRegister)();
//
// Calculate the size of the FCB
//
FcbLength = DpmiCalcFcbLength(FcbAddress);
//
// Buffer the FCB
//
FcbBufferedAddress = DpmiMapAndCopyBuffer(FcbAddress, FcbLength);
//
// Check to see if we need to set the real dta
//
if (CurrentDosDta != CurrentDta) SetDosDTA();
//
// Make the int 21 call
//
DPMI_FLAT_TO_SEGMENTED(FcbBufferedAddress, &FcbSegment, &FcbOffset); setDS(FcbSegment); setDX(FcbOffset); DPMI_EXEC_INT(0x21);
//
// If the call was successful and the PM dta is in high memory
// copy the dta to high memory
//
if ((getAL() == 0) && (CurrentPmDtaAddress != CurrentDta)) { MoveMemory(CurrentPmDtaAddress, CurrentDta, FcbLength); DpmiUnmapAndCopyBuffer(FcbAddress, FcbBufferedAddress, FcbLength); } else { DpmiUnmapBuffer(FcbBufferedAddress, FcbLength); }
setDX(ClientDX); DpmiSwitchToProtectedMode(); setDS(ClientDS); }
VOID MapFCB( VOID ) /*++
Routine Description:
This routine translates the delete file fcb int 21 call
Arguments:
None.
Return Value:
None.
--*/ { DECLARE_LocalVdmContext; USHORT FcbLength, FcbSegment, FcbOffset; PUCHAR FcbAddress, FcbBufferedAddress; USHORT ClientDX; USHORT ClientDS = getDS();
DpmiSwitchToRealMode(); ClientDX = getDX();
FcbAddress = Sim32GetVDMPointer(((ULONG)ClientDS << 16), 1, TRUE) + (*GetDXRegister)();
//
// Get the length of the FCB
//
FcbLength = DpmiCalcFcbLength(FcbAddress);
//
// Copy the FCB
//
FcbBufferedAddress = DpmiMapAndCopyBuffer(FcbAddress, FcbLength);
//
// Make the int 21 call
//
DPMI_FLAT_TO_SEGMENTED(FcbBufferedAddress, &FcbSegment, &FcbOffset); setDS(FcbSegment); setDX(FcbOffset); DPMI_EXEC_INT(0x21);
//
// Copy the FCB back
//
DpmiUnmapAndCopyBuffer(FcbAddress, FcbBufferedAddress, FcbLength);
//
// Clean up
//
setDX(ClientDX); DpmiSwitchToProtectedMode(); setDS(ClientDS); }
VOID RenameFCB( VOID ) /*++
Routine Description:
This routine translates the rename fcb int 21 function
Arguments:
None.
Return Value:
None.
--*/ { DECLARE_LocalVdmContext; USHORT FcbSegment, FcbOffset; PUCHAR FcbAddress, FcbBufferedAddress; USHORT ClientDX; USHORT ClientDS = getDS();
DpmiSwitchToRealMode(); ClientDX = getDX();
FcbAddress = Sim32GetVDMPointer(((ULONG)ClientDS << 16), 1, TRUE) + (*GetDXRegister)();
//
// Copy the FCB (The fcb for rename is a special format, fixed size)
//
FcbBufferedAddress = DpmiMapAndCopyBuffer(FcbAddress, 0x25);
//
// Make the int 21 call
//
DPMI_FLAT_TO_SEGMENTED(FcbBufferedAddress, &FcbSegment, &FcbOffset); setDS(FcbSegment); setDX(FcbOffset); DPMI_EXEC_INT(0x21);
//
// Copy the FCB back
//
DpmiUnmapAndCopyBuffer(FcbAddress, FcbAddress, 0x25);
//
// Clean up
//
setDX(ClientDX); DpmiSwitchToProtectedMode(); setDS(ClientDS); }
VOID GetDriveData( VOID ) /*++
Routine Description:
Translates the drive data int 21 calls
Arguments:
None.
Return Value:
None.
--*/ { DECLARE_LocalVdmContext; USHORT Selector;
DpmiSwitchToRealMode(); DPMI_EXEC_INT(0x21); Selector = getDS(); DpmiSwitchToProtectedMode();
setDS(SegmentToSelector(Selector, STD_DATA)); (*SetBXRegister)((ULONG)getBX());
}
VOID SetVector( VOID ) /*++
Routine Description:
This function translates int 21 function 25
Arguments:
None.
Return Value:
None.
--*/ { DECLARE_LocalVdmContext;
SetProtectedModeInterrupt(getAL(), getDS(), (*GetDXRegister)(), (USHORT)(Frame32 ? VDM_INT_32 : VDM_INT_16));
}
VOID CreatePSP( VOID ) /*++
Routine Description:
This routine translates the selector to a segment and reflects the calls
Arguments:
None.
Return Value:
None.
--*/ { DECLARE_LocalVdmContext; ULONG Segment; USHORT ClientDX;
DpmiSwitchToRealMode(); ClientDX = getDX();
Segment = SELECTOR_TO_INTEL_LINEAR_ADDRESS(ClientDX);
if (Segment > ONE_MB) { //
// Create PSP doesn't do anything on error
//
} else { setDX((USHORT) (Segment >> 4)); DPMI_EXEC_INT(0x21); }
setDX(ClientDX); DpmiSwitchToProtectedMode();
}
VOID ParseFilename( VOID ) /*++
Routine Description:
This routine translates the int 21 parse filename api
Arguments:
None.
Return Value:
None.
--*/ { DECLARE_LocalVdmContext; USHORT ClientSI, ClientDI, FcbLength, StringOff, Seg, Off; PUCHAR Fcb, BufferedFcb, String, BufferedString; USHORT ClientDS = getDS(); USHORT ClientES = getES();
DpmiSwitchToRealMode(); ClientSI = getSI(); ClientDI = getDI();
Fcb = Sim32GetVDMPointer(((ULONG)ClientES << 16), 1, TRUE) + (*GetDIRegister)();
FcbLength = DpmiCalcFcbLength(Fcb);
BufferedFcb = DpmiMapAndCopyBuffer(Fcb, FcbLength);
String = Sim32GetVDMPointer(((ULONG)ClientDS << 16), 1, TRUE) + (*GetSIRegister)();
BufferedString = DpmiMapAndCopyBuffer(String, 20);
DPMI_FLAT_TO_SEGMENTED(BufferedFcb, &Seg, &Off); setES(Seg); setDI(Off); DPMI_FLAT_TO_SEGMENTED(BufferedString, &Seg, &StringOff); setDS(Seg); setSI(StringOff);
DPMI_EXEC_INT(0x21);
DpmiUnmapAndCopyBuffer(Fcb, BufferedFcb, FcbLength); DpmiUnmapAndCopyBuffer(String, BufferedString, 20);
setDI(ClientDI); setSI(ClientSI + (getSI() - StringOff)); DpmiSwitchToProtectedMode(); setDS(ClientDS); setES(ClientES); }
VOID GetDTA( VOID ) /*++
Routine Description:
This routine returns the current DTA.
Arguments:
None.
Return Value:
None.
--*/ { DECLARE_LocalVdmContext;
//
// Win31 compatibility:
//
// Some hosebag programs set the DTA to a selector that they later free!
// This test makes sure that this does not cause us to crash.
//
if (!SEGMENT_IS_WRITABLE(CurrentDtaSelector)) { CurrentDtaSelector = 0; CurrentDtaOffset = 0; }
setES(CurrentDtaSelector); setBX(CurrentDtaOffset); setCF(0);
}
VOID SetDTA( VOID ) /*++
Routine Description:
This routine sets the PM dta address. If the buffer is usable directly, CurrentDta is set to the translated address. Otherwise, it is set to the dosx dta.
N.B. The Set Dta call is not actually reflected to Dos until a function call is made that actually uses the Dta, e.g. the Find First/Next functions. This techique was implemented to match what is done in Win 3.1.
Arguments:
None.
Return Value:
None.
--*/ { DECLARE_LocalVdmContext; USHORT ClientDX;
ClientDX = getDX(); CurrentDtaOffset = ClientDX; CurrentDtaSelector = getDS();
//
// Make sure real DTA is updated later
//
CurrentDosDta = (PUCHAR) NULL;
}
VOID SetDTAPointers( VOID ) /*++
Routine Description:
This routine sets up the flat address values used elsewhere to reference the current DTA.
N.B. This must be done on every entry to handle function calls because the PM dta may have been GlobalRealloc'd. This may change the base address of the PM selector (which invalidates the flat addresses), but not the selector/offset itself.
Arguments:
None.
Return Value:
None.
--*/ { PUCHAR NewDta;
NewDta = Sim32GetVDMPointer( (CurrentDtaSelector << 16), 1, TRUE );
NewDta += CurrentDtaOffset; CurrentPmDtaAddress = NewDta;
//
// If the new dta is not accessible in v86 mode, use the one
// supplied by Dosx
//
if ((ULONG)(NewDta + 128 - IntelBase) > MAX_V86_ADDRESS) { NewDta = DosxDtaBuffer; }
//
// Update Current DTA information
//
CurrentDta = NewDta; }
VOID SetDosDTA( VOID ) /*++
Routine Description:
This routine is called internally by other functions in this module to reflect a Set Dta call to Dos.
WARNING: The client must be in REAL mode
Arguments:
None.
Return Value:
None.
--*/ { DECLARE_LocalVdmContext; USHORT ClientAX, ClientDX, ClientDS, NewDtaSegment, NewDtaOffset;
ASSERT((getMSW() & MSW_PE) == 0);
ClientAX = getAX(); ClientDX = getDX(); ClientDS = getDS();
DPMI_FLAT_TO_SEGMENTED(CurrentDta, &NewDtaSegment, &NewDtaOffset); setDS(NewDtaSegment); setDX(NewDtaOffset); setAH(0x1a);
DPMI_EXEC_INT(0x21);
setAX(ClientAX); setDX(ClientDX); setDS(ClientDS); CurrentDosDta = CurrentDta;
}
VOID TSR( VOID ) /*++
Routine Description:
This function translates int 21h tsr. Win 3.1 does some magic here. We didn't before and it worked fine. Maybe we will later.
Arguments:
None.
Return Value:
None.
--*/ { NoTranslation(); }
VOID GetDevParamBlock( VOID ) /*++
Routine Description:
This routine translates the Device Parameter Block apis
Arguments:
None.
Return Value:
None.
--*/ { DECLARE_LocalVdmContext; USHORT Selector;
DpmiSwitchToRealMode(); DPMI_EXEC_INT(0x21); Selector = getDS(); DpmiSwitchToProtectedMode();
setDS(SegmentToSelector(Selector, STD_DATA)); (*SetBXRegister)((ULONG)getBX());
}
VOID ReturnESBX( VOID ) /*++
Routine Description:
This function translates api that return information in es:bx
Arguments:
None.
Return Value:
None.
--*/ { DECLARE_LocalVdmContext; USHORT Selector;
DpmiSwitchToRealMode(); DPMI_EXEC_INT(0x21); Selector = getES(); DpmiSwitchToProtectedMode();
(*SetBXRegister)((ULONG)getBX()); setES(SegmentToSelector(Selector, STD_DATA));
}
VOID GetVector( VOID ) /*++
Routine Description:
This function translates int 21 function 35
Arguments:
None.
Return Value:
None.
--*/ { DECLARE_LocalVdmContext; PVDM_INTERRUPTHANDLER Handlers = DpmiInterruptHandlers; USHORT IntNumber = getAL();
setES(Handlers[IntNumber].CsSelector); (*SetBXRegister)(Handlers[IntNumber].Eip);
}
VOID GetSetCountry( VOID ) /*++
Routine Description:
This function translates int 21 function 38
Arguments:
None.
Return Value:
None.
--*/ { DECLARE_LocalVdmContext;
if (getDX() == 0xFFFF) { NoTranslation(); } else {
USHORT ClientDX, Seg, Off; PUCHAR Country, BufferedCountry; USHORT ClientDS = getDS();
DpmiSwitchToRealMode(); ClientDX = getDX();
Country = Sim32GetVDMPointer(((ULONG)ClientDS << 16), 1, TRUE) + (*GetDXRegister)();
BufferedCountry = DpmiMapAndCopyBuffer(Country, 34);
DPMI_FLAT_TO_SEGMENTED(BufferedCountry, &Seg, &Off); setDS(Seg); setDX(Off);
DPMI_EXEC_INT(0x21); DpmiSwitchToProtectedMode();
DpmiUnmapAndCopyBuffer(Country, BufferedCountry, 34);
setDX(ClientDX); setDS(ClientDS); } }
VOID MapASCIIZDSDX( VOID ) /*++
Routine Description:
This routine maps the int 21 functions that pass file names in ds:dx
Arguments:
None.
Return Value:
None.
--*/ { DECLARE_LocalVdmContext; PUCHAR BufferedString; USHORT ClientDX, StringSeg, StringOff, Length; USHORT ClientDS = getDS();
DpmiSwitchToRealMode(); ClientDX = getDX();
BufferedString = DpmiMapString(ClientDS, (GetDXRegister)(), &Length);
DPMI_FLAT_TO_SEGMENTED(BufferedString, &StringSeg, &StringOff); setDS(StringSeg); setDX(StringOff); DPMI_EXEC_INT(0x21); DpmiSwitchToProtectedMode();
DpmiUnmapString(BufferedString, Length); setDX(ClientDX); setDS(ClientDS); }
VOID ReadWriteFile( VOID ) /*++
Routine Description:
This routine translates the read/write file int 21 calls. Large reads are broken down into 4k chunks.
Arguments:
None.
Return Value:
None.
--*/ { DECLARE_LocalVdmContext; USHORT ClientCX, ClientDX, ClientAX, Function, DataSeg, DataOff, BytesToRead; ULONG BytesRead, TotalBytesToRead; PUCHAR ReadWriteData, BufferedData; USHORT ClientDS = getDS();
DpmiSwitchToRealMode();
ClientCX = getCX(); ClientDX = getDX(); Function = getAH(); ClientAX = getAX();
TotalBytesToRead = (*GetCXRegister)(); BytesRead = 0;
ReadWriteData = Sim32GetVDMPointer(((ULONG)ClientDS << 16), 1, TRUE) + (*GetDXRegister)();
// while (TotalBytesToRead != BytesRead) {
do {
if ((TotalBytesToRead - BytesRead) > 1024 * 4) { BytesToRead = 4 * 1024; } else { BytesToRead = (USHORT)(TotalBytesToRead - BytesRead); }
BufferedData = DpmiMapAndCopyBuffer(ReadWriteData, BytesToRead);
DPMI_FLAT_TO_SEGMENTED(BufferedData, &DataSeg, &DataOff); setDS(DataSeg); setDX(DataOff); setCX(BytesToRead); setAX(ClientAX);
DPMI_EXEC_INT(0x21);
if (getCF()) { DpmiUnmapBuffer(BufferedData, BytesToRead); break; }
if (getAX() == 0) { DpmiUnmapBuffer(BufferedData, BytesToRead); break; } else if (getAX() < BytesToRead) { CopyMemory(ReadWriteData, BufferedData, getAX()); DpmiUnmapBuffer(BufferedData, BytesToRead); BytesRead += getAX(); break; } else { DpmiUnmapAndCopyBuffer( ReadWriteData, BufferedData, BytesToRead ); }
ReadWriteData += getAX(); BytesRead += getAX(); // }
} while (TotalBytesToRead != BytesRead); setDX(ClientDX); setCX(ClientCX); if (!getCF()) { (*SetAXRegister)(BytesRead); } DpmiSwitchToProtectedMode(); setDS(ClientDS); }
#define MAX_SUPPORTED_DOS_IOCTL_CALL 0x10
//
// Note: The translations here differ from those in the windows dpmi vxd,
// because we do not have to lock memory, and we don't support block
// device drivers.
//
APIXLATFUNCTION IOCTLXlatTable[MAX_SUPPORTED_DOS_IOCTL_CALL] = { NoTranslation , // 00 - Get Device Data
NoTranslation , // 01 - Set Device Data
MapDSDXLenCX , // 02 - Receive Ctrl Chr Data
MapDSDXLenCX , // 03 - Send Ctrl Chr Data
MapDSDXLenCX , // 04 - Receive Ctrl Block Data
MapDSDXLenCX , // 05 - Send Ctrl Block Data
NoTranslation , // 06 - Check Input Status
NoTranslation , // 07 - Check Output Status
NoTranslation , // 08 - Check Block Dev Removable
NoTranslation , // 09 - Check Block Dev Remote
NoTranslation , // 0A - Check if Handle Remote
NoTranslation , // 0B - Change sharing retry cnt
IOCTLMap2Bytes , // 0C - MAP DS:DX LENGTH 2!
IOCTLBlockDevs , // 0D - Generic IOCTL to blk dev
NoTranslation , // 0E - Get Logical Drive Map
NoTranslation // 0F - Set Logical Drive Map
};
VOID IOCTL( VOID ) /*++
Routine Description:
This function translates the int 21 ioctl function.
Arguments:
None.
Return Value:
None.
--*/ { DECLARE_LocalVdmContext; USHORT IoctlMinor;
IoctlMinor = getAL();
if (IoctlMinor >= MAX_SUPPORTED_DOS_IOCTL_CALL) { #if DBG
OutputDebugString("DPMI: IOCTL DOS CALL NOT SUPPORTED\n"); #endif
NoTranslation(); return; }
(*IOCTLXlatTable[IoctlMinor])(); }
VOID GetCurDir( VOID ) /*++
Routine Description:
This routine translates the get current directory call
Arguments:
None.
Return Value:
None.
--*/ { DECLARE_LocalVdmContext; PUCHAR DirInfo, BufferedDirInfo; USHORT ClientSI, Seg, Off; USHORT ClientDS = getDS();
DpmiSwitchToRealMode(); ClientSI = getSI();
DirInfo = Sim32GetVDMPointer(((ULONG)ClientDS << 16), 1, TRUE) + (*GetSIRegister)();
BufferedDirInfo = DpmiMapAndCopyBuffer(DirInfo, 64); DPMI_FLAT_TO_SEGMENTED(BufferedDirInfo, &Seg, &Off); setDS(Seg); setSI(Off);
DPMI_EXEC_INT(0x21); DpmiSwitchToProtectedMode();
DpmiUnmapAndCopyBuffer(DirInfo, BufferedDirInfo, 64); setSI(ClientSI); setDS(ClientDS); }
VOID AllocateMemoryBlock( VOID ) /*++
Routine Description:
This routine translates the AllocateMemory Int 21 api
Arguments:
None.
Return Value:
None.
--*/ { DECLARE_LocalVdmContext; PMEM_DPMI pMem; ULONG MemSize = ((ULONG)getBX()) << 4;
pMem = DpmiAllocateXmem(MemSize);
if (pMem) {
pMem->SelCount = (USHORT) ((MemSize>>16) + 1); pMem->Sel = ALLOCATE_SELECTORS(pMem->SelCount);
if (!pMem->Sel) { pMem->SelCount = 0; DpmiFreeXmem(pMem); pMem = NULL; } else {
SetDescriptorArray(pMem->Sel, (ULONG)pMem->Address, MemSize);
} }
if (!pMem) { setCF(1); setAX(8); setBX(0); } else { setCF(0); setAX(pMem->Sel); } }
VOID FreeMemoryBlock( VOID ) /*++
Routine Description:
This routine translates the ResizeMemory Int 21 api
Arguments:
None.
Return Value:
None.
--*/ { DECLARE_LocalVdmContext; PMEM_DPMI pMem; USHORT Sel = getES();
if (pMem = DpmiFindXmem(Sel)) {
while(pMem->SelCount--) { FreeSelector(Sel); Sel+=8; }
DpmiFreeXmem(pMem); setCF(0);
} else {
setCF(1); setAX(9);
} }
VOID ResizeMemoryBlock( VOID ) /*++
Routine Description:
This routine translates the ResizeMemory int 21 api
Arguments:
None.
Return Value:
None.
--*/ { DECLARE_LocalVdmContext; PMEM_DPMI pMem; ULONG MemSize = ((ULONG)getBX()) << 4; USHORT Sel = getES();
if (pMem = DpmiFindXmem(Sel)) {
if (DpmiReallocateXmem(pMem, MemSize)) {
SetDescriptorArray(pMem->Sel, (ULONG)pMem->Address, MemSize); setCF(0);
} else {
// not enough memory
setCF(1); setAX(8);
} } else {
// invalid block
setCF(1); setAX(9);
} }
VOID LoadExec( VOID ) /*++
Routine Description:
This function translates the int 21 load exec function. Load overlay is not supported.
The child always inherits the environment, and the fcbs in the parameter block are ignored. (win 3.1 does this)
Arguments:
None.
Return Value:
None.
--*/ { DECLARE_LocalVdmContext; PUCHAR CommandTail, BufferedString, Environment; USHORT ClientDX, ClientBX, Seg, Off, Length, i, EnvironmentSel; USHORT ClientDS = getDS(); USHORT ClientES = getES();
DpmiSwitchToRealMode(); ClientDX = getDX(); ClientBX = getBX();
if (getAL() == 3) { setCF(1); setAX(1); } else {
//
// Make sure real DTA is updated later
//
CurrentDosDta = (PUCHAR) NULL;
//
// Map the command string
//
BufferedString = DpmiMapString(ClientDS, (*GetDXRegister)(), &Length);
//
// Set up the Parameter block
//
// We use the large xlat buffer. The parameter block comes
// first, and we fill in the command tail after
//
ZeroMemory(LargeXlatBuffer, 512);
//
// The environment segment address is now set
//
//
// Set the command tail address, and copy the command tail (all
// 128 bytes
//
DPMI_FLAT_TO_SEGMENTED((LargeXlatBuffer + 0x10), &Seg, &Off) *(PWORD16)(LargeXlatBuffer + 2) = Off; *(PWORD16)(LargeXlatBuffer + 4) = Seg;
//
// CommandTail = FLAT(es:bx)
//
CommandTail = Sim32GetVDMPointer(((ULONG)ClientES << 16), 1, TRUE) + (*GetBXRegister)();
if (CurrentAppFlags & DPMI_32BIT) { //
// CommandTail -> string
//
CommandTail = Sim32GetVDMPointer((*(PWORD16)(CommandTail + 4)) << 16, 1, TRUE) + *(PDWORD16)(CommandTail);
} else { //
// CommandTail -> string
//
CommandTail = Sim32GetVDMPointer(*(PDWORD16)(CommandTail + 2), 1, TRUE); }
CopyMemory((LargeXlatBuffer + 0x10), CommandTail, 128);
//
// Set FCB pointers and put spaces in the file names
//
DPMI_FLAT_TO_SEGMENTED((LargeXlatBuffer + 144), &Seg, &Off) *(PWORD16)(LargeXlatBuffer + 6) = Off; *(PWORD16)(LargeXlatBuffer + 8) = Seg; for (i = 0; i < 11; i++) { (LargeXlatBuffer + 144 + 1)[i] = ' '; }
DPMI_FLAT_TO_SEGMENTED((LargeXlatBuffer + 188), &Seg, &Off) *(PWORD16)(LargeXlatBuffer + 0xA) = Off; *(PWORD16)(LargeXlatBuffer + 0xC) = Seg; for (i = 0; i < 11; i++) { (LargeXlatBuffer + 188 + 1)[i] = ' '; }
//
// Save the environment selector, and make it a segment
//
Environment = Sim32GetVDMPointer(((ULONG)CurrentPSPSelector << 16) | 0x2C, 1, TRUE);
EnvironmentSel = *(PWORD16)Environment;
*(PWORD16)Environment = (USHORT)(SELECTOR_TO_INTEL_LINEAR_ADDRESS(EnvironmentSel) >> 4);
//
// Set up registers for the exec
//
DPMI_FLAT_TO_SEGMENTED(BufferedString, &Seg, &Off); setDS(Seg); setDX(Off); DPMI_FLAT_TO_SEGMENTED(LargeXlatBuffer, &Seg, &Off); setES(Seg); setBX(Off);
DPMI_EXEC_INT(0x21);
//
// Restore the environment selector
//
Environment = Sim32GetVDMPointer(((ULONG)CurrentPSPSelector << 16) | 0x2C, 1, TRUE);
*(PWORD16)Environment = EnvironmentSel;
//
// Free translation buffer
//
DpmiUnmapString(BufferedString, Length); } setDX(ClientDX); setBX(ClientBX); DpmiSwitchToProtectedMode(); setES(ClientES); setDS(ClientDS); }
VOID Terminate( VOID ) /*++
Routine Description:
description-of-function.
Arguments:
argument-name - Supplies | Returns description of argument. . .
Return Value:
return-value - Description of conditions needed to return value. - or - None.
--*/ { // bugbug We're currently mapping this one in the dos extender
}
VOID FindFirstFileHandle( VOID ) /*++
Routine Description:
This routine translates the find first api.
Arguments:
None.
Return Value:
None.
--*/ { DECLARE_LocalVdmContext; USHORT ClientDX, Seg, Off, StringLength; PUCHAR BufferedString; USHORT ClientDS = getDS();
DpmiSwitchToRealMode(); SetDTAPointers(); ClientDX = getDX();
//
// Copy the DTA (if necessary)
//
if (CurrentDta != CurrentPmDtaAddress) { CopyMemory(CurrentDta, CurrentPmDtaAddress, 43); }
//
// Check to see if we need to set the real dta
//
if (CurrentDosDta != CurrentDta) SetDosDTA();
//
// map the string
//
BufferedString = DpmiMapString(ClientDS, (GetDXRegister)(), &StringLength);
DPMI_FLAT_TO_SEGMENTED(BufferedString, &Seg, &Off); setDS(Seg); setDX(Off);
DPMI_EXEC_INT(0x21); DpmiSwitchToProtectedMode(); setDS(ClientDS);
DpmiUnmapString(BufferedString, StringLength);
//
// Copy the DTA back (if necessary)
//
if (CurrentDta != CurrentPmDtaAddress) { CopyMemory(CurrentPmDtaAddress, CurrentDta, 43); }
setDX(ClientDX);
}
VOID FindNextFileHandle( VOID ) /*++
Routine Description:
This routine translates the find next api
Arguments:
None.
Return Value:
None.
--*/ { DECLARE_LocalVdmContext;
DpmiSwitchToRealMode(); SetDTAPointers();
//
// Copy the DTA (if necessary)
//
if (CurrentDta != CurrentPmDtaAddress) { CopyMemory(CurrentDta, CurrentPmDtaAddress, 43); }
//
// Check to see if we need to set the real dta
//
if (CurrentDosDta != CurrentDta) SetDosDTA();
DPMI_EXEC_INT(0x21); DpmiSwitchToProtectedMode();
//
// Copy the DTA back (if necessary)
//
if (CurrentDta != CurrentPmDtaAddress) { CopyMemory(CurrentPmDtaAddress, CurrentDta, 43); }
}
VOID SetPSP( VOID ) /*++
Routine Description:
This routine translates the set psp api. This is substantially the same as CreatePSP, except that this can fail (and return carry). It also remembers the PSP selector, so we can return it on request.
Arguments:
None.
Return Value:
None.
--*/ { DECLARE_LocalVdmContext; ULONG Segment; USHORT ClientBX;
DpmiSwitchToRealMode(); ClientBX = getBX();
if (ClientBX == 0) { CurrentPSPSelector = ClientBX; } else { Segment = SELECTOR_TO_INTEL_LINEAR_ADDRESS(ClientBX);
if (Segment > ONE_MB) {
setCF(1);
} else { setBX((USHORT) (Segment >> 4)); DPMI_EXEC_INT(0x21); CurrentPSPSelector = ClientBX; } }
setBX(ClientBX); DpmiSwitchToProtectedMode(); }
VOID GetPSP( VOID ) /*++
Routine Description:
This routine returns the current PSP selector
Arguments:
None.
Return Value:
None.
--*/ { DECLARE_LocalVdmContext;
DpmiSwitchToRealMode(); //
// Get the current psp segment to see if it changed
//
DPMI_EXEC_INT(0x21); DpmiSwitchToProtectedMode();
//
// If it changed get a new selector for the psp
//
if (getBX() != (USHORT)(SELECTOR_TO_INTEL_LINEAR_ADDRESS(CurrentPSPSelector) >> 4) ){ CurrentPSPSelector = SegmentToSelector(getBX(), STD_DATA); }
setBX(CurrentPSPSelector); setCF(0);
}
VOID TranslateBPB( VOID ) /*++
Routine Description:
This function fails and returns. On NT we do not support this dos call.
Arguments:
None.
Return Value:
None.
--*/ { DECLARE_LocalVdmContext;
#if DBG
OutputDebugString("DPMI: Int 21 function 53 is not supported\n"); #endif
setCF(1); }
VOID RenameFile( VOID ) /*++
Routine Description:
This routine translates the rename int 21 api
Arguments:
None.
Return Value:
None.
--*/ { DECLARE_LocalVdmContext; PUCHAR SourceString, DestinationString; USHORT ClientDX, ClientDI, Seg, Off, SourceLength, DestinationLength; USHORT ClientDS = getDS(); USHORT ClientES = getES();
DpmiSwitchToRealMode(); ClientDX = getDX(); ClientDI = getDI();
SourceString = DpmiMapString(ClientDS, (*GetDXRegister)(), &SourceLength); DestinationString = DpmiMapString(ClientES, (*GetDIRegister)(), &DestinationLength);
DPMI_FLAT_TO_SEGMENTED(SourceString, &Seg, &Off); setDX(Off); setDS(Seg); DPMI_FLAT_TO_SEGMENTED(DestinationString, &Seg, &Off); setDI(Off); setES(Seg);
DPMI_EXEC_INT(0x21);
setDX(ClientDX); setDI(ClientDI); DpmiSwitchToProtectedMode(); setDS(ClientDS); setES(ClientES); }
VOID CreateTempFile( VOID ) /*++
Routine Description:
This function maps the int 21 create temp file api
Arguments:
None.
Return Value:
None.
--*/ { DECLARE_LocalVdmContext; PUCHAR String, BufferedString; USHORT ClientDX, Seg, Off, Length; USHORT ClientDS = getDS();
DpmiSwitchToRealMode(); ClientDX = getDX();
String = Sim32GetVDMPointer(((ULONG)ClientDS << 16), 1, TRUE) + (*GetDXRegister)();
Length = 0; while (String[Length] != '\0') { Length++; }
Length += 13;
BufferedString = DpmiMapAndCopyBuffer(String, Length);
DPMI_FLAT_TO_SEGMENTED(BufferedString, &Seg, &Off); setDS(Seg); setDX(Off);
DPMI_EXEC_INT(0x21); DpmiSwitchToProtectedMode();
DpmiUnmapAndCopyBuffer(String, BufferedString, Length);
setDX(ClientDX); setDS(ClientDS); }
#define MAX_SUPPORTED_DOS_5D_CALL 12
APIXLATFUNCTION Func5DXlatTable[MAX_SUPPORTED_DOS_5D_CALL] = { NotSupportedBad , // 0
MapDPL , // 1
NotSupportedBad , // 2
MapDPL , // 3
MapDPL , // 4
NotSupportedBad , // 5
NotSupportedBad , // 6
NoTranslation , // 7
NoTranslation , // 8
NoTranslation , // 9
MapDPL , // 10
NotSupportedBad // 11
};
VOID Func5Dh( VOID ) /*++
Routine Description:
This function translates dos call 5d
Arguments:
None.
Return Value:
None.
--*/ { DECLARE_LocalVdmContext; USHORT Func5DhMinor;
Func5DhMinor = getAL();
if (Func5DhMinor >= MAX_SUPPORTED_DOS_5D_CALL) { #if DBG
OutputDebugString("DPMI: DOS FUNCTION 5D UNSUPPORTED\n"); #endif
NoTranslation(); return; }
(*Func5DXlatTable[Func5DhMinor])(); }
#define MAX_SUPPORTED_DOS_5E_CALL 4
APIXLATFUNCTION Func5EXlatTable[MAX_SUPPORTED_DOS_5E_CALL] = { GetMachineName, MapASCIIZDSDX, GetPrinterSetup, SetPrinterSetup };
VOID Func5Eh( VOID ) /*++
Routine Description:
description-of-function.
Arguments:
argument-name - Supplies | Returns description of argument. . .
Return Value:
return-value - Description of conditions needed to return value. - or - None.
--*/ { DECLARE_LocalVdmContext; USHORT Func5EhMinor;
Func5EhMinor = getAL();
if (Func5EhMinor >= MAX_SUPPORTED_DOS_5E_CALL) { #if DBG
OutputDebugString("DPMI: DOS FUNCTION 5E UNSUPPORTED\n"); #endif
NoTranslation(); return; }
(*Func5EXlatTable[Func5EhMinor])(); }
VOID Func5Fh( VOID ) /*++
Routine Description:
description-of-function.
Arguments:
argument-name - Supplies | Returns description of argument. . .
Return Value:
return-value - Description of conditions needed to return value. - or - None.
--*/ { DECLARE_LocalVdmContext; USHORT Func5FMinor;
Func5FMinor = getAL();
if (Func5FMinor == 4) { MapASCIIZDSSI(); return; } else if ((Func5FMinor == 2) || (Func5FMinor == 3) || (Func5FMinor == 5) ){ USHORT ClientSI, ClientDI, DataOff, DataSeg; PUCHAR Data16, BufferedData16, Data128, BufferedData128; USHORT ClientDS = getDS(); USHORT ClientES = getES();
DpmiSwitchToRealMode(); ClientDI = getDI(); ClientSI = getSI();
Data16 = Sim32GetVDMPointer(((ULONG)ClientDS << 16), 1, TRUE) + (*GetSIRegister)();
BufferedData16 = DpmiMapAndCopyBuffer(Data16, 16);
Data128 = Sim32GetVDMPointer(((ULONG)ClientES << 16), 1, TRUE) + (*GetDIRegister)();
BufferedData128 = DpmiMapAndCopyBuffer(Data128, 128);
DPMI_FLAT_TO_SEGMENTED(BufferedData16, &DataSeg, &DataOff); setDS(DataSeg); setSI(DataOff); DPMI_FLAT_TO_SEGMENTED(BufferedData128, &DataSeg, &DataOff); setES(DataSeg); setDI(DataOff);
DPMI_EXEC_INT(0x21); DpmiSwitchToProtectedMode();
DpmiUnmapAndCopyBuffer(Data16, BufferedData16, 16); DpmiUnmapAndCopyBuffer(Data128, BufferedData128, 128);
setDS(ClientDS); setES(ClientES); setSI(ClientSI); setDI(ClientDI); } else { #if DBG
OutputDebugString("DPMI: UNSUPPORTED INT 21 FUNCTION 5F\n"); #endif
NoTranslation(); } }
VOID NotSupportedBad( VOID ) /*++
Routine Description:
description-of-function.
Arguments:
argument-name - Supplies | Returns description of argument. . .
Return Value:
return-value - Description of conditions needed to return value. - or - None.
--*/ { #if DBG
DECLARE_LocalVdmContext;
DbgPrint("WARNING: DOS INT 21 call AX= %x will not be translated.\n", getAH()); DbgPrint(" Use of this call is not supported from Prot\n"); DbgPrint(" mode applications.\n"); #endif
NoTranslation(); }
VOID ReturnDSSI( VOID ) /*++
Routine Description:
This function translates api that return information in ds:si
Arguments:
None.
Return Value:
None.
--*/ { DECLARE_LocalVdmContext; USHORT Selector;
DpmiSwitchToRealMode(); DPMI_EXEC_INT(0x21); Selector = getDS(); DpmiSwitchToProtectedMode();
(*SetSIRegister)((ULONG)getSI()); setDS(SegmentToSelector(Selector, STD_DATA));
}
VOID NotSupportedBetter( VOID ) /*++
Routine Description:
description-of-function.
Arguments:
argument-name - Supplies | Returns description of argument. . .
Return Value:
return-value - Description of conditions needed to return value. - or - None.
--*/ { #if DBG
DECLARE_LocalVdmContext;
DbgPrint("WARNING: DOS INT 21 call AX= %x will not be translated.", getAH()); DbgPrint(" Use of this call by a Prot Mode app is not"); DbgPrint(" appropriate. There is a better INT 21 call, or a"); DbgPrint(" Windows call which should be used instead of this."); #endif
NoTranslation(); }
VOID GetExtendedCountryInfo( VOID ) /*++
Routine Description:
This routine translates the get extended country info int 21 api
Arguments:
None.
Return Value:
None.
--*/ { DECLARE_LocalVdmContext; PUCHAR Country, BufferedCountry; USHORT ClientDI, Seg, Off, Length; USHORT ClientES = getES();
DpmiSwitchToRealMode(); ClientDI = getDI();
Length = getCX();
Country = Sim32GetVDMPointer(((ULONG)ClientES << 16), 1, TRUE) + (*GetDIRegister)();
BufferedCountry = DpmiMapAndCopyBuffer(Country, Length);
DPMI_FLAT_TO_SEGMENTED(BufferedCountry, &Seg, &Off); setES(Seg); setDI(Off);
DPMI_EXEC_INT(0x21); DpmiSwitchToProtectedMode(); setES(ClientES);
DpmiUnmapAndCopyBuffer(Country, BufferedCountry, Length);
setDI(ClientDI); }
VOID MapASCIIZDSSI( VOID ) /*++
Routine Description:
This function translates the int 21 extended open call
Arguments:
None.
Return Value:
None.
--*/ { DECLARE_LocalVdmContext; PUCHAR BufferedString; USHORT ClientSI, StringSeg, StringOff, Length; USHORT ClientDS = getDS();
DpmiSwitchToRealMode(); ClientSI = getSI();
BufferedString = DpmiMapString(ClientDS, (*GetSIRegister)(), &Length);
DPMI_FLAT_TO_SEGMENTED(BufferedString, &StringSeg, &StringOff); setDS(StringSeg); setSI(StringOff); DPMI_EXEC_INT(0x21); DpmiSwitchToProtectedMode();
DpmiUnmapString(BufferedString, Length); setSI(ClientSI); setDS(ClientDS); }
VOID MapDSDXLenCX( VOID ) /*++
Routine Description:
This function maps the ioctl calls that pass data in DS:DX, with length in cx
Arguments:
None.
Return Value:
None.
--*/ { DECLARE_LocalVdmContext; USHORT ClientDX, ClientCX, DataSeg, DataOff; PUCHAR Data, BufferedData; USHORT ClientDS = getDS();
DpmiSwitchToRealMode(); ClientDX = getDX(); ClientCX = getCX();
Data = Sim32GetVDMPointer(((ULONG)ClientDS << 16), 1, TRUE) + (*GetDXRegister)();
BufferedData = DpmiMapAndCopyBuffer(Data, ClientCX);
DPMI_FLAT_TO_SEGMENTED(BufferedData, &DataSeg, &DataOff);
setDS(DataSeg); setDX(DataOff); DPMI_EXEC_INT(0x21); DpmiSwitchToProtectedMode();
DpmiUnmapAndCopyBuffer(Data, BufferedData, ClientCX);
setDS(ClientDS); setDX(ClientDX); }
VOID IOCTLMap2Bytes( VOID ) /*++
Routine Description:
description-of-function.
Arguments:
argument-name - Supplies | Returns description of argument. . .
Return Value:
return-value - Description of conditions needed to return value. - or - None.
--*/ { DECLARE_LocalVdmContext; USHORT ClientDX, DataSeg, DataOff; PUCHAR Data, BufferedData; USHORT ClientDS = getDS();
DpmiSwitchToRealMode(); ClientDX = getDX();
Data = Sim32GetVDMPointer(((ULONG)ClientDS << 16), 1, TRUE);
BufferedData = DpmiMapAndCopyBuffer(Data, 2);
DPMI_FLAT_TO_SEGMENTED(BufferedData, &DataSeg, &DataOff);
setDS(DataSeg); setDX(DataOff); DPMI_EXEC_INT(0x21); DpmiSwitchToProtectedMode();
DpmiUnmapAndCopyBuffer(Data, BufferedData, 2);
setDS(ClientDS); setDX(ClientDX); }
VOID IOCTLBlockDevs( VOID ) /*++
Routine Description:
This function fails the block device ioctls
Arguments:
None.
Return Value:
None.
--*/ { DECLARE_LocalVdmContext; USHORT IoctlSubFunction, Seg, Off, ClientDX; PUCHAR Data, BufferedData; USHORT Length; USHORT ClientDS = getDS();
IoctlSubFunction = getCL();
if ((IoctlSubFunction < 0x40) || (IoctlSubFunction > 0x42) && (IoctlSubFunction < 0x60) || (IoctlSubFunction > 0x62) && (IoctlSubFunction != 0x68) ) { #if DBG
OutputDebugString("DPMI: IOCTL DOS CALL NOT SUPPORTED\n"); #endif
NoTranslation(); return; }
//
// Read and write track are special (and a pain)
//
if ((IoctlSubFunction == 0x41) || (IoctlSubFunction == 0x61)) { IoctlReadWriteTrack(); return; }
DpmiSwitchToRealMode(); ClientDX = getDX();
Data = Sim32GetVDMPointer(((ULONG)ClientDS << 16), 1, TRUE) + (*GetDXRegister)();
switch (IoctlSubFunction) { case 0x40: //
// Map set device params
//
Length = (*(PWORD16)(Data + 0x26)); Length <<= 2; Length += 0x28; break;
case 0x60: //
// Map get device params
//
Length = 38; break;
case 0x62: //
// Map format verify
//
Length = 5; break;
case 0x68: //
// Map Media sense
//
Length = 4; break; }
BufferedData = DpmiMapAndCopyBuffer(Data, Length); DPMI_FLAT_TO_SEGMENTED(BufferedData, &Seg, &Off); setDS(Seg); setDX(Off);
DPMI_EXEC_INT(0x21); DpmiSwitchToProtectedMode();
DpmiUnmapAndCopyBuffer(Data, BufferedData, Length);
setDS(ClientDS); setDX(ClientDX); }
VOID IoctlReadWriteTrack( VOID ) /*++
Routine Description:
This routine maps the read/write track ioctl.
Arguments:
None.
Return Value:
None.
--*/ { DECLARE_LocalVdmContext; USHORT ClientDX, ClientDS, ClientCX, ClientAX; USHORT Seg, Off, NumberOfSectors, BytesPerSector; USHORT SectorsRead, SectorsToRead; PUCHAR ParameterBlock, BufferedPBlock, Data, BufferedData;
ClientAX = getAX(); ClientDX = getDX(); ClientCX = getCX(); ClientDS = getDS(); DpmiSwitchToRealMode();
//
// Find out how many bytes/sector
//
BufferedData = DpmiAllocateBuffer(0x40); DPMI_FLAT_TO_SEGMENTED(BufferedData, &Seg, &Off); setDS(Seg); setDX(Off);
setAX(0x440D); setCX(0x860);
DPMI_EXEC_INT(0x21);
if (getCF()) { //
// Failed, we don't know how much data to buffer,
// so fail read/write track
//
DpmiFreeBuffer(BufferedData, 0x40); setDX(ClientDX); setCX(ClientCX); DpmiSwitchToProtectedMode(); setDS(ClientDS); return; }
//
// Get the number of bytes/sector
//
BytesPerSector = *(PWORD16)(BufferedData + 0x7);
DpmiFreeBuffer(BufferedData, 0x40);
setDX(ClientDX);
//
// First map the parameter block
//
ParameterBlock = Sim32GetVDMPointer(((ULONG)ClientDS << 16), 1, TRUE) + (*GetDXRegister)();
BufferedPBlock = DpmiMapAndCopyBuffer(ParameterBlock, 13);
//
// Get the segment and offset of the parameter block
//
DPMI_FLAT_TO_SEGMENTED(BufferedPBlock, &Seg, &Off);
setDS(Seg); setDX(Off);
if (CurrentAppFlags & DPMI_32BIT) {
Data = Sim32GetVDMPointer( (*((PWORD16)(BufferedPBlock + 0xd)) << 16), 1, TRUE );
Data += *((PDWORD16)(BufferedPBlock + 0x9));
} else {
Data = Sim32GetVDMPointer( (*((PWORD16)(BufferedPBlock + 0xb)) << 16), 1, TRUE );
Data += *((PWORD16)(BufferedPBlock + 0x9));
}
NumberOfSectors = *((PWORD16)(BufferedPBlock + 7));
SectorsRead = 0;
while (NumberOfSectors != SectorsRead) {
if ((NumberOfSectors - SectorsRead) * BytesPerSector > 1024 * 4) { SectorsToRead = 4 * 1024 / BytesPerSector; } else { SectorsToRead = (USHORT)(NumberOfSectors - SectorsRead); }
BufferedData = DpmiMapAndCopyBuffer( Data, (USHORT) (SectorsToRead * BytesPerSector) );
DPMI_FLAT_TO_SEGMENTED(BufferedData, &Seg, &Off);
*((PWORD16)(BufferedPBlock + 9)) = Off; *((PWORD16)(BufferedPBlock + 11)) = Seg; *((PWORD16)(BufferedPBlock + 7)) = SectorsToRead; setAX(ClientAX); setCX(ClientCX);
DPMI_EXEC_INT(0x21);
if (getCF()) { DpmiUnmapBuffer( BufferedData, (USHORT) (SectorsToRead * BytesPerSector) ); break; }
DpmiUnmapAndCopyBuffer( Data, BufferedData, (USHORT) (SectorsToRead * BytesPerSector) );
Data += SectorsToRead * BytesPerSector; *((PWORD16)(BufferedPBlock + 5)) += SectorsToRead; SectorsRead += SectorsToRead; }
DpmiUnmapBuffer(BufferedPBlock,13); setDX(ClientDX); DpmiSwitchToProtectedMode(); setDS(ClientDS);
}
VOID MapDPL( VOID ) /*++
Routine Description:
This routine maps a DPL for the server call
Arguments:
None.
Return Value:
None.
--*/ { DECLARE_LocalVdmContext; USHORT ClientDX, DataSeg, DataOff; PUCHAR Data, BufferedData; USHORT ClientDS = getDS();
DpmiSwitchToRealMode(); ClientDX = getDX();
Data = Sim32GetVDMPointer(((ULONG)ClientDS << 16), 1, TRUE) + (*GetDXRegister)();
BufferedData = DpmiMapAndCopyBuffer(Data, 22);
DPMI_FLAT_TO_SEGMENTED(BufferedData, &DataSeg, &DataOff);
setDS(DataSeg); setDX(DataOff); DPMI_EXEC_INT(0x21); DpmiSwitchToProtectedMode();
DpmiUnmapAndCopyBuffer(Data, BufferedData, 22);
setDX(ClientDX); setDS(ClientDS); }
VOID GetMachineName( VOID ) /*++
Routine Description:
This routine maps a machine name for int 21 function 5e
Arguments:
None.
Return Value:
None.
--*/ { DECLARE_LocalVdmContext; USHORT ClientDX, DataSeg, DataOff; PUCHAR Data, BufferedData; USHORT ClientDS = getDS();
DpmiSwitchToRealMode(); ClientDX = getDX();
Data = Sim32GetVDMPointer(((ULONG)ClientDS << 16), 1, TRUE) + (*GetDXRegister)();
BufferedData = DpmiMapAndCopyBuffer(Data, 16);
DPMI_FLAT_TO_SEGMENTED(BufferedData, &DataSeg, &DataOff);
setDS(DataSeg); setDX(DataOff); DPMI_EXEC_INT(0x21); DpmiSwitchToProtectedMode();
DpmiUnmapAndCopyBuffer(Data, BufferedData, 16);
setDX(ClientDX); setDS(ClientDS); }
VOID GetPrinterSetup( VOID ) /*++
Routine Description:
This routine maps printer setup data for int 21 function 5e
Arguments:
None.
Return Value:
None.
--*/ { DECLARE_LocalVdmContext; USHORT ClientSI, ClientCX, DataSeg, DataOff; PUCHAR Data, BufferedData; USHORT ClientDS = getDS();
DpmiSwitchToRealMode(); ClientSI = getSI(); ClientCX = getCX();
Data = Sim32GetVDMPointer(((ULONG)ClientDS << 16), 1, TRUE) + (*GetSIRegister)();
BufferedData = DpmiMapAndCopyBuffer(Data, ClientCX);
DPMI_FLAT_TO_SEGMENTED(BufferedData, &DataSeg, &DataOff);
setDS(DataSeg); setSI(DataOff); DPMI_EXEC_INT(0x21); DpmiSwitchToProtectedMode();
DpmiUnmapAndCopyBuffer(Data, BufferedData, ClientCX);
setSI(ClientSI); setDS(ClientDS); }
VOID SetPrinterSetup( VOID ) /*++
Routine Description:
This routine maps printer setup data for int 21 function 5e
Arguments:
None.
Return Value:
None.
--*/ { DECLARE_LocalVdmContext; USHORT ClientDI, DataSeg, DataOff; PUCHAR Data, BufferedData; USHORT ClientES = getES();
DpmiSwitchToRealMode(); ClientDI = getDI();
Data = Sim32GetVDMPointer(((ULONG)ClientES << 16), 1, TRUE) + (*GetDIRegister)();
BufferedData = DpmiMapAndCopyBuffer(Data, 64);
DPMI_FLAT_TO_SEGMENTED(BufferedData, &DataSeg, &DataOff);
setES(DataSeg); setDI(DataOff); DPMI_EXEC_INT(0x21); DpmiSwitchToProtectedMode(); setES(ClientES); DpmiUnmapAndCopyBuffer(Data, BufferedData, 64);
setDI(ClientDI); } VOID GetDate( VOID ) /*++
Routine Description:
This routine maps int21 func 2A GetDate
Arguments:
None.
Return Value:
Client (DH) - month Client (DL) - Day Client (CX) - Year Client (AL) - WeekDay
--*/ { DECLARE_LocalVdmContext; SYSTEMTIME TimeDate;
GetLocalTime(&TimeDate); setDH((UCHAR)TimeDate.wMonth); setDL((UCHAR)TimeDate.wDay); setCX(TimeDate.wYear); setAL((UCHAR)TimeDate.wDayOfWeek); }
|