/*++

Copyright (c) 1992  Microsoft Corporation

Module Name:

    dpmi32.h

Abstract:

    This is the private include file for the 32 bit dpmi and protected mode
    support

Author:

    Dave Hastings (daveh) 24-Nov-1992

Revision History:

    Neil Sandlin (neilsa) 31-Jul-1995 - Updates for the 486 emulator
    Neil Sandlin (neilsa) 15-Sep-1996 - Merged dpmi32p.h, dpmidata.h

--*/

#define FAST_VDM_REGISTERS

//
// DPMI structures and definitions
//

#define I31VERSION 90           // Int 31 services major/minor version #'s
#define I31FLAGS 0x000D         // 386 extender, pMode NetBIOS
#define idCpuType 3             // LATER: conceivably, we could return the real proc type
#define I31MasterPIC    0x08    // Master PIC Interrupts start at 08h
#define I31SlavePIC     0x70    // Slave PIC Interrupts start at 70h


#pragma pack(1)
typedef struct _DPMIMEMINFO {
    DWORD LargestFree;
    DWORD MaxUnlocked;
    DWORD MaxLocked;
    DWORD AddressSpaceSize;
    DWORD UnlockedPages;
    DWORD FreePages;
    DWORD PhysicalPages;
    DWORD FreeAddressSpace;
    DWORD PageFileSize;
} DPMIMEMINFO, *PDPMIMEMINFO;
#pragma pack()

#pragma pack(1)
typedef struct _DPMI_RMCALLSTRUCT {
    DWORD Edi;
    DWORD Esi;
    DWORD Ebp;
    DWORD Reserved;
    DWORD Ebx;
    DWORD Edx;
    DWORD Ecx;
    DWORD Eax;
    WORD Flags;
    WORD Es;
    WORD Ds;
    WORD Fs;
    WORD Gs;
    WORD Ip;
    WORD Cs;
    WORD Sp;
    WORD Ss;
} DPMI_RMCALLSTRUCT, *PDPMI_RMCALLSTRUCT;
#pragma pack()


//
// dpmi32 init structure
//

#pragma pack(1)
typedef struct _DOSX_RM_INIT_INFO {
    USHORT StackSegment;
    USHORT StackFrameSize;
    ULONG  RmBopFe;
    ULONG  PmBopFe;
    USHORT RmCodeSegment;
    USHORT RmCodeSelector;
    ULONG  pFaultHandlerIret;
    ULONG  pFaultHandlerIretd;
    ULONG  pIntHandlerIret;
    ULONG  pIntHandlerIretd;
    ULONG  pIret;
    ULONG  pIretd;
    USHORT RMCallBackBopOffset;
    USHORT RMCallBackBopSeg;
    ULONG  RMReflector;
    USHORT PMReflectorSeg;
    USHORT InitialLDTSeg;
    USHORT InitialLDTSize;
    ULONG  RmSaveRestoreState;
    ULONG  PmSaveRestoreState;
    ULONG  RmRawModeSwitch;
    ULONG  PmRawModeSwitch;
    ULONG  VcdPmSvcCall;
    ULONG  MsDosApi;
    ULONG  XmsControl;
    ULONG  HungAppExit;
} DOSX_RM_INIT_INFO;
typedef DOSX_RM_INIT_INFO UNALIGNED* PDOSX_RM_INIT_INFO;

typedef struct _DOSX_INIT_INFO {
    ULONG  pSmallXlatBuffer;
    ULONG  pLargeXlatBuffer;
    ULONG  pStackFramePointer;
    ULONG  pDtaBuffer;
} DOSX_INIT_INFO;
typedef DOSX_INIT_INFO UNALIGNED* PDOSX_INIT_INFO;
#pragma pack()


#define SWITCH_TO_DOSX_RMSTACK() {                          \
            setSS(DosxStackSegment);                        \
            setSP(*DosxStackFramePointer);                  \
            *DosxStackFramePointer -= DosxStackFrameSize;   \
            }

#define SWITCH_FROM_DOSX_RMSTACK() {                        \
            *DosxStackFramePointer += DosxStackFrameSize;   \
            }

//
// Defines to allow us to use a common dispatch table without having
// to add a bunch of stub functions
//

extern VDM_INTERRUPTHANDLER DpmiInterruptHandlers[256];
extern VDM_FAULTHANDLER DpmiFaultHandlers[32];

