xref: /reactos/win32ss/gdi/gdi32/wine/rosglue.c (revision 279107d5)
1 
2 #include <precomp.h>
3 #include "gdi_private.h"
4 #undef SetWorldTransform
5 
6 #define NDEBUG
7 #include <debug.h>
8 
9 WINEDC *get_nulldrv_dc( PHYSDEV dev );
10 
11 BOOL nulldrv_BeginPath( PHYSDEV dev );
12 BOOL nulldrv_EndPath( PHYSDEV dev );
13 BOOL nulldrv_AbortPath( PHYSDEV dev );
14 BOOL nulldrv_CloseFigure( PHYSDEV dev );
15 BOOL nulldrv_SelectClipPath( PHYSDEV dev, INT mode );
16 BOOL nulldrv_FillPath( PHYSDEV dev );
17 BOOL nulldrv_StrokeAndFillPath( PHYSDEV dev );
18 BOOL nulldrv_StrokePath( PHYSDEV dev );
19 BOOL nulldrv_FlattenPath( PHYSDEV dev );
20 BOOL nulldrv_WidenPath( PHYSDEV dev );
21 
22 static INT i = 0;
23 
24 static
25 INT_PTR
26 NULL_Unused()
27 {
28     DPRINT1("NULL_Unused %d\n",i);
29     // __debugbreak();
30     return 0;
31 }
32 
33 static INT   NULL_SaveDC(PHYSDEV dev) { return 1; }
34 static BOOL  NULL_RestoreDC(PHYSDEV dev, INT level) { return TRUE; }
35 static INT   NULL_SetMapMode(PHYSDEV dev, INT iMode) { return 1; }
36 static HFONT NULL_SelectFont(PHYSDEV dev, HFONT hFont, UINT *aa_flags) { return NULL; }
37 static BOOL  NULL_SetWindowExtEx(PHYSDEV dev, INT cx, INT cy, SIZE *size) { return TRUE; }
38 static BOOL  NULL_SetViewportExtEx(PHYSDEV dev, INT cx, INT cy, SIZE *size) { return TRUE; }
39 static BOOL  NULL_SetWindowOrgEx(PHYSDEV dev, INT x, INT y, POINT *pt) { return TRUE; }
40 static BOOL  NULL_SetViewportOrgEx(PHYSDEV dev, INT x, INT y, POINT *pt) { return TRUE; }
41 static INT   NULL_ExtSelectClipRgn(PHYSDEV dev, HRGN hrgn, INT iMode) { return 1; }
42 static INT   NULL_IntersectClipRect(PHYSDEV dev, INT left, INT top, INT right, INT bottom) { return 1; }
43 static INT   NULL_OffsetClipRgn(PHYSDEV dev, INT x, INT y) { return SIMPLEREGION; }
44 static INT   NULL_ExcludeClipRect(PHYSDEV dev, INT left, INT top, INT right, INT bottom) { return 1; }
45 static BOOL  NULL_ExtTextOutW(PHYSDEV dev, INT x, INT y, UINT fuOptions, const RECT *lprc, LPCWSTR lpString, UINT cwc, const INT *lpDx) { return TRUE; }
46 static BOOL  NULL_ModifyWorldTransform( PHYSDEV dev, const XFORM* xform, DWORD mode ) { return TRUE; }
47 static BOOL  NULL_SetWorldTransform( PHYSDEV dev, const XFORM* xform ) { return TRUE; }
48 static BOOL  NULL_PolyPolyline(PHYSDEV dev, const POINT *pt, const DWORD *lpt, DWORD cw) { return TRUE; }
49 
50 static const struct gdi_dc_funcs DummyPhysDevFuncs =
51 {
52     (PVOID)NULL_Unused, //INT      (*pAbortDoc)(PHYSDEV);
53     nulldrv_AbortPath,  //BOOL     (*pAbortPath)(PHYSDEV);
54     (PVOID)NULL_Unused, //BOOL     (*pAlphaBlend)(PHYSDEV,struct bitblt_coords*,PHYSDEV,struct bitblt_coords*,BLENDFUNCTION);
55     (PVOID)NULL_Unused, //BOOL     (*pAngleArc)(PHYSDEV,INT,INT,DWORD,FLOAT,FLOAT);
56     (PVOID)NULL_Unused, //BOOL     (*pArc)(PHYSDEV,INT,INT,INT,INT,INT,INT,INT,INT);
57     (PVOID)NULL_Unused, //BOOL     (*pArcTo)(PHYSDEV,INT,INT,INT,INT,INT,INT,INT,INT);
58     nulldrv_BeginPath,  //BOOL     (*pBeginPath)(PHYSDEV);
59     (PVOID)NULL_Unused, //DWORD    (*pBlendImage)(PHYSDEV,BITMAPINFO*,const struct gdi_image_bits*,struct bitblt_coords*,struct bitblt_coords*,BLENDFUNCTION);
60     (PVOID)NULL_Unused, //BOOL     (*pChord)(PHYSDEV,INT,INT,INT,INT,INT,INT,INT,INT);
61     nulldrv_CloseFigure, //BOOL     (*pCloseFigure)(PHYSDEV);
62 
63     (PVOID)NULL_Unused, //BOOL     (*pCreateCompatibleDC)(PHYSDEV,PHYSDEV*);
64     (PVOID)NULL_Unused, //BOOL     (*pCreateDC)(PHYSDEV*,LPCWSTR,LPCWSTR,LPCWSTR,const DEVMODEW*);
65     (PVOID)NULL_Unused, //BOOL     (*pDeleteDC)(PHYSDEV);
66     (PVOID)NULL_Unused, //BOOL     (*pDeleteObject)(PHYSDEV,HGDIOBJ);
67     (PVOID)NULL_Unused, //DWORD    (*pDeviceCapabilities)(LPSTR,LPCSTR,LPCSTR,WORD,LPSTR,LPDEVMODEA);
68     (PVOID)NULL_Unused, //BOOL     (*pEllipse)(PHYSDEV,INT,INT,INT,INT);
69     (PVOID)NULL_Unused, //INT      (*pEndDoc)(PHYSDEV);
70     (PVOID)NULL_Unused, //INT      (*pEndPage)(PHYSDEV);
71     nulldrv_EndPath,    //BOOL     (*pEndPath)(PHYSDEV);
72     (PVOID)NULL_Unused, //BOOL     (*pEnumFonts)(PHYSDEV,LPLOGFONTW,FONTENUMPROCW,LPARAM);
73 
74     (PVOID)NULL_Unused, //INT      (*pEnumICMProfiles)(PHYSDEV,ICMENUMPROCW,LPARAM);
75     NULL_ExcludeClipRect, //INT      (*pExcludeClipRect)(PHYSDEV,INT,INT,INT,INT);
76     (PVOID)NULL_Unused, //INT      (*pExtDeviceMode)(LPSTR,HWND,LPDEVMODEA,LPSTR,LPSTR,LPDEVMODEA,LPSTR,DWORD);
77     (PVOID)NULL_Unused, //INT      (*pExtEscape)(PHYSDEV,INT,INT,LPCVOID,INT,LPVOID);
78     (PVOID)NULL_Unused, //BOOL     (*pExtFloodFill)(PHYSDEV,INT,INT,COLORREF,UINT);
79     NULL_ExtSelectClipRgn, //INT      (*pExtSelectClipRgn)(PHYSDEV,HRGN,INT);
80     NULL_ExtTextOutW, //BOOL     (*pExtTextOut)(PHYSDEV,INT,INT,UINT,const RECT*,LPCWSTR,UINT,const INT*);
81     nulldrv_FillPath,   //BOOL     (*pFillPath)(PHYSDEV);
82     (PVOID)NULL_Unused, //BOOL     (*pFillRgn)(PHYSDEV,HRGN,HBRUSH);
83     nulldrv_FlattenPath, //BOOL     (*pFlattenPath)(PHYSDEV);
84 
85     (PVOID)NULL_Unused, //BOOL     (*pFontIsLinked)(PHYSDEV);
86     (PVOID)NULL_Unused, //BOOL     (*pFrameRgn)(PHYSDEV,HRGN,HBRUSH,INT,INT);
87     (PVOID)NULL_Unused, //BOOL     (*pGdiComment)(PHYSDEV,UINT,const BYTE*);
88     (PVOID)NULL_Unused, //UINT     (*pGetBoundsRect)(PHYSDEV,RECT*,UINT);
89     (PVOID)NULL_Unused, //BOOL     (*pGetCharABCWidths)(PHYSDEV,UINT,UINT,LPABC);
90     (PVOID)NULL_Unused, //BOOL     (*pGetCharABCWidthsI)(PHYSDEV,UINT,UINT,WORD*,LPABC);
91     (PVOID)NULL_Unused, //BOOL     (*pGetCharWidth)(PHYSDEV,UINT,UINT,LPINT);
92     (PVOID)NULL_Unused, //INT      (*pGetDeviceCaps)(PHYSDEV,INT);
93     (PVOID)NULL_Unused, //BOOL     (*pGetDeviceGammaRamp)(PHYSDEV,LPVOID);
94     (PVOID)NULL_Unused, //DWORD    (*pGetFontData)(PHYSDEV,DWORD,DWORD,LPVOID,DWORD);
95     (PVOID)NULL_Unused, //BOOL     (*pGetFontRealizationInfo)(PHYSDEV,void*);
96     (PVOID)NULL_Unused, //DWORD    (*pGetFontUnicodeRanges)(PHYSDEV,LPGLYPHSET);
97     (PVOID)NULL_Unused, //DWORD    (*pGetGlyphIndices)(PHYSDEV,LPCWSTR,INT,LPWORD,DWORD);
98     (PVOID)NULL_Unused, //DWORD    (*pGetGlyphOutline)(PHYSDEV,UINT,UINT,LPGLYPHMETRICS,DWORD,LPVOID,const MAT2*);
99     (PVOID)NULL_Unused, //BOOL     (*pGetICMProfile)(PHYSDEV,LPDWORD,LPWSTR);
100     (PVOID)NULL_Unused, //DWORD    (*pGetImage)(PHYSDEV,BITMAPINFO*,struct gdi_image_bits*,struct bitblt_coords*);
101     (PVOID)NULL_Unused, //DWORD    (*pGetKerningPairs)(PHYSDEV,DWORD,LPKERNINGPAIR);
102     (PVOID)NULL_Unused, //COLORREF (*pGetNearestColor)(PHYSDEV,COLORREF);
103     (PVOID)NULL_Unused, //UINT     (*pGetOutlineTextMetrics)(PHYSDEV,UINT,LPOUTLINETEXTMETRICW);
104     (PVOID)NULL_Unused, //COLORREF (*pGetPixel)(PHYSDEV,INT,INT);
105     (PVOID)NULL_Unused, //UINT     (*pGetSystemPaletteEntries)(PHYSDEV,UINT,UINT,LPPALETTEENTRY);
106     (PVOID)NULL_Unused, //UINT     (*pGetTextCharsetInfo)(PHYSDEV,LPFONTSIGNATURE,DWORD);
107     (PVOID)NULL_Unused, //BOOL     (*pGetTextExtentExPoint)(PHYSDEV,LPCWSTR,INT,LPINT);
108     (PVOID)NULL_Unused, //BOOL     (*pGetTextExtentExPointI)(PHYSDEV,const WORD*,INT,LPINT);
109     (PVOID)NULL_Unused, //INT      (*pGetTextFace)(PHYSDEV,INT,LPWSTR);
110     (PVOID)NULL_Unused, //BOOL     (*pGetTextMetrics)(PHYSDEV,TEXTMETRICW*);
111     (PVOID)NULL_Unused, //BOOL     (*pGradientFill)(PHYSDEV,TRIVERTEX*,ULONG,void*,ULONG,ULONG);
112     NULL_IntersectClipRect, //INT      (*pIntersectClipRect)(PHYSDEV,INT,INT,INT,INT);
113     (PVOID)NULL_Unused, //BOOL     (*pInvertRgn)(PHYSDEV,HRGN);
114     (PVOID)NULL_Unused, //BOOL     (*pLineTo)(PHYSDEV,INT,INT);
115     NULL_ModifyWorldTransform, //BOOL     (*pModifyWorldTransform)(PHYSDEV,const XFORM*,DWORD);
116     (PVOID)NULL_Unused, //BOOL     (*pMoveTo)(PHYSDEV,INT,INT);
117     NULL_OffsetClipRgn, //INT      (*pOffsetClipRgn)(PHYSDEV,INT,INT);
118     (PVOID)NULL_Unused, //BOOL     (*pOffsetViewportOrgEx)(PHYSDEV,INT,INT,POINT*);
119     (PVOID)NULL_Unused, //BOOL     (*pOffsetWindowOrgEx)(PHYSDEV,INT,INT,POINT*);
120     (PVOID)NULL_Unused, //BOOL     (*pPaintRgn)(PHYSDEV,HRGN);
121     (PVOID)NULL_Unused, //BOOL     (*pPatBlt)(PHYSDEV,struct bitblt_coords*,DWORD);
122     (PVOID)NULL_Unused, //BOOL     (*pPie)(PHYSDEV,INT,INT,INT,INT,INT,INT,INT,INT);
123     (PVOID)NULL_Unused, //BOOL     (*pPolyBezier)(PHYSDEV,const POINT*,DWORD);
124     (PVOID)NULL_Unused, //BOOL     (*pPolyBezierTo)(PHYSDEV,const POINT*,DWORD);
125     (PVOID)NULL_Unused, //BOOL     (*pPolyDraw)(PHYSDEV,const POINT*,const BYTE *,DWORD);
126     (PVOID)NULL_Unused, //BOOL     (*pPolyPolygon)(PHYSDEV,const POINT*,const INT*,UINT);
127     NULL_PolyPolyline, //BOOL     (*pPolyPolyline)(PHYSDEV,const POINT*,const DWORD*,DWORD);
128     (PVOID)NULL_Unused, //BOOL     (*pPolygon)(PHYSDEV,const POINT*,INT);
129     (PVOID)NULL_Unused, //BOOL     (*pPolyline)(PHYSDEV,const POINT*,INT);
130     (PVOID)NULL_Unused, //BOOL     (*pPolylineTo)(PHYSDEV,const POINT*,INT);
131     (PVOID)NULL_Unused, //DWORD    (*pPutImage)(PHYSDEV,HRGN,BITMAPINFO*,const struct gdi_image_bits*,struct bitblt_coords*,struct bitblt_coords*,DWORD);
132     (PVOID)NULL_Unused, //UINT     (*pRealizeDefaultPalette)(PHYSDEV);
133     (PVOID)NULL_Unused, //UINT     (*pRealizePalette)(PHYSDEV,HPALETTE,BOOL);
134     (PVOID)NULL_Unused, //BOOL     (*pRectangle)(PHYSDEV,INT,INT,INT,INT);
135     (PVOID)NULL_Unused, //HDC      (*pResetDC)(PHYSDEV,const DEVMODEW*);
136     NULL_RestoreDC,     //BOOL     (*pRestoreDC)(PHYSDEV,INT);
137     (PVOID)NULL_Unused, //BOOL     (*pRoundRect)(PHYSDEV,INT,INT,INT,INT,INT,INT);
138     NULL_SaveDC,        //INT      (*pSaveDC)(PHYSDEV);
139     (PVOID)NULL_Unused, //BOOL     (*pScaleViewportExtEx)(PHYSDEV,INT,INT,INT,INT,SIZE*);
140     (PVOID)NULL_Unused, //BOOL     (*pScaleWindowExtEx)(PHYSDEV,INT,INT,INT,INT,SIZE*);
141     (PVOID)NULL_Unused, //HBITMAP  (*pSelectBitmap)(PHYSDEV,HBITMAP);
142     (PVOID)NULL_Unused, //HBRUSH   (*pSelectBrush)(PHYSDEV,HBRUSH,const struct brush_pattern*);
143     nulldrv_SelectClipPath, //BOOL     (*pSelectClipPath)(PHYSDEV,INT);
144     NULL_SelectFont,    //HFONT    (*pSelectFont)(PHYSDEV,HFONT,UINT*);
145     (PVOID)NULL_Unused, //HPALETTE (*pSelectPalette)(PHYSDEV,HPALETTE,BOOL);
146     (PVOID)NULL_Unused, //HPEN     (*pSelectPen)(PHYSDEV,HPEN,const struct brush_pattern*);
147     (PVOID)NULL_Unused, //INT      (*pSetArcDirection)(PHYSDEV,INT);
148     (PVOID)NULL_Unused, //COLORREF (*pSetBkColor)(PHYSDEV,COLORREF);
149     (PVOID)NULL_Unused, //INT      (*pSetBkMode)(PHYSDEV,INT);
150     (PVOID)NULL_Unused, //UINT     (*pSetBoundsRect)(PHYSDEV,RECT*,UINT);
151     (PVOID)NULL_Unused, //COLORREF (*pSetDCBrushColor)(PHYSDEV, COLORREF);
152     (PVOID)NULL_Unused, //COLORREF (*pSetDCPenColor)(PHYSDEV, COLORREF);
153     (PVOID)NULL_Unused, //INT      (*pSetDIBitsToDevice)(PHYSDEV,INT,INT,DWORD,DWORD,INT,INT,UINT,UINT,LPCVOID,BITMAPINFO*,UINT);
154     (PVOID)NULL_Unused, //VOID     (*pSetDeviceClipping)(PHYSDEV,HRGN);
155     (PVOID)NULL_Unused, //BOOL     (*pSetDeviceGammaRamp)(PHYSDEV,LPVOID);
156     (PVOID)NULL_Unused, //DWORD    (*pSetLayout)(PHYSDEV,DWORD);
157     NULL_SetMapMode,    //INT      (*pSetMapMode)(PHYSDEV,INT);
158     (PVOID)NULL_Unused, //DWORD    (*pSetMapperFlags)(PHYSDEV,DWORD);
159     (PVOID)NULL_Unused, //COLORREF (*pSetPixel)(PHYSDEV,INT,INT,COLORREF);
160     (PVOID)NULL_Unused, //INT      (*pSetPolyFillMode)(PHYSDEV,INT);
161     (PVOID)NULL_Unused, //INT      (*pSetROP2)(PHYSDEV,INT);
162     (PVOID)NULL_Unused, //INT      (*pSetRelAbs)(PHYSDEV,INT);
163     (PVOID)NULL_Unused, //INT      (*pSetStretchBltMode)(PHYSDEV,INT);
164     (PVOID)NULL_Unused, //UINT     (*pSetTextAlign)(PHYSDEV,UINT);
165     (PVOID)NULL_Unused, //INT      (*pSetTextCharacterExtra)(PHYSDEV,INT);
166     (PVOID)NULL_Unused, //COLORREF (*pSetTextColor)(PHYSDEV,COLORREF);
167     (PVOID)NULL_Unused, //BOOL     (*pSetTextJustification)(PHYSDEV,INT,INT);
168     NULL_SetViewportExtEx, //BOOL     (*pSetViewportExtEx)(PHYSDEV,INT,INT,SIZE*);
169     NULL_SetViewportOrgEx, //BOOL     (*pSetViewportOrgEx)(PHYSDEV,INT,INT,POINT*);
170     NULL_SetWindowExtEx, //BOOL     (*pSetWindowExtEx)(PHYSDEV,INT,INT,SIZE*);
171     NULL_SetWindowOrgEx, //BOOL     (*pSetWindowOrgEx)(PHYSDEV,INT,INT,POINT*);
172     NULL_SetWorldTransform, //BOOL     (*pSetWorldTransform)(PHYSDEV,const XFORM*);
173     (PVOID)NULL_Unused, //INT      (*pStartDoc)(PHYSDEV,const DOCINFOW*);
174     (PVOID)NULL_Unused, //INT      (*pStartPage)(PHYSDEV);
175     (PVOID)NULL_Unused, //BOOL     (*pStretchBlt)(PHYSDEV,struct bitblt_coords*,PHYSDEV,struct bitblt_coords*,DWORD);
176     (PVOID)NULL_Unused, //INT      (*pStretchDIBits)(PHYSDEV,INT,INT,INT,INT,INT,INT,INT,INT,const void*,BITMAPINFO*,UINT,DWORD);
177     nulldrv_StrokeAndFillPath, //BOOL     (*pStrokeAndFillPath)(PHYSDEV);
178     nulldrv_StrokePath, //BOOL     (*pStrokePath)(PHYSDEV);
179     (PVOID)NULL_Unused, //BOOL     (*pUnrealizePalette)(HPALETTE);
180     nulldrv_WidenPath,  //BOOL     (*pWidenPath)(PHYSDEV);
181     (PVOID)NULL_Unused, //struct opengl_funcs * (*wine_get_wgl_driver)(PHYSDEV,UINT);
182     0 // UINT       priority;
183 };
184 
185 WINEDC *get_nulldrv_dc( PHYSDEV dev )
186 {
187     return CONTAINING_RECORD( dev, WINEDC, NullPhysDev );
188 }
189 
190 WINEDC* get_physdev_dc( PHYSDEV dev )
191 {
192     while (dev->funcs != &DummyPhysDevFuncs)
193         dev = dev->next;
194     return get_nulldrv_dc( dev );
195 }
196 
197 static
198 GDILOOBJTYPE
199 ConvertObjectType(
200     WORD wType)
201 {
202     /* Get the GDI object type */
203     switch (wType)
204     {
205         case OBJ_PEN: return GDILoObjType_LO_PEN_TYPE;
206         case OBJ_BRUSH: return GDILoObjType_LO_BRUSH_TYPE;
207         case OBJ_DC: return GDILoObjType_LO_DC_TYPE;
208         case OBJ_METADC: return GDILoObjType_LO_METADC16_TYPE;
209         case OBJ_PAL: return GDILoObjType_LO_PALETTE_TYPE;
210         case OBJ_FONT: return GDILoObjType_LO_FONT_TYPE;
211         case OBJ_BITMAP: return GDILoObjType_LO_BITMAP_TYPE;
212         case OBJ_REGION: return GDILoObjType_LO_REGION_TYPE;
213         case OBJ_METAFILE: return GDILoObjType_LO_METAFILE16_TYPE;
214         case OBJ_MEMDC: return GDILoObjType_LO_DC_TYPE;
215         case OBJ_EXTPEN: return GDILoObjType_LO_EXTPEN_TYPE;
216         case OBJ_ENHMETADC: return GDILoObjType_LO_ALTDC_TYPE;
217         case OBJ_ENHMETAFILE: return GDILoObjType_LO_METAFILE_TYPE;
218         case OBJ_COLORSPACE: return GDILoObjType_LO_ICMLCS_TYPE;
219         default: return 0;
220     }
221 }
222 
223 HGDIOBJ
224 alloc_gdi_handle(
225     PVOID pvObject,
226     WORD wType,
227     const struct gdi_obj_funcs *funcs)
228 {
229     GDILOOBJTYPE eObjType;
230 
231     /* Get the GDI object type */
232     eObjType = ConvertObjectType(wType);
233     if ((eObjType != GDILoObjType_LO_METAFILE_TYPE) &&
234         (eObjType != GDILoObjType_LO_METAFILE16_TYPE) &&
235         (eObjType != GDILoObjType_LO_METADC16_TYPE))
236     {
237         /* This is not supported! */
238         ASSERT(FALSE);
239         return NULL;
240     }
241 
242     /* Insert the client object */
243     return GdiCreateClientObj(pvObject, eObjType);
244 }
245 
246 PVOID
247 free_gdi_handle(HGDIOBJ hobj)
248 {
249     /* Should be a client object */
250     return GdiDeleteClientObj(hobj);
251 }
252 
253 PVOID
254 GDI_GetObjPtr(
255     HGDIOBJ hobj,
256     WORD wType)
257 {
258     GDILOOBJTYPE eObjType;
259 
260     /* Check if the object type matches */
261     eObjType = ConvertObjectType(wType);
262     if ((eObjType == 0) || (GDI_HANDLE_GET_TYPE(hobj) != eObjType))
263     {
264         return NULL;
265     }
266 
267     /* Check if we have an ALTDC */
268     if (eObjType == GDILoObjType_LO_ALTDC_TYPE)
269     {
270         /* Object is stored as LDC */
271         return GdiGetLDC(hobj);
272     }
273 
274     /* Check for client objects */
275     if ((eObjType == GDILoObjType_LO_METAFILE_TYPE) ||
276         (eObjType == GDILoObjType_LO_METAFILE16_TYPE) ||
277         (eObjType == GDILoObjType_LO_METADC16_TYPE))
278     {
279         return GdiGetClientObjLink(hobj);
280     }
281 
282     /* This should never happen! */
283     ASSERT(FALSE);
284     return NULL;
285 }
286 
287 VOID
288 GDI_ReleaseObj(HGDIOBJ hobj)
289 {
290     /* We don't do any reference-counting */
291 }
292 
293 WINEDC*
294 alloc_dc_ptr(WORD magic)
295 {
296     WINEDC* pWineDc;
297 
298     /* Allocate the Wine DC */
299     pWineDc = HeapAlloc(GetProcessHeap(), 0, sizeof(*pWineDc));
300     if (pWineDc == NULL)
301     {
302         return NULL;
303     }
304 
305     ZeroMemory(pWineDc, sizeof(*pWineDc));
306     pWineDc->refcount = 1;
307     pWineDc->hFont = GetStockObject(SYSTEM_FONT);
308     pWineDc->hBrush = GetStockObject(WHITE_BRUSH);
309     pWineDc->hPen = GetStockObject(BLACK_PEN);
310     pWineDc->hPalette = GetStockObject(DEFAULT_PALETTE);
311 
312     if (magic == OBJ_ENHMETADC)
313     {
314         /* We create a metafile DC, but we ignore the reference DC, this is
315            handled by the wine code */
316         pWineDc->hdc = NtGdiCreateMetafileDC(NULL);
317         if (pWineDc->hdc == NULL)
318         {
319             HeapFree(GetProcessHeap(), 0, pWineDc);
320             return NULL;
321         }
322 
323         /* Set the Wine DC as LDC */
324         GdiSetLDC(pWineDc->hdc, pWineDc);
325     }
326     else if (magic == OBJ_METADC)
327     {
328         pWineDc->hdc = GdiCreateClientObj(pWineDc, GDILoObjType_LO_METADC16_TYPE);
329         if (pWineDc->hdc == NULL)
330         {
331             HeapFree(GetProcessHeap(), 0, pWineDc);
332             return NULL;
333         }
334     }
335     else
336     {
337         // nothing else supported!
338         ASSERT(FALSE);
339     }
340 
341     pWineDc->physDev = &pWineDc->NullPhysDev;
342     pWineDc->NullPhysDev.funcs = &DummyPhysDevFuncs;
343     pWineDc->NullPhysDev.next = NULL;
344 
345     pWineDc->NullPhysDev.hdc = pWineDc->hdc;
346     return pWineDc;
347 }
348 
349 VOID
350 free_dc_ptr(WINEDC* pWineDc)
351 {
352     /* Invoke the DeleteDC callback to clean up the DC */
353     pWineDc->physDev->funcs->pDeleteDC(pWineDc->physDev);
354 
355     /* FIXME */
356     if (GDI_HANDLE_GET_TYPE(pWineDc->hdc) == GDILoObjType_LO_ALTDC_TYPE)
357     {
358         /* Get rid of the LDC */
359         ASSERT((WINEDC*)GdiGetLDC(pWineDc->hdc) == pWineDc);
360         GdiSetLDC(pWineDc->hdc, NULL);
361 
362         /* Free the DC */
363         NtGdiDeleteObjectApp(pWineDc->hdc);
364     }
365     else if (GDI_HANDLE_GET_TYPE(pWineDc->hdc) == GDILoObjType_LO_METADC16_TYPE)
366     {
367         GdiDeleteClientObj(pWineDc->hdc);
368     }
369 
370     /* Free the Wine DC */
371     HeapFree(GetProcessHeap(), 0, pWineDc);
372 }
373 
374 WINEDC*
375 get_dc_ptr(HDC hdc)
376 {
377     /* Check for EMF DC */
378     if (GDI_HANDLE_GET_TYPE(hdc) == GDILoObjType_LO_ALTDC_TYPE)
379     {
380         /* The Wine DC is stored as the LDC */
381         return (WINEDC*)GdiGetLDC(hdc);
382     }
383 
384     /* Check for METADC16 */
385     if (GDI_HANDLE_GET_TYPE(hdc) == GDILoObjType_LO_METADC16_TYPE)
386     {
387         return GdiGetClientObjLink(hdc);
388     }
389 
390     return NULL;
391 }
392 
393 VOID
394 release_dc_ptr(WINEDC* dc)
395 {
396     /* We don't do any reference-counting */
397 }
398 
399 void
400 push_dc_driver_ros(
401     PHYSDEV *dev,
402     PHYSDEV physdev,
403     const struct gdi_dc_funcs *funcs)
404 {
405     while ((*dev)->funcs->priority > funcs->priority) dev = &(*dev)->next;
406     physdev->funcs = funcs;
407     physdev->next = *dev;
408     physdev->hdc = CONTAINING_RECORD(dev, WINEDC, physDev)->hdc;
409     *dev = physdev;
410 }
411 
412 VOID
413 GDI_hdc_using_object(
414     HGDIOBJ hobj,
415     HDC hdc)
416 {
417     /* Record that we have an object in use by a METADC. We simply link the
418        object to the HDC that we use. Wine API does not give us a way to
419        respond to failure, so we silently ignore it */
420     if (!GdiCreateClientObjLink(hobj, hdc))
421     {
422         /* Ignore failure, and return */
423         DPRINT1("Failed to create link for selected METADC object.\n");
424         return;
425     }
426 }
427 
428 VOID
429 GDI_hdc_not_using_object(
430     HGDIOBJ hobj,
431     HDC hdc)
432 {
433     HDC hdcLink;
434 
435     /* Remove the HDC link for the object */
436     hdcLink = GdiRemoveClientObjLink(hobj);
437     ASSERT(hdcLink == hdc);
438 }
439 
440 /***********************************************************************
441  *           bitmap_info_size
442  *
443  * Return the size of the bitmap info structure including color table.
444  */
445 int
446 bitmap_info_size(
447     const BITMAPINFO * info,
448     WORD coloruse)
449 {
450     unsigned int colors, size, masks = 0;
451 
452     if (info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
453     {
454         const BITMAPCOREHEADER *core = (const BITMAPCOREHEADER *)info;
455         colors = (core->bcBitCount <= 8) ? 1 << core->bcBitCount : 0;
456         return sizeof(BITMAPCOREHEADER) + colors *
457              ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBTRIPLE) : sizeof(WORD));
458     }
459     else  /* assume BITMAPINFOHEADER */
460     {
461         if (info->bmiHeader.biClrUsed) colors = min( info->bmiHeader.biClrUsed, 256 );
462         else colors = info->bmiHeader.biBitCount > 8 ? 0 : 1 << info->bmiHeader.biBitCount;
463         if (info->bmiHeader.biCompression == BI_BITFIELDS) masks = 3;
464         size = max( info->bmiHeader.biSize, sizeof(BITMAPINFOHEADER) + masks * sizeof(DWORD) );
465         return size + colors * ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBQUAD) : sizeof(WORD));
466     }
467 }
468 
469 BOOL
470 get_brush_bitmap_info(
471     HBRUSH hbr,
472     PBITMAPINFO pbmi,
473     PVOID *ppvBits,
474     PUINT puUsage)
475 {
476     HBITMAP hbmp;
477     HDC hdc;
478 
479     /* Call win32k to get the bitmap handle and color usage */
480     hbmp = NtGdiGetObjectBitmapHandle(hbr, puUsage);
481     if (hbmp == NULL)
482         return FALSE;
483 
484     hdc = GetDC(NULL);
485     if (hdc == NULL)
486         return FALSE;
487 
488     /* Initialize the BITMAPINFO */
489     ZeroMemory(pbmi, sizeof(*pbmi));
490     pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
491 
492     /* Retrieve information about the bitmap */
493     if (!GetDIBits(hdc, hbmp, 0, 0, NULL, pbmi, *puUsage))
494         return FALSE;
495 
496     /* Now allocate a buffer for the bits */
497     *ppvBits = HeapAlloc(GetProcessHeap(), 0, pbmi->bmiHeader.biSizeImage);
498     if (*ppvBits == NULL)
499         return FALSE;
500 
501     /* Retrieve the bitmap bits */
502     if (!GetDIBits(hdc, hbmp, 0, pbmi->bmiHeader.biHeight, *ppvBits, pbmi, *puUsage))
503     {
504         HeapFree(GetProcessHeap(), 0, *ppvBits);
505         *ppvBits = NULL;
506         return FALSE;
507     }
508 
509     /* GetDIBits doesn't set biClrUsed, but wine code needs it, so we set it */
510     if (pbmi->bmiHeader.biBitCount <= 8)
511     {
512         pbmi->bmiHeader.biClrUsed =  1 << pbmi->bmiHeader.biBitCount;
513     }
514 
515     return TRUE;
516 }
517 
518 BOOL
519 WINAPI
520 SetVirtualResolution(
521     HDC hdc,
522     DWORD cxVirtualDevicePixel,
523     DWORD cyVirtualDevicePixel,
524     DWORD cxVirtualDeviceMm,
525     DWORD cyVirtualDeviceMm)
526 {
527     return NtGdiSetVirtualResolution(hdc,
528                                      cxVirtualDevicePixel,
529                                      cyVirtualDevicePixel,
530                                      cxVirtualDeviceMm,
531                                      cyVirtualDeviceMm);
532 }
533 
534 BOOL
535 WINAPI
536 DeleteColorSpace(
537     HCOLORSPACE hcs)
538 {
539     return NtGdiDeleteColorSpace(hcs);
540 }
541 #if 0
542 BOOL
543 WINAPI
544 SetWorldTransformForMetafile(
545     _In_ HDC hdc,
546     _Out_ CONST XFORM *pxform)
547 {
548     if (GDI_HANDLE_GET_TYPE(hdc) == GDILoObjType_LO_METADC16_TYPE)
549     {
550 #if 0
551         //HANDLE_METADC(BOOL, ModifyWorldTransform, FALSE, hdc, pxform, MWT_SET);
552         /* Get the physdev */
553         physdev = GetPhysDev(hdc);
554         if (physdev == NULL)
555         {
556             DPRINT1("Failed to get physdev for meta DC %p\n", hdc);
557             return FALSE;
558         }
559 
560         physdev->funcs->pSetWorldTransform(physdev, pxform);
561 #endif
562         // HACK!!!
563         return TRUE;
564     }
565 
566     return SetWorldTransform(hdc, pxform);
567 }
568 #endif
569 void
570 __cdecl
571 _assert (
572     const char *exp,
573     const char *file,
574     unsigned line)
575 {
576     DbgRaiseAssertionFailure();
577 }
578 
579 /******************************************************************************/
580 
581 static
582 VOID
583 InitBitBltCoords(
584     struct bitblt_coords *coords,
585     HDC hdc,
586     int x,
587     int y,
588     int cx,
589     int cy)
590 {
591     coords->log_x      = x;
592     coords->log_y      = y;
593     coords->log_width  = cx;
594     coords->log_height = cy;
595     coords->layout     = GetLayout(hdc);
596 }
597 
598 static
599 PHYSDEV
600 GetPhysDev(
601     HDC hdc)
602 {
603     WINEDC *pWineDc;
604 
605     pWineDc = get_dc_ptr(hdc);
606     if (pWineDc == NULL)
607     {
608         return NULL;
609     }
610 
611     return pWineDc->physDev;
612 }
613 
614 static
615 BOOL
616 DRIVER_PatBlt(
617     _In_ PHYSDEV physdev,
618     _In_ HDC hdc,
619     _In_ INT xLeft,
620     _In_ INT yTop,
621     _In_ INT cx,
622     _In_ INT cy,
623     _In_ DWORD dwRop)
624 {
625     struct bitblt_coords coords;
626 
627     InitBitBltCoords(&coords, hdc, xLeft, yTop, cx, cy);
628 
629     return physdev->funcs->pPatBlt(physdev, &coords, dwRop);
630 }
631 
632 static
633 BOOL
634 DRIVER_StretchBlt(
635     _In_ PHYSDEV physdev,
636     _In_ HDC hdcDst,
637     _In_ INT xDst,
638     _In_ INT yDst,
639     _In_ INT cxDst,
640     _In_ INT cyDst,
641     _In_opt_ HDC hdcSrc,
642     _In_ INT xSrc,
643     _In_ INT ySrc,
644     _In_ INT cxSrc,
645     _In_ INT cySrc,
646     _In_ DWORD dwRop)
647 {
648     struct bitblt_coords coordsDst, coordsSrc;
649     struct gdi_physdev physdevSrc = {0};
650 
651     /* Source cannot be a metafile */
652     if (GDI_HANDLE_GET_TYPE(hdcSrc) != GDILoObjType_LO_DC_TYPE)
653         return FALSE;
654 
655     /* Source physdev uses only hdc and func */
656     physdevSrc.hdc = hdcSrc;
657 
658     InitBitBltCoords(&coordsDst, hdcDst, xDst, yDst, cxDst, cyDst);
659     InitBitBltCoords(&coordsSrc, hdcSrc, xSrc, ySrc, cxSrc, cySrc);
660 
661     return physdev->funcs->pStretchBlt(physdev, &coordsDst, &physdevSrc, &coordsSrc, dwRop);
662 }
663 
664 static
665 BOOL
666 DRIVER_RestoreDC(PHYSDEV physdev, INT level)
667 {
668     WINEDC *pWineDc = get_dc_ptr(physdev->hdc);
669 
670     if (GDI_HANDLE_GET_TYPE(physdev->hdc) == GDILoObjType_LO_ALTDC_TYPE)
671     {
672         /* The Restore DC function needs the save level to be set correctly.
673            Note that wine's level is 0 based, while our's is (like win) 1 based. */
674         pWineDc->saveLevel = GetDCDWord(physdev->hdc, GdiGetEMFRestorDc, 0)  - 1;
675 
676         /* Fail if the level is not valid */
677         if ((abs(level) > pWineDc->saveLevel) || (level == 0))
678             return FALSE;
679     }
680 
681     return physdev->funcs->pRestoreDC(physdev,level);
682 }
683 
684 static
685 HFONT
686 DRIVER_SelectFont(PHYSDEV physdev, HFONT hFont, UINT *aa_flags)
687 {
688     WINEDC *pWineDc = get_dc_ptr(physdev->hdc);
689     HFONT hOldFont;
690 
691     if (!physdev->funcs->pSelectFont(physdev, hFont, aa_flags))
692         return 0;
693 
694     hOldFont = pWineDc->hFont;
695     pWineDc->hFont = hFont;
696     return hOldFont;
697 }
698 
699 static
700 HPEN
701 DRIVER_SelectPen(PHYSDEV physdev, HPEN hpen, const struct brush_pattern *pattern)
702 {
703     WINEDC *pWineDc = get_dc_ptr(physdev->hdc);
704     HPEN hOldPen;
705 
706     if (!physdev->funcs->pSelectPen(physdev, hpen, pattern))
707         return 0;
708 
709     hOldPen = pWineDc->hPen;
710     pWineDc->hPen = hpen;
711     return hOldPen;
712 }
713 
714 static
715 HBRUSH
716 DRIVER_SelectBrush(PHYSDEV physdev, HBRUSH hbrush, const struct brush_pattern *pattern)
717 {
718     WINEDC *pWineDc = get_dc_ptr(physdev->hdc);
719     HBRUSH hOldBrush;
720 
721     if (!physdev->funcs->pSelectBrush(physdev, hbrush, pattern))
722         return 0;
723 
724     hOldBrush = pWineDc->hBrush;
725     pWineDc->hBrush = hbrush;
726     return hOldBrush;
727 }
728 
729 static
730 HRGN
731 DRIVER_PathToRegion(PHYSDEV physdev)
732 {
733     DPRINT1("DRIVER_PathToRegion\n");
734     return (HRGN)(ULONG_PTR)physdev->funcs->pAbortPath( physdev );
735 }
736 
737 
738 static
739 DWORD_PTR
740 DRIVER_Dispatch(
741     _In_ PHYSDEV physdev,
742     _In_ DCFUNC eFunction,
743     _In_ va_list argptr)
744 {
745     UINT aa_flags = 0;
746 
747 /* Note that this is a hack that relies on some assumptions regarding the
748    Windows ABI. It relies on the fact that all vararg functions put their
749    parameters on the stack in the correct order. Additionally it relies
750    on the fact that none of the functions we handle here, pass any 64
751    bit arguments on a 32 bit architecture. */
752 #define _va_arg_n(p,t,i) (*(t*)((intptr_t*)(p) + i))
753 
754     switch (eFunction)
755     {
756         case DCFUNC_AbortPath:
757             return physdev->funcs->pAbortPath(physdev);
758         case DCFUNC_Arc:
759             return physdev->funcs->pArc(physdev,
760                                         _va_arg_n(argptr, INT, 0), // left
761                                         _va_arg_n(argptr, INT, 1), // top
762                                         _va_arg_n(argptr, INT, 2), // right
763                                         _va_arg_n(argptr, INT, 3), // bottom
764                                         _va_arg_n(argptr, INT, 4), // xstart
765                                         _va_arg_n(argptr, INT, 5), // ystart
766                                         _va_arg_n(argptr, INT, 6), // xend
767                                         _va_arg_n(argptr, INT, 7)); // yend
768         case DCFUNC_BeginPath:
769             return physdev->funcs->pBeginPath(physdev);
770         case DCFUNC_Chord:
771             return physdev->funcs->pChord(physdev,
772                                           _va_arg_n(argptr, INT, 0),
773                                           _va_arg_n(argptr, INT, 1),
774                                           _va_arg_n(argptr, INT, 2),
775                                           _va_arg_n(argptr, INT, 3),
776                                           _va_arg_n(argptr, INT, 4),
777                                           _va_arg_n(argptr, INT, 5),
778                                           _va_arg_n(argptr, INT, 6),
779                                           _va_arg_n(argptr, INT, 7));
780         case DCFUNC_CloseFigure:
781             return physdev->funcs->pCloseFigure(physdev);
782         case DCFUNC_Ellipse:
783             return physdev->funcs->pEllipse(physdev,
784                                             _va_arg_n(argptr, INT, 0),
785                                             _va_arg_n(argptr, INT, 1),
786                                             _va_arg_n(argptr, INT, 2),
787                                             _va_arg_n(argptr, INT, 3));
788         case DCFUNC_EndPath:
789             return physdev->funcs->pEndPath(physdev);
790         case DCFUNC_ExcludeClipRect:
791             return physdev->funcs->pExcludeClipRect(physdev,
792                                               _va_arg_n(argptr, INT, 0),
793                                               _va_arg_n(argptr, INT, 1),
794                                               _va_arg_n(argptr, INT, 2),
795                                               _va_arg_n(argptr, INT, 3));
796         case DCFUNC_ExtEscape:
797             ASSERT(physdev->funcs->pExtEscape != NULL);
798             return physdev->funcs->pExtEscape(physdev,
799                                               _va_arg_n(argptr, INT, 0),
800                                               _va_arg_n(argptr, INT, 1),
801                                               _va_arg_n(argptr, LPCVOID, 2),
802                                               _va_arg_n(argptr, INT, 3),
803                                               _va_arg_n(argptr, LPVOID, 4));
804         case DCFUNC_ExtFloodFill:
805             return physdev->funcs->pExtFloodFill(physdev,
806                                                  _va_arg_n(argptr, INT, 0),
807                                                  _va_arg_n(argptr, INT, 1),
808                                                  _va_arg_n(argptr, COLORREF, 2),
809                                                  _va_arg_n(argptr, UINT, 3));
810         case DCFUNC_ExtSelectClipRgn:
811             return physdev->funcs->pExtSelectClipRgn(physdev,
812                                                      _va_arg_n(argptr, HRGN, 0), // hrgn
813                                                      _va_arg_n(argptr, INT, 1)); // iMode
814         case DCFUNC_ExtTextOut:
815             return physdev->funcs->pExtTextOut(physdev,
816                                                _va_arg_n(argptr, INT, 0),// x
817                                                _va_arg_n(argptr, INT, 1),// y
818                                                _va_arg_n(argptr, UINT, 2),// fuOptions
819                                                _va_arg_n(argptr, const RECT *, 3),// lprc,
820                                                _va_arg_n(argptr, LPCWSTR, 4),// lpString,
821                                                _va_arg_n(argptr, UINT, 5),// cchString,
822                                                _va_arg_n(argptr, const INT *, 6));// lpDx);
823         case DCFUNC_FillPath:
824             return physdev->funcs->pFillPath(physdev);
825         case DCFUNC_FillRgn:
826             return physdev->funcs->pFillRgn(physdev,
827                                             _va_arg_n(argptr, HRGN, 0),
828                                             _va_arg_n(argptr, HBRUSH, 1));
829         case DCFUNC_FlattenPath:
830             return physdev->funcs->pFlattenPath(physdev);
831         case DCFUNC_FrameRgn:
832             return physdev->funcs->pFrameRgn(physdev,
833                                              _va_arg_n(argptr, HRGN, 0),
834                                              _va_arg_n(argptr, HBRUSH, 1),
835                                              _va_arg_n(argptr, INT, 2),
836                                              _va_arg_n(argptr, INT, 3));
837         case DCFUNC_GetDeviceCaps:
838             return physdev->funcs->pGetDeviceCaps(physdev, va_arg(argptr, INT));
839         case DCFUNC_GdiComment:
840             return physdev->funcs->pGdiComment(physdev,
841                                                _va_arg_n(argptr, UINT, 0),
842                                                _va_arg_n(argptr, const BYTE*, 1));
843         case DCFUNC_IntersectClipRect:
844             return physdev->funcs->pIntersectClipRect(physdev,
845                                                       _va_arg_n(argptr, INT, 0),
846                                                       _va_arg_n(argptr, INT, 1),
847                                                       _va_arg_n(argptr, INT, 2),
848                                                       _va_arg_n(argptr, INT, 3));
849         case DCFUNC_InvertRgn:
850             return physdev->funcs->pInvertRgn(physdev,
851                                               va_arg(argptr, HRGN));
852         case DCFUNC_LineTo:
853             return physdev->funcs->pLineTo(physdev,
854                                            _va_arg_n(argptr, INT, 0),
855                                            _va_arg_n(argptr, INT, 1));
856         case DCFUNC_ModifyWorldTransform:
857             return physdev->funcs->pModifyWorldTransform(physdev,
858                                                          _va_arg_n(argptr, const XFORM*, 0),
859                                                          _va_arg_n(argptr, DWORD, 1));
860         case DCFUNC_MoveTo:
861             return physdev->funcs->pMoveTo(physdev,
862                                            _va_arg_n(argptr, INT, 0),
863                                            _va_arg_n(argptr, INT, 1));
864         case DCFUNC_OffsetClipRgn:
865             return physdev->funcs->pOffsetClipRgn(physdev,
866                                                   _va_arg_n(argptr, INT, 0), // hrgn
867                                                   _va_arg_n(argptr, INT, 1)); // iMode
868         case DCFUNC_OffsetViewportOrgEx:
869             return physdev->funcs->pOffsetViewportOrgEx(physdev,
870                                                         _va_arg_n(argptr, INT, 0), // X
871                                                         _va_arg_n(argptr, INT, 1), // Y
872                                                         _va_arg_n(argptr, LPPOINT, 2)); // lpPoint
873         case DCFUNC_OffsetWindowOrgEx:
874             return physdev->funcs->pOffsetWindowOrgEx(physdev,
875                                                         _va_arg_n(argptr, INT, 0), // X
876                                                         _va_arg_n(argptr, INT, 1), // Y
877                                                         _va_arg_n(argptr, LPPOINT, 2)); // lpPoint
878         case DCFUNC_PatBlt:
879             return DRIVER_PatBlt(physdev,
880                                  physdev->hdc,
881                                  _va_arg_n(argptr, INT, 0),
882                                  _va_arg_n(argptr, INT, 1),
883                                  _va_arg_n(argptr, INT, 2),
884                                  _va_arg_n(argptr, INT, 3),
885                                  _va_arg_n(argptr, DWORD, 4));
886         case DCFUNC_Pie:
887             return physdev->funcs->pPie(physdev,
888                                         _va_arg_n(argptr, INT, 0),
889                                         _va_arg_n(argptr, INT, 1),
890                                         _va_arg_n(argptr, INT, 2),
891                                         _va_arg_n(argptr, INT, 3),
892                                         _va_arg_n(argptr, INT, 4),
893                                         _va_arg_n(argptr, INT, 5),
894                                         _va_arg_n(argptr, INT, 6),
895                                         _va_arg_n(argptr, INT, 7));
896         case DCFUNC_PolyBezier:
897             return physdev->funcs->pPolyBezier(physdev,
898                                                _va_arg_n(argptr, const POINT*, 0),
899                                                _va_arg_n(argptr, DWORD, 1));
900         case DCFUNC_PolyBezierTo:
901             return physdev->funcs->pPolyBezierTo(physdev,
902                                                  _va_arg_n(argptr, const POINT*, 0),
903                                                  _va_arg_n(argptr, DWORD, 1));
904         case DCFUNC_PolyDraw:
905            return physdev->funcs->pPolyDraw(physdev,
906                                              _va_arg_n(argptr, const POINT*, 0),
907                                              _va_arg_n(argptr, const BYTE*, 1),
908                                              _va_arg_n(argptr, DWORD, 2));
909         case DCFUNC_Polygon:
910             return physdev->funcs->pPolygon(physdev,
911                                             _va_arg_n(argptr, const POINT*, 0),
912                                             _va_arg_n(argptr, INT, 1));
913         case DCFUNC_Polyline:
914             return physdev->funcs->pPolyline(physdev,
915                                              _va_arg_n(argptr, const POINT*, 0),
916                                              _va_arg_n(argptr, INT, 1));
917         case DCFUNC_PolylineTo:
918             return physdev->funcs->pPolylineTo(physdev,
919                                                _va_arg_n(argptr, const POINT*, 0),
920                                                _va_arg_n(argptr, INT, 1));
921         case DCFUNC_PolyPolygon:
922             return physdev->funcs->pPolyPolygon(physdev,
923                                                 _va_arg_n(argptr, const POINT*, 0),
924                                                 _va_arg_n(argptr, const INT*, 1),
925                                                 _va_arg_n(argptr, DWORD, 2));
926         case DCFUNC_PolyPolyline:
927             return physdev->funcs->pPolyPolyline(physdev,
928                                                  _va_arg_n(argptr, const POINT*, 0),
929                                                  _va_arg_n(argptr, const DWORD*, 1),
930                                                  _va_arg_n(argptr, DWORD, 2));
931         case DCFUNC_RealizePalette:
932             if (GDI_HANDLE_GET_TYPE(physdev->hdc) != GDILoObjType_LO_METADC16_TYPE)
933             {
934                 UNIMPLEMENTED;
935                 return GDI_ERROR;
936             }
937             return physdev->funcs->pRealizePalette(physdev, NULL, FALSE);
938         case DCFUNC_Rectangle:
939             return physdev->funcs->pRectangle(physdev,
940                                               _va_arg_n(argptr, INT, 0),
941                                               _va_arg_n(argptr, INT, 1),
942                                               _va_arg_n(argptr, INT, 2),
943                                               _va_arg_n(argptr, INT, 3));
944         case DCFUNC_RestoreDC:
945             return DRIVER_RestoreDC(physdev, va_arg(argptr, INT));
946         case DCFUNC_RoundRect:
947             return physdev->funcs->pRoundRect(physdev,
948                                               _va_arg_n(argptr, INT, 0),
949                                               _va_arg_n(argptr, INT, 1),
950                                               _va_arg_n(argptr, INT, 2),
951                                               _va_arg_n(argptr, INT, 3),
952                                               _va_arg_n(argptr, INT, 4),
953                                               _va_arg_n(argptr, INT, 5));
954 
955         case DCFUNC_SaveDC:
956             return physdev->funcs->pSaveDC(physdev);
957         case DCFUNC_ScaleViewportExtEx:
958             return physdev->funcs->pScaleViewportExtEx(physdev,
959                                                      _va_arg_n(argptr, INT, 0), // xNum
960                                                      _va_arg_n(argptr, INT, 1), // xDenom
961                                                      _va_arg_n(argptr, INT, 2), // yNum
962                                                      _va_arg_n(argptr, INT, 3), // yDenom
963                                                      _va_arg_n(argptr, LPSIZE, 4)); // lpSize
964         case DCFUNC_ScaleWindowExtEx:
965             return physdev->funcs->pScaleWindowExtEx(physdev,
966                                                      _va_arg_n(argptr, INT, 0), // xNum
967                                                      _va_arg_n(argptr, INT, 1), // xDenom
968                                                      _va_arg_n(argptr, INT, 2), // yNum
969                                                      _va_arg_n(argptr, INT, 3), // yDenom
970                                                      _va_arg_n(argptr, LPSIZE, 4)); // lpSize
971         case DCFUNC_SelectBrush:
972             return (DWORD_PTR)DRIVER_SelectBrush(physdev, va_arg(argptr, HBRUSH), NULL);
973         case DCFUNC_SelectClipPath:
974             return physdev->funcs->pSelectClipPath(physdev, va_arg(argptr, INT));
975         case DCFUNC_SelectFont:
976             return (DWORD_PTR)DRIVER_SelectFont(physdev, va_arg(argptr, HFONT), &aa_flags);
977         case DCFUNC_SelectPalette:
978             return (DWORD_PTR)physdev->funcs->pSelectPalette(physdev,
979                                                   _va_arg_n(argptr, HPALETTE, 0),
980                                                   _va_arg_n(argptr, BOOL, 1));
981         case DCFUNC_SelectPen:
982             return (DWORD_PTR)DRIVER_SelectPen(physdev, va_arg(argptr, HPEN), NULL);
983         case DCFUNC_SetDCBrushColor:
984             return physdev->funcs->pSetDCBrushColor(physdev, va_arg(argptr, COLORREF));
985         case DCFUNC_SetDCPenColor:
986             return physdev->funcs->pSetDCPenColor(physdev, va_arg(argptr, COLORREF));
987         case DCFUNC_SetDIBitsToDevice:
988             return physdev->funcs->pSetDIBitsToDevice(physdev,
989                                                       _va_arg_n(argptr, INT, 0),
990                                                       _va_arg_n(argptr, INT, 1),
991                                                       _va_arg_n(argptr, DWORD, 2),
992                                                       _va_arg_n(argptr, DWORD, 3),
993                                                       _va_arg_n(argptr, INT, 4),
994                                                       _va_arg_n(argptr, INT, 5),
995                                                       _va_arg_n(argptr, UINT, 6),
996                                                       _va_arg_n(argptr, UINT, 7),
997                                                       _va_arg_n(argptr, LPCVOID, 8),
998                                                       _va_arg_n(argptr, BITMAPINFO*, 9),
999                                                       _va_arg_n(argptr, UINT, 10));
1000         case DCFUNC_SetBkColor:
1001             return physdev->funcs->pSetBkColor(physdev, va_arg(argptr, COLORREF));
1002         case DCFUNC_SetBkMode:
1003             return physdev->funcs->pSetBkMode(physdev, va_arg(argptr, INT));
1004         case DCFUNC_SetLayout:
1005             // FIXME: MF16 is UNIMPLEMENTED
1006             return physdev->funcs->pSetLayout(physdev,
1007                                               _va_arg_n(argptr, DWORD, 0));
1008         //case DCFUNC_SetMapMode:
1009         //    return physdev->funcs->pSetMapMode(physdev, va_arg(argptr, INT));
1010         case DCFUNC_SetPixel:
1011             return physdev->funcs->pSetPixel(physdev,
1012                                              _va_arg_n(argptr, INT, 0),
1013                                              _va_arg_n(argptr, INT, 1),
1014                                              _va_arg_n(argptr, COLORREF, 2));
1015         case DCFUNC_SetPolyFillMode:
1016             return physdev->funcs->pSetPolyFillMode(physdev, va_arg(argptr, INT));
1017         case DCFUNC_SetROP2:
1018             return physdev->funcs->pSetROP2(physdev, va_arg(argptr, INT));
1019         case DCFUNC_SetStretchBltMode:
1020             return physdev->funcs->pSetStretchBltMode(physdev, va_arg(argptr, INT));
1021         case DCFUNC_SetTextAlign:
1022             return physdev->funcs->pSetTextAlign(physdev, va_arg(argptr, UINT));
1023         case DCFUNC_SetTextCharacterExtra:
1024             return physdev->funcs->pSetTextCharacterExtra(physdev, va_arg(argptr, INT));
1025         case DCFUNC_SetTextColor:
1026             return physdev->funcs->pSetTextColor(physdev, va_arg(argptr, COLORREF));
1027         case DCFUNC_SetTextJustification:
1028             return physdev->funcs->pSetTextJustification(physdev,
1029                                                          _va_arg_n(argptr, INT, 0),
1030                                                          _va_arg_n(argptr, INT, 1));
1031         case DCFUNC_SetViewportExtEx:
1032             return physdev->funcs->pSetViewportExtEx(physdev,
1033                                                      _va_arg_n(argptr, INT, 0), // nXExtent
1034                                                      _va_arg_n(argptr, INT, 1), // nYExtent
1035                                                      _va_arg_n(argptr, LPSIZE, 2)); // lpSize
1036         case DCFUNC_SetViewportOrgEx:
1037             return physdev->funcs->pSetViewportOrgEx(physdev,
1038                                                      _va_arg_n(argptr, INT, 0), // X
1039                                                      _va_arg_n(argptr, INT, 1), // Y
1040                                                      _va_arg_n(argptr, LPPOINT, 2)); // lpPoint
1041         case DCFUNC_SetWindowExtEx:
1042             return physdev->funcs->pSetWindowExtEx(physdev,
1043                                                    _va_arg_n(argptr, INT, 0), // nXExtent
1044                                                    _va_arg_n(argptr, INT, 1), // nYExtent
1045                                                    _va_arg_n(argptr, LPSIZE, 2)); // lpSize
1046         case DCFUNC_SetWindowOrgEx:
1047             return physdev->funcs->pSetWindowOrgEx(physdev,
1048                                                    _va_arg_n(argptr, INT, 0), // X
1049                                                    _va_arg_n(argptr, INT, 1), // Y
1050                                                    _va_arg_n(argptr, LPPOINT, 2)); // lpPoint
1051 
1052         case DCFUNC_SetWorldTransform:
1053             return physdev->funcs->pSetWorldTransform(physdev,
1054                                                       va_arg(argptr, const XFORM*));
1055 
1056         case DCFUNC_StretchBlt:
1057             return DRIVER_StretchBlt(physdev,
1058                                      physdev->hdc,
1059                                      _va_arg_n(argptr, INT, 0),
1060                                      _va_arg_n(argptr, INT, 1),
1061                                      _va_arg_n(argptr, INT, 2),
1062                                      _va_arg_n(argptr, INT, 3),
1063                                      _va_arg_n(argptr, HDC, 4),
1064                                      _va_arg_n(argptr, INT, 5),
1065                                      _va_arg_n(argptr, INT, 6),
1066                                      _va_arg_n(argptr, INT, 7),
1067                                      _va_arg_n(argptr, INT, 8),
1068                                      _va_arg_n(argptr, DWORD, 9));
1069         case DCFUNC_StrokeAndFillPath:
1070             return physdev->funcs->pStrokeAndFillPath(physdev);
1071         case DCFUNC_StrokePath:
1072             return physdev->funcs->pStrokePath(physdev);
1073         case DCFUNC_WidenPath:
1074             return physdev->funcs->pWidenPath(physdev);
1075         case DCFUNC_AngleArc:
1076             return physdev->funcs->pAngleArc(physdev,
1077                                              _va_arg_n(argptr, INT, 0),
1078                                              _va_arg_n(argptr, INT, 1),
1079                                              _va_arg_n(argptr, DWORD, 2),
1080                                              _va_arg_n(argptr, FLOAT, 3),
1081                                              _va_arg_n(argptr, FLOAT, 4 ));
1082         case DCFUNC_ArcTo:
1083             return physdev->funcs->pArcTo(physdev,
1084                                           _va_arg_n(argptr, INT, 0),
1085                                           _va_arg_n(argptr, INT, 1),
1086                                           _va_arg_n(argptr, INT, 2),
1087                                           _va_arg_n(argptr, INT, 3),
1088                                           _va_arg_n(argptr, INT, 4),
1089                                           _va_arg_n(argptr, INT, 5),
1090                                           _va_arg_n(argptr, INT, 6),
1091                                           _va_arg_n(argptr, INT, 7));
1092         case DCFUNC_GradientFill:
1093             return physdev->funcs->pGradientFill(physdev,
1094                                                  _va_arg_n(argptr, TRIVERTEX *, 0),
1095                                                  _va_arg_n(argptr, ULONG, 1),
1096                                                  _va_arg_n(argptr, void *, 2),
1097                                                  _va_arg_n(argptr, ULONG , 3),
1098                                                  _va_arg_n(argptr, ULONG , 4));
1099         case DCFUNC_PathToRegion:
1100             return (DWORD_PTR)DRIVER_PathToRegion(physdev);
1101 
1102         /* These are not implemented in wine */
1103         case DCFUNC_AlphaBlend:
1104         case DCFUNC_MaskBlt:
1105         case DCFUNC_PlgBlt:
1106         case DCFUNC_TransparentBlt:
1107             UNIMPLEMENTED;
1108             return 0;
1109 
1110         default:
1111             __debugbreak();
1112             return 0;
1113     }
1114 }
1115 
1116 BOOL
1117 METADC_Dispatch(
1118     _In_ DCFUNC eFunction,
1119     _Out_ PDWORD_PTR pdwResult,
1120     _In_ DWORD_PTR dwError,
1121     _In_ HDC hdc,
1122     ...)
1123 {
1124     PHYSDEV physdev;
1125     va_list argptr;
1126 
1127     /* Handle only METADC16 and ALTDC */
1128     if ((GDI_HANDLE_GET_TYPE(hdc) != GDILoObjType_LO_ALTDC_TYPE) &&
1129         (GDI_HANDLE_GET_TYPE(hdc) != GDILoObjType_LO_METADC16_TYPE))
1130     {
1131         /* Let the caller handle it */
1132         return FALSE;
1133     }
1134 
1135     physdev = GetPhysDev(hdc);
1136     if (physdev == NULL)
1137     {
1138         SetLastError(ERROR_INVALID_HANDLE);
1139         *pdwResult = dwError;
1140         return TRUE;
1141     }
1142 
1143     i = eFunction;
1144     va_start(argptr, hdc);
1145     *pdwResult = DRIVER_Dispatch(physdev, eFunction, argptr);
1146     va_end(argptr);
1147     i = 0;
1148 
1149     /* Return TRUE to indicate that we want to return from the parent  */
1150     return ((GDI_HANDLE_GET_TYPE(hdc) == GDILoObjType_LO_METADC16_TYPE) ||
1151             (*pdwResult == dwError));
1152 }
1153 
1154 BOOL
1155 WINAPI
1156 METADC_GetAndSetDCDWord(
1157     _Out_ DWORD* pdwResult,
1158     _In_ HDC hdc,
1159     _In_ UINT uFunction,
1160     _In_ DWORD dwIn,
1161     _In_ ULONG ulMFId,
1162     _In_ USHORT usMF16Id,
1163     _In_ DWORD dwError)
1164 {
1165     PHYSDEV physdev;
1166 
1167     /* Ignore these, we let wine code handle this */
1168     UNREFERENCED_PARAMETER(ulMFId);
1169     UNREFERENCED_PARAMETER(usMF16Id);
1170 
1171     physdev = GetPhysDev(hdc);
1172     if (physdev == NULL)
1173     {
1174         SetLastError(ERROR_INVALID_HANDLE);
1175         *pdwResult = dwError;
1176         return TRUE;
1177     }
1178 
1179     /* Check the function */
1180     switch (uFunction)
1181     {
1182         case GdiGetSetMapMode:
1183             *pdwResult = physdev->funcs->pSetMapMode(physdev, dwIn);
1184             break;
1185 
1186         case GdiGetSetArcDirection:
1187             if (GDI_HANDLE_GET_TYPE(physdev->hdc) == GDILoObjType_LO_METADC16_TYPE)
1188                 *pdwResult = 0;
1189             else
1190                 *pdwResult = physdev->funcs->pSetArcDirection(physdev, dwIn);
1191             break;
1192 
1193         case GdiGetSetRelAbs:
1194             if (GDI_HANDLE_GET_TYPE(physdev->hdc) == GDILoObjType_LO_METADC16_TYPE)
1195                 *pdwResult = physdev->funcs->pSetRelAbs(physdev, dwIn);
1196             else
1197             {
1198                 UNIMPLEMENTED;
1199                 *pdwResult = 0;
1200             }
1201             break;
1202 
1203 
1204         default:
1205             __debugbreak();
1206     }
1207 
1208     /* Return TRUE to indicate that we want to return from the parent  */
1209     return ((GDI_HANDLE_GET_TYPE(hdc) == GDILoObjType_LO_METADC16_TYPE) ||
1210             (*pdwResult == dwError));
1211 }
1212 
1213 VOID
1214 WINAPI
1215 METADC_DeleteObject(HGDIOBJ hobj)
1216 {
1217     GDILOOBJTYPE eObjectType;
1218     HDC hdc;
1219     PHYSDEV physdev;
1220 
1221     /* Check for one of the types we actually handle here */
1222     eObjectType = GDI_HANDLE_GET_TYPE(hobj);
1223     if ((eObjectType != GDILoObjType_LO_BRUSH_TYPE) &&
1224         (eObjectType != GDILoObjType_LO_PEN_TYPE) &&
1225         (eObjectType != GDILoObjType_LO_EXTPEN_TYPE) &&
1226         (eObjectType != GDILoObjType_LO_PALETTE_TYPE) &&
1227         (eObjectType != GDILoObjType_LO_FONT_TYPE))
1228     {
1229         return;
1230     }
1231 
1232     /* Check if we have a client object link and remove it if it was found.
1233        The link is the HDC that the object was selected into. */
1234     hdc = GdiRemoveClientObjLink(hobj);
1235     if (hdc == NULL)
1236     {
1237         /* The link was not found, so we are not handling this object here */
1238         return;
1239     }
1240 
1241     /* Get the physdev */
1242     physdev = GetPhysDev(hdc);
1243     if (physdev == NULL)
1244     {
1245         /* This happens, when the METADC is already closed, when we delete
1246            the object. Simply ignore it */
1247         DPRINT1("METADC was already closed, cannot delete object. Ignoring.\n");
1248         return;
1249     }
1250 
1251     physdev->funcs->pDeleteObject(physdev, hobj);
1252 }
1253 
1254 BOOL
1255 WINAPI
1256 METADC_DeleteDC(
1257     _In_ HDC hdc)
1258 {
1259     /* Only ALTDCs are supported */
1260     if (GDI_HANDLE_GET_TYPE(hdc) != GDILoObjType_LO_ALTDC_TYPE)
1261     {
1262         DPRINT1("Trying to delete METADC %p\n", hdc);
1263         return FALSE;
1264     }
1265     // FIXME call the driver?
1266     return NtGdiDeleteObjectApp(hdc);
1267 }
1268 
1269 INT
1270 WINAPI
1271 METADC16_Escape(
1272     _In_ HDC hdc,
1273     _In_ INT nEscape,
1274     _In_ INT cbInput,
1275     _In_ LPCSTR lpvInData,
1276     _Out_ LPVOID lpvOutData)
1277 {
1278     DWORD_PTR dwResult;
1279 
1280     /* Do not record MFCOMMENT */
1281     if (nEscape == MFCOMMENT)
1282     {
1283         // HACK required by wine code...
1284         //return 1;
1285     }
1286 
1287     METADC_Dispatch(DCFUNC_ExtEscape,
1288                     &dwResult,
1289                     SP_ERROR,
1290                     hdc,
1291                     nEscape,
1292                     cbInput,
1293                     lpvInData,
1294                     lpvOutData);
1295 
1296     return (INT)dwResult;
1297 }
1298