Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

4496 lines
115 KiB

/*++
*
* WOW v1.0
*
* Copyright (c) 1991, Microsoft Corporation
*
* WGDI.C
* WOW32 16-bit GDI API support
*
* History:
* 07-Mar-1991 Jeff Parsons (jeffpar)
* Created.
*
* 09-Apr-1991 NigelT
* Various defines are used here to remove calls to Win32
* features which don't work yet.
*
* 06-June-1992 Chandan Chauhan (ChandanC)
* Fixed BITMAP and DeviceIndependentBitmap (DIB) issues
*
* 22-May-1995 Craig Jones (a-craigj)
* METAFILE NOTE: several 32-bit API's will return TRUE when GDI is in
* "metafile" mode -- however, the POINT struct does not get
* updated by GDI32 even if the API returns successfully so
* we just return TRUE or FALSE as the point coors like W3.1.
*
--*/
#include "precomp.h"
#pragma hdrstop
#include "wowgdip.h"
#include "wdib.h"
#include "stddef.h" // these three are needed to include the
#include "wingdip.h"
// definition of EXTTEXTMETRICS in wingdip.h
// [bodind]
#define SETGDIXFORM 4113
#define RESETPAGE 4114
// This must be removed from POSTBETA for sure. ChandanC 3/22/94.
#define IGNORESTARTPGAE 0x7FFFFFFF
#define ADD_MSTT 0x7FFFFFFD
MODNAME(wgdi.c);
INT WINAPI SetRelAbs(HDC,INT); /* definition not in gdi.h */
INT WINAPI GetRelAbs(HDC,INT); /* definition not in gdi.h */
LPDEVMODE GetDefaultDevMode32(LPSTR szDriver); // Implemented in wspool.c
// Hack for apps which try to be their own printer driver & send form feeds to
// the printer in Escape(PassThrough) calls. This mechanism prevents an
// additional page being spit out of the printer when the app calls EndDoc()
// because GDI32 EndDoc() does an implicit form feed.
typedef struct _FormFeedHack {
struct _FormFeedHack UNALIGNED *next;
HAND16 hTask16;
HDC hdc;
LPBYTE lpBytes;
int cbBytes;
} FORMFEEDHACK;
typedef FORMFEEDHACK UNALIGNED *PFORMFEEDHACK;
PFORMFEEDHACK gpFormFeedHackList = NULL; // start of global formfeed Hack list
LONG HandleFormFeedHack(HDC hdc, LPBYTE lpdata, int cb);
LPBYTE SendFrontEndOfDataStream(HDC hdc, LPBYTE lpData, int *cb, LONG *ul);
void FreeFormFeedHackNode(PFORMFEEDHACK pNode);
void FreeTaskFormFeedHacks(HAND16 hTask16);
void SendFormFeedHack(HDC hdc);
PFORMFEEDHACK FindFormFeedHackNode(HDC hdc);
PFORMFEEDHACK CreateFormFeedHackNode(HDC hdc, int cb, LPBYTE lpData);
void RemoveFormFeedHack(HDC hdc);
ULONG FASTCALL WG32Arc(PVDMFRAME pFrame)
{
ULONG ul;
register PARC16 parg16;
GETARGPTR(pFrame, sizeof(ARC16), parg16);
ul = GETBOOL16(Arc(HDC32(parg16->f1),
INT32(parg16->f2),
INT32(parg16->f3),
INT32(parg16->f4),
INT32(parg16->f5),
INT32(parg16->f6),
INT32(parg16->f7),
INT32(parg16->f8),
INT32(parg16->f9)));
FREEARGPTR(parg16);
RETURN(ul);
}
ULONG FASTCALL WG32BitBlt(PVDMFRAME pFrame)
{
ULONG ul;
register PBITBLT16 parg16;
GETARGPTR(pFrame, sizeof(BITBLT16), parg16);
ul = GETBOOL16(BitBlt(HDC32(parg16->f1),
INT32(parg16->f2),
INT32(parg16->f3),
INT32(parg16->f4),
INT32(parg16->f5),
HDC32(parg16->f6),
INT32(parg16->f7),
INT32(parg16->f8),
DWORD32(parg16->f9)));
WOW32APIWARN (ul, "BitBlt");
FREEARGPTR(parg16);
RETURN(ul);
}
ULONG FASTCALL WG32GetRelAbs(PVDMFRAME pFrame)
{
ULONG ul;
register PGETRELABS16 parg16;
GETARGPTR(pFrame, sizeof(GETRELABS16), parg16);
ul = GETINT16(GetRelAbs(HDC32(parg16->f1), 0));
FREEARGPTR(parg16);
RETURN(ul);
}
ULONG FASTCALL WG32SetRelAbs(PVDMFRAME pFrame)
{
ULONG ul;
register PSETRELABS16 parg16;
GETARGPTR(pFrame, sizeof(SETRELABS16), parg16);
ul = GETINT16(SetRelAbs(HDC32(parg16->f1), INT32(parg16->f2)));
FREEARGPTR(parg16);
RETURN(ul);
}
ULONG FASTCALL WG32Chord(PVDMFRAME pFrame)
{
ULONG ul;
register PCHORD16 parg16;
GETARGPTR(pFrame, sizeof(CHORD16), parg16);
ul = GETBOOL16(Chord(HDC32(parg16->f1),
INT32(parg16->f2),
INT32(parg16->f3),
INT32(parg16->f4),
INT32(parg16->f5),
INT32(parg16->f6),
INT32(parg16->f7),
INT32(parg16->f8),
INT32(parg16->f9)));
FREEARGPTR(parg16);
RETURN(ul);
}
ULONG FASTCALL WG32CombineRgn(PVDMFRAME pFrame)
{
ULONG ul;
register PCOMBINERGN16 parg16;
GETARGPTR(pFrame, sizeof(COMBINERGN16), parg16);
ul = GETINT16(CombineRgn(HRGN32(parg16->f1),
HRGN32(parg16->f2),
HRGN32(parg16->f3),
INT32(parg16->f4)));
FREEARGPTR(parg16);
RETURN(ul);
}
ULONG FASTCALL WG32CreateBitmap(PVDMFRAME pFrame)
{
ULONG ul;
register PCREATEBITMAP16 parg16;
LPBYTE lpBitsOriginal;
GETARGPTR(pFrame, sizeof(CREATEBITMAP16), parg16);
GETOPTPTR(parg16->f5, 0, lpBitsOriginal);
ul = GETHBITMAP16(CreateBitmap(INT32(parg16->f1),
INT32(parg16->f2),
LOBYTE(parg16->f3),
LOBYTE(parg16->f4),
lpBitsOriginal));
WOW32APIWARN(ul, "CreateBitmap");
FREEOPTPTR(lpBitsOriginal);
FREEARGPTR(parg16);
RETURN(ul);
}
ULONG FASTCALL WG32CreateBitmapIndirect(PVDMFRAME pFrame)
{
ULONG ul;
register PCREATEBITMAPINDIRECT16 parg16;
PBITMAP16 pbm16;
BITMAP bm;
LPBYTE lp = NULL;
GETARGPTR(pFrame, sizeof(CREATEBITMAPINDIRECT16), parg16);
GETVDMPTR(parg16->f1, sizeof(BITMAP16), pbm16);
GETOPTPTR(pbm16->bmBits, 0, lp);
bm.bmType = (LONG) FETCHSHORT(pbm16->bmType);
bm.bmWidth = (LONG) FETCHSHORT(pbm16->bmWidth);
bm.bmHeight = (LONG) FETCHSHORT(pbm16->bmHeight);
bm.bmWidthBytes = (LONG) FETCHSHORT(pbm16->bmWidthBytes);
bm.bmPlanes = (WORD) pbm16->bmPlanes;
bm.bmBitsPixel = (WORD) pbm16->bmBitsPixel;
bm.bmBits = lp;
ul = GETHBITMAP16(CreateBitmapIndirect(&bm));
WOW32APIWARN(ul, "CreateBitmapIndirect");
FREEOPTPTR(lp);
FREEARGPTR(parg16);
RETURN(ul);
}
ULONG FASTCALL WG32CreateBrushIndirect(PVDMFRAME pFrame)
{
ULONG ul;
LOGBRUSH t1;
HAND16 hMem16;
HANDLE hMem32 = NULL;
LPBYTE lpMem16, lpMem32;
INT cb;
VPVOID vp;
register PCREATEBRUSHINDIRECT16 parg16;
GETARGPTR(pFrame, sizeof(CREATEBRUSHINDIRECT16), parg16);
GETLOGBRUSH16(parg16->f1, &t1);
// some apps don't properly set the style. Make sure it is a valid w3.1 style
if (t1.lbStyle > BS_DIBPATTERN)
t1.lbStyle = BS_SOLID;
if (t1.lbStyle == BS_PATTERN) {
t1.lbStyle = BS_PATTERN8X8;
}
else if (t1.lbStyle == BS_DIBPATTERN) {
hMem16 = (WORD) t1.lbHatch;
if (hMem16) {
vp = RealLockResource16(hMem16, &cb);
if (vp) {
GETMISCPTR(vp, lpMem16);
hMem32 = GlobalAlloc(GMEM_MOVEABLE, cb);
WOW32ASSERT(hMem32);
if (hMem32) {
lpMem32 = GlobalLock(hMem32);
RtlCopyMemory(lpMem32, lpMem16, cb);
GlobalUnlock(hMem32);
}
GlobalUnlock16(hMem16);
FREEMISCPTR(lpMem16);
}
}
t1.lbHatch = (LONG)hMem32;
}
else if (t1.lbStyle == BS_SOLID)
{
if (((ULONG)t1.lbColor & 0xff000000) > 0x02000000)
t1.lbColor &= 0xffffff;
}
ul = GETHBRUSH16(CreateBrushIndirect(&t1));
if (hMem32)
{
GlobalFree(hMem32);
}
WOW32APIWARN(ul, "CreateBrushIndirect");
FREEARGPTR(parg16);
RETURN(ul);
}
ULONG FASTCALL WG32CreateCompatibleBitmap(PVDMFRAME pFrame)
{
ULONG ul;
register PCREATECOMPATIBLEBITMAP16 parg16;
GETARGPTR(pFrame, sizeof(CREATECOMPATIBLEBITMAP16), parg16);
ul = GETHBITMAP16(CreateCompatibleBitmap(HDC32(parg16->f1),
INT32(parg16->f2),
INT32(parg16->f3)));
WOW32APIWARN(ul, "CreateCompatibleBitmap");
FREEARGPTR(parg16);
RETURN(ul);
}
ULONG FASTCALL WG32CreateCompatibleDC(PVDMFRAME pFrame)
{
ULONG ul;
HDC hdc;
register PCREATECOMPATIBLEDC16 parg16;
GETARGPTR(pFrame, sizeof(CREATECOMPATIBLEDC16), parg16);
if ( parg16->f1 ) {
hdc = HDC32(parg16->f1);
if ( hdc == NULL ) {
FREEARGPTR(parg16);
return(0);
}
} else {
hdc = NULL;
}
ul = GETHDC16(CreateCompatibleDC(hdc));
//
// Some apps such as MSWORKS and MS PUBLISHER use some wizard code that accepts
// a hDC or a hWnd as a parameter and attempt to figure out what type of handle
// it is by using the IsWindow() call. Since both handles come from different
// handle spaces they may end up the same value and this wizard code will end
// up writing to the DC for a random window. By ORing in a 1 we ensure that the
// handle types will never share the same value since all hWnds are even. Note
// that this hack is also made in WU32GetDC().
//
// Note that there are some apps that use the lower 2 bits of the hDC for their
// own purposes.
if (ul && CURRENTPTD()->dwWOWCompatFlags & WOWCF_UNIQUEHDCHWND) {
ul = ul | 1;
}
WOW32APIWARN(ul, "CreateCompatibleDC");
FREEARGPTR(parg16);
RETURN(ul);
}
ULONG FASTCALL WG32CreateDC(PVDMFRAME pFrame)
{
ULONG ul;
PSZ psz;
PSZ psz1 = NULL;
PSZ psz2 = NULL;
PSZ psz3 = NULL;
PSZ pszDib;
LPDEVMODE t4 = NULL;
register PCREATEDC16 parg16;
GETARGPTR(pFrame, sizeof(CREATEDC16), parg16);
GETPSZPTR(parg16->f1, psz);
if(psz) {
psz1 = malloc_w(lstrlen(psz)+1);
if(psz1) {
lstrcpy(psz1, psz);
}
}
FREEPSZPTR(psz);
GETPSZPTR(parg16->f2, psz);
if(psz) {
psz2 = malloc_w(lstrlen(psz)+1);
if(psz2) {
lstrcpy(psz2, psz);
}
}
FREEPSZPTR(psz);
GETPSZPTR(parg16->f3, psz);
if(psz) {
psz3 = malloc_w(lstrlen(psz)+1);
if(psz3) {
lstrcpy(psz3, psz);
}
}
FREEPSZPTR(psz);
// Note: parg16->f4 will usually be a lpDevMode, but it is documented
// that it can also be a lpBitMapInfo if the driver name is "dib.drv"
// test for "dib.drv". Director 4.0 uses "dirdib.drv"
if ((pszDib = strstr (psz1, "DIB")) ||
(pszDib = strstr (psz1, "dib"))) {
if (_stricmp (pszDib, "DIB") == 0 ||
_stricmp (pszDib, "DIB.DRV") == 0) {
ul = GETHDC16(W32HandleDibDrv ((PVPVOID)parg16->f4));
// Note: flat 16:16 ptrs should be considered invalid after this call
}
}
// handle normal non-dib.drv case
else {
if (FETCHDWORD(parg16->f4) == 0L) {
t4 = GetDefaultDevMode32(psz2);
}
else {
t4 = ThunkDevMode16to32(parg16->f4);
}
// this can callback into a 16-bit fax driver!
ul = GETHDC16(CreateDC(psz1, psz2, psz3, t4));
// Note: flat 16:16 ptrs should be considered invalid after this call
}
WOW32APIWARN(ul, "CreateDC");
FREEDEVMODE32(t4);
FREEARGPTR(parg16);
RETURN(ul);
}
ULONG FASTCALL WG32CreateDIBPatternBrush(PVDMFRAME pFrame)
{
ULONG ul = 0;
LPBYTE lpb16;
LOGBRUSH logbr;
register PCREATEDIBPATTERNBRUSH16 parg16;
GETARGPTR(pFrame, sizeof(CREATEDIBPATTERNBRUSH16), parg16);
GETMISCPTR(parg16->f1, lpb16);
logbr.lbStyle = BS_DIBPATTERN8X8;
logbr.lbColor = WORD32(parg16->f2);
logbr.lbHatch = (LONG) lpb16;
ul = GETHBRUSH16(CreateBrushIndirect(&logbr));
WOW32APIWARN(ul, "CreateDIBPatternBrush");
FREEARGPTR(parg16);
RETURN(ul);
}
ULONG FASTCALL WG32CreateDIBitmap(PVDMFRAME pFrame)
{
ULONG ul = 0;
LPBYTE lpib4;
BITMAPINFOHEADER bmxh2;
STACKBMI32 bmi32;
LPBITMAPINFOHEADER lpbmih32;
LPBITMAPINFO lpbmi32;
register PCREATEDIBITMAP16 parg16;
GETARGPTR(pFrame, sizeof(CREATEDIBITMAP16), parg16);
GETMISCPTR(parg16->f4, lpib4);
lpbmih32 = CopyBMIH16ToBMIH32((PVPVOID) FETCHDWORD(parg16->f2), &bmxh2);
lpbmi32 = CopyBMI16ToBMI32((PVPVOID)FETCHDWORD(parg16->f5),
(LPBITMAPINFO)&bmi32,
FETCHWORD(parg16->f6));
// Code below fixes problems in Sounditoutland with rle-encoded
// bitmaps which have biSizeImage == 0. On Win 3.1 they work since
// gdi is happy with decoding some piece of memory. NT GDI however
// needs to know the size of bits passed. We remedy this by calculating
// size using RET_GETDIBSIZE (GetSelectorLimit). GDI won't copy the
// memory, it will just use size as indication of accessibility
// Application: "Sound It Out Land",
if (lpbmi32 && (lpbmi32->bmiHeader.biCompression == BI_RLE4 ||
lpbmi32->bmiHeader.biCompression == BI_RLE8) &&
lpbmi32->bmiHeader.biSizeImage == 0 &&
lpib4 != NULL &&
DWORD32(parg16->f3) == CBM_INIT) {
// we have to determine what the size is
PARM16 Parm16; // prepare to callback
ULONG SelectorLimit;
LONG lSize;
LPBITMAPINFOHEADER lpbmi = &lpbmi32->bmiHeader;
// now what is this 16:16 ?
Parm16.WndProc.wParam = HIWORD((LPVOID)parg16->f4);
CallBack16(RET_GETDIBSIZE,
&Parm16,
0,
(PVPVOID)&SelectorLimit);
if (SelectorLimit != 0 && SelectorLimit != 0xffffffff) {
// so sel is valid
// now see how much room we have in there
lSize = (LONG)SelectorLimit - LOWORD((LPVOID)parg16->f4);
// now we have size
if (lSize > 0) {
lpbmi->biSizeImage = lSize;
}
else {
LOGDEBUG(LOG_ALWAYS, ("CreateDIBitmap: Bad size of the bits ptr\n"));
}
}
else {
LOGDEBUG(LOG_ALWAYS, ("CreateDIBitmap: Selector [ptr:%x] is invalid\n", (DWORD)parg16->f4));
}
}
ul = GETHBITMAP16(CreateDIBitmap(HDC32(parg16->f1),
lpbmih32,
DWORD32(parg16->f3),
lpib4,
lpbmi32,
WORD32(parg16->f6) ));
WOW32APIWARN(ul, "CreateDIBitmap");
FREEMISCPTR(lpib4);
FREEARGPTR(parg16);
return(ul);
}
ULONG FASTCALL WG32CreateDiscardableBitmap(PVDMFRAME pFrame)
{
ULONG ul;
register PCREATEDISCARDABLEBITMAP16 parg16;
GETARGPTR(pFrame, sizeof(CREATEDISCARDABLEBITMAP16), parg16);
ul = GETHBITMAP16(CreateDiscardableBitmap(HDC32(parg16->hdc),
INT32(parg16->width),
INT32(parg16->height)));
WOW32APIWARN(ul, "CreateDiscardableBitmap");
FREEARGPTR(parg16);
RETURN(ul);
}
ULONG FASTCALL WG32CreateEllipticRgn(PVDMFRAME pFrame)
{
ULONG ul;
register PCREATEELLIPTICRGN16 parg16;
GETARGPTR(pFrame, sizeof(CREATEELLIPTICRGN16), parg16);
ul = GETHRGN16(CreateEllipticRgn(INT32(parg16->f1),
INT32(parg16->f2),
INT32(parg16->f3),
INT32(parg16->f4)));
WOW32APIWARN(ul, "CreateEllipticRgn");
FREEARGPTR(parg16);
RETURN(ul);
}
ULONG FASTCALL WG32CreateEllipticRgnIndirect(PVDMFRAME pFrame)
{
ULONG ul;
RECT t1;
register PCREATEELLIPTICRGNINDIRECT16 parg16;
GETARGPTR(pFrame, sizeof(CREATEELLIPTICRGNINDIRECT16), parg16);
WOW32VERIFY(GETRECT16(parg16->f1, &t1));
ul = GETHRGN16(CreateEllipticRgnIndirect(&t1));
WOW32APIWARN(ul, "CreateEllipticRgnIndirect");
FREEARGPTR(parg16);
RETURN(ul);
}
ULONG FASTCALL WG32CreateHatchBrush(PVDMFRAME pFrame)
{
ULONG ul;
register PCREATEHATCHBRUSH16 parg16;
GETARGPTR(pFrame, sizeof(CREATEHATCHBRUSH16), parg16);
ul = GETHBRUSH16(CreateHatchBrush(INT32(parg16->f1), DWORD32(parg16->f2)));
WOW32APIWARN(ul, "CreateHatchBrush");
FREEARGPTR(parg16);
RETURN(ul);
}
ULONG FASTCALL WG32CreateIC(PVDMFRAME pFrame)
{
ULONG ul;
PSZ psz;
PSZ psz1 = NULL;
PSZ psz2 = NULL, psz2t;
PSZ psz3 = NULL;
LPDEVMODE t4;
register PCREATEIC16 parg16;
INT len;
PCHAR pch;
GETARGPTR(pFrame, sizeof(CREATEIC16), parg16);
GETPSZPTR(parg16->f1, psz);
if(psz) {
psz1 = malloc_w(lstrlen(psz)+1);
if(psz1) {
lstrcpy(psz1, psz);
}
}
FREEPSZPTR(psz);
GETPSZPTR(parg16->f2, psz);
if(psz) {
psz2 = malloc_w(lstrlen(psz)+1);
if(psz2) {
lstrcpy(psz2, psz);
}
}
FREEPSZPTR(psz);
GETPSZPTR(parg16->f3, psz);
if(psz) {
psz3 = malloc_w(lstrlen(psz)+1);
if(psz3) {
lstrcpy(psz3, psz);
}
}
FREEPSZPTR(psz);
if (FETCHDWORD(parg16->f4) != 0L) {
t4 = ThunkDevMode16to32(parg16->f4);
}
else {
t4 = GetDefaultDevMode32(psz2);
}
// invalidate all flat ptrs to 16:16 memory now!
FREEARGPTR(parg16);
psz2t = psz2;
//
// HACK Alert!
//
// NBI's Legacy comes with a pscript.drv that resides in [AppPath]\cbt
// they call CreateIC() specifying the the path to this file as the driver.
// the app GP faults if the CreateIC returns 0. once they've loaded this
// printer driver, on successive calls to CreateIC() they simply use
// "PSCRIPT" as the driver name and use "PostScript Printer", "FILE:" as
// the other parms.
// let's recognize these driver names and try to replace it with the
// system default printer. if there's no printer installed, a GP fault
// is unavoidable. the app appears to use this pscript.drv only during
// the tutorial, so we're not providing life-support for an app that's
// clinically dead.
//
//
// check for a driver name that ends with "PSCRIPT" and if so,
// check that the device name is "PostScript Printer".
// on NT the driver name should always be "winspool", although it's
// completely ignored.
//
// PageMaker 5.0a calls this with ("pscript","Postscript printer","LPT1:",0)
// when opening calibrat.pt5
len = psz1 ? strlen(psz1) : 0;
if (len >= 7) {
#if 0
static CHAR achPS[] = "PostScript Printer";
#endif
if (!_stricmp(psz1+len-7, "pscript")
#if 0
// let's see who else thinks they're using a pscript driver
//
&& (RtlCompareMemory(achPS, psz2, sizeof(achPS)) == sizeof(achPS))
#endif
) {
DWORD dw;
CHAR achDevice[256];
LOGDEBUG(LOG_ALWAYS,("WOW32: CreateIC - detected request for Pscript driver\n"));
dw = GetProfileString("windows", "device", "", achDevice,
sizeof(achDevice));
if (dw) {
psz2t = achDevice;
pch = strchr(achDevice, ',');
if (pch) {
*pch = '\0';
}
}
}
}
// this can callback into a 16-bit fax driver!
ul = GETHDC16(CreateIC(psz1, psz2t, psz3, t4));
WOW32APIWARN(ul, "CreateIC");
FREEDEVMODE32(t4);
RETURN(ul);
}
ULONG FASTCALL WG32CreatePatternBrush(PVDMFRAME pFrame)
{
ULONG ul;
LOGBRUSH logbr;
register PCREATEPATTERNBRUSH16 parg16;
GETARGPTR(pFrame, sizeof(CREATEPATTERNBRUSH16), parg16);
logbr.lbStyle = BS_PATTERN8X8;
logbr.lbColor = 0;
logbr.lbHatch = (LONG)HBITMAP32(parg16->f1);
ul = GETHBRUSH16(CreateBrushIndirect(&logbr));
WOW32APIWARN(ul, "CreatePatternBrush");
FREEARGPTR(parg16);
RETURN(ul);
}
ULONG FASTCALL WG32CreatePen(PVDMFRAME pFrame)
{
ULONG ul;
register PCREATEPEN16 parg16;
GETARGPTR(pFrame, sizeof(CREATEPEN16), parg16);
ul = GETHPEN16(CreatePen(INT32(parg16->f1),
INT32(parg16->f2),
DWORD32(parg16->f3)));
WOW32APIWARN(ul, "CreatePen");
FREEARGPTR(parg16);
RETURN(ul);
}
ULONG FASTCALL WG32CreatePenIndirect(PVDMFRAME pFrame)
{
ULONG ul;
LOGPEN t1;
register PCREATEPENINDIRECT16 parg16;
GETARGPTR(pFrame, sizeof(CREATEPENINDIRECT16), parg16);
GETLOGPEN16(parg16->f1, &t1);
ul = GETHPEN16(CreatePenIndirect(&t1));
WOW32APIWARN(ul, "CreatePenIndirect");
FREEARGPTR(parg16);
RETURN(ul);
}
ULONG FASTCALL WG32CreatePolyPolygonRgn(PVDMFRAME pFrame)
{
ULONG ul;
LPPOINT pPoints;
PINT pPolyCnt;
UINT cpts = 0;
INT ii;
register PCREATEPOLYPOLYGONRGN16 parg16;
INT cInt16;
INT BufferT[256]; // comfortably large array
GETARGPTR(pFrame, sizeof(CREATEPOLYPOLYGONRGN16), parg16);
cInt16 = INT32(parg16->f3);
pPolyCnt = STACKORHEAPALLOC(cInt16 * sizeof(INT), sizeof(BufferT), BufferT);
if (!pPolyCnt) {
FREEARGPTR(parg16);
RETURN(0);
}
getintarray16(parg16->f2, cInt16, pPolyCnt);
for (ii=0; ii < cInt16; ii++)
cpts += pPolyCnt[ii];
pPoints = STACKORHEAPALLOC(cpts * sizeof(POINT),
sizeof(BufferT) - cInt16 * sizeof(INT),
BufferT + cInt16);
getpoint16(parg16->f1, cpts, pPoints);
ul = GETHRGN16(CreatePolyPolygonRgn(pPoints,
pPolyCnt,
INT32(parg16->f3),
INT32(parg16->f4)));
WOW32APIWARN(ul, "CreatePolyPolygonRgn");
STACKORHEAPFREE(pPoints, BufferT + cInt16);
STACKORHEAPFREE(pPolyCnt, BufferT);
FREEARGPTR(parg16);
RETURN(ul);
}
ULONG FASTCALL WG32CreatePolygonRgn(PVDMFRAME pFrame)
{
ULONG ul;
LPPOINT t1;
register PCREATEPOLYGONRGN16 parg16;
POINT BufferT[128];
GETARGPTR(pFrame, sizeof(CREATEPOLYGONRGN16), parg16);
t1 = STACKORHEAPALLOC(parg16->f2 * sizeof(POINT), sizeof(BufferT), BufferT);
getpoint16(parg16->f1, parg16->f2, t1);
ul = GETHRGN16(CreatePolygonRgn(t1, INT32(parg16->f2), INT32(parg16->f3)));
WOW32APIWARN(ul, "CreatePolygonRgn");
STACKORHEAPFREE(t1, BufferT);
FREEARGPTR(parg16);
RETURN(ul);
}
ULONG FASTCALL WG32CreateRectRgn(PVDMFRAME pFrame)
{
ULONG ul;
register PCREATERECTRGN16 parg16;
GETARGPTR(pFrame, sizeof(CREATERECTRGN16), parg16);
ul = GETHRGN16(CreateRectRgn(INT32(parg16->f1),
INT32(parg16->f2),
INT32(parg16->f3),
INT32(parg16->f4)));
WOW32APIWARN(ul, "CreateRectRgn");
FREEARGPTR(parg16);
RETURN(ul);
}
ULONG FASTCALL WG32CreateRectRgnIndirect(PVDMFRAME pFrame)
{
ULONG ul;
RECT t1;
register PCREATERECTRGNINDIRECT16 parg16;
GETARGPTR(pFrame, sizeof(CREATERECTRGNINDIRECT16), parg16);
WOW32VERIFY(GETRECT16(parg16->f1, &t1));
ul = GETHRGN16(CreateRectRgnIndirect(&t1));
WOW32APIWARN(ul, "CreateRectRgnIndirect");
FREEARGPTR(parg16);
RETURN(ul);
}
ULONG FASTCALL WG32CreateRoundRectRgn(PVDMFRAME pFrame)
{
ULONG ul;
register PCREATEROUNDRECTRGN16 parg16;
GETARGPTR(pFrame, sizeof(CREATEROUNDRECTRGN16), parg16);
ul = GETHRGN16(CreateRoundRectRgn(INT32(parg16->f1),
INT32(parg16->f2),
INT32(parg16->f3),
INT32(parg16->f4),
INT32(parg16->f5),
INT32(parg16->f6)));
WOW32APIWARN(ul, "CreateRoundRectRgn");
FREEARGPTR(parg16);
RETURN(ul);
}
ULONG FASTCALL WG32CreateSolidBrush(PVDMFRAME pFrame)
{
ULONG ul;
register PCREATESOLIDBRUSH16 parg16;
DWORD dwColor;
GETARGPTR(pFrame, sizeof(CREATESOLIDBRUSH16), parg16);
dwColor = DWORD32(parg16->f1);
if (((ULONG)dwColor & 0xff000000) > 0x02000000)
dwColor &= 0xffffff;
ul = GETHBRUSH16(CreateSolidBrush(dwColor));
WOW32APIWARN(ul, "CreateSolidBrush");
FREEARGPTR(parg16);
RETURN(ul);
}
ULONG FASTCALL WG32DPtoLP(PVDMFRAME pFrame)
{
ULONG ul;
LPPOINT t2;
register PDPTOLP16 parg16;
POINT BufferT[128];
GETARGPTR(pFrame, sizeof(DPTOLP16), parg16);
t2 = STACKORHEAPALLOC(parg16->f3 * sizeof(POINT), sizeof(BufferT), BufferT);
getpoint16(parg16->f2, parg16->f3, t2);
ul = GETBOOL16(DPtoLP(HDC32(parg16->f1), t2, INT32(parg16->f3)));
PUTPOINTARRAY16(parg16->f2, parg16->f3, t2);
STACKORHEAPFREE(t2, BufferT);
FREEARGPTR(parg16);
RETURN(ul);
}
ULONG FASTCALL WG32DeleteDC(PVDMFRAME pFrame)
{
ULONG ul;
register PDELETEDC16 parg16;
GETARGPTR(pFrame, sizeof(DELETEDC16), parg16);
if ((ul = W32CheckAndFreeDibInfo (HDC32(parg16->f1))) == FALSE) {
ul = GETBOOL16(DeleteDC(HDC32(parg16->f1)));
// Free 16-bit handle alias if 32-bit handle successfully deleted
if (ul) {
FREEHOBJ16(parg16->f1);
}
}
FREEARGPTR(parg16);
RETURN(ul);
}
ULONG FASTCALL WG32DeleteObject(PVDMFRAME pFrame)
{
ULONG ul;
register PDELETEOBJECT16 parg16;
GETARGPTR(pFrame, sizeof(DELETEOBJECT16), parg16);
if ((pDibSectionInfoHead == NULL) ||
(ul = W32CheckAndFreeDibSectionInfo (HBITMAP32(parg16->f1))) == FALSE) {
ul = GETBOOL16(DeleteObject(HOBJ32(parg16->f1)));
// Free 16-bit handle alias if 32-bit handle successfully deleted
if (ul) {
FREEHOBJ16(parg16->f1);
}
}
FREEARGPTR(parg16);
RETURN(ul);
}
ULONG FASTCALL WG32Ellipse(PVDMFRAME pFrame)
{
ULONG ul;
register PELLIPSE16 parg16;
GETARGPTR(pFrame, sizeof(ELLIPSE16), parg16);
ul = GETBOOL16(Ellipse(HDC32(parg16->hdc),
INT32(parg16->x1),
INT32(parg16->y1),
INT32(parg16->x2),
INT32(parg16->y2)));
FREEARGPTR(parg16);
RETURN(ul);
}
// WARNING: This function may cause 16-bit memory movement
INT W32EnumObjFunc(LPSTR lpLogObject, PENUMOBJDATA pEnumObjData)
{
PARM16 Parm16;
INT iReturn;
WOW32ASSERT(pEnumObjData);
switch (pEnumObjData->ObjType) {
case OBJ_BRUSH:
PUTLOGBRUSH16(pEnumObjData->vpObjData, sizeof(LOGBRUSH), (LPLOGBRUSH)lpLogObject);
break;
case OBJ_PEN:
PUTLOGPEN16(pEnumObjData->vpObjData, sizeof(LOGPEN), (LPLOGPEN)lpLogObject);
break;
default:
LOGDEBUG(LOG_ALWAYS,("WOW32 ERROR -- Illegal type %d passes to EnumObj\n",pEnumObjData->ObjType));
return 0;
} // end switch
STOREDWORD(Parm16.EnumObjProc.vpLogObject, pEnumObjData->vpObjData);
STOREDWORD(Parm16.EnumObjProc.vpData, pEnumObjData->dwUserParam);
CallBack16(RET_ENUMOBJPROC, &Parm16, pEnumObjData->vpfnEnumObjProc, (PVPVOID)&iReturn);
return (SHORT)iReturn;
}
ULONG FASTCALL WG32EnumObjects(PVDMFRAME pFrame)
{
ULONG ul = 0;
register PENUMOBJECTS16 parg16;
ENUMOBJDATA EnumObjData;
GETARGPTR(pFrame, sizeof(ENUMOBJECTS16), parg16);
EnumObjData.ObjType = INT32(parg16->f2);
switch(EnumObjData.ObjType) {
case OBJ_BRUSH:
EnumObjData.vpObjData = malloc16(sizeof(LOGBRUSH16));
break;
case OBJ_PEN:
EnumObjData.vpObjData = malloc16(sizeof(LOGPEN16));
break;
default:
LOGDEBUG(LOG_ALWAYS,("WOW32 ERROR -- Illegal type %d passes to EnumObj\n",EnumObjData.ObjType));
EnumObjData.vpObjData = (VPVOID)0;
}
// malloc16 may have caused 16-bit memory movement - invalidate flat ptrs
FREEVDMPTR(pFrame);
FREEARGPTR(parg16);
GETFRAMEPTR(((PTD)CURRENTPTD())->vpStack, pFrame);
GETARGPTR(pFrame, sizeof(ENUMOBJECTS16), parg16);
if( EnumObjData.vpObjData ) {
EnumObjData.vpfnEnumObjProc = DWORD32(parg16->f3);
EnumObjData.dwUserParam = DWORD32(parg16->f4);
ul = (ULONG)(GETINT16(EnumObjects(HDC32(parg16->f1),
(int)INT32(parg16->f2),
(GOBJENUMPROC)W32EnumObjFunc,
(LPARAM)&EnumObjData)));
// 16-bit memory may have moved - invalidate flat pointers
FREEARGPTR(parg16);
FREEVDMPTR(pFrame);
free16(EnumObjData.vpObjData);
}
FREEARGPTR(parg16);
RETURN(ul);
}
ULONG FASTCALL WG32EqualRgn(PVDMFRAME pFrame)
{
ULONG ul;
register PEQUALRGN16 parg16;
GETARGPTR(pFrame, sizeof(EQUALRGN16), parg16);
ul = GETBOOL16(EqualRgn(HRGN32(parg16->f1), HRGN32(parg16->f2)));
FREEARGPTR(parg16);
RETURN(ul);
}
/**************************************************************************\
*
\**************************************************************************/
typedef struct _ESCKERNPAIR {
union
{
BYTE each[2];
WORD both;
} kpPair;
SHORT KernAmount;
} ESCKERNPAIR;
/******************************Public*Routine******************************\
* iGetKerningPairsEsc32
*
* History:
* Tue 16-Mar-1993 11:08:36 by Kirk Olynyk [kirko]
* Wrote it.
\**************************************************************************/
int
iGetKerningPairsEsc32(
HDC hdc,
ESCKERNPAIR *pekp
)
{
int i,j;
int n;
HGLOBAL hglblMem = NULL;
ESCKERNPAIR *pekpT, *pekpTOut;
KERNINGPAIR *pkpT;
KERNINGPAIR *pkp = (KERNINGPAIR*) NULL;
if
(
(n = GetKerningPairs(hdc,0,NULL)) &&
(hglblMem = GlobalAlloc(GMEM_FIXED, n * sizeof(KERNINGPAIR))) &&
(pkp = (KERNINGPAIR*) GlobalLock(hglblMem)) &&
(n = (int) GetKerningPairs(hdc, n, pkp))
)
{
n = min(n,512);
//
// load the low byte of each word, Win 3.1 doesn't seem to care about
// the high byte
//
pekpT = pekp;
pekpTOut = pekp + n;
pkpT = pkp;
while (pekpT < pekpTOut)
{
pekpT->kpPair.each[0] = (BYTE) pkpT->wFirst;
pekpT->kpPair.each[1] = (BYTE) pkpT->wSecond;
pekpT->KernAmount = (SHORT) pkpT->iKernAmount;
pekpT += 1;
pkpT += 1;
}
//
// bubble sort word formed by byte pair
//
for (i = 0; i < n - 1; i++)
{
for (j = n-1; j > i; --j)
{
if (pekp[j-1].kpPair.both > pekp[j].kpPair.both)
{
ESCKERNPAIR ekp;
ekp = pekp[j];
pekp[j] = pekp[j-1];
pekp[j] = ekp;
}
}
}
}
if (hglblMem != NULL)
{
GlobalUnlock(hglblMem);
GlobalFree(hglblMem);
}
return(n);
}
ULONG FASTCALL WG32Escape(PVDMFRAME pFrame)
{
ULONG ul=0;
register PESCAPE16 parg16;
PVOID pin;
int iMapMode;
CHAR buf[32];
GETARGPTR(pFrame, sizeof(ESCAPE16), parg16);
GETOPTPTR(parg16->f4, 0, pin);
switch (INT32(parg16->f2)) {
case GETPHYSPAGESIZE:
case GETPRINTINGOFFSET:
case GETSCALINGFACTOR:
{ POINT pt;
ul = GETINT16(Escape(HDC32(parg16->f1),
INT32(parg16->f2),
INT32(parg16->f3),
pin,
(LPSTR)&pt));
if (!ul)
{
// if these fail, they are almost certainly doing it on a display dc.
// We will fill the return value in with reasonable values for those
// apps (micrographx draw) that ignore our return values.
// we still return failure.
switch (INT32(parg16->f2))
{
case GETPHYSPAGESIZE:
pt.x = GetDeviceCaps(HDC32(parg16->f1),HORZRES);
pt.y = GetDeviceCaps(HDC32(parg16->f1),VERTRES);
break;
case GETPRINTINGOFFSET:
pt.x = 0;
pt.y = 0;
break;
default:
break;
}
}
PUTPOINT16(parg16->f5, &pt);
}
break;
case GETCOLORTABLE:
{
PDWORD pdw;
DWORD dw;
INT i;
if (pin) {
i = (INT) FETCHSHORT(*(PSHORT)pin);
} else {
ul = (ULONG)-1;
break;
}
ul = GETINT16(Escape(HDC32(parg16->f1),
INT32(parg16->f2),
sizeof(INT),
(LPCSTR)&i,
&dw));
GETVDMPTR(parg16->f5, sizeof(DWORD), pdw);
STOREDWORD ((*pdw), dw);
FREEVDMPTR(pdw);
}
break;
case NEXTBAND:
{ RECT rt;
ul = GETINT16(Escape(HDC32(parg16->f1),
INT32(parg16->f2),
INT32(parg16->f3),
pin,
(LPSTR)&rt));
PUTRECT16(parg16->f5, &rt);
}
break;
case QUERYESCSUPPORT:
{
INT i;
i = (INT) FETCHWORD((*(PWORD)pin));
switch (i) {
// For Escapes return FALSE for MGX Draw and TRUE for all other apps.
// ChandanC, 27/5/93.
//
case OPENCHANNEL: // 4110
case DOWNLOADHEADER: // 4111
case CLOSECHANNEL: // 4112
case SETGDIXFORM: // 4113
case RESETPAGE: // 4114
if (CURRENTPTD()->dwWOWCompatFlags & WOWCF_MGX_ESCAPES) {
ul = 0;
}
else {
ul = 1;
}
break;
case POSTSCRIPT_PASSTHROUGH: // 4115
if (CURRENTPTD()->dwWOWCompatFlags & WOWCF_MGX_ESCAPES) {
ul = 0;
}
else {
LOGDEBUG(3,("Querying support for escape %x\n",i));
ul = GETINT16(Escape(HDC32(parg16->f1),
INT32(parg16->f2),
sizeof(int),
(PVOID)&i,
NULL));
}
break;
case ENCAPSULATED_POSTSCRIPT: // 4116
if (CURRENTPTD()->dwWOWCompatFlags & WOWCF_MGX_ESCAPES) {
ul = 0;
}
else {
LOGDEBUG(3,("Querying support for escape %x\n",i));
ul = GETINT16(DrawEscape (HDC32(parg16->f1),
INT32(parg16->f2),
sizeof(int),
(PVOID)&i));
}
break;
case GETEXTENDEDTEXTMETRICS:
case GETPAIRKERNTABLE:
case FLUSHOUTPUT:
ul = 1;
break;
case SETCOPYCOUNT:
case GETCOLORTABLE:
case GETPHYSPAGESIZE:
case GETPRINTINGOFFSET:
case GETSCALINGFACTOR:
case NEXTBAND:
case SETABORTPROC:
case BEGIN_PATH:
case END_PATH:
case CLIP_TO_PATH:
LOGDEBUG(3,("Querying support for escape %x\n",i));
ul = GETINT16(Escape(HDC32(parg16->f1),
INT32(parg16->f2),
sizeof(int),
(PVOID)&i,
NULL));
break;
case POSTSCRIPT_DATA:
case POSTSCRIPT_IGNORE:
if (CURRENTPTD()->dwWOWCompatFlags & WOWCF_MGX_ESCAPES) {
ul = 0;
}
else {
LOGDEBUG(3,("Querying support for escape %x\n",i));
ul = GETINT16(Escape(HDC32(parg16->f1),
INT32(parg16->f2),
sizeof(int),
(PVOID)&i,
NULL));
}
break;
case GETTECHNOLOGY:
case PASSTHROUGH:
case DOWNLOADFACE:
case GETFACENAME:
case GETDEVICEUNITS:
case EPSPRINTING:
LOGDEBUG(3,("Querying support for escape %x\n",i));
ul = GETINT16(ExtEscape(HDC32(parg16->f1),
INT32(parg16->f2),
sizeof(int),
(PVOID)&i,
0,
NULL));
break;
default:
LOGDEBUG(3,("Querying support for escape %x\n",i));
ul = GETINT16(Escape(HDC32(parg16->f1),
INT32(parg16->f2),
sizeof(int),
(PVOID)&i,
NULL));
break;
}
}
break;
case SETABORTPROC:
((PTDB)SEGPTR(pFrame->wTDB, 0))->TDB_vpfnAbortProc =
FETCHDWORD(parg16->f4);
ul = GETINT16(Escape(HDC32(parg16->f1),
INT32(parg16->f2),
0,
(LPCSTR)W32AbortProc,
NULL));
break;
case GETDEVICEUNITS:
{
PVOID pout;
LONG out[4];
ul = GETINT16(Escape(HDC32(parg16->f1),
INT32(parg16->f2),
0,
NULL,
(LPSTR)out));
if (ul == 1) {
GETOPTPTR(parg16->f5, 0, pout);
RtlCopyMemory(pout, out, sizeof(out));
FREEOPTPTR(pout);
}
}
break;
case GETPAIRKERNTABLE:
{
PVOID pout;
GETOPTPTR(parg16->f5, 0, pout);
ul = GETINT16(iGetKerningPairsEsc32(
HDC32(parg16->f1),
(ESCKERNPAIR*) pout));
FREEOPTPTR(pout);
}
break;
case GETEXTENDEDTEXTMETRICS:
{
PVOID pout;
EXTTEXTMETRIC etm;
if ( (ul = GETINT16(GetETM(HDC32(parg16->f1),
&etm))) != 0 )
{
GETOPTPTR(parg16->f5, 0, pout);
RtlCopyMemory(pout, &etm, sizeof(EXTTEXTMETRIC));
FREEOPTPTR(pout);
}
}
break;
case OPENCHANNEL: // 4110
if (CURRENTPTD()->dwWOWCompatFlags & WOWCF_MGX_ESCAPES) {
ul = 0;
} else {
DOCINFO16 *pout;
DOCINFO DocInfo;
DocInfo.cbSize = sizeof(DocInfo);
DocInfo.lpszDatatype = "RAW";
DocInfo.fwType = 0;
GETOPTPTR(parg16->f5, 0, pout);
if (pout) {
GETOPTPTR(pout->lpszDocName, 0, DocInfo.lpszDocName);
GETOPTPTR(pout->lpszOutput, 0, DocInfo.lpszOutput);
ul = StartDoc(HDC32(parg16->f1), &DocInfo);
FREEOPTPTR(DocInfo.lpszDocName);
FREEOPTPTR(DocInfo.lpszOutput);
} else {
//
// Fifth parameter null, use old (startdoc) format
//
GETOPTPTR(parg16->f4, 0, DocInfo.lpszDocName);
DocInfo.lpszOutput = NULL;
ul = StartDoc(HDC32(parg16->f1), &DocInfo);
FREEOPTPTR(DocInfo.lpszDocName);
}
FREEOPTPTR(pout);
}
break;
case DOWNLOADHEADER: // 4111
if (CURRENTPTD()->dwWOWCompatFlags & WOWCF_MGX_ESCAPES) {
ul = 0;
}
else {
PBYTE pout;
char ach[64];
GETOPTPTR(parg16->f5, 0, pout);
if (pout) {
ul = GETINT16(ExtEscape(HDC32(parg16->f1),
INT32(parg16->f2),
0,
NULL,
sizeof(ach),
ach));
strcpy (pout, ach);
}
else {
ul = GETINT16(ExtEscape(HDC32(parg16->f1),
INT32(parg16->f2),
0,
NULL,
0,
NULL));
}
FREEOPTPTR(pout);
}
break;
case CLOSECHANNEL: // 4112
if (CURRENTPTD()->dwWOWCompatFlags & WOWCF_MGX_ESCAPES) {
ul = 0;
}
else {
// send any buffered data streams to the printer before EndDoc
if(CURRENTPTD()->dwWOWCompatFlagsEx & WOWCFEX_FORMFEEDHACK) {
SendFormFeedHack(HDC32(parg16->f1));
}
ul = EndDoc(HDC32(parg16->f1));
}
break;
// This Escape is defined for PageMaker. It is SETGDIXFORM.
// ChandanC, 24/5/93.
//
case SETGDIXFORM: // 4113
case RESETPAGE: // 4114
if (CURRENTPTD()->dwWOWCompatFlags & WOWCF_MGX_ESCAPES) {
ul = 0;
}
else {
ul = 1;
}
break;
case POSTSCRIPT_PASSTHROUGH: // 4115
if (CURRENTPTD()->dwWOWCompatFlags & WOWCF_MGX_ESCAPES) {
ul = 0;
}
else {
ul = GETINT16(Escape(HDC32(parg16->f1),
INT32(parg16->f2),
(FETCHWORD(*(PWORD)pin) + 2),
(LPCSTR)pin,
NULL));
}
break;
case ENCAPSULATED_POSTSCRIPT: // 4116
if (CURRENTPTD()->dwWOWCompatFlags & WOWCF_MGX_ESCAPES) {
ul = 0;
}
else {
DWORD cb;
PVOID lpInData32 = NULL;
lpInData32 = pin;
cb = FETCHDWORD (*(PDWORD) pin);
if ((DWORD) pin & 3) {
if (lpInData32 = (PVOID) malloc_w (cb)) {
RtlCopyMemory(lpInData32, pin, cb);
}
else {
ul = 0;
break;
}
}
ul = GETINT16(DrawEscape(HDC32(parg16->f1),
INT32(parg16->f2),
cb,
lpInData32));
if (((DWORD) pin & 3) && (lpInData32)) {
free_w (lpInData32);
}
}
break;
case POSTSCRIPT_DATA:
if (CURRENTPTD()->dwWOWCompatFlags & WOWCF_MGX_ESCAPES) {
ul = 0;
LOGDEBUG (LOG_ALWAYS, ("MicroGraphax app using POSTSCRIPT_DATA, contact PingW/ChandanC\n"));
WOW32ASSERT(FALSE);
}
else {
//
// XPress needs IGNORESTARTPAGE escape.
// PingW, ChandanC 3/22/94
//
if (CURRENTPTD()->dwWOWCompatFlags & WOWCF_NEEDIGNORESTARTPAGE) {
int l;
char szBuf[40];
if ((l = ExtEscape(HDC32(parg16->f1),
GETTECHNOLOGY,
0,
NULL,
sizeof(szBuf),
szBuf)) > 0) {
if (!_stricmp(szBuf, szPostscript)) {
l = ExtEscape(HDC32(parg16->f1),
IGNORESTARTPGAE,
0,
NULL,
0,
NULL);
}
}
}
ul = GETINT16(Escape(HDC32(parg16->f1),
INT32(parg16->f2),
(FETCHWORD(*(PWORD)pin) + 2),
(LPCSTR)pin,
NULL));
}
break;
case POSTSCRIPT_IGNORE:
if (CURRENTPTD()->dwWOWCompatFlags & WOWCF_MGX_ESCAPES) {
ul = 0;
LOGDEBUG (LOG_ALWAYS, ("MicroGraphax app using POSTSCRIPT_IGNORE, contact PingW/ChandanC\n"));
WOW32ASSERT(FALSE);
}
else {
ul = GETINT16(Escape(HDC32(parg16->f1),
INT32(parg16->f2),
INT32(parg16->f3),
(LPCSTR)pin,
NULL));
}
break;
case BEGIN_PATH:
// Some apps set the empty clip region before doing the path escapes,
// We need to undo that so the drawing APIs between begin and endpath
// go through to drivers.
SelectClipRgn(HDC32(parg16->f1),NULL);
case END_PATH:
case CLIP_TO_PATH:
ul = GETINT16(Escape(HDC32(parg16->f1),
INT32(parg16->f2),
INT32(parg16->f3),
(LPCSTR)pin,
NULL));
break;
case PASSTHROUGH:
// if this is a form feed hack app...
if(CURRENTPTD()->dwWOWCompatFlagsEx & WOWCFEX_FORMFEEDHACK) {
ul = HandleFormFeedHack(HDC32(parg16->f1),
pin,
FETCHWORD(*(PWORD)pin)); // cb only
}
else {
ul = GETINT16(Escape(HDC32(parg16->f1),
INT32(parg16->f2),
(FETCHWORD(*(PWORD)pin) + 2),
(LPCSTR)pin,
NULL));
}
break;
case FLUSHOUTPUT:
ul = TRUE;
break;
case DOWNLOADFACE:
{
WORD InData;
PWORD lpInData = NULL;
// PM5 forgot to set there map mode so we do it.
if (CURRENTPTD()->dwWOWCompatFlags & WOWCF_FORCETWIPSESCAPE)
iMapMode = SetMapMode(HDC32(parg16->f1),MM_TWIPS);
if (pin) {
InData = FETCHWORD(*(PWORD)pin);
lpInData = &InData;
}
ul = GETINT16(Escape(HDC32(parg16->f1),
INT32(parg16->f2),
sizeof(USHORT),
(LPCSTR)lpInData,
NULL));
if (CURRENTPTD()->dwWOWCompatFlags & WOWCF_FORCETWIPSESCAPE)
SetMapMode(HDC32(parg16->f1),iMapMode);
}
break;
case GETFACENAME:
{
PSZ pout;
CHAR ach[60];
// PM5 forgot to set there map mode so we do it.
if (CURRENTPTD()->dwWOWCompatFlags & WOWCF_FORCETWIPSESCAPE)
iMapMode = SetMapMode(HDC32(parg16->f1),MM_TWIPS);
GETOPTPTR(parg16->f5, 0, pout);
// This HACK is for FH4.0 only. If you have any questions
// talk to PingW or ChandanC.
// July 21st 1994.
//
if (CURRENTPTD()->dwWOWCompatFlags & WOWCF_ADD_MSTT) {
ExtEscape(HDC32(parg16->f1),
ADD_MSTT,
0,
NULL,
60,
ach);
}
// pass in 60 as a magic number. Just copy out the valid string.
ul = GETINT16(ExtEscape(HDC32(parg16->f1),
INT32(parg16->f2),
INT32(parg16->f3),
pin,
60,
ach));
strcpy (pout, ach);
FREEOPTPTR(pout);
if (CURRENTPTD()->dwWOWCompatFlags & WOWCF_FORCETWIPSESCAPE)
SetMapMode(HDC32(parg16->f1),iMapMode);
}
break;
case EPSPRINTING:
{
WORD InData;
PWORD lpInData = NULL;
if (pin)
{
InData = FETCHWORD(*(PWORD)pin);
lpInData = &InData;
}
ul = GETINT16(ExtEscape(HDC32(parg16->f1),
INT32(parg16->f2),
sizeof(BOOL),
(LPCSTR)lpInData,
0,
NULL));
}
break;
case GETTECHNOLOGY:
{
PVOID pout;
buf[0] = '\0';
GETOPTPTR(parg16->f5, 0, pout);
if (!(CURRENTPTD()->dwWOWCompatFlags & WOWCF_FORCENOPOSTSCRIPT))
{
ul = GETINT16(ExtEscape(HDC32(parg16->f1),
INT32(parg16->f2),
INT32(parg16->f3),
pin,
sizeof(buf),
buf));
}
if (pout)
strcpy (pout, buf);
FREEOPTPTR(pout);
}
break;
case SETCOPYCOUNT:
{
int cCopiesOut, cCopiesIn=1;
if (pin)
cCopiesIn = *(UNALIGNED SHORT *)pin;
ul = GETINT16(Escape(HDC32(parg16->f1),
INT32(parg16->f2),
pin ? sizeof(cCopiesIn) : 0,
pin ? &cCopiesIn : pin,
parg16->f5 ? &cCopiesOut : NULL));
if ( parg16->f5 ) {
if ( (INT)ul > 0 ) {
PUTINT16(parg16->f5, cCopiesOut);
} else {
// Pagemaker v4 needs the output value
PUTINT16(parg16->f5, 1);
}
}
}
break;
case STARTDOC:
{
PVOID pout;
GETOPTPTR(parg16->f5, 0, pout);
//
// Win32 StartDoc depends on having the correct current directory
// when printing to FILE: (which pops up for a filename).
//
UpdateDosCurrentDirectory(DIR_DOS_TO_NT);
ul = GETINT16(Escape(HDC32(parg16->f1),
INT32(parg16->f2),
INT32(parg16->f3),
pin,
pout));
//
// PhotoShop needs a StartPage when it does StartDoc Escape.
// PingW, ChandanC 3/22/94
//
if (CURRENTPTD()->dwWOWCompatFlags & WOWCF_NEEDSTARTPAGE) {
int l;
char szBuf[80];
//
// It should be done ONLY for POSTSCRIPT drivers
//
if ((l = ExtEscape(HDC32(parg16->f1),
GETTECHNOLOGY,
0,
NULL,
sizeof(szBuf),
szBuf)) > 0) {
if (!_stricmp(szBuf, szPostscript)) {
l = StartPage(HDC32(parg16->f1));
}
}
}
FREEOPTPTR(pout);
}
break;
default:
{
PVOID pout;
GETOPTPTR(parg16->f5, 0, pout);
ul = GETINT16(Escape(HDC32(parg16->f1),
INT32(parg16->f2),
INT32(parg16->f3),
pin,
pout));
FREEOPTPTR(pout);
}
break;
} // end switch
FREEOPTPTR(pin);
FREEARGPTR(parg16);
RETURN(ul);
}
ULONG FASTCALL WG32ExcludeClipRect(PVDMFRAME pFrame)
{
ULONG ul;
register PEXCLUDECLIPRECT16 parg16;
GETARGPTR(pFrame, sizeof(EXCLUDECLIPRECT16), parg16);
ul = GETINT16(ExcludeClipRect(HDC32(parg16->f1),
INT32(parg16->f2),
INT32(parg16->f3),
INT32(parg16->f4),
INT32(parg16->f5)));
FREEARGPTR(parg16);
RETURN(ul);
}
ULONG FASTCALL WG32ExtFloodFill(PVDMFRAME pFrame)
{
ULONG ul;
register PEXTFLOODFILL16 parg16;
GETARGPTR(pFrame, sizeof(EXTFLOODFILL16), parg16);
ul = GETBOOL16(ExtFloodFill(HDC32(parg16->f1),
INT32(parg16->f2),
INT32(parg16->f3),
DWORD32(parg16->f4),
WORD32(parg16->f5)));
WOW32APIWARN (ul, "ExtFloodFill");
FREEARGPTR(parg16);
RETURN(ul);
}
ULONG FASTCALL WG32FillRgn(PVDMFRAME pFrame)
{
ULONG ul;
register PFILLRGN16 parg16;
GETARGPTR(pFrame, sizeof(FILLRGN16), parg16);
ul = GETBOOL16(FillRgn(HDC32(parg16->f1),
HRGN32(parg16->f2),
HBRUSH32(parg16->f3)));
FREEARGPTR(parg16);
RETURN(ul);
}
ULONG FASTCALL WG32FloodFill(PVDMFRAME pFrame)
{
ULONG ul;
register PFLOODFILL16 parg16;
GETARGPTR(pFrame, sizeof(FLOODFILL16), parg16);
ul = GETBOOL16(FloodFill(HDC32(parg16->f1),
INT32(parg16->f2),
INT32(parg16->f3),
DWORD32(parg16->f4)));
WOW32APIWARN (ul, "FloodFill");
FREEARGPTR(parg16);
RETURN(ul);
}
ULONG FASTCALL WG32FrameRgn(PVDMFRAME pFrame)
{
ULONG ul;
register PFRAMERGN16 parg16;
GETARGPTR(pFrame, sizeof(FRAMERGN16), parg16);
ul = GETBOOL16(FrameRgn(HDC32(parg16->f1),
HRGN32(parg16->f2),
HBRUSH32(parg16->f3),
INT32(parg16->f4),
INT32(parg16->f5)));
FREEARGPTR(parg16);
RETURN(ul);
}
#if 0
// there's no thunk for this routine
ULONG FASTCALL WG32GdiFlush(PVDMFRAME pFrame)
{
GdiFlush();
RETURN(0);
pFrame;
}
#endif
ULONG FASTCALL WG32GetBitmapBits(PVDMFRAME pFrame)
{
ULONG ul;
PBYTE pb3;
register PGETBITMAPBITS16 parg16;
GETARGPTR(pFrame, sizeof(GETBITMAPBITS16), parg16);
ALLOCVDMPTR(parg16->f3, (INT)parg16->f2, pb3);
ul = GETLONG16(GetBitmapBits(HBITMAP32(parg16->f1),
LONG32(parg16->f2),
pb3));
WOW32APIWARN (ul, "GetBitmapBits");
FLUSHVDMPTR(parg16->f3, (INT)parg16->f2, pb3);
FREEVDMPTR(pb3);
FREEARGPTR(parg16);
RETURN(ul);
}
ULONG FASTCALL WG32GetBitmapDimension(PVDMFRAME pFrame)
{
ULONG ul;
SIZE size2;
register PGETBITMAPDIMENSION16 parg16;
GETARGPTR(pFrame, sizeof(GETBITMAPDIMENSION16), parg16);
ul = 0;
if (GetBitmapDimensionEx(HBITMAP32(parg16->f1), &size2)) {
ul = (WORD)size2.cx | (size2.cy << 16);
}
else {
WOW32APIWARN (ul, "GetBitmapBits");
}
FREEARGPTR(parg16);
RETURN(ul);
}
ULONG FASTCALL WG32GetBkColor(PVDMFRAME pFrame)
{
ULONG ul;
register PGETBKCOLOR16 parg16;
GETARGPTR(pFrame, sizeof(GETBKCOLOR16), parg16);
ul = GETDWORD16(GetBkColor(HDC32(parg16->f1)));
FREEARGPTR(parg16);
RETURN(ul);
}
ULONG FASTCALL WG32GetBkMode(PVDMFRAME pFrame)
{
ULONG ul;
register PGETBKMODE16 parg16;
GETARGPTR(pFrame, sizeof(GETBKMODE16), parg16);
ul = GETINT16(GetBkMode(HDC32(parg16->f1)));
FREEARGPTR(parg16);
RETURN(ul);
}
ULONG FASTCALL WG32GetBrushOrg(PVDMFRAME pFrame)
{
ULONG ul;
POINT pt;
POINT pt2;
register PGETBRUSHORG16 parg16;
GETARGPTR(pFrame, sizeof(GETBRUSHORG16), parg16);
// for windows compatability, we must first add the DCorg
// since windows brushorg is relative to the screen where as NT
// is relative to the window. In the future, this should call
// a private gdi entry point to avoid an extra c/s hit. (erick)
ul = 0;
if (GetDCOrgEx(HDC32(parg16->f1),&pt))
{
if (GetBrushOrgEx(HDC32(parg16->f1), &pt2)) {
ul = (WORD)(pt2.x + pt.x) | ((pt2.y + pt.y) << 16);
}
}
FREEARGPTR(parg16);
RETURN(ul);
}
ULONG FASTCALL WG32GetClipBox(PVDMFRAME pFrame)
{
ULONG ul;
RECT t2;
register PGETCLIPBOX16 parg16;
HDC hdc;
GETARGPTR(pFrame, sizeof(GETCLIPBOX16), parg16);
hdc = HDC32(parg16->f1);
ul = GETINT16(GetClipBox(hdc,&t2));
if (CURRENTPTD()->dwWOWCompatFlags & WOWCF_SIMPLEREGION)
ul = SIMPLEREGION;
PUTRECT16(parg16->f2, &t2);
FREEARGPTR(parg16);
RETURN(ul);
}
ULONG FASTCALL WG32GetCurrentPosition(PVDMFRAME pFrame)
{
ULONG ul;
POINT pt;
register PGETCURRENTPOSITION16 parg16;
GETARGPTR(pFrame, sizeof(GETCURRENTPOSITION16), parg16);
ul = 0;
if (GetCurrentPositionEx(HDC32(parg16->f1), &pt)) {
ul = (WORD)pt.x | (pt.y << 16);
}
FREEARGPTR(parg16);
RETURN(ul);
}
ULONG FASTCALL WG32GetDCOrg(PVDMFRAME pFrame)
{
ULONG ul;
POINT pt;
register PGETDCORG16 parg16;
GETARGPTR(pFrame, sizeof(GETDCORG16), parg16);
ul = 0;
if ( GetDCOrgEx(HDC32(parg16->f1),&pt) ) {
ul = (WORD)pt.x | (pt.y << 16);
}
LOGDEBUG(6,("GetDCOrg for hdc %x returns %lx\n",parg16->f1,ul));
FREEARGPTR(parg16);
RETURN(ul);
}
// PowerPoint 2&3 call this 2 times for each slide in the slide previewer
// the lpvBits == NULL on the first call (presumably to find the size to
// allocate) -- in which case Win3.x returns 1
ULONG FASTCALL WG32GetDIBits(PVDMFRAME pFrame)
{
INT nbmiSize;
ULONG ul = 0L;
PBYTE pb5;
PBYTE pb6;
STACKBMI32 bmi32;
LPBITMAPINFO lpbmi32;
register PGETDIBITS16 parg16;
GETARGPTR(pFrame, sizeof(GETDIBITS16), parg16);
GETMISCPTR(parg16->f5, pb5);
GETMISCPTR(parg16->f6, pb6);
// copy just the BITMAPINFOHEADER portion of the BITMAPINFO struct
if(lpbmi32=(LPBITMAPINFO)CopyBMIH16ToBMIH32((PVPVOID)FETCHDWORD(parg16->f6),
(LPBITMAPINFOHEADER)&bmi32)) {
// gdi32 will adjust key fields of the BITMAPINFOHEADER & copy the
// color table into the 32-bit BITMAPINFO struct
if( ul = GETINT16(GetDIBits(HDC32(parg16->f1),
HBITMAP32(parg16->f2),
WORD32(parg16->f3),
WORD32(parg16->f4),
pb5,
lpbmi32,
WORD32(parg16->f7))) ) {
// if lpvBits, then they want the bits of the bitmap too
if(pb5) {
ul = WORD32(parg16->f4); // return # scanlines requested
FLUSHVDMPTR(parg16->f5, SIZE_BOGUS, pb5);
}
// else tell app that BITMAPINFO structure filled in only
else {
ul = 1L;
}
// copy the updated BITMAPINFO struct back into the 16-bit version
nbmiSize = GetBMI32Size(lpbmi32, WORD32(parg16->f7));
RtlCopyMemory(pb6, lpbmi32, nbmiSize);
FLUSHVDMPTR(parg16->f6, nbmiSize, pb6);
}
}
FREEMISCPTR(pb5);
FREEMISCPTR(pb6);
FREEARGPTR(parg16);
RETURN(ul);
}
ULONG FASTCALL WG32GetDeviceCaps(PVDMFRAME pFrame)
{
ULONG ul;
register PGETDEVICECAPS16 parg16;
GETARGPTR(pFrame, sizeof(GETDEVICECAPS16), parg16);
if (INT32(parg16->f2) == COLORRES) {
ul = 18;
}
else {
ul = GetDeviceCaps(HDC32(parg16->f1), INT32(parg16->f2));
if (ul == (ULONG)-1) {
switch (parg16->f2) {
case NUMBRUSHES:
case NUMPENS:
case NUMCOLORS:
ul = 2048;
break;
default:
break;
}
}
// if the 4plane conversion flag is set, tell them we are 4 planes 1bpp
// instead of 1plane 4bpp.
if (CURRENTPTD()->dwWOWCompatFlags & WOWCF_4PLANECONVERSION) {
if (INT32(parg16->f2) == BITSPIXEL) {
if ((ul == 4) && (GetDeviceCaps(HDC32(parg16->f1),PLANES) == 1))
ul = 1;
}
else if (INT32(parg16->f2) == PLANES) {
if ((ul == 1) && (GetDeviceCaps(HDC32(parg16->f1),BITSPIXEL) == 4))
ul = 4;
}
}
if ( (POLYGONALCAPS == parg16->f2) && (CURRENTPTD()->dwWOWCompatFlags & WOWCF_NOPC_RECTANGLE)) {
ul &= !PC_RECTANGLE; // Quattro Pro 1.0 for Windows doesn't handle this bit well.
}
}
ul = GETINT16(ul);
FREEARGPTR(parg16);
RETURN(ul);
}
ULONG FASTCALL WG32GetEnvironment(PVDMFRAME pFrame)
{
// not a Win32 function
//
// if lpEnviron==NULL then the user is querying the size of device
// data. WinProj doesn't check the return value, calling the driver
// with an undersized buffer, trashing the global heap.
// WinFax passes a hard coded 0xA9 == 0x44+0x69 == sizeof(win3.0 DevMode) +
// known WinFax.DRV->dmDriverExtra. Beware also that WinFax calls this
// whenever an app calls any API that requires a DevMode.
ULONG ul=0;
register PGETENVIRONMENT16 parg16;
PSZ psz;
PSZ psz1 = NULL;
VPDEVMODE31 vpdm2;
CHAR szDriver[40];
UINT cbT = 0;
WORD nMaxBytes;
GETARGPTR(pFrame, sizeof(GETENVIRONMENT16), parg16);
// save off the 16-bit params now since this could callback into a 16-bit
// fax driver & cause 16-bit memory to move.
GETPSZPTR(parg16->f1, psz);
if(psz) {
psz1 = malloc_w(lstrlen(psz)+1);
if(psz1) {
lstrcpy(psz1, psz);
}
}
FREEPSZPTR(psz);
vpdm2 = FETCHDWORD(parg16->f2);
nMaxBytes = FETCHWORD(parg16->f3);
FREEARGPTR(parg16);
// invalidate all flat ptrs to 16:16 memory now
if (!(*spoolerapis[WOW_EXTDEVICEMODE].lpfn)) {
if (!LoadLibraryAndGetProcAddresses("WINSPOOL.DRV", spoolerapis, WOW_SPOOLERAPI_COUNT)) {
return (0);
}
}
// get required size for output buffer
// When WinFax calls this api, calls to GetDriverName for szDriver ==
// "FaxModem" seem to fail -- this is a good thing if the app called
// ExtDeviceMode() because we would get into an infinite loop here. WinFax
// just fills in a DevMode with default values if this api fails.
if (GetDriverName(psz1, szDriver)) {
ul = (*spoolerapis[WOW_EXTDEVICEMODE].lpfn)(NULL,
NULL,
NULL,
szDriver,
psz1,
NULL,
NULL,
0);
LOGDEBUG(6,("WOW::GetEnvironment returning ul = %d, for Device = %s, Port = %s \n", ul, szDriver, psz1));
// adjust the size for our DEVMODE handling (see note in wstruc.c)
// (it won't hurt to allocate too much)
if(ul) {
ul += sizeof(WOWDM31);
cbT = (UINT)ul;
}
// if they also want us to fill in their environment structure...
if ((vpdm2 != 0) && (ul != 0)) {
LPDEVMODE lpdmOutput;
if (lpdmOutput = malloc_w(ul)) {
// this might be calling into a 16-bit fax driver!!
ul = (*spoolerapis[WOW_EXTDEVICEMODE].lpfn)(NULL,
NULL,
lpdmOutput,
szDriver,
psz1,
NULL,
NULL,
DM_OUT_BUFFER);
// if a WinFax call to GetDriverName() succeeds & gets to here
// we may need to hack on the lpdmOutput->dmSize==0x40
// (Win3.0 size) to account for the hard coded buffer size of
// 0xa9 the app passes. So far I haven't seen WinFax get past
// GetDriverName() call & it still seems to work OK.
if (ul > 0L) {
// Use the min of nMaxBytes & what we calculated
ThunkDevMode32to16(vpdm2, lpdmOutput, min(nMaxBytes, cbT));
}
free_w(lpdmOutput);
LOGDEBUG(6,("WOW::GetEnvironment getting DEVMODE structure, ul = %d, for Device = %s, Port = %s \n", ul, szDriver, psz1));
}
}
}
free_w(psz1);
RETURN(ul);
}
ULONG FASTCALL WG32GetMapMode(PVDMFRAME pFrame)
{
ULONG ul;
register PGETMAPMODE16 parg16;
GETARGPTR(pFrame, sizeof(GETMAPMODE16), parg16);
ul = GETINT16(GetMapMode(HDC32(parg16->f1)));
FREEARGPTR(parg16);
RETURN(ul);
}
ULONG FASTCALL WG32GetNearestColor(PVDMFRAME pFrame)
{
ULONG ul;
register PGETNEARESTCOLOR16 parg16;
GETARGPTR(pFrame, sizeof(GETNEARESTCOLOR16), parg16);
ul = GETDWORD16(GetNearestColor(HDC32(parg16->f1), DWORD32(parg16->f2)));
FREEARGPTR(parg16);
RETURN(ul);
}
ULONG FASTCALL WG32GetObject(PVDMFRAME pFrame)
{
ULONG ul;
HANDLE hgdi;
register PGETOBJECT16 parg16;
GETARGPTR(pFrame, sizeof(GETOBJECT16), parg16);
hgdi = HOBJ32(parg16->f1);
switch (GetObjectType(hgdi)) {
case OBJ_BITMAP:
{
BITMAP bm;
ul = GETINT16(GetObject(hgdi, sizeof(BITMAP), (LPSTR)&bm));
if (ul) {
PUTBITMAP16(parg16->f3, parg16->f2, &bm);
if ( ul > sizeof(BITMAP16) ) {
ul = sizeof(BITMAP16);
}
}
}
break;
case OBJ_BRUSH:
{
LOGBRUSH lb;
ul = GETINT16(GetObject(hgdi, sizeof(LOGBRUSH), (LPSTR)&lb));
if (ul) {
PUTLOGBRUSH16(parg16->f3, parg16->f2, &lb);
if (ul > sizeof(LOGBRUSH16)) {
ul = sizeof(LOGBRUSH16);
}
}
}
break;
case OBJ_PEN:
{
LOGPEN lp;
ul = GETINT16(GetObject(hgdi, sizeof(LOGPEN), (LPSTR)&lp));
if (ul) {
PUTLOGPEN16(parg16->f3, parg16->f2, &lp);
if (ul > sizeof(LOGPEN16)) {
ul = sizeof(LOGPEN16);
}
}
}
break;
case OBJ_FONT:
{
LOGFONT lf;
ul = GETINT16(GetObject(hgdi, sizeof(LOGFONT), (LPSTR)&lf));
if (ul) {
PUTLOGFONT16(parg16->f3, parg16->f2, &lf);
if (ul > sizeof(LOGFONT16)) {
ul = sizeof(LOGFONT16);
}
}
}
break;
case OBJ_PAL:
{
PSHORT16 lpT;
SHORT sT;
ul = GETINT16(GetObject(hgdi, sizeof(SHORT), (LPSTR)&sT));
if (ul && (FETCHWORD(parg16->f2) >= sizeof(WORD))) {
GETVDMPTR(FETCHDWORD(parg16->f3), sizeof(WORD), lpT);
if (lpT) {
STOREWORD(lpT[0], sT);
}
FREEVDMPTR(lpT);
}
}
break;
default:
{
PBYTE pb3;
LOGDEBUG(LOG_ALWAYS,(" HACK: GetObject handle unknown, contact ChandanC\n"));
GETVDMPTR(parg16->f3, parg16->f2, pb3);
ul = GETINT16(GetObject(hgdi, INT32(parg16->f2), pb3));
FLUSHVDMPTR(parg16->f3, parg16->f2, pb3);
FREEVDMPTR(pb3);
}
} // switch
WOW32APIWARN(ul, "GetObject");
FREEARGPTR(parg16);
RETURN(ul);
}
ULONG FASTCALL WG32GetPixel(PVDMFRAME pFrame)
{
ULONG ul;
register PGETPIXEL16 parg16;
GETARGPTR(pFrame, sizeof(GETPIXEL16), parg16);
ul = GETDWORD16(GetPixel(HDC32(parg16->f1),
INT32(parg16->f2),
INT32(parg16->f3)));
if (ul == CLR_INVALID) {
LOGDEBUG(6,("GetPixel : Pixel outside of clipping region\n"));
}
FREEARGPTR(parg16);
RETURN(ul);
}
ULONG FASTCALL WG32GetPolyFillMode(PVDMFRAME pFrame)
{
ULONG ul;
register PGETPOLYFILLMODE16 parg16;
GETARGPTR(pFrame, sizeof(GETPOLYFILLMODE16), parg16);
ul = GETINT16(GetPolyFillMode(HDC32(parg16->f1)));
FREEARGPTR(parg16);
RETURN(ul);
}
ULONG FASTCALL WG32GetROP2(PVDMFRAME pFrame)
{
ULONG ul;
register PGETROP216 parg16;
GETARGPTR(pFrame, sizeof(GETROP216), parg16);
ul = GETINT16(GetROP2(HDC32(parg16->f1)));
FREEARGPTR(parg16);
RETURN(ul);
}
ULONG FASTCALL WG32GetRgnBox(PVDMFRAME pFrame)
{
ULONG ul;
RECT t2;
register PGETRGNBOX16 parg16;
GETARGPTR(pFrame, sizeof(GETRGNBOX16), parg16);
ul = GETINT16(GetRgnBox(HRGN32(parg16->f1), &t2));
PUTRECT16(parg16->f2, &t2);
FREEARGPTR(parg16);
RETURN(ul);
}
ULONG FASTCALL WG32GetStockObject(PVDMFRAME pFrame)
{
ULONG ul;
register PGETSTOCKOBJECT16 parg16;
GETARGPTR(pFrame, sizeof(GETSTOCKOBJECT16), parg16);
ul = GETHOBJ16(GetStockObject(INT32(parg16->f1)));
WOW32APIWARN(ul, "GetStockObject");
FREEARGPTR(parg16);
RETURN(ul);
}
ULONG FASTCALL WG32GetStretchBltMode(PVDMFRAME pFrame)
{
ULONG ul;
register PGETSTRETCHBLTMODE16 parg16;
GETARGPTR(pFrame, sizeof(GETSTRETCHBLTMODE16), parg16);
ul = GETINT16(GetStretchBltMode(HDC32(parg16->f1)));
FREEARGPTR(parg16);
RETURN(ul);
}
ULONG FASTCALL WG32GetViewportExt(PVDMFRAME pFrame)
{
ULONG ul;
SIZE size;
register PGETVIEWPORTEXT16 parg16;
GETARGPTR(pFrame, sizeof(GETVIEWPORTEXT16), parg16);
ul = 0;
if (GetViewportExtEx(HDC32(parg16->f1), &size)) {
//
// win31 returns 1 rather than 0 unless there was an error
//
if (!(ul = (WORD)size.cx | (size.cy << 16)))
ul = 1;
}
FREEARGPTR(parg16);
RETURN(ul);
}
ULONG FASTCALL WG32GetViewportOrg(PVDMFRAME pFrame)
{
ULONG ul;
POINT pt;
register PGETVIEWPORTORG16 parg16;
GETARGPTR(pFrame, sizeof(GETVIEWPORTORG16), parg16);
ul = 0;
if (GetViewportOrgEx(HDC32(parg16->f1), &pt)) {
ul = (WORD)pt.x | (pt.y << 16);
}
FREEARGPTR(parg16);
RETURN(ul);
}
ULONG FASTCALL WG32GetWindowExt(PVDMFRAME pFrame)
{
ULONG ul;
SIZE size;
register PGETWINDOWEXT16 parg16;
GETARGPTR(pFrame, sizeof(GETWINDOWEXT16), parg16);
ul = 0;
if (GetWindowExtEx(HDC32(parg16->f1), &size)) {
if (!(ul = (WORD)size.cx | (size.cy << 16))) // see above
ul = 1;
}
FREEARGPTR(parg16);
RETURN(ul);
}
ULONG FASTCALL WG32GetWindowOrg(PVDMFRAME pFrame)
{
ULONG ul;
POINT pt;
register PGETWINDOWORG16 parg16;
GETARGPTR(pFrame, sizeof(GETWINDOWORG16), parg16);
ul = 0;
if (GetWindowOrgEx(HDC32(parg16->f1), &pt)) {
ul = (WORD)pt.x | (pt.y << 16);
}
FREEARGPTR(parg16);
RETURN(ul);
}
ULONG FASTCALL WG32IntersectClipRect(PVDMFRAME pFrame)
{
ULONG ul;
register PINTERSECTCLIPRECT16 parg16;
GETARGPTR(pFrame, sizeof(INTERSECTCLIPRECT16), parg16);
ul = GETINT16(IntersectClipRect(HDC32(parg16->f1),
INT32(parg16->f2),
INT32(parg16->f3),
INT32(parg16->f4),
INT32(parg16->f5)));
FREEARGPTR(parg16);
RETURN(ul);
}
ULONG FASTCALL WG32InvertRgn(PVDMFRAME pFrame)
{
ULONG ul;
register PINVERTRGN16 parg16;
GETARGPTR(pFrame, sizeof(INVERTRGN16), parg16);
ul = GETBOOL16(InvertRgn(HDC32(parg16->f1), HRGN32(parg16->f2)));
FREEARGPTR(parg16);
RETURN(ul);
}
ULONG FASTCALL WG32LPtoDP(PVDMFRAME pFrame)
{
ULONG ul;
LPPOINT t2;
register PLPTODP16 parg16;
POINT BufferT[128];
GETARGPTR(pFrame, sizeof(LPTODP16), parg16);
t2 = STACKORHEAPALLOC(parg16->f3 * sizeof(POINT), sizeof(BufferT), BufferT);
getpoint16(parg16->f2, parg16->f3, t2);
ul = GETBOOL16(LPtoDP(HDC32(parg16->f1), t2, INT32(parg16->f3)));
PUTPOINTARRAY16(parg16->f2, parg16->f3, t2);
STACKORHEAPFREE(t2, BufferT);
FREEARGPTR(parg16);
RETURN(ul);
}
void W32LineDDAFunc(int x, int y, PLINEDDADATA pDDAData)
{
PARM16 Parm16;
WOW32ASSERT(pDDAData);
Parm16.LineDDAProc.vpData = (VPVOID)pDDAData->dwUserDDAParam;
Parm16.LineDDAProc.x = (SHORT)x;
Parm16.LineDDAProc.y = (SHORT)y;
Parm16.LineDDAProc.vpData = (VPVOID)pDDAData->dwUserDDAParam;
CallBack16(RET_LINEDDAPROC, &Parm16, pDDAData->vpfnLineDDAProc, NULL);
return;
}
ULONG FASTCALL WG32LineDDA(PVDMFRAME pFrame)
{
LINEDDADATA DDAData;
register PLINEDDA16 parg16;
GETARGPTR(pFrame, sizeof(LINEDDA16), parg16);
DDAData.vpfnLineDDAProc = DWORD32(parg16->f5);
DDAData.dwUserDDAParam = DWORD32(parg16->f6);
LineDDA(INT32(parg16->f1),
INT32(parg16->f2),
INT32(parg16->f3),
INT32(parg16->f4),
(LINEDDAPROC)W32LineDDAFunc,
(LPARAM)&DDAData);
// 16-bit memory may have moved - invalidate flat pointers now
FREEVDMPTR(pFrame);
FREEARGPTR(parg16);
RETURN(1L);
}
ULONG FASTCALL WG32LineTo(PVDMFRAME pFrame)
{
ULONG ul;
register PLINETO16 parg16;
GETARGPTR(pFrame, sizeof(LINETO16), parg16);
ul = GETBOOL16(LineTo(HDC32(parg16->f1),
INT32(parg16->f2),
INT32(parg16->f3)));
FREEARGPTR(parg16);
RETURN(ul);
}
ULONG FASTCALL WG32MoveTo(PVDMFRAME pFrame)
{
ULONG ul;
POINT pt;
register PMOVETO16 parg16;
GETARGPTR(pFrame, sizeof(MOVETO16), parg16);
ul = 0;
pt.x = 1L; // see "METAFILE NOTE"
pt.y = 0L;
if (MoveToEx(HDC32(parg16->f1),
INT32(parg16->f2),
INT32(parg16->f3),
&pt)) {
ul = (WORD)pt.x | (pt.y << 16);
}
FREEARGPTR(parg16);
RETURN(ul);
}
ULONG FASTCALL WG32MulDiv(PVDMFRAME pFrame)
{
ULONG ul;
register PMULDIV16 parg16;
GETARGPTR(pFrame, sizeof(MULDIV16), parg16);
ul = GETINT16(MulDiv(INT32(parg16->f1),
INT32(parg16->f2),
INT32(parg16->f3)));
FREEARGPTR(parg16);
RETURN(ul);
}
ULONG FASTCALL WG32OffsetClipRgn(PVDMFRAME pFrame)
{
ULONG ul;
register POFFSETCLIPRGN16 parg16;
GETARGPTR(pFrame, sizeof(OFFSETCLIPRGN16), parg16);
ul = GETINT16(OffsetClipRgn(HDC32(parg16->f1),
INT32(parg16->f2),
INT32(parg16->f3)));
FREEARGPTR(parg16);
RETURN(ul);
}
ULONG FASTCALL WG32OffsetRgn(PVDMFRAME pFrame)
{
ULONG ul;
register POFFSETRGN16 parg16;
GETARGPTR(pFrame, sizeof(OFFSETRGN16), parg16);
ul = GETINT16(OffsetRgn(HRGN32(parg16->f1),
INT32(parg16->f2),
INT32(parg16->f3)));
FREEARGPTR(parg16);
RETURN(ul);
}
ULONG FASTCALL WG32OffsetViewportOrg(PVDMFRAME pFrame)
{
ULONG ul;
POINT pt;
register POFFSETVIEWPORTORG16 parg16;
GETARGPTR(pFrame, sizeof(OFFSETVIEWPORTORG16), parg16);
ul = 0;
pt.x = 1L; // see "METAFILE NOTE"
pt.y = 0L;
if (OffsetViewportOrgEx(HDC32(parg16->f1),
INT32(parg16->f2),
INT32(parg16->f3),
&pt)) {
ul = (WORD)pt.x | (pt.y << 16);
}
FREEARGPTR(parg16);
RETURN(ul);
}
ULONG FASTCALL WG32OffsetWindowOrg(PVDMFRAME pFrame)
{
ULONG ul;
POINT pt;
register POFFSETWINDOWORG16 parg16;
GETARGPTR(pFrame, sizeof(OFFSETWINDOWORG16), parg16);
ul = 0;
pt.x = 1L; // see "METAFILE NOTE"
pt.y = 0L;
if (OffsetWindowOrgEx(HDC32(parg16->f1),
INT32(parg16->f2),
INT32(parg16->f3),
&pt)) {
ul = (WORD)pt.x | (pt.y << 16);
}
FREEARGPTR(parg16);
RETURN(ul);
}
ULONG FASTCALL WG32PaintRgn(PVDMFRAME pFrame)
{
ULONG ul;
register PPAINTRGN16 parg16;
GETARGPTR(pFrame, sizeof(PAINTRGN16), parg16);
ul = GETBOOL16(PaintRgn(HDC32(parg16->f1), HRGN32(parg16->f2)));
FREEARGPTR(parg16);
RETURN(ul);
}
ULONG FASTCALL WG32PatBlt(PVDMFRAME pFrame)
{
ULONG ul;
register PPATBLT16 parg16;
GETARGPTR(pFrame, sizeof(PATBLT16), parg16);
ul = GETBOOL16(PatBlt(HDC32(parg16->hdc),
INT32(parg16->x),
INT32(parg16->y),
INT32(parg16->nWidth),
INT32(parg16->nHeight),
DWORD32(parg16->dwRop)));
WOW32APIWARN(ul, "PatBlt");
FREEARGPTR(parg16);
RETURN(ul);
}
ULONG FASTCALL WG32Pie(PVDMFRAME pFrame)
{
ULONG ul;
register PPIE16 parg16;
GETARGPTR(pFrame, sizeof(PIE16), parg16);
ul = GETBOOL16(Pie(HDC32(parg16->f1),
INT32(parg16->f2),
INT32(parg16->f3),
INT32(parg16->f4),
INT32(parg16->f5),
INT32(parg16->f6),
INT32(parg16->f7),
INT32(parg16->f8),
INT32(parg16->f9)));
FREEARGPTR(parg16);
RETURN(ul);
}
ULONG FASTCALL WG32PolyPolygon(PVDMFRAME pFrame)
{
ULONG ul;
LPPOINT pPoints;
PINT pPolyCnt;
UINT cpts = 0;
INT ii;
register PPOLYPOLYGON16 parg16;
INT cInt16;
INT BufferT[256]; // comfortably large array
GETARGPTR(pFrame, sizeof(POLYPOLYGON16), parg16);
cInt16 = INT32(parg16->f4);
pPolyCnt = STACKORHEAPALLOC(cInt16 * sizeof(INT), sizeof(BufferT), BufferT);
if (!pPolyCnt) {
FREEARGPTR(parg16);
RETURN(0);
}
getintarray16(parg16->f3, cInt16, pPolyCnt);
for (ii=0; ii < cInt16; ii++)
cpts += pPolyCnt[ii];
pPoints = STACKORHEAPALLOC(cpts * sizeof(POINT),
sizeof(BufferT) - cInt16 * sizeof(INT),
BufferT + cInt16);
getpoint16(parg16->f2, cpts, pPoints);
ul = GETBOOL16(PolyPolygon(HDC32(parg16->f1),
pPoints,
pPolyCnt,
INT32(parg16->f4)));
STACKORHEAPFREE(pPoints, BufferT + cInt16);
STACKORHEAPFREE(pPolyCnt, BufferT);
FREEARGPTR(parg16);
RETURN(ul);
}
ULONG FASTCALL WG32PolyPolylineWOW(PVDMFRAME pFrame)
{
ULONG ul;
register PPOLYPOLYLINEWOW16 parg16;
LPPOINT pptArray;
LPDWORD pcntArray;
DWORD cnt;
GETARGPTR(pFrame, sizeof(POLYPOLYLINEWOW16), parg16);
cnt = FETCHDWORD(parg16->f4);
GETVDMPTR(parg16->f2, sizeof(POINT)*cnt, pptArray);
GETVDMPTR(parg16->f3, sizeof(DWORD)*cnt, pcntArray);
ul = GETBOOL16(PolyPolyline(HDC32(parg16->f1),
pptArray,
pcntArray,
cnt));
FREEVDMPTR(pptArray);
FREEVDMPTR(pcntArray);
FREEARGPTR(parg16);
RETURN(ul);
}
ULONG FASTCALL WG32Polygon(PVDMFRAME pFrame)
{
ULONG ul;
LPPOINT p2;
register PPOLYGON16 parg16;
POINT BufferT[128];
GETARGPTR(pFrame, sizeof(POLYGON16), parg16);
p2 = STACKORHEAPALLOC(parg16->f3 * sizeof(POINT), sizeof(BufferT), BufferT);
getpoint16(parg16->f2, parg16->f3, p2);
ul = GETBOOL16(Polygon(HDC32(parg16->f1), p2, INT32(parg16->f3)));
STACKORHEAPFREE(p2, BufferT);
FREEARGPTR(parg16);
RETURN(ul);
}
ULONG FASTCALL WG32Polyline(PVDMFRAME pFrame)
{
ULONG ul;
PPOINT t2;
register PPOLYLINE16 parg16;
POINT BufferT[128];
GETARGPTR(pFrame, sizeof(POLYLINE16), parg16);
t2 = STACKORHEAPALLOC(parg16->f3 * sizeof(POINT), sizeof(BufferT), BufferT);
getpoint16(parg16->f2, parg16->f3, t2);
ul = GETBOOL16(Polyline(HDC32(parg16->f1), t2, INT32(parg16->f3)));
STACKORHEAPFREE(t2, BufferT);
FREEARGPTR(parg16);
RETURN(ul);
}
ULONG FASTCALL WG32PtInRegion(PVDMFRAME pFrame)
{
ULONG ul;
register PPTINREGION16 parg16;
GETARGPTR(pFrame, sizeof(PTINREGION16), parg16);
ul = GETBOOL16(PtInRegion(HRGN32(parg16->f1),
INT32(parg16->f2),
INT32(parg16->f3)));
FREEARGPTR(parg16);
RETURN(ul);
}
ULONG FASTCALL WG32PtVisible(PVDMFRAME pFrame)
{
ULONG ul;
register PPTVISIBLE16 parg16;
GETARGPTR(pFrame, sizeof(PTVISIBLE16), parg16);
ul = GETBOOL16(PtVisible(HDC32(parg16->f1),
INT32(parg16->f2),
INT32(parg16->f3)));
FREEARGPTR(parg16);
RETURN(ul);
}
ULONG FASTCALL WG32RectInRegion(PVDMFRAME pFrame)
{
ULONG ul;
RECT t2;
register PRECTINREGION16 parg16;
GETARGPTR(pFrame, sizeof(RECTINREGION16), parg16);
WOW32VERIFY(GETRECT16(parg16->f2, &t2));
ul = GETBOOL16(RectInRegion(HRGN32(parg16->f1), &t2));
FREEARGPTR(parg16);
RETURN(ul);
}
ULONG FASTCALL WG32RectVisible(PVDMFRAME pFrame)
{
ULONG ul;
RECT t2;
register PRECTVISIBLE16 parg16;
GETARGPTR(pFrame, sizeof(RECTVISIBLE16), parg16);
WOW32VERIFY(GETRECT16(parg16->f2, &t2));
ul = GETBOOL16(RectVisible(HDC32(parg16->f1), &t2));
FREEARGPTR(parg16);
RETURN(ul);
}
ULONG FASTCALL WG32Rectangle(PVDMFRAME pFrame)
{
ULONG ul;
register PRECTANGLE16 parg16;
GETARGPTR(pFrame, sizeof(RECTANGLE16), parg16);
ul = GETBOOL16(Rectangle(HDC32(parg16->hdc),
INT32(parg16->x1),
INT32(parg16->y1),
INT32(parg16->x2),
INT32(parg16->y2)));
FREEARGPTR(parg16);
RETURN(ul);
}
ULONG FASTCALL WG32RestoreDC(PVDMFRAME pFrame)
{
ULONG ul;
register PRESTOREDC16 parg16;
GETARGPTR(pFrame, sizeof(RESTOREDC16), parg16);
ul = GETBOOL16(RestoreDC(HDC32(parg16->f1), INT32(parg16->f2)));
FREEARGPTR(parg16);
RETURN(ul);
}
ULONG FASTCALL WG32RoundRect(PVDMFRAME pFrame)
{
ULONG ul;
register PROUNDRECT16 parg16;
GETARGPTR(pFrame, sizeof(ROUNDRECT16), parg16);
ul = GETBOOL16(RoundRect(HDC32(parg16->f1),
INT32(parg16->f2),
INT32(parg16->f3),
INT32(parg16->f4),
INT32(parg16->f5),
INT32(parg16->f6),
INT32(parg16->f7)));
FREEARGPTR(parg16);
RETURN(ul);
}
ULONG FASTCALL WG32SaveDC(PVDMFRAME pFrame)
{
ULONG ul;
register PSAVEDC16 parg16;
GETARGPTR(pFrame, sizeof(SAVEDC16), parg16);
ul = GETINT16(SaveDC(HDC32(parg16->f1)));
FREEARGPTR(parg16);
RETURN(ul);
}
ULONG FASTCALL WG32ScaleViewportExt(PVDMFRAME pFrame)
{
ULONG ul;
SIZE size;
register PSCALEVIEWPORTEXT16 parg16;
GETARGPTR(pFrame, sizeof(SCALEVIEWPORTEXT16), parg16);
ul = 0;
if (ScaleViewportExtEx(HDC32(parg16->f1),
INT32(parg16->f2),
INT32(parg16->f3),
INT32(parg16->f4),
INT32(parg16->f5),
&size)) {
if (!(ul = (WORD)size.cx | (size.cy << 16))) // see above
ul = 1;
}
FREEARGPTR(parg16);
RETURN(ul);
}
ULONG FASTCALL WG32ScaleWindowExt(PVDMFRAME pFrame)
{
ULONG ul;
SIZE size;
register PSCALEWINDOWEXT16 parg16;
GETARGPTR(pFrame, sizeof(SCALEWINDOWEXT16), parg16);
ul = 0;
if (ScaleWindowExtEx(HDC32(parg16->f1),
INT32(parg16->f2),
INT32(parg16->f3),
INT32(parg16->f4),
INT32(parg16->f5),
&size)) {
if (!(ul = (WORD)size.cx | (size.cy << 16))) // see above
ul = 1;
}
FREEARGPTR(parg16);
RETURN(ul);
}
ULONG FASTCALL WG32SelectClipRgn(PVDMFRAME pFrame)
{
ULONG ul;
register PSELECTCLIPRGN16 parg16;
GETARGPTR(pFrame, sizeof(SELECTCLIPRGN16), parg16);
ul = GETINT16(SelectClipRgn(HDC32(parg16->f1), HRGN32(parg16->f2)));
WOW32APIWARN(ul, "SelectClipRgn");
FREEARGPTR(parg16);
RETURN(ul);
}
ULONG FASTCALL WG32SelectObject(PVDMFRAME pFrame)
{
ULONG ul;
register PSELECTOBJECT16 parg16;
GETARGPTR(pFrame, sizeof(SELECTOBJECT16), parg16);
ul = GETHOBJ16(SelectObject(HDC32(parg16->f1), HOBJ32(parg16->f2)));
WOW32APIWARN(ul, "SelectObject");
FREEARGPTR(parg16);
RETURN(ul);
}
/******************************Public*Routine******************************\
* PBYTE pjCvtPlaneToPacked4
*
* Convert a 4plane, 1bpp bitmap into a 1plane, 4bpp bitmap.
* This functions returns a pointer that must later be freed with LocalFree().
*
* This has been added for PhotoShop 16 color vga compatability.
*
* History:
* 28-May-1993 -by- Eric Kutter [erick]
* Wrote it.
\**************************************************************************/
PBYTE pjCvtPlaneToPacked4(
BITMAP *pbm,
PBYTE pjSrc,
DWORD *pcjSrc)
{
PBYTE pjDstRet;
PBYTE pjDst;
PBYTE pjPlane[4]; // pointer to first byte of current scan for each plane
DWORD cjWidth; // width of the destination in bytes
DWORD cjSrcWidth; // width of the source scan in bytes inc. all planes
DWORD cy; // number of scans
BYTE shift; // shift value,
DWORD i,x,y;
// just grab the width of the dest out of the BITMAP
cjWidth = pbm->bmWidthBytes;
// the src should be word aligned for each plane with 4 planes
cjSrcWidth = ((pbm->bmWidth + 15) & ~15) / 8 * 4;
// compute the height, the smaller of the bm height and the source height
cy = min((DWORD)pbm->bmHeight,(DWORD)(*pcjSrc / cjSrcWidth));
// allocate the new chunk of memory
*pcjSrc = cy * cjWidth;
pjDst = LocalAlloc(LMEM_FIXED,*pcjSrc);
if (pjDst == NULL)
return(NULL);
pjDstRet = pjDst;
// intialize the beginings of the planes
for (i = 0; i < 4; ++i)
pjPlane[i] = pjSrc + (cjSrcWidth / 4) * i;
// loop through the scans
for (y = 0; y < cy; ++y)
{
shift = 7;
// loop through the bytes within a scan
for (x = 0; x < cjWidth; ++x)
{
// bit 7 -> nibble 1
// bit 6 -> nibble 0
// bit 5 -> nibble 3
// bit 4 -> nibble 2
// . . .
*pjDst = (((pjPlane[0][x/4] >> (shift-1)) & 1) << 0 ) | // 0x01
(((pjPlane[1][x/4] >> (shift-1)) & 1) << 1 ) | // 0x02
(((pjPlane[2][x/4] >> (shift-1)) & 1) << 2 ) | // 0x04
(((pjPlane[3][x/4] >> (shift-1)) & 1) << 3 ) | // 0x08
(((pjPlane[0][x/4] >> (shift-0)) & 1) << 4 ) | // 0x10
(((pjPlane[1][x/4] >> (shift-0)) & 1) << 5 ) | // 0x20
(((pjPlane[2][x/4] >> (shift-0)) & 1) << 6 ) | // 0x40
(((pjPlane[3][x/4] >> (shift-0)) & 1) << 7 ); // 0x80
pjDst++;
shift = (shift - 2) & 7;
}
pjPlane[0] += cjSrcWidth;
pjPlane[1] += cjSrcWidth;
pjPlane[2] += cjSrcWidth;
pjPlane[3] += cjSrcWidth;
}
return(pjDstRet);
}
ULONG FASTCALL WG32SetBitmapBits(PVDMFRAME pFrame)
{
ULONG ul;
PBYTE pb3;
register PSETBITMAPBITS16 parg16;
HBITMAP hbm;
DWORD cj;
BITMAP bm;
BOOL fValidObj;
GETARGPTR(pFrame, sizeof(SETBITMAPBITS16), parg16);
GETOPTPTR(parg16->f3, 0, pb3);
hbm = HBITMAP32(parg16->f1);
cj = DWORD32(parg16->f2);
fValidObj = (GetObject(hbm,sizeof(BITMAP),&bm) == sizeof(BITMAP));
if (CURRENTPTD()->dwWOWCompatFlags & WOWCF_4PLANECONVERSION) {
// Get the size of the destination bitmap
if (fValidObj &&
(bm.bmPlanes == 1) &&
(bm.bmBitsPixel == 4))
{
PBYTE pjCvt = pjCvtPlaneToPacked4(&bm,pb3,&cj);
if (pjCvt)
ul = SetBitmapBits(hbm,cj,pjCvt);
else
ul = 0;
LocalFree(pjCvt);
hbm = 0;
}
}
else {
cj = min(cj, (DWORD)(bm.bmWidthBytes * bm.bmHeight));
}
if (hbm != 0)
ul = GETLONG16(SetBitmapBits(hbm,cj,pb3));
WOW32APIWARN (ul, "SetBitmapBits");
FREEMISCPTR(pb3);
FREEARGPTR(parg16);
RETURN(ul);
}
ULONG FASTCALL WG32SetBitmapDimension(PVDMFRAME pFrame)
{
ULONG ul;
SIZE size4;
register PSETBITMAPDIMENSION16 parg16;
GETARGPTR(pFrame, sizeof(SETBITMAPDIMENSION16), parg16);
ul = 0;
if (SetBitmapDimensionEx(HBITMAP32(parg16->f1),
INT32(parg16->f2),
INT32(parg16->f3),
&size4)) {
ul = (WORD)size4.cx | (size4.cy << 16);
}
FREEARGPTR(parg16);
RETURN(ul);
}
ULONG FASTCALL WG32SetBkColor(PVDMFRAME pFrame)
{
ULONG ul;
register PSETBKCOLOR16 parg16;
COLORREF color;
GETARGPTR(pFrame, sizeof(SETBKCOLOR16), parg16);
color = DWORD32(parg16->f2);
if (((ULONG)color >= 0x03000000) &&
(HIWORD(color) != 0x10ff))
{
color &= 0xffffff;
}
ul = GETDWORD16(SetBkColor(HDC32(parg16->f1), color));
FREEARGPTR(parg16);
RETURN(ul);
}
ULONG FASTCALL WG32SetBkMode(PVDMFRAME pFrame)
{
ULONG ul;
register PSETBKMODE16 parg16;
GETARGPTR(pFrame, sizeof(SETBKMODE16), parg16);
ul = GETINT16(SetBkMode(HDC32(parg16->f1), INT32(parg16->f2)));
FREEARGPTR(parg16);
RETURN(ul);
}
ULONG FASTCALL WG32SetBrushOrg(PVDMFRAME pFrame)
{
ULONG ul = 0;
POINT pt;
POINT pt2;
register PSETBRUSHORG16 parg16;
GETARGPTR(pFrame, sizeof(SETBRUSHORG16), parg16);
// for windows compatability, we must first subtract off the DCorg
// since windows brushorg is relative to the screen where as NT
// is relative to the window. In the future, this should call
// a private gdi entry point to avoid an extra c/s hit. (erick)
if (GetDCOrgEx(HDC32(parg16->f1),&pt))
{
ul = 0;
pt2.x = 1L; // see "METAFILE NOTE"
pt2.y = 0L;
if (SetBrushOrgEx(HDC32(parg16->f1),
INT32(parg16->f2) - pt.x,
INT32(parg16->f3) - pt.y,
&pt2)) {
// add the origin back on so the app gets a consistent return value.
// view...all from micrografx designer doesn't work unless this returns
// the right thing.
ul = (WORD)(pt2.x + pt.x) | ((pt2.y + pt.y) << 16);
}
}
FREEARGPTR(parg16);
RETURN(ul);
}
ULONG FASTCALL WG32SetDIBits(PVDMFRAME pFrame)
{
ULONG ul = 0L;
PBYTE pb5;
STACKBMI32 bmi32;
LPBITMAPINFO lpbmi32;
register PSETDIBITS16 parg16;
GETARGPTR(pFrame, sizeof(SETDIBITS16), parg16);
GETMISCPTR(parg16->f5, pb5);
lpbmi32 = CopyBMI16ToBMI32((PVPVOID)FETCHDWORD(parg16->f6),
(LPBITMAPINFO)&bmi32,
FETCHWORD(parg16->f7));
ul = GETINT16(SetDIBits(HDC32(parg16->f1),
HBITMAP32(parg16->f2),
WORD32(parg16->f3),
WORD32(parg16->f4),
pb5,
lpbmi32,
WORD32(parg16->f7)));
WOW32APIWARN (ul, "WG32SetDIBits\n");
FREEMISCPTR(pb5);
FREEARGPTR(parg16);
RETURN(ul);
}
ULONG FASTCALL WG32SetDIBitsToDevice(PVDMFRAME pFrame)
{
ULONG ul = 0L;
PSZ p10;
STACKBMI32 bmi32;
LPBITMAPINFO lpbmi32;
register PSETDIBITSTODEVICE16 parg16;
GETARGPTR(pFrame, sizeof(SETDIBITSTODEVICE16), parg16);
GETMISCPTR(parg16->f10, p10);
lpbmi32 = CopyBMI16ToBMI32((PVPVOID)FETCHDWORD(parg16->f11),
(LPBITMAPINFO)&bmi32,
FETCHWORD(parg16->f12));
// these are doc'd as WORD in Win3.0, doc'd as INT in Win3.1
WOW32ASSERTMSG(((INT)parg16->f4 >= 0),("WOW:signed val - a-craigj\n"));
WOW32ASSERTMSG(((INT)parg16->f5 >= 0),("WOW:signed val - a-craigj\n"));
WOW32ASSERTMSG(((INT)parg16->f8 >= 0),("WOW:signed val - a-craigj\n"));
WOW32ASSERTMSG(((INT)parg16->f9 >= 0),("WOW:signed val - a-craigj\n"));
ul = GETINT16(SetDIBitsToDevice(HDC32(parg16->f1),
INT32(parg16->f2),
INT32(parg16->f3),
WORD32(parg16->f4),
WORD32(parg16->f5),
INT32(parg16->f6),
INT32(parg16->f7),
WORD32(parg16->f8),
WORD32(parg16->f9),
p10,
lpbmi32,
WORD32(parg16->f12)));
WOW32APIWARN (ul, "WG32SetDIBitsToDevice\n");
FREEMISCPTR(p10);
FREEARGPTR(parg16);
RETURN(ul);
}
ULONG FASTCALL WG32SetMapMode(PVDMFRAME pFrame)
{
ULONG ul;
register PSETMAPMODE16 parg16;
GETARGPTR(pFrame, sizeof(SETMAPMODE16), parg16);
ul = GETINT16(SetMapMode(HDC32(parg16->f1), INT32(parg16->f2)));
FREEARGPTR(parg16);
RETURN(ul);
}
ULONG FASTCALL WG32SetMapperFlags(PVDMFRAME pFrame)
{
ULONG ul;
register PSETMAPPERFLAGS16 parg16;
GETARGPTR(pFrame, sizeof(SETMAPPERFLAGS16), parg16);
ul = GETDWORD16(SetMapperFlags(HDC32(parg16->f1), DWORD32(parg16->f2)));
FREEARGPTR(parg16);
RETURN(ul);
}
ULONG FASTCALL WG32SetPixel(PVDMFRAME pFrame)
{
ULONG ul;
register PSETPIXEL16 parg16;
GETARGPTR(pFrame, sizeof(SETPIXEL16), parg16);
ul = GETDWORD16(SetPixel(HDC32(parg16->f1),
INT32(parg16->f2),
INT32(parg16->f3),
DWORD32(parg16->f4)));
if (ul == CLR_INVALID) {
LOGDEBUG(6,("SetPixel : Pixel outside of clipping region\n"));
}
FREEARGPTR(parg16);
RETURN(ul);
}
ULONG FASTCALL WG32SetPolyFillMode(PVDMFRAME pFrame)
{
ULONG ul;
register PSETPOLYFILLMODE16 parg16;
GETARGPTR(pFrame, sizeof(SETPOLYFILLMODE16), parg16);
ul = GETINT16(SetPolyFillMode(HDC32(parg16->f1), INT32(parg16->f2)));
FREEARGPTR(parg16);
RETURN(ul);
}
ULONG FASTCALL WG32SetROP2(PVDMFRAME pFrame)
{
ULONG ul;
register PSETROP216 parg16;
GETARGPTR(pFrame, sizeof(SETROP216), parg16);
ul = GETINT16(SetROP2(HDC32(parg16->f1), INT32(parg16->f2)));
FREEARGPTR(parg16);
RETURN(ul);
}
ULONG FASTCALL WG32SetRectRgn(PVDMFRAME pFrame)
{
register PSETRECTRGN16 parg16;
GETARGPTR(pFrame, sizeof(SETRECTRGN16), parg16);
SetRectRgn(HRGN32(parg16->f1),
INT32(parg16->f2),
INT32(parg16->f3),
INT32(parg16->f4),
INT32(parg16->f5));
FREEARGPTR(parg16);
RETURN(0);
}
ULONG FASTCALL WG32SetStretchBltMode(PVDMFRAME pFrame)
{
ULONG ul;
register PSETSTRETCHBLTMODE16 parg16;
GETARGPTR(pFrame, sizeof(SETSTRETCHBLTMODE16), parg16);
ul = GETINT16(SetStretchBltMode(HDC32(parg16->f1), INT32(parg16->f2)));
WOW32APIWARN (ul, "SetStretchBltMode");
FREEARGPTR(parg16);
RETURN(ul);
}
ULONG FASTCALL WG32SetViewportExt(PVDMFRAME pFrame)
{
ULONG ul;
SIZE size;
register PSETVIEWPORTEXT16 parg16;
GETARGPTR(pFrame, sizeof(SETVIEWPORTEXT16), parg16);
ul = 0;
if (SetViewportExtEx(HDC32(parg16->f1),
INT32(parg16->f2),
INT32(parg16->f3),
&size)) {
if (!(ul = (WORD)size.cx | (size.cy << 16))) // see above
ul = 1;
}
FREEARGPTR(parg16);
RETURN(ul);
}
ULONG FASTCALL WG32SetViewportOrg(PVDMFRAME pFrame)
{
ULONG ul;
POINT pt;
register PSETVIEWPORTORG16 parg16;
GETARGPTR(pFrame, sizeof(SETVIEWPORTORG16), parg16);
ul = 0;
pt.x = 1L; // see "METAFILE NOTE"
pt.y = 0L;
if (SetViewportOrgEx(HDC32(parg16->f1),
INT32(parg16->f2),
INT32(parg16->f3),
&pt)) {
ul = (WORD)pt.x | (pt.y << 16);
}
FREEARGPTR(parg16);
RETURN(ul);
}
ULONG FASTCALL WG32SetWindowExt(PVDMFRAME pFrame)
{
ULONG ul;
SIZE size;
register PSETWINDOWEXT16 parg16;
GETARGPTR(pFrame, sizeof(SETWINDOWEXT16), parg16);
ul = 0;
if (SetWindowExtEx(HDC32(parg16->f1),
INT32(parg16->f2),
INT32(parg16->f3),
&size)) {
if (!(ul = (WORD)size.cx | (size.cy << 16))) // see above
ul = 1;
}
FREEARGPTR(parg16);
RETURN(ul);
}
ULONG FASTCALL WG32SetWindowOrg(PVDMFRAME pFrame)
{
ULONG ul;
POINT pt;
register PSETWINDOWORG16 parg16;
GETARGPTR(pFrame, sizeof(SETWINDOWORG16), parg16);
ul = 0;
pt.x = 1L; // see "METAFILE NOTE"
pt.y = 0L;
if (SetWindowOrgEx(HDC32(parg16->f1),
INT32(parg16->f2),
INT32(parg16->f3),
&pt)) {
ul = (WORD)pt.x | (pt.y << 16);
}
FREEARGPTR(parg16);
RETURN(ul);
}
ULONG FASTCALL WG32StretchBlt(PVDMFRAME pFrame)
{
ULONG ul;
register PSTRETCHBLT16 parg16;
GETARGPTR(pFrame, sizeof(STRETCHBLT16), parg16);
ul = GETBOOL16(StretchBlt(HDC32(parg16->f1),
INT32(parg16->f2),
INT32(parg16->f3),
INT32(parg16->f4),
INT32(parg16->f5),
HDC32(parg16->f6),
INT32(parg16->f7),
INT32(parg16->f8),
INT32(parg16->f9),
INT32(parg16->f10),
DWORD32(parg16->f11)));
WOW32APIWARN (ul, "StretchBlt");
FREEARGPTR(parg16);
RETURN(ul);
}
ULONG FASTCALL WG32StretchDIBits(PVDMFRAME pFrame)
{
ULONG ul = 0L;
PBYTE pb10;
STACKBMI32 bmi32;
LPBITMAPINFO lpbmi32;
register PSTRETCHDIBITS16 parg16;
GETARGPTR(pFrame, sizeof(STRETCHDIBITS16), parg16);
GETMISCPTR(parg16->f10, pb10);
lpbmi32 = CopyBMI16ToBMI32((PVPVOID)FETCHDWORD(parg16->f11),
(LPBITMAPINFO)&bmi32,
FETCHWORD(parg16->f12));
// some apps (QuarkXPress) don't fill in the size image for RLE's
// if it is 4bpp RLE with 0 size, fill in the size.
if ((lpbmi32->bmiHeader.biCompression == 2) &&
(lpbmi32->bmiHeader.biSizeImage == 0) &&
(pb10 != NULL))
{
int cj = 0;
PBYTE pj = pb10;
BOOL bDone = FALSE;
while (!bDone)
{
if (*pj == 0)
{
// absolute mode
switch (pj[1])
{
case 0: // end of line
pj += 2;
break;
case 1: // end of bitmap
pj += 2;
bDone = TRUE;
break;
case 2: // offset
pj += 4;
break;
default:
pj += (2 + ((pj[1] + 3) / 2) & ~1); // align nibles to word boundry
break;
}
}
else
{
// encoded mode
pj += 2;
}
}
lpbmi32->bmiHeader.biSizeImage = pj - pb10;
}
ul = GETINT16(StretchDIBits(HDC32(parg16->f1),
INT32(parg16->f2),
INT32(parg16->f3),
INT32(parg16->f4),
INT32(parg16->f5),
INT32(parg16->f6),
INT32(parg16->f7),
INT32(parg16->f8),
INT32(parg16->f9),
pb10,
lpbmi32,
(DWORD)FETCHWORD(parg16->f12),
DWORD32(parg16->f13)));
WOW32APIWARN (ul, "WG32StretchDIBits\n");
FREEMISCPTR(pb10);
FREEARGPTR(parg16);
RETURN(ul);
}
ULONG FASTCALL WG32UnrealizeObject(PVDMFRAME pFrame)
{
ULONG ul;
register PUNREALIZEOBJECT16 parg16;
GETARGPTR(pFrame, sizeof(UNREALIZEOBJECT16), parg16);
ul = GETBOOL16(UnrealizeObject(HOBJ32(parg16->f1)));
FREEARGPTR(parg16);
RETURN(ul);
}
// *** New Private APIs ***
#if 0
// no thunk for this routine!
ULONG FASTCALL WG32GetObjectType( PVDMFRAME pFrame)
{
ULONG ul;
PGETOBJECTTYPE16 parg16;
GETARGPTR(pFrame, sizeof(GETOBJECTTYPE16), parg16);
ul = GetObjectType(HOBJ32(parg16->f1));
FREEARGPTR(parg16);
RETURN(ul);
}
#endif
ULONG FASTCALL WG32GetCurrentObject( PVDMFRAME pFrame)
{
ULONG ul;
HANDLE h;
PGETCURRENTOBJECT16 parg16;
GETARGPTR(pFrame, sizeof(GETCURRENTOBJECT16), parg16);
h = GetCurrentObject(HDC32(parg16->f1), (ULONG)(parg16->f2));
ul = HGDI16(h);
FREEARGPTR(parg16);
RETURN(ul);
}
ULONG FASTCALL WG32GetRegionData( PVDMFRAME pFrame)
{
ULONG ul;
PBYTE pb3;
PGETREGIONDATA16 parg16;
GETARGPTR(pFrame, sizeof(GETREGIONDATA16), parg16);
ALLOCVDMPTR(parg16->f3, (INT)parg16->f2, pb3);
ul = GetRegionData(HRGN32(parg16->f1), (ULONG)(parg16->f2), (LPRGNDATA)pb3);
FLUSHVDMPTR(parg16->f3, (INT)parg16->f2, pb3);
FREEVDMPTR(pb3);
FREEARGPTR(parg16);
RETURN(ul);
}
ULONG FASTCALL WG32SetObjectOwner( PVDMFRAME pFrame)
{
ULONG ul = 1;
LOGDEBUG(6,("WOW32::WG32SetObjectOwner: was called \n"));
RETURN(ul);
}
//
// This routine calls back the apps SetAbortProc routine.
//
LONG W32AbortProc(HDC hPr, int code)
{
LONG lReturn;
PARM16 Parm16;
register PTD ptd;
DWORD AbortProcT;
ptd = CURRENTPTD();
WOW32ASSERT(ptd->htask16);
AbortProcT = ((PTDB)SEGPTR(ptd->htask16, 0))->TDB_vpfnAbortProc;
if (AbortProcT) {
Parm16.SetAbortProc.hPr = GETHDC16(hPr);
Parm16.SetAbortProc.code = (SHORT) code;
CallBack16(RET_SETABORTPROC,
&Parm16,
AbortProcT,
(PVPVOID)&lReturn);
lReturn = (LONG)LOWORD(lReturn); // Returns a BOOL
}
else {
lReturn = (LONG)TRUE;
}
return (lReturn);
}
// note: cb is the number of data bytes in lpData NOT including the USHORT byte
// count at the start of the data stream. In other words, lpData contains
// cb + sizeof(USHORT) bytes.
LONG HandleFormFeedHack(HDC hdc, LPBYTE lpdata, int cb)
{
int cbBytes;
LONG ul;
PFORMFEEDHACK pCur;
// look for a node with a pointer to a data stream buffer from the previous
// call to Escape(,,PASSTHROUGH,,)...
pCur = FindFormFeedHackNode(hdc);
// if we found one, it's time to send the data stream to the printer...
if(pCur) {
// ...time to send it to the printer
ul = GETINT16(Escape(hdc,
PASSTHROUGH,
pCur->cbBytes + sizeof(USHORT),
pCur->lpBytes,
NULL));
// free the current node
FreeFormFeedHackNode(pCur);
// if there was a problem we're done
if(ul <= 0) {
return(ul);
}
}
// send everything up to the last form feed in the new data stream
cbBytes = cb;
lpdata = SendFrontEndOfDataStream(hdc, lpdata, &cbBytes, &ul);
// if there was a problem
// OR if the entire data stream got sent since it didn't contain a formfeed
// -- we're done
if(lpdata == NULL) {
return(ul); // this will contain error code OR number of bytes sent
}
// else create a node for this data stream
else {
pCur = CreateFormFeedHackNode(hdc, cbBytes, lpdata);
// if we can't allocate a new node...
if(pCur == NULL) {
// Things are in pretty bad shape if we get to here...
// We need to write the byte count at the front of the data stream.
// Remember lpdata had a word size byte count at the front of it
// when it was sent to us.
// if any bytes got sent via SendFrontEndOfDataStream()...
if(cbBytes < cb) {
// ...first we need to word align this for Escape32()...
if((DWORD)lpdata & 0x00000001) {
lpdata--;
*lpdata = '\0'; // stick a harmless char in the stream
cbBytes++; // ...and account for it
}
// ...adjust the data stream ptr to accomodate the byte count...
lpdata -= sizeof(USHORT);
}
// ...write in the byte count...
*(UNALIGNED USHORT *)lpdata = cbBytes;
// ...and send the remainder of the data stream to the printer.
// If an extra page gets sent to the printer, too bad.
ul = GETINT16(Escape(hdc,
PASSTHROUGH,
cbBytes + sizeof(USHORT),
lpdata,
NULL));
// if the was an error, return it to the app
if(ul <= 0) {
return(ul);
}
// else we managed to get everything sent to the printer OK
else {
return(cb); // return the number of bytes the app sent
}
}
}
// return the number of bytes the app requested to send
return(cb);
}
LPBYTE SendFrontEndOfDataStream(HDC hdc, LPBYTE lpData, int *cb, LONG *ul)
{
int diff;
LPBYTE lpByte, lpStart;
// if there's no data or a bad cb, just send it so we can get the error code
if((lpData == NULL) || (*cb <= 0)) {
*ul = GETINT16(Escape(hdc,
PASSTHROUGH,
*cb + sizeof(USHORT),
lpData,
NULL));
return(NULL);
}
// find the start of the actual data after the byte count
lpStart = lpData + sizeof(USHORT);
// look for a formfeed char at or near the end of the data stream
lpByte = lpStart + ((*cb - 1) * sizeof(BYTE));
while(lpByte >= lpStart) {
// if we have found the odious formfeed char....
if((UCHAR)(*lpByte) == 0x0c) {
diff = lpByte - lpStart;
// send everything in the stream up to (but not incl) the formfeed
if(diff) {
// adjust the byte count in the data stream
*(UNALIGNED USHORT *)lpData = (USHORT)diff;
// send it to the printer
*ul = GETINT16(Escape(hdc,
PASSTHROUGH,
diff + sizeof(USHORT),
lpData,
NULL));
// if there was a problem, return it to the app
if(*ul <= 0) {
return(NULL);
}
}
// else formfeed is the first char in the data stream
else {
*ul = *cb; // just lie and say we sent it all
}
// adjust the remaining number of bytes
*cb -= diff;
// return ptr to the formfeed char as new start of data stream
return(lpByte);
}
lpByte--;
}
// if there are no formfeed's in the data stream just send the whole thing
*ul = GETINT16(Escape(hdc,
PASSTHROUGH,
*cb + sizeof(USHORT),
lpData,
NULL));
return(NULL); // specify we sent the whole thing
}
// note: this assumes that if there is a node, there is a list
void FreeFormFeedHackNode(PFORMFEEDHACK pNode)
{
PFORMFEEDHACK pCur, pPrev, pListStart;
pPrev = NULL;
pCur = pListStart = gpFormFeedHackList;
// if there is a node, there must be a node list
WOW32ASSERT(pCur);
if(pNode) {
while(pCur) {
if(pCur == pNode) {
if(pNode->lpBytes) {
free_w(pNode->lpBytes);
}
if(pPrev) {
pPrev->next = pCur->next;
}
else {
pListStart = pCur->next;
}
free_w(pNode);
break;
}
else {
pPrev = pCur;
pCur = pCur->next;
}
}
}
gpFormFeedHackList = pListStart;
}
void FreeTaskFormFeedHacks(HAND16 h16)
{
PFORMFEEDHACK pNext, pCur;
pCur = gpFormFeedHackList;
while(pCur) {
if(pCur->hTask16 == h16) {
// we already told the app we sent this so give it one last try
Escape(pCur->hdc,
PASSTHROUGH,
pCur->cbBytes + sizeof(USHORT),
pCur->lpBytes,
NULL);
pNext = pCur->next;
if(pCur->lpBytes) {
free_w(pCur->lpBytes);
}
if(pCur == gpFormFeedHackList) {
gpFormFeedHackList = pNext;
}
free_w(pCur);
pCur = pNext;
}
}
}
// this should only be called by Escape(,,ENDDOC,,)
void SendFormFeedHack(HDC hdc)
{
int cb;
LPBYTE pBytes = NULL;
PFORMFEEDHACK pCur;
pCur = gpFormFeedHackList;
while(pCur) {
if(pCur->hdc == hdc) {
if(pCur->lpBytes) {
cb = pCur->cbBytes;
// point to actual data after byte count
pBytes = pCur->lpBytes + sizeof(USHORT);
// strip the form feed from the buffered data stream...
if((UCHAR)(*pBytes) == 0x0c) {
*pBytes = '\0';
pBytes++;
cb--;
}
// strip the carriage ret from the buffered data stream...
// (some apps put a carriage return after the last formfeed)
if((UCHAR)(*pBytes) == 0x0d) {
*pBytes = '\0';
cb--;
}
// ...and send it to the printer
if(cb > 0) {
Escape(hdc,
PASSTHROUGH,
cb + sizeof(USHORT),
pCur->lpBytes,
NULL);
}
}
// free this node from the hack list now
FreeFormFeedHackNode(pCur);
break;
}
pCur = pCur->next;
}
}
PFORMFEEDHACK FindFormFeedHackNode(HDC hdc)
{
PFORMFEEDHACK pCur;
pCur = gpFormFeedHackList;
while(pCur) {
if(pCur->hdc == hdc) {
return(pCur);
}
pCur = pCur->next;
}
return(NULL);
}
// this will only get called if PART of the data stream got sent to the printer
PFORMFEEDHACK CreateFormFeedHackNode(HDC hdc, int cb, LPBYTE lpData)
{
LPBYTE pBytes;
PFORMFEEDHACK pNode;
// allocate a new node
pNode = malloc_w(sizeof(FORMFEEDHACK));
// if we were able to get one...
if(pNode) {
// ...allocate a buffer for the data stream
pBytes = malloc_w(cb + sizeof(USHORT));
// if we were able to get one...
if(pBytes) {
// ...fill in the node...
pNode->hdc = hdc;
pNode->lpBytes = pBytes;
pNode->cbBytes = cb;
pNode->hTask16 = CURRENTPTD()->htask16;
// ...and stick the new node at the front of the node list
pNode->next = gpFormFeedHackList;
gpFormFeedHackList = pNode;
// add the new size to the front of the data stream
*(UNALIGNED USHORT *)pBytes = (USHORT)cb;
pBytes += sizeof(USHORT);
// copy the the data stream into the node buffer
RtlCopyMemory(pBytes, lpData, cb);
return(pNode);
}
// else if we couldn't get a data stream buffer...
else {
free_w(pNode);
}
}
return(NULL); // return NULL if either allocate failed
}
// this should only be called by Escape(,,AbortDOC,,) and AbortDoc()
void RemoveFormFeedHack(HDC hdc)
{
PFORMFEEDHACK pNode;
pNode = FindFormFeedHackNode(hdc);
if(pNode) {
FreeFormFeedHackNode(pNode);
}
}