[GDI] Fix metafile crashes and null driver issues.
[reactos.git] / win32ss / gdi / gdi32 / wine / rosglue.c
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)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 }