#ifdef _X86_

#ifdef FAST_VDM_REGISTERS

#define LockedPMStackSel      (_LocalVdmTib->DpmiInfo.SsSelector)
#define LockedPMStackCount    (_LocalVdmTib->DpmiInfo.LockCount)

#define PMLockOrigEIP         (_LocalVdmTib->DpmiInfo.SaveEip)
#define PMLockOrigESP         (_LocalVdmTib->DpmiInfo.SaveEsp)
#define PMLockOrigSS          (_LocalVdmTib->DpmiInfo.SaveSsSelector)

#define DosxFaultHandlerIret  (_LocalVdmTib->DpmiInfo.DosxFaultIret)
#define DosxFaultHandlerIretd (_LocalVdmTib->DpmiInfo.DosxFaultIretD)
#define DosxIntHandlerIret    (_LocalVdmTib->DpmiInfo.DosxIntIret)
#define DosxIntHandlerIretd   (_LocalVdmTib->DpmiInfo.DosxIntIretD)
#define DosxRMReflector       (_LocalVdmTib->DpmiInfo.DosxRmReflector)


#else   //FAST_VDM_REGISTERS

// Temporary only.  Doing this so I can switch back to the old way in case ...

#define LockedPMStackSel      ((PVDM_TIB)NtCurrentTeb()->Vdm)->DpmiInfo.SsSelector
#define LockedPMStackCount    ((PVDM_TIB)NtCurrentTeb()->Vdm)->DpmiInfo.LockCount

#define PMLockOrigEIP         ((PVDM_TIB)NtCurrentTeb()->Vdm)->DpmiInfo.SaveEip
#define PMLockOrigESP         ((PVDM_TIB)NtCurrentTeb()->Vdm)->DpmiInfo.SaveEsp
#define PMLockOrigSS          ((PVDM_TIB)NtCurrentTeb()->Vdm)->DpmiInfo.SaveSsSelector

#define DosxFaultHandlerIret  ((PVDM_TIB)NtCurrentTeb()->Vdm)->DpmiInfo.DosxFaultIret
#define DosxFaultHandlerIretd ((PVDM_TIB)NtCurrentTeb()->Vdm)->DpmiInfo.DosxFaultIretD
#define DosxIntHandlerIret    ((PVDM_TIB)NtCurrentTeb()->Vdm)->DpmiInfo.DosxIntIret
#define DosxIntHandlerIretd   ((PVDM_TIB)NtCurrentTeb()->Vdm)->DpmiInfo.DosxIntIretD
#define DosxRMReflector       ((PVDM_TIB)NtCurrentTeb()->Vdm)->DpmiInfo.DosxRmReflector

#endif //FAST_VDM_REGISTERS

#else  // _X86_

extern USHORT LockedPMStackSel;
extern ULONG LockedPMStackCount;
extern ULONG PMLockOrigEIP;
extern ULONG PMLockOrigSS;
extern ULONG PMLockOrigESP;

extern ULONG DosxFaultHandlerIret;
extern ULONG DosxFaultHandlerIretd;
extern ULONG DosxIntHandlerIret;
extern ULONG DosxIntHandlerIretd;
extern ULONG DosxRMReflector;

//
// Ldt entry definition
//
// This appears in nti386.h, and winnt.h.  The definitions in
// winnt.h are not included if the nt include files are included.
// The simple solution, since this structure will never change
// is to put the definition here.
//

typedef struct _LDT_ENTRY {
    WORD    LimitLow;
    WORD    BaseLow;
    union {
        struct {
            BYTE    BaseMid;
            BYTE    Flags1;     // Declare as bytes to avoid alignment
            BYTE    Flags2;     // Problems.
            BYTE    BaseHi;
        } Bytes;
        struct {
            DWORD   BaseMid : 8;
            DWORD   Type : 5;
            DWORD   Dpl : 2;
            DWORD   Pres : 1;
            DWORD   LimitHi : 4;
            DWORD   Sys : 1;
            DWORD   Reserved_0 : 1;
            DWORD   Default_Big : 1;
            DWORD   Granularity : 1;
            DWORD   BaseHi : 8;
        } Bits;
    } HighWord;
} LDT_ENTRY, *PLDT_ENTRY;


//
// Data items
//

extern VOID force_yoda(VOID);
extern VOID DisableEmulatorIretHooks(VOID);
extern VOID EnableEmulatorIretHooks(VOID);

