;/* ; Flags for Heap Header L32F_NOHUSED equ 1 ; Heap signature L32_SIGNATURE equ 3233484Ch ; 'LH32' ; Flags for Local32Init LINIT_MAX16HEAP equ 1 LINIT_TILEHEAP equ 2 ; Flags for Local32Alloc LMEM32_64K equ 1 LMEM32_ZEROINIT equ 2 ; Address types NOHPTR16 equ -2 NOHPTR32 equ -1 HANDLE16 equ 0 PTR16 equ 1 PTR32 equ 2 ; if address type is < MINHTYPE, there is no handle associated with address MINHTYPE equ 0 ;-----------------------------------------------------------------------; ; Heap Header (lives at 64K-(SIZE L32HeapHeader)) ;-----------------------------------------------------------------------; L32HeapHeader struc FreeLists dw 16 dup(?) ; array of ptrs to free handles in each page FreeCounts dw 16 dup(?) ; array of counts of free handles in each page FreeTails dw 16 dup(?) ; array of ptrs to tail of free lists dwSelTable dd ? ; 32bit offset of handle->sel mapping table wMaxBaseDelta dw ? ; # of 64K blocks in heap * 8 wSelAdjust dw ? ; (see L32FindHandleEntry, NOHPTR16 code) dwBaseSel dd ? ; base selector linBaseAddr dd ? ; base linear address of heap hCommit dd ? ; highest committed handle L32Flags dd ? ; flags field (L32F_*) L32Signature dd ? ; heap signature (L32_SIGNATURE) hHeap dd ? ; handle to heap L32HeapHeader ends L32HdrSize equ (size L32HeapHeader) ;Translation macro for fast handle->pointer conversion .386p EnumArgs macro arglist,prefix argctr = 0 for arg, argctr = argctr + 1 @CatStr(prefix,%argctr) TEXTEQU endm @CatStr(prefix,) = argctr endm ProcessOptions macro optlist ; Initialize options to default values THOptFULL = 0 THOffset = 10000h THForce32 = 0 THNoValid = 0 irp opt, ifidni , THOptFULL = 1 endif ifidni , THOffset = 0 endif ifidni , THForce32 = 1 endif ifidni , THNoValid = 1 endif endm THHdrPos = THOffset endm InList macro reg,reglist ifnb IsInList INSTR , exitm %IsInList else exitm %0 endif endm ChooseSegReg macro wSel PopDS=1 ifidni ,<0> sptr TEXTEQU PopDS=0 else irp creg, ifidni , sptr TEXTEQU PopDS=0 endif endm endif endm UseSegReg macro wSel if PopDS push ds mov ds,wSel sptr TEXTEQU endif ; Hack: We need to generate instructions like mov eax,[10000h] ; and MASM won't generate a 32-bit offset unless the ; segment is not assumed to be a 16-bit segment. We only ; need this for ds since we only generate these instructions ; for merged segments. ifidni sptr, assume ds:nothing endif endm RestoreSegReg macro if PopDS pop ds endif ; See note in UseSegReg. ifidni sptr, assumes ds,data endif endm ParseDestReg macro hMem ; Sigh. elseif InList(...) doesn't compile so ; NoDestReg is a workaround. Somebody please ; get rid of it if they can figure out how! NoDestReg = 1 if InList(,) destreg32 TEXTEQU @CatStr(, ) destreg16 TEXTEQU destreg8 TEXTEQU @CatStr(@SubStr(,1,1),) NoDestReg = 0 endif if ((NoDestReg NE 0) AND (InList(,) NE 0)) destreg32 TEXTEQU destreg16 TEXTEQU @SubStr(,2,2) destreg8 TEXTEQU @CatStr(@SubStr(,2,1),) NoDestReg = 0 endif if ((NoDestReg NE 0) AND (InList(,) NE 0)) ; these regs only work if opts is blank destreg32 TEXTEQU <> destreg16 TEXTEQU destreg8 TEXTEQU <> NoDestReg = 0 endif if NoDestReg destreg32 TEXTEQU destreg16 TEXTEQU destreg8 TEXTEQU movzx destreg32,hMem endif endm ; Table to determine if two registers overlap ??al = 00000001b ??ah = 00000001b ??ax = 00000001b ??eax = 00000001b ??bl = 00000010b ??bh = 00000010b ??bx = 00000010b ??ebx = 00000010b ??cl = 00000100b ??ch = 00000100b ??cx = 00000100b ??ecx = 00000100b ??dl = 00001000b ??dh = 00001000b ??dx = 00001000b ??edx = 00001000b ??si = 00010000b ??esi = 00010000b ??di = 00100000b ??edi = 00100000b ??Paste macro arg1:req, arg2:req exitm endm TranslateHandle macro wSel,dwMem,wMemType,wRetType,reglist,dreg,opts local THErr local THOk local DestOk if (wMemType EQ HANDLE16) EnumArgs ,regs ProcessOptions ; choose appropriate segment register based on wSel ChooseSegReg wSel ; choose appropriate destination register based on dreg if (regsCnt EQ 1) destreg TEXTEQU ??destreg = ??Paste(??,%regs1) else destreg TEXTEQU ??destreg = ??eax endif ??dwMem = ??Paste(??,dwMem) ; if trivial conversion (HANDLE->HANDLE) do it & exit if (wRetType EQ HANDLE16) mov destreg,dwMem exitm endif ; if wSel isn't in segment register load it in ds UseSegReg wSel if THForce32 mov ecx, THHdrPos endif ;if full validation requested do it now if THOptFULL ParseDestReg test destreg8,3 ; make sure hMem % 4 == 0 jnz THErr cmp destreg16,L32HdrSize jb THErr if THForce32 cmp destreg16,word ptr sptr:[ecx].hCommit ; see if handle is below commit else cmp destreg16,word ptr sptr:[THHdrPos].hCommit ; see if handle is below commit endif ja THErr ifdifi destreg32, movzx ebx,destreg16 endif if THForce32 mov destreg,sptr:[ebx+ecx] ; get 32bit offset in destreg else mov destreg,sptr:[ebx+THOffset] ; get 32bit offset in destreg endif cmp destreg,10000h ; see if its free jb THErr else ; fetch the address (assume dwMem is valid) if THForce32 mov destreg,sptr:[dwMem+ecx] else mov destreg,sptr:[dwMem+THOffset] endif endif ifdef DEBUG ife THNoValid cmp destreg,10000h ; see if its free jae DestOk int 3 endif DestOk: endif ; if HANDLE16->PTR16 compute the selector if (wRetType EQ PTR16) if InList(,) OR InList(,) push ebx endif if THForce32 mov ebx,sptr:[ecx].dwSelTable else mov ebx,sptr:[THHdrPos].dwSelTable endif ; determine which registers to use... if (regsCnt EQ 0) ; eax,dx:ax = PTR16 mov edx,eax shr edx,15 and ax,7fffh mov dx,sptr:[ebx+edx*2] rol eax,16 mov ax,dx rol eax,16 elseif (regsCnt EQ 1) ; regs1 = PTR16 destreg16 TEXTEQU @SubStr(dreg,2) if InList(,) OR InList(,) push edx endif mov edx,destreg shr edx,15 and destreg16,7fffh mov dx,sptr:[ebx+edx*2] rol destreg,16 mov destreg16,dx rol destreg,16 if InList(,) OR InList(,) pop edx endif elseif (regsCnt EQ 2) ; regs1:regs2 = PTR16 if InList(,) OR InList(,) push edx endif mov edx,eax shr edx,15 mov regs1,sptr:[ebx+edx*2] ifdifi ,regs2 mov regs2,ax endif and regs2,7fffh if InList(,) OR InList(,) pop edx endif else .err Too many destination regs passed to TranslateHandle endif if InList(,) OR InList(,) pop ebx endif endif if THOptFULL jmp THOk THErr: ; determine which registers to use... if (regsCnt EQ 0) ; eax,dx:ax = PTR16 xor eax,eax xor edx,edx elseif (regsCnt EQ 1) ; regs1 = PTR16 xor regs1,regs1 elseif (regsCnt EQ 2) ; regs1:regs2 = PTR16 xor regs2,regs2 mov regs1,regs2 else .err Too many destination regs passed to TranslateHandle endif THOk: endif ; if wSel wasn't in segment register restore ds RestoreSegReg elseif ((wMemType EQ PTR32) AND (wRetType EQ PTR16)) ; input: eax = 32-bit offset ; output: eax = 16:16 ptr (ebx,ecx,edx trashed) mov ebx,THHdrPos mov edx,eax shr edx,15 mov ecx,sptr:[ebx].dwSelTable and eax,7fffh rol eax,16 mov ax,sptr:[ecx+edx*2] rol eax,16 else ifnb Save endif int 3 cCall Local32Translate, ifnb mov dreg,eax endif endif endm ;Validation macro for fast 32bit handle validation ValidHandle32 macro wSel,hMem,opts local VH32_Err local VH32_End ifb test hMem,2 ; ZF=0 => 32-bit, ZF=1 => 16-bit else ParseDestReg ProcessOptions ChooseSegReg wSel UseSegReg wSel if THForce32 mov ecx, THHdrPos endif test destreg8,3 ; make sure hMem % 4 = 0 jnz VH32_Err ; if not we know it isn't valid cmp destreg16,L32HdrSize ; see if handle points in header jb VH32_Err ; if THForce32 cmp destreg32,sptr:[ecx].hCommit ; see if handle is else cmp destreg32,sptr:[THHdrPos].hCommit ; see if handle is endif ; below commit line ja VH32_Err if THForce32 mov destreg32,sptr:[destreg32+ecx] else mov destreg32,sptr:[destreg32+THHdrPos] endif cmp destreg32,10000h ; see if its free jae VH32_End ; if not we're happy VH32_Err: xor ax,ax ; set zero flag VH32_End: RestoreSegReg endif ; cCall Local32ValidHandle, endm ifndef ?INHEAP32 .286p externFP Local32Init externFP Local32Alloc externFP Local32ReAlloc externFP Local32Size externFP Local32Translate externFP Local32ValidHandle externFP Local32Free externFP Local32GetSel endif if 0 ;*/ /* Flags for Local32Init */ #define LINIT_MAX16HEAP 1 #define LINIT_TILEHEAP 2 #define LINIT_EMS16HEAP 4 /* Flags for Local32Alloc */ #define LMEM32_64K 1 #define LMEM32_ZEROINIT 2 /* Address types */ #define NOHPTR16 (WORD) (-2) #define NOHPTR32 (WORD) (-1) #define HANDLE16 0 #define PTR16 1 #define PTR32 2 DWORD FAR PASCAL Local32Init(WORD wSel, DWORD dwcbInit, DWORD dwcbMax, DWORD dwFlags); DWORD FAR PASCAL Local32Alloc(DWORD linHdr, DWORD dwcbRequest, WORD wType, DWORD dwFlags); DWORD FAR PASCAL Local32ReAlloc(DWORD linHdr, DWORD dwMem, WORD wType, DWORD dwcbNew, DWORD dwFlags); DWORD FAR PASCAL Local32Size(DWORD linHdr, DWORD dwMem, WORD wType); DWORD FAR PASCAL Local32Translate(DWORD linHdr, DWORD dwMem, WORD wMemType, WORD wRetType); BOOL FAR PASCAL Local32ValidHandle(DWORD linHdr, HANDLE hMem); BOOL FAR PASCAL Local32Free(DWORD linHdr, DWORD dwMem, WORD wMemType); WORD FAR PASCAL Local32GetSel(DWORD linHdr); #define TranslateHandle(a,b,c,d) Local32Translate((a),(b),(c),(d)) #ifndef _flat #define _flat __based32(__segname("_DATA")) #endif #define HTOFLAT(p,h) \ { \ DWORD _flat* _tp_ = (DWORD _flat*)((h)+0x10000); \ (p) = ((void _flat*)*_tp_); \ } ;/* endif ;*/