;/* GDIMACRO.INC - GDI macros LMHLockCnt equ byte ptr 3 wptr equ word ptr bptr equ byte ptr PtoLMH macro r1,r2 ifnb mov r1,[r2 - 2] else mov r1,[r1 - 2] endif endm LMHtoP macro r1,r2 ;; Local Movable Handle to pointer ifnb mov r1,[r2] else mov r1,[r1] endif endm LMHtoPES macro r1,r2 ;; Local Movable Handle to ptr, deref vi ES ifnb mov r1,es:[r2] else mov r1,es:[r1] endif endm LMPsize macro r1,r2 ;; Local Movable pointer size mov r1,-4[r2] endm LockDataSegment macro endm UnlockDataSegment macro endm farLockDataSegment macro endm farUnlockDataSegment macro endm ; NOTE: The lock/unlock macros are not going to check ; for under/overflow. Its highly unlikely that ; it will occur, and if it does, we'll be hosed ; anyway.... LLock macro r inc LMHLockCnt[r] ;;Increment ref count endm LUnlock macro r dec LMHLockCnt[r] ;;Decrement reference count endm LLocked? macro r cmp LMHLockCnt[r],0 ;; is the handle locked? endm LLockES macro r inc es:LMHLockCnt[r] ;;Increment ref count endm LUnlockES macro r dec es:LMHLockCnt[r] ;;Decrement reference count endm LLockedES? macro r cmp es:LMHLockCnt[r],0 ;; is the handle locked? endm ; The jmpnext macro and associated symbols are used to generate ; the fall-through chain and generate the labels required for ; error checking. ??ji = 0 ;;Initial index value jmpnext macro e jn %??ji,%(??ji+1),e ;;Set next label endm jn macro i,j,e .sall ??ji&i: .xall ifb ;;If not the end of the chain db 03dh ;;mov bx, next two bytes errn$ ??ji&j,+2 ;;mext lable must be two bytes away endif ??ji=j ;;increment counter endm ifdef DEBUG ifndef ?HELPER ExternFP ValidateHandle endif endif ;* ;* Valid? macro Handle,Error_exit,LowLimit,UpLimit ;* ;* Validate an object handle. A valid handle must 1)not be NULL 2)be for ;* an object of the specified type. ;* ;* ;* Macro Arguments: ;* ;* Handle - object handle ;* Error_exit - the next instruction to execute if an invalid obj ;* LowLimit, UpLimit - Range of the possible object type ;* ;* Return: ;* DS:BX - pointer to the object ;* ;* Trashes: ;* AX,BX,CX,DX ;* Valid? macro Handle,Error_exit,LowLimit,UpLimit local ValidHandle,Invalidexit ifdef DISABLE ifdef DEBUG ;****************************************************************************** ; ; Object handle validation in a debug version ; ;****************************************************************************** push dx mov bx, LowLimit ifnb mov dx, UpLimit else mov dx, LowLimit endif cCall , pop dx or ax,ax jnz ValidHandle jmp Error_exit else ;****************************************************************************** ; ; Object handle validation in a retail version ; ;****************************************************************************** mov bx,Handle ; NULL handle validation or bx,bx jz Invalidexit LMHtoP bx ; dereference for object pointer mov ax,ilObjType[bx] ; Validate the object type irp stock_type, ife stock_type-LowLimit and ax,NOT OBJ_FLAGS ; mask only for possible stock obj endif endm ifnb cmp ax,LowLimit ; Check object type range jl Invalidexit cmp ax,UpLimit jle ValidHandle else cmp ax,LowLimit ; Check a particular object type je ValidHandle endif Invalidexit: xor ax,ax jmp Error_exit ; it is not a valid handle endif ValidHandle: else ; !DISABLE mov bx,Handle LMHtoP bx endif ; !DISABLE endm ValidDebug? macro Handle,LowLimit,UpLimit ifdef DEBUG push bx push dx mov bx, LowLimit ifnb mov dx, UpLimit else mov dx, LowLimit endif cCall , pop dx pop bx endif endm ;* ;* Notify? macro ;* ;* Tests if the given dc is hooked, and if it is, calls off to ;* send a notification to whomever is hooked into the dc notification ;* hook. ;* ;* Macro Arguments: ;* ;* hDC - the actual DC handle ;* lParam - the notification code to send via the hook ;* errLbl - optional parameter, which gives label to ;* jump to if notification returns 0 ;* ;* Trashes: ;* AX,BX,flags ;* ifdef LATER ifndef ?LVB ExternFP SendDCNotify ExternFP SendInvalidVisRgn endif Notify? macro hDC,code,param1,param2,errLbl mov bx,hDC mov bx,[bx] mov ax,word ptr lpNotifyProc[bx] or ax,word ptr lpNotifyProc+2[bx] jz @F push hDC mov ax,code push ax mov ax,param1 push ax mov ax,param2 push ax cCall ifnb or ax,ax endif ifnb jnz @F jmp errLbl endif @@: endm ;* VNotify? ;* ;* Tests if the given dc is hooked and has an invalid visrgn. If ;* it does, then a notification is sent to the dc hook. ;* ;* Warning: ;* if we call the call-back, the gdi heap can be compacted, ;* so no dereferenced handles can be relied on after making ;* this call. ;* ;* Entry: ;* hDC - handle to dc to check and send notifications ;* reg - scratch register to use ;* ;* Exit: ;* reg - trashed ;* flags - trashed ;* VNotify? macro hDC,reg mov reg,hDC LMHtoP reg test byte ptr DCFlags[reg],BadVisRgn jz @F cCall , @@: endm VNotifyPtr? macro reg,hDC test byte ptr DCFlags[reg],BadVisRgn jz @F cCall , @@: endm endif ;----------------------------------------------------------------------- ; cProcVDO - cProc "Validate Debug Only" ; ; Same as cProc, except used for "Validate in Debug Only" entry points. ; Declares Iname if debug, name if retail. ; cProcVDO macro name,opts,savelist ifdef DEBUG cProc ,, else LabelFP cProc ,, endif endm GDIGLOBALLOCK macro Handle,segRegister,offsetRegister .lall ifndef GlobalLock ExternFP GlobalLock endif cCall , ifnb mov segRegister,dx endif ifnb mov offsetRegister,ax endif .sall endm GDIGLOBALUNLOCK macro Handle ifndef GlobalUnlock ExternFP GlobalUnlock endif cCall , endm GDIRequestSem macro endm GDIClearSem macro endm ; setlbl generates a macro which will declare labels public ; if "debug" has been defined. The symbol generated will ; be of the form: ; ; filename_label ; ; where ; ; filename is the parameter given to the setlbl macro, ; and label is the first parameter given to the lbl macro ; which is generated by setlbl. ; ; ; lbl is the macro which will define the given label and ; if "debug" is defined, declare it public. ; ; ; lbl foo,,opt2 ; ; where ; ; foo is the name of the label ; opt1 is an optional second parameter. If present, ; it must be some combination of ; proc, label, near, far, byte, word, dword ; opt2 is an optional third parameter which if present ; must be "public". It forces the declaration of ; "foo" to be public. setlbl macro filename lbl ¯o n,opt1,opt2 .sall ifnb n opt1 ifdef debug filename&&_&&n equ n public filename&&_&&n endif else n: ifdef debug filename&&_&&n: public filename&&_&&n endif endif ifnb public n endif .xall &endm endm smov macro segreg1,segreg2 push segreg2 pop segreg1 endm jmps macro there jmp short there endm ; structure to allow easy access to components of DWORD. HILO struc lo dw ? hi dw ? HILO ends ; structure to allow easy access to components of LP. OFFSEL struc off dw ? sel dw ? OFFSEL ends ;--------------------------------------------------------------------------; ; ABS ; Maps the signed integer in AX to a positive signed integer to be ; returned in AX. If FOO is blank then 8000h is mapped to 7fffh. ; Since GDI defines MININT as 8000h, we should deal with this case. ; If FOO is non-blank, 8000h is mapped to 8000h. (Usually bad!) ; All other integers behave as one would expect with Absolute Value. ; Entry: ; AX = signed integer (8000h to 7fffh) ; Returns: ; AX = ABS(AX) ; Trashes: ; DX, FLAGS ; ; History: ; Tue 29 October 1991 -by- Raymond E. Endres [rayen] ; Wrote it. ;--------------------------------------------------------------------------; ABS macro FOO ;NOTE: default FOO is blank! cwd xor ax,dx sub ax,dx ifb ;if FOO is blank cwd ;remove the 8000h case xor ax,dx endif endm ;--------------------------------------------------------------------------; ; min_ax ; returns min of AX and REG ; Entry: ; AX = integer ; REG = general purpose register containing an integer ; Returns: ; AX = min(AX,REG) ; Error Returns: ; none ; Registers Destroyed: ; DX,FLAGS ; Registers Preserved: ; BX,CX,SI,DI,DS,ES,BP ; Calls: ; none ; History: ; Sat Mar 07, 1987 08:39:04p -by- Tony Pisculli [tonyp] ; wrote it ;--------------------------------------------------------------------------; min_ax macro REG sub ax,REG cwd and ax,dx add ax,REG endm ;--------------------------------------------------------------------------; ; max_ax ; returns max of AX and REG ; Entry: ; AX = integer ; REG = general purpose register containing an integer ; Returns: ; AX = max(AX, REG) ; Error Returns: ; none ; Registers Destroyed: ; DX,FLAGS ; Registers Preserved: ; BX,CX,SI,DI,DS,ES,BP ; Calls: ; none ; History: ; Sat Mar 07, 1987 08:41:38p -by- Tony Pisculli [tonyp] ; wrote it ;--------------------------------------------------------------------------; maxintoax macro mem1,mem2 mov ax,mem1 max_ax mem2 endm max_ax macro REG sub ax,REG cwd not dx and ax,dx add ax,REG endm ; The following equates are used for defining the target ; processor to the shift macros. GENERIC equ 0 ;CPU equ GENERIC ;CPU equ 88 ;CPU equ 86 ;CPU equ 186 CPU equ 286 ;CPU equ 386 ;--------------------------------------------------------------------------; ; shiftl ; ; shiftl is used to implement the advanced shift left immediate ; (SHL dest,count) functionality of the 286 and 386. ; ; Entry: ; DEST = var to shift ; COUNT = number to shift by ; Returns: ; DEST = DEST shl COUNT ; Error Returns: ; none ; Registers Destroyed: ; none ; Registers Preserved: ; all ; Calls: ; none ; History: ; Sat Mar 07, 1987 08:44:30p -by- Tony Pisculli [tonyp] ; wrote it ;--------------------------------------------------------------------------; shiftl macro DEST,COUNT if (CPU eq 286) or (CPU eq 386) shl DEST,COUNT else REPT COUNT shl DEST,1 ENDM endif endm ;--------------------------------------------------------------------------; ; shiftr ; ; shiftr is used to implement the advanced shift right immediate ; (SHR dest,count) functionality of the 286 and 386. ; ; Entry: ; DEST = var to shift ; COUNT = number to shift by ; Returns: ; DEST = DEST shr COUNT ; Error Returns: ; none ; Registers Destroyed: ; none ; Registers Preserved: ; all ; Calls: ; none ; History: ; Sat Mar 07, 1987 08:44:52p -by- Tony Pisculli [tonyp] ; wrote it ;--------------------------------------------------------------------------; shiftr macro DEST,COUNT if (CPU eq 286) or (CPU eq 386) shr DEST,COUNT else REPT COUNT shr DEST,1 ENDM endif endm ;--------------------------------------------------------------------------; ; nop32 ; ; compensate for bug in the 386 chip and 32-bit string operations. ; ;--------------------------------------------------------------------------; nop32 macro db 067h nop endm if 0 */ #ifndef DEBUG #include "igdi.inc" #endif #define MAX(a,b) ((a)>(b)?(a):(b)) #define MIN(a,b) ((a)<=(b)?(a):(b)) #define ABS(x) (((x) >= 0) ? (x) : (-(x))) #define LBYTE(x) ((BYTE)((x)&0xFF)) #define HBYTE(y) ((BYTE)(((y)>>8)&0xFF)) #define LWORD(x) ((short)((x)&0xFFFF)) #define HWORD(y) ((short)(((y)>>16)&0xFFFF)) #define MAKELONG(h,l) ((long)(((WORD)l)|(((long)h)<<16))) extern far PASCAL ValidateHandle(HANDLE, short, short); #ifdef DISABLE #define Valid(Handle, Low, High) ValidateHandle(Handle, Low, High) #else #define Valid(Handle, Low, High) TRUE #endif #ifdef DEBUG #define ValidDebug(Handle, Low, High) {if(!ValidateHandle(Handle, Low, High)) return(NULL);} #else #define ValidDebug(Handle, Low, High) TRUE #endif #define GDIGLOBALLOCK(x) GlobalLock(x) #define GDIGLOBALUNLOCK(x) GlobalUnlock(x) #define GDILOCKRESOURCE(x) LockResource(x) #define GDIENTERCRITSEC() #define GDIEXITCRITSEC() #define LockDataSegment() #define UnlockDataSegment() #define farLockDataSegment() #define farUnlockDataSegment() #define GDIRequestSem() #define GDIClearSem() #define LOWORD(l) ((WORD)(l)) #define HIWORD(l) ((WORD)(((DWORD)(l) >> 16) & 0xFFFF)) #define SELECTOROF(lp) HIWORD(lp) #define OFFSETOF(lp) LOWORD(lp) /* endif ;*/