#endif

typedef struct _IDT_ENTRY {
    WORD    OffsetLow;
    WORD    Selector;
    BYTE    Reserved;
    union {
        struct {
            BYTE Flags;
        } Bytes;
        struct {
            BYTE   Type : 5;
            BYTE   Dpl : 2;
            BYTE   Pres : 1;
        } Bits;
    } u;
    WORD    OffsetHi;
} IDT_ENTRY, *PIDT_ENTRY;


#define GET_SELECTOR_BASE(Sel) ( (ULONG) (              \
            Ldt[Sel>>3].BaseLow |                       \
            Ldt[Sel>>3].HighWord.Bytes.BaseMid << 16 |  \
            Ldt[Sel>>3].HighWord.Bytes.BaseHi << 24     \
            ))

#define GET_SELECTOR_LIMIT(Sel) ( (ULONG) (                                     \
            ((Ldt[Sel>>3].HighWord.Bits.LimitHi << 16 | Ldt[Sel>>3].LimitLow)   \
                 << (12 * Ldt[Sel>>3].HighWord.Bits.Granularity)) +             \
                    Ldt[Sel>>3].HighWord.Bits.Granularity * 0xFFF               \
            ))

#if DBG
#define GET_SHADOW_SELECTOR_LIMIT(Selector, Limit) \
            Limit = SelectorLimit[Selector>>3]
#else
#ifdef _X86_
#define GET_SHADOW_SELECTOR_LIMIT(Selector, Limit) _asm      \
         {                                          \
            _asm    xor     eax, eax                \
            _asm    xor     ecx, ecx                \
            _asm    mov     ax, Selector            \
            _asm    or      eax, 7                  \
            _asm    lsl     ecx, eax                \
            _asm    mov     [Limit], ecx            \
         }
#else
#define GET_SHADOW_SELECTOR_LIMIT(Selector, Limit)  \
            Limit = GET_SELECTOR_LIMIT(Selector)
#endif
#endif

#define SET_SELECTOR_LIMIT(Sel, Limit) {                                    \
            USHORT i = Sel>>3;                                              \
            if (!Ldt[i].HighWord.Bits.Granularity) {                        \
                Ldt[i].LimitLow = (USHORT)(Limit & 0x0000FFFF);             \
                Ldt[i].HighWord.Bits.LimitHi =                              \
                    (Limit & 0x000f0000) >> 16;                             \
            } else {                                                        \
                Ldt[i].LimitLow = (USHORT)((Limit >> 12) & 0xFFFF);         \
                Ldt[i].HighWord.Bits.LimitHi =                              \
                    ((Limit >> 12) & 0x000f0000) >> 16;                     \
            }                                                               \
        }

#define SET_SELECTOR_ACCESS(Sel, Access) {                                  \
            Ldt[Sel>>3].HighWord.Bytes.Flags1 = LOBYTE(Access);             \
            Ldt[Sel>>3].HighWord.Bytes.Flags2 = (HIBYTE(Access) & 0xd0) +   \
           (Ldt[Sel>>3].HighWord.Bytes.Flags2 & 0x0f);                      \
            }


#define IS_SELECTOR_FREE(Sel) ((Ldt[Sel>>3].HighWord.Bytes.Flags1 == 0) &&  \
                               (Ldt[Sel>>3].HighWord.Bytes.BaseHi == 0x80))

#define IS_SELECTOR_READABLE(Sel) (                                         \
            ((Ldt[Sel>>3].HighWord.Bytes.Flags1 &                           \
              (AB_DPL3|AB_PRESENT|AB_DATA)) ==                              \
                                      (AB_DPL3|AB_PRESENT|AB_DATA))         \
            )

#ifdef _X86_
#define FLUSH_SELECTOR_CACHE(SelStart, SelCount) TRUE
#else
#define FLUSH_SELECTOR_CACHE(SelStart, SelCount) FlushSelectorCache(SelStart, SelCount)
#endif

//
// These values define the range of the reserved DPMI selectors, given
// out by Int31, func 000d.
//
#define SEL_DPMI_FIRST 0
#define SEL_DPMI_LAST 0x78

// Whenever we allocate a descriptor, the access rights byte is set
// to 0Fh.  This marks it as a '386 task gate, which is not legal to
// have in the GDT.  We need to stick something in this byte, because
// having the access rights byte be 0 means that it is free, which is
// no longer the case.

