summaryrefslogtreecommitdiffstats
path: root/private/mvdm/wow16/gdi
diff options
context:
space:
mode:
authorAdam <you@example.com>2020-05-17 05:51:50 +0200
committerAdam <you@example.com>2020-05-17 05:51:50 +0200
commite611b132f9b8abe35b362e5870b74bce94a1e58e (patch)
treea5781d2ec0e085eeca33cf350cf878f2efea6fe5 /private/mvdm/wow16/gdi
downloadNT4.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.c119
-rw-r--r--private/mvdm/wow16/gdi/gdi.api3047
-rw-r--r--private/mvdm/wow16/gdi/gdi.asm551
-rw-r--r--private/mvdm/wow16/gdi/gdi.def405
-rw-r--r--private/mvdm/wow16/gdi/gdi.rc5
-rw-r--r--private/mvdm/wow16/gdi/gdi.rcv13
-rw-r--r--private/mvdm/wow16/gdi/gdi16.h422
-rw-r--r--private/mvdm/wow16/gdi/gdimacro.inc676
-rw-r--r--private/mvdm/wow16/gdi/gdimem.inc50
-rw-r--r--private/mvdm/wow16/gdi/layer.asm47
-rw-r--r--private/mvdm/wow16/gdi/makefile126
-rw-r--r--private/mvdm/wow16/gdi/meta.c1835
-rw-r--r--private/mvdm/wow16/gdi/metacons.inc90
-rw-r--r--private/mvdm/wow16/gdi/metarec.c2325
-rw-r--r--private/mvdm/wow16/gdi/metasup.c523
-rw-r--r--private/mvdm/wow16/gdi/muldiv.asm110
-rw-r--r--private/mvdm/wow16/gdi/sort.asm706
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 &macro 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 &macro 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 &macro 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