diff options
author | Adam <you@example.com> | 2020-05-17 05:51:50 +0200 |
---|---|---|
committer | Adam <you@example.com> | 2020-05-17 05:51:50 +0200 |
commit | e611b132f9b8abe35b362e5870b74bce94a1e58e (patch) | |
tree | a5781d2ec0e085eeca33cf350cf878f2efea6fe5 /private/mvdm/wow16/gdi | |
download | NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.gz NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.bz2 NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.lz NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.xz NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.zst NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.zip |
Diffstat (limited to 'private/mvdm/wow16/gdi')
-rw-r--r-- | private/mvdm/wow16/gdi/fontres.c | 119 | ||||
-rw-r--r-- | private/mvdm/wow16/gdi/gdi.api | 3047 | ||||
-rw-r--r-- | private/mvdm/wow16/gdi/gdi.asm | 551 | ||||
-rw-r--r-- | private/mvdm/wow16/gdi/gdi.def | 405 | ||||
-rw-r--r-- | private/mvdm/wow16/gdi/gdi.rc | 5 | ||||
-rw-r--r-- | private/mvdm/wow16/gdi/gdi.rcv | 13 | ||||
-rw-r--r-- | private/mvdm/wow16/gdi/gdi16.h | 422 | ||||
-rw-r--r-- | private/mvdm/wow16/gdi/gdimacro.inc | 676 | ||||
-rw-r--r-- | private/mvdm/wow16/gdi/gdimem.inc | 50 | ||||
-rw-r--r-- | private/mvdm/wow16/gdi/layer.asm | 47 | ||||
-rw-r--r-- | private/mvdm/wow16/gdi/makefile | 126 | ||||
-rw-r--r-- | private/mvdm/wow16/gdi/meta.c | 1835 | ||||
-rw-r--r-- | private/mvdm/wow16/gdi/metacons.inc | 90 | ||||
-rw-r--r-- | private/mvdm/wow16/gdi/metarec.c | 2325 | ||||
-rw-r--r-- | private/mvdm/wow16/gdi/metasup.c | 523 | ||||
-rw-r--r-- | private/mvdm/wow16/gdi/muldiv.asm | 110 | ||||
-rw-r--r-- | private/mvdm/wow16/gdi/sort.asm | 706 |
17 files changed, 11050 insertions, 0 deletions
diff --git a/private/mvdm/wow16/gdi/fontres.c b/private/mvdm/wow16/gdi/fontres.c new file mode 100644 index 000000000..aa6d24d6a --- /dev/null +++ b/private/mvdm/wow16/gdi/fontres.c @@ -0,0 +1,119 @@ +/*++ + * + * WOW v1.0 + * + * Copyright (c) 1991, Microsoft Corporation + * + * FONTRES.C + * WOW16 user resource services + * + * History: + * + * Created 05-Apr-1993 by Craig Jones (v-cjones) + * + * This file provides support for the Win 3.1 AddFontResource & + * RemoveFontResource API's. + * +--*/ + +#include <windows.h> + +int WINAPI WOWAddFontResource (LPCSTR lpszFileName); +BOOL WINAPI WOWRemoveFontResource (LPCSTR lpszFileName); +WORD WINAPI WOWCreateDIBPatternBrush(LPVOID lpData, UINT fColor); + + +int WINAPI IAddFontResource (LPCSTR lpszFileName) +{ + + int ret; + char sz[128]; + LPSTR lpsz; + + // if the app passed a handle instead of a file name - get the file name + if(HIWORD((DWORD)lpszFileName) == 0) { + + if(GetModuleFileName((HINSTANCE)LOWORD((DWORD)lpszFileName), sz, 128)) { + lpsz = sz; + } + else { + lpsz = NULL; + ret = 0; + } + } + else { + lpsz = (LPSTR)lpszFileName; + } + + // we're really calling wg32AddFontResource here + if(lpsz) { + ret = WOWAddFontResource((LPCSTR)lpsz); + } + + // ALDUS PM5 expects AddFontResource to succeed if given the base name of + // a font that it previously did a LoadLibrary on. The full path name was + // passed to LoadLibrary. So if AddFontResouce failed then find out if + // there is a loaded module already. If so then get the full path name + // and retry the AddFontResource. - MarkRi 6/93 + if( !ret && (HIWORD((DWORD)lpszFileName) != 0) ) { + HMODULE hmod ; + + hmod = GetModuleHandle( lpszFileName ) ; + if( hmod ) { + if( GetModuleFileName( (HINSTANCE)hmod, sz, sizeof(sz) ) ) { + ret = WOWAddFontResource( (LPCSTR)sz ) ; + } + } + } + + return(ret); +} + + + + +BOOL WINAPI IRemoveFontResource (LPCSTR lpszFileName) +{ + BOOL ret; + char sz[128]; + LPSTR lpsz; + + // if the app passed a handle instead of a file name - get the file name + if(HIWORD((DWORD)lpszFileName) == 0) { + + if(GetModuleFileName((HINSTANCE)LOWORD((DWORD)lpszFileName), sz, 128)) { + lpsz = sz; + } + else { + lpsz = NULL; + ret = FALSE; + } + } + else { + lpsz = (LPSTR)lpszFileName; + } + + // we're really calling wg32RemoveFontResource here + if(lpsz) { + ret = (BOOL)WOWRemoveFontResource((LPCSTR)lpsz); + } + + return(ret); +} + + + +WORD WINAPI ICreateDIBPatternBrush (HGLOBAL hMem, UINT fColor) +{ + LPVOID lpT; + WORD wRet = 0; + + if (lpT = LockResource(hMem)) { + wRet = WOWCreateDIBPatternBrush(lpT, fColor); + UnlockResource(hMem); + } + + return wRet; +} + + diff --git a/private/mvdm/wow16/gdi/gdi.api b/private/mvdm/wow16/gdi/gdi.api new file mode 100644 index 000000000..c97b19dfe --- /dev/null +++ b/private/mvdm/wow16/gdi/gdi.api @@ -0,0 +1,3047 @@ +;=========================================================================== +; +; For WOW only +; + +;=========================================================================== +; +; Validation constants +; +PS_MAX equ 6 +HS_MAX equ 5 +BS_MAX equ 5 +FW_MAX equ 1000 +OUT_MAX equ 7 +CLIP_MAX equ 2 +QUALITY_MAX equ 2 +DIB_MAX equ 1 +PFILL_MIN equ 1 +PFILL_MAX equ 2 +EFF_MAX equ 1 +OBJ_MIN equ 1 +OBJ_MAX equ 2 +STOCK_MAX equ 16 +RGN_MIN equ 1 +RGN_MAX equ 5 +BK_MIN equ 1 +BK_MAX equ 3 ;SHOULD let TRANSPARENT1 ROP code go through. +R2_MIN equ 1 +R2_MAX equ 16 +STR_MIN equ 1 +STR_MAX equ 3 +PFILL_MIN equ 1 +PFILL_MAX equ 2 +MM_MIN equ 1 +MM_MAX equ 8 +DIB_MAX equ 1 +PR_MAX equ 4 +RM_MAX equ 2 +DIB_RGB_COLORS equ 0 +CBM_INIT equ 4 +BI_RGB equ 0 + +TA_VALID equ 0001fh +GLYPH_VALID equ 00003h +MAPFLG_VALID_L equ 00001h +MAPFLG_VALID_H equ 00000h +CBM_VALID_L equ 00004h +CBM_VALID_H equ 00000h +ETO_VALID equ 00007h +PC_VALID equ 00007h + +CCHDEVICENAME equ 32 + + + +;special error codes + +SP_ERROR equ -1 + + +;============================================================================ +; +; Special ATM hackery (See ATM HACK comments in dcman1.asm) +; +;ExternFP <LoadLibrary> TEMPLY !!!!!!!!!!! ChandanC +;ExternFP <FreeLibrary> TEMPLY !!!!!!!!!!! ChandanC +;ExternFP <GetProcAddress> TEMPLY !!!!!!!!!!! ChandanC +; +; Macro to set up stubs required for ATM's GDI patching code +; +ATM_LPFN macro gdifunc, kernfunc +IFNDEF WOW + db 09ah ; call far instruction +public gdifunc&kernfunc +gdifunc&kernfunc: + dd kernfunc +ENDIF +endm + +; +; Argument types +; +IFNDEF WOW +ExternFP <IsGDIObject> +ExternFP <IsValidMetaFile> +ENDIF + +P_LPSIZE equ <P_LPPOINT> +P_LPSIZE0 equ <P_LPPOINT0> + +; +; Generate a GDI object validation macro. +; +; If nullok is 1, allow NULL. +; min & max are the allowed OBJ_* range. +; except, if specified, is an OBJ_* value within the range to reject. +; +_GenHGDI macro name,func + P_&name ¯o hObj,opts + _GenParm <hObj>,2,<opts> + if VLgen + IFNDEF WOW + mov bx,_P_&&hObj + lcall V&name + _gensub name + _gensub VGOT + ENDIF + endif + &endm + + P_&name&0 ¯o hObj,opts + _GenParm <hObj>,2,<opts> + if VLgen + IFNDEF WOW + mov bx,_P_&&hObj + lcall V&name&0 + _gensub name + _gensub VGOT + ENDIF + endif + &endm +endm + +_GenHGDI <HGDIOBJ> +_GenHGDI <HPEN> +_GenHGDI <HBRUSH> +_GenHGDI <HFONT> +_GenHGDI <HPALETTE> +_GenHGDI <HBITMAP> +_GenHGDI <HRGN> + +; HDC variants: HDC - Any kind of DC except a metafile DC + +_GenHGDI <HDC> + +; Anything including a metafile DC + +_GenHGDI <HDCMETA> + +P_HDCNOTMEM equ <P_HDCMETA> + +; output-only DC - metafiles ok but no ICs allowed + +_GenHGDI <HDCNOIC> + +; output-only DC - neither metafiles nor ICs allowed + +_GenHGDI <HDCNOICNOMETA> + +; GetObject(): Pen, brush, font, palette, or bitmap. +; +_GenHGDI <HGDIOBJGET> + +; UnrealizeObject(): Brush or palette +; +_GenHGDI <HGDIOBJUNR> + +; SelectObject(): pen, brush, font, bitmap, region (no palette) +; +_GenHGDI <HGDIOBJSEL> + +; Metafile handle +; +P_HMETAFILE macro hmf,opts + _GenParm <hmf>,2,<opts> + if VLgen + IFNDEF WOW + mov ax,_P_&hmf + lcall VHMETAFILE + _gensub VHMETAFILE + ENDIF + endif +endm + +_GenHGDIX macro name,errtyp,lseg,min,max,except +local badobj +local objok +local trap + +IFNDEF WOW +public V&name&0&lseg +V&name&0&lseg: + or bx,bx + jz objok + +public V&name&lseg +V&name&lseg: + lcall VGetObjType + ifnb <except> + cmp ax,except + jz badobj + endif + ife min-max + cmp ax,min + jne badobj + errnz $-objok + else + cmp ax,min + jb badobj + cmp ax,max + ja badobj + endif +objok: + ret +badobj: + mov ax,cx + mov bx,ERR_BAD_&errtyp + ljmp Inval_Param_ +ENDIF +endm ; _GenHGDIX + +; +; Macro that gets expanded in each LAYER_EXPAND invocation. Includes common +; subroutines for parameter validation. +; +EXTRA_EXPAND macro lseg + +ifdef genHGDIOBJ&lseg +_GenHGDIX <HGDIOBJ>,GDI_OBJECT,lseg,OBJ_PEN,OBJ_METAFILE ; DeleteObject: any kind of object +endif + +ifdef genHPEN&lseg +_GenHGDIX <HPEN>,lseg,HPEN,OBJ_PEN,OBJ_PEN +endif + +ifdef genHBRUSH&lseg +_GenHGDIX <HBRUSH>,HBRUSH,lseg,OBJ_BRUSH,OBJ_BRUSH +endif + +ifdef genHFONT&lseg +_GenHGDIX <HFONT>,HFONT,lseg,OBJ_FONT,OBJ_FONT +endif + +ifdef genHPALETTE&lseg +_GenHGDIX <HPALETTE>,HPALETTE,lseg,OBJ_PALETTE,OBJ_PALETTE +endif + +ifdef genHBITMAP&lseg +_GenHGDIX <HBITMAP>,HBITMAP,lseg,OBJ_BITMAP,OBJ_BITMAP +endif + +ifdef genHRGN&lseg +_GenHGDIX <HRGN>,HRGN,lseg,OBJ_RGN,OBJ_RGN +endif + +; GetObject(): Pen, brush, font, palette, or bitmap. +; +ifdef genHGDIOBJGET&lseg +_GenHGDIX <HGDIOBJGET>,GDI_OBJECT,lseg,OBJ_PEN,OBJ_BITMAP +endif + +; UnrealizeObject(): Brush or palette +; +ifdef genHGDIOBJUNR&lseg +_GenHGDIX <HGDIOBJUNR>,GDI_OBJECT,lseg,OBJ_BRUSH,OBJ_PALETTE,OBJ_FONT +endif +; SelectObject(): pen, brush, font, bitmap, region (no palette) +; +ifdef genHGDIOBJSEL&lseg +_GenHGDIX <HGDIOBJSEL>,GDI_OBJECT,lseg,OBJ_PEN,OBJ_RGN,OBJ_PALETTE +endif + +; HDC variants: HDC - Any kind of DC except a metafile DC + +ifdef genHDC&lseg +_GenHGDIX <HDC>,HDC,lseg,OBJ_DC,OBJ_METADC +endif + +; Anything including a metafile DC + +ifdef genHDCMETA&lseg +_GenHGDIX <HDCMETA>,HDC,lseg,OBJ_DC,OBJ_METAFILE +endif + +; output-only DC - metafiles ok but no ICs allowed + +ifdef genHDCNOIC&lseg +_GenHGDIX <HDCNOIC>,HDC,lseg,OBJ_DC,OBJ_METAFILE,OBJ_IC +endif + +; output-only DC - neither metafiles nor ICs allowed + +ifdef genHDCNOICNOMETA&lseg +_GenHGDIX <HDCNOICNOMETA>,HDC,lseg,OBJ_DC,OBJ_DC +endif + +IFNDEF WOW +ifdef genVGOT&lseg + +public VGetObjType&lseg +VGetObjType&lseg: + mov cx,bx + jcxz VGOTbad&lseg +beg_fault_trap VGOTtrap&lseg + mov ax,_DATA + mov es,ax + mov bx,es:[bx] + mov ax,es:[bx].ilObjType +end_fault_trap + and ah,high(not OBJ_FLAGS) + errnz low(Stock) + ret + +VGOTtrap&lseg: + fault_fix_stack +VGOTbad&lseg: + xor ax,ax + ret + +endif ; genVGOT&lseg + + +ifdef genVHMETAFILE&lseg + +public VHMETAFILE&lseg +VHMETAFILE&lseg: + push ax + push ax + call IsValidMetaFile + or ax,ax + pop ax + jz @F + ret + @@: + mov bx,ERR_BAD_HMETAFILE + jmp short Inval_Param_&lseg + +endif ; genVHMETAFILE&lseg +ENDIF + +endm ; EXTRA_EXPAND + +P_ROP equ <P_DWORD> +P_COLORREF equ <P_DWORD> + +_GenLP <P_CLPLOGPALETTE>,<CLP>,1 +_GenLP <P_CLPBITMAP>,<CLP>,1 +_GenLP <P_LPHANDLETABLE0>,<LP0>,2 + +_GenLP <P_CLPBITMAPINFOHEADER>,<CLP>,1 + +P_CLPSTRHRSRC equ <P_CLPSTRATOM> + +_GenLP <P_CLPDOCINFO>,<CLP>,1 + +P_CLPFACENAME equ <P_CLPSTR> +P_CLPFACENAME0 equ <P_CLPSTR0> + +P_LPFNABORT0 equ <P_LPFN0> +P_LPFNMENUM equ <P_LPFN> +P_LPFNOENUM equ <P_LPFN> +P_LPFNFENUM equ <P_LPFN> +P_LPFNLENUM equ <P_LPFN> + +P_intN0 equ <P_WORDMBNZ> +P_DEVCAP equ <P_int> + +P_PITCHFAMILY equ <P_BYTE> + +P_LPPOINTBUFFER macro p, c, opts + _DefParm <p>,4,<opts> + _DefParm <c>,2,<opts> + if VLgen + _FlsFrame + mov ax,_P_&p + mov cx,_P_&p+2 + mov bx,_P_&c + shl bx,2 + errnz VLcbsPOINT-4 + lcall LP + _gensub LP + endif +endm + +P_CLPPOINTBUFFER macro lptr, c, opts + _DefParm <lptr>,4,<opts> + _DefParm <c>,2,<opts> + if VLgen + _FlsFrame + mov ax,_P_&lptr + mov cx,_P_&lptr+2 + mov bx,_P_&c + shl bx,2 + errnz VLcbsPOINT-4 + lcall CLP + _gensub LP + endif +endm + +STRUCT <PALETTEENTRY> +F_BYTE peRed +F_BYTE peGreen +F_BYTE peBlue +F_BFLAGS peFlags, PC_VALID +ENDSTRUCT + +P_LPPALENTRYBUFFER macro c, p, opts + _DefParm <c>,2,<opts> + _DefParm <p>,4,<opts> + if VLgen + _FlsFrame + mov ax,_P_&p + mov cx,_P_&p+2 + mov bx,_P_&c + shl bx,2 + errnz VLcbsPALETTEENTRY-4 + lcall LP + _gensub LP + endif +endm + +P_CLPPALENTRYBUFFER macro c, lp, opts + _DefParm <c>,2,<opts> + _DefParm <lp>,4,<opts> + if VLgen + _FlsFrame + mov ax,_P_&lp + mov cx,_P_&lp+2 + mov bx,_P_&c + shl bx,2 + errnz VLcbsPALETTEENTRY-4 + lcall CLP + _gensub LP + endif +endm +; +; lppt - pointer to array of points: size = sum(lpcpt). +; lpcpt - pointer to array of counts of points +; ccpt - number of point counts in *lpcpt. +; +P_POLYPOLYPOINTS macro lppt, lpcpt, ccpt, opts + P_LPPOINT <lppt>,<opts> + P_LPINT <lpcpt>,<opts> + P_int <ccpt>,<opts> + endm + +ifdef WOW +P_POLYPOLYLARGEPOINTS macro lppt, lpcpt, ccpt, opts + P_LPLARGEPOINT <lppt>,<opts> + P_LPDWORD <lpcpt>,<opts> + P_DWORD <ccpt>,<opts> + endm +endif + +P_XY1XY2 macro x1,y1,x2,y2, opts + P_int <x1>,<opts> + P_int <y1>,<opts> + P_int <x2>,<opts> + P_int <y2>,<opts> + endm + +P_LPBUFFERDW macro cb, lp, opts + P_DWORD <cb>,<opts> + P_LPBYTE <lp>,<opts> + endm + +P_LPBUFFERDW0 macro cb, lp, opts + P_DWORD <cb>,<opts> + P_LPBYTE0 <lp>,<opts> + endm + +P_CLPBUFFERDW macro cb, lp, opts + P_DWORD <cb>,<opts> + P_CLPBYTE <lp>,<opts> + endm + +P_LPBUFFERX macro cb, pb, opts + P_int <cb>,<opts> + P_LPBYTE <pb>,<opts> + endm + +ValidateHugeLP macro cch, lp, r, null + local exit + +ifnb <null> + + mov ax,lp + or ax,lp+2 + jz exit +endif + + push lp+2 + push lp + push cch+2 + push cch + call &r + or ax,ax + jz exit + mov cx, lp+2 + mov ax, lp + mov bx,ERR_BAD_PTR + lcall Inval_Param_ +exit: + endm + +;----------------------------------------------------------------------------; +; This macro is used to validate the buffer length for the two APIs +; GetCharWidth and GetABCWidths. The 'size' parameter is not a part of the +; API. It is the size of each entry in the buffer. The number of entries are +; dictated by the character range passed in. + +P_LPRWBUFFER macro chFirst, chLast, lpBuffer, size, opts + local exit + + _GenParm <chFirst>,2,<opts> + _GenParm <chLast>,2,<opts> + _GenParm <lpBuffer>,4,<opts> + + if VLgen + _FlsFrame + +;; first validate that the character range is not inverted. + + mov ax,_P_&chLast ;;last character in range + cmp ax,_P_&chFirst ;;should not be < than first character + jae @F ;;range is proper + +;; character range is not valid. + + mov bx,ERR_BAD_VALUE ;;invalid parameter error. + lcall Inval_Param_ + jmp exit + +@@: + +;; the size of the buffer should atleast be (chLast-chFirst+1)*size + + sub ax,_P_&chFirst + inc ax ;;no of entries + mov bx,size ;;size of each entry + mul bx + mov bx,ax ;;total size (ignore DX) + mov ax,_P_&lpBuffer + mov cx,_P_&lpBuffer+2 + lcall LP + _gensub LP +exit: + endif + endm + +;----------------------------------------------------------------------------; +P_CLPRECTBITSINFOBUFFER macro cyDst, xSrc, ySrc, nStartScan,nNumScans, lpBits, lpBitsInfo, wUsage, opts + P_VALIDATEBITSINFOBUFFER DIB_DIBTODEV, cyDst, xSrc, ySrc, nStartScan, nNumScans, lpBits, lpBitsInfo, wUsage, DIB_PTR_CLP, DIB_PTR_CLP, opts + endm +;----------------------------------------------------------------------------; +P_CLPBITSINFOBUFFER macro cscan, lpBits, lpBitsInfo, wUsage, opts + P_VALIDATEBITSINFOBUFFER DIB_PART_DIB, 0, 0, 0, 0, cscans, lpBits, lpBitsInfo, wUsage, DIB_PTR_CLP, DIB_PTR_CLP, opts + endm +;----------------------------------------------------------------------------; +P_LPBITSINFOBUFFER macro cScans, lpBits, lpBitsInfo, wUsage, opts + P_VALIDATEBITSINFOBUFFER DIB_PART_DIB, 0, 0, 0, 0, cscans, lpBits, lpBitsInfo, wUsage, DIB_PTR_LP, DIB_PTR_LP, opts + endm + +;----------------------------------------------------------------------------; +;NOTE: It is assumed that this macro is only called from GetDIBits. The flag +;DIB_PTR_GETDIBITS is a special one which tells the ValidateDIBHeader routine +;to ignore the biClrUsed field. + +P_LPBITSINFOBUFFER0 macro cScans, lpBits, lpBitsInfo, wUsage, opts + P_VALIDATEBITSINFOBUFFER DIB_PART_DIB, 0, 0, 0, 0, cscans, lpBits, lpBitsInfo, wUsage, DIB_PTR_LP0, DIB_PTR_GETDIBITS, opts + endm + +;----------------------------------------------------------------------------; +P_CFULLLPBITSINFOBUFFER macro lpBits, lpBitsInfo, wUsage, opts + P_VALIDATEBITSINFOBUFFER DIB_FULL_DIB, 0, 0, 0, 0, 0, lpBits, lpBitsInfo, wUsage, DIB_PTR_CLP, DIB_PTR_CLP, opts + endm + +;----------------------------------------------------------------------------; +P_GHPACKEDDIB macro hDIB, wUsage, opts + local exit + local errexit + +;; hDIB is a global handle to a apacked DIB. + + _GenParm <hDIB>,2,<opts> + _GenParm <wUsage>,2,<opts> + + if VLgen + +;; first validate the handle itself. + IFNDEF WOW + mov ax,_P_&hDIB + lcall GHANDLE + _gensub GHANDLE + + ENDIF +;; validate wUsage + + mov ax,_P_&wUsage + cmp ax,DIB_MAX + jbe @F ;; unsigned comparison to catch < 0. + mov bx,ERR_BAD_VALUE + lcall Inval_Param_ + jmp exit +@@: + + push si + push di ;;save + +;; validate the header. + + mov dx,_P_&wUsage + xor ax,ax + mov cx,_P_&hDIB ;;CX:AX has a pointer to the DIB + mov di, DIB_VALIDATE_COLOR + DIB_PTR_CLP + + call ValidateDIBHeader + or ax,ax + jz @f ;;valid header + pop di + pop si ;;restore + mov bx,ERR_BAD_PTR + lcall Inval_Param_ + jmp exit + +@@: + +;; the header has been validated. DI:SI returns the pointer past the end of +;; the DIB header and the color table. For a packed DIB this is the start of +;; the bits. + + mov es,_P_&hDIB + xor bx,bx ;;es:bx-> header, di:si -> bits + mov cx, DIB_FULL_DIB+DIB_PTR_CLP + + call ValidateDIBSize + pop di + pop si + or ax,ax + jz exit ;;valid size + mov bx,ERR_BAD_PTR + lcall Inval_Param_ +exit: + endif + endm +;----------------------------------------------------------------------------; +P_CLPBITMAPINFOHEADER macro lpBi, opts + local exit + +;; lpBi - pointer to bitmap info header which does not have a color table + + _GenParm <lpBi>,4,<opts> + + if VLgen + + push si + push di + mov ax,word ptr _P_&lpBi + mov cx,word ptr _P_&lpBi+2 + mov di, DIB_NO_COLOR + DIB_PTR_CLP + + call ValidateDIBHeader + pop di + pop si + or ax,ax + jz exit + mov bx,ERR_BAD_PTR + lcall Inval_Param_ +exit: + + endif + endm +;----------------------------------------------------------------------------; + +P_CLPDIBITMAP0 macro dwUsage, lpInitBits, lpInitInfo, wUsage, opts + local validate_dib + local no_init + local exit + local flags_ok + + _DefParm <dwUsage>,4,<opts> + _DefParm <lpInitBits>,4,<opts> + _DefParm <lpInitInfo>,4,<opts> + _DefParm <wUsage>,2,<opts> + + if VLgen + _FlsFrame + +ifdef DEBUG + mov ax,_P_&dwUsage + mov cx,_P_&dwUsage+2 + test ax,not(CBM_VALID_L) + jnz @F + test cx,not(CBM_VALID_H) + jz flags_ok +@@: + mov bx,ERR_BAD_DFLAGS + lcall Inval_Param_ +flags_ok: + +endif ;DEBUG + +;; the rest of the validation depends on the value of dwUsage. + + cmp word ptr _P_&dwUsage+2,0 + jne no_init + mov ax, word ptr _P_&dwUsage + cmp ax,CBM_INIT + je validate_dib + +no_init: + mov ax,_P_&lpInitBits + mov cx,_P_&lpInitBits+2 + xor bx,bx + lcall CLP0 + _gensub LP + + mov ax,_P_&lpInitInfo + mov cx,_P_&lpInitInfo+2 + xor bx,bx + lcall CLP0 + + mov ax,_P_&wUsage + cmp ax,DIB_MAX + jbe @F ;; unsigned comparison to catch < 0. + mov bx,ERR_BAD_VALUE + lcall Inval_Param_ +@@: + jmp exit + +validate_dib: + +;; validate the bitmap info header first. Validate the color table size too. + + push si + push di + mov ax,word ptr _P_&lpInitInfo + mov cx,word ptr _P_&lpInitInfo+2 + mov dx,_P_&wUsage + mov di, DIB_VALIDATE_COLOR + DIB_PTR_CLP + + call ValidateDIBHeader + or ax,ax + jz @f + pop di + pop si + mov bx,ERR_BAD_PTR + lcall Inval_Param_ + jmp exit +@@: + +;; now validate the size of the bitsbuffer. Use complete height + + mov si, word ptr _P_&lpInitBits + mov di, word ptr _P_&lpInitBits+2 + les bx,_P_&lpInitInfo + mov cx, DIB_FULL_DIB+DIB_PTR_CLP + + call ValidateDIBSize + pop di + pop si + or ax,ax + jz exit + mov bx,ERR_BAD_PTR + lcall Inval_Param_ +exit: + endif + endm +;----------------------------------------------------------------------------; + +P_CLPBITBUFFER0 macro cx, cy, cPlanes, cBitsPixel, lpBits, opts + P_int <cx>,<opts> + P_int <cy>,<opts> + P_int <cPlanes>,<opts> + P_int <cBitsPixel>,<opts> + P_CLPBYTE0 <lpBits>,<opts> + endm + +P_CLPETOBUF macro lpsz, cch, lpdx, opts + P_CLPBUFFER0 <lpsz>,<cch>,<opts> + P_CLPINT0 <lpdx>,<opts> + endm + +P_TEXTEXTEX macro lpsz, cch, nMaxExt, lpnFit, lpDx, opts + P_CLPBUFFER <lpsz>,<cch>,<opts> + P_int <nMaxExt>,<opts> + P_LPINT0 <lpnFit>,<opts> + P_LPINT0 <lpDX>,<opts> + endm +; +; GDI structures +; +_DefSimpleF F_LBCOLOR,4 +_DefSimpleF F_CLPBITS,4 +_DefSimpleF F_DWSIZE,4 +_DefSimpleF F_COMPRESS,4 +_DefSimpleF F_DIBSIZE0,4 + +_DefSimpleF F_HMF,2 +_DefSimpleF F_VALUE,2 +_DefSimpleF F_WMBZ,2 +_DefSimpleF F_WSIZE,2 +_DefSimpleF F_CONST,2 +_DefSimpleF F_BITCOUNT,2 +_DefSimpleF F_RVALUE,2 +_DefSimpleF F_short,2 +_DefSimpleF F_VERSION,2 + +_DefSimpleF F_PITCHFAMILY,1 +_DefSimpleF F_BVALUE,1 +_DefSimpleF F_BFLAGS,1 + +STRUCT <RGBQUAD> +F_BYTE rgbBlue +F_BYTE rgbGreen +F_BYTE rgbRed +F_BYTE rgbReserved +ENDSTRUCT + +STRUCT <RGBTRIPLE> +F_BYTE rgbtBlue +F_BYTE rgbtGreen +F_BYTE rgbtRed +ENDSTRUCT + +STRUCT <LOGBRUSH> +F_VALUE lbStyle, BS_MAX +F_LBCOLOR lbColor +F_VALUE lbHatch, HS_MAX +ENDSTRUCT + +_GenLP <P_CLPLOGBRUSH>,<CLP>,%VLcbsLOGBRUSH +_GenLP <P_CLPLOGBRUSH0>,<CLP0>,%VLcbsLOGBRUSH +_GenLP <P_LPLOGBRUSH>,<LP>,%VLcbsLOGBRUSH +_GenLP <P_LPLOGBRUSH0>,<LP0>,%VLcbsLOGBRUSH + +STRUCT <LOGFONT> +F_int lfHeight +F_int lfWidth +F_int lfEscapement +F_int lfOrientation +F_VALUE lfWeight, FW_MAX +F_BYTE lfItalic +F_BYTE lfUnderline +F_BYTE lfStrikeOut +F_BYTE lfCharSet +F_BVALUE lfOutPrecision, OUT_MAX +F_BVALUE lfClipPrecision, CLIP_MAX +F_BVALUE lfQuality, QUALITY_MAX +F_PITCHFAMILY lfPitchAndFamily +F_BYTE lfFaceName ;var-length field +ENDSTRUCT + +_GenLP <P_CLPLOGFONT>,<CLP>,%VLcbsLOGFONT +_GenLP <P_CLPLOGFONT0>,<CLP0>,%VLcbsLOGFONT +_GenLP <P_LPLOGFONT>,<LP>,%VLcbsLOGFONT +_GenLP <P_LPLOGFONT0>,<LP0>,%VLcbsLOGFONT + +STRUCT <LOGPEN> +F_VALUE lopnStyle, PS_MAX +F_POINT lopnWidth +F_DWORD lopnColor +ENDSTRUCT + +_GenLP <P_CLPLOGPEN>,<CLP>,%VLcbsLOGPEN +_GenLP <P_CLPLOGPEN0>,<CLP0>,%VLcbsLOGPEN +_GenLP <P_LPLOGPEN>,<LP>,%VLcbsLOGPEN +_GenLP <P_LPLOGPEN0>,<LP0>,%VLcbsLOGPEN + +STRUCT <METAFILEPICT> +F_RVALUE nMapMode, MM_MIN, MM_MAX +F_int xExt +F_int yExt +F_HMF hMF +ENDSTRUCT + +_GenLP <P_CLPMETAFILEPICT>,<CLP>,%VLcbsMETAFILEPICT +_GenLP <P_CLPMETAFILEPICT0>,<CLP0>,%VLcbsMETAFILEPICT +_GenLP <P_LPMETAFILEPICT>,<LP>,%VLcbsMETAFILEPICT +_GenLP <P_LPMETAFILEPICT0>,<LP0>,%VLcbsMETAFILEPICT + +STRUCT <TEXTMETRIC> ;currently used only for output +F_int tmHeight +F_int tmAscent +F_int tmDescent +F_int tmInternalLeading +F_int tmExternalLeading +F_int tmAveCharWidth +F_int tmMaxCharWidth +F_int tmWeight +F_BYTE tmItalic +F_BYTE tmUnderlined +F_BYTE tmStruckOut +F_BYTE tmFirstChar +F_BYTE tmLastChar +F_BYTE tmDefaultChar +F_BYTE tmBreakChar +F_BYTE tmPitchAndFamily +F_BYTE tmCharSet +F_int tmOverhang +F_int tmDigitizedAspectX +F_int tmDigitizedAspectY +ENDSTRUCT + +_GenLP <P_CLPTEXTMETRIC>,<CLP>,%VLcbsTEXTMETRIC +_GenLP <P_CLPTEXTMETRIC0>,<CLP0>,%VLcbsTEXTMETRIC +_GenLP <P_LPTEXTMETRIC>,<LP>,%VLcbsTEXTMETRIC +_GenLP <P_LPTEXTMETRIC0>,<LP0>,%VLcbsTEXTMETRIC + +; OutlineTextMetrics return buffer +; +P_LPETM0 macro cch, lpch, opts + + _DefParm <cch>,2,<opts> + _DefParm <lpch>,4,<opts> + + if VLgen + _FlsFrame + mov ax,_P_&lpch + mov cx,_P_&lpch+2 + mov bx,_P_&cch + lcall LP0 + _gensub LP + endif +endm + +; GetGlyphOutline return buffer. +; + +P_LPGGO0 macro cch, lpch, opts + + _DefParm <cch>,4,<opts> + _DefParm <lpch>,4,<opts> + + if VLgen + _FlsFrame + +;; The buffer should be atleast of the given size. + + ValidateHugeLP _P_&cch, _P_&lpch, IsBadHugeWritePtr, NULL + + endif + endm + + +; GetFontData return buffer +; + +P_LPFDATA0 macro lpch, cch, opts + + _DefParm <lpch>,4,<opts> + _DefParm <cch>,4,<opts> + + if VLgen + _FlsFrame + + ValidateHugeLP _P_&cch, _P_&lpch, IsBadHugeWritePtr, NULL + + endif + endm + +;---------------------------------------------------------------------------; +; hugw pointer validation routine. + + +STRUCT <GLYPHMETRICS> ;only used for output +F_WORD gmBlackBoxX +F_WORD gmBlackBoxY +F_POINT gmptGlyphOrigin +F_short gmCellIncX +F_short gmCellIncY +ENDSTRUCT + +_GenLP <P_CLPGLYPHMETRICS>,<CLP>,%VLcbsGLYPHMETRICS +_GenLP <P_CLPGLYPHMETRICS0>,<CLP0>,%VLcbsGLYPHMETRICS +_GenLP <P_LPGLYPHMETRICS>,<LP>,%VLcbsGLYPHMETRICS +_GenLP <P_LPGLYPHMETRICS0>,<LP0>,%VLcbsGLYPHMETRICS + +STRUCT METARECORD +F_DWORD rdSize +F_WORD rdFunction +F_WORD rdParm ;var. length field +ENDSTRUCT + +_GenLP <P_CLPMETARECORD>,<CLP>,%VLcbsMETARECORD +_GenLP <P_CLPMETARECORD>,<CLP0>,%VLcbsMETARECORD +_GenLP <P_LPMETARECORD>,<LP>,%VLcbsMETARECORD +_GenLP <P_LPMETARECORD>,<LP0>,%VLcbsMETARECORD + +;------------------------------- +; special-case macro definitions + + +STRUCT <BITMAP> +F_intMBZ bmType +F_int bmWidth +F_int bmHeight +F_int bmWidthBytes +F_BYTE bmPlanes +F_BYTE bmBitsPixel +F_CLPBITS bmBits +ENDSTRUCT + +P_CLPBITMAP macro lp, opts + _GenParm <lp>,4,<opts> + if VLgen + mov ax,_P_&lp + mov cx,_P_&lp+2 + mov bx,VLcbsBITMAP + lcall CLP + _gensub LP + + les bx,_P_&lp ; Accept bmBits == NULL + mov ax,es:[bx]._F_bmBits + mov cx,es:[bx]._F_bmBits+2 + or ax,cx + jz @F + xor ax,ax + mov al,es:[bx]._F_bmPlanes ;bmPlanes + mul word ptr es:[bx]._F_bmHeight + mul word ptr es:[bx]._F_bmWidthBytes + xchg ax,dx + mov ax,es:[bx]._F_bmBits + mov bx,dx ;bx = size + lcall CLP + _gensub LP + @@: + endif +endm + +STRUCT <BITMAPCOREHEADER> +F_DWSIZE bcSize +F_WORD bcWidth +F_WORD bcHeight +F_CONST bcPlanes, 1 +F_BITCOUNT bcBitCount +ENDSTRUCT + +STRUCT <BITMAPINFOHEADER> +F_DWSIZE biSize +F_WORD biWidthLo +F_WMBZ biWidthHi +F_WORD biHeightLo +F_WMBZ biHeightHi +F_CONST biPlanes, 1 +F_BITCOUNT biBitCount +F_COMPRESS biCompression +F_DIBSIZE0 biSizeImage +F_DWORD biXPelsPerMeter +F_DWORD biYPelsPerMeter +F_DWORD biClrUsed +F_DWORD biClrImportant +ENDSTRUCT +;----------------------------------------------------------------------------; +P_VALIDATEBITSINFOBUFFER macro fn, yE, xS, yS, nStart, n, lpBits, lpBi, wUse, rBits, rBi, opts + local exit + local total_clip + +;; NOTE: The first 4 parameters are defined only when fn & DIB_RECT_DIB is +;; TRUE (they are 0 otherwise). +;; The 5th parameter is undefined if fn & DIB_FULL_DIB is TRUE. + +;; yE - yExtent in DIB (only when fn & DIB_RECT_DIB is TRUE) +;; xS - xStart in DIB (only when fn & DIB_RECT_DIB is TRUE) +;; yS - yStart in DIB (only when fn & DIB_RECT_DIB is TRUE) +;; nStart - start DIB scan (only when fn & DIB_RECT_DIB is TRUE) +;; +;; n - numScans parameter. If fn & DIB_FULL_DIB is TRUE, n is not defined. +;; lpBits - pointer to the bits +;; lpBi - pointer to bitmap info +;; wUse - the wUsage parameter +;; rBits - routine to validate length of lpBits buffer +;; rBi - routine to validate length of lpBi buffer. +;; opts - optional parameters + + if fn and DIB_RECT_DIB + _DefParm <yE>,2,<opts> + _DefParm <xS>,2,<opts> + _DefParm <yS>,2,<opts> + _DefParm <nStart>,2,<opts> + endif + + if fn and DIB_PART_DIB + _DefParm <n>,2,<opts> + endif + + _DefParm <lpBits>,4,<opts> + _DefParm <lpBi>,4,<opts> + _DefParm <wUsage>,2,<opts> + + if VLgen + _FlsFrame + +;; validate wUsage + + mov ax,_P_&wUsage + cmp ax,DIB_MAX + jbe @F ;; unsigned comparison to catch < 0. + mov bx,ERR_BAD_VALUE + lcall Inval_Param_ +@@: + + + push si + push di + +;; validate the bitmap info header first. Validate the color table size too. + + mov ax,word ptr _P_&lpBi + mov cx,word ptr _P_&lpBi+2 + mov dx,_P_&wUsage + mov di, DIB_VALIDATE_COLOR + or di, rBi + + call ValidateDIBHeader + or ax,ax + jz @f + pop di + pop si + mov bx,ERR_BAD_PTR + lcall Inval_Param_ + jmp exit +@@: + +;; now validate the size of the bitsbuffer. + + mov si, word ptr _P_&lpBits + mov di, word ptr _P_&lpBits+2 + les bx,_P_&lpBi + + if fn and DIB_PART_DIB + + mov dx,_P_&n + + endif + + if fn and DIB_RECT_DIB + +;; for a call which specifies a rectangular area in the DIB (SetDIBitsToDevice), +;; compute the size of the DIB that will actually be validated. +;; +;; The cases are: +;; +;; (1) If (yS > (nStart + n) : The DIB RECT will be totally clipped. Do not +;; validate the DIB size in this case. +;; (2) If (yS + yE) < nStart : The DIB rect will totally be clipped. Do not +;; validate the DIB size in this case. +;; (3) Else, compute the min of (yS+yE-nStart) and (n) and use it to validate +;; the size of the DIB buffer. + + mov dx, _P_&yS + mov cx, _P_&nStart + add cx, _P_&n + cmp dx, cx + ja total_clip ;; case (1) + add dx, _P_&yE + cmp dx, _P_&nStart + jb total_clip ;; case (2) + sub dx, _P_&nStart + cmp dx, _P_&n ;; compute min in case (3) + jb @f ;; (yS+yE-nStart) is < n + mov dx, _P_&n ;; validate only n scans + jmp short @f + +total_clip: + pop di + pop si ;; will not validate DIB size + jmp short exit + +@@: + endif + + mov cx, fn + or cx, rBits + + call ValidateDIBSize + pop di + pop si + or ax,ax + jz exit + mov bx,ERR_BAD_PTR + lcall Inval_Param_ +exit: + + + endif + endm + +;----------------------------------------------------------------------------; + +STRUCT <LOGPALETTE> ;fixed-size portion of struct. +F_VERSION palVersion +F_WORD wEntries +ENDSTRUCT + +P_CLPLOGPALETTE macro lp, opts + _GenParm <lp>,4,<opts> + if VLgen + mov ax,_P_&lp + mov cx,_P_&lp+2 + mov bx,VLcbsLOGPALETTE + lcall CLP + _gensub LP + + les bx,_P_&lp + mov cx,es + + mov ax,VLcbsPALETTEENTRY + mul word ptr es:[bx]._F_wEntries ; ax = size of all palette entries + add ax,VLcbsLOGPALETTE ; ax = total size of struct + xchg ax,bx + + lcall CLP + _gensub LP + endif +endm + +STRUCT DEVMODE ;fixed-size fields +F_RGCH dmDeviceName, CCHDEVICENAME +F_VERSION dmSpecVersion +F_WORD dmDriverVersion ;value assigned by driver developer +F_WSIZE dmSize ;size of DEVMODE struct. +F_WORD dmDriverExtra ;size of dmDriverData field. +F_DWORD dmFields +F_RVALUE dmOrientation, DMORIENT_PORTRAIT, DMORIENT_LANDSCAPE +F_RVALUE dmPaperSize, DMPAPER_FIRST, DMPAPER_LAST +F_short dmPaperLength +F_short dmPaperWidth +F_short dmScale +F_short dmCopies +F_RVALUE dmDefaultSource, DMBIN_FIRST, DMBIN_LAST +F_RVALUE dmPrintQuality, DMPRINT_FIRST, DMPRINT_LAST ;** range -4 to -1 +F_RVALUE dmColor, DMCOLOR_FIRST, DMCOLOR_LAST ;** range 1-2 +F_RVALUE dmDuplex, DMDUP_FIRST, DMDUP_LAST ;** range 1-3 +ENDSTRUCT + +P_CLPDEVMODE0 macro lp, opts + local dmexit + local dmbad + local dmbad1 + + _GenParm <lp>,4,<opts> + if VLgen + mov ax,_P_&lp + mov cx,_P_&lp+2 + mov bx,ax + or bx,cx + jz dmexit ;allow NULL pointer + + mov bx,VLcbsDEVMODE + lcall CLP ;verify fixed-size fields + _gensub LP + + les bx,_P_&lp + mov ax,es:[bx]._F_dmDriverExtra + or ax,ax + jz dmexit ;if 0 extra bytes, we're done + + add ax,VLcbsDEVMODE + xchg ax,bx ;bx=size of DEVMODE+extra bytes + mov cx,es + +;; MICROGRAFIX draw uses CreateDC to load one of thier format conversion DLLs. +;; The pass in a DevMode structure which is either a private structure, or +;; has a bogus value in the _F_dmDriverExtra field. We need to loosen the +;; validation and turn an invalid DevMode detection into a warning. + +beg_fault_trap dmbad + mov es,cx + or bx,bx ; cb == 0? + jz dmexit ; yes: just check selector + dec bx + add bx,ax + jc dmbad1 ; check 16 bit overflow + mov bl,es:[bx] ; check read permission, limit +end_fault_trap + jmp short dmexit ; structure is valid + +dmbad: + fault_fix_stack +dmbad1: + mov bx,ERR_BAD_PTR or ERR_WARNING + lcall Inval_Param_ + +dmexit: + endif +endm + + +;----------------------------------------------------------------------------; +; P A R A M E T E R V A L I D A T I O N R O U T I N E S ; +;----------------------------------------------------------------------------; + +; DIB validation flag constants. Do not change these constants without +; changing them in GDI.API. + +DIB_RGB_COLORS equ 0 +DIB_VALIDATE_COLOR equ 1 +DIB_VALIDATE_RW equ 2 +DIB_PTR0 equ 4 +DIB_FULL_DIB equ 8 +DIB_FULL_COLOR equ 16 +DIB_RECT_DIB equ 32 +DIB_PART_DIB equ 64 + +; derived DIB flag constants + +DIB_PTR_CLP equ 0 +DIB_NO_COLOR equ 0 +DIB_PTR_LP equ DIB_VALIDATE_RW +DIB_PTR_CLP0 equ DIB_PTR0 +DIB_PTR_LP0 equ DIB_VALIDATE_RW+DIB_PTR0 +ERR_BAD_PTR equ 07007h +DIB_DIBTODEV equ DIB_PART_DIB+DIB_RECT_DIB +DIB_PTR_GETDIBITS equ DIB_VALIDATE_RW+DIB_FULL_COLOR +NO_COLOR_TABLE equ 9 + +BITMAP struc + bmType DW ? + bmWidth DW ? + bmHeight DW ? + bmWidthBytes DW ? + bmPlanes DB ? + bmBitsPixel DB ? + bmBits DD ? +BITMAP ends + +RGBTRIPLE struc + rgbBlue db ? + rgbGreen db ? + rgbRed db ? +RGBTRIPLE ends + +RGBQUAD struc + rgbqBlue db ? + rgbqGreen db ? + rgbqRed db ? + rgbqReserved db ? +RGBQUAD ends + +; structures for defining DIBs +BITMAPCOREHEADER struc + bcSize dd ? + bcWidth dw ? + bcHeight dw ? + bcPlanes dw ? + bcBitCount dw ? +BITMAPCOREHEADER ends + +BITMAPINFOHEADER struc + biSize dd ? + biWidth dd ? + biHeight dd ? + biPlanes dw ? + biBitCount dw ? + + biCompression dd ? + biSizeImage dd ? + biXPelsPerMeter dd ? + biYPelsPerMeter dd ? + biClrUsed dd ? + biClrImportant dd ? +BITMAPINFOHEADER ends + +BITMAPINFO struc + bmiHeader db (SIZE BITMAPINFOHEADER) DUP (?) + bmiColors db ? ; array of RGBQUADs +BITMAPINFO ends + +BITMAPCOREINFO struc + bmciHeader db (SIZE BITMAPCOREHEADER) DUP (?) + bmciColors db ? ; array of RGBTRIPLEs +BITMAPCOREINFO ends + +BITMAPFILEHEADER struc + bfType dw ? + bfSize dd ? + bfReserved1 dw ? + bfReserved2 dw ? + bfOffBits dd ? +BITMAPFILEHEADER ends + +externFP IsBadReadPtr ;(KERNEL) +externFP IsBadWritePtr ;(KERNEL) +externFP IsBadHugeReadPtr ;(KERNEL) +externFP IsBadHugeWritePtr ;(KERNEL) + +;createseg _TEXT,TEXT,BYTE,PUBLIC,CODE +createseg _TEXT,TEXT,WORD,PUBLIC,CODE +sBegin TEXT +;----------------------------------------------------------------------------; +; ValidateDIBHeader: ; +; ; +; This routine validates the DIB header: ; +; ; +; Entry: ; +; CX:AX -- pointer to DIB header (either core or info header) ; +; DX: -- wUsage parameter ; +; DI: -- Flags: ; +; BIT0 - (DIB_VALIDATE_COLOR) set if no color table validatio ; +; to be done. ; +; BIT1 - (DIB_VALIDATE_RW) set if R-W validation to be done. ; +; BIT2 _ (DIB_PTR0) set if NULL pointer OK ; +; BIT3 _ (DIB_FULL_DIB) set if complete DIB (not used here); +; BIT4 - (DIB_FULL_COLOR) ignore biClrUsed if set. ; +; Returns: ; +; AX = 0 if valid header. ; +; DI:SI: will point just past the end of the buffer. ; +; ; +; Uses: ; +; Free to use AX,BX,CX,DX,SI,DI and ES. ; +; ; +;----------------------------------------------------------------------------; + +public ValidateDIBHeader +ValidateDIBHeader proc near + + +; the header must atleast be the size of COREHEADER. + + mov bx,SIZE BitmapCoreHeader + push cx + push ax ;save the pointer to header + call DIB_Validate_Pointer ;is it a valid pointer ? + or ax,ax + pop ax + pop cx ;restore pointer + jz VDH_cont ;base size ok + jmp VDH_bad_header ;invalid size + +VDH_cont: + +; now it is safe to load the pointer to the header and validate the actual +; size. + + mov es,cx + mov bx,ax ;es:bx -> dib header + mov si,word ptr es:[bx].biSize ;load and keep the size + mov cx, SIZE RGBTriple ;assume COREHEADER. + cmp si,SIZE BitmapCoreHeader ;COREHEADER ? + jz VDH_core ;it is a core header + mov cx, SIZE RGBQuad ;assume INFOHEADER + cmp si, SIZE BitmapInfoHeader ;is it an info header ? + jnz VDH_bad_header ;header is not right. + +; we have a new header. Make sure that some of the fields that the code +; expects to be 0 are 0. + + xor ax,ax ;need zeros. + cmp word ptr es:[bx].biHeight+2,ax + jne VDH_bad_header ;invalid + cmp word ptr es:[bx].biWidth+2,ax + jne VDH_bad_header ;invalid + +VDH_get_bit_count: + cmp es:[bx].biPlanes,1 + jne VDH_bad_header ;no. + mov ax,es:[bx].biBitCount ;load the bits per pel + jmp short VDH_check_color ;validate color + +VDH_core: + cmp es:[bx].bcPlanes,1 + jne VDH_bad_header ;no. + mov ax,es:[bx].bcBitCount ;load the bits per pel + +VDH_check_color: + +; if the bits per pel is >= NO_COLOR_TABLE, we do not have a color table in +; the DIB. + + cmp ax,NO_COLOR_TABLE + jae VDH_no_color_table + +; if color table validation is not needed, we can return if the header is +; a core header (we have validated size) or validate the size of the +; basic header and return. + + test di, DIB_VALIDATE_COLOR ;color validation needed ? + jnz VDH_validate_color ;yes. + +VDH_no_color_table: + +; color table validation is not needed. We are done if this is a core header. + + cmp si, SIZE BitmapCoreHeader ;core header ? + jz VDH_return_OK ;is, validation done. valid. + mov ax,bx ;get offset + mov bx,si ;get base header size + jmp short VDH_validate_size ;validate the total size + +VDH_bad_header: + + mov ax,1 ;return from here with error + jmp short VDH_return ;error return + + +VDH_validate_color: + cmp dx,DIB_RGB_COLORS ;is the usage RGB values + jz VDH_color_entry_size_in_cx ;cx has size of each entry + mov cx,2 ;size per entry for palettes + +VDH_color_entry_size_in_cx: + mov dx,ax ;get the bit count in dx + +; if DIB_FULL_COLOR bit is set, we will ignore the value if biClrUsed. + + test di,DIB_FULL_COLOR ;validate complete color table ? + jnz VDH_get_num_colors ;yes. + +; check out the biClrUsed value. + + cmp si, SIZE BitmapInfoHeader ;is this an info header ? + jnz VDH_get_num_colors ;no. + mov ax,word ptr es:[bx].biClrUsed ;is this specified ? + or ax,ax + jnz VDH_num_colors_got ;yes. ax has num colors + +VDH_get_num_colors: + xchg dx,cx + mov ax,1 + shl ax,cl ;number of color entries in ax + xchg dx,cx + +VDH_num_colors_got: + mul cx ;cx had size of each entry + add ax,si ;add size of header + xchg ax,bx ;size in bx, offset in ax + +VDH_validate_size: + mov cx,es ;cx:ax has ptr, bx has size + +; store the pointer past the header in DI:SI + + mov di,cx + mov si,ax + add si,bx ;past the end. Assume no wrap + call DIB_Validate_Pointer ;validate pointer + jmp short VDH_return ;ax has status + +VDH_return_OK: + xor ax,ax ;valid return + +VDH_return: + ret + +ValidateDIBHeader endp + + +;----------------------------------------------------------------------------; +; ValidateDIBSize: ; +; ; +; Validates the size of the DIB bits. ; +; ; +; Entry: ; +; DI:SI -- pointer to DIB bits (either core or info header) ; +; ES:BX -- pointer to DIB header (already validated) ; +; DX: -- num scans. ; +; CX: -- Flags: ; +; BIT1 - (DIB_VALIDATE_RW) set if R-W validation to be done. ; +; BIT2 _ (DIB_PTR0) set if NULL pointer OK ; +; BIT3 - (DIB_FULL_DIB) set if full DIB bit size to be ; +; validated. ; +; Returns: ; +; AX = 0 if valid header. ; +; ; +; Uses: ; +; Free to use AX,BX,CX,DX,SI,DI and ES. ; +; ; +; Assumes: ; +; Caller has done a PUSH SI/PUSH DI on the frame. ; +;----------------------------------------------------------------------------; +public ValidateDIBSize +ValidateDIBSize proc near + + push cx ;save + cmp word ptr es:[bx].biSize, SIZE BitmapInfoHeader + jz VDB_info ;info header + mov cx,es:[bx].bcBitCount ;get the bit count + mov ax,es:[bx].bcWidth ;and width in pels + jmp short VDB_get_scan_size ;calculate scan size + +VDB_info: + cmp word ptr es:[bx].biCompression+2,0 + jnz VDB_check_size_image + cmp word ptr es:[bx].biCompression, BI_RGB + jz VDB_not_rle ;not an RLE DIB + +VDB_check_size_image: + mov ax,word ptr es:[bx].biSizeImage + mov cx,ax + or cx,word ptr es:[bx].biSizeImage+2 + jz VDB_unknown_size ;unknown size + pop cx ;restore saved cx + mov dx,word ptr es:[bx].biSizeImage+2 + jmp short VDB_validate_size ;size is in dx:ax + +VDB_unknown_size: + mov ax,1 ;validate for 1byte + cwd + pop cx ;restore flags + jmp short VDB_validate_size + +VDB_not_rle: +; calculate the size of the scan. Assume that the width is a word + + mov cx,es:[bx].biBitCount + mov ax,word ptr es:[bx].biWidth + +VDB_get_scan_size: + + push dx ;save + mul cx ;dx:ax = num of bits + add ax,31 + adc dx,0 + and ax, NOT 31 ;round up to multiple of 32 + ror dx,3 ;get ls 3 bits into upper byte + and dh,0e0h ;keep the ms 3 bits + shr ax,3 ;ignore ls 3 bits + or ah,dh ;ax = num bytes per scan + pop dx + +VDB_scan_width_in_ax: + + pop cx ;restore flags + xchg cx,dx ;get flags into dx, scan in cx + + push di ;save + mov di,word ptr es:[bx].bcHeight ;assume core header + cmp word ptr es:[bx].biSize, SIZE BitmapCoreHeader + jz VDB_total_scans_in_di ;di has total height of DIB + mov di,word ptr es:[bx].biHeight ;get low word of height + +VDB_total_scans_in_di: + mov bx,di ;get total height in BX + pop di ;restore + test dx,DIB_FULL_DIB ;is full DIB to be validated ? + jnz VDB_num_scans_in_bx ;yes, bx has num scans. + +; when we are validating partial DIBs, we want to make sure that the +; numScan parameter passed in (now in cx) is not greater than the total +; height. If it is, we will simply validate for the full DIB. + + cmp cx,bx ;is numScan > total scans ? + ja VDB_num_scans_in_bx ;yes, invalid numScans. Use total scans + mov bx,cx ;use numScans + +VDB_num_scans_in_bx: + push dx ;save flags + mul bx ;dx:ax has size + pop cx ;get the flags in cx + +VDB_validate_size: + +; dx:ax has size of the buffer. di:si is the ptr, cx has flags. + + call DIB_Validate_Huge_Pointer + ret + +ValidateDIBSize endp + + +;----------------------------------------------------------------------------; +; DIB_Validate_Pointer: ; +; ; +; Validates the size and access of a pointer. ; +; ; +; Entry: ; +; CX:AX -- pointer to be validate ; +; BX: -- size of buffer ; +; DI: -- flags: ; +; BIT1 - (DIB_VALIDATE_RW) set if R-W validation to be done. ; +; BIT2 _ (DIB_PTR0) set if NULL pointer OK ; +; ; +; Uses: None ; +; returns AX = 0 if valid. ; +; ; +;----------------------------------------------------------------------------; + +public DIB_Validate_Pointer +DIB_Validate_Pointer proc near + + test di,DIB_PTR0 ;NULL pointer allowed ? + jz DBP_not_null ;no. + push ax ;save + or ax,cx ;is the pointer NULL ? + pop ax ;restore + jz DBP_return_ok ;pointer is NULL and is valid + +DBP_not_null: + + push cx + push ax + push bx + test di, DIB_VALIDATE_RW ;read/write validation ? + jnz DBP_rw_validation ;yes. + +; do read only validation: + + call IsBadReadPtr + jmp short DBP_return + +DBP_rw_validation: + call IsBadWritePtr + jmp short DBP_return + +DBP_return_ok: + xor ax,ax ;valid pointer + +DBP_return: + ret + +DIB_Validate_Pointer endp + + +;----------------------------------------------------------------------------; +; DIB_Validate_Huge_Pointer: ; +; ; +; Validates the size and access of a pointer. ; +; ; +; Entry: ; +; DI:SI -- pointer to be validate ; +; DX:AX -- size of buffer ; +; CX: -- flags: ; +; BIT1 - (DIB_VALIDATE_RW) set if R-W validation to be done. ; +; BIT2 _ (DIB_PTR0) set if NULL pointer OK ; +; ; +; Uses: None ; +; returns AX = 0 if valid. ; +; ; +;----------------------------------------------------------------------------; + +public DIB_Validate_Huge_Pointer +DIB_Validate_Huge_Pointer proc near + + test cx,DIB_PTR0 ;NULL pointer allowed ? + jz DBPH_not_null ;no. + push si ;save + or si,di ;is the pointer NULL ? + pop si ;restore + jz DBPH_return_ok ;pointer is NULL and is valid + +DBPH_not_null: + + push di + push si ;ds:si is pointer to bits + push dx + push ax ;dx:ax is the dword size + test cx, DIB_VALIDATE_RW ;read/write validation ? + jnz DBPH_rw_validation ;yes. + +; do read only validation: + + call IsBadHugeReadPtr + jmp short DBPH_return + +DBPH_rw_validation: + + call IsBadHugeWritePtr + jmp short DBPH_return + +DBPH_return_ok: + xor ax,ax ;valid pointer + +DBPH_return: + ret + +DIB_Validate_Huge_Pointer endp + +sEnd TEXT + +;======================================================================= +; +; API Descriptions +; +; in PALETTE.ASM +API void, AnimatePalette, TEXT, <ASM> +P_HPALETTE hPal ; validated by VALID? (3.0 and 3.1) +P_WORD wStartIndex +P_CLPPALENTRYBUFFER nEntries,lpPalColors ; ** + +; in PALETTE.ASM +API HPALETTE, CreatePalette, TEXT, <ASM> +P_CLPLOGPALETTE lpLogPal ;** + +; in PALETTE.ASM +API WORD, GetPaletteEntries, TEXT, <ASM> +P_HPALETTE hPalette ;validated by VALID? (3.0 and 3.1) +P_WORD wStartIndex +P_LPPALENTRYBUFFER wEntries, lpPalColors ; buffer filled in DEBUG Win 3.1 + +; in PALETTE.ASM +API WORD, GetNearestPaletteIndex, TEXT, <ASM> +P_HPALETTE hPalette ;validated by VALID? (3.0 and 3.1) +P_DWORD color + +; in PALETTE.ASM +API WORD, GetSystemPaletteEntries, TEXT, <ASM> +P_HDC hdc ;validated by VALID? (3.0 and 3.1) +P_WORD wStartIndex +P_LPPALENTRYBUFFER wEntries,lpPalColors ;buffer filled in DEBUG Win 3.1 + +; in PALETTE.ASM +API WORD, GetSystemPaletteUse, TEXT, <ASM> +P_HDC hdc ;validated by VALID? (3.0 and 3.1) + +; in PALETTE.ASM +API BOOL, ResizePalette, TEXT, <ASM> +P_HPALETTE hPalette ;validated by VALID? (3.0 and 3.1) +P_WORD nNumEntries + +; in PALETTE.ASM +API WORD, SetPaletteEntries, TEXT, <ASM> +P_HPALETTE hPalette ;validated by VALID? (3.0 and 3.1) +P_WORD wStartIndex +P_CLPPALENTRYBUFFER wEntries, lpPalColors + +; in PALETTE.ASM +API WORD, SetSystemPaletteUse, TEXT, <ASM> +P_HDC hdc ;validated by VALID? (3.0 and 3.1) +P_WORD wUsage + +; in PALETTE.ASM +API int, UpdateColors, TEXT, <ASM> +P_HDCMETA hdc ;validated by VALID? (3.0 and 3.1) + +; in PRNTCTL.C (new for Win 3.1) +API int, AbortDoc, TEXT +P_HDCMETA hdc ; validated by Valid() +APIERR + mov ax, SP_ERROR ;General escape error +APIEND + +; in PRNTCTL.C (New for Win 3.1) +API int, EndPage, TEXT +P_HDCMETA hdc ; Checked by Valid(). Encapsulates ENDPAGE escape +APIERR + mov ax, SP_ERROR ;General escape error +APIEND + +; in PRNTCTL.C (New for Win 3.1) +API int, EndDoc, TEXT +P_HDCMETA hdc ; Checked by Valid(). Encapsulates NEWFRAME escape +APIERR + mov ax, SP_ERROR ;General escape error +APIEND + +STRUCT <DOCINFO> +F_int cbSize +F_CLPSTR lpszDocName +F_CLPSTR0 lpszOutput +ENDSTRUCT + +_GenLP <P_CLPDOCINFO>,<CLP>,%VLcbsDOCINFO + +; in PRNTCTL.C (new for 3.1) +API int, StartDoc, TEXT +P_HDCMETA hdc ;checked by Valid() +P_CLPDOCINFO lpDocInfo +APIERR + mov ax, SP_ERROR ;General escape error +APIEND + +; in PRNTCTL.C (new for 3.1) +API int, StartPage, TEXT +P_HDCMETA hdc ;checked by Valid(). Null error return + +; in PRNTCTL.C (new for 3.1) +API int, SetAbortProc, TEXT +P_HDCMETA hdc +P_LPFNABORT0 lpProc ;** +APIERR + mov ax, SP_ERROR ;General escape error +APIEND + +; in DCMAN1.ASM +API HDC, CreateCompatibleDC, TEXT, <ASM> +P_HDC0 hdc ; 0 => use screen DC + +; in DCMAN1.ASM +API HDC, CreateIC ,TEXT, <ASM,FUNNYFRAME,NODATA> ;nogen +P_CLPSTR lpDriverName +P_CLPSTR0 lpDeviceName +P_CLPSTR0 lpOutput +P_DWORD lpInitData ; Driver-dependent data or NULL +APIEND + + +; in DCMAN1.ASM +API HDC, CreateDC, TEXT, <ASM,FUNNYFRAME,NODATA> ;nogen +; +; START of special ATM hackery. +; + jmp short SkipATMHackery +; +; Addresses of certain kernel functions patched by ATM loader. +; +;ATM_LPFN CreateDC_lpfn, LoadLibrary +;ATM_LPFN CreateDC_lpfn, GetProcAddress +;ATM_LPFN CreateDC_lpfn, FreeLibrary +; +; InternalCreateDC() hook that gets patched by ATM +; +;public ATMInternalCreateDC +;ATMInternalCreateDC: +; +; Old Windows prolog code that will be properly +; recognized by the ATM installation code... +; +; mov ax,_DATA +; inc bp +; push bp +; mov bp,sp +; push ds ; push ds and pop it off. +; pop ds ; (we need to pop DS rather than +; ; something fast like pop AX because +; ; ATM doesn't preserve DS itself) +; pop bp ; Take down the frame completely. +; dec bp +;ExternNP InternalCreateDC ; (in dcman1.asm) +; jmp InternalCreateDC ; now go to the real code +SkipATMHackery: +; +; END of special ATM hackery +; +P_CLPSTR lpDriverName +P_CLPSTR0 lpDeviceName ; can be NULL if lpDriverName is "DISPLAY" +P_CLPSTR0 lpOutput ; can be NULL if lpDriverName is "DISPLAY" +P_CLPDEVMODE0 lpInitData ; ** points to DEVMODE struct. + +; in DCMAN2.ASM +API BOOL, DeleteDC, TEXT, <ASM,ATMFRAMEDS> +P_HDC hdc ; Validated by VALIDDEBUG? (3.1), VALID? (3.0) +APIEND +ATM_LPFN DeleteDC_lpfn, FreeLibrary + +; in DCMAN2.ASM +API BOOL, RestoreDC, TEXT, <ASM> +P_HDCMETA hdc +P_int level ;number of DC on context stack or -1 + +; in DCMAN2.ASM +API int, SaveDC, TEXT, <ASM> +P_HDCMETA hdc ; validated by VALID? (3.0 and 3.1) + +; in RESETDC.C +API BOOL, RESETDC, TEXT +P_HDC hdc +P_CLPDEVMODE0 lpInitData ; ** points to DEVMODE struct. + +; in OBJDEL.ASM +API BOOL, DeleteObject, TEXT, <ASM> +P_HGDIOBJ hObject ; ** Validated by VALID? (3.0 and 3.1) + ; object shouldn't be selected into a DC + ; Pens, brushes, fonts, bitmaps & + ; palettes and regions. +; in OBJMAN.ASM +API HPEN, CreatePen, TEXT, <ASM> +P_VALUE style, PS_MAX ; ** range 0-6 +P_int cx +P_COLORREF color ; ** DWORD + +; in OBJMAN.ASM +API HPEN, CreatePenIndirect, TEXT, <ASM> +P_CLPLOGPEN lpLogPen ; ** + +; in OBJMAN.ASM +API HBRUSH, CreateSolidBrush, TEXT, <ASM, NOGEN> +P_COLORREF color + +; in OBJMAN.ASM +API HBRUSH, CreateHatchBrush, TEXT, <ASM> +P_VALUE nIndex, HS_MAX ; ** range 0-5 +P_COLORREF color ; + +; in OBJMAN.ASM +API HBRUSH, CreatePatternBrush, TEXT, <ASM> +P_HBITMAP hBitmap ; + +; in OBJMAN.ASM +API HBRUSH, CreateBrushIndirect, TEXT, <ASM> +P_CLPLOGBRUSH lpLogBrush ; ** + +; in OBJMAN.ASM +API HBITMAP, CreateBitmap, TEXT, <ASM> ;<FUNNYFRAME> in 3.0 +P_CLPBITBUFFER0 cx, cy, bPlanes, bBitC, lpBits ; ** buffer size + ;determined by bitmap attributes + ;cx and cy are int. values + ;bPlanes and bBitC are BYTE values + +; in OBJMAN.ASM +API HBITMAP, CreateBitmapIndirect, TEXT, <ASM> ;<FUNNYFRAME> in 3.0 +P_CLPBITMAP lpBitmap ; ** + +; in OBJMAN.ASM +API HBITMAP, CreateCompatibleBitmap, TEXT, <ASM, FUNNYFRAME,NODATA> ;nogen +P_HDC hdc ; validated by VALID? (3.0 and 3.1) in CompatibleBitmap +P_int cx +P_int cy + +; in OBJMAN.ASM +API HBITMAP, CreateDiscardableBitmap, TEXT, <ASM,FUNNYFRAME,NODATA> ;nogen +P_HDC hdc ; validated by VALID? (3.0 and 3.1) in CompatibleBitmap +P_int cx +P_int cy + +; in OBJMAN.ASM +API HFONT, CreateFont, TEXT, <ASM> +P_int cy +P_int cx +P_int nEscapement +P_int nOrientation +P_VALUE nWeight, FW_MAX ;** range 0-1000 +P_BYTE cItalic +P_BYTE cUnderline +P_BYTE cStrikeOut +P_BYTE cCharSet +P_BVALUE cOutPrecis, OUT_MAX ;** range 0-3 +P_BVALUE cClipPrecis, CLIP_MAX ;** range 0-2 +P_BVALUE cQuality, QUALITY_MAX ;** range 0-2 +P_PITCHFAMILY cPitchAndFamily ;** BYTE. Flags in upper and lower nibbles +P_CLPFACENAME0 lpFaceName ;** null-terminated string length + ;not > LF_FACESIZE + +; in OBJMAN.ASM +API HFONT, CreateFontIndirect, TEXT, <ASM> +P_CLPLOGFONT lpLogFont ;** + +; in OBJMAN.ASM +API HBRUSH, CreateDIBPatternBrush, TEXT, <ASM> +P_GHPACKEDDIB hPackedDIB, wUsage + +; in OBJMAN.ASM +API DWORD, SetBitmapDimension, TEXT, <ASM> +P_HBITMAP hBitmap ; validated by VALID? (3.0 and 3.1) +P_int x +P_int y + +; in WIN32.C +API BOOL, SetBitmapDimensionEx, TEXT +P_HBITMAP hBitmap +P_int x +P_int y +P_LPSIZE0 lpSize + +; in OBJMAN.ASM +API DWORD, GetBitmapDimension, TEXT, <ASM> +P_HBITMAP hBitmap ;validated by VALID? (3.0 and 3.1) + +; in WIN32.C +API BOOL, GetBitmapDimensionEx, TEXT +P_HBITMAP hBitmap +P_LPSIZE lpDimension + +; in OBJMAN.ASM +API int, SetTextJustification, TEXT, <ASM> +P_HDCMETA hdc ;validated by VALID? (3.0 and 3.1) +P_int nBreakExtra +P_int nBreakCount + +; in OBJMAN.ASM +API int, SetTextCharacterExtra, TEXT, <ASM> +P_HDCMETA hdc ;validated by VALID? (3.0 and 3.1) +P_int nCharExtra + +; in METAREC.C +API GHANDLE, CopyMetaFile, TEXT +P_GHANDLE hMeta ;checked by IsValidMetaFile() +P_CLPSTR0 lpFileName ;0 => use memory metafile + +; in METAREC.C +API HDC, CreateMetaFile, TEXT +P_CLPSTR0 lpFileName ;0 => return memory metafile DC + +; in METAREC.C +API GHANDLE, CloseMetaFile, TEXT +P_HDCMETA hdc + + +; in METAPLAY.ASM +API BOOL, DeleteMetaFile, TEXT, <ASM,FUNNYFRAME> ; is NODATA +P_HMETAFILE hMF + +; in METAPLAY.ASM +API BOOL, PlayMetaFile, TEXT, <ASM, ATMFRAMEDS> +P_HDCMETA hdc ;validated by Valid() (3.1 only) +P_HMETAFILE hMF + +; in METAPLAY.ASM +API GHANDLE, GetMetaFile, TEXT, <ASM> +P_CLPSTR lpFileName + + +; in META.C +API void, PlayMetaFileRecord, TEXT +P_HDCMETA hdc ;validated by Valid() (3.1 only) +P_LPHANDLETABLE0 lpHT +P_CLPMETARECORD lpMR +P_WORD nhandles + +; in META.C +API BOOL, EnumMetaFile, TEXT +P_HDCMETA0 hdc ; NULL DC is OK. Checked by Valid() (3.0 and 3.1) +P_HMETAFILE hMF +P_LPFNMENUM lpfnEnum ; ** +P_DWORD lpClientData ; CLPVOID0 ?, but often just contains data + +; in METAREC.C +API GHANDLE, GetMetaFileBits, TEXT +P_HMETAFILE hMF + +; in METAREC.C +API HANDLE, SetMetaFileBits, TEXT +P_HMETAFILE hMem ; just returns hMem + +; in METAREC.C +API HANDLE, SetMetaFileBitsBetter, TEXT +P_HMETAFILE hMem ; just returns hMem, new for 3.1 + +; in XLATE.ASM +API BOOL, DPtoLP, TEXT, <ASM, FUNNYFRAME,NODATA> ;nogen +P_HDC hdc ;validated by VALID? (3.0 and 3.1) by DPXlate +P_LPPOINTBUFFER lpPoints, nCount ;** + +; in XLATE.ASM +API BOOL, LPtoDP, TEXT, <ASM, FUNNYFRAME,NODATA> ;nogen +P_HDC hdc ;validated by VALID? (3.0 and 3.1) in DPXlate +P_LPPOINTBUFFER lpPoints, nCount + +; in ARC.ASM +API HRGN, CreateEllipticRgnIndirect, TEXT, <ASM> +P_CLPRECT lpRect + +; in ARC.ASM +API HRGN, CreateEllipticRgn, TEXT, <ASM, NOGEN> +P_XY1XY2 x1,y1,x2,y2 ;X2-X1 and Y2-Y1 under 32,767 units + +; in ARC.ASM +API HRGN, CreatePolygonRgn, TEXT, <ASM> +P_CLPPOINTBUFFER lpPoints, nCount ;** +P_RVALUE nPolyFillMode, PFILL_MIN, PFILL_MAX ;** range 1-2 + +; in ARC.ASM +API HRGN, CreatePolyPolygonRgn, TEXT, <ASM> +P_POLYPOLYPOINTS lpPoints, lpPolyCounts, nCount ;**lpPolyCounts is a buffer + ;of nCount Integers. lpPoints + ;is a buffer of POINTS. Size of + ;lpPoints det. by sum of all + ;integers in lpPolyCounts +P_RVALUE nPolyFillMode, PFILL_MIN, PFILL_MAX ;** range 1-2 + +; in ARC.ASM +API HRGN, CreateRoundRectRgn, TEXT, <ASM, NOGEN> +P_XY1XY2 x1,y1,x2,y2 ;X2-X1 and Y2-Y1 under 32,767 units +P_int x3 +P_int y3 + +; in ARC.ASM +API BOOL, Ellipse, TEXT, <ASM> +P_HDCNOIC hdc ;validated by VALID? (3.0 and 3.1) +P_XY1XY2 x1,y1,x2,y2 + +; in ARC.ASM +API BOOL, Arc, TEXT, <ASM> +P_HDCNOIC hdc ; validated by VALID? (3.0 and 3.1) +P_XY1XY2 x1,y1,x2,y2 +P_int x3 +P_int y3 +P_int x4 +P_int y4 + +; in ARC.ASM +API BOOL, Pie, TEXT, <ASM> +P_HDCNOIC hdc ;validated by VALID? (3.0 and 3.1) +P_XY1XY2 x1,y1,x2,y2 +P_int x3 +P_int y3 +P_int x4 +P_int y4 + +; in ARC.ASM +API BOOL, Chord, TEXT, <ASM> +P_HDCNOIC hdc ; validated by VALID? (3.0 and 3.1) +P_XY1XY2 x1,y1,x2,y2 ; ** X2-X1 and Y2-Y1 under 32,767 units +P_int x3 +P_int y3 +P_int x4 +P_int y4 + +; in ARC.ASM +API BOOL, RoundRect, TEXT, <ASM> +P_HDCNOIC hdc ;validated by VALID? (3.0 and 3.1) +P_XY1XY2 x1,y1,x2,y2 +P_int x3 +P_int y3 + +; in RECT.C +API BOOL, Rectangle, TEXT, <RECT> +P_HDCNOIC hdc ;validated by Valid() (3.0 and 3.1) in RectangleBody +P_XY1XY2 x1,y1,x2,y2 + +; in FLOOD.ASM +API BOOL, FloodFill, TEXT, <ASM> ; calls ExtFloodFill +P_HDCNOIC hdc +P_int x +P_int y +P_COLORREF color + +; in FLOOD.ASM +API BOOL, ExtFloodFill, TEXT, <ASM> +P_HDCNOIC hdc ;validated by VALID? (3.0 and 3.1) +P_int x +P_int y +P_COLORREF color +P_UVALUE fillType, EFF_MAX ;** range 0-1 + +P_LPESCPARMS macro code, cb, lp, opts + _DefParm <code>,2,<opts> + _DefParm <cb>,2,<opts> + _DefParm <lp>,4,<opts> + if VLgen + _FlsFrame + mov ax,_P_&lp + mov cx,_P_&lp+2 + mov bx,_P_&cb + lcall CLP0 + _gensub LP + endif +endm + +; in ESC.ASM +API int, Escape, TEXT, <ASM, ATMFRAMEDS> +P_HDCNOTMEM hdc ; ** not mem. DC. VALID? (3.0 and 3.1) +P_LPESCPARMS code, cbInData, lpInData +P_LPVOID0 lpOutData +APIERR + mov ax,SP_ERROR ;General escape error +APIEND + +; in ENUMOBJE.ASM +API int, EnumObjects, TEXT, <ASM> +P_HDC hdc ; validated by VALID? (3.0 and 3.1) +P_RVALUE nObjectType, OBJ_MIN, OBJ_MAX ; ** range 1-2 +P_LPFNOENUM lpCallBack ; ** +P_DWORD lpClientData ; CLPVOID0 ?, but often just contains data + +; in ENUMFONT.ASM +API int, EnumFonts, TEXT, <ASM,ATMFRAMEDS> +P_HDC hdc ; validated by VALID? (3.0 and 3.1) in RectStuff +P_CLPFACENAME0 lpFaceName +P_LPFNFENUM lpFontFunc ; ** +P_DWORD lpData ; CLPVOID0 ?, but often just contains data + +; in ENUMFONT.ASM (new for Win 3.1) +API int EnumFontFamilies, TEXT, <ASM> +P_HDC hdc ; validated by VALID? +P_CLPFACENAME0 lpFaceName +P_LPFNFENUM lpFontFunc ; +P_DWORD lpData ; CLPVOID0 ?, but often just contains data + +; in GETSTUFF.ASM +API DWORD, GetCurrentPosition, TEXT, <ASM,FUNNYFRAME,NODATA,DEBUGONLY> ;nogen +P_HDC hdc ;validated by VALID? (3.0 and 3.1) in GSV + +; in WIN32.C +API BOOL GetCurrentPositionEx, TEXT, <FUNNYFRAME, NODATA, DEBUGONLY> ;nogen +P_HDC hdc +P_LPPOINT lpPoint + +; in GETSTUFF.ASM +API DWORD, GetDCOrg, TEXT, <ASM,FUNNYFRAME,NODATA,DEBUGONLY> ;nogen +P_HDC hdc ;validated by VALID? (3.0 and 3.1) in GSV + +; in GETSTUFF.ASM +API DWORD, GetBrushOrg, TEXT, <ASM,FUNNYFRAME,NODATA,DEBUGONLY> ; nogen +P_HDC hdc ; validated by VALID? (3.0 and 3.1) in GSV + +; in WIN32.C +API BOOL, GetBrushOrgEx, TEXT, <FUNNYFRAME, NODATA, DEBUGONLY> ; nogen +P_HDC hdc +P_LPPOINT lpPoint + +; in GETSTUFF.ASM +API DWORD, GetBkColor, TEXT, <ASM, FUNNYFRAME,NODATA,DEBUGONLY> ; nogen +P_HDC hdc ;validated by VALID? (3.0 and 3.1) by GSV + +; in GETSTUFF.ASM +API int, GetBkMode, TEXT, <ASM,FUNNYFRAME,NODATA,DEBUGONLY> ;nogen +P_HDC hdc ;validated by VALID? (3.0 and 3.1) by GSV + +; in GETSTUFF.ASM +API DWORD, GetTextColor, TEXT, <ASM,FUNNYFRAME,NODATA,DEBUGONLY>;nogen +P_HDC hdc ;validated by VALID? (3.0 and 3.1) by GSV + +; in GETSTUFF.ASM +API WORD, GetTextAlign, TEXT, <ASM, FUNNYFRAME,DEBUGONLY> ;nogen +P_HDC hdc ;validated by VALID? (3.0 and 3.1) by GSV + +; in GETSTUFF.ASM +API int, GetROP2, TEXT, <ASM, FUNNYFRAME, NODATA, DEBUGONLY> +P_HDC hdc ;validated by VALID? (3.0 and 3.1) by GSV + +; in GETSTUFF.ASM +API int, GetStretchBltMode, TEXT, <ASM, FUNNYFRAME,NODATA,DEBUGONLY> ;nogen +P_HDC hdc ;validated by VALID? (3.0 and 3.1) by GSV + +; in GETSTUFF.ASM +API int, GetPolyFillMode, TEXT, <ASM, FUNNYFRAME,NODATA,DEBUGONLY> ;nogen +P_HDC hdc ;validated by VALID? (3.0 and 3.1) by GSV + +; in GETSTUFF.ASM +API int, GetMapMode, TEXT, <ASM, FUNNYFRAME,NODATA,DEBUGONLY> ;nogen +P_HDC hdc ;validated by VALID? (3.0 and 3.1) by GSV + +; in GETSTUFF.ASM +API DWORD, GetWindowOrg, TEXT, <ASM, FUNNYFRAME,NODATA,DEBUGONLY> ;nogen +P_HDC hdc ;validated by VALID? (3.0 and 3.1) by GSV + +;in WIN32.C +API BOOL, GetWindowOrgEx, TEXT, <FUNNYFRAME,NODATA,DEBUGONLY> ;nogen +P_HDC hdc +P_LPPOINT lpPoint + +; in GETSTUFF.ASM +API DWORD, GetWindowExt, TEXT, <ASM, FUNNYFRAME,NODATA,DEBUGONLY> ;nogen +P_HDC hdc ;validated by VALID? (3.0 and 3.1) by GSV + +; in WIN32.C +API BOOL, GetWindowExtEx, TEXT, <FUNNYFRAME,NODATA,DEBUGONLY> ;nogen +P_HDC hdc +P_LPSIZE lpSize + +; in GETSTUFF.ASM +API DWORD, GetViewportOrg, TEXT, <ASM, FUNNYFRAME,NODATA,DEBUGONLY> ;nogen +P_HDC hdc ;validated by VALID? (3.0 and 3.1) by GSV + +; in WIN32.C +API BOOL, GetViewportOrgEx, TEXT, <FUNNYFRAME,NODATA,DEBUGONLY> ;nogen +P_HDC hdc +P_LPPOINT lpPoint + +; in WIN32.C +API BOOL, GetViewportExtEx, TEXT, <FUNNYFRAME,NODATA,DEBUGONLY> ;nogen +P_HDC hdc +P_LPSIZE lpSize + +; in GETSTUFF.ASM +API DWORD, GetViewportExt, TEXT, <ASM, FUNNYFRAME,NODATA,DEBUGONLY> ;nogen +P_HDC hdc ;validated by VALID? (3.0 and 3.1) by GSV + +; in CHARWID.ASM +API BOOL, GetCharWidth, TEXT, <ASM, ATMFRAMEDS> +P_HDC hdc ;validated by VALID? (3.0 and 3.1) +P_LPRWBUFFER chFirst, chLast, lpBuffer, 2 ;** size dictated by + ;char. range. Each entry in + ;buffer is 2 bytes. Buffer + ;filled in DEBUG Win 3.1 only + ;lpBuffer is an int. buffer +; in SETPIXEL.ASM +API DWORD, GetPixel, TEXT, <ASM> +P_HDC hdc ;validated by VALID? (3.0 and 3.1) +P_int x +P_int y + +; in SETPIXEL.ASM +API DWORD, SetPixel, TEXT, <ASM> +P_HDCMETA hdc ; validated by VALID? (3.0 and 3.1) +P_int x +P_int y +P_COLORREF color +APIERR + mov ax, -1 + cwd +APIEND + +; in STOCK.ASM +API HANDLE, GetStockObject, TEXT, <ASM> +P_VALUE nIndex, STOCK_MAX ; ** range 0-16 + +; in GDIINQ1.ASM +API LONG, GetBitmapBits, TEXT, <ASM, FUNNYFRAME,NODATA> +P_HBITMAP hBitmap ;validated by VALID? (3.0 and 3.1) +P_LPBUFFERDW dwCount, lpBits ;** buffer size a DWORD + ;buffer filled in DEBUG Win 3.1 + +; in GDIINQ1.ASM +API int, GetDeviceCaps, TEXT, <ASM> +P_HDCMETA hdc ;validated by VALID? (3.0 and 3.1) +P_DEVCAP nIndex ;** valid int. indices even-numbered + ;ranges 0-44, 88-90, 104-108. + +; in GDIINQ1.ASM +API LONG, SetBitmapBits, TEXT, <ASM, FUNNYFRAME,NODATA> ;nogen +P_HBITMAP hBitmap ; validated by VALID? (3.0 and 3.1) in BitmapBits +P_CLPBUFFERDW dwCount, lpBits ;** buffer size a DWORD + ;buffer filled in DEBUG Win 3.1 + +; in GDIINQ2.ASM +API int, GetObject, TEXT, <ASM> +P_HGDIOBJGET hObject ;** Validated by VALID? (3.0 and 3.1) + ; pens, brushes, fonts, bitmaps & + ; palettes. +P_LPBUFFERX nCount, lpObject ;** nCount occurs before lpBits + ;buffer filled in DEBUG Win 3.1 + +; in FASPECT.ASM +API DWORD, GetAspectRatioFilter, TEXT, <ASM> +P_HDC hdc ;validated by VALID? (3.0 and 3.1) + +; in WIN32.C +API BOOL, GetAspectRatioFilterEx, TEXT +P_HDC hdc +P_LPSIZE lpSize + +; in FASPECT.ASM +API DWORD, SetMapperFlags, TEXT, <ASM> +P_HDCMETA hdc ; validated by VALID? (3.0 and 3.1) in WordSet +P_DFLAGS dwFlag, MAPFLG_VALID_L, MAPFLG_VALID_H ; ** only bit #1 is recognized + +; in XFORMMAN.ASM +API DWORD, GetNearestColor, TEXT, <ASM> +P_HDC hdc ; validated by VALID? (3.0 and 3.1) +P_COLORREF color + +; in XFORMMAN.ASM +API DWORD, OffsetViewportOrg, TEXT, <ASM, FUNNYFRAME,NODATA> ;nogen +P_HDCMETA hdc ;validated by VALID? (3.0 and 3.1) in OffsetOrg +P_int x +P_int y + +; in WIN32.C +API BOOL, OffsetViewportOrgEx, TEXT, <FUNNYFRAME,NODATA> ;nogen +P_HDCMETA hdc +P_int x +P_int y +P_LPPOINT0 lpPoint + +; in XFORMMAN.ASM +API DWORD, OffsetWindowOrg, TEXT, <ASM, FUNNYFRAME,NODATA> ;nogen +P_HDCMETA hdc ;validated by VALID? (3.0 and 3.1) in OffsetOrg +P_int x +P_int y + +; in WIN32.C +API BOOL, OffsetWindowOrgEx, TEXT, <FUNNYFRAME,NODATA> ;nogen +P_HDCMETA hdc +P_int x +P_int y +P_LPPOINT0 lpPoint + +; in XFORMMAN.ASM +API int, SetMapMode, TEXT, <ASM> +P_HDCMETA hdc ;validated by VALID? (3.0 and 3.1) +P_RVALUE nMapMode, MM_MIN, MM_MAX ;** range 1-8 + +; in XFORMMAN.ASM +API DWORD, SetWindowExt, TEXT, <ASM,FUNNYFRAME,NODATA> ;nogen +P_HDCMETA hdc ;validated by VALID? (3.0 and 3.1) in SetWinViewExt +P_int x +P_int y + +; in WIN32.C +API BOOL SetWindowExtEx, TEXT, <FUNNYFRAME,NODATA> ;nogen +P_HDCMETA hdc +P_int x +P_int y +P_LPSIZE0 lpSize + +; in XFORMMAN.ASM +API DWORD, SetViewportExt, TEXT, <ASM,FUNNYFRAME,NODATA> ;nogen +P_HDCMETA hdc ;validated by VALID? (3.0 and 3.1) in SetWinViewExt +P_int x +P_int y + +; in WIN32.C +API BOOL, SetViewportExtEx, TEXT, <FUNNYFRAME,NODATA> ;nogen +P_HDCMETA hdc +P_int x +P_int y +P_LPSIZE0 lpSize + +; in XFORMMAN.ASM +API DWORD, ScaleViewportExt, TEXT, <ASM,FUNNYFRAME,NODATA> ;nogen +P_HDCMETA hdc ;validated by VALID? (3.0 and 3.1) in ScaleExt +P_int xNum +P_intN0 XDenom ;calls MulDiv +P_int yNum +P_intN0 YDenom ;calls MulDiv + +; in WIN32.C +API BOOL, ScaleViewportExtEx, TEXT, <FUNNYFRAME,NODATA> ;nogen +P_HDCMETA hdc ;validated by VALID? (3.0 and 3.1) in ScaleExt +P_int xNum +P_intN0 XDenom ;calls MulDiv +P_int yNum +P_intN0 YDenom ;calls MulDiv +P_LPSIZE0 lpSize + +; in XFORMMAN.ASM +API DWORD, ScaleWindowExt, TEXT, <ASM,FUNNYFRAME,NODATA> ;nogen +P_HDCMETA hdc ;validated by VALID? (3.0 and 3.1) in ScaleExt +P_int xNum +P_intN0 XDenom ;calls MulDiv +P_int yNum +P_intN0 YDenom ;calls MulDiv + +; in WIN32.C +API BOOL, ScaleWindowExtEx, TEXT, <FUNNYFRAME,NODATA> ;nogen +P_HDCMETA hdc ;validated by VALID? (3.0 and 3.1) in ScaleExt +P_int xNum +P_intN0 XDenom ;calls MulDiv +P_int yNum +P_intN0 YDenom ;calls MulDiv +P_LPSIZE0 lpSize + +; in CLIPMAN.ASM +API int, GetRgnBox, TEXT, <ASM> +P_HRGN hrgn ;validated by VALID? (3.0 and 3.1) +P_LPRECT lpRect ;buffer filled in DEBUG Win 3.1 + +; in GETTEXTE.ASM +API DWORD, GetTextExtent, TEXT, <ASM, ATMFRAMEDS> +P_HDC hdc ;validated by VALID? (3.0 and 3.1) +P_CLPBUFFER lpString, nCount + +; win WIN32.C +API BOOL, GetTextExtentPoint, TEXT +P_HDC hdc +P_CLPSTR lpString +P_int nCount +P_LPSIZE lpSize + +; in TEXTATTS.ASM +API int, GetTextCharacterExtra, TEXT, <ASM> +P_HDC hdc ;validated by VALID? (3.0 and 3.1) + +; in GETTEXTF.ASM +API int, GetTextFace, TEXT, <ASM> +P_HDC hdc ;validated by VALID? (3.0 and 3.1) +P_LPBUFFERX lpFaceName, nBytes ;nBytes occurs before lpFaceName + ;buffer filled in DEBUG Win 3.1 +APIERR +E_SETEMPTY lpFaceName, nBytes +APIEND + +; in GETTEXTM.ASM +API BOOL, GetTextMetrics, TEXT, <ASM> +P_HDC hdc ;validated by VALID? (3.0 and 3.1) +P_LPTEXTMETRIC lptm ;**buffer filled in DEBUG Win 3.1 + +; in ENVIRON.ASM +API int, GetEnvironment, TEXT, <ASM> +P_CLPSTR lpPortName ; ** converted to atom after + ; stripping off colons +P_LPBUFFER0 lpEnviron, nBytes ; NULL => return env. block size + ; buffer filled in DEBUG Win 3.1 +APIERR +E_SETEMPTY lpEnviron, nBytes +APIEND + + +; in ENVIRON.ASM +API int, SetEnvironment, TEXT, <ASM> +P_CLPSTR lpPortName ; converted to atom after stripping off ":"s +P_CLPBUFFER lpEnviron, wCount ; buffer filled in DEBUG Win 3.1 + +; in ADDFONTR.ASM +API int, AddFontResource, TEXT, <ASM> +P_CLPSTRHRSRC lpFileName ; ** null-terminated filename or handle to + ; loaded resource handle in LOWORD + +; in DELFONT.ASM +API BOOL, RemoveFontResource, TEXT, <ASM> +P_CLPSTRHRSRC lpFileName ; ** null-terminated filename or handle to + ; loaded resource handle in LOWORD + +; in FONTENG2.ASM (new for Win 3.1) +API BOOL, CreateScalableFontResource, TEXT, <ASM> +F_VALUE fEmbed, 1 +P_CLPSTR lpResFileName +P_CLPSTR lpFntFileName +P_CLPSTR0 lpCurrentPath + +STRUCT <MAT2> +F_WORD fract1 +F_int value1 +F_WORD fract2 +F_int value2 +F_WORD fract2 +F_int value4 +F_WORD fract4 +F_int value4 +ENDSTRUCT + +_GenLP <P_LPMAT2>,<LP>,%VLcbsMAT2 + +; in FONTENG2.ASM (new for Win 3.1) +API DWORD, GetGlyphOutline, TEXT, <ASM> +P_HDC hdc ; validated by VALID? +P_WORD cch +P_FLAGS wFlags, GLYPH_VALID ; ** 0,1,2 +P_LPGLYPHMETRICS lpMetrics +P_LPGGO0 cbBuffer, lpPoints +P_LPMAT2 lpXForm +APIERR + mov ax,-1 + cwd +APIEND + + +; in FONTENG2.ASM (new for Win 3.1) +API DWORD, GetFontData, TEXT, <ASM> +P_HDC hdc ; validated by VALID? +P_DWORD dwTable +P_DWORD dwOffset +P_LPFDATA0 lpBuffer, cbBuffer +APIERR + mov ax,-1 + cwd +APIEND + +; in FONTENG2.ASM (new for Win 3.1) +API BOOL, GetCharABCWidths, TEXT, <ASM> +P_HDC hdc ; validated by VALID? +P_LPRWBUFFER chFirst, chLast, lpBuffer, 6 ;size dictated by + ;char. range. Buffer filled + ;in DEBUG Win 3.1 only + ;Each entry in lpBuffer is + ;of 6 bytes. + +; in FONTENG2.ASM (new for Win 3.1) +API BOOL GetOutlineTextMetrics, TEXT, <ASM> +P_HDC hdc ;validated by VALID? +P_LPETM0 cb, lpBuffer ;** NULL ptr. is valid + ;Buffer filled in DEBUG Win 3.1 + +STRUCT <KERNINGPAIR> +F_WORD wFirst +F_WORD wSecond +F_int iKernAmount +ENDSTRUCT + +P_LPKERNINGPAIRS0 macro ckp, lpkp + _DefParm <ckp>,2,<opts> + _DefParm <lpkp>,4,<opts> + if VLgen + _FlsFrame + mov ax,VLcbsKERNINGPAIR ; bx = ckp * sizeof(KERNINGPAIR) + mul word ptr _P_&ckp + xchg ax,bx + mov ax,_P_&lpkp ; cx:ax = lpkp + mov cx,_P_&lpkp+2 + lcall LP0 + endif +endm + + +API int GetKerningPairs, TEXT +P_HDC hdc +P_LPKERNINGPAIRS0 ckp, lpkp + +; in OUTMAN.ASM +API BOOL, LineTo, TEXT, <ASM> +P_HDCNOIC hdc ;validated by VALID? (3.0 and 3.1) +P_int x +P_int y + +; in OUTMAN.ASM +API DWORD, MoveTo, TEXT, <ASM> +P_HDCMETA hdc ;validated by VALID? (3.0 and 3.1) in DPXlate +P_int x +P_int y + +; in WIN32.C +API BOOL, MoveToEx, TEXT +P_HDCMETA hdc +P_int x +P_int y +P_LPPOINT0 lpPoint + +; in OUTMAN.ASM +API BOOL, Polyline, TEXT, <ASM> +P_HDCNOIC hdc ;validated by VALID? (3.0 and 3.1) +P_CLPPOINTBUFFER lpPoints, nCount + +; in LINEDDA.ASM +API void, LineDDA, TEXT, <ASM, FUNNYFRAME> +P_XY1XY2 x1,y1,x2,y2 ; overflow problem here too? +P_LPFNLENUM lpFontFunc ; ** +P_DWORD lpData ; CLPVOID0 ?, but often just contains data + +; in MULDIV.ASM +API int, MulDiv, TEXT, <ASM, NOGEN> +P_int a +P_int b +P_intN0 c ;** MulDiv checks for overflow + +; in POLYGON.ASM +API BOOL, Polygon, TEXT, <ASM> +P_HDCNOIC hdc ;validated by VALID? (3.0 and 3.1) +P_CLPPOINTBUFFER lpPoints, nCount + +; in POLYGON.ASM +API BOOL, PolyPolygon, TEXT, <ASM> +P_HDCNOIC hdc ;validated by VALID? (3.0 and 3.1) +P_POLYPOLYPOINTS lpPoints, lpPolyCounts, nCount ;lpPolyCounts is a buffer + ;of nCount Integers. lpPoints + ;is a buffer of POINTS. Size of + ;lpPoints det. by sum of all + ;integers in lpPolyCounts + +ifdef WOW +API BOOL, PolyPolylineWOW, TEXT, <ASM> +P_HDCNOIC hdc ;validated by VALID? (3.0 and 3.1) +P_POLYPOLYLARGEPOINTS lpPoints, lpPolyCounts, nCount +endif + +; in PATBL.ASM +API BOOL, StretchBlt, TEXT, <ASM> +P_HDCNOIC hdcDst ; validated by VALID? (3.0 and 3.1) +P_int xDst +P_int yDst +P_int cxDst +P_int cyDst +P_HDC hdcSrc ; validated by VALID? (3.0 and 3.1) +P_int xSrc +P_int ySrc +P_int cxSrc +P_int cySrc +P_ROP rop + +; in PATBL.ASM +API BOOL, BitBlt, TEXT, <ASM> +P_HDCNOIC hdcDst ; validated by VALID? (3.0 and 3.1) +P_int xDst +P_int yDst +P_int cxDst +P_int cyDst +P_HDC0 hdcSrc ; ** hSrcDC Used only if higher 2 bits of each +P_int cxSrc ; nibble of HIWORD(rop) != lower 2 bis of +P_int cySrc ; same nibble. Validated by VALID? (3.1 only) +P_ROP rop ; XSrc and YSrc are int. values. + +; in PATBL.ASM +API BOOL, PatBlt, TEXT, <ASM> +P_HDCNOIC hdc ;validated by VALID? (3.0 and 3.1) +P_int x +P_int y +P_int cx +P_int cy +P_ROP rop ; ** Only HIWORD used. LOWORD carried + ; around for 1.x driver compatiblity + +; in GETPOBJ.ASM +API DWORD, SetBrushOrg, TEXT, <ASM> +P_HDC hdc ; validated by VALID? (3.0 and 3.1) +P_int x +P_int y + +; in GETPOBJ.ASM +API BOOL, UnrealizeObject, TEXT, <ASM> +P_HGDIOBJUNR hObject ;** brush or palette + ;cannot be selected into any DC + +; in CLIPMAN.ASM +API int, ExcludeClipRect, TEXT, <ASM, FUNNYFRAME,NODATA> +P_HDCMETA hdc ;validated by VALID? (3.0 and 3.1) in RectStuff +P_XY1XY2 x1,y1,x2,y2 + +; in CLIPMAN.ASM +API int, GetClipBox, TEXT, <ASM> +P_HDC hdc ;validated by VALID? (3.0 and 3.1) +P_LPRECT lpRect ;buffer filled in DEBUG Win 3.1 + +; in CLIPMAN.ASM +API int, IntersectClipRect, TEXT, <ASM, FUNNYFRAME,NODATA> ; nogen +P_HDCMETA hdc ;validated by VALID? (3.0 and 3.1) in RectStuff +P_XY1XY2 x1,y1,x2,y2 + +; in CLIPMAN.ASM +API int, SelectClipRgn, TEXT, <ASM> +P_HDCMETA hdc ; validated by VALID? (3.0 and 3.1) +P_HRGN0 hrgn ; validated by VALID? (3.0), VALIDDEBUG? (3.1) + +; in RG.ASM +API HRGN, CreateRectRgnIndirect, TEXT, <ASM> +P_CLPRECT lpRect + +; in RG.ASM +API BOOL, EqualRgn, TEXT, <ASM> +P_HRGN hrgn1 ;validated by VALID? (3.0 and 3.1) in RectStuff +P_HRGN hrgn2 ;validated by VALID? (3.0 and 3.1) in RectStuff + +; in RG.ASM +API BOOL, RectInRegion, TEXT, <ASM, FUNNYFRAME> ;nogen +P_HRGN hrgn ;validated by VALID? (3.0), ValidDebug? (3.1) StuffInRegion +P_CLPRECT lpRect + +; in RG.ASM +API BOOL, RectVisible, TEXT, <ASM, FUNNYFRAME> ; nogen +P_HDC hdc ;validated by VALID? (3.0), ValidDebug? (3.1) StuffVisible +P_CLPRECT lpRect + +; in RG.ASM +API int, OffsetRgn, TEXT, <ASM> +P_HRGN hrgn ;validated by VALID? (3.0 and 3.1) +P_int x +P_int y + +; in RG.ASM +API int, OffsetClipRgn, TEXT, <ASM> +P_HDCMETA hdc ;validated by VALID? (3.0 and 3.1) +P_int x +P_int y + +; in REGION.ASM +API HRGN, CreateRectRgn, TEXT, <ASM, NOGEN> +P_XY1XY2 x1,y1,x2,y2 ; X2-X1 and Y2-Y1 under 32,767 units + +; in REGION.ASM +API int, CombineRgn, TEXT, <ASM> +P_HRGN hrgnDst ;validated by VALID? (3.0 and 3.1) +P_HRGN hrgnSrc1 ;validated by VALID? (3.0 and 3.1) +P_HRGN0 hrgnSrc2 ;validated by VALID? (3.0 and 3.1) + ; Can be NULL if code is RGN_COPY +P_RVALUE code, RGN_MIN, RGN_MAX ;** range 1-5 + +; in REGION.ASM +API void, SetRectRgn, TEXT, <ASM> +P_HRGN hrgn ; validated by VALID? (3.0 and 3.1) +P_XY1XY2 x1,y1,x2,y2 + +; in RGOUT.C +API BOOL, FillRgn, TEXT +P_HDCNOIC hdc ; Checked by Valid() +P_HRGN hrgn ; Checked by Valid() +P_HBRUSH hBrush ; Checked by Valid() + +; in RG.ASM +API BOOL, PtInRegion, TEXT, <ASM> +P_HRGN hrgn ;checked by Valid() (3.0 and 3.1) +P_int x +P_int y + +; in RGOUT.C +API BOOL, PaintRgn, TEXT +P_HDCNOIC hdc ;checked by Valid() (3.0 and 3.1) +P_HRGN hrgn ;checked by Valid() (3.0 and 3.1) + +; in RG.ASM +API BOOL, PtVisible, TEXT, <ASM> +P_HDC hdc ;validated by Valid() (3.0 and 3.1) +P_int x +P_int y + +; in RGOUT.C +API BOOL, FrameRgn, TEXT +P_HDCNOIC hdc ; Checked by Valid() +P_HRGN hrgn ; Checked by Valid() +P_HBRUSH hBrush ; Checked by Valid() +P_int cx +P_int cy + +; in RGOUTZ.ASM +API BOOL, InvertRgn, TEXT, <ASM> +P_HDCNOIC hdc ;validated by VALID? (3.0 and 3.1) +P_HRGN hrgn ;validated by VALID? (3.0 and 3.1) + +; in OBJSEL.ASM +API HANDLE, SelectObject, TEXT, <ASM, ATMFRAMEDS> +P_HDCMETA hdc ; validated by VALID? (3.0 and 3.1) +P_HGDIOBJSEL hObj ; ** validated by VALID? (3.0 and 3.1) + ; only pens, brushes, fonts, bitmaps & + ; regions (no palettes) + +; in COLOR.ASM +API DWORD, SetTextColor, TEXT, <ASM> +P_HDCMETA hdc ; validated by VALID? (3.0 and 3.1) +P_COLORREF color + +; in COLOR.ASM +API DWORD, SetBkColor, TEXT, <ASM> +P_HDCMETA hdc ; validated by VALID? (3.0 and 3.1) +P_COLORREF color +APIERR + mov dh,80h ;; return 0x8000:0x0000 +APIEND + +; in NEWXFORM.ASM +API int, SetBkMode, TEXT, <ASM,FUNNYFRAME,NODATA> ;nogen +P_HDCMETA hdc ; validated by VALID? (3.0 and 3.1) in WordSet +P_RVALUE nBkMode, BK_MIN, BK_MAX ; range 1-2 + +; in NEWXFORM.ASM +API WORD, SetTextAlign, TEXT, <ASM,FUNNYFRAME> ;nogen +P_HDCMETA hdc ; validated by VALID? (3.0 and 3.1) in WordSet +P_FLAGS wFlags, TA_VALID ; ** + +; in NEWXFORM.ASM +API int, SetROP2, TEXT, <ASM, FUNNYFRAME,NODATA> ;nogen +P_HDCMETA hdc ; validated by VALID? (3.0 and 3.1) in WordSet +P_RVALUE nDrawMode, R2_MIN,R2_MAX ; ** range 1-16 + +; in NEWXFORM.ASM +API int, SetStretchBltMode, TEXT, <ASM, FUNNYFRAME,NODATA> ;nogen +P_HDCMETA hdc ;validated by VALID? (3.0 and 3.1) in WordSet +P_RVALUE nStrMode, STR_MIN, STR_MAX ;** range 1-3 + +; in NEWXFORM.ASM +API int, SetPolyFillMode, TEXT, <ASM,FUNNYFRAME,NODATA> ;nogen +P_HDCMETA hdc ;validated by VALID? (3.0 and 3.1) in WordSet +P_RVALUE nPolyFillMode,PFILL_MIN, PFILL_MAX ; ** range 1-2 + +; in NEWXFORM.ASM +API DWORD, SetWindowOrg, TEXT, <ASM> +P_HDCMETA hdc ;validated by VALID? (3.0 and 3.1) +P_int x +P_int y + +; in WIN32.C +API BOOL, SetWindowOrgEx, TEXT +P_HDCMETA hdc +P_int x +P_int y +P_LPPOINT0 lpPoint + +; in NEWXFORM.ASM +API DWORD, SetViewportOrg, TEXT, <ASM> +P_HDCMETA hdc ;validated by VALID? (3.0 and 3.1) +P_int x +P_int y + +; in WIN32.C +API BOOL, SetViewportOrgEx, TEXT +P_HDCMETA hdc +P_int x +P_int y +P_LPPOINT0 lpPoint + +;----------------------------------------------------------------------------; +; D I B V A L I D A T I O N R O U T I N E S ; +;----------------------------------------------------------------------------; +; NOTES: ; +; ; +; (1). The size of a color table entry is sizeof RGB_TRIPLE for a core DIB ; +; header and RGB_QUAD for a info DIB header. However, if wUsage ; +; indicates a npalette usage, the size per entry is 2 bytes. ; +; ; +; (2). The lpInfoHeader paramater in CreateDIBitmap may not have a color ; +; table in the header. ; +; ; +; (3). For SetDIBits/GetDIBits and SetDIBitsToDevice, a 'numScans' parameter ; +; specifies the size of the DIBits. The buffer may not contain the ; +; complete DIB. ; +; ; +; However, in the case of StretchDIBits, the entire DIB buffer should ; +; be present and the height of the DIB should be picked up from the ; +; associated header. Likewise, if an initializer DIB is provided in the ; +; CreateDIBitmap call, it has to have a complete DIB buffer. ; +; ; +; (4). SetDIBitsToDevice specifies a rectangle in the DIB. This is the only ; +; part of the DIB that will be accessed. The validation code should ; +; figure out the amount of the DIB buffer that will need to ve accessed ; +; and validate that the buffer is big enough for it. ; +; ; +; (5). If the DIB is RLE compressed and the biSizeImage field is non zero, ; +; we will use that size to validate the length of the DIB buffer. ; +; ; +; (6). The validation code will not validate the bits per pixel and the ; +; biCompression fields. This is to allow expansion of these fields in ; +; the future. The validation code for these would instead be done in ; +; the DIB simulation code. ; +;----------------------------------------------------------------------------; + +; in DIBITM.ASM +API int, SetDIBits, TEXT, <ASM> +P_HDCNOIC hdc ;validated by VALID? (3.0 and 3.1) +P_HANDLE hBitmap ;validated by VALID? (3.1 only) + ;must not be selected into a DC +P_WORD nStartScan +P_CLPBITSINFOBUFFER nNumScans, lpBits, lpBitsInfo, wUsage + ;** lpBits size depends on number of + ;scans and info. in lpBitsInfo + ;lpBitsInfo points to BITMAPINFO + ;or BITMAPCOREINFO + +; in DIBITM.ASM +API HBITMAP, CreateDIBitmap, TEXT, <ASM> +P_HDCNOIC hdc ; validated by VALID? (3.0 and 3.1) +P_CLPBITMAPINFOHEADER lpInfoHeader ; ** ptr. to BITMAPINFOHEADER or BITMAPCOREHEADER +P_CLPDIBITMAP0 dwUsage, lpInitBits, lpInitInfo, wUsage + ; ** lpInitBits NULL if + ; dwUsage is not CBM_INIT + ; Size of lpInitBits depends + ; on fields in info. block + ; lpInitInfo points to BITMAPINFO + ; or BITMAPCOREINFO + +; in DIBITM.ASM +API int, SetDIBitsToDevice, TEXT, <ASM> +P_HDCNOIC hdc ;validated by VALID? (3.0 and 3.1) +P_WORD xDst +P_WORD yDst +P_WORD cxDst +P_CLPRECTBITSINFOBUFFER cyDst, xSrc, ySrc, nStartScan,nNumScans, lpBits, lpBitsInfo, wUsage + ;** lpBits size depends on number of + ;scans and info. in lpBitsInfo + ;lpBitsInfo points to BITMAPINFO + ;or BITMAPCOREINFO + +; in DIBITM.ASM +API int, GetDIBits, TEXT, <ASM> +P_HDC hdc ;validated by VALID? (3.0 and 3.1) +P_HANDLE hBitmap ;validated by VALID? (3.1 only) +P_WORD nStartScan +P_LPBITSINFOBUFFER0 nNumScans, lpBits, lpBitsInfo, wUsage + ;**lpBits + ;can be NULL. + ;buffer size depends on number of + ;scans and info. in lpBitsInfo + ;lpBitsInfo is a ptr. to + ;BITMAPINFO or BITMAPCOREINFO + +; in DIBSTRCH.ASM +API int, StretchDIBits, TEXT, <ASM> +P_HDCNOIC hdc ;validated by VALID? (3.0 and 3.1) +P_WORD xDst +P_WORD yDst +P_WORD cxDst +P_WORD cyDst +P_WORD xSrc +P_WORD ySrc +P_WORD cxSrc +P_WORD cySrc +P_CFULLLPBITSINFOBUFFER lpBits, lpBitsInfo, wUsage + ;** lpBits size depends on height + ;and info. in lpBitsInfo + ;lpBitsInfo points to BITMAPINFO + ;or BITMAPCOREINFO +P_ROP rop + +;----------------------------------------------------------------------------; +; in TEXTOUT.C +API BOOL, ExtTextOut, TEXT, <ATMFRAMEDS> +P_HDCNOIC hdc ; checked by Valid() +P_int x +P_int y +P_FLAGS flags, ETO_VALID ; ** (1,2,4) +P_CLPRECT0 lprc +P_CLPETOBUF lpString, nCount, lpDx ;lpDx is NULL or has nCount integers + + +; in TEXTOUT.C +API BOOL, TextOut, TEXT +P_HDCNOIC hdc +P_int X +P_int Y +P_CLPBUFFER lpString, nCount diff --git a/private/mvdm/wow16/gdi/gdi.asm b/private/mvdm/wow16/gdi/gdi.asm new file mode 100644 index 000000000..b0df151be --- /dev/null +++ b/private/mvdm/wow16/gdi/gdi.asm @@ -0,0 +1,551 @@ + TITLE GDI.ASM + PAGE ,132 +; +; WOW v1.0 +; +; Copyright (c) 1991, Microsoft Corporation +; +; GDI.ASM +; Thunks in 16-bit space to route Windows API calls to WOW32 +; +; History: +; 25-Jan-1991 Jeff Parsons (jeffpar) +; Created. +; + + ; Some applications require that USER have a heap. This means + ; we must always have: LIBINIT equ 1 + LIBINIT equ 1 + + .286p + + .xlist + include wow.inc + include wowgdi.inc + include cmacros.inc + include metacons.inc + .list + + __acrtused = 0 + public __acrtused ;satisfy external C ref. + +ifdef LIBINIT +externFP LocalInit +endif + +createSeg _TEXT,CODE,WORD,PUBLIC,CODE +createSeg _DATA,DATA,WORD,PUBLIC,DATA,DGROUP +defgrp DGROUP,DATA + +sBegin DATA +Reserved db 16 dup (0) ;reserved for Windows //!!!!! what is this + +GDI_Identifier db 'GDI16 Data Segment' + + Stocks dw 17 dup (0) ; Stock Object Handles +public FTRAPPING0 +FTRAPPING0 dw 0 +sEnd DATA + +; +; GP fault exception handler table definition +; + +createSeg _GPFIX0,GPFIX0,WORD,PUBLIC,CODE,IGROUP ; GP fault trapping + +sBegin GPFIX0 +__GP label word +public __GP +sEnd GPFIX0 + +sBegin CODE +assumes CS,CODE +assumes DS,DATA +assumes ES,NOTHING + +externFP GetStockObject +cProc GDI16,<PUBLIC,FAR,PASCAL,NODATA,ATOMIC> + + cBegin <nogen> + IFDEF LIBINIT + ; push params and call user initialisation code + + push di ;hModule + + ; if we have a local heap declared then initialize it + + jcxz no_heap + + push 0 ;segment + push 0 ;start + push cx ;length + call LocalInit + +no_heap: + ; + ; I didn't put a call to LibMain here, because I didn't think we + ; had anything to do. + ; + pop di + mov ax,1 + ELSE + mov ax,1 + ENDIF + + push ax + push di + push si + + xor si,si + xor di,di +my_loop: + push si + call GetStockObject + mov ds:[di + offset Stocks],ax + add di,2 + inc si + cmp si,16 ; Stock Objects have an index range of 0 through 16 + jna my_loop + + pop si + pop di + pop ax + ret + cEnd <nogen> + +assume DS:nothing + +cProc WEP,<PUBLIC,FAR,PASCAL,NODATA,NOWIN,ATOMIC> + parmW iExit ;DLL exit code + + cBegin + mov ax,1 ;always indicate success + cEnd + +assume DS:nothing + +;*--------------------------------------------------------------------------* +;* +;* CheckStockObject() +;* +;* Checks to see if the stock object is already fetched. +;* +;*--------------------------------------------------------------------------* + +cProc CheckStockObject, <PUBLIC, NEAR> +parmW nIndex +parmD lpReturn ; Callers Return Address +;parmW wBP ; Thunk saved BP +;parmW wDS ; Thunk saved DS +cBegin + mov bx,nIndex + cmp bx,16 + ja @f + push ds + mov ax,seg Stocks + mov ds,ax + shl bx,1 + mov ax,ds:[bx+offset Stocks] + pop ds + or ax,ax + jz @f + + pop bp + add sp,2 ; skip thunk IP + + ; mov sp,bp + ; pop bp + ; lea sp,-2[bp] + ; pop ds + ; pop bp + ; dec bp + retf 2 ; 2 bytes to pop +@@: + mov sp,bp ; Do cEnd without Ret count (leave parameters there) + pop bp + ret + +cEnd <nogen> + + +externFP GlobalHandle + +cProc IGetMetafileBits, <PUBLIC, FAR> +parmW hmf +cBegin + ; return (GlobalHandle(hMF) & 0xffff) ? hMF : FALSE; + + push hmf + call GlobalHandle + cmp ax, 0 + je @f + mov ax, hmf +@@: +cEnd + + +cProc ISetMetafileBits, <PUBLIC, FAR> +parmW hmf +cBegin + ; return (hBits) + mov ax, hmf +cEnd + +externFP GlobalReAlloc +cProc ISetMetafileBitsBetter, <PUBLIC, FAR> +parmW hmf +cBegin + ; return (GlobalReAlloc(hBits, 0L, GMEM_MODIFY | GMEM_SHAREALL)); + push hmf + push 0 + push 0 + push 2080h ;; GMEM_MODIFY or GMEM_SHAREALL + call GlobalReAlloc +cEnd + + + + GDIThunk CLOSEMETAFILE + GDIThunk COPYMETAFILE + GDIThunk CREATEMETAFILE + GDIThunk DELETEMETAFILE + GDIThunk GETMETAFILE + ; GDIThunk GETMETAFILEBITS + GDIThunk ENUMMETAFILE + DGDIThunk ISVALIDMETAFILE, 0 + GDIThunk PLAYMETAFILE + GDIThunk PLAYMETAFILERECORD + ; GDIThunk SETMETAFILEBITS + +FUN_WOWADDFONTRESOURCE EQU FUN_ADDFONTRESOURCE + DGDIThunk WOWADDFONTRESOURCE %(size ADDFONTRESOURCE16) + + GDIThunk ANIMATEPALETTE + GDIThunk ARC + GDIThunk BITBLT + DGDIThunk BRUTE + GDIThunk CHORD + DGDIThunk CLOSEJOB + GDIThunk COMBINERGN + GDIThunk COMPATIBLEBITMAP,6 + DGDIThunk COPY,10 + GDIThunk CREATEBITMAP + GDIThunk CREATEBITMAPINDIRECT + GDIThunk CREATEBRUSHINDIRECT + GDIThunk CREATECOMPATIBLEBITMAP + GDIThunk CREATECOMPATIBLEDC + GDIThunk CREATEDC + GDIThunk CREATEDIBITMAP +FUN_WOWCREATEDIBPATTERNBRUSH EQU FUN_CREATEDIBPATTERNBRUSH + DGDIThunk WOWCREATEDIBPATTERNBRUSH, %(size CREATEDIBPATTERNBRUSH16) + GDIThunk CREATEDISCARDABLEBITMAP + DGDIThunk CREATEELLIPTICRGN + GDIThunk CREATEELLIPTICRGNINDIRECT + GDIThunk CREATEFONT + GDIThunk CREATEFONTINDIRECT + GDIThunk CREATEHATCHBRUSH + GDIThunk CREATEIC + GDIThunk CREATEPALETTE + GDIThunk CREATEPATTERNBRUSH + GDIThunk CREATEPEN + GDIThunk CREATEPENINDIRECT + GDIThunk CREATEPOLYGONRGN + GDIThunk CREATEPOLYPOLYGONRGN +;;; DGDIThunk CREATEPQ,2 + GDIThunk CREATEREALBITMAP,14 + GDIThunk CREATEREALBITMAPINDIRECT,6 + DGDIThunk CREATERECTRGN + GDIThunk CREATERECTRGNINDIRECT + DGDIThunk CREATEROUNDRECTRGN + DGDIThunk CREATESOLIDBRUSH + DGDIThunk CREATEUSERBITMAP + DGDIThunk CREATEUSERDISCARDABLEBITMAP,6 + DGDIThunk DEATH,2 + GDIThunk DELETEABOVELINEFONTS + GDIThunk DELETEDC + DGDIThunk DELETEJOB,4 + GDIThunk DELETEOBJECT +;;; DGDIThunk DELETEPQ,2 + DGDIThunk DEVICECOLORMATCH,8 + GDIThunk DEVICEMODE + DGDIThunk DMBITBLT + DGDIThunk DMCOLORINFO,12 + DGDIThunk DMENUMDFONTS,16 + DGDIThunk DMENUMOBJ,14 + DGDIThunk DMOUTPUT,28 + DGDIThunk DMPIXEL,16 + DGDIThunk DMREALIZEOBJECT,18 + DGDIThunk DMSCANLR,14 + DGDIThunk DMSTRBLT,30 + DGDIThunk DMTRANSPOSE,10 + GDIThunk DPTOLP + GDIThunk DPXLATE,8 + GDIThunk ELLIPSE + DGDIThunk ENDSPOOLPAGE,2 + GDIThunk ENUMCALLBACK,14 + GDIThunk ENUMFONTS + GDIThunk ENUMOBJECTS + GDIThunk EQUALRGN + GDIThunk ESCAPE + GDIThunk EXCLUDECLIPRECT + DGDIThunk EXCLUDEVISRECT,10 + GDIThunk EXTDEVICEMODE + GDIThunk EXTFLOODFILL +;;; DGDIThunk EXTRACTPQ,2 + GDIThunk EXTTEXTOUT + DGDIThunk FASTWINDOWFRAME,14 + GDIThunk FILLRGN + DGDIThunk FINALGDIINIT,2 + GDIThunk FLOODFILL + GDIThunk FRAMERGN + DGDIThunk GDIINIT2,4 + DGDIThunk GDIMOVEBITMAP,2 + DGDIThunk GDIREALIZEPALETTE,2 + DGDIThunk GDISELECTPALETTE,6 + GDIThunk GETASPECTRATIOFILTER + GDIThunk GETBITMAPBITS + GDIThunk GETBITMAPDIMENSION + DGDIThunk GETBKCOLOR + DGDIThunk GETBKMODE + DGDIThunk GETBRUSHORG + GDIThunk GETCHARWIDTH + GDIThunk GETCLIPBOX + DGDIThunk GETCLIPRGN + DGDIThunk GETCURLOGFONT,2 + GDIThunk GETCURRENTOBJECT + DGDIThunk GETCURRENTPOSITION + DGDIThunk GETDCORG + DGDIThunk GETDCSTATE,2 + GDIThunk GETDEVICECAPS + GDIThunk GETDIBITS + GDIThunk GETENVIRONMENT + DGDIThunk GETMAPMODE + GDIThunk GETNEARESTCOLOR + GDIThunk GETNEARESTPALETTEINDEX + GDIThunk GETOBJECT + GDIThunk GETPALETTEENTRIES + DGDIThunk GETPHYSICALFONTHANDLE,2 + GDIThunk GETPIXEL + DGDIThunk GETPOLYFILLMODE + DGDIThunk GETRELABS + GDIThunk GETREGIONDATA + GDIThunk GETRGNBOX + DGDIThunk GETROP2 + DGDIThunk GETSPOOLJOB,6 + PGDIThunk GETSTOCKOBJECT,CheckStockObject + DGDIThunk GETSTRETCHBLTMODE + GDIThunk GETSYSTEMPALETTEENTRIES + GDIThunk GETSYSTEMPALETTEUSE + DGDIThunk GETTEXTALIGN + GDIThunk GETTEXTCHARACTEREXTRA + DGDIThunk GETTEXTCOLOR + GDIThunk GETTEXTEXTENT + GDIThunk GETTEXTFACE + GDIThunk GETTEXTMETRICS + DGDIThunk GETVIEWPORTEXT + DGDIThunk GETVIEWPORTORG + DGDIThunk GETWINDOWEXT + DGDIThunk GETWINDOWORG + GDIThunk GSV,2 + DGDIThunk INQUIREVISRGN +;;; DGDIThunk INSERTPQ,6 + GDIThunk INTERNALCREATEDC,16 + GDIThunk INTERSECTCLIPRECT + DGDIThunk INTERSECTVISRECT,10 + GDIThunk INVERTRGN + DGDIThunk ISDCCURRENTPALETTE,2 + DGDIThunk ISDCDIRTY,6 + GDIThunk LINEDDA + GDIThunk LINETO + GDIThunk LPTODP + GDIThunk LVBUNION,10 + GDIThunk MFDRAWTEXT,14 +;;; DGDIThunk MINPQ,2 + GDIThunk MOVETO +; DGDIThunk MULDIV ; thunk locally + GDIThunk OFFSETCLIPRGN + GDIThunk OFFSETORG,6 + GDIThunk OFFSETRGN + GDIThunk OFFSETVIEWPORTORG + DGDIThunk OFFSETVISRGN,6 + GDIThunk OFFSETWINDOWORG + DGDIThunk OPENJOB,10 + GDIThunk PAINTRGN + GDIThunk PATBLT + GDIThunk PIE + GDIThunk PIXTOLINE,16 + GDIThunk POLYGON + GDIThunk POLYLINE + GDIThunk POLYPOLYGON + GDIThunk POLYPOLYLINEWOW ; New for ACAD guys. + GDIThunk PTINREGION + GDIThunk PTVISIBLE + DGDIThunk QUERYJOB,4 + GDIThunk RCOS,4 + DGDIThunk REALIZEDEFAULTPALETTE,2 + GDIThunk RECTANGLE + GDIThunk RECTINREGION + GDIThunk RECTSTUFF,10 + GDIThunk RECTVISIBLE + +FUN_WOWREMOVEFONTRESOURCE EQU FUN_REMOVEFONTRESOURCE + DGDIThunk WOWREMOVEFONTRESOURCE %(size REMOVEFONTRESOURCE16) + + GDIThunk RESIZEPALETTE + GDIThunk RESTOREDC + DGDIThunk RESTOREVISRGN,2 + DGDIThunk RESURRECTION,14 + GDIThunk ROUNDRECT + GDIThunk RSIN,4 + GDIThunk SAVEDC + DGDIThunk SAVEVISRGN,2 + GDIThunk SCALEEXT,10 + GDIThunk SCALEVIEWPORTEXT + GDIThunk SCALEWINDOWEXT + DGDIThunk SCANLR,12 + GDIThunk SELECTCLIPRGN + GDIThunk SELECTOBJECT + DGDIThunk SELECTVISRGN,4 + GDIThunk SETBITMAPBITS + GDIThunk SETBITMAPDIMENSION + GDIThunk SETBKCOLOR + GDIThunk SETBKMODE + GDIThunk SETBRUSHORG + DGDIThunk SETDCORG,6 + DGDIThunk SETDCSTATE,4 + DGDIThunk SETDCSTATUS,8 + GDIThunk SETDIBITS + GDIThunk SETDIBITSTODEVICE + GDIThunk SETENVIRONMENT + GDIThunk SETMAPMODE + GDIThunk SETMAPPERFLAGS + GDIThunk SETPALETTEENTRIES + GDIThunk SETPIXEL + GDIThunk SETPOLYFILLMODE + GDIThunk SETRECTRGN + DGDIThunk SETRELABS + GDIThunk SETROP2 + GDIThunk SETSTRETCHBLTMODE + GDIThunk SETSYSTEMPALETTEUSE + GDIThunk SETTEXTALIGN + GDIThunk SETTEXTCHARACTEREXTRA + GDIThunk SETTEXTCOLOR + GDIThunk SETTEXTJUSTIFICATION + GDIThunk SETVIEWPORTEXT + GDIThunk SETVIEWPORTORG + GDIThunk SETWINDOWEXT + GDIThunk SETWINDOWORG + GDIThunk SETWINVIEWEXT,6 + DGDIThunk SHRINKGDIHEAP +;;; DGDIThunk SIZEPQ,4 + DGDIThunk STARTSPOOLPAGE,2 + GDIThunk STRETCHBLT + GDIThunk STRETCHDIBITS + GDIThunk STUFFINREGION,6 + GDIThunk STUFFVISIBLE,6 + GDIThunk TEXTOUT + GDIThunk UNREALIZEOBJECT + GDIThunk UPDATECOLORS + GDIThunk WORDSET,4 + DGDIThunk WRITEDIALOG,8 + DGDIThunk WRITESPOOL,8 + +; New Win 3.1 thunks + + DGDIThunk BITMAPBITS,10 ;Internal + + DGDIThunk SETDCHOOK,10 ;Internal + DGDIThunk GETDCHOOK,6 ;Internal + DGDIThunk SETHOOKFLAGS,4 ;Internal + DGDIThunk SETBOUNDSRECT + DGDIThunk GETBOUNDSRECT + DGDIThunk SELECTBITMAP,4 ;Internal + ; GDIThunk SETMETAFILEBITSBETTER ;New for 3.1 + + DGDIThunk DMEXTTEXTOUT,40 + DGDIThunk DMGETCHARWIDTH,24 + DGDIThunk DMSTRETCHBLT,40 + DGDIThunk DMDIBBITS,26 + DGDIThunk DMSTRETCHDIBITS,50 + DGDIThunk DMSETDIBTODEV,32 + + + DGDIThunk DELETESPOOLPAGE,2 ; new for 3.1 + DGDIThunk SPOOLFILE ; new for 3.1 + + DGDIThunk ENGINEENUMERATEFONT,12 ;Internal + DGDIThunk ENGINEDELETEFONT,4 ;Internal + DGDIThunk ENGINEREALIZEFONT,12 ;Internal + DGDIThunk ENGINEGETCHARWIDTH,12 ;Internal + DGDIThunk ENGINESETFONTCONTEXT,6 ;Internal + DGDIThunk ENGINEGETGLYPHBMP,22 ;Internal + DGDIThunk ENGINEMAKEFONTDIR,10 ;Internal + GDIThunk GETCHARABCWIDTHS + GDIThunk GETOUTLINETEXTMETRICS + GDIThunk GETGLYPHOUTLINE + GDIThunk CREATESCALABLEFONTRESOURCE + GDIThunk GETFONTDATA + DGDIThunk CONVERTOUTLINEFONTFILE,12 ;internal + DGDIThunk GETRASTERIZERCAPS + DGDIThunk ENGINEEXTTEXTOUT,42 ;internal + GDIThunk ENUMFONTFAMILIES + GDIThunk GETKERNINGPAIRS + + + GDIThunk RESETDC + GDIThunk STARTDOC + GDIThunk ENDDOC + GDIThunk STARTPAGE + GDIThunk ENDPAGE + GDIThunk SETABORTPROC + GDIThunk ABORTDOC + + + DGDIThunk GDISEEGDIDO,8 ;Internal + + DGDIThunk GDITASKTERMINATION,2 ;Internal + DGDIThunk SETOBJECTOWNER,4 ;Internal + DGDIThunk ISGDIOBJECT + DGDIThunk MAKEOBJECTPRIVATE,4 ;Internal + DGDIThunk FIXUPBOGUSPUBLISHERMETAFILE,6 ;Internal + DGDIThunk RECTVISIBLE_EHH,6 + DGDIThunk RECTINREGION_EHH,6 + DGDIThunk UNICODETOANSI,8 ;Internal + + + GDIThunk GETBITMAPDIMENSIONEX + DGDIThunk GETBRUSHORGEX + DGDIThunk GETCURRENTPOSITIONEX + GDIThunk GETTEXTEXTENTPOINT + DGDIThunk GETVIEWPORTEXTEX + DGDIThunk GETVIEWPORTORGEX + DGDIThunk GETWINDOWEXTEX + DGDIThunk GETWINDOWORGEX + GDIThunk OFFSETVIEWPORTORGEX + GDIThunk OFFSETWINDOWORGEX + GDIThunk SETBITMAPDIMENSIONEX + GDIThunk SETVIEWPORTEXTEX + GDIThunk SETVIEWPORTORGEX + GDIThunk SETWINDOWEXTEX + GDIThunk SETWINDOWORGEX + GDIThunk MOVETOEX + GDIThunk SCALEVIEWPORTEXTEX + GDIThunk SCALEWINDOWEXTEX + GDIThunk GETASPECTRATIOFILTEREX + + DGDITHUNK CREATEDIBSECTION ; new for chicago + DGDITHUNK GETDIBCOLORTABLE ; new for chicago + DGDITHUNK SETDIBCOLORTABLE ; new for chicago + +cProc QUERYABORT,<PUBLIC,FAR,PASCAL,NODATA,WIN> + parmw hdc + parmw res +cBegin + ; Not Supported + mov ax,1 +cEnd + +sEnd CODE + +end GDI16 +
\ No newline at end of file diff --git a/private/mvdm/wow16/gdi/gdi.def b/private/mvdm/wow16/gdi/gdi.def new file mode 100644 index 000000000..1b1f1456c --- /dev/null +++ b/private/mvdm/wow16/gdi/gdi.def @@ -0,0 +1,405 @@ +LIBRARY GDI +DESCRIPTION 'WOW REPLACEMENT GDI' +EXETYPE WINDOWS +STUB '..\BIN\WINSTUB.EXE' +CODE PRELOAD MOVEABLE DISCARDABLE +DATA PRELOAD MOVEABLE SINGLE +HEAPSIZE 2048 +EXPORTS + WEP ;Internal + + SETBKCOLOR @ 1 + SETBKMODE @ 2 NODATA + SETMAPMODE @ 3 + SETROP2 @ 4 NODATA + SETRELABS @ 5 NODATA ;Internal + SETPOLYFILLMODE @ 6 NODATA + SETSTRETCHBLTMODE @ 7 NODATA + SETTEXTCHARACTEREXTRA @ 8 + SETTEXTCOLOR @ 9 + SETTEXTJUSTIFICATION @10 + SETWINDOWORG @11 + SETWINDOWEXT @12 NODATA + SETVIEWPORTORG @13 + SETVIEWPORTEXT @14 NODATA + OFFSETWINDOWORG @15 NODATA + SCALEWINDOWEXT @16 NODATA + OFFSETVIEWPORTORG @17 NODATA + SCALEVIEWPORTEXT @18 NODATA + LINETO @19 + MOVETO @20 + EXCLUDECLIPRECT @21 NODATA + INTERSECTCLIPRECT @22 NODATA + ARC @23 + ELLIPSE @24 + FLOODFILL @25 + PIE @26 + RECTANGLE @27 + ROUNDRECT @28 + PATBLT @29 + SAVEDC @30 + SETPIXEL @31 + OFFSETCLIPRGN @32 + TEXTOUT @33 + BITBLT @34 + STRETCHBLT @35 + POLYGON @36 + POLYLINE @37 + ESCAPE @38 ; Patched by ATM + RESTOREDC @39 + FILLRGN @40 + FRAMERGN @41 + INVERTRGN @42 + PAINTRGN @43 + +; BLTREGION @40 + + + + SELECTCLIPRGN @44 + SELECTOBJECT @45 ; Patched by ATM +;;; BITMAPBITS @46 ;Internal +; +; GP fault exception handler table +; + __GP @46 RESIDENTNAME ;Internal + + COMBINERGN @47 + CREATEBITMAP @48 + CREATEBITMAPINDIRECT @49 + CREATEBRUSHINDIRECT @50 + CREATECOMPATIBLEBITMAP @51 NODATA + CREATECOMPATIBLEDC @52 + CREATEDC @53 NODATA ; Patched by ATM + CREATEELLIPTICRGN @54 + CREATEELLIPTICRGNINDIRECT @55 + CREATEFONT @56 + CREATEFONTINDIRECT @57 + CREATEHATCHBRUSH @58 + + CREATEPATTERNBRUSH @60 + CREATEPEN @61 + CREATEPENINDIRECT @62 + CREATEPOLYGONRGN @63 + CREATERECTRGN @64 + CREATERECTRGNINDIRECT @65 + CREATESOLIDBRUSH @66 + DPTOLP @67 NODATA + DELETEDC @68 ; Patched by ATM + DELETEOBJECT @69 + ENUMFONTS @70 ; Patched by ATM + ENUMOBJECTS @71 + EQUALRGN @72 + EXCLUDEVISRECT @73 NODATA ;Internal + GETBITMAPBITS @74 NODATA + GETBKCOLOR @75 + GETBKMODE @76 NODATA + GETCLIPBOX @77 + GETCURRENTPOSITION @78 NODATA + GETDCORG @79 NODATA + GETDEVICECAPS @80 + GETMAPMODE @81 NODATA + GETOBJECT @82 + GETPIXEL @83 + GETPOLYFILLMODE @84 NODATA + GETROP2 @85 NODATA + GETRELABS @86 NODATA ;Internal + GETSTOCKOBJECT @87 + GETSTRETCHBLTMODE @88 NODATA + GETTEXTCHARACTEREXTRA @89 + GETTEXTCOLOR @90 + GETTEXTEXTENT @91 ; Patched by ATM + GETTEXTFACE @92 + GETTEXTMETRICS @93 + GETVIEWPORTEXT @94 NODATA + GETVIEWPORTORG @95 NODATA + GETWINDOWEXT @96 NODATA + GETWINDOWORG @97 NODATA + INTERSECTVISRECT @98 NODATA ;Internal + LPTODP @99 NODATA + LINEDDA @100 + OFFSETRGN @101 + OFFSETVISRGN @102 ;Internal + PTVISIBLE @103 + RECTVISIBLE @104 + SELECTVISRGN @105 ;Internal + SETBITMAPBITS @106 NODATA + SETDCORG @117 ;Internal +;;;;INTERNALCREATEDC @118 ;Internal + ADDFONTRESOURCE @119 +; GETCONTINUINGTEXTEXTENT @120 + DEATH @121 ;Internal + RESURRECTION @122 ;Internal + PLAYMETAFILE @123 ; Patched by ATM + GETMETAFILE @124 + CREATEMETAFILE @125 + CLOSEMETAFILE @126 + DELETEMETAFILE @127 + MULDIV @128 + SAVEVISRGN @129 ;Internal + RESTOREVISRGN @130 ;Internal + INQUIREVISRGN @131 ;Internal + SETENVIRONMENT @132 + GETENVIRONMENT @133 + GETRGNBOX @134 + SCANLR @135 ;Internal + REMOVEFONTRESOURCE @136 +;;;;GSV @137 ;Internal +;;;;DPXLATE @138 ;Internal +;;;;SETWINVIEWEXT @139 ;Internal +;;;;SCALEEXT @140 ;Internal +;;;;WORDSET @141 ;Internal +;;;;RECTSTUFF @142 ;Internal +;;;;OFFSETORG @143 ;Internal +; LOCKDC @144 NODATA +; UNLOCKDC @145 NODATA +; LOCKUNLOCK @146 +; GDI_FARFRAME = _TEXT_FARFRAME @147 + SETBRUSHORG @148 + GETBRUSHORG @149 NODATA + UNREALIZEOBJECT @150 + COPYMETAFILE @151 +;; GDIINITAPP @152 + CREATEIC @153 NODATA + GETNEARESTCOLOR @154 + QUERYABORT @155 + CREATEDISCARDABLEBITMAP @156 NODATA +;;;;COMPATIBLEBITMAP @157 ;Internal +;;;;ENUMCALLBACK @158 ;Internal +; + GETMETAFILEBITS @159 + SETMETAFILEBITS @160 +; + + PTINREGION @161 + GETBITMAPDIMENSION @162 + SETBITMAPDIMENSION @163 +;;;;PIXTOLINE @164 ;Internal + +; CREATELVB @165 +; SELECTLVB @166 +; ENABLELVB @167 +; UPDATELVB @168 + ISDCDIRTY @169 ;Internal + SETDCSTATUS @170 ;Internal +;;;;LVBUNION @171 ;Internal +; GETLVB @171 + SETRECTRGN @172 + GETCLIPRGN @173 ;Internal +; BLOAT @174 +; + ENUMMETAFILE @175 + PLAYMETAFILERECORD @176 +; + +;;;;RCOS @177 ;Internal +;;;;RSIN @178 ;Internal + GETDCSTATE @179 ;Internal + SETDCSTATE @180 ;Internal + RECTINREGION @181 +; REQUESTSEM @182 +; CLEARSEM @183 +;;;;STUFFVISIBLE @184 ;Internal +;;;;STUFFINREGION @185 ;Internal + +;;;;DELETEABOVELINEFONTS @186 ;Internal + +; SETFONTMAPPERWEIGHTS @187 +; GETTEXTEXTENTEX @188 ;Internal + + SETDCHOOK @190 ;Internal + GETDCHOOK @191 ;Internal + SETHOOKFLAGS @192 ;Internal + SETBOUNDSRECT @193 + GETBOUNDSRECT @194 + SELECTBITMAP @195 ;Internal + SETMETAFILEBITSBETTER @196 ;New for 3.1 + + DMBITBLT @201 NODATA + DMCOLORINFO @202 NODATA + DMENUMDFONTS @206 NODATA + DMENUMOBJ @207 NODATA + DMOUTPUT @208 NODATA + DMPIXEL @209 NODATA + DMREALIZEOBJECT @210 NODATA + DMSTRBLT @211 + DMSCANLR @212 NODATA + BRUTE @213 + DMEXTTEXTOUT @214 + DMGETCHARWIDTH @215 + DMSTRETCHBLT @216 + DMDIBBITS @217 + DMSTRETCHDIBITS @218 + DMSETDIBTODEV @219 + DMTRANSPOSE @220 + + CREATEPQ @230 NODATA + MINPQ @231 NODATA + EXTRACTPQ @232 NODATA + INSERTPQ @233 NODATA + SIZEPQ @234 NODATA + DELETEPQ @235 NODATA + + OPENJOB @240 + WRITESPOOL @241 + WRITEDIALOG @242 + CLOSEJOB @243 + DELETEJOB @244 + GETSPOOLJOB @245 + STARTSPOOLPAGE @246 + ENDSPOOLPAGE @247 + QUERYJOB @248 ;Internal + COPY @250 ;Internal +; ADDFILESPOOLJOB @251 +; SPOOLESCAPE @252 + DELETESPOOLPAGE @253 ; new for 3.1 + SPOOLFILE @254 ; new for 3.1 + + ENGINEENUMERATEFONT @300 ;Internal + ENGINEDELETEFONT @301 ;Internal + ENGINEREALIZEFONT @302 ;Internal + ENGINEGETCHARWIDTH @303 ;Internal + ENGINESETFONTCONTEXT @304 ;Internal + ENGINEGETGLYPHBMP @305 ;Internal + ENGINEMAKEFONTDIR @306 ;Internal + GETCHARABCWIDTHS @307 + GETOUTLINETEXTMETRICS @308 + GETGLYPHOUTLINE @309 + CREATESCALABLEFONTRESOURCE @310 + GETFONTDATA @311 + CONVERTOUTLINEFONTFILE @312 ;internal + GETRASTERIZERCAPS @313 + ENGINEEXTTEXTOUT @314 ;internal +;;; DUMPEFT @320 + ENUMFONTFAMILIES @330 +;;;;ENUMFONTSINTERNAL @331 ;internal + GETKERNINGPAIRS @332 + + GETTEXTALIGN @345 + SETTEXTALIGN @346 +;;;;MFDRAWTEXT @347 ;Internal + CHORD @348 + SETMAPPERFLAGS @349 + GETCHARWIDTH @350 ; Patched by ATM + EXTTEXTOUT @351 ; Patched by ATM + GETPHYSICALFONTHANDLE @352 ;Internal + GETASPECTRATIOFILTER @353 + SHRINKGDIHEAP @354 ;Internal + FTRAPPING0 @355 ;Internal + + CREATEPALETTE @360 + GDISELECTPALETTE @361 ;Internal + GDIREALIZEPALETTE @362 ;Internal + GETPALETTEENTRIES @363 + SETPALETTEENTRIES @364 + REALIZEDEFAULTPALETTE @365 ;Internal + + UPDATECOLORS @366 + ANIMATEPALETTE @367 + RESIZEPALETTE @368 + + GETNEARESTPALETTEINDEX @370 +;; SELECTCOLORMATCHER @371 + + EXTFLOODFILL @372 + + SETSYSTEMPALETTEUSE @373 + GETSYSTEMPALETTEUSE @374 + GETSYSTEMPALETTEENTRIES @375 + + RESETDC @376 + STARTDOC @377 + ENDDOC @378 + STARTPAGE @379 + ENDPAGE @380 + SETABORTPROC @381 + ABORTDOC @382 + + FASTWINDOWFRAME @400 ;Internal + GDIMOVEBITMAP @401 ;Internal + GDIINIT2 @403 ;Internal + + FINALGDIINIT @405 ;Internal +;;;;CREATEREALBITMAPINDIRECT @406 ;Internal + CREATEUSERBITMAP @407 NODATA ;Internal +;;;;CREATEREALBITMAP @408 ;Internal + CREATEUSERDISCARDABLEBITMAP @409 NODATA ;Internal + ISVALIDMETAFILE @410 ;Internal + + GETCURLOGFONT @411 ;Internal + ISDCCURRENTPALETTE @412 ;Internal +; GETCLIPPINGRGN @435 + + STRETCHDIBITS @439 + SETDIBITS @440 + GETDIBITS @441 + CREATEDIBITMAP @442 + SETDIBITSTODEVICE @443 + + CREATEROUNDRECTRGN @444 + CREATEDIBPATTERNBRUSH @445 +; GETFONTMAPPERWEIGHTS @446 +; LOCKMONOBITMAP @447 +; UNLOCKMONOBITMAP @448 + + DEVICECOLORMATCH @449 ;Internal + POLYPOLYGON @450 + CREATEPOLYPOLYGONRGN @451 + + GDISEEGDIDO @452 ;Internal + + GDITASKTERMINATION @460 ;Internal + SETOBJECTOWNER @461 ;Internal + ISGDIOBJECT @462 + MAKEOBJECTPRIVATE @463 ;Internal + FIXUPBOGUSPUBLISHERMETAFILE @464 ;Internal + RECTVISIBLE_EHH @465 + RECTINREGION_EHH @466 + UNICODETOANSI @467 ;Internal + +; the following functions are added for the NT windows group. + + GETBITMAPDIMENSIONEX @468 + GETBRUSHORGEX @469 NODATA + GETCURRENTPOSITIONEX @470 NODATA + GETTEXTEXTENTPOINT @471 + GETVIEWPORTEXTEX @472 NODATA + GETVIEWPORTORGEX @473 NODATA + GETWINDOWEXTEX @474 NODATA + GETWINDOWORGEX @475 NODATA + OFFSETVIEWPORTORGEX @476 NODATA + OFFSETWINDOWORGEX @477 NODATA + SETBITMAPDIMENSIONEX @478 + SETVIEWPORTEXTEX @479 NODATA + SETVIEWPORTORGEX @480 + SETWINDOWEXTEX @481 NODATA + SETWINDOWORGEX @482 + MOVETOEX @483 + SCALEVIEWPORTEXTEX @484 NODATA + SCALEWINDOWEXTEX @485 NODATA + GETASPECTRATIOFILTEREX @486 + + POLYPOLYLINEWOW @490 ; Internal + + CREATEDIBSECTION @489 + GETDIBCOLORTABLE @603 + SETDIBCOLORTABLE @602 + +; ENGINEENUMERATEFONT @500 ;Internal +; ENGINEDELETEFONT @501 ;internal +; ENGINEREALIZEFONT @502 ;Internal +; ENGINEGETCHARWIDTH @503 ;internal +; ENGINESETFONTCONTEXT @504 ;Internal +; ENGINEGETGLYPHBMP @505 ;internal +; ENGINEMAKEFONTDIR @506 ;Internal +; ENGINEGETABCWIDTHS @507 +; ENGINEGETEXTTEXTMETRICS @508 +; APPGETENGINEOUTLINE @509 +; CREATESCALABLEFONTRESOURCE @510 + +; TEFTI for DNW + + +IMPORTS + + HandleParamError = KERNEL.327 diff --git a/private/mvdm/wow16/gdi/gdi.rc b/private/mvdm/wow16/gdi/gdi.rc new file mode 100644 index 000000000..4a47934ce --- /dev/null +++ b/private/mvdm/wow16/gdi/gdi.rc @@ -0,0 +1,5 @@ +/********************************************************************/ +/* GDI.RC */ +/********************************************************************/ + +#include "gdi.rcv" diff --git a/private/mvdm/wow16/gdi/gdi.rcv b/private/mvdm/wow16/gdi/gdi.rcv new file mode 100644 index 000000000..219ce168c --- /dev/null +++ b/private/mvdm/wow16/gdi/gdi.rcv @@ -0,0 +1,13 @@ +/********************************************************************/ +/* GDI.RCV */ +/********************************************************************/ + +#include <version.h> + +#define VER_FILETYPE VFT_DLL +#define VER_FILESUBTYPE VFT_UNKNOWN +#define VER_FILEDESCRIPTION_STR "Windows Graphics Device Interface core component" +#define VER_INTERNALNAME_STR "GDI" +#define VER_ORIGINALFILENAME_STR "GDI.EXE" + +#include <common.ver> diff --git a/private/mvdm/wow16/gdi/gdi16.h b/private/mvdm/wow16/gdi/gdi16.h new file mode 100644 index 000000000..1f649950d --- /dev/null +++ b/private/mvdm/wow16/gdi/gdi16.h @@ -0,0 +1,422 @@ +/*++ BUILD Version: 0001 + * + * WOW v1.0 + * + * Copyright (c) 1991, Microsoft Corporation + * + * GDI16.H + * + * History: + * Created 01-Jul-1991 by John Colleran (johnc) + * + * Warning!!! + * The same code is used to play 16 bit metafiles in WOW (16 bit code) + * and GDI (32 bit code) + * +--*/ + +#ifdef WOW + #define WIN16 + #define UINT WORD + #define HUGE_T huge +#else + #define WIN32 + #include "port1632.h" + #include "firewall.h" + #ifdef FIREWALLS + #define DEBUG + #endif +#endif + +#define GDIENTRY FAR PASCAL +#define INTERNAL NEAR PASCAL + + +// If this is 32 bit code append a 16 to all the exported APIs + +#ifdef WIN32 + HANDLE FAR PASCAL GetMetaFile16(LPSTR); + BOOL FAR PASCAL PlayMetaFile16(HDC, HANDLE); + void FAR PASCAL PlayMetaFileRecord16(HDC, LPHANDLETABLE, LPMETARECORD, WORD); + + #define GetMetaFile GetMetaFile16 + #define DeleteMetaFile DeleteMetaFile16 + #define PlayMetaFile PlayMetaFile16 + #define PlayMetaFileRecord PlayMetaFileRecord16 + #define IsValidMetaFile IsValidMetaFile16 + + #define AnimatePalettePriv AnimatePalette + #define DeleteObjectPriv DeleteObject + #define ResizePalettePriv ResizePalette + #define SetPaletteEntriesPriv SetPaletteEntries + + #define GetViewportExt(hdc) GetViewportExt32(hdc) + #define GetWindowExt(hdc) GetWindowExt32(hdc) + #define SetViewportExt(h,x,y) SetViewportExt32(h,x,y) + #define SetWindowExt(h,x,y) SetWindowExt32(h,x,y) + + LPINT ConvertInts( signed short * pWord, UINT cWords ); + DWORD GetViewportExt32(HDC hdc); + DWORD GetWindowExt32(HDC hdc); + DWORD SetViewportExt32(HDC hdc, UINT x, UINT y); + DWORD SetWindowExt32(HDC hdc, UINT x, UINT y); + + #define CONVERTPTS(p,c) (LPPOINT)CONVERTINTS((signed short *)p,(c)*2) + #define CONVERTINTS(p,c) ConvertInts((signed short *)p,c) + + #define FREECONVERT(p) LocalFree(p) + + #define PlayIntoAMetafile(a,b) 0 + #define DEFIFWIN16(a) 0 + + #pragma pack(2) + typedef struct + { + WORD mtType; + WORD mtHeaderSize; + WORD mtVersion; + WORD mtSize; + WORD mtSize2; + WORD mtNoObjects; + DWORD mtMaxRecord; + WORD mtNoParameters; + } METAHEADER16; + #define METAHEADER METAHEADER16 + + typedef struct tagLOGFONT16 + { + int lfHeight; + int lfWidth; + int lfEscapement; + int lfOrientation; + int lfWeight; + BYTE lfItalic; + BYTE lfUnderline; + BYTE lfStrikeOut; + BYTE lfCharSet; + BYTE lfOutPrecision; + BYTE lfClipPrecision; + BYTE lfQuality; + BYTE lfPitchAndFamily; + BYTE lfFaceName[LF_FACESIZE]; + } LOGFONT16; + typedef LOGFONT16 FAR *LPLOGFONT16; + #pragma pack() + + #define LOGFONT32FROM16( plf32, plf16 ) \ + { plf32->lfHeight = plf16->lfHeight; \ + plf32->lfWidth = plf16->lfWidth; \ + plf32->lfEscapement = plf16->lfEscapement; \ + plf32->lfOrientation = plf16->lfOrientation; \ + plf32->lfWeight = plf16->lfWeight; \ + plf32->lfItalic = plf16->lfItalic; \ + plf32->lfUnderline = plf16->lfUnderline; \ + plf32->lfStrikeOut = plf16->lfStrikeOut; \ + plf32->lfCharSet = plf16->lfCharSet; \ + plf32->lfOutPrecision = plf16->lfOutPrecision; \ + plf32->lfClipPrecision = plf16->lfClipPrecision; \ + plf32->lfQuality = plf16->lfQuality; \ + plf32->lfPitchAndFamily = plf16->lfPitchAndFamily; \ + memcpy( &plf32->lfItalic, &plf16->lfItalic, LF_FACESIZE); \ + } + + #define ISDCVALID(hdc) TRUE + #define ISMETADC(hdc) FALSE +#else + #define CONVERTPTS(p,c) (LPPOINT)(p) + #define CONVERTINTS(p,c) (p) + #define FREECONVERT(p) + #define DEFIFWIN16(a) a + + #define LOGFONT32FROM16( plf32, plf16 ) {plf32 = plf16;} + #define ISDCVALID(hdc) IsDCValid(hdc) + #define ISMETADC(hdc) IsMetaDC(hdc) + + typedef struct _RGNDATAHEADER { + DWORD dwSize; + DWORD iType; + DWORD nCount; + } RGNDATAHEADER, *PRGNDATAHEADER; + + typedef struct _RGNDATA { + RGNDATAHEADER rdh; + char Buffer[1]; + } RGNDATA,FAR *LPRGNDATA; + + typedef struct _RECTL { + LONG xLeft; + LONG yTop; + LONG xRight; + LONG yBottom; + } RECTL,FAR *LPRECTL; +#endif + +/*** MetaFile Internal Constants and Macros ***/ + +#define METAVERSION 0x0300 +#define METAVERSION100 0x0100 + +/* Metafile constants not in Windows.h */ +#define META_RESETDC 0x0149 +#define META_STARTDOC 0x0150 +#define META_STARTPAGE 0x0051 +#define META_ENDPAGE 0x0052 +#define META_ENDDOC 0x0053 +#define META_ABORTDOC 0x0054 +#define META_EXTFLOODFILL 0x0548 + +#define MAXFILECHUNK ((unsigned)63*1024) + +#define METAFILEFAILURE 1 + +#define METAEXITCODE 0 /* arbitrary value */ + +#define MEMORYMETAFILE 1 +#define DISKMETAFILE 2 + +#define DATASIZE 100 +#define HEADERSIZE (sizeof(METAHEADER)/sizeof(WORD)) + +#define RECHDRSIZE (sizeof(WORD) + sizeof(DWORD)) + +#define LMHtoP(handle) (*((char * *)(handle))) + +#define ID_METADC 0x444D // "MD" +#define METADCBIT 0x1 // Set if DC is a MetaFile DC +#define MAKEMETADC(h) (h|METADCBIT) +#define HANDLEFROMMETADC(h) (((UINT)h) & (~METADCBIT)) +#define HMFFROMNPMF(h) (LocalHandle((WORD)h)|METADCBIT) +#define NPFROMMETADC(h) (LMHtoP((h&(~METADCBIT)))) + +//!!!!!! assert this +#define MAXOBJECTSIZE sizeof(LOGFONT) + +/*** MetaFile Internal TypeDefs ***/ + +typedef BYTE near *NPBYTE; +typedef BYTE HUGE_T *HPBYTE; +typedef WORD HUGE_T *HPWORD; + +typedef HANDLE HMETAFILE; + +typedef struct _METADATA { /* md */ + METAHEADER dataHeader; + WORD metaDataStuff[DATASIZE]; +} METADATA; +typedef METADATA *NPMETADATA; +typedef METADATA FAR *LPMETADATA; + +typedef struct _METAFILE { /* mf */ + METAHEADER MetaFileHeader; + UINT MetaFileNumber; + DWORD MetaFilePosition; + OFSTRUCT MetaFileBuffer; + HANDLE MetaFileRecordHandle; +} METAFILE; +typedef METAFILE *NPMETAFILE; +typedef METAFILE FAR *LPMETAFILE; +typedef METAFILE HUGE_T *HPMETAFILE; + +typedef struct _METACACHE { + HANDLE hCache; + HANDLE hMF; + WORD wCacheSize; + WORD wCachePos; +} METACACHE; + +typedef struct _ILOBJHEAD { + WORD ident; + WORD nextinchain; + int ilObjType; + long ilObjCount; + HANDLE ilObjMetaList; +} ILOBJHEAD; + +typedef struct _METARECORDER { + ILOBJHEAD metaDCHeader; + METAHEADER recordHeader; + DWORD recFilePosition; + OFSTRUCT recFileBuffer; + DWORD sizeBuffer; + WORD recFileNumber; + WORD recFlags; + HANDLE hMetaData; + HANDLE hObjectTable; + HANDLE recCurObjects[6]; // Current Selected Object +} METARECORDER; +typedef METARECORDER *NPMETARECORDER; +typedef METARECORDER FAR *LPMETARECORDER; + +typedef METARECORD HUGE_T *HPMETARECORD; + +typedef struct _OBJECTTABLE { + DWORD objectIndex; + HANDLE objectCurHandle; +} OBJECTTABLE; +typedef OBJECTTABLE *NPOBJECTTABLE; +typedef OBJECTTABLE FAR *LPOBJECTTABLE; + +typedef struct _OBJMETALIST { + WORD omlCount; + HANDLE omlMetaDC[1]; +} OBJMETALIST; + +typedef struct _WIN2OBJHEAD { + WORD nextinchain; + int w2ObjType; + long w2ObjCount; +} WIN2OBJHEAD; +typedef WIN2OBJHEAD *NPWIN2OBJHEAD; +typedef WIN2OBJHEAD FAR *LPWIN2OBJHEAD; + +typedef struct _SCAN { + WORD scnPntCnt; // Scan point count + WORD scnPntTop; // Top of scan + WORD scnPntBottom; // Bottom of scan + WORD scnPntsX[2]; // Start of points in scan + WORD scnPtCntToo; // Point count-- to allow UP travel +} SCAN; +typedef SCAN *NPSCAN; +typedef SCAN FAR *LPSCAN; + +typedef struct _WIN3REGION { + WORD nextInChain; // Not used should be zero + WORD ObjType; // Must always be 6 (Windows OBJ_RGN) + DWORD ObjCount; // Not used + WORD cbRegion; // size of following region struct + WORD cScans; + WORD maxScan; + RECT rcBounding; + SCAN aScans[1]; +} WIN3REGION; +typedef WIN3REGION *NPWIN3REGION; +typedef WIN3REGION FAR *LPWIN3REGION; + +typedef struct _EXTTEXTDATA { + int xPos; + int yPos; + WORD cch; + RECT rcClip; + LPSTR lpString; + LPWORD lpWidths; +}EXTTEXTDATA; +typedef EXTTEXTDATA *NPEXTTEXTDATA; +typedef EXTTEXTDATA FAR *LPEXTTEXTDATA; + +// These are from wingdi.h +#define OBJ_PEN 1 +#define OBJ_BRUSH 2 +#define OBJ_DC 3 +#define OBJ_METADC 4 +#define OBJ_PALETTE 5 +#define OBJ_FONT 6 +#define OBJ_BITMAP 7 +#define OBJ_RGN 8 +#define OBJ_METAFILE 9 +#define OBJ_MEMDC 10 + +#define MIN_OBJ OBJ_PEN +#define MAX_OBJ OBJ_MEMDC + + +// These Function have no DC; so these function allow you to call them directly +#ifdef WIN16 +HANDLE GDIENTRY GetCurrentObject(HDC hdc, WORD wObjType); +DWORD GDIENTRY GetRegionData(HRGN, DWORD, LPRGNDATA); +void GDIENTRY AnimatePalettePriv(HPALETTE, WORD, WORD, LPPALETTEENTRY); +BOOL GDIENTRY DeleteObjectPriv(HANDLE); +BOOL GDIENTRY ResizePalettePriv(HPALETTE, WORD); +WORD GDIENTRY SetPaletteEntriesPriv(HPALETTE,WORD,WORD,LPPALETTEENTRY); +#endif // WIN16 + +BOOL GDIENTRY GdiFlush(VOID); +DWORD GDIENTRY GetObjectType(HANDLE h); +BOOL GDIENTRY IsValidMetaFile(HANDLE hMetaData); + +// Internal Function Declarations +VOID INTERNAL AddToHandleTable(LPHANDLETABLE lpHandleTable, HANDLE hObject, WORD noObjs); +HANDLE INTERNAL AllocBuffer(LPWORD iBufferSize); +DWORD INTERNAL BigRead(UINT fileNumber, LPSTR lpRecord, DWORD dwSizeRec); +VOID INTERNAL CallMetaFunction(HDC, FARPROC, WORD, LPWORD ); +BOOL INTERNAL GDIsSelectPalette(HDC hdc, HPALETTE pal, BOOL f); +LPMETARECORD INTERNAL GetEvent(LPMETAFILE pmf,HPMETARECORD pmr,BOOL bFree); +int INTERNAL GetObjectAndType(HANDLE hObj, LPSTR lpObjectBuf); +HANDLE INTERNAL GetPMetaFile(HDC hdc); +BOOL INTERNAL InitializeGdi(VOID); +BOOL INTERNAL IsDIBBlackAndWhite(LPBITMAPINFOHEADER lpDIBInfo); +BOOL INTERNAL IsDCValid(HDC hdc); +BOOL INTERNAL IsMetaDC(HDC hdc); +BOOL INTERNAL IsObjectStock(HANDLE hObj); +BOOL INTERNAL LPtoSP(HDC,LPPOINT,int); +BOOL INTERNAL PlayIntoAMetafile(LPMETARECORD lpMR, HDC hdcDest); +int INTERNAL RecordObject(HANDLE hMF, WORD magic, WORD count, LPWORD lpParm); +BOOL INTERNAL RecordParms(HANDLE hDC, WORD magic, DWORD count, LPWORD lpParm); +BOOL INTERNAL RecordOther(HANDLE hMF, WORD magic, WORD count, LPWORD lpParm); +BOOL INTERNAL Valid( HANDLE hnd, int l, int h); + + +/**************************************************************************** + + debugging support + +****************************************************************************/ + +// Put a wrapper around 16 bit memory Allocation to help track down bugs +#ifdef DEBUG +#ifndef WIN32 +PSTR INTERNAL _LocalLock(HANDLE h ); +BOOL INTERNAL _LocalUnlock(HANDLE h ); +HANDLE INTERNAL _LocalAlloc(WORD w, WORD w2); +LPSTR INTERNAL _GlobalLock(HANDLE h ); +BOOL INTERNAL _GlobalUnlock(HANDLE h ); +HANDLE INTERNAL _GlobalAlloc(WORD w, DWORD dw ); + +#define LocalLock(h) _LocalLock(h) +#define GlobalLock(h) _GlobalLock(h) +#define LocalUnlock(h) _LocalUnlock(h) +#define GlobalUnlock(h) _GlobalUnlock(h) +#define LocalAlloc(w, w2 ) _LocalAlloc(w, w2) +#define GlobalAlloc(w, dw ) _GlobalAlloc(w, dw) +#endif +#endif + + +#ifdef DEBUG + extern void dDbgOut(int iLevel, LPSTR lpszFormat, ...); + extern void dDbgAssert(LPSTR exp, LPSTR file, int line); + +#ifdef WIN32 + #define dprintf + #define GdiLogFunc(str) + #define GdiLogFunc2(str) + #define GdiLogFunc3(str) + #define ASSERTGDIW(exp,str,w) ASSERTGDI(exp,str) +#else + #define dprintf dDbgOut + #define GdiLogFunc(str) {dDbgOut(3, str );} + #define GdiLogFunc2(str) {dDbgOut(6, str );} + #define GdiLogFunc3(str) {dDbgOut(7, str );} + #define ASSERTGDI(exp,str) \ + {((exp) ? (void)0 : dDbgAssert(str, __FILE__, __LINE__));} + #define ASSERTGDIW(exp,str,w) \ + { char buf[256]; \ + ((exp) ? 0 : \ + ( wsprintf(buf, (LPSTR)str, (WORD)w), \ + dDbgAssert(buf, __FILE__, __LINE__),0)); \ + } \ + +#endif //WIN32 +#else // !DEBUG +#ifdef i386 + #define dprintf /##/ +#else + #define dprintf +#endif + + #define GdiLogFunc(str) + #define GdiLogFunc2(str) + #define GdiLogFunc3(str) + #define ASSERTGDI(exp,str) + #define ASSERTGDIW(exp, str, w) + +#endif // else DEBUG diff --git a/private/mvdm/wow16/gdi/gdimacro.inc b/private/mvdm/wow16/gdi/gdimacro.inc new file mode 100644 index 000000000..a0312ecbf --- /dev/null +++ b/private/mvdm/wow16/gdi/gdimacro.inc @@ -0,0 +1,676 @@ +;/* GDIMACRO.INC - GDI macros + +LMHLockCnt equ byte ptr 3 +wptr equ word ptr +bptr equ byte ptr + +PtoLMH macro r1,r2 +ifnb <r2> + mov r1,[r2 - 2] +else + mov r1,[r1 - 2] +endif +endm + +LMHtoP macro r1,r2 ;; Local Movable Handle to pointer +ifnb <r2> + mov r1,[r2] +else + mov r1,[r1] +endif +endm + +LMHtoPES macro r1,r2 ;; Local Movable Handle to ptr, deref vi ES +ifnb <r2> + 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 <e> ;;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 <UpLimit> +mov dx, UpLimit + else +mov dx, LowLimit + endif + + cCall <far ptr ValidateHandle>,<Handle,bx,dx> + 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,<OBJ_PEN,OBJ_BRUSH,OBJ_FONT,OBJ_BITMAP,OBJ_PALETTE> +ife stock_type-LowLimit + and ax,NOT OBJ_FLAGS ; mask only for possible stock obj +endif +endm + +ifnb <UpLimit> + 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 <UpLimit> +mov dx, UpLimit + else +mov dx, LowLimit + endif + + cCall <far ptr ValidateHandle>,<Handle,bx,dx> + 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 <far ptr SendDCNotify> +ifnb <errLbl> + or ax,ax +endif +ifnb <errLbl> + 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 <far ptr SendInvalidVisRgn>,<hDC> +@@: + endm + +VNotifyPtr? macro reg,hDC + test byte ptr DCFlags[reg],BadVisRgn + jz @F + cCall <far ptr SendInvalidVisRgn>,<hDC> +@@: + 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 <I&name>,<opts>,<savelist> + else + LabelFP <PUBLIC, I&name> + cProc <name>,<opts>,<savelist> + endif +endm + +GDIGLOBALLOCK macro Handle,segRegister,offsetRegister +.lall +ifndef GlobalLock +ExternFP GlobalLock +endif + cCall <far ptr GlobalLock>,<Handle> +ifnb <segRegister> + mov segRegister,dx +endif +ifnb <offsetRegister> + mov offsetRegister,ax +endif +.sall + endm + + +GDIGLOBALUNLOCK macro Handle +ifndef GlobalUnlock +ExternFP GlobalUnlock +endif + cCall <far ptr GlobalUnlock>,<Handle> + 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,<opt1>,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 <opt1> + n opt1 + ifdef debug + filename&&_&&n equ n + public filename&&_&&n + endif + else + n: + ifdef debug + filename&&_&&n: + public filename&&_&&n + endif + endif + ifnb <opt2> + 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 <FOO> ;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 + +;*/ + +
\ No newline at end of file diff --git a/private/mvdm/wow16/gdi/gdimem.inc b/private/mvdm/wow16/gdi/gdimem.inc new file mode 100644 index 000000000..da351658d --- /dev/null +++ b/private/mvdm/wow16/gdi/gdimem.inc @@ -0,0 +1,50 @@ +;definitions pasted in from WINDOWS.INC for memory management call to KERNEL: +; +; Memory manager flags +; +LMEM_FIXED = 0000h +LMEM_MOVEABLE = 0002h +LMEM_NOCOMPACT = 0010H +LMEM_NODISCARD = 0020H +LMEM_ZEROINIT = 0040h +LMEM_MODIFY = 0080H +LMEM_DISCARDABLE= 0F00h +LHND = LMEM_MOVEABLE+LMEM_ZEROINIT +LPTR = LMEM_FIXED+LMEM_ZEROINIT +; Flags returned by LocalFlags (in addition to LMEM_DISCARDABLE) +LMEM_DISCARDED = 4000H +LMEM_LOCKCOUNT = 00FFH + +NONZEROLHND = LMEM_MOVEABLE +NONZEROLPTR = LMEM_FIXED + +LNOTIFY_OUTOFMEM = 0 +LNOTIFY_MOVE = 1 +LNOTIFY_DISCARD = 2 + + +GMEM_FIXED = 0000h +GMEM_MOVEABLE = 0002h +GMEM_NOCOMPACT = 0010h +GMEM_NODISCARD = 0020h +GMEM_ZEROINIT = 0040h +GMEM_MODIFY = 0080h +GMEM_DISCARDABLE= 0100h +GMEM_NOT_BANKED = 1000h +GMEM_DDESHARE = 2000h +GMEM_SHARE = 2000h +GMEM_NOTIFY = 4000h +GMEM_LOWER = GMEM_NOT_BANKED +GHND = GMEM_MOVEABLE+GMEM_ZEROINIT +GPTR = GMEM_FIXED+GMEM_ZEROINIT + +; Flags returned by GlobalFlags (in addition to GMEM_DISCARDABLE) +GMEM_DISCARDED = 4000h +GMEM_LOCKCOUNT = 00FFh + +; Debug fill constants + +DBGFILL_ALLOC equ 0fdh +DBGFILL_FREE equ 0fbh +DBGFILL_BUFFER equ 0f9h +DBGFILL_STACK equ 0f7h diff --git a/private/mvdm/wow16/gdi/layer.asm b/private/mvdm/wow16/gdi/layer.asm new file mode 100644 index 000000000..5a21c692d --- /dev/null +++ b/private/mvdm/wow16/gdi/layer.asm @@ -0,0 +1,47 @@ + title LAYER.ASM - Parameter validation layer + +.xlist + +LAYER_INCLUDE=1 + +include layer.inc +include gpfix.inc +;include gditype.inc +ilObjType = 2 +;include gdiobj.inc + +createSeg _DATA,DATA,WORD,PUBLIC,DATA,DGROUP + +.list + +.lall + +LAYER_START + +include gdi.api + +LAYER_END + +;LAYER_EXPAND INIT +LAYER_EXPAND TEXT +;LAYER_EXPAND PALETTE +;LAYER_EXPAND ESC +;LAYER_EXPAND DCSTUFF +;LAYER_EXPAND LOGMISC +;LAYER_EXPAND FONTLOAD +;LAYER_EXPAND FONTRES +;LAYER_EXPAND FONTINQ +;LAYER_EXPAND FONTSIMS +;LAYER_EXPAND METAREC +;LAYER_EXPAND METAPLAY +;LAYER_EXPAND ARCDDA +;LAYER_EXPAND OUTMAN +;LAYER_EXPAND POLYGON +;LAYER_EXPAND RGOUT +;LAYER_EXPAND MISC +;LAYER_EXPAND PIXDDA +;LAYER_EXPAND DIBITMAP +;LAYER_EXPAND FLOODFILL +;LAYER_EXPAND RECT + +end diff --git a/private/mvdm/wow16/gdi/makefile b/private/mvdm/wow16/gdi/makefile new file mode 100644 index 000000000..effa313da --- /dev/null +++ b/private/mvdm/wow16/gdi/makefile @@ -0,0 +1,126 @@ +# GDI16 makefile +# +# Copyright (c) 1991, Microsoft Corporation +# +# History: +# 26-Jan-1991 Jeff Parsons (jeffpar) +# Created. +# + +!IFDEF USEBUILD + +# If using BUILD.EXE, edit .\sources. if you want to add a new source +# file to this component. This file merely indirects to the real make file +# that is shared by all the components of NT OS/2. + +!INCLUDE $(NTMAKEENV)\makefile.def + +!ELSE + +.SUFFIXES: +.SUFFIXES: .c .asm .h .inc .obj .lst .sys .exe .com .map .sym .def .lib .rc .res + + +!ifdef INCLUDE +INCS = +!else +INCS = -I..\inc -I..\..\inc +RINCS = -I..\inc +!endif + +########## Path definition so we find 16 bit tools ########## +# Also works around stupid bug in RC 3.1 that doesn't allow rcpp.err to be +# in a directory that is greater than 128 chars down the path, even if +# rc 3.1 is running as an OS/2 app. + +PATH = $(_NTBINDIR)\private\mvdm\tools16;$(PATH) + +# DEFINES = -DWOW -DDEBUG $(MVDMFLAGS) +DEFINES = -DWOW -DBUILDDLL $(MVDMFLAGS) + +AOBJ = -Mx -t $(DEFINES) $(INCS) + +CW16 = -PLM -Asnw -G2sw $(DEFINES) $(INCS) +#CW16 = -AS -G2sw $(DEFINES) $(INCS) +CW16B = $(CW16) -B1 c1l.exe -B2 c2l.exe -B3 c3l.exe + +LINK = /map /align:16 + +!if "$(NTDEBUG)"!="" && "$(NTDEBUG)"!="retail" && "$(NTDEBUG)" != "ntsdnodbg" +AOBJ = $(AOBJ) -Zd +CW16 = $(CW16) /Odi /Zd +LINK = $(LINK) /LI +!else +CW16 = $(CW16) /Os /Zp +!endif + +W16LIBS = ..\lib\snocrtd.lib ..\lib\libw.lib + + +.asm.obj: + masm $(AOBJ) $*; + +.asm.lst: + masm $(AOBJ) -l $*,nul,$*.lst; + + +.c.obj: + cl16 -c -nologo $(CW16) $*.c + +.c.lst: + cl16 -c -nologo $(CW16) -Fonul -Fc$*.lst $*.c + + +.def.lib: + implib $*.lib $*.def + +.map.sym: + mapsym $* + +.rc.res: + rc16 -r $(INCS) -fo $@ $*.rc + +all: gdi.exe gdi.sym + binplace gdi.exe + binplace gdi.sym + binplace gdi.map + +clean: cleanup all + +cleanup: + if exist *.lrf del *.lrf + if exist *.obj del *.obj + if exist *.exe del *.exe + if exist *.map del *.map + if exist *.sym del *.sym + if exist *.res del *.res + +gdi.obj: gdi.asm ..\..\inc\wow.inc ..\..\inc\wowgdi.inc + masm $(AOBJ) gdi; + +sort.obj: sort.asm ..\..\inc\wow.inc ..\..\inc\wowgdi.inc + masm $(AOBJ) sort; + +layer.obj: layer.asm ..\inc\layer.inc gdi.api + masm $(AOBJ) layer; + +muldiv.obj: muldiv.asm + masm $(AOBJ) muldiv; + +fontres.obj: fontres.c ..\..\inc\wow.h ..\..\inc\wowgdi.h + cl16 -c -nologo $(CW16) fontres.c + +gdi.lrf: makefile + echo gdi.obj+layer.obj+muldiv.obj+fontres.obj+sort.obj >gdi.lrf + echo gdi.exe>>gdi.lrf + echo gdi $(LINK)>>gdi.lrf + echo $(W16LIBS) /nod>>gdi.lrf + echo gdi;>>gdi.lrf + +gdi.res: $*.rc $*.rcv ..\inc\common.ver + +gdi.exe gdi.map: sort.obj gdi.obj gdi.lrf gdi.def layer.obj muldiv.obj fontres.obj gdi.res + link16 @gdi.lrf; + rc16 -t gdi.res gdi.exe + +!ENDIF diff --git a/private/mvdm/wow16/gdi/meta.c b/private/mvdm/wow16/gdi/meta.c new file mode 100644 index 000000000..7e98d8682 --- /dev/null +++ b/private/mvdm/wow16/gdi/meta.c @@ -0,0 +1,1835 @@ +/****************************** Module Header ******************************\ +* Module Name: Meta.c +* +* This file contains the routines for playing the GDI metafile. Most of these +* routines are adopted from windows gdi code. Most of the code is from +* win3.0 except for the GetEvent code which is taken from win2.1 +* +* Created: 11-Oct-1989 +* +* Copyright (c) 1985, 1986, 1987, 1988, 1989 Microsoft Corporation +* +* +* Public Functions: +* PlayMetaFile +* PlayMetaFileRecord +* GetMetaFile +* DeleteMetaFile +* Private Functions: +* GetEvent +* IsDIBBlackAndWhite +* +* History: +* 02-Jul-1991 -by- John Colleran [johnc] +* Combined From Win 3.1 and WLO 1.0 sources +\***************************************************************************/ + +#include <windows.h> +#include <string.h> +#ifdef WIN32 +#include "firewall.h" +#endif +#include "gdi16.h" + +HDC hScreenDC = 0; +METACACHE MetaCache = { 0, 0, 0, 0 }; + +UINT INTERNAL GetFileNumber (LPMETAFILE lpMF); +HANDLE INTERNAL CreateBitmapForDC (HDC hMemDC, LPBITMAPINFOHEADER lpDIBInfo); +WORD INTERNAL GetSizeOfColorTable (LPBITMAPINFOHEADER lpDIBInfo); + +#define MAX_META_DISPATCH 0x48 +FARPROC alpfnMetaFunc[MAX_META_DISPATCH+1] = +/* 00 */ {(FARPROC)ScaleWindowExt, +/* 01 */ (FARPROC)SetBkColor, +/* 02 */ (FARPROC)SetBkMode, +/* 03 */ (FARPROC)SetMapMode, +/* 04 */ (FARPROC)SetROP2, +/* 05 */ DEFIFWIN16((FARPROC)SetRelAbs), +/* 06 */ (FARPROC)SetPolyFillMode, +/* 07 */ (FARPROC)SetStretchBltMode, +/* 08 */ (FARPROC)SetTextCharacterExtra, +/* 09 */ (FARPROC)SetTextColor, +/* 0A */ (FARPROC)SetTextJustification, +/* 0B */ (FARPROC)SetWindowOrg, +/* 0C */ (FARPROC)SetWindowExt, +/* 0D */ (FARPROC)SetViewportOrg, +/* 0E */ (FARPROC)SetViewportExt, +/* 0F */ (FARPROC)OffsetWindowOrg, +/* 10 */ 0, +/* 11 */ DEFIFWIN16((FARPROC)OffsetViewportOrg), +/* 12 */ DEFIFWIN16((FARPROC)ScaleViewportExt), +/* 13 */ (FARPROC)LineTo, +/* 14 */ DEFIFWIN16((FARPROC)MoveTo), +/* 15 */ (FARPROC)ExcludeClipRect, +/* 16 */ (FARPROC)IntersectClipRect, +/* 17 */ (FARPROC)Arc, +/* 18 */ (FARPROC)Ellipse, +/* 19 */ (FARPROC)FloodFill, +/* 1A */ (FARPROC)Pie, +/* 1B */ (FARPROC)Rectangle, +/* 1C */ (FARPROC)RoundRect, +/* 1D */ (FARPROC)PatBlt, +/* 1E */ (FARPROC)SaveDC, +/* 1F */ (FARPROC)SetPixel, +/* 20 */ (FARPROC)OffsetClipRgn, +/* 21 */ 0, // TextOut, +/* 22 */ 0, // BitBlt, +/* 23 */ 0, // StretchBlt. +/* 24 */ 0, // Polygon, +/* 25 */ 0, // Polyline, +/* 26 */ 0, // Escape, +/* 27 */ (FARPROC)RestoreDC, +/* 28 */ 0, // FillRegion, +/* 29 */ 0, // FrameRegion, +/* 2A */ 0, // InvertRegion, +/* 2B */ 0, // PaintRegion, +/* 2C */ (FARPROC)SelectClipRgn, +/* 2D */ 0, // SelectObject, +/* 2E */ (FARPROC)SetTextAlign, +/* 2F */ 0, // DrawText, +/* 30 */ (FARPROC)Chord, +/* 31 */ (FARPROC)SetMapperFlags, +/* 32 */ 0, // ExtTextOut, +/* 33 */ 0, // SetDibsToDevice, +/* 34 */ 0, // SelectPalette, +/* 35 */ 0, // RealizePalette, +/* 36 */ 0, // AnimatePalette, +/* 37 */ 0, // SetPaletteEntries, +/* 38 */ 0, // PolyPolygon, +/* 39 */ 0, // ResizePalette, +/* 3A */ 0, +/* 3B */ 0, +/* 3C */ 0, +/* 3D */ 0, +/* 3E */ 0, +/* 3F */ 0, +/* 40 */ 0, // DIBBitblt, +/* 41 */ 0, // DIBStretchBlt, +/* 42 */ 0, // DIBCreatePatternBrush, +/* 43 */ 0, // StretchDIB, +/* 44 */ 0, +/* 45 */ 0, +/* 46 */ 0, +/* 47 */ 0, +/* 48 */ (FARPROC)ExtFloodFill }; + + +#if 0 // this is going to gdi.dll + +/***************************** Public Function ****************************\ +* BOOL APIENTRY PlayMetaFile(hdc, hmf) +* HDC hDC; +* HMETAFILE hMF; +* +* Play a windows metafile. +* +* History: +* Tue 27-Mar-1990 11:11:45 -by- Paul Klingler [paulk] +* Ported from Windows +\***************************************************************************/ + +BOOL GDIENTRY PlayMetaFile(HDC hdc, HMETAFILE hmf) +{ + WORD i; + WORD noObjs; + BOOL bPrint=FALSE; + LPMETAFILE lpmf; + int oldMapMode = -1; + LPMETARECORD lpmr = NULL; + LPHANDLETABLE pht = NULL; + HANDLE hht = NULL; +#ifndef WIN32 + HFONT hLFont; + HBRUSH hLBrush; + HPALETTE hLPal; + HPEN hLPen; + HRGN hClipRgn; + HRGN hRegion; + DWORD oldWndExt; + DWORD oldVprtExt; +#endif //WIN32 + + GdiLogFunc("PlayMetaFile"); + + if(!IsValidMetaFile(hmf)) + goto exitPlayMetaFile; + + if(lpmf = (LPMETAFILE)GlobalLock(hmf)) + { + if((noObjs = lpmf->MetaFileHeader.mtNoObjects) > 0) + { + if(!(hht = GlobalAlloc(GMEM_ZEROINIT|GMEM_MOVEABLE, + (sizeof(HANDLE) * lpmf->MetaFileHeader.mtNoObjects) + sizeof(WORD )))) + { + goto exitPlayMetaFile10; + } + pht = (LPHANDLETABLE)GlobalLock(hht); + } +#ifdef CR1 +IMP: Optmizations playing into another metafile. Look at the win3.0 +IMP: code +#endif + +// !!!!! what if this is a metafile DC +#ifndef WIN32 + /* save the old objects so we can put them back */ + hLPen = GetCurrentObject( hdc, OBJ_PEN ); + hLBrush = GetCurrentObject( hdc, OBJ_BRUSH); + hLFont = GetCurrentObject( hdc, OBJ_FONT); + hClipRgn = GetCurrentObject( hdc, OBJ_RGN); + hLPal = GetCurrentObject( hdc, OBJ_PALETTE); + + if(hRegion = GetCurrentObject( hdc, OBJ_RGN)) + { + if(hClipRgn = CreateRectRgn(0,0,0,0)) + CombineRgn(hClipRgn,hRegion,hRegion,RGN_COPY); + } +#endif // WIN32 + + // we should really remove this abort proc thing. + + while(lpmr = GetEvent(lpmf,lpmr,FALSE)) + { +#if 0 //!!!!! + if(GET_pAbortProc(pdc)) +#else + if( 0 ) +#endif //!!!!! + { +//!!!!! if((bPrint = (*(pdc->pAbortProc))(hdc,0)) == FALSE) + { + GetEvent(lpmf,lpmr,TRUE); + RestoreDC(hdc,0); + goto exitPlayMetaFile20; + } + } + PlayMetaFileRecord(hdc,pht,lpmr,noObjs); + } + + bPrint = TRUE; +exitPlayMetaFile20: + /* if we fail restoring an object, we need to select some + default object so that we can DeleteObject any Metafile- + selected objects */ + +#ifndef WIN32 + if(!SelectObject(hdc,hLPen)) + SelectObject(hdc,GetStockObject(BLACK_PEN)); + if(!SelectObject(hdc,hLBrush)) + SelectObject(hdc,GetStockObject(BLACK_BRUSH)); + if(!SelectPalette(hdc, GetCurrentObject( hdc, OBJ_PALETTE), FALSE)) + SelectPalette(hdc, GetStockObject(DEFAULT_PALETTE), FALSE); + + if(!SelectObject(hdc,hLFont)) + { + /* if we cannot select the original font back in, we + ** select the system font. this will allow us to delete + ** the metafile font selected. to insure that the system + ** font gets selected, we reset the DC's transform to + ** default. after the selection, we restore this stuff + */ + oldVprtExt = GetViewportExt(hdc); + oldWndExt = GetWindowExt(hdc); + oldMapMode = SetMapMode(hdc,MM_TEXT); + + SelectObject(hdc,GetStockObject(SYSTEM_FONT)); + + SetMapMode(hdc,oldMapMode); + SetWindowExt(hdc,LOWORD (oldWndExt),HIWORD (oldWndExt)); + SetViewportExt(hdc,LOWORD (oldVprtExt),HIWORD (oldVprtExt)); + } + + if(hClipRgn) + { + SelectObject(hdc,hClipRgn); + DeleteObject(hClipRgn); + } +#endif // WIN32 + + for(i = 0; i < lpmf->MetaFileHeader.mtNoObjects; ++i) + { + if(pht->objectHandle[i]) + DeleteObject(pht->objectHandle[i]); + } + +#ifndef WIN32 + /* if we fiddled with the map mode because we could not + ** restore the original font, then maybe we can restore the + ** font now */ + if(oldMapMode > 0) + SelectObject(hdc,hLFont); +#endif // WIN32 + + if(hht) + { + GlobalUnlock(hht); + GlobalFree(hht); + } + +exitPlayMetaFile10: + GlobalUnlock(hmf); + } + +exitPlayMetaFile: + return(bPrint); +} +#endif // this is going to gdi.dll + +/***************************** Internal Function **************************\ +* BOOL NEAR PASCAL IsDIBBlackAndWhite +* +* Check to see if this DIB is a black and white DIB (and should be +* converted into a mono bitmap as opposed to a color bitmap). +* +* Returns: TRUE it is a B&W bitmap +* FALSE this sucker is for color +* +* Effects: ? +* +* Warnings: ? +* +* History: +\***************************************************************************/ + +BOOL INTERNAL IsDIBBlackAndWhite(LPBITMAPINFOHEADER lpDIBInfo) +{ + LPDWORD lpRGB; + + GdiLogFunc3( " IsDIBBlackAndWhite"); + + /* pointer color table */ + lpRGB = (LPDWORD)((LPBITMAPINFO)lpDIBInfo)->bmiColors; + + if ((lpDIBInfo->biBitCount == 1 && lpDIBInfo->biPlanes == 1) + && (lpRGB[0] == (DWORD)0) + && (lpRGB[1] == (DWORD)0xFFFFFF)) + return(TRUE); + else + return(FALSE); +} + + +/***************************** Internal Function **************************\ +* BigRead +* +* allows reads of greater than 64K +* +* Returns: Number of bytes read +* +\***************************************************************************/ + +DWORD INTERNAL BigRead(UINT fileNumber, LPSTR lpRecord, DWORD dwSizeRec) +{ + DWORD dwRead = dwSizeRec; + HPBYTE hpStuff; + + GdiLogFunc2( " BigRead"); + + hpStuff = (HPBYTE)lpRecord; + + while (dwRead > MAXFILECHUNK) + { + if (_lread(fileNumber, (LPSTR)hpStuff, MAXFILECHUNK) != MAXFILECHUNK) + return(0); + + dwRead -= MAXFILECHUNK; + hpStuff += MAXFILECHUNK; + } + + if (_lread(fileNumber, (LPSTR)hpStuff, (UINT)dwRead) != (UINT)dwRead) + return(0); + + return(dwSizeRec); +} + + +/***************************** Internal Function **************************\ +* UseStretchDIBits +* +* set this directly to the device using StretchDIBits. +* if DIB is black&white, don't do this. +* +* Returns: +* TRUE --- operation successful +* FALSE -- decided not to use StretchDIBits +* +* Effects: ? +* +* Warnings: ? +* +* History: +\***************************************************************************/ + +BOOL INTERNAL UseStretchDIB(HDC hDC, WORD magic, LPMETARECORD lpMR) +{ + LPBITMAPINFOHEADER lpDIBInfo; + int sExtX, sExtY; + int sSrcX, sSrcY; + int DstX, DstY, DstXE, DstYE; + + if (magic == META_DIBBITBLT) + { + lpDIBInfo = (LPBITMAPINFOHEADER)&lpMR->rdParm[8]; + + DstX = lpMR->rdParm[7]; + DstY = lpMR->rdParm[6]; + + sSrcX = lpMR->rdParm[3]; + sSrcY = lpMR->rdParm[2]; + DstXE = sExtX = lpMR->rdParm[5]; + DstYE = sExtY = lpMR->rdParm[4]; + } + else + { + lpDIBInfo = (LPBITMAPINFOHEADER)&lpMR->rdParm[10]; + + DstX = lpMR->rdParm[9]; + DstY = lpMR->rdParm[8]; + DstXE = lpMR->rdParm[7]; + DstYE = lpMR->rdParm[6]; + + sSrcX = lpMR->rdParm[5]; + sSrcY = lpMR->rdParm[4]; + sExtX = lpMR->rdParm[3]; + sExtY = lpMR->rdParm[2]; + } + + /* if DIB is black&white, we don't really want to do this */ + if (IsDIBBlackAndWhite(lpDIBInfo)) + return(FALSE); + + StretchDIBits(hDC, DstX, DstY, DstXE, DstYE, + sSrcX, sSrcY, sExtX, sExtY, + (LPBYTE)((LPSTR)lpDIBInfo + lpDIBInfo->biSize + + GetSizeOfColorTable(lpDIBInfo)), + (LPBITMAPINFO)lpDIBInfo, DIB_RGB_COLORS, + (MAKELONG(lpMR->rdParm[1], lpMR->rdParm[0]))); + return(TRUE); +} + +/***************************** Internal Function **************************\ +* GetEvent +* +* This routine will now open a disk metafile in READ_ONLY mode. This will +* allow us to play read-only metafiles or to share such file. +* +* [amitc: 06/19/91] +\***************************************************************************/ + +LPMETARECORD INTERNAL GetEvent(LPMETAFILE lpMF, HPMETARECORD lpMR, BOOL bFree) +// BOOL bFree; /* non-zero ==> done with metafile */ +{ + int fileNumber = 0; + WORD i; + LPWORD lpCache = NULL; + LPWORD lpMRbuf; + HANDLE hMF; + DWORD rdSize; + + GdiLogFunc2( " GetEvent"); + +#ifdef WIN32 + hMF = GlobalHandle(lpMF); +#else + hMF = LOWORD(GlobalHandle(HIWORD((DWORD)(lpMF)))); +#endif + + ASSERTGDI( hMF != (HANDLE)NULL, "GetEvent: Global Handle failed"); + + if (lpMF->MetaFileHeader.mtType == MEMORYMETAFILE) + { + /* Are we at the end of the metafile */ + if(lpMR && lpMR->rdFunction == 0) + return((LPMETARECORD)0); + + /* done with metafile, so free up the temp selector */ + else if (bFree) + { + if (lpMR) + #ifndef WIN32 + FreeSelector(HIWORD(lpMR)); + #endif + return((LPMETARECORD)0); + } + else + { + /* if we don't already have a selector, get one */ + if (lpMR == NULL) + { + #ifdef WIN32 + lpMR = (HPMETARECORD)((LPMETADATA)lpMF)->metaDataStuff; + // lpMR = (LPMETARECORD)GlobalLock(lpMF->hMetaData); + #else + lpMR = (LPMETARECORD)MAKELP(AllocSelector(HIWORD((DWORD)&lpMF->MetaFileNumber)),LOWORD((DWORD)&lpMF->MetaFileNumber)); + #endif + } + else + lpMR = (LPMETARECORD) (((HPWORD)lpMR)+lpMR->rdSize); + + /* end of the metafile. free up the selector we were using */ + if (lpMR->rdFunction == 0) + { + #ifndef WIN32 + FreeSelector(HIWORD(lpMR)); + #endif + return((LPMETARECORD)0); + } + } + return(lpMR); + } + else if (lpMF->MetaFileHeader.mtType == DISKMETAFILE) + { + if (bFree) + goto errGetEvent; /* never TRUE on the first call to GetEvent */ + + if (lpMR == NULL) + { + if ((fileNumber = OpenFile((LPSTR)lpMF->MetaFileBuffer.szPathName, (LPOFSTRUCT)&(lpMF->MetaFileBuffer), (WORD)OF_PROMPT|OF_REOPEN|OF_READ)) != -1) + { + if (lpMF->MetaFileRecordHandle = GlobalAlloc(GMEM_DDESHARE|GMEM_MOVEABLE,(DWORD)(lpMF->MetaFileHeader.mtMaxRecord * sizeof(WORD)))) + { + lpMR = (LPMETARECORD)GlobalLock(lpMF->MetaFileRecordHandle); + lpMF->MetaFilePosition = _lread(lpMF->MetaFileNumber = fileNumber, (LPSTR)&lpMF->MetaFileHeader, sizeof(METAHEADER)); + + // Check for an Aldus header + if (*((LPDWORD)&(lpMF->MetaFileHeader)) == 0x9AC6CDD7) + { + _llseek( fileNumber, 22, 0); + lpMF->MetaFilePosition = 22 + _lread(fileNumber,(LPSTR)(&(lpMF->MetaFileHeader)),sizeof(METAHEADER)); + } + + lpMF->MetaFileHeader.mtType = DISKMETAFILE; + + if (!MetaCache.hCache) + { + MetaCache.hCache = AllocBuffer(&MetaCache.wCacheSize); + MetaCache.wCacheSize >>= 1; + MetaCache.hMF = hMF; + + /* force cache fill on first access */ + MetaCache.wCachePos = MetaCache.wCacheSize; + } + + if (!(lpMF->MetaFileBuffer.fFixedDisk)) + { + _lclose(fileNumber); + + /* need to update the following for floppy files -- amitc */ + fileNumber = 0 ; + lpMF->MetaFileNumber = 0 ; + } + } + } + else + return((LPMETARECORD)0); + } + + /* update fileNumber, this is so that floopy based files can be closed + and not left open -- amitc */ + + fileNumber = lpMF->MetaFileNumber ; + + if (lpMR) + { + if (MetaCache.hMF == hMF) + { + + lpCache = (LPWORD) GlobalLock(MetaCache.hCache); + lpMRbuf = (LPWORD) lpMR; + + // Make sure we can read the size and function fields + if (MetaCache.wCachePos >= (WORD)(MetaCache.wCacheSize - 2)) + { + WORD cwCopy; + + if (!fileNumber) + if ((fileNumber = GetFileNumber(lpMF)) == -1) + goto errGetEvent; + + // We need to fill up the cache but save any data already + // in the cache + cwCopy = MetaCache.wCacheSize - MetaCache.wCachePos; + for (i = 0; i < cwCopy; i++) + { + lpCache[i] = lpCache[MetaCache.wCacheSize-(cwCopy-i)]; + } + lpMF->MetaFilePosition += _lread(fileNumber, + (LPSTR) (lpCache + cwCopy), + (MetaCache.wCacheSize-cwCopy) << 1); + MetaCache.wCachePos = 0; + } + + lpCache += MetaCache.wCachePos; + rdSize = ((LPMETARECORD)lpCache)->rdSize; + + /* Check for end */ + if (!((LPMETARECORD)lpCache)->rdFunction) + goto errGetEvent; + + // Make sure we can read the rest of the metafile record + if (rdSize + MetaCache.wCachePos > MetaCache.wCacheSize) + { + if (!fileNumber) + if ((fileNumber = GetFileNumber(lpMF)) + == -1) + goto errGetEvent; + + for (i=MetaCache.wCachePos; i < MetaCache.wCacheSize; ++i) + *lpMRbuf++ = *lpCache++; + + lpMF->MetaFilePosition += + BigRead(fileNumber, (LPSTR) lpMRbuf, + (DWORD)(rdSize + + (DWORD)MetaCache.wCachePos + - (DWORD)MetaCache.wCacheSize) << 1); + + // Mark the cache as depleted because we just read + // directly into the metafile record rather than the cache + MetaCache.wCachePos = MetaCache.wCacheSize; + } + else + { + ASSERTGDI( HIWORD(rdSize) == 0, "Huge rdsize"); + for (i = 0; i < LOWORD(rdSize); ++i) + *lpMRbuf++ = *lpCache++; + + MetaCache.wCachePos += LOWORD(rdSize); + } + + GlobalUnlock(MetaCache.hCache); + + return lpMR; + } + + if ((fileNumber = GetFileNumber(lpMF)) == -1) + goto errGetEvent; + + lpMF->MetaFilePosition += _lread(fileNumber, (LPSTR)&lpMR->rdSize, sizeof(DWORD)); + lpMF->MetaFilePosition += BigRead(fileNumber, (LPSTR)&lpMR->rdFunction, (DWORD)(lpMR->rdSize * sizeof(WORD)) - sizeof(DWORD)); + if (!(lpMF->MetaFileBuffer.fFixedDisk)) + { + _lclose(fileNumber); + lpMF->MetaFileNumber = 0 ; + fileNumber = 0 ; + } + + if (lpMR->rdFunction == 0) + { +errGetEvent:; + + if (lpMF->MetaFileBuffer.fFixedDisk || fileNumber) + _lclose(lpMF->MetaFileNumber); + GlobalUnlock(lpMF->MetaFileRecordHandle); + GlobalFree(lpMF->MetaFileRecordHandle); + lpMF->MetaFileNumber = 0; + + if (MetaCache.hMF == hMF) + { + if (lpCache) + GlobalUnlock(MetaCache.hCache); + GlobalFree(MetaCache.hCache); + MetaCache.hCache = MetaCache.hMF = 0; + } + + return((LPMETARECORD)0); + } + } + return(lpMR); + + } + + return((LPMETARECORD)0); +} + + +/***************************** Internal Function **************************\ +* void GDIENTRY PlayMetaFileRecord +* +* Plays a metafile record by executing the GDI function call contained +* withing the metafile record +* +* Effects: +* +\***************************************************************************/ +#if 0 // this is going to gdi.dll + +void +GDIENTRY PlayMetaFileRecord( + HDC hdc, + LPHANDLETABLE lpHandleTable, + LPMETARECORD lpMR, + WORD noObjs + ) + +{ + WORD magic; + HANDLE hObject; + HANDLE hOldObject; + HBRUSH hBrush; + HRGN hRgn; + HANDLE hPal; + BOOL bExtraSel = FALSE; + + dprintf( 3," PlayMetaFileRecord 0x%lX", lpMR); + + if (!ISDCVALID(hdc)) + return; + + magic = lpMR->rdFunction; + + /* being safe, make sure that the lp will give us full access to + ** the record header without overstepping a segment boundary. + */ + #ifndef WIN32 + if ((unsigned)(LOWORD((DWORD)lpMR)) > 0x7000) + { + lpMR = (LPMETARECORD)MAKELP(AllocSelector(HIWORD((DWORD)lpMR)),LOWORD((DWORD)lpMR)); + bExtraSel = TRUE; + } + #endif // WIN32 + + switch (magic & 255) + { + case (META_BITBLT & 255): + case (META_STRETCHBLT & 255): + { + HDC hSDC; + HANDLE hBitmap; + LPBITMAP lpBitmap; + int delta = 0; + + /* if playing into another Metafile, do direct copy */ + if (PlayIntoAMetafile(lpMR, hdc)) + goto errPlayMetaFileRecord20; + + if ((lpMR->rdSize - 3) == (magic >> 8)) + { + hSDC = hdc; + delta = 1; + } + else + { + if (hSDC = CreateCompatibleDC(hdc)) + { + if (magic == META_BITBLT) + lpBitmap = (LPBITMAP)&lpMR->rdParm[8]; + else + lpBitmap = (LPBITMAP)&lpMR->rdParm[10]; + + //!!!!! ALERT DWORD align on NT + if (hBitmap = CreateBitmap(lpBitmap->bmWidth, + lpBitmap->bmHeight, + lpBitmap->bmPlanes, + lpBitmap->bmBitsPixel, + (LPBYTE)&lpBitmap->bmBits)) + hOldObject = SelectObject(hSDC, hBitmap); + else + goto errPlayMetaFileRecord10; + } + else + goto errPlayMetaFileRecord20; + } + + if (hSDC) + { + if (magic == META_BITBLT) + BitBlt(hdc, lpMR->rdParm[7 + delta], + lpMR->rdParm[6 + delta], + lpMR->rdParm[5 + delta], + lpMR->rdParm[4 + delta], + hSDC, + lpMR->rdParm[3], + lpMR->rdParm[2], + MAKELONG(lpMR->rdParm[0], lpMR->rdParm[1])); + else + StretchBlt(hdc, lpMR->rdParm[9 + delta], + lpMR->rdParm[8 + delta], + lpMR->rdParm[7 + delta], + lpMR->rdParm[6 + delta], + hSDC, + lpMR->rdParm[5], + lpMR->rdParm[4], + lpMR->rdParm[3], + lpMR->rdParm[2], + MAKELONG(lpMR->rdParm[0], lpMR->rdParm[1])); + } + if (hSDC != hdc) + { + if (SelectObject(hSDC, hOldObject)) + DeleteObject(hBitmap); +errPlayMetaFileRecord10:; + DeleteDC(hSDC); +errPlayMetaFileRecord20:; + } + } + break; + + case (META_DIBBITBLT & 255): + case (META_DIBSTRETCHBLT & 255): + { + HDC hSDC; + HANDLE hBitmap; + LPBITMAPINFOHEADER lpDIBInfo ; + int delta = 0; + HANDLE hOldPal; + + /* if playing into another metafile, do direct copy */ + if (PlayIntoAMetafile(lpMR, hdc)) + goto errPlayMetaFileRecord40; + + if ((lpMR->rdSize - 3) == (magic >> 8)) + { + hSDC = hdc; + delta = 1; + } + else + { + if( (magic & 255) == (META_DIBSTRETCHBLT & 255) ) + if (UseStretchDIB(hdc, magic, lpMR)) + goto errPlayMetaFileRecord40; + + if (hSDC = CreateCompatibleDC(hdc)) + { + /* set up the memDC to have the same palette */ + hOldPal = SelectPalette(hSDC, GetCurrentObject(hdc,OBJ_PALETTE), TRUE); + + if (magic == META_DIBBITBLT) + lpDIBInfo = (LPBITMAPINFOHEADER)&lpMR->rdParm[8]; + else + lpDIBInfo = (LPBITMAPINFOHEADER)&lpMR->rdParm[10]; + + /* now create the bitmap for the MemDC and fill in the bits */ + + /* the processing for old and new format of metafiles is + different here (till hBitmap is obtained) */ + + /* new metafile version */ + hBitmap = CreateBitmapForDC (hdc,lpDIBInfo); + + if (hBitmap) + hOldObject = SelectObject (hSDC, hBitmap) ; + else + goto errPlayMetaFileRecord30 ; + } + else + goto errPlayMetaFileRecord40; + } + + if (hSDC) + { + if (magic == META_DIBBITBLT) + BitBlt(hdc, lpMR->rdParm[7 + delta], + lpMR->rdParm[6 + delta], + lpMR->rdParm[5 + delta], + lpMR->rdParm[4 + delta], + hSDC, + lpMR->rdParm[3], + lpMR->rdParm[2], + MAKELONG(lpMR->rdParm[0], lpMR->rdParm[1])); + else + StretchBlt(hdc, lpMR->rdParm[9 + delta], + lpMR->rdParm[8 + delta], + lpMR->rdParm[7 + delta], + lpMR->rdParm[6 + delta], + hSDC, + lpMR->rdParm[5], + lpMR->rdParm[4], + lpMR->rdParm[3], + lpMR->rdParm[2], + MAKELONG(lpMR->rdParm[0], lpMR->rdParm[1])); + } + + if (hSDC != hdc) + { + /* Deselect hDC's palette from memDC */ + SelectPalette(hSDC, hOldPal, TRUE); + if (SelectObject(hSDC, hOldObject)) + DeleteObject(hBitmap); +errPlayMetaFileRecord30:; + DeleteDC(hSDC); +errPlayMetaFileRecord40:; + } + } + break; + + case (META_SELECTOBJECT & 255): + { + HANDLE hObject; + + if (hObject = lpHandleTable->objectHandle[lpMR->rdParm[0]]) + SelectObject(hdc, hObject); + } + break; + + case (META_CREATEPENINDIRECT & 255): + { + #ifdef WIN32 + LOGPEN lp; + + lp.lopnStyle = lpMR->rdParm[0]; + lp.lopnWidth.x = lpMR->rdParm[1]; + lp.lopnColor = *((COLORREF *)&lpMR->rdParm[3]); + if (hObject = CreatePenIndirect(&lp)) + #else + if (hObject = CreatePenIndirect((LPLOGPEN)&lpMR->rdParm[0])) + #endif + AddToHandleTable(lpHandleTable, hObject, noObjs); + break; + } + + case (META_CREATEFONTINDIRECT & 255): + { + LOGFONT lf; + LPLOGFONT lplf = &lf; + + LOGFONT32FROM16( lplf, ((LPLOGFONT)&lpMR->rdParm[0])); + if (hObject = CreateFontIndirect(lplf)) + AddToHandleTable(lpHandleTable, hObject, noObjs); + } + break; + + case (META_CREATEPATTERNBRUSH & 255): + { + HANDLE hBitmap; + LPBITMAP lpBitmap; + + lpBitmap = (LPBITMAP)lpMR->rdParm; + + //!!!!! ALERT DWORD align on NT + if (hBitmap = CreateBitmapIndirect(lpBitmap)) + { + LPBITMAPINFO lpbmInfo; + HANDLE hmemInfo; + + hmemInfo = GlobalAlloc( GMEM_ZEROINIT | GMEM_MOVEABLE, + sizeof(BITMAPINFO) + 2<<(lpBitmap->bmPlanes*lpBitmap->bmBitsPixel)); + + lpbmInfo = (LPBITMAPINFO)GlobalLock( hmemInfo); + + lpbmInfo->bmiHeader.biPlanes = lpBitmap->bmPlanes; + lpbmInfo->bmiHeader.biBitCount = lpBitmap->bmBitsPixel; + SetDIBits( (HDC)NULL, hBitmap, 0, lpBitmap->bmHeight, + (LPBYTE)&lpMR->rdParm[8], lpbmInfo, DIB_RGB_COLORS ); + + if (hObject = CreatePatternBrush(hBitmap)) + AddToHandleTable(lpHandleTable, hObject, noObjs); + + GlobalUnlock(hmemInfo); + GlobalFree(hmemInfo); + DeleteObject(hBitmap); + } + } + break; + + case (META_DIBCREATEPATTERNBRUSH & 255): + { + HDC hMemDC ; + HANDLE hBitmap; + LPBITMAPINFOHEADER lpDIBInfo ; + WORD nDIBSize; /* number of WORDs in packed DIB */ + HANDLE hDIB; + LPWORD lpDIB; + LPWORD lpSourceDIB; + WORD i; + + + if (lpMR->rdParm[0] == BS_PATTERN) + { + /* the address of the second paramter is the address of the DIB + header, extract it */ + lpDIBInfo = (BITMAPINFOHEADER FAR *) &lpMR->rdParm[2]; + + /* now create a device dependend bitmap compatible to the default + screen DC - hScreenDC and extract the bits from the DIB into it. + The following function does all these, and returns a HANDLE + to the device dependent BItmap. */ + + /* we will use a dummy memory DC compatible to the screen DC */ + hMemDC = CreateCompatibleDC (hScreenDC) ; + + hBitmap = CreateBitmapForDC (hScreenDC,lpDIBInfo) ; + + if (hBitmap) + { + if (hObject = CreatePatternBrush(hBitmap)) + AddToHandleTable(lpHandleTable, hObject, noObjs); + DeleteObject(hBitmap); + } + + /* delete the dummy memory DC for new version Metafiles*/ + DeleteDC (hMemDC) ; + } + + /* this is a DIBPattern brush */ + else + { + /* get size of just the packed DIB */ + nDIBSize = (WORD) (lpMR->rdSize - 4); + if ((hDIB = GlobalAlloc(GMEM_DDESHARE|GMEM_MOVEABLE,(LONG)(nDIBSize << 1)))) + { + lpDIB = (WORD FAR *) GlobalLock (hDIB); + lpSourceDIB = (WORD FAR *)&lpMR->rdParm[2]; + + /* copy the DIB into our new memory block */ + for (i = 0; i < nDIBSize; i++) + *lpDIB++ = *lpSourceDIB++; + + GlobalUnlock (hDIB); + + if (hObject = CreateDIBPatternBrush(hDIB, lpMR->rdParm[1])) + AddToHandleTable(lpHandleTable, hObject, noObjs); + + GlobalFree(hDIB); + } + } + } + break; + + case (META_CREATEBRUSHINDIRECT & 255): + { + #ifdef WIN32 + LOGBRUSH lb; + + lb.lbStyle = lpMR->rdParm[0]; + lb.lbColor = *((COLORREF *)&lpMR->rdParm[1]); + lb.lbHatch = lpMR->rdParm[3]; + + if (hObject = CreateBrushIndirect(&lb)) + #else + if (hObject = CreateBrushIndirect((LPLOGBRUSH)&lpMR->rdParm[0])) + #endif + AddToHandleTable(lpHandleTable, hObject, noObjs); + break; + } + + case (META_POLYLINE & 255): + { + LPPOINT lppt; + Polyline(hdc, (lppt=CONVERTPTS(&lpMR->rdParm[1],lpMR->rdParm[0])), lpMR->rdParm[0]); + FREECONVERT(lppt); + break; + } + + case (META_POLYGON & 255): + { + LPPOINT lppt; + Polygon(hdc, (lppt=CONVERTPTS(&lpMR->rdParm[1],lpMR->rdParm[0])), lpMR->rdParm[0]); + FREECONVERT(lppt); + break; + } + + case (META_POLYPOLYGON & 255): + { + LPPOINT lppt; + #ifdef WIN32 + WORD cPts=0; + WORD ii; + + for(ii=0; ii<lpMR->rdParm[0]; ii++) + cPts += ((LPWORD)&lpMR->rdParm[1])[ii]; + #endif // WIN32 + + PolyPolygon(hdc, + (lppt=CONVERTPTS(&lpMR->rdParm[1] + lpMR->rdParm[0], cPts)), + (LPINT)&lpMR->rdParm[1], + lpMR->rdParm[0]); + FREECONVERT(lppt); + } + break; + + case (META_EXTTEXTOUT & 255): + { + LPWORD lpdx; + LPSTR lpch; + LPRECT lprt; + + lprt = (lpMR->rdParm[3] & (ETO_OPAQUE|ETO_CLIPPED)) ? (LPRECT)&lpMR->rdParm[4] : 0; + lpch = (LPSTR)&lpMR->rdParm[4] + ((lprt) ? sizeof(RECT) : 0); + + /* dx array starts at next word boundary after char string */ + lpdx = (LPWORD)(lpch + ((lpMR->rdParm[2] + 1) & 0xFFFE)); + + /* check to see if there is a Dx array by seeing if + structure ends after the string itself + */ + if ( ((DWORD)((LPWORD)lpdx - (LPWORD)(lpMR))) >= lpMR->rdSize) + lpdx = NULL; + else + lpdx = (LPWORD)CONVERTINTS((signed short FAR *)lpdx, lpMR->rdParm[2]); + + ExtTextOut(hdc, lpMR->rdParm[1], lpMR->rdParm[0], lpMR->rdParm[3], + lprt, (LPSTR)lpch, lpMR->rdParm[2], (LPINT)lpdx); + if (lpdx != (LPWORD)NULL) + FREECONVERT(lpdx); + break; + } + + case (META_TEXTOUT & 255): + TextOut(hdc, lpMR->rdParm[lpMR->rdSize-4], lpMR->rdParm[lpMR->rdSize-5], (LPSTR)&lpMR->rdParm[1], lpMR->rdParm[0]); + break; + + case (META_ESCAPE & 255): + { + LPSTR lpStuff; + + if (lpMR->rdParm[0] != MFCOMMENT) + { + lpStuff = (LPSTR)&lpMR->rdParm[2]; +#ifdef OLDEXTTEXTOUT + if (lpMR->rdParm[0] == EXTTEXTOUT) + { + EXTTEXTDATA ExtData; + + ExtData.xPos = lpMR->rdParm[2]; + ExtData.yPos = lpMR->rdParm[3]; + ExtData.cch = lpMR->rdParm[4]; + ExtData.rcClip = *((LPRECT)&lpMR->rdParm[5]); + ExtData.lpString = (LPSTR)&lpMR->rdParm[9]; + ExtData.lpWidths = (WORD FAR *)&lpMR->rdParm[9+((ExtData.cch+1)/2)]; + lpStuff = (LPSTR)&ExtData; + } +#endif + Escape(hdc, lpMR->rdParm[0], lpMR->rdParm[1], lpStuff, (LPSTR)0); + } + } + break; + + case (META_FRAMEREGION & 255): + if((hRgn = lpHandleTable->objectHandle[lpMR->rdParm[0]]) + && (hBrush = lpHandleTable->objectHandle[lpMR->rdParm[1]])) + FrameRgn(hdc, hRgn, hBrush, lpMR->rdParm[3], lpMR->rdParm[2]); + break; + + case (META_PAINTREGION & 255): + if(hRgn = lpHandleTable->objectHandle[lpMR->rdParm[0]]) + PaintRgn(hdc, hRgn); + break; + + case (META_INVERTREGION & 255): + if(hRgn = lpHandleTable->objectHandle[lpMR->rdParm[0]]) + InvertRgn(hdc, hRgn); + break; + + case (META_FILLREGION & 255): + if((hRgn = lpHandleTable->objectHandle[lpMR->rdParm[0]]) + && (hBrush = lpHandleTable->objectHandle[lpMR->rdParm[1]])) + FillRgn(hdc, hRgn, hBrush); + break; + +#ifdef DEADCODE +#ifdef GDI104 + case (META_DRAWTEXT & 255): + MFDrawText(hdc, (LPPOINT)&lpMR->rdParm[6], lpMR->rdParm[1], (LPPOINT)&lpMR->rdParm[2], lpMR->rdParm[0]); + break; +#endif +#endif + +/* +*** in win2, METACREATEREGION records contained an entire region object, +*** including the full header. this header changed in win3. +*** +*** to remain compatible, the region records will be saved with the +*** win2 header. here we read a win2 header with region, and actually +*** create a win3 header with same region internals +*/ + + case (META_CREATEREGION & 255): + { +#if 0 //!!!!! + HANDLE hRgn; + WORD *pRgn; + WORD iChar; + LPWORD *lpTemp; + + iChar = lpMR->rdSize*2 - sizeof(WIN2OBJHEAD) - RECHDRSIZE; + if (hRgn = LocalAlloc(LMEM_ZEROINIT, iChar + sizeof(ILOBJHEAD))) + + { + pRgn = (WORD *)Lock IT(hRgn); + + *((WIN2OBJHEAD *)pRgn) = *((WIN2OBJHEAD FAR *)&lpMR->rdParm[0]); + ((ILOBJHEAD *)pRgn)->ilObjMetaList = 0; + + lpTemp = (LPWORD)&(lpMR->rdParm[0]); + ((WIN2OBJHEAD FAR *)lpTemp)++; + + ((ILOBJHEAD *)pRgn)++; /* --> actual region */ + + for(i = 0; i < (iChar >> 1) ; i++) + *pRgn++ = *lpTemp++; + pRgn = (WORD *)lock IT(hRgn); + ((PRGN)pRgn)->rgnSize = iChar + sizeof(ILOBJHEAD); + + AddToHandleTable(lpHandleTable, hRgn, noObjs); + } +#endif //!!!!! + HANDLE hRgn = NULL; + HANDLE hRgn2 = NULL; + WORD cScans; + WORD cPnts; + WORD cbIncr; + LPWIN3REGION lpW3Rgn = (LPWIN3REGION)lpMR->rdParm; + LPSCAN lpScan = lpW3Rgn->aScans; + LPWORD lpXs; + + for( cScans=lpW3Rgn->cScans; cScans>0; cScans--) + { + + // If this is the first scan then hRgn2 IS the region + // otherwise OR it in + if( hRgn == NULL ) + { + // Create the first region in this scan + hRgn = CreateRectRgn( lpScan->scnPntsX[0], lpScan->scnPntTop, + lpScan->scnPntsX[1], lpScan->scnPntBottom); + + // Allocate a worker region + hRgn2 = CreateRectRgn( 1, 1, 2, 2); + } + else + { + SetRectRgn( hRgn2, lpScan->scnPntsX[0], lpScan->scnPntTop, + lpScan->scnPntsX[1], lpScan->scnPntBottom ); + CombineRgn( hRgn, hRgn, hRgn2, RGN_OR ); + } + + lpXs = &lpScan->scnPntsX[2]; + + // If there are more regions on this scan OR them in + for(cPnts = (WORD)(lpScan->scnPntCnt-2); cPnts>0; cPnts-=2) + { + SetRectRgn( hRgn2, *lpXs++, lpScan->scnPntTop, + *lpXs++, lpScan->scnPntBottom ); + + CombineRgn( hRgn, hRgn, hRgn2, RGN_OR ); + } + + cbIncr = (WORD)sizeof(SCAN) + (WORD)(lpScan->scnPntCnt-2); + cbIncr = (WORD)sizeof(WORD)*(WORD)(lpScan->scnPntCnt-2); + cbIncr = (WORD)sizeof(SCAN) + (WORD)sizeof(WORD)*(WORD)(lpScan->scnPntCnt-2); + cbIncr = (WORD)sizeof(SCAN) + (WORD)(sizeof(WORD)*(lpScan->scnPntCnt-2)); + lpScan = (LPSCAN)((LPBYTE)lpScan + cbIncr); + } + + if( hRgn2 != NULL ) + DeleteObject( hRgn2 ); + + AddToHandleTable(lpHandleTable, hRgn, noObjs); + } + break; + + case (META_DELETEOBJECT & 255): + { + HANDLE h; + + if (h = lpHandleTable->objectHandle[lpMR->rdParm[0]]) + { + DeleteObjectPriv(h); + lpHandleTable->objectHandle[lpMR->rdParm[0]] = NULL; + } + } + break; + + case (META_CREATEPALETTE & 255): + if (hObject = CreatePalette((LPLOGPALETTE)&lpMR->rdParm[0])) + AddToHandleTable(lpHandleTable, hObject, noObjs); + break; + + case (META_SELECTPALETTE & 255): + if(hPal = lpHandleTable->objectHandle[lpMR->rdParm[0]]) + { + SelectPalette(hdc, hPal, 0); + } + break; + + case (META_REALIZEPALETTE & 255): + RealizePalette(hdc); + break; + + case (META_SETPALENTRIES & 255): + /* we know the palette being set is the current palette */ + SetPaletteEntriesPriv(GetCurrentObject(hdc,OBJ_PALETTE), lpMR->rdParm[0], + lpMR->rdParm[1], (LPPALETTEENTRY)&lpMR->rdParm[2]); + break; + + case (META_ANIMATEPALETTE & 255): + AnimatePalettePriv(GetCurrentObject(hdc,OBJ_PALETTE), lpMR->rdParm[0], + lpMR->rdParm[1], (LPPALETTEENTRY)&lpMR->rdParm[2]); + + break; + + case (META_RESIZEPALETTE & 255): + ResizePalettePriv(GetCurrentObject(hdc,OBJ_PALETTE), lpMR->rdParm[0]); + break; + + case (META_SETDIBTODEV & 255): + { + LPBITMAPINFOHEADER lpBitmapInfo; + WORD ColorSize; + + /* if playing into another metafile, do direct copy */ + if (PlayIntoAMetafile(lpMR, hdc)) + goto DontReallyPlay; + + lpBitmapInfo = (LPBITMAPINFOHEADER)&(lpMR->rdParm[9]); + + if (lpBitmapInfo->biClrUsed) + { + ColorSize = ((WORD)lpBitmapInfo->biClrUsed) * + (WORD)(lpMR->rdParm[0] == DIB_RGB_COLORS ? + sizeof(RGBQUAD) : + sizeof(WORD)); + } + else if (lpBitmapInfo->biBitCount == 24) + ColorSize = 0; + else + ColorSize = (WORD)(1 << lpBitmapInfo->biBitCount) * + (WORD)(lpMR->rdParm[0] == DIB_RGB_COLORS ? + sizeof(RGBQUAD) : + sizeof(WORD)); + + ColorSize += sizeof(BITMAPINFOHEADER); + + SetDIBitsToDevice(hdc, lpMR->rdParm[8], lpMR->rdParm[7], + lpMR->rdParm[6], lpMR->rdParm[5], + lpMR->rdParm[4], lpMR->rdParm[3], + lpMR->rdParm[2], lpMR->rdParm[1], + (BYTE FAR *)(((BYTE FAR *)lpBitmapInfo) + ColorSize), + (LPBITMAPINFO) lpBitmapInfo, + lpMR->rdParm[0]); +DontReallyPlay:; + } + break; + + case (META_STRETCHDIB & 255): + { + LPBITMAPINFOHEADER lpBitmapInfo; + WORD ColorSize; + + /* if playing into another metafile, do direct copy */ + if (PlayIntoAMetafile(lpMR, hdc)) + goto DontReallyPlay2; + + lpBitmapInfo = (LPBITMAPINFOHEADER)&(lpMR->rdParm[11]); + + if (lpBitmapInfo->biClrUsed) + { + ColorSize = ((WORD)lpBitmapInfo->biClrUsed) * + (WORD)(lpMR->rdParm[2] == DIB_RGB_COLORS ? + sizeof(RGBQUAD) : + sizeof(WORD)); + } + else if (lpBitmapInfo->biBitCount == 24) + ColorSize = 0; + else + ColorSize = (WORD)(1 << lpBitmapInfo->biBitCount) * + (WORD)(lpMR->rdParm[2] == DIB_RGB_COLORS ? + sizeof(RGBQUAD) : + sizeof(WORD)); + + ColorSize += sizeof(BITMAPINFOHEADER); + + StretchDIBits(hdc, lpMR->rdParm[10], lpMR->rdParm[9], + lpMR->rdParm[8], lpMR->rdParm[7], + lpMR->rdParm[6], lpMR->rdParm[5], + lpMR->rdParm[4], lpMR->rdParm[3], + (LPBYTE)(((BYTE FAR *)lpBitmapInfo) + ColorSize), + (LPBITMAPINFO) lpBitmapInfo, + lpMR->rdParm[2], + MAKELONG(lpMR->rdParm[1], lpMR->rdParm[0])); +DontReallyPlay2:; + } + break; + +// Function that have new parameters on WIN32 +// Or have DWORDs that stayed DWORDs; all other INTs to DWORDs +#ifdef WIN32 + case (META_MOVETO & 255): + MoveTo( hdc, (long)lpMR->rdParm[1], (long)lpMR->rdParm[0], NULL ); + break; + + case (META_RESTOREDC & 255): + RestoreDC( hdc, (long)(signed short)lpMR->rdParm[0] ); + break; + + case (META_SETBKCOLOR & 255): + SetBkColor( hdc, (UINT)*((LPDWORD)lpMR->rdParm) ); + break; + + case (META_SETTEXTCOLOR & 255): + SetTextColor( hdc, (UINT)*((LPDWORD)lpMR->rdParm) ); + break; + + case (META_SETPIXEL & 255): + SetPixel( hdc, (UINT)lpMR->rdParm[3], (UINT)lpMR->rdParm[2], + (UINT)*((LPDWORD)lpMR->rdParm) ); + break; + + case (META_SETMAPPERFLAGS & 255): + SetMapperFlags( hdc, (UINT)*((LPDWORD)lpMR->rdParm) ); + break; + + case (META_FLOODFILL & 255): + FloodFill( hdc, (UINT)lpMR->rdParm[3], (UINT)lpMR->rdParm[2], + (UINT)*((LPDWORD)lpMR->rdParm) ); + break; + + case (META_EXTFLOODFILL & 255): + ExtFloodFill( hdc, (UINT)lpMR->rdParm[4], (UINT)lpMR->rdParm[3], + (UINT)*((LPDWORD)&lpMR->rdParm[1]), (UINT)lpMR->rdParm[0] ); + break; + + // These puppies all got a new NULL and have only two parameters and a DC. + case (META_SETWINDOWORG & 255): + case (META_SETWINDOWEXT & 255): + case (META_SETVIEWPORTORG & 255): + case (META_SETVIEWPORTEXT & 255): + case (META_OFFSETWINDOWORG & 255): + case (META_SCALEWINDOWEXT & 255): + case (META_OFFSETVIEWPORTORG & 255): + case (META_SCALEVIEWPORTEXT & 255): + { + FARPROC lpProc; + + ASSERTGDI((magic&0x00ff) <= MAX_META_DISPATCH, "Unknown function to dispatch1"); + + lpProc = alpfnMetaFunc[magic&0x00ff]; + + ASSERTGDI( lpProc != (FARPROC)NULL, "function not in dispatch table1 "); + + if (lpProc != (FARPROC)NULL) + (*lpProc)(hdc, (long)(short)lpMR->rdParm[1], (long)(short)lpMR->rdParm[0], NULL ); + } + break; +#endif // WIN32 + + default: + { + FARPROC lpProc; + signed short *pshort; + + ASSERTGDI((magic&0x00ff) <= MAX_META_DISPATCH, "Unknown function to dispatch"); + + lpProc = alpfnMetaFunc[magic&0x00ff]; + + ASSERTGDI( (lpProc != (FARPROC)NULL) || (magic == META_SETRELABS), "function not in dispatch table"); + + if ((lpProc == (FARPROC)NULL)) + return; + + // Switch to the corresponding dispatcher by number of parameters + // The number of parameters in the dispatch number does not include the DC. + switch (magic >> 8) + { + typedef int (FAR PASCAL *META1PROC)(HDC); + typedef int (FAR PASCAL *META2PROC)(HDC, int); + typedef int (FAR PASCAL *META3PROC)(HDC, int, int); + typedef int (FAR PASCAL *META4PROC)(HDC, int, int, int); + typedef int (FAR PASCAL *META5PROC)(HDC, int, int, int, int); + typedef int (FAR PASCAL *META6PROC)(HDC, int, int, int, int, int); + typedef int (FAR PASCAL *META7PROC)(HDC, int, int, int, int, int, int); + typedef int (FAR PASCAL *META9PROC)(HDC, int, int, int, int, int, int, int, int); + + case 0: + (*((META1PROC)lpProc))(hdc); + break; + case 1: + (*((META2PROC)lpProc))(hdc,lpMR->rdParm[0]); + break; + case 2: + (*((META3PROC)lpProc))(hdc,lpMR->rdParm[1],lpMR->rdParm[0]); + break; + case 3: + (*((META4PROC)lpProc))(hdc,lpMR->rdParm[2],lpMR->rdParm[1],lpMR->rdParm[0]); + break; + case 4: + (*((META5PROC)lpProc))(hdc,lpMR->rdParm[3],lpMR->rdParm[2],lpMR->rdParm[1],lpMR->rdParm[0]); + break; + case 5: + (*((META6PROC)lpProc))(hdc,lpMR->rdParm[4],lpMR->rdParm[3],lpMR->rdParm[2],lpMR->rdParm[1],lpMR->rdParm[0]); + break; + case 6: + (*((META7PROC)lpProc))(hdc,lpMR->rdParm[5],lpMR->rdParm[4],lpMR->rdParm[3],lpMR->rdParm[2],lpMR->rdParm[1],lpMR->rdParm[0]); + break; + case 8: + (*((META9PROC)lpProc))(hdc,lpMR->rdParm[7],lpMR->rdParm[6],lpMR->rdParm[5],lpMR->rdParm[4],lpMR->rdParm[3],lpMR->rdParm[2],lpMR->rdParm[1],lpMR->rdParm[0]); + break; + + default: + ASSERTGDI( FALSE, "No dispatch for this count of args"); + break; + } + } + break; + } +#ifndef WIN32 + if (bExtraSel) + FreeSelector(HIWORD(lpMR)); +#endif // WIN32 +} + +#endif // this is going to gdi.dll + +/****************************** Internal Function **************************\ +* AddToHandleTable +* +* Adds an object to the metafile table of objects +* +* +\***************************************************************************/ + +VOID INTERNAL AddToHandleTable(LPHANDLETABLE lpHandleTable, HANDLE hObject, WORD noObjs) +{ + WORD i; + + GdiLogFunc3( " AddToHandleTable"); + + /* linear search through table for first open slot */ + for (i = 0; ((lpHandleTable->objectHandle[i] != NULL) && (i < noObjs)); + ++i); + + if (i < noObjs) /* ok index */ + lpHandleTable->objectHandle[i] = hObject; + else + { + ASSERTGDI( 0, "Too many objects in table"); + FatalExit(METAEXITCODE); /* Why can't we store the handle? */ + } +} + + +/****************************** Internal Function **************************\ +* GetFileNumber +* +* Returns the DOS file number for a metafiles file +* -1 if failure +* +\***************************************************************************/ + +UINT INTERNAL GetFileNumber(LPMETAFILE lpMF) +{ + int fileNumber; + + GdiLogFunc3( " GetFileNumber"); + + if (!(fileNumber = lpMF->MetaFileNumber)) + { + if ((fileNumber = OpenFile((LPSTR) lpMF->MetaFileBuffer.szPathName, + (LPOFSTRUCT) &(lpMF->MetaFileBuffer), + (WORD)OF_PROMPT | OF_REOPEN | OF_READ) + ) != -1) + { + _llseek(fileNumber, (long)lpMF->MetaFilePosition, 0); + + /* need to update MetaFileNumber for floppy files -- amitc */ + lpMF->MetaFileNumber = fileNumber ; + } + } + + return fileNumber; +} + +#if 0 +/****************************** Internal Function **************************\ +* IsValidMetaFile(HANDLE hMetaData) +* +* Validates a metafile +* +* Returns TRUE iff hMetaData is a valid metafile +* +\***************************************************************************/ + +BOOL GDIENTRY IsValidMetaFile(HANDLE hMetaData) +{ + LPMETADATA lpMetaData; + BOOL status = FALSE; + + GdiLogFunc3( " IsValidMetaFile"); + + /* if this is a valid metafile we will save the version in a global variable */ + + if (hMetaData && (lpMetaData = (LPMETADATA) GlobalLock(hMetaData))) + { + status = ( + (lpMetaData->dataHeader.mtType == MEMORYMETAFILE || + lpMetaData->dataHeader.mtType == DISKMETAFILE) && + (lpMetaData->dataHeader.mtHeaderSize == HEADERSIZE) && + ((lpMetaData->dataHeader.mtVersion ==METAVERSION) || + (lpMetaData->dataHeader.mtVersion ==METAVERSION100)) + ); + GlobalUnlock(hMetaData); + } + return status; +} +#endif + +#define INITIALBUFFERSIZE 16384 + +/****************************** Internal Function **************************\ +* +* AllocBuffer - Allocates a buffer as "large" as possible +* +\***************************************************************************/ + +HANDLE INTERNAL AllocBuffer(LPWORD piBufferSize) +{ + WORD iCurBufferSize = INITIALBUFFERSIZE; + HANDLE hBuffer; + + GdiLogFunc3( " AllocBuffer"); + + while (!(hBuffer = GlobalAlloc(GMEM_MOVEABLE | + GMEM_NODISCARD, (LONG) iCurBufferSize)) + && iCurBufferSize) + iCurBufferSize >>= 1; + + *piBufferSize = iCurBufferSize; + return (iCurBufferSize) ? hBuffer : NULL; +} + + +/****************************** Internal Function **************************\ +* CreateBitmapForDC (HDC hMemDC, LPBITMAPINFOHEADER lpDIBInfo) +* +* This routine takes a memory device context and a DIB bitmap, creates a +* compatible bitmap for the DC and fills it with the bits from the DIB (co- +* -nverting to the device dependent format). The pointer to the DIB bits +* start immediately after the color table in the INFO header. ** +* ** +* The routine returns the handle to the bitmap with the bits filled in if +* everything goes well else it returns NULL. ** +\***************************************************************************/ + +HANDLE INTERNAL CreateBitmapForDC (HDC hMemDC, LPBITMAPINFOHEADER lpDIBInfo) +{ + HBITMAP hBitmap ; + LPBYTE lpDIBits ; + + GdiLogFunc3( " CreateBitmapForDC"); + + /* preserve monochrome if it started out as monochrome + ** and check for REAL Black&white monochrome as opposed + ** to a 2-color DIB + */ + if (IsDIBBlackAndWhite(lpDIBInfo)) + hBitmap = CreateBitmap ((WORD)lpDIBInfo->biWidth, + (WORD)lpDIBInfo->biHeight, + 1, 1, (LPBYTE) NULL); + else + /* otherwise, make a compatible bitmap */ + hBitmap = CreateCompatibleBitmap (hMemDC, + (WORD)lpDIBInfo->biWidth, + (WORD)lpDIBInfo->biHeight); + + if (!hBitmap) + goto CreateBitmapForDCErr ; + + /* take a pointer past the header of the DIB, to the start of the color + table */ + lpDIBits = (LPBYTE) lpDIBInfo + sizeof (BITMAPINFOHEADER) ; + + /* take the pointer past the color table */ + lpDIBits += GetSizeOfColorTable (lpDIBInfo) ; + + /* get the bits from the DIB into the Bitmap */ + if (!SetDIBits (hMemDC, hBitmap, 0, (WORD)lpDIBInfo->biHeight, + lpDIBits, (LPBITMAPINFO)lpDIBInfo, 0)) + { + DeleteObject(hBitmap); + goto CreateBitmapForDCErr ; + } + + /* return success */ + return (hBitmap) ; + +CreateBitmapForDCErr: + + /* returm failure for function */ + return (NULL) ; +} + + +/****************************** Internal Function **************************\ +* GetSizeOfColorTable (LPBITMAPINFOHEADER lpDIBInfo) +* +* Returns the number of bytes in the color table for the giving info header +* +\***************************************************************************/ + +WORD INTERNAL GetSizeOfColorTable (LPBITMAPINFOHEADER lpDIBInfo) +{ + + GdiLogFunc3( "GetSizeOfColorTable"); + + if (lpDIBInfo->biClrUsed) + return((WORD)lpDIBInfo->biClrUsed * (WORD)sizeof(RGBQUAD)); + else + { + switch (lpDIBInfo->biBitCount) + { + case 1: + return (2 * sizeof (RGBQUAD)) ; + break ; + case 4: + return (16 * sizeof (RGBQUAD)) ; + break ; + case 8: + return (256 * sizeof (RGBQUAD)) ; + break ; + default: + return (0) ; + break ; + } + } +} + +#if 0 // this is going to gdi.dll + +/***************************** Public Function ****************************\ +* BOOL APIENTRY DeleteMetaFile(hmf) +* +* Frees a metafile handle. +* +* Effects: +* +\***************************************************************************/ + +BOOL GDIENTRY DeleteMetaFile(HMETAFILE hmf) +{ + GdiLogFunc("DeleteMetaFile"); + + GlobalFree(hmf); + + return(TRUE); +} + + +/***************************** Public Function ****************************\ +* HMETAFILE APIENTRY GetMetaFile(pzFilename) +* +* Returns a metafile handle for a disk based metafile. +* +* Effects: +* +* History: +* Sat 14-Oct-1989 14:21:37 -by- Paul Klingler [paulk] +* Wrote it. +\***************************************************************************/ + +HMETAFILE GDIENTRY GetMetaFile(LPSTR pzFilename) +{ + BOOL status=FALSE; + UINT cBytes; + int file; + HMETAFILE hmf; + LPMETAFILE lpmf; + + GdiLogFunc("GetMetaFile"); + + // Allocate the Metafile + if(hmf = GlobalAlloc(GMEM_DDESHARE|GMEM_MOVEABLE,(DWORD)sizeof(METAFILE))) + { + lpmf = (LPMETAFILE)GlobalLock(hmf); + + // Make sure the file Exists + if((file = OpenFile(pzFilename, + &(lpmf->MetaFileBuffer), + (WORD)OF_PROMPT | OF_EXIST)) == -1L) + { + ASSERTGDI( FALSE, "GetMetaFile: Metafile does not exist"); + goto exitGetMetaFile; + } + + // Open the file + if((file = OpenFile(pzFilename, + &(lpmf->MetaFileBuffer), + (WORD)OF_PROMPT | OF_REOPEN | OF_READWRITE)) == -1) + { + ASSERTGDI( FALSE, "GetMetaFile: Unable to open Metafile"); + goto exitGetMetaFile; + } + + cBytes = (UINT)_lread(file,(LPSTR)(&(lpmf->MetaFileHeader)),sizeof(METAHEADER)); + + // Check for an Aldus header + if (*((LPDWORD)&(lpmf->MetaFileHeader)) == 0x9AC6CDD7) + { + + _llseek( file, 22, 0); + cBytes = (UINT)_lread(file,(LPSTR)(&(lpmf->MetaFileHeader)),sizeof(METAHEADER)); + } + + _lclose(file); + + // Validate the metafile + if(cBytes == sizeof(METAHEADER)) + { + lpmf->MetaFileHeader.mtType = DISKMETAFILE; + status = TRUE; + } + + exitGetMetaFile: + GlobalUnlock(hmf); + } + + if(status == FALSE) + { + GlobalFree(hmf); + hmf = NULL; + } + + return(hmf); +} +#endif // this is going to gdi.dll + +#ifdef WIN32 +#undef GetViewportExt +DWORD GetViewportExt32(HDC hdc) +{ + SIZE sz; + GetViewportExt( hdc, &sz ); + return(MAKELONG(LOWORD(sz.cx),LOWORD(sz.cy))); +} + +#undef GetWindowExt +DWORD GetWindowExt32(HDC hdc) +{ + SIZE sz; + GetWindowExt( hdc, &sz ); + return(MAKELONG(LOWORD(sz.cx),LOWORD(sz.cy))); +} + +#undef SetViewportExt +DWORD SetViewportExt32(HDC hdc, UINT x, UINT y) +{ + SIZE sz; + SetViewportExt( hdc, x, y, &sz ); + return(MAKELONG(LOWORD(sz.cx),LOWORD(sz.cy))); +} + +#undef SetWindowExt +DWORD SetWindowExt32(HDC hdc, UINT x, UINT y) +{ + SIZE sz; + SetWindowExt( hdc, x, y, &sz ); + return(MAKELONG(LOWORD(sz.cx),LOWORD(sz.cy))); +} + +/* Convert WORD arrays into DWORDs */ +LPINT ConvertInts( signed short * pWord, UINT cWords ) +{ + UINT ii; + LPINT pInt; + + pInt = (LPINT)LocalAlloc( LMEM_FIXED, cWords * sizeof(UINT)); + + for( ii=0; ii<cWords; ii++) + { + pInt[ii] = (long)(signed)pWord[ii]; + } + + return(pInt); +} + +#endif // WIN32 diff --git a/private/mvdm/wow16/gdi/metacons.inc b/private/mvdm/wow16/gdi/metacons.inc new file mode 100644 index 000000000..e3071a538 --- /dev/null +++ b/private/mvdm/wow16/gdi/metacons.inc @@ -0,0 +1,90 @@ +;++ +; +; WOW v1.0 +; +; Copyright (c) 1991, Microsoft Corporation +; +; MetaCons.inc +; Windows.h Metafile Constants +; +; History: +; +; Created 28-May-1991 by John Colleran (johnc) +; Derived from Windows.h (using h2inc was not successful over the whole file) +;-- + + +METASETBKCOLOR EQU 0201H +METASETBKMODE EQU 0102H +METASETMAPMODE EQU 0103H +METASETROP2 EQU 0104H +METASETRELABS EQU 0105H +METASETPOLYFILLMODE EQU 0106H +METASETSTRETCHBLTMODE EQU 0107H +METASETTEXTCHAREXTRA EQU 0108H +METASETTEXTCOLOR EQU 0209H +METASETTEXTJUSTIFICATION EQU 020aH +MFCOMMENT EQU 15 +METASETWINDOWORG EQU 020bH +METASETWINDOWEXT EQU 020cH +METASETVIEWPORTORG EQU 020dH +METASETVIEWPORTEXT EQU 020eH +METAOFFSETWINDOWORG EQU 020fH +METASCALEWINDOWEXT EQU 0400H +METAOFFSETVIEWPORTORG EQU 0211H +METASCALEVIEWPORTEXT EQU 0412H +METALINETO EQU 0213H +METAMOVETO EQU 0214H +METAEXCLUDECLIPRECT EQU 0415H +METAINTERSECTCLIPRECT EQU 0416H +METAARC EQU 0817H +METAELLIPSE EQU 0418H +METAFLOODFILL EQU 0419H +METAPIE EQU 081aH +METARECTANGLE EQU 041bH +METAROUNDRECT EQU 061cH +METAPATBLT EQU 061dH +METASAVEDC EQU 001eH +METASETPIXEL EQU 041fH +METAOFFSETCLIPRGN EQU 0220H +METATEXTOUT EQU 0521H +METABITBLT EQU 0922H +METASTRETCHBLT EQU 0b23H +METAPOLYGON EQU 0324H +METAPOLYLINE EQU 0325H +METAESCAPE EQU 0626H +METARESTOREDC EQU 0127H +METAFILLREGION EQU 0228H +METAFRAMEREGION EQU 0529H +METAINVERTREGION EQU 012aH +METAPAINTREGION EQU 012bH +METASELECTCLIPREGION EQU 012cH +METASELECTOBJECT EQU 012dH +METASETTEXTALIGN EQU 012eH +METADRAWTEXT EQU 062fH +METACHORD EQU 0830H +METASETMAPPERFLAGS EQU 0231H +METAEXTTEXTOUT EQU 0a32H +METASETDIBTODEV EQU 0d33H +METASELECTPALETTE EQU 0234H +METAREALIZEPALETTE EQU 0035H +METAANIMATEPALETTE EQU 0436H +METASETPALENTRIES EQU 0037H +METAPOLYPOLYGON EQU 0538H +METARESIZEPALETTE EQU 0139H +METADIBBITBLT EQU 0940H +METADIBSTRETCHBLT EQU 0b41H +METADIBCREATEPATTERNBRUSH EQU 0142H +METASTRETCHDIB EQU 0f43H +METAPMMETAFILE EQU 0ff44H +METAEXTFLOODFILL EQU 0548H +METADELETEOBJECT EQU 01f0H +METACREATEPALETTE EQU 00f7H +METACREATEBRUSH EQU 00f8H +METACREATEPATTERNBRUSH EQU 01f9H +METACREATEPENINDIRECT EQU 02faH +METACREATEFONTINDIRECT EQU 02fbH +METACREATEBRUSHINDIRECT EQU 02fcH +METACREATEBITMAPINDIRECT EQU 02fdH +METACREATEBITMAP EQU 06feH +METACREATEREGION EQU 06ffH diff --git a/private/mvdm/wow16/gdi/metarec.c b/private/mvdm/wow16/gdi/metarec.c new file mode 100644 index 000000000..60708c9cc --- /dev/null +++ b/private/mvdm/wow16/gdi/metarec.c @@ -0,0 +1,2325 @@ +/****************************** Module Header ******************************\ +* +* Module Name: MetaRec.c +* +* +* DESCRIPTIVE NAME: Metafile Recorder +* +* FUNCTION: Records GDI functions in memory and disk metafiles. +* +* PUBLIC ENTRY POINTS: +* CloseMetaFile +* CopyMetaFile +* CreateMetaFile +* GetMetaFileBits +* SetMetaFileBits +* PRIVATE ENTRY POINTS: +* RecordParms +* AttemptWrite +* MarkMetaFile +* RecordOther +* RecordObject +* ProbeSize +* AddToTable +* +* History: +* 02-Jul-1991 -by- John Colleran [johnc] +* Combined From Win 3.1 and WLO 1.0 sources +\***************************************************************************/ + +#include <windows.h> +#include <drivinit.h> +#include "gdi16.h" + +#define SP_OUTOFDISK (-4) /* simply no disk to spool */ + +extern HANDLE hStaticBitmap ; // MetaSup.c +extern METACACHE MetaCache; // Meta.c +extern HDC hScreenDC; + + +WORD INTERNAL AddToTable(HANDLE hMF, HANDLE hObject, LPWORD position, BOOL bRealAdd); +HANDLE INTERNAL AllocateSpaceForDIB (LPBITMAP, LPBYTE, LPWORD, LPDWORD); +BOOL INTERNAL AttemptWrite(HANDLE, WORD, DWORD, BYTE huge *); +BOOL INTERNAL CopyFile(LPSTR lpSFilename, LPSTR lpDFilename); +LPWORD INTERNAL InitializeDIBHeader (LPBITMAPINFOHEADER, LPBITMAP, BYTE, WORD); +VOID INTERNAL MarkMetaFile(HANDLE hMF); +HANDLE INTERNAL ProbeSize(NPMETARECORDER pMF, DWORD dwLength); + +HANDLE hFirstMetaFile = 0; // Linked list of all open MetaFiles + + +/**************************************************************************** +* * +* RecordParms * +* * +* Parameters: 1.hMF handle to a metafile header. * +* 2.The magic number of the function being recorded. * +* 3.The number of parmmeter of the function (size of lpParm * +* in words) * +* 4.A long pointer to parameters stored in reverse order * +* * +****************************************************************************/ + +BOOL INTERNAL RecordParms(HANDLE hdc, WORD magic, DWORD count, LPWORD lpParm) +{ + BOOL status = FALSE; + DWORD i; + DWORD dwLength; + HPWORD hpwSpace; + HPWORD hpHugeParm; + LPWORD lpCache; + HANDLE hSpace; + WORD fileNumber; + METARECORD recPair; + HANDLE hMF; + + NPMETARECORDER npMF; + + dprintf( 6," RecordParms 0x%X", magic); + + hpHugeParm = (HPWORD)lpParm; + + // Validate the metafile handle + + if(npMF = (NPMETARECORDER)LocalLock(HANDLEFROMMETADC(hdc))) + { + if(npMF->metaDCHeader.ident != ID_METADC ) + { + LocalUnlock(HANDLEFROMMETADC(hdc)); + ASSERTGDI( FALSE, "RecordParms: invalid metafile ID"); + return(FALSE); + } + } + else + { + ASSERTGDI( FALSE, "RecordParms: invalid metafile"); + return(FALSE); + } + + hMF = HANDLEFROMMETADC(hdc); + + if (!(npMF->recFlags & METAFILEFAILURE)) + { + if (npMF->recordHeader.mtType == MEMORYMETAFILE) + { + if (hSpace = ProbeSize(npMF, dwLength = count + RECHDRSIZE / 2)) + { + hpwSpace = (HPWORD) GlobalLock(hSpace); + + hpwSpace = (HPWORD) ((LPMETADATA) hpwSpace)->metaDataStuff; + hpwSpace = hpwSpace + npMF->recFilePosition; + + // write length out at a pair of words because we + // are not DWORD aligned, so we can't use "DWORD huge *" + + *hpwSpace++ = LOWORD(dwLength); + *hpwSpace++ = HIWORD(dwLength); + + *hpwSpace++ = magic; + for (i = 0; i < count; ++i) + *hpwSpace++ = *hpHugeParm++; + npMF->recFilePosition += dwLength; + GlobalUnlock(hSpace); + } + else + { + goto Exit_RecordParms; + } + } + else if (npMF->recordHeader.mtType == DISKMETAFILE) + { + dwLength = count + RECHDRSIZE / 2; + if (npMF->recFileBuffer.fFixedDisk) + { + fileNumber = npMF->recFileNumber; + } + else + { + if ((fileNumber = + OpenFile((LPSTR)npMF->recFileBuffer.szPathName, + (LPOFSTRUCT)&(npMF->recFileBuffer), + OF_PROMPT|OF_REOPEN|READ_WRITE)) + == -1) + { + goto Exit_RecordParms; + } + _llseek(fileNumber, (LONG) 0, 2); + } + + if (hMF == MetaCache.hMF) + { + lpCache = (LPWORD) GlobalLock(MetaCache.hCache); + if (dwLength + MetaCache.wCachePos >= MetaCache.wCacheSize) + { + if (!AttemptWrite(hdc, + fileNumber, + (DWORD)(MetaCache.wCachePos << 1), + (BYTE huge *) lpCache)) + { + MarkMetaFile(hMF); + GlobalUnlock(MetaCache.hCache); + goto Exit_RecordParms; + } + MetaCache.wCachePos = 0; + + if (dwLength >= MetaCache.wCacheSize) + { + GlobalUnlock(MetaCache.hCache); + goto NOCACHE; + } + } + + lpCache += MetaCache.wCachePos; + + *((LPDWORD) lpCache)++ = dwLength; + *lpCache++ = magic; + + for (i = 0; i < count; ++i) + *lpCache++ = *lpParm++; + + MetaCache.wCachePos += dwLength; + GlobalUnlock(MetaCache.hCache); + } + else + { +NOCACHE: + recPair.rdSize = dwLength; + recPair.rdFunction = magic; + if (!AttemptWrite(hdc, + fileNumber, + (DWORD)RECHDRSIZE, + (BYTE huge *) &recPair)) + { + goto Exit_RecordParms; + } + if (count) + { + if (!AttemptWrite(hdc, + fileNumber, + (DWORD)(count * sizeof(WORD)), + (BYTE huge *) lpParm)) + { + goto Exit_RecordParms; + } + } + } + if (!(npMF->recFileBuffer.fFixedDisk)) + _lclose(fileNumber); + } + } + + if (npMF->recordHeader.mtMaxRecord < dwLength) + npMF->recordHeader.mtMaxRecord = dwLength; + + npMF->recordHeader.mtSize += dwLength; + status = TRUE; + +Exit_RecordParms: + if (status == FALSE) + { + ASSERTGDI( FALSE, "RecordParms: failing"); + MarkMetaFile(hMF); + } + + LocalUnlock(HANDLEFROMMETADC(hdc)); + + return(status); + +} /* RecordParms */ + + +/***************************** Internal Function ***************************\ +* AttempWrite +* +* Tries to write data to a metafile disk file +* +* Returns TRUE iff the write was sucessful +* +* +\***************************************************************************/ + +BOOL INTERNAL AttemptWrite(hdc, fileNumber, dwBytes, lpData) +HANDLE hdc; +DWORD dwBytes; +WORD fileNumber; +HPBYTE lpData; +{ + WORD cShort; + WORD cbWritten; + WORD cBytes; + + + GdiLogFunc2( " AttemptWrite" ); + + while(dwBytes > 0) + { + cBytes = (dwBytes > MAXFILECHUNK ? MAXFILECHUNK : (WORD) dwBytes); + + if ((cbWritten = _lwrite(fileNumber, (LPSTR)lpData, cBytes)) != cBytes) + { + cShort = cBytes - cbWritten; + lpData += cbWritten; + + ASSERTGDI( 0, "Disk full?"); +// !!!!! handle disk full -- diskAvailable + + if( !IsMetaDC(hdc) ) + return(FALSE); + } + + /* how many bytes are left? */ + dwBytes -= cBytes; + lpData += cbWritten; + } + return(TRUE); +} + + +/***************************** Internal Function ***************************\ +* VOID INTERNAL MarkMetaFile(hmr) +* +* Marks a metafile as failed +* +* Effects: +* Frees the metafile resources +* +\***************************************************************************/ + +VOID INTERNAL MarkMetaFile(HANDLE hMF) +{ + NPMETARECORDER npMF; + + GdiLogFunc2( " MarkMetaFile" ); + + npMF = (NPMETARECORDER) NPFROMMETADC(hMF); + npMF->recFlags |= METAFILEFAILURE; + + if (npMF->recordHeader.mtType == MEMORYMETAFILE) + { + if (npMF->hMetaData) + GlobalFree(npMF->hMetaData); + } + else if (npMF->recordHeader.mtType == DISKMETAFILE) + { + if (npMF->recFileBuffer.fFixedDisk) + _lclose(npMF->recFileNumber); + + OpenFile((LPSTR) npMF->recFileBuffer.szPathName, + (LPOFSTRUCT) &(npMF->recFileBuffer), + OF_PROMPT|OF_DELETE); + } +} + + +/***************************** Internal Function **************************\ +* MakeLogPalette +* +* Records either CreatePalette or SetPaletteEntries +* +* Returns +* +* +\***************************************************************************/ + +WORD NEAR MakeLogPalette(HANDLE hMF, HANDLE hPal, WORD magic) +{ + WORD cPalEntries; + WORD status = 0xFFFF; + HANDLE hSpace; + WORD cbPalette; + LPLOGPALETTE lpPalette; + + GdiLogFunc2( " MakeLogPalette" ); + + cPalEntries = GetObject( hPal, 0, NULL ); + + /* alloc memory and get the palette entries */ + if (hSpace = GlobalAlloc(GMEM_DDESHARE|GMEM_MOVEABLE, + cbPalette = sizeof(LOGPALETTE)+sizeof(PALETTEENTRY)*(cPalEntries))) + { + lpPalette = (LPLOGPALETTE)GlobalLock(hSpace); + + lpPalette->palNumEntries = cPalEntries; + + GetPaletteEntries( hPal, 0, cPalEntries, lpPalette->palPalEntry); + + if (magic == (META_CREATEPALETTE & 255)) + { + lpPalette->palVersion = 0x300; + magic = META_CREATEPALETTE; + } + else if (magic == (META_SETPALENTRIES & 255)) + { + lpPalette->palVersion = 0; /* really "starting index" */ + magic = META_SETPALENTRIES; + } + + status = RecordParms(hMF, magic, (DWORD)cbPalette >> 1, (LPWORD)lpPalette); + + GlobalUnlock(hSpace); + GlobalFree(hSpace); + } + + return(status); +} + + +/**************************************************************************** +* * +* Routine: RecordOther, records parameters for certain "hard functions" * +* * +* Parameters: 1. hMF handle to a metafile header. * +* 2. The magic number of the function being recorded. * +* 3. The number of parmmeter of the function (size of lpParm * +* in words) * +* 4. A long pointer to parameters stored in reverse order * +* * +****************************************************************************/ + +BOOL INTERNAL RecordOther(HDC hdc, WORD magic, WORD count, LPWORD lpParm) +{ + NPMETARECORDER npMF; + WORD buffer[5]; + WORD i; + WORD status = FALSE; + WORD iChar; + WORD position; + HANDLE hSpace = NULL; + WORD iWords; + LPWORD lpSpace; + LPWORD lpTemp; + HANDLE hMF; + + dprintf( 6," RecordOther 0x%X", magic); + + if ((hMF = GetPMetaFile(hdc)) != -1 ) + { + // Handle functions with no DC. + if( hMF == 0 ) + { + HANDLE hmfSearch = hFirstMetaFile; + + // Play these records into all active metafiles + while( hmfSearch ) + { + npMF = (NPMETARECORDER)LocalLock( hmfSearch ); + if (!(npMF->recFlags & METAFILEFAILURE)) + { + switch (magic & 255) + { + case (META_ANIMATEPALETTE & 255): + { + HANDLE hSpace; + LPSTR lpSpace; + LPSTR lpHolder; + WORD SpaceSize; + LPPALETTEENTRY lpColors; + + SpaceSize = 4 + (lpParm[2] * sizeof(PALETTEENTRY)); + if ((hSpace = GlobalAlloc(GMEM_DDESHARE|GMEM_MOVEABLE,(LONG) SpaceSize))) + { + lpHolder = lpSpace = GlobalLock(hSpace); + + *((LPWORD)lpSpace)++ = lpParm[3]; + *((LPWORD)lpSpace)++ = lpParm[2]; + lpColors = (LPPALETTEENTRY)lpParm; + + for (i=0; i<lpParm[2]; i++) + *((LPPALETTEENTRY)lpSpace)++ = *lpColors++; + + status = RecordParms(HMFFROMNPMF(npMF), magic, (DWORD)(SpaceSize >> 1), + (LPWORD) lpHolder); + + GlobalUnlock(hSpace); + GlobalFree(hSpace); + } + } + break; + + case (META_RESIZEPALETTE & 255): + { + status = RecordParms(HMFFROMNPMF(npMF), magic, (DWORD)1, (LPWORD)&lpParm[0]); + } + break; + + case (META_DELETEOBJECT & 255): + if (AddToTable(HMFFROMNPMF(npMF), *lpParm, (LPWORD) &position, FALSE) == 1) + { + status = RecordParms(HMFFROMNPMF(npMF), META_DELETEOBJECT, 1UL, &position); + } + break; + } /* switch */ + } + + LocalUnlock( hmfSearch ); + hmfSearch = npMF->metaDCHeader.nextinchain; + } /* while */ + } + + + npMF = (NPMETARECORDER) NPFROMMETADC(hMF); + if (!(npMF->recFlags & METAFILEFAILURE)) + { + + switch (magic & 255) + { + + + + case (META_FRAMEREGION & 255): + case (META_FILLREGION & 255): + case (META_INVERTREGION & 255): + case (META_PAINTREGION & 255): + // Each region function has at least a region to record + buffer[0] = RecordObject(hMF, magic, count, (LPWORD)&(lpParm[count-1])); + + /* Is there a brush too; FillRgn */ + if(count > 1 ) + buffer[1] = RecordObject(hMF, magic, count, (LPWORD)&(lpParm[count-2])); + + /* Are there are extents too; FrameRegion */ + if(count > 2) + { + buffer[2] = lpParm[0]; + buffer[3] = lpParm[1]; + } + + status = RecordParms(hMF, magic, (DWORD)count, (LPWORD)buffer); + break; + + case (META_FLOODFILL & 255): + buffer[0] = 0; // Regular FloodFill + buffer[1] = lpParm[0]; + buffer[2] = lpParm[1]; + buffer[3] = lpParm[2]; + buffer[4] = lpParm[3]; + status = RecordParms(hMF, META_EXTFLOODFILL, (DWORD)count+1, (LPWORD)buffer); + break; + + case (META_ESCAPE & 255): + /* record the function number */ + { + WORD iBytes; + WORD count; + char * pSpace; + char * pTemp; + LPSTR lpInData; + LPEXTTEXTDATA lpTextData; + WORD function; + + *((WORD FAR * FAR *) lpParm)++; + lpInData = (LPSTR) *((WORD FAR * FAR *) lpParm)++; + lpTextData = (LPEXTTEXTDATA) lpInData; + count = iBytes = *lpParm++; + + function = *lpParm++; +#ifdef OLDEXTTEXTOUT + if (function == EXTTEXTOUT) + { + iBytes = (lpTextData->cch * (sizeof(WORD)+sizeof(char))) + + 1 + sizeof(EXTTEXTDATA); + } +#endif + + if (!(pTemp = pSpace = + (char *) LocalAlloc(LMEM_FIXED|LMEM_ZEROINIT, (iBytes + (sizeof(WORD) * 2))))) + return(FALSE); + + *((WORD *) pTemp)++ = function; + *((WORD *) pTemp)++ = count; + +#ifdef OLDEXTTEXTOUT + if (function != EXTTEXTOUT) { +#endif + for (i = 0; i < iBytes; ++i) + *pTemp++ = *lpInData++; +#ifdef OLDEXTTEXTOUT + } else { + *((WORD *) pTemp)++ = lpTextData->xPos; + *((WORD *) pTemp)++ = lpTextData->yPos; + *((WORD *) pTemp)++ = lpTextData->cch; + *((RECT *) pTemp)++ = lpTextData->rcClip; + for (i = 0; i < ((lpTextData->cch + 1) & ~1) ; ++i) + *pTemp++ = lpTextData->lpString[i]; + + for (i = 0; i < lpTextData->cch; ++i) + *((WORD *) pTemp)++ = lpTextData->lpWidths[i]; + } +#endif + + /* info block + 2 words for function and count */ + status = RecordParms(hMF, magic, + (DWORD)((iBytes + 1) >> 1) + 2, + (LPWORD) pSpace); + + LocalFree((HANDLE) pSpace); + } + break; + + case (META_POLYLINE & 255): + case (META_POLYGON & 255): + { + WORD iPoints; + WORD *pSpace; + WORD *pTemp; + LPWORD lpPoints; + + iPoints = *lpParm++; + + iWords = iPoints * 2; + if (!(pTemp = pSpace = (WORD *) LocalAlloc( LMEM_FIXED|LMEM_ZEROINIT, + (iPoints * sizeof(POINT)) + sizeof(WORD)))) + return(FALSE); + + lpPoints = *((WORD FAR * FAR *) lpParm)++; + *pTemp++ = iPoints; + + for (i = 0; i < iWords; ++i) + *pTemp++ = *lpPoints++; + status = RecordParms(hMF, magic, (DWORD)iWords + 1, (LPWORD) pSpace); + LocalFree((HANDLE) pSpace); + } + break; + + case (META_POLYPOLYGON & 255): + { + WORD iPoints; + WORD iPolys; + WORD *pSpace; + WORD *pTemp; + LPWORD lpPoints; + LPWORD lpNumPoints; + + /* get the number of polygons */ + iPolys = *lpParm++; + + /* get the pointers to Points and NumPoints */ + lpNumPoints = *((WORD FAR * FAR *) lpParm)++; + lpPoints = *((WORD FAR * FAR *) lpParm)++; + + /* count the total number of points */ + iPoints = 0 ; + for (i=0; i<iPolys; i++) + iPoints += *(lpNumPoints + i) ; + + /* allocate space needed for Points, NumPoints and Count */ + if (!(pTemp = pSpace = (WORD *) LocalAlloc( LMEM_FIXED|LMEM_ZEROINIT, + (iPoints * sizeof(POINT)) + + iPolys * sizeof(WORD) + + sizeof(WORD)))) + return(FALSE); + + /* save the Count parameter */ + *pTemp++ = iPolys; + + /* now copy the NumPoints array*/ + for (i = 0; i < iPolys; ++i) + *pTemp++ = *lpNumPoints++; + + /* finally copy the number of words in the Points array, remember + the number of words there are double the number of points */ + iWords = iPoints * 2; + for (i = 0; i < iWords; ++i) + *pTemp++ = *lpPoints++; + + /* total number of words in the parameter list = + iPoints*2(for Points) + iPolys(for NumPoints) + 1(for Count) + and iWords has already iPoints*2 */ + + iWords += iPolys + 1 ; + + /* finally record all the parameters */ + status = RecordParms(hMF, magic, (DWORD)iWords , (LPWORD) pSpace); + LocalFree((HANDLE) pSpace); + } + break; + +#ifdef DEADCODE + + case (META_DRAWTEXT & 255): + { + WORD wFormat; + WORD count; + WORD *pSpace; + WORD *pTemp; + LPBYTE lpString; + LPBYTE lpS; + LPWORD lpRect; + + wFormat = *lpParm++; + lpRect = *((WORD FAR * FAR *) lpParm)++; + count = *lpParm++; + lpString = (LPBYTE) *((WORD FAR * FAR *) lpParm)++; + + if(count == -1){ /* another null terminated string */ + lpS = lpString; + for (count = 0 ; *lpS++ != 0; count++) ; + } + + if (!(pTemp = pSpace = (WORD *) LocalAlloc( LMEM_FIXED|LMEM_ZEROINIT, + count + 6 * sizeof(WORD)))) + return(FALSE); + + *pTemp++ = wFormat; + *pTemp++ = count; + for (i = 0; i < 4; ++i) + *pTemp++ = *lpRect++; + + for (i = 0; i < count; ++i) + *((BYTE *) pTemp)++ = *lpString++; + + count = (count + 1) >> 1; + status = RecordParms(hMF, magic, (DWORD)count + 6, (LPWORD) pSpace); + LocalFree((HANDLE) pSpace); + } + break; +#endif + + case (META_EXTTEXTOUT & 255): + { + WORD iBytes; + WORD count; + WORD options; + WORD *pTemp; + WORD *pSpace; + LPINT lpdx; + LPWORD lpString; + LPRECT lprt; + WORD ii; + + lpdx = *((WORD FAR * FAR *) lpParm)++; + count = iBytes = *lpParm++; + + lpString = (LPWORD) *((LPSTR FAR *) lpParm)++; + lprt = (LPRECT) *((LPSTR FAR *) lpParm)++; + options = *lpParm++; + + /* how much space do we need? + ** room for the char string + ** room for the 4 words that are the fixed parms + ** if there is a dx array, we need room for it + ** if the rectangle is being used, we need room for it + ** and we need extra byte for eventual word roundoff + */ + iBytes = (count * (((lpdx) ? sizeof(WORD) : 0) + + sizeof(BYTE))) + + ((options & (ETO_OPAQUE | ETO_CLIPPED)) + ? sizeof(RECT) : 0) + + 1 + (sizeof(WORD) * 4); + + if (!(pTemp = pSpace = (WORD *) LocalAlloc( LMEM_FIXED|LMEM_ZEROINIT,iBytes))) + return(FALSE); + + /* record YPos and XPos */ + + *pTemp++ = *lpParm++; + *pTemp++ = *lpParm++; + *pTemp++ = count; + *pTemp++ = options; + + /* if there's an opaquing rect copy it */ + if (options & (ETO_OPAQUE|ETO_CLIPPED)) + { + *pTemp++ = lprt->left; + *pTemp++ = lprt->top; + *pTemp++ = lprt->right; + *pTemp++ = lprt->bottom; + } + + /* need to copy bytes because it may not be even */ + for (ii = 0; ii < count; ++ii) + *((BYTE *)pTemp)++ = *((LPBYTE)lpString)++; + if (count & 1) /* word align */ + *((BYTE *)pTemp)++; + + if (lpdx) + for (ii = 0; ii < count; ++ii) + *pTemp++ = *lpdx++; + + status = RecordParms(hMF, magic, (DWORD)iBytes >> 1, + (LPWORD) pSpace); + + LocalFree((HANDLE)pSpace); + + } + break; + + case (META_TEXTOUT & 255): + { + LPWORD lpString; + WORD *pSpace; + WORD *pTemp; + POINT pt; + + iChar = *lpParm++; + if (!(pTemp = pSpace = (WORD *) LocalAlloc( LMEM_FIXED|LMEM_ZEROINIT, + iChar + (sizeof(WORD) * 4)))) + return(FALSE); + + *pTemp++ = iChar; + lpString = (LPWORD) *((LPSTR FAR *) lpParm)++; + + for (i = 0; i < iChar; ++i) + *((BYTE *)pTemp)++ = *((LPBYTE)lpString)++; + if (iChar & 1) /* word align */ + *((BYTE *)pTemp)++; + + pt.y = *pTemp++ = *lpParm++; + pt.x = *pTemp++ = *lpParm++; + + status = RecordParms(hMF, magic, (DWORD)((iChar + 1) >> 1) + 3, + (LPWORD) pSpace); + + LocalFree((HANDLE) pSpace); + } + break; + + case (META_DIBBITBLT & 255): + case (META_DIBSTRETCHBLT & 255): + { + LPBITMAPINFOHEADER lpDIBInfo ; + DWORD iWords; + DWORD iBits; + WORD wColorTableSize ; + BOOL bSame=FALSE; + HANDLE hSpace=FALSE; + HBITMAP hBitmap; + HDC hSDC; + BYTE bBitsPerPel ; + BITMAP logBitmap; + + iWords = (WORD)count; + hSDC = lpParm[iWords - 5]; + + if (hMF == hSDC || hSDC == NULL) + bSame = TRUE; + else + { + WORD iParms; + + if( GetObjectType( (HANDLE)hSDC ) == OBJ_MEMDC) + { + HBITMAP hBitmap; + + hBitmap = GetCurrentObject( hSDC, OBJ_BITMAP ); + + GetObject( hBitmap, sizeof(BITMAP), (LPSTR)&logBitmap); + + /* allocate space for the DIB header and bits */ + if (!(hSpace = AllocateSpaceForDIB (&logBitmap, + &bBitsPerPel, + &wColorTableSize, + &iBits ))) + return (FALSE) ; + lpTemp = lpSpace = (LPWORD) GlobalLock(hSpace); + +/*--------------------------------------------------------------------------** +** copy the parameters from the end of the list which is at the top of the ** +** stack till the hSrcDC parameter,skip the hSrcDC parameter and copy the ** +** rest of the parameters. ** ** +**--------------------------------------------------------------------------*/ + + iParms = (magic == META_DIBBITBLT) ? 4 : 6; + + for (i = 0; i < iParms; ++i) + *lpSpace++ = *lpParm++; + + /* skip the hSrcDC parameter and reduce parameter count */ + *lpParm++; + iWords--; + + /* copy the rest of the parameters in the call */ + for ( ; i < (WORD)iWords; ++i) + *lpSpace++ = *lpParm++; + + + /* save the start of the bitmap info header field */ + lpDIBInfo = (LPBITMAPINFOHEADER) lpSpace ; + + /* preapare the header and return lpSpace pointing to area + for thr bits */ + lpSpace = InitializeDIBHeader (lpDIBInfo, + &logBitmap, bBitsPerPel,wColorTableSize) ; + + /* lpSpace now points to the area to hold DIB bits */ + + } + else + return(FALSE); + } + + if (bSame) + status = RecordParms(hMF, magic, (DWORD)count, lpParm); + else + { + /* get the bits into the DIB */ + hBitmap = SelectObject (hSDC, hStaticBitmap) ; + GetDIBits(hSDC, hBitmap, 0, logBitmap.bmHeight, + (LPBYTE) lpSpace, (LPBITMAPINFO)lpDIBInfo, 0 ) ; + SelectObject (hSDC,hBitmap) ; + + /* finally record the parameters into the file*/ + status = RecordParms(hMF, magic, (DWORD)(iWords + + (iBits >> 1)) , (LPWORD) lpTemp ) ; + + if (hSpace) + { + GlobalUnlock(hSpace); + GlobalFree(hSpace); + } + } + } + break; + + case (META_SETDIBTODEV & 255): + { + HANDLE hSpace; + LPWORD lpSpace; + LPWORD lpHolder; + DWORD SpaceSize; + WORD ColorSize; + DWORD BitmapSize; + LPBITMAPINFOHEADER lpBitmapInfo; + HPWORD lpBits; + WORD wUsage; + LPBITMAPCOREHEADER lpBitmapCore; /* used for old DIBs */ + DWORD dwi; + HPWORD lpHugeSpace; + + wUsage = *lpParm++; + + lpBitmapInfo = (LPBITMAPINFOHEADER) *((WORD FAR * FAR *) lpParm)++; + lpBits = (WORD huge *) *((WORD FAR * FAR *) lpParm)++; + + /* old style DIB header */ + if (lpBitmapInfo->biSize == sizeof(BITMAPCOREHEADER)) + { + lpBitmapCore = (LPBITMAPCOREHEADER)lpBitmapInfo; + + if (lpBitmapCore->bcBitCount == 24) + ColorSize = 0; + else + ColorSize = (1 << lpBitmapCore->bcBitCount) * + (wUsage == DIB_RGB_COLORS ? + sizeof(RGBQUAD) : + sizeof(WORD)); + + /* bits per scanline */ + BitmapSize = lpBitmapCore->bcWidth * + lpBitmapCore->bcBitCount; + + /* bytes per scanline (rounded to DWORD boundary) */ + BitmapSize = ((BitmapSize + 31) & (~31)) >> 3; + /* bytes for the NumScans of the bitmap */ + BitmapSize *= lpParm[0]; + } + /* new style DIB header */ + else + { + if (lpBitmapInfo->biClrUsed) + { + ColorSize = ((WORD)lpBitmapInfo->biClrUsed) * + (wUsage == DIB_RGB_COLORS ? + sizeof(RGBQUAD) : + sizeof(WORD)); + } + else if (lpBitmapInfo->biBitCount == 24) + ColorSize = 0; + else + ColorSize = (1 << lpBitmapInfo->biBitCount) * + (wUsage == DIB_RGB_COLORS ? + sizeof(RGBQUAD) : + sizeof(WORD)); + + /* if biSizeImage is already there and we are + ** getting a full image, there is no more work + ** to be done. + ** ****** what about partial RLEs? ***** + */ + if (!(BitmapSize = lpBitmapInfo->biSizeImage) || + (lpBitmapInfo->biHeight != lpParm[0])) + { + /* bits per scanline */ + BitmapSize = lpBitmapInfo->biWidth * + lpBitmapInfo->biBitCount; + /* bytes per scanline (rounded to DWORD boundary) */ + BitmapSize = ((BitmapSize + 31) & (~31)) >> 3; + /* bytes for the NumScans of the bitmap */ + BitmapSize *= lpParm[0]; + } + } + + SpaceSize = (DWORD)sizeof(BITMAPINFOHEADER) + (DWORD)ColorSize + + (DWORD)BitmapSize + + (DWORD)(9*sizeof(WORD)); + + if ((hSpace = GlobalAlloc(GMEM_DDESHARE|GMEM_MOVEABLE,SpaceSize))) + { + lpHolder = lpSpace = (LPWORD) GlobalLock(hSpace); + + /* copy over call parameters */ + *lpSpace++ = wUsage; + for (i=0; i<8; i++) + *lpSpace++ = *lpParm++; + + /* copy the bitmap header */ + if (lpBitmapInfo->biSize == sizeof(BITMAPCOREHEADER)) + { + LPBITMAPINFOHEADER lpDIBInfo; + + lpDIBInfo = (LPBITMAPINFOHEADER) lpSpace; + + lpDIBInfo->biSize = sizeof (BITMAPINFOHEADER); + lpDIBInfo->biWidth = (DWORD)lpBitmapCore->bcWidth; + lpDIBInfo->biHeight = (DWORD)lpBitmapCore->bcHeight; + lpDIBInfo->biPlanes = lpBitmapCore->bcPlanes; + lpDIBInfo->biBitCount = lpBitmapCore->bcBitCount; + + lpDIBInfo->biCompression = 0; + lpDIBInfo->biSizeImage = 0; + lpDIBInfo->biXPelsPerMeter = 0; + lpDIBInfo->biYPelsPerMeter = 0; + lpDIBInfo->biClrUsed = 0; + lpDIBInfo->biClrImportant = 0; + + /* get lpSpace to point at color table location */ + ((LPBITMAPINFOHEADER)lpSpace)++; + + /* copy the color table */ + + lpBitmapCore++; /* get to color table */ + if (wUsage == DIB_RGB_COLORS) + { + for (i=0; i< (ColorSize/(sizeof(RGBQUAD))); i++) + { + /* copy the triple */ + *((RGBTRIPLE FAR *)lpSpace)++ = + *((RGBTRIPLE FAR *)lpBitmapCore)++; + /* zero out reserved byte */ + *((LPBYTE)lpSpace)++ = 0; + } + } + else + { + /* copy over indices */ + for (i=0; i< (ColorSize/2); i++) + *lpSpace++ = *((LPWORD)lpBitmapCore)++; + } + } + else + { + *((LPBITMAPINFOHEADER)lpSpace)++ = *lpBitmapInfo++; + + /* copy the color table */ + for (i=0; i< (ColorSize/2); i++) + *lpSpace++ = *((LPWORD)lpBitmapInfo)++; + } + + /* copy the actual bits */ + lpHugeSpace = (HPWORD) lpSpace; + for (dwi=0; dwi < (BitmapSize/2); dwi++) + *lpHugeSpace++ = *lpBits++; + + status = RecordParms(hMF, magic, (DWORD) (SpaceSize >> 1), + (LPWORD) lpHolder); + + GlobalUnlock(hSpace); + GlobalFree(hSpace); + } + } + break; + +/* **** this should be combined with the above, but to eliminate possible +** **** breakage right before shipping, keep it separate. +*/ + case (META_STRETCHDIB & 255): + { + LPBITMAPINFOHEADER lpBitmapInfo; + LPBITMAPCOREHEADER lpBitmapCore; /* used for old DIBs */ + HANDLE hSpace; + LPWORD lpSpace; + LPWORD lpHolder; + DWORD SpaceSize; + WORD ColorSize; + DWORD BitmapSize; + HPWORD lpBits; + WORD wUsage; + DWORD dwi; + HPWORD lpHugeSpace; + DWORD dwROP; + + dwROP = *((LPDWORD)lpParm)++; + wUsage = *lpParm++; + + lpBitmapInfo = (LPBITMAPINFOHEADER) *((WORD FAR * FAR *) lpParm)++; + lpBits = (HPWORD) *((WORD FAR * FAR *) lpParm)++; + + /* old style DIB header */ + if (lpBitmapInfo->biSize == sizeof(BITMAPCOREHEADER)) + { + lpBitmapCore = (LPBITMAPCOREHEADER)lpBitmapInfo; + + if (lpBitmapCore->bcBitCount == 24) + ColorSize = 0; + else + ColorSize = (1 << lpBitmapCore->bcBitCount) * + (wUsage == DIB_RGB_COLORS ? + sizeof(RGBQUAD) : + sizeof(WORD)); + + /* bits per scanline */ + BitmapSize = lpBitmapCore->bcWidth * + lpBitmapCore->bcBitCount; + + /* bytes per scanline (rounded to DWORD boundary) */ + BitmapSize = ((BitmapSize + 31) & (~31)) >> 3; + /* bytes for the height of the bitmap */ + BitmapSize *= lpBitmapCore->bcHeight; + } + /* new style DIB header */ + else + { + if (lpBitmapInfo->biClrUsed) + { + ColorSize = ((WORD)lpBitmapInfo->biClrUsed) * + (wUsage == DIB_RGB_COLORS ? + sizeof(RGBQUAD) : + sizeof(WORD)); + } + else if (lpBitmapInfo->biBitCount == 24) + ColorSize = 0; + else + ColorSize = (1 << lpBitmapInfo->biBitCount) * + (wUsage == DIB_RGB_COLORS ? + sizeof(RGBQUAD) : + sizeof(WORD)); + + /* if biSizeImage is already there and we are + ** getting a full image, there is no more work + ** to be done. + */ + if (!(BitmapSize = lpBitmapInfo->biSizeImage)) + { + /* bits per scanline */ + BitmapSize = lpBitmapInfo->biWidth * + lpBitmapInfo->biBitCount; + /* bytes per scanline (rounded to DWORD boundary) */ + BitmapSize = ((BitmapSize + 31) & (~31)) >> 3; + /* bytes for the height of the bitmap */ + BitmapSize *= (WORD)lpBitmapInfo->biHeight; + } + + } + + SpaceSize = (DWORD)sizeof(BITMAPINFOHEADER) + (DWORD)ColorSize + + (DWORD)BitmapSize + + (DWORD)(11*sizeof(WORD)); + + if ((hSpace = GlobalAlloc(GMEM_DDESHARE|GMEM_MOVEABLE,SpaceSize))) + { + lpHolder = lpSpace = (LPWORD) GlobalLock(hSpace); + + /* copy over call parameters */ + *((LPDWORD)lpSpace)++ = dwROP; + *lpSpace++ = wUsage; + for (i=0; i<8; i++) + *lpSpace++ = *lpParm++; + + /* copy the bitmap header */ + if (lpBitmapInfo->biSize == sizeof(BITMAPCOREHEADER)) + { + LPBITMAPINFOHEADER lpDIBInfo; + + lpDIBInfo = (LPBITMAPINFOHEADER) lpSpace; + + lpDIBInfo->biSize = sizeof (BITMAPINFOHEADER); + lpDIBInfo->biWidth = (DWORD)lpBitmapCore->bcWidth; + lpDIBInfo->biHeight = (DWORD)lpBitmapCore->bcHeight; + lpDIBInfo->biPlanes = lpBitmapCore->bcPlanes; + lpDIBInfo->biBitCount = lpBitmapCore->bcBitCount; + + lpDIBInfo->biCompression = 0; + lpDIBInfo->biSizeImage = 0; + lpDIBInfo->biXPelsPerMeter = 0; + lpDIBInfo->biYPelsPerMeter = 0; + lpDIBInfo->biClrUsed = 0; + lpDIBInfo->biClrImportant = 0; + + /* get lpSpace to point at color table location */ + ((LPBITMAPINFOHEADER)lpSpace)++; + + /* copy the color table */ + + lpBitmapCore++; /* get to color table */ + if (wUsage == DIB_RGB_COLORS) + { + for (i=0; i< (ColorSize/(sizeof(RGBQUAD))); i++) + { + /* copy the triple */ + *((RGBTRIPLE FAR *)lpSpace)++ = + *((RGBTRIPLE FAR *)lpBitmapCore)++; + /* zero out reserved byte */ + *((LPBYTE)lpSpace)++ = 0; + } + } + else + { + /* copy over indices */ + for (i=0; i< (ColorSize/2); i++) + *lpSpace++ = *((LPWORD)lpBitmapCore)++; + } + } + else + { + *((LPBITMAPINFOHEADER)lpSpace)++ = *lpBitmapInfo++; + + /* copy the color table */ + for (i=0; i< (ColorSize/2); i++) + *lpSpace++ = *((LPWORD)lpBitmapInfo)++; + } + + /* copy the actual bits */ + lpHugeSpace = (HPWORD) lpSpace; + for (dwi=0; dwi < (BitmapSize/2); dwi++) + *lpHugeSpace++ = *lpBits++; + + status = RecordParms(hMF, magic, (DWORD) (SpaceSize >> 1), + (LPWORD) lpHolder); + + GlobalUnlock(hSpace); + GlobalFree(hSpace); + } + } + break; + + case (META_REALIZEPALETTE & 255): + { + /* we need to see if the palette has changed since + ** it was selected into the DC. if so, we need to + ** adjust things with a SetPaletteEntries call + */ + + status = MakeLogPalette(hMF, npMF->recCurObjects[OBJ_PALETTE-1], META_SETPALENTRIES); + + if (status) + status = RecordParms(hMF, META_REALIZEPALETTE, (DWORD)0, (LPWORD) NULL); + } + break; + + case (META_SELECTPALETTE & 255): + lpParm++; /* skip over fore/back flag */ + npMF->recCurObjects[OBJ_PALETTE-1] = *lpParm; /* pal used in this DC */ + if ((position = RecordObject(hMF, magic, count, lpParm)) != -1) + status = RecordParms(hMF, META_SELECTPALETTE, 1UL, &position); + break; + + case (META_SELECTOBJECT & 255): + if (*lpParm) + { + if ((position = RecordObject(hMF, magic, count, lpParm)) == -1) + return(FALSE); + else + { + HANDLE hObject; + + status = RecordParms(hMF, META_SELECTOBJECT, 1UL, &position); + + /* maintain the new selection in the CurObject table */ + hObject = *lpParm; + npMF->recCurObjects[GetObjectType(hObject)-1] = hObject; + } + } + break; + + case (META_RESETDC & 255): + status = RecordParms( hMF, magic, + ((LPDEVMODE)lpParm)->dmSize + + ((LPDEVMODE)lpParm)->dmDriverExtra, + lpParm ); + break; + + case (META_STARTDOC & 255): + { + short iBytes; + LPSTR lpSpace; + LPSTR lpsz; + short n; + + lpsz = (LPSTR)lpParm; // point to lpDoc + n = lstrlen((LPSTR)lpsz + 2) + 1; + iBytes = n + lstrlen((LPSTR)lpsz + 6) + 1; + + lpSpace = (char *) LocalAlloc( LMEM_FIXED|LMEM_ZEROINIT,iBytes); + lstrcpy(lpSpace, (LPSTR)lpsz + 2); + lstrcpy(lpSpace + n + 1, lpsz + 6); + status = RecordParms(hMF, magic, (DWORD)(iBytes >> 1), (LPWORD)lpSpace); + LocalFree((HANDLE)(DWORD)lpSpace); + } + break; + + } + return(status); + } + } +} /* RecordOther */ + + +/***************************** Internal Function ***************************\ +* RecordObject +* +* Records the use of an object by creating the object +* +* Returns: index of object in table +* +* +\***************************************************************************/ + +int INTERNAL RecordObject(HANDLE hMF, WORD magic, WORD count, LPWORD lpParm) +{ + LPBITMAPINFOHEADER lpDIBInfo ; + WORD status; + WORD position; + HANDLE hObject; + WORD objType; + BYTE bBitsPerPel; + WORD wColorTableSize; + DWORD iBits ; + WORD i; + HANDLE hSpace = NULL ; + LPWORD lpSpace; + LPWORD lpTemp ; + BYTE objBuf[MAXOBJECTSIZE]; + + + dprintf( 6," RecordObject 0x%X", magic); + + hObject = *lpParm; + + hMF = MAKEMETADC(hMF); + ASSERTGDI( IsMetaDC(hMF), "RecordObject: Expects only valid metafiles"); + + // Add the object to the metafiles list + if ((status = AddToTable(hMF, hObject, (LPWORD) &position, TRUE)) == -1) + return(status); + else if (status == FALSE) + { + objType = GetObjectAndType( hObject, objBuf ); + + switch (objType) + { + case OBJ_PEN: + status = RecordParms(hMF, META_CREATEPENINDIRECT, + (DWORD)((sizeof(LOGPEN) + 1) >> 1), + + (LPWORD)objBuf ); + break; + + case OBJ_FONT: + /* size of LOGFONT adjusted based on the length of the facename */ + status = RecordParms(hMF, META_CREATEFONTINDIRECT, + (DWORD)((1 + lstrlen((LPSTR) ((LPLOGFONT)objBuf)->lfFaceName) + + sizeof(LOGFONT) - LF_FACESIZE + 1) >> 1), + (LPWORD) objBuf); + break; + +/* +!!! in win2, METACREATEREGION records contained an entire region object, +!!! including the full header. this header changed in win3. +!!! +!!! to remain compatible, the region records will be saved with the +!!! win2 header. here we save our region with a win2 header. +*/ + case OBJ_RGN: + { + LPWIN3REGION lpw3rgn = (LPWIN3REGION)NULL; + DWORD cbNTRgnData; + WORD sel; + DWORD curRectl = 0; + WORD cScans = 0; + WORD maxScanEntry = 0; + WORD curScanEntry; + WORD cbw3data; + LPRGNDATA lprgn = (LPRGNDATA)NULL; + LPRECTL lprcl; + LPSCAN lpScan; + + status = FALSE; // just in case something goes wrong + + // Get the NT Region Data + cbNTRgnData = GetRegionData( hObject, 0, NULL ); + if (cbNTRgnData == 0) + break; + + sel = GlobalAlloc( GMEM_FIXED, cbNTRgnData); + if (!sel) + break; + + lprgn = (LPRGNDATA)MAKELONG(0, sel); + + cbNTRgnData = GetRegionData( hObject, cbNTRgnData, lprgn ); + if (cbNTRgnData == 0) + break; + + lprcl = (LPRECTL)lprgn->Buffer; + + // Create the Windows 3.x equivalent + + // worst case is one scan for each rect + cbw3data = 2*sizeof(WIN3REGION) + (WORD)lprgn->rdh.nCount*sizeof(SCAN); + + sel = GlobalAlloc( GMEM_FIXED, cbw3data); + if (!sel) + break; + + lpw3rgn = (LPWIN3REGION)MAKELONG(0, sel); + GetRgnBox( hObject, &lpw3rgn->rcBounding ); + + cbw3data = sizeof(WIN3REGION) - sizeof(SCAN) + 2; + + // visit all the rects + lpScan = lpw3rgn->aScans; + while(curRectl < lprgn->rdh.nCount) + { + LPWORD lpXEntry; + WORD cbScan; + + curScanEntry = 0; // Current X pair in this scan + + lpScan->scnPntTop = (WORD)lprcl[curRectl].yTop; + lpScan->scnPntBottom = (WORD)lprcl[curRectl].yBottom; + + lpXEntry = lpScan->scnPntsX; + + // handle rects on this scan + do + { + lpXEntry[curScanEntry + 0] = (WORD)lprcl[curRectl].xLeft; + lpXEntry[curScanEntry + 1] = (WORD)lprcl[curRectl].xRight; + curScanEntry += 2; + curRectl++; + } while ( (curRectl < lprgn->rdh.nCount) + && (lprcl[curRectl-1].yTop == lprcl[curRectl].yTop) + && (lprcl[curRectl-1].yBottom == lprcl[curRectl].yBottom) + ); + + lpScan->scnPntCnt = curScanEntry; + lpXEntry[curScanEntry] = curScanEntry; // Count also follows Xs + cScans++; + + if (curScanEntry > maxScanEntry) + maxScanEntry = curScanEntry; + + // account for each new scan + each X1 X2 Entry but the first + cbScan = sizeof(SCAN)-(sizeof(WORD)*2) + (curScanEntry*sizeof(WORD)); + cbw3data += cbScan; + lpScan = (LPSCAN)(((LPBYTE)lpScan) + cbScan); + } + + // Initialize the header + lpw3rgn->nextInChain = 0; + lpw3rgn->ObjType = 6; // old Windows OBJ_RGN identifier + lpw3rgn->ObjCount= 0x2F6; + lpw3rgn->cbRegion = cbw3data; // don't count type and next + lpw3rgn->cScans = cScans; + lpw3rgn->maxScan = maxScanEntry; + + status = RecordParms(hMF, META_CREATEREGION, + cbw3data-1 >> 1, // Convert to count of words + (LPWORD) lpw3rgn); + + GlobalFree( HIWORD(lprgn) ); + GlobalFree( HIWORD(lpw3rgn) ); + } + + break; + + + case OBJ_BRUSH: + switch (((LPLOGBRUSH)objBuf)->lbStyle) + { + case BS_DIBPATTERN: + { + WORD cbDIBBits; + BITMAP logBitmap; + + /* get the pattern DIB */ + GetObject( (HANDLE)((LPLOGBRUSH)objBuf)->lbHatch, sizeof(BITMAP), (LPSTR)&logBitmap ); + + cbDIBBits = logBitmap.bmWidthBytes * logBitmap.bmHeight; + if ((hSpace = GlobalAlloc(GMEM_DDESHARE|GMEM_MOVEABLE,(LONG)(cbDIBBits + 4)))) + { + lpTemp = lpSpace = (LPWORD)GlobalLock (hSpace) ; + + /* mark this as a DIB pattern brush */ + *lpSpace++ = BS_DIBPATTERN; + + /* set the usage word */ + *lpSpace++ = (WORD)((LPLOGBRUSH)objBuf)->lbColor; + + // lpPackedDIB = (LPWORD)GlobalLock(hPatBits); + + /* copy the bits to the new buffer */ + for (i = 0; i < (cbDIBBits >> 1); i++) + *lpSpace++ = *logBitmap.bmBits++; + + status = RecordParms (hMF, META_DIBCREATEPATTERNBRUSH, + (DWORD)(cbDIBBits >> 1) + 2, (LPWORD)lpTemp); + + /* release the allocated space */ + GlobalUnlock (hSpace) ; + GlobalFree (hSpace) ; + } + } + break; + + case BS_PATTERN: + { + BITMAP logBitmap; + + if (GetObject((HANDLE)((LPLOGBRUSH)objBuf)->lbHatch, sizeof(logBitmap), (LPSTR)&logBitmap)) + { + /* allocate space for the device independent bitmap */ + if (hSpace = AllocateSpaceForDIB (&logBitmap, + (LPBYTE)&bBitsPerPel, + (LPWORD) &wColorTableSize , + (LPDWORD) &iBits)) + { + /* get a pointer to the allocated space */ + lpTemp = lpSpace = (LPWORD) GlobalLock (hSpace) ; + + /* mark this as a normal pattern brush */ + *lpSpace++ = BS_PATTERN; + + /* use RGB colors */ + *lpSpace++ = DIB_RGB_COLORS; + + /* this also will be a pointer to the DIB header */ + lpDIBInfo = (LPBITMAPINFOHEADER) lpSpace ; + + /* prepare the header of the bitmap and get a pointer to the + start of the area which is to hold the bits */ + lpSpace = InitializeDIBHeader (lpDIBInfo, + &logBitmap, bBitsPerPel, wColorTableSize); + + /* convert the bits into the DIB format */ + // !!! validate that the DC is ignored + GetDIBits (hScreenDC, (HBITMAP)((LPLOGBRUSH)objBuf)->lbHatch, + 0, logBitmap.bmHeight, + (LPSTR) lpSpace, (LPBITMAPINFO)lpDIBInfo,0) ; + + /* now record the Header and Bits as parameters */ + status = RecordParms (hMF, META_DIBCREATEPATTERNBRUSH, + (DWORD)(iBits >> 1) + 2, (LPWORD) lpTemp); + + /* release the allocated space */ + GlobalUnlock (hSpace) ; + GlobalFree (hSpace) ; + } + } + } + break; + + default: + /* non-pattern brush */ + status = RecordParms(hMF, META_CREATEBRUSHINDIRECT, + (DWORD)((sizeof(LOGBRUSH) + 1) >> 1), + (LPWORD)objBuf); + break; + } /* Brush Type switch */ + break; /* Brush object case */ + + case OBJ_PALETTE: + status = MakeLogPalette(hMF, hObject, META_CREATEPALETTE); + break; + + default: + ASSERTGDIW( 0, "unknown case RecordObject: %d", objType ); + break; + } +// RecordObj10: + } + + ASSERTGDI( status == TRUE, "RecordObject: Failing"); + return ((status == TRUE) ? position : -1); +} /* RecordObject */ + + +/***************************** Internal Function ***************************\ +* ProbeSize +* +* Determines if there is sufficient space for metafiling the dwLength +* words into the memory metafile +* +* Returns: a global handle of where next metafile is to be recorded +* or FALSE if unable to allocate more memory +* +\***************************************************************************/ + +HANDLE INTERNAL ProbeSize(NPMETARECORDER npMF, DWORD dwLength) +{ + DWORD nWords; + DWORD totalWords; + BOOL status = FALSE; + HANDLE hand; + + GdiLogFunc3( " ProbeSize"); + + if (npMF->hMetaData == NULL) + { + nWords = ((DWORD)DATASIZE > dwLength) ? (DWORD)DATASIZE : dwLength; + totalWords = (nWords * sizeof(WORD)) + sizeof(METAHEADER); + if (npMF->hMetaData = GlobalAlloc(GMEM_DDESHARE|GMEM_MOVEABLE, totalWords)) + { + npMF->sizeBuffer = nWords; + npMF->recFilePosition = 0; + status = TRUE; + } + } + else if(npMF->sizeBuffer < (npMF->recFilePosition + dwLength)) + { + nWords = ((DWORD)DATASIZE > dwLength) ? (DWORD)DATASIZE : dwLength; + nWords += npMF->sizeBuffer; + totalWords = (nWords * sizeof(WORD)) + sizeof(METAHEADER); + if (hand = GlobalReAlloc(npMF->hMetaData, totalWords, GMEM_MOVEABLE)) + { + npMF->hMetaData = hand; + npMF->sizeBuffer = nWords; + status = TRUE; + } + } + else + { + status = TRUE; + } + return ((status) ? npMF->hMetaData : NULL); +} + + +/***************************** Internal Function ***************************\ +* AddToTable +* +* Add an object (brush, pen...) to a list of objects associated with the +* metafile. +* +* +* +* Returns: TRUE if object is already in table +* FALSE if object was just added to table +* -1 if failure +* +* Remarks +* bAdd is TRUE iff the object is being added otherwise it is being deleted +* +\***************************************************************************/ + +WORD INTERNAL AddToTable(HANDLE hMF, HANDLE hObject, LPWORD pPosition, BOOL bAdd) +{ + NPMETARECORDER npMF; + WORD iEmptySpace = -1; + WORD i; + WORD status = -1; + HANDLE hTable; + OBJECTTABLE *pHandleTable; + + + GdiLogFunc2(" AddToTable"); + + if ((hMF = GetPMetaFile(hMF)) != -1 ) + { + npMF = (NPMETARECORDER) LocalLock(hMF); + + if (hTable = npMF->hObjectTable) + { + pHandleTable = (NPOBJECTTABLE) LMHtoP(hTable); + for (i = 0; i < npMF->recordHeader.mtNoObjects; ++i) + { + if (hObject == pHandleTable[i].objectCurHandle ) //!!!!! used to be check unique ID# + { + *pPosition = i; + status = TRUE; + + // if we are doing a METADELETEOBJECT. + // delete object from table + if (!bAdd) + { + pHandleTable[i].objectIndex = NULL; + pHandleTable[i].objectCurHandle = NULL; + } + goto AddToTable10; + } + + /* if the entry has been deleted, we want to add a new object + ** in its place. iEmptySpace will tell us where that place is. + */ + else if ((pHandleTable[i].objectIndex == NULL) && (iEmptySpace == -1)) + iEmptySpace = i; + } + } + + if (bAdd) + { + // If there is no object table for this MetaFile then Allocate one. + if (hTable == NULL) + { + npMF->hObjectTable = hTable = LocalAlloc(LMEM_MOVEABLE, sizeof(OBJECTTABLE)); + } + else if (iEmptySpace == -1) + hTable = LocalReAlloc(hTable, (npMF->recordHeader.mtNoObjects + 1) + * sizeof(OBJECTTABLE), LMEM_MOVEABLE); + + if (hTable) + { + pHandleTable = (NPOBJECTTABLE) LMHtoP(hTable); + if (iEmptySpace == -1) + *pPosition = npMF->recordHeader.mtNoObjects++; + else + *pPosition = iEmptySpace; + pHandleTable[*pPosition].objectIndex = hObject; //!!!!! pObjHead->ilObjCount; + pHandleTable[*pPosition].objectCurHandle = hObject; + status = FALSE; + } + } +AddToTable10:; + LocalUnlock(hMF); + } + + ASSERTGDI( status != -1, "AddToTable: Failing"); + return(status); +} + +#if 0 // this is going to gdi.dll + +/***************************** Internal Function **************************\ +* HDC GDIENTRY CreateMetaFile +* +* Creates a MetaFile DC +* +* +* Effects: +* +\***************************************************************************/ + +HDC GDIENTRY CreateMetaFile(LPSTR lpFileName) +{ + BOOL status=FALSE; + GLOBALHANDLE hMF; + NPMETARECORDER npMF; + + GdiLogFunc("CreateMetaFile"); + + if (hMF = LocalAlloc(LMEM_MOVEABLE|LMEM_ZEROINIT, sizeof(METARECORDER))) + { + npMF = (NPMETARECORDER) LocalLock(hMF); + npMF->metaDCHeader.ilObjType = OBJ_METAFILE; + npMF->metaDCHeader.ident = ID_METADC; + + npMF->recordHeader.mtHeaderSize = HEADERSIZE; + npMF->recordHeader.mtVersion = METAVERSION; + npMF->recordHeader.mtSize = HEADERSIZE; + + if (lpFileName) + { + npMF->recordHeader.mtType = DISKMETAFILE; + if (((npMF->recFileNumber = OpenFile(lpFileName, + (LPOFSTRUCT) &(npMF->recFileBuffer), + OF_CREATE|READ_WRITE)) + != -1) + && (_lwrite(npMF->recFileNumber, (LPSTR)npMF, sizeof(METAHEADER)) + == sizeof(METAHEADER))) + { + status = TRUE; + } + if (npMF->recFileNumber != -1) + { + if (!(npMF->recFileBuffer.fFixedDisk)) + _lclose(npMF->recFileNumber); + } + + if (!MetaCache.hCache) + { + MetaCache.hCache = AllocBuffer(&MetaCache.wCacheSize); + MetaCache.wCacheSize >>= 1; + MetaCache.hMF = hMF; + MetaCache.wCachePos = 0; + } + } + + else + { + npMF->recordHeader.mtType = MEMORYMETAFILE; + status = TRUE; + } + } + + // If successfull then add the metafile to the linked list + if( status != FALSE ) + { + if( hFirstMetaFile == 0 ) + { + hFirstMetaFile = hMF; + } + else + { + npMF->metaDCHeader.nextinchain = hFirstMetaFile; + hFirstMetaFile = hMF; + } + LocalUnlock( hMF ); + } + + return ((status) ? MAKEMETADC(hMF) : FALSE); +} + + +/***************************** Internal Function **************************\ +* HANDLE GDIENTRY CloseMetaFile +* +* The CloseMetaFile function closes the metafile device context and creates a +* metafile handle that can be used to play the metafile by using the +* PlayMetaFile function. +* +* Effects: +* +\***************************************************************************/ + +HANDLE GDIENTRY CloseMetaFile(HANDLE hdc) +{ + BOOL status = FALSE; + HANDLE hMetaFile=NULL; + LPMETADATA lpMetaData; + LPMETAFILE lpMFNew; + WORD fileNumber; + NPMETARECORDER npMF; + DWORD metafileSize; + LPWORD lpCache; + HANDLE hMF; + HANDLE hMFSearch; + int rc; + + GdiLogFunc("CloseMetaFile"); + + hMF = HANDLEFROMMETADC(hdc); + + if (hMF && RecordParms(hMF, 0, (DWORD)0, (LONG)0)) + { + + npMF = (NPMETARECORDER)LocalLock(hMF); + if (!(npMF->recFlags & METAFILEFAILURE)) + { + if (npMF->recordHeader.mtType == MEMORYMETAFILE) + { + lpMetaData = (LPMETADATA) GlobalLock(npMF->hMetaData); + lpMetaData->dataHeader = npMF->recordHeader; + metafileSize = (npMF->recordHeader.mtSize * sizeof(WORD)) + + sizeof(METAHEADER); + GlobalUnlock(hMetaFile = npMF->hMetaData); + if (!(status = (BOOL) GlobalReAlloc(hMetaFile, + (LONG)metafileSize, + GMEM_MOVEABLE))) + GlobalFree(hMetaFile); + } + else + /* rewind the file and write the header out */ + if (hMetaFile = GlobalAlloc(GMEM_DDESHARE|GMEM_MOVEABLE,(LONG) sizeof(METAFILE))) + { + lpMFNew = (LPMETAFILE) GlobalLock(hMetaFile); + lpMFNew->MetaFileHeader = npMF->recordHeader; + npMF->recordHeader.mtType = MEMORYMETAFILE; + if (npMF->recFileBuffer.fFixedDisk) + fileNumber = npMF->recFileNumber; + else + { + if ((fileNumber = OpenFile((LPSTR) npMF->recFileBuffer.szPathName, + (LPOFSTRUCT) &(npMF->recFileBuffer), + OF_PROMPT | OF_REOPEN | READ_WRITE)) + == -1) + { + GlobalUnlock(hMetaFile); + GlobalFree(hMetaFile); + LocalUnlock(hMF); + + if (MetaCache.hMF == hMF) + { + GlobalFree(MetaCache.hCache); + MetaCache.hCache = MetaCache.hMF = 0; + } + + goto errCloseMetaFile; + } + } + + if (MetaCache.hCache && MetaCache.hMF == hMF) + { + _llseek(fileNumber, (LONG) 0, 2); + lpCache = (LPWORD) GlobalLock(MetaCache.hCache); + rc = (MetaCache.wCachePos) ? + AttemptWrite(hMF, + fileNumber, + (DWORD)(MetaCache.wCachePos << 1), + (LPSTR) lpCache) + : TRUE; + GlobalUnlock(MetaCache.hCache); + GlobalFree(MetaCache.hCache); + MetaCache.hCache = MetaCache.hMF = 0; + + if (!rc) + { + MarkMetaFile(hMF); + goto errCloseMetaFile; + } + } + + _llseek(fileNumber, (LONG) 0, 0); + if(_lwrite(fileNumber, (LPSTR) (&npMF->recordHeader), + sizeof(METAHEADER)) == sizeof(METAHEADER)) + { + status = TRUE; + } + lpMFNew->MetaFileBuffer = npMF->recFileBuffer; + _lclose(fileNumber); + GlobalUnlock(hMetaFile); + } + + if (npMF->hObjectTable) + { + LocalFree((HANDLE) npMF->hObjectTable); + } + } + + /* Remove the meta file from the list of active metafiles */ + hMFSearch = hFirstMetaFile; + + if( hFirstMetaFile == hMF ) + { + hFirstMetaFile = npMF->metaDCHeader.nextinchain; + } + else + { + while( hMFSearch ) + { + NPMETARECORDER npMFSearch; + HANDLE hNext; + + npMFSearch = (NPMETARECORDER)LocalLock(hMFSearch); + hNext = npMFSearch->metaDCHeader.nextinchain; + if( hNext == hMF ) + { + npMFSearch->metaDCHeader.nextinchain = + npMF->metaDCHeader.nextinchain; + } + else + { + hNext = npMFSearch->metaDCHeader.nextinchain; + } + LocalUnlock(hMFSearch); + hMFSearch = hNext; + } + } + LocalUnlock(hMF); + LocalFree(hMF); + } + +errCloseMetaFile: + return ((status) ? hMetaFile : FALSE); +} + + +/***************************** Internal Function **************************\ +* CopyMetaFile(hSrcMF, lpFileName) +* +* Copies the metafile (hSrcMF) to a new metafile with name lpFileName. The +* function then returns a handle to this new metafile if the function was +* successful. +* +* Retuns a handle to a new metafile, 0 iff failure +* +* IMPLEMENTATION: +* The source and target metafiles are checked to see if they are both memory +* metafile and if so a piece of global memory is allocated and the metafile +* is simply copied. +* If this is not the case CreateMetaFile is called with lpFileName and then +* records are pulled out of the source metafile (using GetEvent) and written +* into the destination metafile one at a time (using RecordParms). +* +* Lock the source +* if source is a memory metafile and the destination is a memory metafile +* alloc the same size global memory as the source +* copy the bits directly +* else +* get a metafile handle by calling CreateMetaFile +* while GetEvent returns records form the source +* record the record in the new metafile +* +* close the metafile +* +* return the new metafile handle +* +\***************************************************************************/ + +HANDLE GDIENTRY CopyMetaFile(HANDLE hSrcMF, LPSTR lpFileName) +{ + DWORD i; + DWORD iBytes; + LPMETAFILE lpMF; + LPMETAFILE lpDstMF; + LPMETARECORD lpMR = NULL; + HANDLE hTempMF; + HANDLE hDstMF; + NPMETARECORDER pDstMF; + WORD state; + + GdiLogFunc( "CopyMetaFile" ); + + if (!IsValidMetaFile(hSrcMF)) + return NULL; + + if (hSrcMF && (lpMF = (LPMETAFILE) GlobalLock(hSrcMF))) + { + state = (lpMF->MetaFileHeader.mtType == MEMORYMETAFILE) ? 0 : 2; + state |= (lpFileName) ? 1 : 0; + + switch (state) + { + case 0: /* memory -> memory */ + iBytes = GlobalSize(hSrcMF); + if (hDstMF = GlobalAlloc(GMEM_DDESHARE|GMEM_MOVEABLE, (DWORD) iBytes)) + { + lpDstMF = (LPMETAFILE) GlobalLock(hDstMF); + iBytes = iBytes/2; /* get WORD count */ + for (i = 0; i < iBytes; ++i) + *((WORD huge *) lpDstMF)++ = *((WORD huge *) lpMF)++; + + GlobalUnlock(hDstMF); + } + break; + + case 3: /* disk -> disk */ + hDstMF = CopyFile(lpMF->MetaFileBuffer.szPathName, + lpFileName) + ? GetMetaFile(lpFileName) : NULL; + break; + + case 1: + case 2: + if (hDstMF = CreateMetaFile(lpFileName)) + { + while (lpMR = GetEvent(lpMF, lpMR, FALSE)) + if (!RecordParms(hDstMF, lpMR->rdFunction, + lpMR->rdSize - 3, + (LPWORD) lpMR->rdParm)) + { + MarkMetaFile(hDstMF); + LocalFree(hDstMF); + goto CopyMetaFile10; + } + pDstMF = (NPMETARECORDER) NPFROMMETADC(hDstMF); + pDstMF->recordHeader = lpMF->MetaFileHeader; + + pDstMF->recordHeader.mtType = (lpFileName) ? DISKMETAFILE + : MEMORYMETAFILE; + + hDstMF = (hTempMF = CloseMetaFile(hDstMF)) ? hTempMF : NULL; + + } + break; + } + +CopyMetaFile10:; + GlobalUnlock(hSrcMF); + } + return(hDstMF); +} + + +/***************************** Internal Function ***************************\ +* HANDLE GDIENTRY GetMetaFileBits(HANDLE hMF) +* +* The GetMetaFileBits function returns a handle to a global memory block that +* contains the specified metafile as a collection of bits. The memory block +* can be used to determine the size of the metafile or to save the metafile as +* a file. The memory block should not be modified. +* +* Effects: +* +\***************************************************************************/ + +HANDLE GDIENTRY GetMetaFileBits(HANDLE hMF) +{ + GdiLogFunc( "GetMetaFileBits"); + +/* 6/3/88 t-kensy: This code does nothing, except make sure hMF is valid + BOOL status = FALSE; + LPMETAFILE lpMF; + + if (hMF && (lpMF = (LPMETAFILE) GlobalLock(hMF))) + { + if (lpMF->MetaFileHeader.mtType == MEMORYMETAFILE) + { + if (hMF = GlobalReAlloc(hMF, GlobalSize(hMF), + GLOBALMOVABLENONSHARED)) + status = TRUE; + } + GlobalUnlock(hMF); + } + return(status ? hMF : status); +*/ + return (GlobalHandle(hMF) & 0xffff) ? hMF : FALSE; +} + + +/***************************** Internal Function **************************\ +* HANDLE GDIENTRY SetMetaFileBits(HANDLE hMF) +* +* +* +* Effects: +* +\***************************************************************************/ + +HANDLE GDIENTRY SetMetaFileBits(HANDLE hBits) +{ + GdiLogFunc( "SetMetaFileBits"); + +/* return (GlobalReAlloc(hBits, GlobalSize(hBits), GLOBALMOVABLE));*/ + + +//--------------------------------------------------------------------------------- +// We will make GDI take over the ownership of this memory block. This is +// done to help OLE, where either the server or the client could end while +// the other still had the handle to the memory block. This will prevent +// the block to dissapear after the creator exits. The strategy could be +// changed if this causes memory leaks with other application. +// +// Amit Chatterjee. 6/18/91. +//--------------------------------------------------------------------------------- + + return (GlobalReAlloc (hBits, 0L, GMEM_MODIFY | GMEM_DDESHARE)) ; +} +#endif // this is going to gdi.dll + + +/***************************** Internal Function **************************\ +* CopyFile +* +* +* Returns TRUE iff success +* +* +\***************************************************************************/ + +BOOL INTERNAL CopyFile(LPSTR lpSFilename, LPSTR lpDFilename) +{ + int ihSrc, ihDst, iBufferSize; + int iBytesRead; + OFSTRUCT ofStruct; + HANDLE hBuffer; + LPSTR lpBuffer; + BOOL fUnlink = FALSE; + + GdiLogFunc3( "CopyFile"); + + /* Open the source file for reading */ + if ((ihSrc = OpenFile(lpSFilename, &ofStruct, READ)) == -1) + goto CopyError10; + + /* Open the destination file for writing */ + if ((ihDst = OpenFile(lpDFilename, &ofStruct, OF_CREATE | + WRITE)) + == -1) + goto CopyError20; + + /* Get a buffer to transfer the file with */ + if (!(hBuffer = AllocBuffer((LPWORD)&iBufferSize))) + goto CopyError30; + + /* Lock the buffer and get a pointer to the storage */ + if (!(lpBuffer = GlobalLock(hBuffer))) + goto CopyError40; + + /* Copy the file, reading chunks at a time into the buffer */ + do + { + if ((iBytesRead = _lread(ihSrc, lpBuffer, iBufferSize)) + == -1) + goto CopyError40; + + if (_lwrite(ihDst, lpBuffer, iBytesRead) != (WORD)iBytesRead) + goto CopyError40; + } while (iBytesRead == iBufferSize); + +#ifdef FIREWALL + /* if we are able to read anything from the source file at this + * point, then something is wrong! + */ + if (_lread(ihSrc, lpBuffer, iBufferSize)) + { + fUnlink = TRUE; + goto CopyError40; + } +#endif + + /* Everything's fine. Close up and exit successfully */ + if (_lclose(ihSrc) == -1 || _lclose(ihDst) == -1) + goto CopyError40; + + GlobalUnlock(hBuffer); + GlobalFree(hBuffer); + + return TRUE; + +/* Error exit points */ +CopyError40:; + GlobalUnlock(hBuffer); + GlobalFree(hBuffer); +CopyError30:; + _lclose(ihDst); + if (fUnlink) + OpenFile(lpDFilename, &ofStruct, OF_DELETE); + +CopyError20:; + _lclose(ihSrc); + +CopyError10:; + return FALSE; +} + + +/***************************** Internal Function **************************\ +* AllocateSpaceForDIB +* +* The following routine takes as input a device dependent bitmap structure +* and calculates the size needed to store the corresponding DIB structure +* including the DIB bits. It then proceeds to allocate space for it and +* returns a HANDLE to the caller (HANDLE could be NULL if allocation fails) +* +* Returns a global handle to memory or FALSE +* +\***************************************************************************/ + +HANDLE INTERNAL AllocateSpaceForDIB (lpBitmap, pbBitsPerPel, pwColorTableSize, + pdwcBits ) +LPBITMAP lpBitmap ; +LPBYTE pbBitsPerPel ; +LPWORD pwColorTableSize; +LPDWORD pdwcBits ; +{ + int InputPrecision ; + DWORD iBits ; + + GdiLogFunc3( " AllocateSpaceForDIB"); + + /* calculate the number of bits per pel that we are going to have in + the DIB format. This value should correspond to the number of planes + and bits per pel in the device dependent bitmap format */ + + + /* multiply the number of planes and the bits pel pel in the device + dependent bitmap */ + + InputPrecision = lpBitmap->bmPlanes * lpBitmap->bmBitsPixel ; + + + /* DIB precision should be more than or equal this precison, though + the limit is 24 bits per pel */ + + if (InputPrecision == 1) + { + *pbBitsPerPel = 1 ; + *pwColorTableSize = 2 * sizeof (RGBQUAD) ; + } + else if (InputPrecision <= 4) + { + *pbBitsPerPel = 4 ; + *pwColorTableSize = 16 * sizeof (RGBQUAD) ; + } + else if (InputPrecision <= 8) + { + *pbBitsPerPel = 8 ; + *pwColorTableSize = 256 * sizeof (RGBQUAD) ; + } + else + { + *pbBitsPerPel = 24 ; + *pwColorTableSize = 0 ; + } + +/*--------------------------------------------------------------------------** +** calulate the size of the DIB. Each scan line is going to be a mutiple of ** +** a DWORD. Also we shall need to allocate space for the color table. ** +**--------------------------------------------------------------------------*/ + + /* get the number of bits we need for a scanline */ + iBits = lpBitmap->bmWidth * (*pbBitsPerPel); + iBits = (iBits + 31) & (~31) ; + + /* convert to number of bytes and get the size of the DIB */ + iBits = (iBits >> 3) * lpBitmap->bmHeight ; + + /* add the space needed for the color table */ + iBits += *pwColorTableSize ; + + /* add the size for the BITMAPINFOHeader */ + iBits += sizeof(BITMAPINFOHEADER) ; + + /* return back the value for iBits */ + *pdwcBits = iBits ; + + /* actually allocate about 100 bytes more for params */ + iBits += 100 ; + +/*--------------------------------------------------------------------------** +** alocate space for the bitmap info header, the color table and the bits ** +** Return the value of the HANDLE. ** +**--------------------------------------------------------------------------*/ + + return (GlobalAlloc(GMEM_DDESHARE|GMEM_MOVEABLE,(LONG) iBits)) ; +} + + +/***************************** Internal Function **************************\ +* InitializeDIBHeader +* +* This function takes as input a pointer to a BITMAPINFO header structure +* and a pointer to a device dependendent bitmap pointer together with the +* number of bitsperpel requested for the DIB and the color table size. It +* initializes the DIB header and returns a pointer pointing to the first +* word after the color table. ** +* +\***************************************************************************/ + +LPWORD INTERNAL InitializeDIBHeader (lpDIBInfo, lpBitmap, bBitsPerPel, wColorTableSize) + +LPBITMAPINFOHEADER lpDIBInfo ; +LPBITMAP lpBitmap ; +BYTE bBitsPerPel ; +WORD wColorTableSize ; + +{ + LPBYTE lpSpace ; + + GdiLogFunc3( " InitializeDIBHeader"); + + /* Initialize the fields till the start of the color table */ + lpDIBInfo->biSize = sizeof (BITMAPINFOHEADER) ; + lpDIBInfo->biWidth = (DWORD)lpBitmap->bmWidth ; + lpDIBInfo->biHeight = (DWORD)lpBitmap->bmHeight ; + lpDIBInfo->biPlanes = 1 ; + lpDIBInfo->biBitCount = (WORD) bBitsPerPel ; + + lpDIBInfo->biCompression = 0; + lpDIBInfo->biSizeImage = 0; + lpDIBInfo->biXPelsPerMeter = 0; + lpDIBInfo->biYPelsPerMeter = 0; + lpDIBInfo->biClrUsed = 0; + lpDIBInfo->biClrImportant = 0; + + /* take the pointer past the HEADER and cast it to a BYTE ptr */ + lpDIBInfo ++ ; + lpSpace = (LPBYTE) lpDIBInfo ; + + /* take the pointer past the color table structure */ + lpSpace += wColorTableSize ; + + /* return this pointer as a WORD pointer */ + return ((LPWORD) lpSpace) ; +} diff --git a/private/mvdm/wow16/gdi/metasup.c b/private/mvdm/wow16/gdi/metasup.c new file mode 100644 index 000000000..1989bf44f --- /dev/null +++ b/private/mvdm/wow16/gdi/metasup.c @@ -0,0 +1,523 @@ +/****************************** Module Header ******************************\ +* Module Name: MetaSup.c +* +* This file contains the routines for playing the GDI metafile. Most of these +* routines are adopted from windows gdi code. Most of the code is from +* win3.0 except for the GetEvent code which is taken from win2.1 +* +* +* Public Functions: +* EnumMetaFile +* Private Functions: +* +* +* Created: 02-Jul-1991 +* +* Copyright (c) 1985, 1991 Microsoft Corporation +* +* History: +* 02-Jul-1991 -by- John Colleran [johnc] +* Combined From Win 3.1 and WLO 1.0 sources +\***************************************************************************/ + +#include <windows.h> +#include "gdi16.h" + +extern HANDLE hFirstMetaFile; +extern HDC hScreenDC; + +#define MYSTOCKBITMAP (SYSTEM_FIXED_FONT+1) +#define MYSTOCKRGN (SYSTEM_FIXED_FONT+2) +#define CNT_GDI_STOCK_OBJ (MYSTOCKRGN+1) + +HANDLE ahStockObject[CNT_GDI_STOCK_OBJ] = {-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1}; +HBITMAP hStaticBitmap; + +// Provide a Mapping from Object type to a stock object; See GetCurObject +int mpObjectToStock[] = + { -1, // UNUSED 0 + WHITE_PEN, // OBJ_PEN 1 + BLACK_BRUSH, // OBJ_BRUSH 2 + -1, // OBJ_DC 3 + -1, // OBJ_METADC 4 + DEFAULT_PALETTE, // OBJ_PALETTE 5 + SYSTEM_FONT, // OBJ_FONT 6 + MYSTOCKBITMAP, // OBJ_BITMAP 7 + MYSTOCKRGN, // OBJ_RGN 8 //!!!!! init + -1, // OBJ_METAFILE 9 + -1 }; // OBJ_MEMDC 10 + + +HANDLE INTERNAL GetCurObject(HDC hdc, WORD wObjType) +{ + HANDLE cur; + + +//!!!!! fix to work with meta DCs as well + + GdiLogFunc3( " GetCurObject" ); + + ASSERTGDI( wObjType <= MAX_OBJ, "GetCurObject invalid Obj" ); + +//!!!!! fix regions when new API is done + if( wObjType == OBJ_RGN ) + { + return(0); + } + + if( wObjType == OBJ_PALETTE) + { + cur = SelectPalette( hdc, ahStockObject[DEFAULT_PALETTE], FALSE ); + SelectPalette( hdc, cur, FALSE ); + } + else + { + cur = SelectObject(hdc,ahStockObject[mpObjectToStock[wObjType]]); + SelectObject( hdc, cur ); + } + + ASSERTGDIW( cur, "GetCurObect Failed. Type %d", wObjType ); + return(cur); +} + +#if 0 // this is going to gdi.dll + +/******************************** Public Function **************************\ +* BOOL GDIENTRY EnumMetaFile(hmf) +* +* The EnumMetaFile function enumerates the GDI calls within the metafile +* identified by the hMF parameter. The EnumMetaFile function retrieves each +* GDI call within the metafile and passes it to the function pointed to by the +* lpCallbackFunc parameter. This callback function, an application-supplied +* function, can process each GDI call as desired. Enumeration continues until +* there are no more GDI calls or the callback function returns zero. +* +* +* Effects: +* +\***************************************************************************/ + +BOOL GDIENTRY EnumMetaFile(hdc, hMF, lpCallbackFunction, lpClientData) +HDC hdc; +LOCALHANDLE hMF; +FARPROC lpCallbackFunction; +LPBYTE lpClientData; +{ + WORD i; + WORD noObjs; + BOOL bPrint=TRUE; + HANDLE hObject; + HANDLE hLBrush; + HANDLE hLPen; + HANDLE hLFont; + HANDLE hRegion; + HANDLE hPalette; + LPMETAFILE lpMF; + LPMETARECORD lpMR = NULL; + LPHANDLETABLE lpHandleTable = NULL; + GLOBALHANDLE hHandleTable = NULL; + + + GdiLogFunc( "EnumMetaFile"); + + if (!ISDCVALID(hdc)) + { + ASSERTGDI( FALSE, "EnumMetaFile: DC is invalid"); + return (FALSE); + } + +/* use GlobalFix() instead of GlobalLock() to insure that the +** memory never moves, keeping our aliased selector pointing to the +** right place +*/ +// !!!!! replaced GlobalFix with GlobalLock + if (hMF && (lpMF = (LPMETAFILE)(DWORD)(0xFFFF0000 & (DWORD)GlobalLock(hMF)))) + { + if ((noObjs = lpMF->MetaFileHeader.mtNoObjects) > 0) + { + if (!(hHandleTable = + GlobalAlloc((WORD)(GMEM_ZEROINIT | GMEM_MOVEABLE), (LONG) + ((sizeof(HANDLE) * lpMF->MetaFileHeader.mtNoObjects) + + sizeof(WORD))))) + { + goto ABRRT2; + } + lpHandleTable = (LPHANDLETABLE)GlobalLock(hHandleTable); + } + + /* only do object save/reselect for real DC's */ + if (hdc && !ISMETADC(hdc)) + { + hLPen = GetCurObject( hdc, OBJ_PEN ); /* save the old objects so */ + hLBrush = GetCurObject( hdc, OBJ_BRUSH); /* we can put them back */ + hLFont = GetCurObject( hdc, OBJ_FONT); + hRegion = GetCurObject( hdc, OBJ_RGN); + hPalette = GetCurObject( hdc, OBJ_PALETTE); + } + + while(lpMR = GetEvent(lpMF, lpMR, FALSE)) + { + typedef int (FAR PASCAL *ENUMPROC)(HDC, LPHANDLETABLE, LPMETARECORD, int, LPBYTE); + + if ((bPrint = (*((ENUMPROC)lpCallbackFunction))(hdc, lpHandleTable, lpMR, noObjs, lpClientData)) + == 0) + { + GetEvent(lpMF,lpMR,TRUE); + break; + } + } + + if (hdc && !ISMETADC(hdc)) + { + SelectObject(hdc, hLPen); + SelectObject(hdc, hLBrush); + SelectObject(hdc, hLFont); + if (hRegion) + SelectObject(hdc, hRegion); + SelectPalette(hdc, hPalette, 0); + } + + for(i = 0; i < lpMF->MetaFileHeader.mtNoObjects; ++i) + if (hObject = lpHandleTable->objectHandle[i]) + DeleteObject(hObject); + + if (hHandleTable) + { + GlobalUnlock(hHandleTable); + GlobalFree(hHandleTable); + } +ABRRT2:; + GlobalUnfix(hMF); + } + return(bPrint); +} +#endif // this is going to gdi.dll + +/***************************** Internal Function **************************\ +* BOOL FAR PASCAL PlayIntoAMetafile +* +* if this record is being played into another metafile, simply record +* it into that metafile, without hassling with a real playing. +* +* Returns: TRUE if record was played (copied) into another metafile +* FALESE if destination DC was a real (non-meta) DC +* +* Effects: ? +* +* Warnings: ? +* +\***************************************************************************/ + +BOOL INTERNAL PlayIntoAMetafile(LPMETARECORD lpMR, HDC hdcDest) +{ + GdiLogFunc3( " PlayIntoAMetafile"); + + if (!ISMETADC(hdcDest)) + return(FALSE); + else + { + /* the size is the same minus 3 words for the record header */ + RecordParms(hdcDest, lpMR->rdFunction, (DWORD)lpMR->rdSize - 3, + (LPWORD)&(lpMR->rdParm[0])); + return(TRUE); + } +} + +BOOL INTERNAL IsDCValid(HDC hdc) +{ + NPMETARECORDER npdc; + + hdc = (HDC)HANDLEFROMMETADC(hdc); + + // Is the DC a valid Real DC + switch (GetObjectType(hdc)) + { + case OBJ_DC: + case OBJ_METADC: + case OBJ_MEMDC: + return(TRUE); + break; + } + + // Is the DC a GDI16 metafile DC + if (npdc = (NPMETARECORDER)LocalLock(hdc)) + { + if( npdc->metaDCHeader.ident == ID_METADC ) + return(TRUE); + } + + ASSERTGDI(FALSE, "Invalid DC"); + return(FALSE); +} + + +/***************************** Internal Function **************************\ +* IsMetaDC(hdc) +* +* +* Returns TRUE iff hdc is a valid GDI16 Metafile +* +* +\***************************************************************************/ + +BOOL INTERNAL IsMetaDC(HDC hdc) +{ + NPMETARECORDER npdc; + BOOL fMeta = FALSE; + + GdiLogFunc3(" IsMetaDC"); + + if( ((UINT)hdc) & METADCBIT ) + if( npdc = (NPMETARECORDER)LocalLock( (HANDLE)HANDLEFROMMETADC(hdc))) + { + if( npdc->metaDCHeader.ident == ID_METADC ) + fMeta = TRUE; + + LocalUnlock( (HANDLE)HANDLEFROMMETADC(hdc) ); + } + + return( fMeta ); +} + + +/***************************** Public Function ****************************\ +* HANDLE INTERNAL GetPMetaFile( HDC hdc ) +* +* if hdc is a DC it is validated as a metafile +* if hdc is a PALETTE the metafile the palette is selected into is returned +* +* Returns: +* -1 iff Error +* HANDLE to metafile if valid meta DC +* 0 if valid object +* +* Effects: +* +* History: +* 08-Jul-1991 -by- John Colleran [johnc] +* Wrote it. +\***************************************************************************/ + +HANDLE INTERNAL GetPMetaFile( HDC hdc ) +{ + NPMETARECORDER npMR; + + GdiLogFunc3( " GetPMetaFile"); + + + if( hdc & METADCBIT ) + { + if( npMR = (NPMETARECORDER)LocalLock(HANDLEFROMMETADC(hdc)) ) + { + if(npMR->metaDCHeader.ident == ID_METADC ) + { + LocalUnlock(HANDLEFROMMETADC(hdc)); + return( HANDLEFROMMETADC(hdc) ); + } + LocalUnlock(HANDLEFROMMETADC(hdc)); + } + } + + // is hdc really a palette or object for the strange no-DC APIs + // Validate the object is real + if( (hdc != (HDC)NULL) && (GetObjectType( hdc ) == 0)) + { + extern int iLogLevel; // Gdi.asm + // WinWord has a bug where it deletes valid objects so + // only log this error if the loglevel is high. + ASSERTGDI( (iLogLevel < 5), "GetPMetaFile: Invalid metafile or object") + return( -1 ); // Not a valid object + } + else + return( 0 ); // Valid Object +} + + +BOOL INTERNAL IsObjectStock(HANDLE hObj) +{ + int ii; + + // handle Bitmaps and regions !!!!! + + // Get all the Stock Objects + for( ii=WHITE_BRUSH; ii<=NULL_PEN; ii++ ) + if( ahStockObject[ii] == hObj ) + return( TRUE ); + + for( ii=OEM_FIXED_FONT; ii<=SYSTEM_FIXED_FONT; ii++ ) + if( ahStockObject[ii] == hObj ) + return( TRUE ); + + return( FALSE ); +} + +/***************************** Internal Function **************************\ +* GetObjectAndType +* +* +* Returns the object type, eg OBJ_FONT, as well as a the LogObject +* +* +\***************************************************************************/ + +int INTERNAL GetObjectAndType(HANDLE hObj, LPSTR lpObjectBuf) +{ + int iObj = -1; + + GdiLogFunc3( " GetObjectAndType" ); + + GetObject(hObj, MAXOBJECTSIZE, lpObjectBuf); + switch( iObj = (int)GetObjectType(hObj) ) + { + case OBJ_PEN: + case OBJ_BITMAP: + case OBJ_BRUSH: + case OBJ_FONT: + break; + + // Watch out for Palettes; returns the number of entries. + case OBJ_PALETTE: + GetPaletteEntries( hObj, 0, 1, (LPPALETTEENTRY)lpObjectBuf ); + iObj = OBJ_PALETTE; + break; + + case OBJ_RGN: + break; + + default: + ASSERTGDIW( 0, "GetObject unknown object type: %d", iObj); + break; + } + return( iObj ); +} + + +/***************************** Internal Function **************************\ +* BOOL GDIENTRY InitializeGdi +* +* Initializes the GDI16.exe +* +* +* Effects: +* +* Returns: TRUE iff GDI was initilized successfully +* +\***************************************************************************/ + +BOOL INTERNAL InitializeGdi(void) +{ +BOOL status; +int ii; + + GdiLogFunc2 ( " InitializeGDI"); + if( !(hScreenDC = CreateCompatibleDC(NULL))) + goto ExitInit; + + // Get all the Stock Objects + for( ii=WHITE_BRUSH; ii<=NULL_PEN; ii++ ) + ahStockObject[ii] = GetStockObject( ii ); + + for( ii=OEM_FIXED_FONT; ii<=SYSTEM_FIXED_FONT; ii++ ) + ahStockObject[ii] = GetStockObject( ii ); + + // Create a fake Stock Region and Bitmap + ahStockObject[MYSTOCKRGN] = CreateRectRgn(1,1,3,3); + hStaticBitmap = ahStockObject[MYSTOCKBITMAP] = CreateBitmap(1,1,1,1,NULL); + + status = TRUE; + + ExitInit: + ASSERTGDI( status, "GDI16 Failed to initialized correctly"); + return( status ); +} + + +/*************************************************************************** + + debugging support + +***************************************************************************/ + +#ifdef DEBUG + +void dDbgOut(int iLevel, LPSTR lpszFormat, ...) +{ + char buf[256]; + char far *lpcLogLevel; + extern int iLogLevel; // Gdi.asm + extern int iBreakLevel; // Gdi.asm + + // Get the external logging level from the emulated ROM + + (LONG)lpcLogLevel = 0x00400042; + if (*lpcLogLevel >= '0' && *lpcLogLevel <= '9') + iLogLevel = (*lpcLogLevel-'0')*10+(*(lpcLogLevel+1)-'0'); + + if (iLevel<=iLogLevel) + { + OutputDebugString(" W16GDI:"); + wvsprintf(buf, lpszFormat, (LPSTR)(&lpszFormat + 1)); + OutputDebugString(buf); + OutputDebugString("\r\n"); + + if( iLevel<=iBreakLevel ) + _asm int 3; + } +} + +void dDbgAssert(LPSTR str, LPSTR file, int line) +{ + static char buf3[256]; + + wsprintf(buf3, "Assertion FAILED: %s %d : %s", file, line, str ); + OutputDebugString(buf3); + OutputDebugString("\r\n"); + _asm int 3; +} + + + +#undef LocalLock +#undef LocalUnlock +#undef LocalAlloc +#undef GlobalLock +#undef GlobalUnlock +#undef GlobalAlloc +PSTR INTERNAL _LocalLock(HANDLE h ) +{ +PSTR p; +dDbgOut(7, "LocalLock 0x%X", h ); +p = LocalLock(h); +if( p == NULL ) + _asm int 3 +return( p ); +} +BOOL INTERNAL _LocalUnlock(HANDLE h ) +{ +dDbgOut(7, "LocalUnlock 0x%X", h ); +return( LocalUnlock(h) ); +} +HANDLE INTERNAL _LocalAlloc(WORD w, WORD w2) +{ +dDbgOut(7, "LocalAlloc"); +return( LocalAlloc(w,w2) ); +} +LPSTR INTERNAL _GlobalLock(HANDLE h ) +{ +dDbgOut(7, "GlobalLock 0x%X", h ); +return( GlobalLock(h) ); +} +BOOL INTERNAL _GlobalUnlock(HANDLE h ) +{ +dDbgOut(7, "GlobalUnlock 0x%X", h ); +return( GlobalUnlock(h) ); +} +HANDLE INTERNAL _GlobalAlloc(WORD w, DWORD dw ) +{ +dDbgOut(7, "GlobalAlloc"); +return( GlobalAlloc(w,dw) ); +} + + + +#endif diff --git a/private/mvdm/wow16/gdi/muldiv.asm b/private/mvdm/wow16/gdi/muldiv.asm new file mode 100644 index 000000000..066fd0f8d --- /dev/null +++ b/private/mvdm/wow16/gdi/muldiv.asm @@ -0,0 +1,110 @@ + Title Muldiv - (A*B)/C With Correct Rounding + %out MulDiv + page ,132 +;----------------------------Module-Header------------------------------; +; Module Name: muldiv.asm +; +; (w * Numer) / Denom with correct rounding. +; +; Created: +; Author: +; +; Copyright (c) 1985, 1986, 1987 Microsoft Corporation +; +; MulDiv(w, Numer, Denom) returns (w * Numer) / Denom rounded to the nearest +; integer. A check is made so that division by zero is not attempted. +;-----------------------------------------------------------------------; + + + .xlist + include cmacros.inc +; include gditype.inc + .list + + +sBegin code +assumes cs,code + +;--------------------------Public-Routine-------------------------------; +; short FAR PASCAL MulDiv(short, short, short) +; short w; +; short Numer; +; short Denom; +; +; (w * Numer)/ Denom with correct rounding. +; +; Returns: AX = result. +; DX = 1 if no overflow. +; DX = 0 if overflow. +; +; Preserves: BX,CX +; Doesn't lose: SI,DI,ES,DS +; +; Warnings: +; +; Effects: +; +; History: +; Mon 22-Dec-1986 17:08:55 -by- Kent Settle [kentse] +; Added headers and comments. +;-----------------------------------------------------------------------; + +cProc MulDiv,<FAR,PUBLIC>,<bx,cx> + + parmW <w, Numer, Denom> + +cBegin MulDiv + + mov bx,Denom ; get the demoninator + mov cx,bx ; CX holds the final sign + or bx,bx ; ensure the denominator is positive + jns md1 + neg bx + +md1: + mov ax,w ; get the word we are multiplying + xor cx,ax ; make CX reflect any sign change + or ax,ax ; ensure this word is positive + jns md2 + neg ax + +md2: + mov dx,Numer ; get the numerator + xor cx,dx ; make CX reflect any sign change + or dx,dx ; ensure the numerator is positive + jns md3 + neg dx + +md3: + mul dx ; multiply + mov cl,bl ; get half of the demoninator to adjust for rounding + sar bx,1 + add ax,bx ; adjust for possible rounding error + adc dx,0 ; this is really a long addition + sal bx,1 ; restore the demoninator + or bl,cl + cmp dx,bx ; check for overflow + jae md5 ; (ae handles /0 case) + div bx ; divide + or ax,ax ; If sign is set, then overflow occured + js md5 ; Overflow. + or cx,cx ; put the sign on the result + jns md4 + neg ax +md4: + mov dx,1 ; indicate no overflow. +md6: + +cEnd MulDiv + + +md5: + xor dx,dx ; indicate overflow. + mov ax,7FFFh ; return the largest integer + or cx,cx ; with the correct sign + jns md6 + not ax + jmp md6 + +sEnd code +end diff --git a/private/mvdm/wow16/gdi/sort.asm b/private/mvdm/wow16/gdi/sort.asm new file mode 100644 index 000000000..bf072ad03 --- /dev/null +++ b/private/mvdm/wow16/gdi/sort.asm @@ -0,0 +1,706 @@ +;----------------------M O D U L E H E A D E R----------------------------; +; ; +; Module Name: SORT.ASM ; +; ; +; History: SORT.C ; +; Created by Charles Whitmer 12/30/1986 ; +; Modified by Mitchel B. London 08/05/1987 ; +; ; +; SORT.ASM - translation of SORT.C ; +; CreateModule David Weise ; +; Other Modules Amit Chatterjee 08/09/1988 ; +; ; +; Copyright (c) 1985 - 1988 Microsoft Corporation ; +; ; +; General Description: ; +; ; +; The SORT module creates and maintains a tree of nodes, each node ; +; having a KEY value and a TAG field. The KEY field is used to or- ; +; -ganize the tree into a heap. ; +; The heap tree is implemented using an array, where if ; +; parent node occurs in position i, its left child will be at index ; +; (2 * i) and the right chaild at index (2 * i + 1). ; +; The Module ensures that at any instant, the root node ; +; of any subtree has the least key value in the subtree. ; +; First few positions in the array are used for storing ; +; a header for the tree. ; +; ; +; SubModules: ; +; ; +; 1. CreatePQ: ; +; Allocates space for the heaptree and its header ; +; and initializes the header. ; +; 2. InsertPQ: ; +; Inserts a node into the heap ensuring that the heap ; +; property is not violated. ; +; 3. MinPQ: ; +; Returns the tag value associated with the lowest ; +; key in the heap. (node is not deleted) ; +; 4. ExtractPQ: ; +; Return the tag value associated with the lowest key ; +; in the heap and deletes the node. The heap is then ; +; reconstructed with the remaining nodes. ; +; 5. DeletePQ: ; +; Deletes the entire heap by freeing the allocated ; +; area. ; +; 6. SizePQ: ; +; Increases the size of the heap by adding space ; +; for a requested number of entries ; +; Heap Data Structure: ; +; ; +; The heap data structure has two parts, a header and a set of nodes and ; +; these are blocked one after the other. ; +; The header maintains: ; +; (i) A pointer to the next available node slot ; +; relative to start of the node area ; +; (ii) A pointer to the first valid node slot ; +; node slots between the header and this pointer ; +; are actually deleted nodes ; +; (iii) A pointer past the last allocated node slot ; +; (iv) A last key value, which either holds the largest; +; key value as long as the nodes are sequentially ; +; ordered, or a very large value to indicate there; +; is no sequential ordering ; +; ; +; ---------------- ; +; | INDEX | ---- Pointer to next available node slot ; +; ---------------- ; +; | MAXENTRY | ---- Pointer past last allocated node slot ; +; ---------------- ; +; START | LASTKEY | ---- Aslong as possible holds max key ; +; NODE | START | ---- pointer to first active node slot ; +; ---------------- ; +; | KEY | ---- Node 1. ; +; | TAG | ; +; //---------------// ; +; | KEY | ---- Last allocated node slot ; +; | TAG | ; +; ---------------- ; +; ; +; All pointers to nodes are relative to node 1 (pointer to node 1 is ZERO) ; +;----------------------------------------------------------------------------; +;----------------------------------------------------------------------------; +; Include File Section and definitions: ; +; ; + + .xlist + include cmacros.inc + include gdimacro.inc + include gdimem.inc + .286p + .list + +START equ SIZE PQ - SIZE ENTRY ; The header includes Node 0 + +VERYLARGE equ 4000h ; assumed to be larger than any key +PQERROR equ -1 ; return value on error +TRUE equ 1 +FALSE equ 0 + +Entry struc + e_key dw ? ; key value of node + e_tag dw ? ; corresponding tag value +Entry ends + +PQ struc ; HEAP Header Structure + Start Node + pq_index dw ? + pq_maxentry dw ? ; excludes START NODE + pq_lastkey dw ? + pq_start dw ? +PQ ends + + + externFP GlobalLock + externFP GlobalUnlock + externFP GlobalReAlloc + externFP GlobalFree + externFP GlobalAlloc ; Defined in HELPER.ASM + +createSeg _SORT,SORT,byte,public,CODE +sBegin SORT + +;-----------------------------------------------------------------------------; +; ; +;CreatePQ: ; +; Inputs: ; +; Max Number of entries the tree will hold ; +; Outputs: ; +; HANDLE to Heap -- if creation successful ; +; PQERROR if failure ; +; Registers Preserved: ; +; DI,SI ; +; ; +; -by- David Weise [davidw] ; +; ; +;-----------------------------------------------------------------------------; + + assumes cs,SORT + assumes ds,nothing + +cProc farGDIGlobalAlloc,<FAR,PUBLIC> + + parmd amount +cBegin + cCall GlobalAlloc,<GMEM_MOVEABLE+GMEM_SHARE,amount> +cEnd + +cProc CreatePQ,<FAR,PUBLIC,NODATA>,<di,si> + parmW cEntries + +cBegin + mov ax,cEntries ; max no of nodes the tree will hold + shl ax,1 + shl ax,1 ; ax <---- ax * SIZE ENTRY + .errnz (SIZE ENTRY - 4) + mov si,ax ; save number of bytes in node array + add ax, SIZE PQ ; size of header including NODE 0 + xor dx,dx + cCall farGDIGlobalAlloc,<dx,ax> + mov bx,ax ; Handle returned + dec ax ; set to -1 if handle returned == 0 + .errnz (-1 - PQERROR) + or bx,bx ; test for succesfull memory allocation + jz cPQ_Done ; error return. + push bx + cCall GlobalLock,<bx> ; lock handle get back segment + pop bx + mov es,dx + mov di,ax ; es:di points to start of structure + +; now initialize the header part of the structure with values +; si has size of the node array + + stosw ; index set to zero + .errnz (0 - pq_index) + mov ax,si ; pointer past end of node array + stosw ; max no of entries + .errnz (2 - pq_maxentry) + xor ax,ax ; last key = 0, as heap empty + stosw + .errnz (4 - pq_lastkey) + stosw ; START = 0, implies no deleted slot + .errnz (6 - pq_start) + + push bx + cCall GlobalUnlock,<bx> ; unlock the handle to heap + pop ax ; return the handle + +cPQ_Done: + +cEnd + +;-----------------------------------------------------------------------------; +; ; +; InsertPQ: ; +; Inputs: ; +; hPQ -- handle to heap structure segment ; +; tag -- tag value for new node ; +; key -- key value for new node ; +; Outputs: ; +; return TRUE if insertion was successful ; +; return PQERROR if heap was already packed ; +; Preserves: ; +; DS,SI ; +; ; +; -by- Amit Chatterjee [amitc] Tue Aug 9 10:45:25 ; +;----------------------------------------------------------------------------- + + assumes cs,SORT + assumes ds,nothing + +cProc InsertPQ,<FAR,PUBLIC,NODATA>,<di,si> + parmW hPQ + parmW tag + parmW key + +cBegin + mov di,hPQ + cCall GlobalLock,<di> ; lock heap and get back segment addres + or ax,dx ; Invalid handle causes zero return + jz Ins_Cant_Proceed + mov es,dx + xor si,si ; offset in segment always zero + mov ax,es:[si] ; pointer to next available slot + sub ax,es:[si].pq_start ; convert it relative to 1st active node + cmp ax,es:[si].pq_maxentry ; compare with pointer past last slot + jb Insertion_Possible + cCall GlobalUnlock,<di> +Ins_Cant_Proceed: + mov ax,PQERROR ; error return + jmp cInsert_Done + +Insertion_Possible: + push es ; HEAP structure segment + smov es,ds ; save local segment in es + pop ds ; change DS to heap segment + mov ax,[si].pq_index ; next available slot in node area + cmp ax,[si].pq_maxentry + jb Enough_Space_Atend ; insertion possible w/o compaction + +; Deleted nodes exist near the head of the tree, compaction necessary + call CompactList ; removes all deleted elements + +; LASTKEY still holds the max key value in the tree + +Enough_Space_Atend: + mov bx,[si].pq_index ; pointer to next available slot + mov dx,bx ; save value in register + add bx,SIZE PQ ; area for header + mov ax,tag + mov [si][bx].e_tag,ax ; insert new tag and key + mov ax,key + mov [si][bx].e_key,ax ; key in ax will be used below + mov bx,dx ; bx points to last occupied slot + add dx,SIZE ENTRY ; available slot points to next node + mov [si].pq_index,dx ; save in the structure + +; Now test whether the heap property is valid still. +; ax has key, dx has pointer to next slot after addition +; bx points to last valid node + + cmp ax,[si].pq_lastkey ; compare with new key + jb Heap_Violated + mov [si].pq_lastkey,ax ; new key is the largest key in tree + jmp short Heap_Restructured ; Insertion over + +comment ~ + + node i has lchild at 2*i and rchild at 2*i+1. But we maintain their + address relative to start of node array. [ie node 1 has addr 0, + node 2 has 4, node 3 12 and so on.] + so if x happens to be the address of a node, the address of its + parent is (x/2 -2) AND 0fffch. + if x is the address of a parent, the address of its lchild is 2*x + 4 + and that of its rchild is 2*x + 8 + +end comment ~ + +Heap_Violated: + call CompactList ; make sure heap is compacted first! + mov [si].pq_lastkey,VERYLARGE ; to imply heap nolonger seq. ordered + mov bx,[si].pq_index ; bx = offset of inserted elem. + sub bx,SIZE ENTRY + +Heap_Walk_Loop: + cmp bx,[si].pq_start ; traversed to top of heap ? + jz Heap_Restructured + mov cx,bx + shr cx,1 ; cx points to parent of current node + dec cx + dec cx + and cx,0fffch ; refer to comment above + .errnz (SIZE ENTRY - 4) + +; Test whether current node has to move up or not, if not it resets carry +; else it swaps the two nodes and sets carry + + call TestShuffle + mov bx,cx ; next node to inspect ifnec. is parent + jc Heap_Walk_Loop + +Heap_Restructured: + smov ds,es ; get back own segment in ds + cCall GlobalUnlock,<di> ; di still has the handle + mov ax,di ; return true + +cInsert_Done: +cEnd + + +;-----------------------------------------------------------------------------; +; TestShuffle: ; +; ; +; Takes as input the node addresses of a parent and on of it's childs. If the; +; key of the parent is >= key of the child, it returns with carry clear, else; +; it swaps the two nodes and returns with carry set. ; +; ; +; bx has current node address in HEAP, relative to start NODE 1 ; +; cx has address of parent node of bx ; +; ; +; -by- Amit Chatterjee [amitc] Tue Aug 9 12:00:00 ; +;-----------------------------------------------------------------------------; + +cProc TestShuffle,<NEAR,PUBLIC>,<si,di> + +cBegin + lea di,[si][SIZE PQ] ; di points to node 1 + add di,cx ; di points to parent + lea si,[bx].SIZE PQ ; si points to child node + mov ax,[si].e_key ; childs key + cmp ax,[di].e_key ; key of parent + jb Nodes_Tobe_Swapped +; +; Carry cleared by comparision, use for return +; + jmp short TestShuffle_Ret + +Nodes_Tobe_Swapped: +; +; Carry has been set by comparision, use for return +; + xchg ax,[di].e_key + mov [si].e_key,ax + mov ax,[si].e_tag + xchg ax,[di].e_tag + mov [si].e_tag,ax ; swap complete +TestShuffle_Ret: + +cEnd + +;-----------------------------------------------------------------------------; +; MinPQ: ; +; Inputs: ; +; hPQ -- Handle to the heap structure ; +; Outputs: ; +; minimum tag value in the tree or PQERROR(if invalid handle) ; +; ; +; Calls Local Procedure GetMinPQ. ; +; GetMinPQ takes the handle and a flag as parameter. ; +; If the flag is TRUE, the node with the least key is deleted ; +; GetMinPQ also returns the tag value of least key in AX ; +; ; +; ; +; -by- Amit Chatterjee [amitc] Tue Aug 9 12:46:10 ; +;-----------------------------------------------------------------------------; + + assumes cs,SORT + assumes ds,nothing + +cProc MinPQ,<FAR,PUBLIC,NODATA> +; parmW hPQ + +cBegin nogen + + mov cl,FALSE ; to imply node not to be deleted + jmpnext ; fall through trick, refer cmacros + +cEnd nogen + +;-----------------------------------------------------------------------------; +; ExtractPQ: ; +; Inputs: ; +; hPQ -- Handle to the heap structure ; +; Outputs: ; +; minimum tag value if heap handle is valid and heap not empty ; +; return PQERROR otherwise ; +; The node with min key is deleted ; +; Calls Local Procedure GetMinPQ ; +; ; +; -by- Amit Chatterjee [amitc] Tue Aug 9 12:54:00 ; +;-----------------------------------------------------------------------------; + + assumes cs,SORT + assumes ds,nothing + +cProc ExtractPQ,<FAR,PUBLIC,NODATA> +; parmW hPQ + + +cBegin nogen + + mov cl,TRUE ; to imply that node to be deleted + jmpnext stop ; fall through trick, refer cmacros + +cEnd nogen + +;-----------------------------------------------------------------------------; +; GetMinPQ: ; +; ; +; One of the inputs is a flag. If the flag is FALSE it simply returns the tag ; +; associated with the lease key value in the heap. If the flag is TRUE besides; +; returnning the above tag value it also deletes the node. ; +; ; +; ; +; hPQ --- handle of HEAP segment ; +; cl --- Deletion Flag ( Delete node if TRUE) ; +; ; +; -by- Amit Chatterjee [amitc] Tue Aug 9 13:00:00 ; +;-----------------------------------------------------------------------------; + +cProc GetMinPQ,<FAR,PUBLIC,NODATA>,<di,si> + parmW hPQ +cBegin + mov di,hPQ + push cx ; save flag + cCall GlobalLock,<di> + pop cx ; get back flag into cl + or dx,ax ; invalid handle implies zero return + jz Min_Cant_Proceed + mov es,dx + mov si,ax ; ds:si points to heap start + mov bx,es:[si].pq_start ; pointer to 1st. available slot + cmp bx,es:[si].pq_index ; empty if equal to next available node + jb Heap_Not_Empty + cCall GlobalUnlock,<di> + +Min_Cant_Proceed: + mov ax,PQERROR + jmp cGetMin_Done ; error return + +; bx still has [si].pq_start + +Heap_Not_Empty: + push es ; save heap segment + smov es,ds ; save local segment is es + pop ds ; ds:si points to start of heap + lea dx,[si][SIZE PQ] + add dx,bx ; points past deleted nodes + xchg di,dx ; save di in dx and use dx's value + mov ax,[di].e_tag ; get the tag associated with least key + xchg di,dx ; get back values + or cl,cl ; test for bl = FALSE + .errnz (0 - FALSE) + jnz Delete_Node ; TRUE implies get tag and delete node + jmp cGetMin_Ret ; return after unlocking heap + +Delete_Node: + +; bx retains [si].start + + add bx,SIZE ENTRY ; one more node deleted + cmp bx,[si].pq_index ; is tree empty ? + jb Tree_Not_Empty + xor cx,cx + mov [si].pq_lastkey,cx ; initialize for empty tree + mov [si].pq_start,cx ; initialize for empty tree + mov [si].pq_index,cx + jmp cGetMin_Ret ; return after unlocking heap + +Tree_Not_Empty: + +; ax has return tag value +; bx has [si].pq_start + SIZE ENTRY + + cmp [si].pq_lastkey,VERYLARGE ; implies keys in random order + jae Min_Restructure_Heap ; maybe restructuring necessary + mov [si].pq_start,bx ; updates past deleted entry + jmp cGetMin_Ret + +Min_Restructure_Heap: + +; dx still has offset to NODE 1, because +; if LASTKEY = VERYLARGE, pq_start has to be zero + + push ax ; save return tag value + mov bx,dx ; offset to first active node + xchg di,dx ; get pointer into di ,save di + add di,[si].pq_index ; dx points to next available slot + sub di,SIZE ENTRY ; point to last filled node + mov ax,di ; last node being moved upfront + sub ax,SIZE PQ ; point ax one node ahead of last + mov [si].pq_index,ax ; update it + mov cx,[di].e_key + mov [bx].e_key,cx ; move from last position to NODE 1 + mov cx,[di].e_tag + mov [bx].e_tag,cx + xchg di,dx ; restore di,dx + xor cx,cx ; start traversing heap from root + + +Min_Traverse_Heap: + mov bx,cx + shl bx,1 + add bx,SIZE ENTRY ; bx has left child addr of parent in cx + cmp bx,[si].pq_index ; compare with next available slot + jae Min_Heap_Fixed ; heap restored + push cx ; save current parent + mov cx,bx ; have lchild in cx + add cx,SIZE ENTRY ; cx now get address of rchild + cmp cx,[si].pq_index ; test against last node + jae Right_Child_Not_Present + call GetLesserChild ; gets child with lesser key in bx + +Right_Child_Not_Present: + pop cx ; get back parent +; +; cx has node number of parent node and bx has node no of child node with +; least key. If parents key value is greater it should be swapped +; + call TestShuffle + +; swaps the two nodes if necessary. + + mov cx,bx ; lesser child is next parent + jmp Min_Traverse_Heap + +Min_Heap_Fixed: + pop ax ; get back return tag value +cGetMin_Ret: + push ax ; save return value + smov ds,es ; get back own ds + cCall GlobalUnlock,<di> ; unlock heap + pop ax ; get back return value +cGetMin_Done: + +cEnd + +;-----------------------------------------------------------------------------; +; GetLesserChild: ; +; ; +; Given two child node numbers, it returns the child which has a lesser key ; +; ; +; cx has RCHILD NODE address ; +; bx has LCHILD NODE address ; +; si points to start of heap ; +; will return node address of lesser child in bx ; +; ; +; -by- Amit Chatterjee [amitc] Tue Aug 9 13:50 ; +;-----------------------------------------------------------------------------; + + +cProc GetLesserChild,<NEAR,PUBLIC,NODATA>,<di,si> + +cBegin + lea di,[si][SIZE PQ] ; dx now points to NODE 1 + mov si,di ; si also points to start of NODE 1 + add di,cx ; di get address of rchild + mov ax,[si+bx].e_key ; rchilds key + cmp ax,[di].e_key ; compare with rchild + jb Right_Child_Lesser ; bx still has the correct child no. + mov bx,cx ; get RCHILD address into bx +Right_Child_Lesser: + +cEnd +; +;-----------------------------------------------------------------------------; +; DeletePQ: ; +; Inputs: ; +; hPQ --- handle to a heap structure ; +; OutPuts: nothing ; +; Preserves: DI ; +; ; +; -by- Amit Chatterjee [amitc] Tue Aug 9 14:15:45 ; +;----------------------------------------------------------------------------- +; + assumes cs,SORT + assumes ds,nothing + +cProc DeletePQ,<FAR,PUBLIC,NODATA> + parmW hPQ + +cBegin + cCall GlobalFree,<hPQ> ; free the handle +cEnd + +;-----------------------------------------------------------------------------; +;SizePQ: ; +; Input: ; +; hPQ --- Handle to a heap structure ; +; entry --- number of nodes by which heap is to be expanded ; +; Output: ; +; Returns the total number of node slots in new heap, if successful +; else return PQERROR ; +; ; +; -by- Amit Chatterjee [amitc] Tue Aug 9 14:31:40 ; +;----------------------------------------------------------------------------- + + assumes cs,SORT + assumes ds,nothing + +cProc SizePQ,<FAR,PUBLIC,NODATA>,<si,di> + parmW hPQ + parmW cEntry + +cBegin + mov di,hPQ + cCall GlobalLock,<di> ; lock to get back segment address + or ax,dx ; Invalid handle implies NULL return + jz Siz_Cant_Proceed + mov es,dx + xor si,si ; offset will always be zro + mov ax,cEntry ; additional nodes + or ax,ax ; if zero return original numof nodes + jnz Size_Tobe_Increased + mov ax,es:[si].pq_maxentry ; offset past last node + shr ax,1 + shr ax,1 ; ax <--- ax / SIZE ENTRY + .errnz (SIZE ENTRY - 4) + jmp short cSize_Ret ; return after unlocking handle + +Size_Tobe_Increased: + shl ax,1 + shl ax,1 ; ax <-- ax * SIZE ENTRY, = extra bytes + .errnz (SIZE ENTRY - 4) + add ax,es:[si].pq_maxentry ; number of byte for new node array + cmp ax,es:[si].pq_index ; next available slot + jae Valid_Increase + mov ax,PQERROR ; error code + jmp short cSize_Ret ; return after releasing handle + +Valid_Increase: + push ax ; save number of bytes in node block + add ax,SIZE PQ ; size of header + push ax + cCall GlobalUnlock,<di> ; unlock handle + xor dx,dx ; high word for size + pop ax ; get back size + cCall GlobalReAlloc,<di,dx,ax,GMEM_MOVEABLE> + or ax,ax + jz Siz_Cant_Proceed + mov di,ax ; new handle + cCall GlobalLock,<ax> ; lock it + mov es,dx ; set new segment + pop cx ; get back total no of nodes into cx + jmp short Reloc_Successful +Siz_Cant_Proceed: + pop cx ; balance stack + dec ax + .errnz (-1 - PQERROR) + jmp short cSize_End + +Reloc_Successful: + mov es:[si].pq_maxentry,cx ; total number of slots now + shr cx,1 + shr cx,1 ; no of nodes = bytes / SIZE ENTRY + .errnz (SIZE ENTRY - 4) + mov ax,cx ; return value +cSize_Ret: + cCall GlobalUnlock,<di> +cSize_End: + +cEnd + +;-----------------------------------------------------------------------------; +;CompactList: ; +; Input: ; +; ds:si --- pointer to heap structure ; +; Output: ; +; all deleted elements are removed from heap structure ; +; Registers trashed: +; AX,BX,CX,DX +; +; -by- Ken Sykes [kensy] Tue Nov 12 1991 10:20:00am ; +;----------------------------------------------------------------------------- + +CompactList proc near + mov ax,[si].pq_index ; next available slot in node area + sub ax,[si].pq_start ; ax had pointer to available slot + mov [si].pq_index,ax ; next available slot will come up + lea dx,[si][SIZE PQ] ; points to NODE 1 + mov ax,[si].pq_start ; pointer to 1st active node rel to 1 + add ax,dx ; ax has offset to first valid node. + mov bx,ax + mov cx,[si].pq_maxentry ; pointer past end of node slots + sub cx,[si].pq_start ; pointer to strt of active block + shr cx,1 ; will do a REP MOVSW + .errnz (1 and SIZE ENTRY) + push es ; es has local segment + smov es,ds ; moth es ds point to heap segment + push si + push di ; save start to heap and its handle + mov si,bx ; si points to start of valid nodes + mov di,dx ; dx points to node 1 + cld + rep movsw ; Compacted + pop di + pop si + pop es ; restore local segment in es + mov [si].pq_start,cx ; after compaction deleted nodes = 0 + ret +CompactList endp + +;-----------------------------------------------------------------------------; + +sEnd SORT + +end |