#define MARK_SELECTOR_ALLOCATED(Sel) {                  \
            Ldt[Sel>>3].HighWord.Bytes.Flags1 = 0xf;    \
            Ldt[Sel>>3].HighWord.Bytes.BaseHi = 0;      \
            }

#define MARK_SELECTOR_FREE(Sel) {                       \
            Ldt[Sel>>3].HighWord.Bytes.Flags1 = 0;      \
            Ldt[Sel>>3].HighWord.Bytes.BaseHi = 0x80;   \
            }

#define NEXT_FREE_SEL(Sel) (Ldt[Sel>>3].LimitLow)

#define ALLOCATE_SELECTOR() AllocateSelectors(1, FALSE)
#define ALLOCATE_SELECTORS(Count) AllocateSelectors(Count, FALSE)
#define ALLOCATE_WOW_SELECTORS(Count) AllocateSelectors(Count, TRUE)



#define SEGMENT_IS_BIG(sel) ((sel<LdtMaxSel) && (Ldt[(sel & ~0x7)/sizeof(LDT_ENTRY)].HighWord.Bits.Default_Big))
#define SEGMENT_IS_PRESENT(sel) ((sel<LdtMaxSel) && (Ldt[(sel & ~0x7)/sizeof(LDT_ENTRY)].HighWord.Bits.Pres))

// This checks for S, Data, W
#define SEGMENT_IS_WRITABLE(sel) ((sel<LdtMaxSel) && ( (Ldt[(sel & ~0x7)/sizeof(LDT_ENTRY)].HighWord.Bits.Type & 0x1a) == 0x12))


#define SEL_INDEX_MASK ~7
// Ldt, ring 3 bits
#define SEL_LDT3 7

//
// Descriptor Access Byte constants
//

#define AB_ACCESSED     0x01    //segment has been accessed
#define AB_WRITE        0x02    //writable data

#define AB_DATA         0x10    //data segment
#define AB_CODE         0x18    //code segment
#define AB_DPL3         0x60    //ring 3 DPL
#define AB_PRESENT      0x80    //segment present bit

#define AB_TRAPGATE     0x07    //trap gate descriptor
#define AB_INTRGATE     0x0e    //80386 interrupt gate descriptor

#define STD_DATA AB_PRESENT+AB_DPL3+AB_DATA+AB_WRITE
#define STD_TRAP AB_PRESENT+AB_DPL3+AB_TRAPGATE
#define STD_INTR AB_PRESENT+AB_DPL3+AB_INTRGATE

//
// Internal Constants
//

#define MAX_V86_ADDRESS         64 * 1024 + 1024 * 1024
#define ONE_MB                  1024 * 1024

// bugbug
#define SMALL_XLAT_BUFFER_SIZE  128
// bugbug
#define LARGE_XLAT_BUFFER_SIZE  8192

#define DPMI_32BIT              0x1

#define Frame32 ((BOOL)CurrentAppFlags)
#define LockedPMStackOffset 0x1000

//
// Internal types
//
typedef ULONG (*GETREGISTERFUNCTION)(VOID);
typedef VOID (*SETREGISTERFUNCTION)(ULONG);

#define SAVE_CLIENT_REGS(Regs) {\
    Regs.Eax = getEAX();        \
    Regs.Ebx = getEBX();        \
    Regs.Ecx = getECX();        \
    Regs.Edx = getEDX();        \
    Regs.Edi = getEDI();        \
    Regs.Esi = getESI();        \
    Regs.Ebp = getEBP();        \
    Regs.Eip = getEIP();        \
    Regs.Esp = getESP();        \
    Regs.Eflags = getEFLAGS();  \
    Regs.Cs = getCS();          \
    Regs.Ds = getDS();          \
    Regs.Es = getES();          \
    Regs.Fs = getFS();          \
    Regs.Gs = getGS();          \
    Regs.Ss = getSS();          \
    }

#define SET_CLIENT_REGS(Regs) { \
    setEAX(Regs.Eax);           \
    setEBX(Regs.Ebx);           \
    setECX(Regs.Ecx);           \
    setEDX(Regs.Edx);           \
    setEDI(Regs.Edi);           \
    setESI(Regs.Esi);           \
    setEBP(Regs.Ebp);           \
    setEIP(Regs.Eip);           \
    setESP(Regs.Esp);           \
    setEFLAGS(Regs.Eflags);     \
    setCS(Regs.Cs);             \
    setDS(Regs.Ds);             \
    setES(Regs.Es);             \
    setFS(Regs.Fs);             \
    setGS(Regs.Gs);             \
    setSS(Regs.Ss);             \
    }

