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