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