typedef struct _CLIENT_REGS {
    ULONG Eax;
    ULONG Ebx;
    ULONG Ecx;
    ULONG Edx;
    ULONG Edi;
    ULONG Esi;
    ULONG Ebp;
    ULONG Eip;
    ULONG Esp;
    ULONG Eflags;
    USHORT Cs;
    USHORT Ss;
    USHORT Es;
    USHORT Ds;
    USHORT Fs;
    USHORT Gs;
} CLIENT_REGS, *PCLIENT_REGS;

//
// Memory management definitions
//

#define DELETE_BLOCK(BLK)   (BLK->Prev)->Next = BLK->Next;\
                (BLK->Next)->Prev = BLK->Prev

#define INSERT_BLOCK(BLK, HEAD)  BLK->Next = HEAD.Next; BLK->Prev= HEAD.Next->Prev;\
                (HEAD.Next)->Prev = BLK; HEAD.Next = BLK

//
// Visible structure for save state stuff
//
typedef struct _VSavedState {
    UCHAR Misc[28];
} VSAVEDSTATE, PVSAVEDSTATE;

//
// Descriptor mapping (for dib.drv)
//

#ifndef _X86_
ULONG
GetDescriptorMapping(
    USHORT Sel,
    ULONG LdtBase
    );

typedef struct _DESC_MAPPING {
    USHORT Sel;
    USHORT SelCount;
    ULONG LdtBase;
    ULONG FlatBase;
    struct _DESC_MAPPING* pNext;
} DESC_MAPPING, *PDESC_MAPPING;
#endif

//
// Dpmi32 data
//

//SLT: these two should be per-thread
extern ULONG LastLockedPMStackSS;
extern ULONG LastLockedPMStackESP;

extern PUCHAR SmallXlatBuffer;
extern PUCHAR LargeXlatBuffer;
extern BOOL SmallBufferInUse;
extern USHORT LargeBufferInUseCount;
extern USHORT DosxStackSegment;
extern USHORT DosxRmCodeSegment;
extern USHORT DosxRmCodeSelector;
extern PWORD16 DosxStackFramePointer;
extern USHORT DosxStackFrameSize;
extern USHORT CurrentAppFlags;
extern ULONG RmBopFe;
extern ULONG PmBopFe;
extern USHORT RMCallBackBopSeg;
extern USHORT RMCallBackBopOffset;
extern USHORT PMReflectorSeg;
extern PUCHAR DosxDtaBuffer;
extern ULONG IntelBase;
extern PLDT_ENTRY Ldt;
extern USHORT LdtSel;
extern USHORT LdtMaxSel;
extern USHORT LdtUserSel;
extern PIDT_ENTRY Idt;
extern USHORT WOWAllocSeg;
extern USHORT WOWAllocFunc;
extern USHORT WOWFreeSeg;
extern USHORT WOWFreeFunc;

//
// Information about the current DTA
//
// N.B.  The selector:offset, and flat pointer following MAY point to
//       different linear addresses.  This will be the case if the
//       dta selector is in high memory
extern PUCHAR CurrentDta;
extern PUCHAR CurrentPmDtaAddress;
extern PUCHAR CurrentDosDta;
extern USHORT CurrentDtaSelector;
extern USHORT CurrentDtaOffset;

#if DBG
extern ULONG SelectorLimit[LDT_SIZE];
#endif


//
// Register manipulation functions (for register that might be 16 or 32 bits)
//
extern GETREGISTERFUNCTION GetCXRegister;
extern GETREGISTERFUNCTION GetDXRegister;
extern GETREGISTERFUNCTION GetDIRegister;
extern GETREGISTERFUNCTION GetSIRegister;
extern GETREGISTERFUNCTION GetBXRegister;
extern GETREGISTERFUNCTION GetAXRegister;
extern GETREGISTERFUNCTION GetSPRegister;

