CodeData equ include thkrp.inc include cbcheck.inc include thkframe.inc include public.inc include thkmacro.inc include struc.inc include cbcid.inc include gdicbid.inc externDef PrivateEscape:near16 externDef CALLBACK_BODY_16:far16 externDef Escape:far16 externDef AllocCallback:far16 externDef MapLS:far16 externDef UnmapLS:far16 externDef GlobalAlloc:far16 externDef GlobalSize:far16 externDef GlobalFree:far16 externDef GlobalLock:far16 externDef GlobalUnlock:far16 externDef GetTextExtentPoint:far16 ifdef DEBUG externDef _wsprintf:far16 externDef OutputDebugString:far16 endif externDef AllocSelectorArray:far16 externDef SetSelectorBase:far16 externDef SetSelectorLimit:far16 externDef FreeSelector:far16 externDef SelectorAccessRights:far16 externDef GetLastError:far16 ilObjType equ 2 ObjPrivate equ 2000H Stock equ 8000H INT_OBJ_FLAGS equ (Stock or ObjPrivate) INT_MIN_OBJ equ 4f47h INT_OBJ_PEN equ 4f47h INT_OBJ_BRUSH equ 4f48h INT_OBJ_FONT equ 4f49h INT_OBJ_PALETTE equ 4f4ah INT_OBJ_BITMAP equ 4f4bh INT_OBJ_RGN equ 4f4ch INT_OBJ_DC equ 4f4dh INT_OBJ_IC equ 4f4eh INT_OBJ_DISABLED_DC equ 4f4fh INT_OBJ_METADC equ 4f50h INT_OBJ_METAFILE equ 4f51h INT_OBJ_MF equ 4f52h INT_MAX_OBJ equ 4f52h ;; Writes message to debug port. ;; ;; Usage: ;; DPRINT "I'm feeling buggy." ;; DPRINT macro string local mes, skip_mes jmp skip_mes mes db &string&,13,10,0 skip_mes: push eax ;Save all registers not preserved by PASCAL format. push ebx push ecx push edx push cs ;Arg: OutputDebugString(lpstr) push offset mes call OutputDebugString pop edx pop ecx pop ebx pop eax endm ;DPRINT RECT16_SIZE equ 8 POINT16_SIZE equ 4 LOGFONT32_SIZE equ 60 BITMAP32_SIZE equ 24 DIBSECTION32_SIZE equ 84 BITMAP16 struc bm16_Type dw ? bm16_Width dw ? bm16_Height dw ? bm16_WidthBytes dw ? bm16_Planes db ? bm16_BitsPixel db ? bm16_Bits dd ? BITMAP16 ends BITMAP32 struc bm32_Type dd ? bm32_Width dd ? bm32_Height dd ? bm32_WidthBytes dd ? bm32_Planes dw ? bm32_BitsPixel dw ? bm32_Bits dd ? BITMAP32 ends ABC16 struc abcA dw ? abcB dw ? abcC dw ? ABC16 ends fLocalFlag equ fGdiLog16 ; Corresponds to the 32 bit BITMAPINFOHEADER structure. BMIH32 struc bi32_Size dd ? bi32_Width dd ? bi32_Height dd ? bi32_Planes dw ? bi32_BitCount dw ? bi32_Compression dd ? bi32_SizeImage dd ? bi32_XPelsPerMeter dd ? bi32_YPelsPerMeter dd ? bi32_ClrUsed dd ? bi32_ClrImportant dd ? BMIH32 ends ; Corresponds to the 32-bit BITMAPCOREHEADER structure. BMCH32 struc bc32_Size dd ? bc32_Width dw ? bc32_Height dw ? bc32_Planes dw ? bc32_BitCount dw ? BMCH32 ends ; Corresponds to the 32-bit BITMAPV4HEADER structure. BMV4H32 struc bv432_Size dd ? bv432_Width dd ? bv432_Height dd ? bv432_Planes dw ? bv432_BitCount dw ? bv432_Compression dd ? bv432_SizeImage dd ? bv432_XPelsPerMeter dd ? bv432_YPelsPerMeter dd ? bv432_ClrUsed dd ? bv432_ClrImportant dd ? bV432_RedMask dd ? bV432_GreenMask dd ? bV432_BlueMask dd ? bV432_AlphaMask dd ? bV432_CSType dd ? bV4Endpoints db 36 dup (?) bV4GammaRed dd ? bV4GammaGreen dd ? bV4GammaBlue dd ? BMV4H32 ends BMV5H32 struc bv532_Size dd ? bv532_Width dd ? bv532_Height dd ? bv532_Planes dw ? bv532_BitCount dw ? bv532_Compression dd ? bv532_SizeImage dd ? bv532_XPelsPerMeter dd ? bv532_YPelsPerMeter dd ? bv532_ClrUsed dd ? bv532_ClrImportant dd ? bV532_RedMask dd ? bV532_GreenMask dd ? bV532_BlueMask dd ? bV532_AlphaMask dd ? bV532_CSType dd ? bV5Endpoints db 36 dup (?) bV5GammaRed dd ? bV5GammaGreen dd ? bV5GammaBlue dd ? bV5Intent dd ? bV5ProfileData dd ? bV5ProfileSize dd ? bV5Reserved dd ? BMV5H32 ends THUNK16B SEGMENT WORD USE16 PUBLIC 'CODE' IF 0 REPACK_DEVMODE_32_16 macro externDef Repack_Devmode_32_16_Proc:near16 call Repack_Devmode_32_16_Proc endm ;-----------------------------------------------------------------------; ; Repack_Pevmode_32_16_Proc ; ; Entry: ; DS:ESI --> 32-bit source (ESI might be flat offset) ; ES:EDI --> 16-bit destination (EDI is zero-extended from DI) ; direction flag cleared ;-----------------------------------------------------------------------; Repack_Devmode_32_16_Proc proc near public ; local done ;Move the common part as a single block move. MoveBytes <(size DEVMODECOMMON)> ;Update the dmSize field ;;;; mov es:[di].(dmSize - (size DEVMODECOMMON)),size DEVMODE16 ;!!!Clear out any win32-only flags ;and es:[di].(dmFields - (size DEVMODECOMMON)),0FFFFh ;Insert win16-only fields. EDI points to the byte after ;DEVMODECOMMON. Afterwards, will point to byte after DEVMODE16. ;ZeroBytes <((size DEVMODE16) - (size DEVMODECOMMON))> ;Skip over the extra win32 fields. ESI still points to the byte ;after DEVMODECOMMON. add esi,(size DEVMODE32) - (size DEVMODECOMMON) ;Move the driver-dependent part. EDI points to the byte after ;DEVMODE16. mov cx,es:[di].(dmDriverExtra - (size DEVMODE16)) jcxz done movzx ecx,cx mov edx,ecx shr cx,2 and dx,3 rep movs dword ptr es:[edi],dword ptr ds:[esi] mov cx,dx rep movs byte ptr es:[edi],byte ptr ds:[esi] done: ret Repack_Devmode_32_16_Proc endp ENDIF DIB_BITS_SIZE macro externDef Dib_Bits_Size_Proc:near16 call Dib_Bits_Size_Proc endm ;-----------------------------------------------------------------------; ; Dib_Bits_Size_Proc ; ; Inputs: ; eax: linear address of 32-bit BITMAPINFOHEADER (or BITMAPCOREHEADER) ; struct. ; ; Output: ; ecx: inferred size of bitmap data, or 0 for failure. ; ; Formula is: ; if bi32_Compression != (BI_RGB | BI_BITFIELDS) ; size = bi32_SizeImage ; else ; size = ((Width * BitCount + 31) / 32) * 4 * Height * Planes ;-----------------------------------------------------------------------; Dib_Bits_Size_Proc proc near public ; local exit,fail_exit,use_formula ; local bitmapcoreheader,bitmapinfoheader push ds mov ds,FlatData mov esi,eax ; DPRINT "DIB_BIT_SIZE: Computing bitmap data size." ; int 3 mov eax, dword ptr [esi] cmp eax, SIZEOF BMIH32 je bitmapinfoheader cmp eax, SIZEOF BMV4H32 je bitmapinfoheader cmp eax, SIZEOF BMV5H32 je bitmapinfoheader cmp eax, SIZEOF BMCH32 je bitmapcoreheader ; int 3 jmp fail_exit bitmapcoreheader: movzx eax, [esi].bc32_Width movzx ebx,[esi].bc32_BitCount mul ebx jc fail_exit add eax, 31 jc fail_exit shr eax, 5 ;Divide by 32 (and exorcise remainder!) shl eax, 2 ;Multiply by 4 movzx ecx, [esi].bc32_Height mul ecx jc fail_exit movzx ebx,[esi].bc32_Planes mul ebx mov ecx,eax jnc exit jmp fail_exit bitmapinfoheader: cmp dword ptr [esi].bi32_Compression, BI_RGB je use_formula cmp dword ptr [esi].bi32_Compression, BI_BITFIELDS je use_formula mov ecx, [esi].bi32_SizeImage jmp exit use_formula: ; DPRINT "DIB_BIT_SIZE: Using formula." mov eax, [esi].bi32_Width xor ebx,ebx mov bx,[esi].bi32_BitCount mul ebx jc fail_exit add eax, 31 jc fail_exit shr eax, 5 ;Divide by 32 (and exorcise remainder!) shl eax, 2 ;Multiply by 4 mov ecx,[esi].bi32_Height test ecx,ecx ;top down dibs ? jns got_height neg ecx ;make it positive. got_height: mul ecx jc fail_exit xor ebx,ebx mov bx,[esi].bi32_Planes mul ebx mov ecx,eax jnc exit fail_exit: xor ecx,ecx exit: ; int 3 pop ds ret Dib_Bits_Size_Proc endp THUNK16B ENDS ;-----------------------------------------------------------------------; ; UNPACK__GETTEXTMETRICSA_lpMetrics ;-----------------------------------------------------------------------; UNPACK__GETTEXTMETRICSA_lpMetrics macro x, y PACK_TEXTMETRIC_16_32 endm ;-----------------------------------------------------------------------; ; PUSH__SETABORTPROC_pfnAbort ;-----------------------------------------------------------------------; PUSH__SETABORTPROC_pfnAbort macro iOffset, iTempOffset push dword ptr [bp+iOffset] push dword ptr CBID_ABORTPROC call AllocCallback push dx push ax endm ;-----------------------------------------------------------------------; ; PACK__STARTDOCA_lpdi ;-----------------------------------------------------------------------; OLD_DOCINFO_SIZE equ 12 NEW_DOCINFO_SIZE equ 20 PACK__STARTDOCA_lpdi macro iOffset, iTempOffset lods dword ptr ds:[esi] ; ax == lpdi->cbSize ; if cbSize is not the new sizeof(DOCINFO), ; assume lpdi is a 3.x style DOCINFO cmp ax,NEW_DOCINFO_SIZE je @F mov ax,OLD_DOCINFO_SIZE @@: push ax sub ax,2 stosw ;;cbSize (int) MAP_POINTER LOCAL__STARTDOCA_lpszDocNameTemp ;;PLUGGED lpszDocName MAP_POINTER LOCAL__STARTDOCA_lpszOutputTemp ;;PLUGGED lpszOutput pop ax cmp ax,OLD_DOCINFO_SIZE je @F MAP_POINTER LOCAL__STARTDOCA_lpszDatatypeTemp lods dword ptr ds:[esi] stosd ;;fwType @@: endm ;-----------------------------------------------------------------------; ; UNPACK__STARTDOCA_lpdi ;-----------------------------------------------------------------------; UNPACK__STARTDOCA_lpdi macro iOffset, iTempOffset pushd LOCAL__STARTDOCA_lpszDocNameTemp call UnmapLS pushd LOCAL__STARTDOCA_lpszOutputTemp call UnmapLS pushd LOCAL__STARTDOCA_lpszDatatypeTemp call UnmapLS endm ;-----------------------------------------------------------------------; ; body_THKESCAPE ;-----------------------------------------------------------------------; body_THKESCAPE macro bp_hdc equ bp_nEscape equ bp_cbInput equ bp_lpInData equ bp_lpOutData equ push word ptr bp_hdc push word ptr bp_nEscape push word ptr bp_cbInput push dword ptr bp_lpInData push dword ptr bp_lpOutData call PrivateEscape endm ;-----------------------------------------------------------------------; ; body_SETMETAFILEBITSEX ;-----------------------------------------------------------------------; body_SETMETAFILEBITSEX macro local exit bp_nSize equ bp_lpvData equ bp_hmem equ <[bp-2]> sub sp,2 ;make space for bp_hmem ; Protect ourselves -- no pointer or no bytes to copy mean no reason to ; call Win3.1. mov eax,bp_lpvData or eax,eax jz exit mov eax,bp_nSize or eax,eax jz exit ; Allocate a global handle to pass to Win3.1. If can't get handle return ; error. ; ;!!! This memory should be deleted in DeleteMetaFile. If the app never ; calls DeletMetaFile, it will be deleted when the process dies because ; GlobalAlloc tags the memory with the process that allocated it. pushw GMEM_MOVEABLE push eax call GlobalAlloc movzx eax,ax ;prepare for error return code or ax,ax jz exit ; Copy the data from the input buffer to the global memory we allocated. mov bp_hmem,ax push ds mov ds,FlatData ;DS:ESI --> source mov esi,bp_lpvData ; mov es,ax ;ES:EDI --> destination xor edi,edi ; ; Compute dword (ECX) and byte (DX) counts. We can use DX because it will ; contain 0, 1, or 2. When we copy bytes, the high word of ECX will already ; be zero from the dword-copy, so we only have to update CX for the ; byte-copy. mov ecx,dword ptr bp_nSize mov dx,cx shr ecx,2 and dx,3 cld rep movs dword ptr es:[edi], dword ptr ds:[esi] mov cx,dx rep movs byte ptr es:[edi], byte ptr ds:[esi] pop ds ; Since Win32 GetMetaFileBitsEx actually returns the bits for a disk ; metafile, we must patch the metafile header now. (This is compatible ; with NT.) xor edi,edi mov word ptr es:[edi], 1 ; METAHEADER.mtType = MEMORYMETAFILE ; !!! SetMetaFileBitsBetter just returns the handle passed in. With ; this assumption, we will be passing back the handle allocated above ; with GlobalAlloc. push word ptr bp_hmem call SetMetaFileBitsBetter movzx eax,ax ;prepare return code ; EAX = return code (global memory handle) exit: endm ;-----------------------------------------------------------------------; ; CREATEBITMAP_COMMON: ; ; Common thunk code for CreateBitmap() and CreateBitmapIndirect(). ; Tiles the bit buffer (if any), creates equivalent Win16 BITMAP ; structure on stack and calls Win16 CreateBitmapIndirect(). ; ; Note: All device-dependent bitmap scan lines are word-padded (not ; dword-padded) even in Win32 (decided this with DavidW: 2/93) ; ; Entry points: ; eax = 0:32 pointer to Win32 BITMAP structure. ; ; Exit: ; eax = result of Win16 CreateBitmapIndirect() if successfully ; thunked arguments. 0 if unsuccessful. ; ;-----------------------------------------------------------------------; CREATEBITMAP_COMMON macro local exit,fail_exit,dwFreeInfo,wOldDS ; DPRINT "Just entered CREATEBITMAP_COMMON. eax -> Win32 BITMAP" ; int 3 push bp mov bp,sp push ds ;Save ds xor edx,edx ;New local (to store result of TILE_BUFFER) push edx wOldDS equ word ptr [bp - 2] dwFreeInfo equ dword ptr [bp - 6] mov ds,FlatData mov esi,eax ;Infer the size of the bit buffer: ; ; size = ((width * bitspixel + 15) / 16) * 2 * height * planes ; mov ax,[esi].bm32_BitsPixel movzx eax,ax mul [esi].bm32_Width jc fail_exit add eax,15 jc fail_exit shr eax,4 shl eax,1 mov ebx,eax ;Tuck WidthBytes in safe register mul [esi].bm32_Height jc fail_exit xor ecx,ecx mov cx,[esi].bm32_Planes mul ecx jc fail_exit mov ecx,eax ; assert(ecx == size of bm32_Bits buffer) sub sp,14 ;make room for a Win16 BITMAP structure mov ax,ss mov es,ax mov di,sp ; repack Win32 BITMAP (ds:esi) into Win16 BITMAP (es:di) lodsd ds:[esi] ;Type (DWORD->WORD) stosw es:[di] lodsd ds:[esi] ;Width (DWORD->WORD) stosw es:[di] lodsd ds:[esi] ;Height (DWORD->WORD) stosw es:[di] add esi,4 ;WidthBytes (DWORD->WORD) mov ax,bx ; Replace with our own computed value stosw es:[di] lodsw ds:[esi] ;Planes (WORD->BYTE) stosb es:[di] lodsw ds:[esi] ;BitsPixel (WORD->BYTE) stosb es:[di] lodsd ds:[esi] ;lpBits (0:32 -> tiled 0:16) ; DPRINT "CREATEBITMAP_COMMON: About to tile buffer" ; int 3 push es ;Save registers that TILE_BUFFER push di ; trashes ; assert (eax == 0:32 ptr to bit data, ecx == inferred size of bit buffer) TILE_BUFFER pop di pop es jc fail_exit mov dwFreeInfo,ecx stosd es:[di] mov bx,sp push ss ;Arg: CreateBitmapIndirect(lpbm) push bx ;^^^ ; DPRINT "CREATEBITMAP_COMMON: About to call Win16 API." ; int 3 call CreateBitmapIndirect movzx eax,ax push eax ;save API result mov ecx,dwFreeInfo UNTILE_BUFFER pop eax ;restore API result jmp exit fail_exit: xor eax,eax exit: mov ds,wOldDS ;do this before restoring sp! mov sp,bp pop bp endm; CREATEBITMAP_COMMON ;-----------------------------------------------------------------------; ; body_CREATEBITMAPINDIRECT ;-----------------------------------------------------------------------; body_CREATEBITMAPINDIRECT macro mov eax,[bp_top] ;eax == 0:32 pointer to Win32 BITMAP CREATEBITMAP_COMMON endm ;-----------------------------------------------------------------------; ; body_CREATEBITMAP ; ; Create equivalent Win32 BITMAP structure on stack and call ; same code that CreateBitmapIndirect() does. ;-----------------------------------------------------------------------; body_CREATEBITMAP macro local bp_nWidth, bp_nHeight, bp_nPlanes, bp_nBitCount, bp_lpBits bp_nWidth equ [bp_top] bp_nHeight equ [bp_top+4] bp_nPlanes equ [bp_top+8] bp_nBitCount equ [bp_top+12] bp_lpBits equ [bp_top+16] ; Create an equivalent Win32 BITMAP structure on stack and pass it ; to CreateBitmapIndirect pushd bp_lpBits pushw bp_nBitCount pushw bp_nPlanes pushd 0 ;Dummy WidthBytes (CREATEBITMAPCOMMON ignores it) pushd bp_nHeight pushd bp_nWidth pushd 0 ;Type mov ax,sp push ss ;Arg: MapSL(sel:off) push ax ;^^^ call MapSL ;OK: ss is never a movable handle here. CREATEBITMAP_COMMON mov sp,bp endm ;body_CREATEBITMAP ;------------------------------------------------------------------------- ; RAWPACK_GETBITMAPBITS ;------------------------------------------------------------------------- RAWPACK__GETBITMAPBITS_lpBits macro lpBits,lp1616 local exit,fail_exit mov eax,[bp + &lpBits] or eax,eax jz fail_exit mov ecx,[bp_top + 4] ;dwCount (size of buffer) or ecx,ecx jz fail_exit ;is this the right action?? TILE_BUFFER mov [bp - &lp1616&],eax mov LOCAL__GETBITMAPBITS_dwFreeInfo,ecx jmp exit fail_exit: mov sp,bp xor eax,eax ERRCHK_EXIT 0,87,Exit_12 exit: endm ;RAWPACK_GETBITMAPBITS_lpBits ;------------------------------------------------------------------------- ; RAWUNPACK_GETBITMAPBITS ;------------------------------------------------------------------------- RAWUNPACK__GETBITMAPBITS_lpBits macro lpBits,lp1616 mov ecx,LOCAL__GETBITMAPBITS_dwFreeInfo UNTILE_BUFFER endm ;RAWUNPACK_GETBITMAPBITS ;------------------------------------------------------------------------- ; RAWPACK_SETBITMAPBITS ;------------------------------------------------------------------------- RAWPACK__SETBITMAPBITS_lpBits macro lpBits,lp1616 local exit,fail_exit mov eax,[bp + &lpBits] or eax,eax jz fail_exit mov ecx,[bp_top + 4] ;dwCount (size of buffer) or ecx,ecx jz fail_exit ;(fail return or 0 bytes copied: it's the same) TILE_BUFFER mov [bp - &lp1616&],eax mov LOCAL__SETBITMAPBITS_dwFreeInfo,ecx jmp exit fail_exit: mov sp,bp xor eax,eax ERRCHK_EXIT 0,87,Exit_12 exit: endm ;RAWPACK_SETBITMAPBITS ;------------------------------------------------------------------------- ; RAWUNPACK_SETBITMAPBITS ;------------------------------------------------------------------------- RAWUNPACK__SETBITMAPBITS_lpBits macro lpBits,lp1616 mov ecx,LOCAL__SETBITMAPBITS_dwFreeInfo UNTILE_BUFFER endm ;RAWUNPACK_SETBITMAPBITS ;-----------------------------------------------------------------------; ; body_DELETEMETAFILE ;-----------------------------------------------------------------------; body_DELETEMETAFILE macro local exit bp_hmf equ ; !!! Determine whether or not to delete directly! push bp_hmf call DeleteMetaFile cwde exit: endm IF 0 ;-----------------------------------------------------------------------; ; body_CREATEICA ;-----------------------------------------------------------------------; body_CREATEICA macro local exit local repack_devmode local push_callframe bp_lpszDriver equ bp_lpszDevice equ bp_lpszOutput equ bp_lpdm equ bp_lpdmTmp equ bp_hdm equ < word ptr [bp-6]> bp_lpszDriverTmp equ bp_lpszDeviceTmp equ bp_lpszOutputTmp equ sub eax,eax push eax ;bp_lpdmTmp push ax ;bp_hdm push eax ;bp_lpszDriverTmp push eax ;bp_lpszDeviceTmp push eax ;bp_lpszOutputTmp mov ecx,bp_lpdm or ecx,ecx jnz repack_devmode jmp push_callframe ; We have to repack the DEVMODE structure. Compute the size needed, ; allocate it, setup pointers and invoke the macro to do the copying. repack_devmode: push word ptr GMEM_MOVEABLE mov es,FlatData movzx eax,es:[ecx].dmSize movzx ecx,es:[ecx].dmDriverExtra add eax,ecx push eax call GlobalAlloc movzx eax,ax ;prepare for error or ax,ax jz exit mov word ptr bp_hdm,ax ; Set up DS:ESI ; ES:EDI push ds mov ds,FlatData mov esi,bp_lpdm mov es,ax sub edi,edi mov word ptr bp_lpdmTmp[0],di mov word ptr bp_lpdmTmp[2],ax cld REPACK_DEVMODE_32_16 pop ds push_callframe: push dword ptr bp_lpszDriver call MapLS ;PLUGGED mov bp_lpszDriverTmp,eax push eax push dword ptr bp_lpszDevice call MapLS ;PLUGGED mov bp_lpszDeviceTmp,eax push eax push dword ptr bp_lpszOutput call MapLS ;PLUGGED mov bp_lpszOutputTmp,eax push eax push bp_lpdmTmp call CreateIC movzx eax,ax push eax mov cx,bp_hdm or cx,cx jz @F push cx call GlobalFree @@: pushd bp_lpszOutputTmp call UnmapLS pushd bp_lpszDeviceTmp call UnmapLS pushd bp_lpszDriverTmp call UnmapLS pop eax exit: endm ENDIF ;-----------------------------------------------------------------------; ; body_GETOUTLINETEXTMETRICSA ;-----------------------------------------------------------------------; OUTLINETEXTMETRIC16_SIZEX equ 114+3*32+64 OUTLINETEXTMETRIC32_SIZEX equ 212+3*32+64 body_GETOUTLINETEXTMETRICSA macro local push_callframe local exit bp_hdc equ bp_cbData equ bp_lpotm equ bp_lpotm16 equ bp_lpotm32 equ sub eax,eax push eax ; Make room for lpotm16 push eax ; Make room for lpotm32 cmp dword ptr bp_lpotm, 0 ; Size call? je push_callframe ; Yes, drop thru ; Make 16bit return buffer sub sp, OUTLINETEXTMETRIC16_SIZEX mov word ptr bp_lpotm16[0],sp mov word ptr bp_lpotm16[2],ss ; Make 32bit temp buffer sub sp, OUTLINETEXTMETRIC32_SIZEX mov word ptr bp_lpotm32[0],sp mov word ptr bp_lpotm32[2],ss push_callframe: push word ptr bp_hdc pushw OUTLINETEXTMETRIC16_SIZEX push dword ptr bp_lpotm16 call GetOutlineTextMetrics movzx eax,ax test eax, eax ; Win16 return success? jz exit ; No, return NULL cmp dword ptr bp_lpotm, 0 ; Caller really wants data? jne unpackotm ; Yes, unpack and copy it to him add eax, (OUTLINETEXTMETRIC32_SIZE - OUTLINETEXTMETRIC16_SIZE) jmp exit ; No, add delta and return unpackotm: ; Unpack the OUTLINETEXTMETRICS structure. push eax ; Save rc push ds ; Save ds xor esi, esi ; lds si, bp_lpotm16 ; ds:[esi] -> otm16 temp xor edi, edi ; les di, bp_lpotm32 ; es:[edi] -> otm32 temp cld PACK_OUTLINETEXTMETRIC_16_32 pop ds ; Restore ds (FlatLand) xor esi, esi ; fs:[esi] -> otm32 temp lfs si, bp_lpotm32 ; mov es, FlatData ; es:[edi] -> caller's buffer mov edi, bp_lpotm ; mov ecx, bp_cbData ; Copy amount caller requested rep movsb es:[edi], fs:[esi] ; pop eax ; Restore rc exit: mov sp,bp endm ;-----------------------------------------------------------------------; ; body_GETOBJECTA ;-----------------------------------------------------------------------; body_GETOBJECTA macro local exit local type_palette local type_brush local type_pen local type_font local copy_bitmap local copy_palette local copy_brush local copy_pen local copy_font local copy_data local reload_dst local GO_BUF_SIZE bp_hObject equ bp_nCount equ bp_lpObject equ bp_lpObjectTmp equ ;Make the temporary buffer big enough for 32-bit DIBSECTION, the biggest ;structure returned by GetObjectA32. We will allocate two temporary ;buffers. The first will receive the bits from Win3.1. The second ;will receive the repacked bits, and will then be copied to the output ;buffer. ; GO_BUF_SIZE equ DIBSECTION32_SIZE xor eax,eax push eax ; ptr param #1 bp_lpObjectTmp sub sp,GO_BUF_SIZE*2 ; alloc two temp buffers mov word ptr bp_lpObjectTmp[0],sp ; save buffer offset mov word ptr bp_lpObjectTmp[2],ss ; save buffer selector ; create new call frame and make the call push word ptr bp_hObject push word ptr GO_BUF_SIZE ; temp buffer size push dword ptr bp_lpObjectTmp call GetObject ; call 16-bit version cwde or ax,ax jz exit ; nothing to unpack mov si,bp_hObject ; dereference the object & find out mov cx,INT_OBJ_FONT ; assume it's a font test si,2 ; is it a moveable handle jz GO_Branch ; if not it must be a font mov si,[si] ; what type it is (LMHtoP) mov cx,[si].ilObjType ; and ch,HIGH (NOT INT_OBJ_FLAGS) ; GO_Branch: mov si,word ptr bp_lpObjectTmp mov edi,dword ptr bp_lpObject cld cmp cx,INT_OBJ_PALETTE je type_palette cmp cx,INT_OBJ_BRUSH je type_brush cmp cx,INT_OBJ_PEN je type_pen cmp cx,INT_OBJ_FONT je type_font ; Structure conversion code ; Each of these code fragments must leave with ; eax = computed number of bytes for return structure. ; bitmap or edi,edi jnz copy_bitmap mov eax,DIBSECTION32_SIZE ; sizeof DIBSECTION jmp exit copy_bitmap: mov di,ss mov ds,di mov es,di lea di,[si+GO_BUF_SIZE] lodsw ; bmType cwde stosd lodsw ; bmWidth mov cx,ax cwde stosd lodsw ; bmHeight cwde stosd lodsw ; bmWidthBytes cwde stosd ;store it lodsb ; bmPlanes cbw stosw lodsb ; bmBitsPixel cbw stosw ; the bmBits field will be non NULL for CreateDIBSection bitmaps and we need ; to convert that to a flat pointer. lodsd ; get bmBits or eax,eax ; is it null ? jz short @f ; yes, no translation needed. push eax ; 16:16 pointer call MapSL ; convert to flat. @@: stosd ; save. ; what follows now is the DIBSECTION structure minus the BITMAP structure. ; however, all the fields here are properly aligned and can be moved in one shot. mov cx,(DIBSECTION32_SIZE - BITMAP32_SIZE)/4 .errnz (DIBSECTION32_SIZE - BITMAP32_SIZE) and 3 rep movsd mov eax,DIBSECTION32_SIZE ; bytes generated thus far. jmp copy_data type_font: or edi,edi jnz copy_font mov eax,LOGFONT32_SIZE jmp exit copy_font: mov di,ss mov ds,di mov es,di lea di,[si+GO_BUF_SIZE] PACK_LOGFONT_16_32 mov eax,LOGFONT32_SIZE jmp copy_data type_pen: or edi,edi jnz copy_pen mov eax,LOGPEN32_SIZE jmp exit copy_pen: mov di,ss mov ds,di mov es,di lea di,[si+GO_BUF_SIZE] lodsw ; lopnStyle cwde stosd lodsw ; lopnWidth.x cwde stosd lodsw ; lopnWidth.y cwde stosd movsd ; lopnColor mov eax,LOGPEN32_SIZE jmp copy_data type_brush: or edi,edi jnz copy_brush mov eax,LOGBRUSH32_SIZE jmp exit copy_brush: mov di,ss mov ds,di mov es,di lea di,[si+GO_BUF_SIZE] lodsw ; lbStyle cwde stosd movsd ; lbColor lodsw ; lbHatch cwde stosd mov eax,LOGBRUSH32_SIZE jmp copy_data type_palette: or edi,edi jnz copy_palette mov eax,4 ; only 4 bytes returned jmp exit copy_palette: mov di,ss mov ds,di mov es,di lea di,[si+GO_BUF_SIZE] lodsw movzx eax,ax stosd mov eax,4 ; only 4 bytes returned ; Copy converted data to caller's buffer. ; eax = computed byte count copy_data: mov ecx,dword ptr bp_nCount cmp ecx,eax jb reload_dst mov ecx,eax reload_dst: push ecx ; save return code mov edx,ecx shr ecx,2 and edx,3 movzx esi,word ptr bp_lpObjectTmp add esi,GO_BUF_SIZE mov es,cs:THUNK16BCodeData mov es,es:FlatData mov edi,dword ptr bp_lpObject rep movs dword ptr es:[edi],dword ptr ds:[esi] mov ecx,edx rep movs byte ptr es:[edi],byte ptr ds:[esi] pop eax ; restore return code directly to eax exit: endm ;------------------------------------------------------------------------ ; RAWPACK__GETFONTDATA_lpvBuffer ;------------------------------------------------------------------------ ; Special cases: ; lpvBuffer == NULL return size of required buffer ; cbData == 0 return size of required buffer RAWPACK__GETFONTDATA_lpvBuffer macro lpvBufferOff, lp16Off local fail_exit,exit,cbData cbData equ <[bp_top + 16]> ;size of lpvBuffer mov eax,[bp + &lpvBufferOff&] mov ecx,cbData TILE_BUFFER jc fail_exit mov dword ptr [bp - &lp16Off&], eax mov dword ptr LOCAL__GETFONTDATA_dwFreeInfo, ecx jmp exit fail_exit: mov sp,bp xor eax,eax ;GetFontData() returns -1 to indicate dec eax ; failure. ERRCHK_EXIT -1,87,Exit_20 exit: endm ;RAWPACK__GETFONTDATA_lpvBuffer ;------------------------------------------------------------------------ ; RAWUNPACK__GETFONTDATA_lpvBuffer ;------------------------------------------------------------------------ RAWUNPACK__GETFONTDATA_lpvBuffer macro lpvBufferOff, lp16Off mov ecx, dword ptr LOCAL__GETFONTDATA_dwFreeInfo UNTILE_BUFFER endm ;RAWUNPACK__GETFONTDATA_lpvBuffer ;------------------------------------------------------------------------ ; RAWPACK__GETGLYPHOUTLINEA_lpvBuffer ;------------------------------------------------------------------------ ; ; Special cases: ; lpvBuffer == NULL return size of required buffer ; cbData == 0 return size of required buffer RAWPACK__GETGLYPHOUTLINEA_lpvBuffer macro lpvBufferOff, lp16Off local fail_exit,exit,cbData cbData equ <[bp_top + 16]> ;size of user's buffer mov eax,[bp+&lpvBufferOff&] mov ecx,cbData TILE_BUFFER jc fail_exit mov dword ptr [bp - &lp16Off&], eax mov dword ptr LOCAL__GETGLYPHOUTLINEA_dwFreeInfo, ecx jmp exit fail_exit: mov sp,bp xor eax,eax dec eax ERRCHK_EXIT -1,87,Exit_28 exit: endm ;RAWPACK__GETGLYPHOUTLINEA_lpvBuffer ;------------------------------------------------------------------------ ; RAWUNPACK__GETGLYPHOUTLINEA_lpvBuffer ;------------------------------------------------------------------------ RAWUNPACK__GETGLYPHOUTLINEA_lpvBuffer macro lpvBufferOff, lp16Off mov ecx, LOCAL__GETGLYPHOUTLINEA_dwFreeInfo UNTILE_BUFFER endm ;RAWUNPACK__GETGLYPHOUTLINEA_lpvBuffer ;------------------------------------------------------------------------ ; RAWPACK__GETKERNINGPAIRSA_lpkp ;------------------------------------------------------------------------ RAWPACK__GETKERNINGPAIRSA_lpkp macro lpkpOff, lp16Off local fail_exit,exit,cPairs,tile_it cPairs equ <[bp_top + 4]> mov eax,[bp+&lpkpOff&] or eax,eax jz tile_it mov ecx,cPairs or ecx,ecx ;if the buffer size is 0, function jz fail_exit ; should return 0. cmp ecx,10000h ;make sure buffer size will fit in jae fail_exit ; a Win16 INT. shl ecx,1 mov edx,ecx shl ecx,1 add ecx,edx ; assert(ecx == cPairs * 6) tile_it: ; int 3 TILE_BUFFER ; int 3 jc fail_exit mov dword ptr [bp - &lp16Off&], eax mov dword ptr LOCAL__GETKERNINGPAIRSA_dwFreeInfo,ecx jmp exit fail_exit: mov sp,bp xor eax,eax ERRCHK_EXIT 0,87,Exit_12 exit: endm ;RAWPACK__GETKERNINGPAIRSA_lpkp ;------------------------------------------------------------------------ ; RAWUNPACK__GETKERNINGPAIRSA_lpkp ;------------------------------------------------------------------------ RAWUNPACK__GETKERNINGPAIRSA_lpkp macro lpkpOff, lp16Off local exit,cPairs,unpack_loop cPairs equ <[bp_top + 4]> ; int 3 test ax, ax ; Any pairs returned? jz exit ; No, skip out mov esi,[bp + &lpkpOff&] or esi,esi jz exit push ds push es movzx ecx,ax ; Get # pairs in ecx mov ds,FlatData mov ax,ds mov es,ax shl ecx,1 mov edx,ecx shl ecx,1 ; assert(edx == 2*cPairs) ; assert(ecx == 4*cPairs) add esi,edx add esi,ecx dec esi dec esi ; assert(esi == lpkp + 6*cPairs - 2) mov edi,esi add edi,edx ; assert(edi == lpkp + 8*cPairs - 2) shr ecx,2 ;Restore ecx to cPairs std unpack_loop: lodsw ds:[esi] cwde dec edi dec edi stosd es:[edi] inc edi inc edi movsw es:[edi],ds:[esi] movsw es:[edi],ds:[esi] loopd unpack_loop cld pop es pop ds exit: mov ecx,dword ptr LOCAL__GETKERNINGPAIRSA_dwFreeInfo UNTILE_BUFFER ; int 3 endm ;RAWUNPACK__GETKERNINGPAIRSA_lpkp IF 0 ;-----------------------------------------------------------------------; ; body_RESETDCA ;-----------------------------------------------------------------------; body_RESETDCA macro local exit local repack_devmode local push_callframe bp_hdc equ bp_lpdm equ bp_lpdmTmp equ bp_hdm equ < word ptr [bp-6]> sub eax,eax push eax ;bp_lpdmTmp push ax ;bp_hdm mov ecx,bp_lpdm or ecx,ecx jnz repack_devmode jmp push_callframe ; We have to repack the DEVMODE structure. Compute the size needed, ; allocate it, setup pointers and invoke the macro to do the copying. repack_devmode: push word ptr GMEM_MOVEABLE mov es,FlatData movzx eax,es:[ecx].dmSize movzx ecx,es:[ecx].dmDriverExtra add eax,ecx push eax call GlobalAlloc movzx eax,ax ;prepare for error or ax,ax jz exit mov word ptr bp_hdm,ax ; Set up DS:ESI ; ES:EDI push ds mov ds,FlatData mov esi,bp_lpdm mov es,ax sub edi,edi mov word ptr bp_lpdmTmp[0],di mov word ptr bp_lpdmTmp[2],ax cld REPACK_DEVMODE_32_16 pop ds push_callframe: push word ptr bp_hdc push bp_lpdmTmp call ResetDC movzx eax,ax mov cx,bp_hdm or cx,cx jz exit push eax push cx call GlobalFree pop eax exit: endm ENDIF ;---------------------------------------------------------------------------; ; RAWPACK__THKCREATEDIBITMAP_lpInitBits ;---------------------------------------------------------------------------; RAWPACK__THKCREATEDIBITMAP_lpInitBits macro lpBits, lp1616 local exit,fail_exit cmp dword ptr [bp_top+8], CBM_INIT jne exit ;lp1616 already contains 0:0 pointer mov eax,[bp_top + 16] ;Get pointer to BITMAPINFOHEADER DIB_BITS_SIZE or ecx,ecx jz fail_exit mov eax,[bp + &lpBits&] or eax,eax jz fail_exit TILE_BUFFER jc fail_exit mov dword ptr [bp - &lp1616&], eax mov dword ptr LOCAL__THKCREATEDIBITMAP_dwFreeInfo, ecx jmp exit fail_exit: mov sp,bp xor eax,eax ERRCHK_EXIT 0,87,Exit_24 exit: endm ;RAWPACK__THKCREATEDIBITMAP_lpInitBits ;---------------------------------------------------------------------------; ; RAWUNPACK__THKCREATEDIBITMAP_lpInitBits ;---------------------------------------------------------------------------; RAWUNPACK__THKCREATEDIBITMAP_lpInitBits macro lpBits, lp1616 mov ecx,dword ptr LOCAL__THKCREATEDIBITMAP_dwFreeInfo UNTILE_BUFFER endm ;RAWUNPACK__THKCREATEDIBITMAP_lpInitBits ;---------------------------------------------------------------------------; ; RAWPACK__STRETCHDIBITS_lpBits ;---------------------------------------------------------------------------; RAWPACK__STRETCHDIBITS_lpBits macro lpBits, lp1616 local exit,fail_exit mov eax,[bp_top + 40] ;Get pointer to BITMAPINFOHEADER DIB_BITS_SIZE or ecx,ecx jz fail_exit mov eax,[bp + &lpBits&] or eax,eax jz fail_exit TILE_BUFFER jc fail_exit mov dword ptr [bp - &lp1616&], eax mov dword ptr LOCAL__STRETCHDIBITS_dwFreeInfo, ecx jmp exit fail_exit: mov sp,bp xor eax,eax dec eax ERRCHK_EXIT -1,87,Exit_52 exit: endm ;RAWPACK__STRETCHDIBITS_lpBits ;---------------------------------------------------------------------------; ; RAWUNPACK__STRETCHDIBITS_lpBits ;---------------------------------------------------------------------------; RAWUNPACK__STRETCHDIBITS_lpBits macro lpBits, lp1616 mov ecx,dword ptr LOCAL__STRETCHDIBITS_dwFreeInfo UNTILE_BUFFER endm ;RAWUNPACK__STRETCHDIBITS_lpBits ;---------------------------------------------------------------------------; ; RAWPACK__SETDIBITS_lpBits ;---------------------------------------------------------------------------; RAWPACK__SETDIBITS_lpBits macro lpBits, lp1616 local exit,fail_exit mov eax,[bp_top + 20] ;Get pointer to BITMAPINFOHEADER DIB_BITS_SIZE or ecx,ecx jz fail_exit mov eax,[bp + &lpBits&] or eax,eax jz fail_exit TILE_BUFFER jc fail_exit mov dword ptr [bp - &lp1616&], eax mov dword ptr LOCAL__SETDIBITS_dwFreeInfo, ecx jmp exit fail_exit: mov sp,bp xor eax,eax ERRCHK_EXIT 0,87,Exit_28 exit: endm ;RAWPACK__SETDIBITS_lpBits ;---------------------------------------------------------------------------; ; RAWUNPACK__SETDIBITS_lpBits ;---------------------------------------------------------------------------; RAWUNPACK__SETDIBITS_lpBits macro lpBits, lp1616 mov ecx,dword ptr LOCAL__SETDIBITS_dwFreeInfo UNTILE_BUFFER endm ;RAWUNPACK__SETDIBITS_lpBits ;---------------------------------------------------------------------------; ; RAWPACK__GETDIBITS_lpBits ;---------------------------------------------------------------------------; RAWPACK__GETDIBITS_lpBits macro lpBits, lp1616 local exit,null_exit,fail_exit mov eax,[bp + &lpBits&] or eax,eax jz null_exit mov eax,[bp_top + 20] ;Get pointer to BITMAPINFOHEADER DIB_BITS_SIZE or ecx,ecx jz fail_exit mov eax,[bp + &lpBits&] TILE_BUFFER jc fail_exit mov dword ptr [bp - &lp1616&], eax mov dword ptr LOCAL__GETDIBITS_dwFreeInfo, ecx jmp exit fail_exit: mov sp,bp xor eax,eax ERRCHK_EXIT 0,87,Exit_28 null_exit: xor eax,eax mov dword ptr LOCAL__GETDIBITS_dwFreeInfo,eax exit: endm ;RAWPACK__GETDIBITS_lpBits ;---------------------------------------------------------------------------; ; RAWUNPACK__GETDIBITS_lpBits ;---------------------------------------------------------------------------; RAWUNPACK__GETDIBITS_lpBits macro lpBits, lp1616 mov ecx,dword ptr LOCAL__GETDIBITS_dwFreeInfo UNTILE_BUFFER endm ;RAWUNPACK__GETDIBITS_lpBits ;---------------------------------------------------------------------------; ; RAWPACK__SETDIBITSTODEVICE_lpBits ;---------------------------------------------------------------------------; RAWPACK__SETDIBITSTODEVICE_lpBits macro lpBits, lp1616 local exit,fail_exit mov eax,[bp_top + 40] ;Get pointer to BITMAPINFOHEADER DIB_BITS_SIZE or ecx,ecx jz fail_exit mov eax,[bp + &lpBits&] or eax,eax jz fail_exit TILE_BUFFER jc fail_exit mov dword ptr [bp - &lp1616&], eax mov dword ptr LOCAL__SETDIBITSTODEVICE_dwFreeInfo, ecx jmp exit fail_exit: mov sp,bp xor eax,eax ERRCHK_EXIT 0,87,Exit_48 exit: endm ;RAWPACK__SETDIBITSTODEVICE_lpBits ;---------------------------------------------------------------------------; ; RAWUNPACK__SETDIBITSTODEVICE_lpBits ;---------------------------------------------------------------------------; RAWUNPACK__SETDIBITSTODEVICE_lpBits macro lpBits, lp1616 mov ecx,dword ptr LOCAL__SETDIBITSTODEVICE_dwFreeInfo UNTILE_BUFFER endm ;RAWUNPACK__SETDIBITSTODEVICE_lpBits ;---------------------------------------------------------------------------; ; RAWPACK__PLAYMETAFILERECORD_lpMetaRecord ;---------------------------------------------------------------------------; RAWPACK__PLAYMETAFILERECORD_lpMetaRecord macro lpMFR, lp1616 local exit,fail_exit mov eax,[bp + &lpMFR&] or eax,eax jz fail_exit mov es,FlatData mov ecx,es:[eax] shl ecx,1 jc fail_exit add ecx,4 ; add some slop in case drivers touch jo fail_exit ; a little too much... #9978,win95c TILE_BUFFER jc fail_exit mov dword ptr [bp - &lp1616&], eax mov dword ptr LOCAL__PLAYMETAFILERECORD_dwFreeInfo, ecx jmp exit fail_exit: mov sp,bp xor eax,eax ;PlayMetaFileRecord doesn't return a ERRCHK_EXIT 0,87,Exit_16 ;a value, so fake it. exit: endm ;RAWPACK__PLAYMETAFILERECORD_lpMetaRecord ;---------------------------------------------------------------------------; ; RAWUNPACK__PLAYMETAFILERECORD_lpMetaRecord ;---------------------------------------------------------------------------; RAWUNPACK__PLAYMETAFILERECORD_lpMetaRecord macro lpMFR, lp1616 mov ecx,dword ptr LOCAL__PLAYMETAFILERECORD_dwFreeInfo UNTILE_BUFFER endm ;RAWUNPACK__PLAYMETAFILERECORD_lpMetaRecord ;---------------------------------------------------------------------------; ; Return value for PlayMetaFileRecord ;---------------------------------------------------------------------------; RET__PLAYMETAFILERECORD macro ; The 16-bit PlayMetaFileRecord API has a void return but the Win32 version ; has a BOOL return so always return success. mov eax,1 endm ;--------------------------------------------------------------------------- ; Handling error code of STARTDOC api. ;--------------------------------------------------------------------------- err_STARTDOCA macro local exit,l1,l2,l3,l4 cmp eax,0 ;Avoid overhead when successful jge exit cmp eax,-1 ;SP_ERROR, generic error, check GetLastError() jne l1 call GetLastError cmp eax,0 jne l4 ;if GetLastError() != 0, exit pushd 87 ;if GetLastError() == 0, SetLastError(INVALID_PARAM) call SetLastError jmp l4 ; This expands to a pretty embarrassing control structure (checks ; against all four values even after a match is found). Looking forward ; to throwing this out when we optimize the thunk layer. ; ERRCHK_EXIT -1,87,l1 ;SP_ERROR -> BAD_PARAM l1: ERRCHK_EXIT -4,112,l2 ;SP_OUTOFDISK -> DISK_FULL l2: ERRCHK_EXIT -5,8,l3 ;SP_OUTOFMEMORY -> NOT_ENOUGH_MEM l3: ERRCHK_EXIT -3,63,l4 ;SP_USERABORT -> PRINT_CANCELLED l4: mov eax,-1 ;return SP_ERROR for failure exit: endm ;err_STARTDOCA ;--------------------------------------------------------------------------- ; Handling error code of ESCAPE api. ;--------------------------------------------------------------------------- err_THKESCAPE macro local exit,l1,l2,l3 cmp eax,0 ;Avoid overhead when successful jge exit ; This expands to a pretty embarrassing control structure (checks ; against all four values even after a match is found). Looking forward ; to throwing this out when we optimize the thunk layer. ERRCHK_EXIT -1,87,l1 ;SP_ERROR -> BAD_PARAM l1: ERRCHK_EXIT -4,112,l2 ;SP_OUTOFDISK -> DISK_FULL l2: ERRCHK_EXIT -5,8,l3 ;SP_OUTOFMEMORY -> NOT_ENOUGH_MEM l3: ERRCHK_EXIT -3,63,exit ;SP_USERABORT -> PRINT_CANCELLED exit: endm ;err_ESCAPE ;-------------------------------------------------------------------------- ; body_GETTEXTEXTENTEXPOINTA ;-------------------------------------------------------------------------- body_GETTEXTEXTENTEXPOINTA macro local exit,fail_exit local bp_hdc, bp_lpszStr, bp_cchString, bp_nMaxExtent local bp_lpnFit, bp_alpDx, bp_lpSize local bp_lpszStr16,bp_lpSize16 local p1,loop,loop_exit,loop_exit2,unpack_size,no_alpDx bp_hdc equ <[bp_top]> bp_lpszStr equ <[bp_top+4]> bp_cchString equ <[bp_top+8]> bp_nMaxExtent equ <[bp_top+12]> bp_lpnFit equ <[bp_top+16]> bp_alpDx equ <[bp_top+20]> bp_lpSize equ <[bp_top+24]> bp_lpszStr16 equ <[bp-4]> ;16:16 lpszStr pointer bp_lpSize16 equ <[bp-8]> ;16:16 lpSize pointer xor eax,eax ;Allocate 0-initialized locals push eax ; bp_lpszStr16 push eax ; bp_lpSize16 ; Convert lpszStr arg to 16:16 pointer and stuff away. mov eax,dword ptr bp_lpszStr push eax call MapLS ;PLUGGED mov dword ptr bp_lpszStr16,eax ; Convert lpSize arg to 16:16 pointer and stuff away. mov eax,dword ptr bp_lpSize push eax call MapLS ;PLUGGED mov dword ptr bp_lpSize16,eax ; Optimization: if lpfnFit and alpDx both NULL, degenerate to ; GetTextExtentPoint(). mov eax,dword ptr bp_lpnFit or eax,dword ptr bp_alpDx jz measure_whole ; If lpfnFit == 0, we're supposed to ignore nMaxExtent. To avoid dealing ; with this special case, set nMaxExtent to max. mov eax,dword ptr bp_lpnFit or eax,eax jnz p1 dec eax ;eax <-- 0xffffffff mov dword ptr bp_nMaxExtent, eax ; Assert: nMaxExtent now set to valid value. p1: mov ecx,1 loop: ; Measure increasingly long prefixes until we reach the end of the ; string or exceed nMaxExtent. ecx == prefix length (ranges from 1 ; to cchString inclusive). cmp ecx,dword ptr bp_cchString ja loop_exit push ecx ;Save prefix length ; Note: Using caller's SIZE as temporary for GetTextExtentPoint(). ; If this is the last call before hitting the end of the string, ; this'll put the right return value in SIZE. If not, we'll ; do a final measure to set SIZE right. push word ptr bp_hdc ;Arg: GetTextExtentPoint push dword ptr bp_lpszStr16 ;Arg: GetTextExtentPoint push cx ;Arg: GetTextExtentPoint push dword ptr bp_lpSize16 ;Arg: GetTextExtentPoint call GetTextExtentPoint pop ecx ;Restore prefix length or ax,ax jz fail_exit mov es,FlatData mov esi,bp_lpSize mov ax,es:[esi + 0] ;Retrieve size.cx cwde cmp eax,bp_nMaxExtent ;If exceeded nMaxExtent, end of ja loop_exit ; story. ; Store partial width in alpDx (if not NULL). mov edi,dword ptr bp_alpDx or edi,edi jz no_alpDx mov es,FlatData mov es:[edi + ecx*4 - 4], eax no_alpDx: inc ecx jmp loop ; Assert: ecx - 1 == length of longest prefix not violating nMaxExtent loop_exit: dec ecx mov edi,bp_lpnFit or edi,edi jz loop_exit2 mov es,FlatData mov es:[edi],ecx loop_exit2: ; Optimization: if we ran off the end of the string, SIZE already contains ; right (16-bit) values so bypass final call to GetTextExtentPoint(). cmp ecx,dword ptr bp_cchString je unpack_size ; Deliberate fall-through to measure_whole measure_whole: push word ptr bp_hdc push dword ptr bp_lpszStr16 push word ptr bp_cchString push dword ptr bp_lpSize16 call GetTextExtentPoint or ax,ax jz fail_exit unpack_size: ; Unpack LPSIZE object mov es,FlatData mov esi,bp_lpSize mov ax,es:[esi + 2] ;Unpack Y cwde mov es:[esi + 4],eax mov ax,es:[esi + 0] ;Unpack X cwde mov es:[esi + 0],eax xor eax,eax ;Set success return value. inc eax jmp exit fail_exit: xor eax,eax exit: push eax pushd bp_lpszStr16 call UnmapLS pushd bp_lpSize16 call UnmapLS pop eax endm ;body_GETTEXTEXTENTEXPOINTA ;-------------------------------------------------------------------------- ; body_THKPLAYENHMETAFILERECORD ;-------------------------------------------------------------------------- body_THKPLAYENHMETAFILERECORD macro local pop_exit bp_hdc equ <[bp_top]> bp_lpht equ <[bp_top+4]> bp_lpby equ <[bp_top+8]> bp_che equ <[bp_top+12]> bp_cby equ <[bp_top+16]> bp_return equ <[bp-4]> ;return value bp_tile_lpht equ <[bp-8]> ;ecx from TILE_BUFFER bp_tile_lpby equ <[bp-12]> ;ecx from TILE_BUFFER ; Create zero-inited stack space for the return value. xor eax, eax push eax ;bp_return = 0 ; Convert lpht arg into a selector array and create stack space. mov eax, dword ptr bp_lpht mov ecx, dword ptr bp_che test ecx, 0C0000000h ;so we can shift left safely jnz pop_exit shl ecx, 2 ;HANDLE is 4 bytes in 16-bit and 32-bit TILE_BUFFER push ecx push eax ;save 16:16 ptr temporarily ; Convert lpby arg into a selector array and create stack space. mov eax, dword ptr bp_lpby mov ecx, dword ptr bp_cby TILE_BUFFER pop edx ;get 16:16 pointer to handles push ecx ; Re-pack the stack and make the 16-bit call. push word ptr bp_hdc push edx ;16:16 pointer to handles push eax ;16:16 pointer to bytes push dword ptr bp_che call PlayEnhMetaFileRecord ; Save the return value on the stack. (The high word is already zero.) mov word ptr bp_return, ax ; Free the tiled selector arrays and stack space. pop ecx UNTILE_BUFFER pop ecx UNTILE_BUFFER ; Clean the stack and set the return value. pop_exit: pop eax endm ;body_THKPLAYENHMETAFILERECORD ;------------------------------------------------------------------------- ; RAWPACK_GETPATH_lpptl ;------------------------------------------------------------------------- RAWPACK__GETPATH_lpptl macro lpptl,lp1616 local exit,fail_exit,no_check mov ecx,[bp_top+12] ;cptl (count of points) test ecx, 0E0000000h ;so we can shift left safely jnz fail_exit shl ecx, 3 ;# bytes = cptl * 8 mov LOCAL__GETPATH_dwFreeInfo1,ecx ;assume ecx is zero or ecx,ecx jz exit mov eax,[bp + &lpptl] or eax,eax jz fail_exit ; Make sure it's writeable. If not, thunk fault handler will catch it. mov es, FlatData or byte ptr es:[eax],0 mov edx, [bp + &lpptl& + 4] or edx,edx jz no_check or byte ptr es:[edx],0 no_check: TILE_BUFFER mov [bp - &lp1616&],eax mov LOCAL__GETPATH_dwFreeInfo1,ecx jmp exit fail_exit: mov sp,bp xor eax,eax dec eax ERRCHK_EXIT -1,87,Exit_16 exit: endm ;RAWPACK_GETPATH_lpBits ;------------------------------------------------------------------------- ; RAWUNPACK_GETPATH_lpptl ;------------------------------------------------------------------------- RAWUNPACK__GETPATH_lpptl macro lpptl,lp1616 mov ecx,LOCAL__GETPATH_dwFreeInfo1 UNTILE_BUFFER endm ;RAWUNPACK_GETPATH ;------------------------------------------------------------------------- ; RAWPACK_GETPATH_lpby ;------------------------------------------------------------------------- RAWPACK__GETPATH_lpby macro lpby,lp1616 local exit,fail_exit mov ecx,[bp_top+12] ;cptl (count of points) mov LOCAL__GETPATH_dwFreeInfo2,ecx ;assume ecx is zero or ecx,ecx jz exit mov eax,[bp + &lpby] or eax,eax jz fail_exit TILE_BUFFER mov [bp - &lp1616&],eax mov LOCAL__GETPATH_dwFreeInfo2,ecx jmp exit fail_exit: mov sp,bp xor eax,eax dec eax ERRCHK_EXIT -1,87,Exit_16 exit: endm ;RAWPACK_GETPATH_lpBits ;------------------------------------------------------------------------- ; RAWUNPACK_GETPATH_lpby ;------------------------------------------------------------------------- RAWUNPACK__GETPATH_lpby macro lpby,lp1616 mov ecx,LOCAL__GETPATH_dwFreeInfo2 UNTILE_BUFFER endm ;RAWUNPACK_GETPATH ;------------------------------------------------------------------------- ; RAWPACK_GDICOMMENT ;------------------------------------------------------------------------- RAWPACK__GDICOMMENT_lpby macro lpby,lp1616 local exit,fail_exit mov eax,[bp + &lpby] or eax,eax jz fail_exit mov ecx,[bp_top+4] ;cby (size of buffer) or ecx,ecx jz fail_exit TILE_BUFFER mov [bp - &lp1616&],eax mov LOCAL__GDICOMMENT_dwFreeInfo,ecx jmp exit fail_exit: mov sp,bp xor eax,eax ERRCHK_EXIT 0,87,Exit_12 exit: endm ;RAWPACK_GDICOMMENT_lpBits ;------------------------------------------------------------------------- ; RAWUNPACK_GDICOMMENT ;------------------------------------------------------------------------- RAWUNPACK__GDICOMMENT_lpby macro lpby,lp1616 mov ecx,LOCAL__GDICOMMENT_dwFreeInfo UNTILE_BUFFER endm ;RAWUNPACK_GDICOMMENT ;------------------------------------------------------------------------- ; RAWPACK_GETENHMETAFILEBITS ;------------------------------------------------------------------------- RAWPACK__GETENHMETAFILEBITS_lpby macro lpby,lp1616 local exit mov eax,[bp + &lpby] mov ecx,[bp_top+4] ;cby (size of buffer) TILE_BUFFER mov [bp - &lp1616&],eax mov LOCAL__GETENHMETAFILEBITS_dwFreeInfo,ecx exit: endm ;RAWPACK_GETENHMETAFILEBITS_lpBits ;------------------------------------------------------------------------- ; RAWUNPACK_GETENHMETAFILEBITS ;------------------------------------------------------------------------- RAWUNPACK__GETENHMETAFILEBITS_lpby macro lpby,lp1616 mov ecx,LOCAL__GETENHMETAFILEBITS_dwFreeInfo UNTILE_BUFFER endm ;RAWUNPACK_GETENHMETAFILEBITS ;------------------------------------------------------------------------- ; RAWPACK_GETENHMETAFILEDESCRIPTIONA ;------------------------------------------------------------------------- RAWPACK__GETENHMETAFILEDESCRIPTIONA_lpby macro lpby,lp1616 local exit mov eax,[bp + &lpby] mov ecx,[bp_top+4] ;cby (size of buffer) TILE_BUFFER mov [bp - &lp1616&],eax mov LOCAL__GETENHMETAFILEDESCRIPTIONA_dwFreeInfo,ecx exit: endm ;RAWPACK_GETENHMETAFILEDESCRIPTIONA_lpBits ;------------------------------------------------------------------------- ; RAWUNPACK_GETENHMETAFILEDESCRIPTIONA ;------------------------------------------------------------------------- RAWUNPACK__GETENHMETAFILEDESCRIPTIONA_lpby macro lpby,lp1616 mov ecx,LOCAL__GETENHMETAFILEDESCRIPTIONA_dwFreeInfo UNTILE_BUFFER endm ;RAWUNPACK_GETENHMETAFILEDESCRIPTIONA ;------------------------------------------------------------------------- ; RAWPACK_GETENHMETAFILEPALETTEENTRIES ;------------------------------------------------------------------------- RAWPACK__GETENHMETAFILEPALETTEENTRIES_lpby macro lpby,lp1616 local exit,fail_exit mov eax,[bp + &lpby] mov ecx,[bp_top+4] ;cpe (count of PALETTEENTRYs) test ecx, 0C0000000h ;so we can shift left safely jnz fail_exit shl ecx,2 TILE_BUFFER mov [bp - &lp1616&],eax mov LOCAL__GETENHMETAFILEPALETTEENTRIES_dwFreeInfo,ecx jmp exit fail_exit: mov sp,bp xor eax,eax dec eax ERRCHK_EXIT -1,87,Exit_12 exit: endm ;RAWPACK_GETENHMETAFILEPALETTEENTRIES_lpPALETTEENTRIES ;------------------------------------------------------------------------- ; RAWUNPACK_GETENHMETAFILEPALETTEENTRIES ;------------------------------------------------------------------------- RAWUNPACK__GETENHMETAFILEPALETTEENTRIES_lpby macro lpby,lp1616 mov ecx,LOCAL__GETENHMETAFILEPALETTEENTRIES_dwFreeInfo UNTILE_BUFFER endm ;RAWUNPACK_GETENHMETAFILEPALETTEENTRIES ;------------------------------------------------------------------------- ; RAWPACK_SETENHMETAFILEBITS ;------------------------------------------------------------------------- RAWPACK__SETENHMETAFILEBITS_lpby macro lpby,lp1616 local exit,fail_exit mov eax,[bp + &lpby] or eax,eax jz fail_exit mov ecx,[bp_top] ;cby (size of buffer) or ecx,ecx jz fail_exit TILE_BUFFER mov [bp - &lp1616&],eax mov LOCAL__SETENHMETAFILEBITS_dwFreeInfo,ecx jmp exit fail_exit: mov sp,bp xor eax,eax ERRCHK_EXIT 0,87,Exit_8 exit: endm ;RAWPACK_SETENHMETAFILEBITS_lpBits ;------------------------------------------------------------------------- ; RAWUNPACK_SETENHMETAFILEBITS ;------------------------------------------------------------------------- RAWUNPACK__SETENHMETAFILEBITS_lpby macro lpby,lp1616 mov ecx,LOCAL__SETENHMETAFILEBITS_dwFreeInfo UNTILE_BUFFER endm ;RAWUNPACK_SETENHMETAFILEBITS ;------------------------------------------------------------------------- ; RAWPACK_ENUMOBJECTS ;------------------------------------------------------------------------- RAWPACK__ENUMOBJECTS_lpObjectFunc macro iOffset,iTempOffset local pen, exit cmp word ptr [bp_top+4],1 ;OBJ_PEN? je pen PACK_CALLBACK iOffset,iTempOffset,CBID_ENUMBRUSH jmp exit pen: PACK_CALLBACK iOffset,iTempOffset,CBID_ENUMPEN exit: endm ;RAWPACK__ENUMOBJECTS_lpObjectFunc ;------------------------------------------------------------------------- ; RAWUNPACK_ENUMOBJECTS ;------------------------------------------------------------------------- RAWUNPACK__ENUMOBJECTS_lpObjectFunc macro iOffset,iTempOffset local pen, exit ;unpack don't care about CBID ;just make it readable cmp word ptr [bp_top+4],1 ;OBJ_PEN? je pen UNPACK_CALLBACK iOffset,iTempOffset,CBID_ENUMBRUSH jmp exit pen: UNPACK_CALLBACK iOffset,iTempOffset,CBID_ENUMPEN exit: endm ;RAWUNPACK__ENUMOBJECTS_lpObjectFunc