extern SETREGISTERFUNCTION SetCXRegister;
extern SETREGISTERFUNCTION SetDXRegister;
extern SETREGISTERFUNCTION SetDIRegister;
extern SETREGISTERFUNCTION SetSIRegister;
extern SETREGISTERFUNCTION SetBXRegister;
extern SETREGISTERFUNCTION SetAXRegister;
extern SETREGISTERFUNCTION SetSPRegister;


extern USHORT CurrentPSPSelector;
extern ULONG FlatAddress[LDT_SIZE];

extern ULONG DosxIret;
extern ULONG DosxIretd;

extern ULONG DosxRmSaveRestoreState;
extern ULONG DosxPmSaveRestoreState;
extern ULONG DosxRmRawModeSwitch;
extern ULONG DosxPmRawModeSwitch;

extern ULONG DosxVcdPmSvcCall;
extern ULONG DosxMsDosApi;
extern ULONG DosxXmsControl;
extern ULONG DosxHungAppExit;

//
// Monitor functions
//
VOID
GetFastBopEntryAddress(
    PCONTEXT VdmContext
    );

//
// Dispatched functions (via bop)
//

VOID DpmiInitDosxRM(VOID);
VOID DpmiInitDosx(VOID);
VOID DpmiInitLDT(VOID);
VOID DpmiGetFastBopEntry(VOID);
VOID DpmiInitIDT(VOID);
VOID DpmiInitExceptionHandlers(VOID);
VOID DpmiInitPmStackInfo(VOID);
VOID DpmiInitApp(VOID);
VOID DpmiTerminateApp(VOID);
VOID DpmiDpmiInUse(VOID);
VOID DpmiDpmiNoLongerInUse(VOID);

VOID switch_to_protected_mode(VOID);
VOID switch_to_real_mode(VOID);
VOID DpmiSetAltRegs(VOID);

VOID DpmiVcdPmSvcCall32(VOID);
VOID DpmiFreeAppXmem(VOID);
VOID DpmiFreeAllXmem(VOID);

VOID DpmiIntHandlerIret16(VOID);
VOID DpmiIntHandlerIret32(VOID);
VOID DpmiFaultHandlerIret16(VOID);
VOID DpmiFaultHandlerIret32(VOID);
VOID DpmiUnhandledExceptionHandler(VOID);

VOID DpmiRMCallBackCall(VOID);
VOID DpmiReflectIntrToPM(VOID);
VOID DpmiReflectIntrToV86(VOID);

VOID DpmiSetDescriptorEntry(VOID);
VOID DpmiAllocateSelectors(VOID);
VOID DpmiFreeSelector(VOID);
VOID DpmiResetLDTUserBase(VOID);

VOID DpmiXlatInt21Call(VOID);
VOID DpmiInt31Entry(VOID);
VOID DpmiInt31Call(VOID);

VOID DpmiHungAppIretAndExit(VOID);

//
// Internal functions
//

VOID
BeginUseLockedPMStack(
    VOID
    );

BOOL
EndUseLockedPMStack(
    VOID
    );

BOOL
BuildStackFrame(
    ULONG StackUnits,
    PUCHAR *pVdmStackPointer,
    ULONG *pNewSP
    );

VOID
EmulateV86Int(
    UCHAR InterruptNumber
    );

typedef enum {
    RESTORE_FLAGS,
    PASS_FLAGS,
    PASS_CARRY_FLAG,
    PASS_CARRY_FLAG_16
} IRET_BEHAVIOR;

VOID
SimulateIret(
    IRET_BEHAVIOR fdsp
    );

VOID
SimulateFarCall(
    USHORT Seg,
    ULONG Offset
    );

VOID
SimulateCallWithIretFrame(
    USHORT Seg,
    ULONG Offset
    );

BOOL
DpmiSwIntHandler(
    ULONG IntNumber
    );

BOOL
DpmiHwIntHandler(
    ULONG IntNumber
    );

BOOL
DpmiFaultHandler(
    ULONG IntNumber,
    ULONG ErrorCode
    );

BOOL
SetProtectedModeInterrupt(
    USHORT IntNumber,
    USHORT Sel,
    ULONG Offset,
    USHORT Flags
    );

BOOL
SetFaultHandler(
    USHORT IntNumber,
    USHORT Sel,
    ULONG Offset
    );

BOOL
DispatchPMInt(
    UCHAR InterruptNumber
    );

VOID
DpmiRMCall(
    UCHAR mode
    );

VOID
DpmiAllocateRMCallBack(
    VOID
    );

VOID
DpmiFreeRMCallBack(
    VOID
    );

BOOL
PMInt2fHandler(
    VOID
    );

VOID
GetVxDApiHandler(
    USHORT VxdId
    );

BOOL
DpmiSetDebugRegisters(
    PULONG RegisterPointer
    );

BOOL
DpmiGetDebugRegisters(
    PULONG RegisterPointer
    );
//
// Descriptor managagment
//

#ifdef _X86_
BOOL
DpmiSetX86Descriptor(
    USHORT  SelStart,
    USHORT  SelCount
    );
#else
VOID
FlushSelectorCache(
    USHORT  SelStart,
    USHORT  SelCount
    );
#endif

VOID
SetShadowDescriptorEntries(
    USHORT SelStart,
    USHORT SelCount
    );

VOID
SetDescriptorBase(
    USHORT Sel,
    ULONG Base
    );

VOID
SetDescriptor(
    USHORT Sel,
    ULONG Base,
    ULONG Limit,
    USHORT Access
    );

USHORT
AllocateSelectors(
    USHORT Count,
    BOOL bWow
    );

BOOL
FreeSelector(
    USHORT Sel
    );

USHORT
FindSelector(
    ULONG Base,
    UCHAR Access
    );

BOOL
RemoveFreeSelector(
    USHORT Sel
    );

USHORT
SegmentToSelector(
    USHORT Segment,
    USHORT Access
    );

VOID
SetDescriptorArray(
    USHORT Sel,
    ULONG Base,
    ULONG MemSize
    );

//
// Memory management
//

NTSTATUS
DpmiAllocateVirtualMemory(
    PVOID *Address,
    PULONG Size
    );

NTSTATUS
DpmiFreeVirtualMemory(
    PVOID *Address,
    PULONG Size
    );

NTSTATUS
DpmiReallocateVirtualMemory(
    PVOID OldAddress,
    ULONG OldSize,
    PVOID *NewAddress,
    PULONG NewSize
    );

VOID
DpmiGetMemoryInfo(
    VOID
    );

PMEM_DPMI
DpmiAllocateXmem(
    ULONG Size
    );

BOOL
DpmiFreeXmem(
    PMEM_DPMI XmemBlock
    );

BOOL
DpmiIsXmemHandle(
    PMEM_DPMI XmemBlock
    );

BOOL
DpmiReallocateXmem(
    PMEM_DPMI XmemBlock,
    ULONG Size
    );

PMEM_DPMI
DpmiFindXmem(
    USHORT Sel
    );

VOID
DpmiAllocateDosMem(
    VOID
    );

VOID
DpmiFreeDosMem(
    VOID
    );

VOID
DpmiSizeDosMem(
    VOID
    );

//
// Utility functions
//

VOID
DpmiInitRegisterSize(
    VOID
    );

VOID
DpmiSwitchToProtectedMode(
    VOID
    );

VOID
DpmiSwitchToRealMode(
    VOID
    );

VOID
DpmiPushRmInt(
    USHORT InterruptNumber
    );

VOID
DpmiSaveSegmentsAndStack(
    PVOID ContextPointer
    );

PVOID
DpmiRestoreSegmentsAndStack(
    VOID
    );

//
// Int21 translation
//

VOID
SetVector(
    VOID
    );

VOID
GetVector(
    VOID
    );

PUCHAR
DpmiMapAndCopyBuffer(
    PUCHAR Buffer,
    USHORT BufferLength
    );

VOID
DpmiUnmapAndCopyBuffer(
    PUCHAR Destination,
    PUCHAR Source,
    USHORT BufferLength
    );

USHORT
DpmiCalcFcbLength(
    PUCHAR FcbPointer
    );

PUCHAR
DpmiMapString(
    USHORT StringSeg,
    ULONG StringOff,
    PWORD16 Length
    );

PUCHAR
DpmiAllocateBuffer(
    USHORT Length
    );

#define DpmiUnmapString DpmiFreeBuffer
#define DpmiUnmapBuffer DpmiFreeBuffer

VOID
DpmiFreeBuffer(
    PUCHAR Buffer,
    USHORT Length
    );

VOID
DpmiFreeAllBuffers(
    VOID
    );

#ifdef DBCS
VOID
DpmiSwitchToDosxStack(
    VOID
    );

VOID
DpmiSwitchFromDosxStack(
    VOID
    );
#endif //DBCS