636d20db514b3508a208becacce25170d338be56
[reactos.git] / subsystems / win32 / win32k / objects / dclife.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * PURPOSE: Functions for creation and destruction of DCs
5 * FILE: subsystem/win32/win32k/objects/dclife.c
6 * PROGRAMER: Timo Kreuzer (timo.kreuzer@rectos.org)
7 */
8
9 #include <w32k.h>
10 #include <bugcodes.h>
11
12 #define NDEBUG
13 #include <debug.h>
14
15 //FIXME: windows uses 0x0012009f
16 #define DIRTY_DEFAULT DIRTY_CHARSET|DIRTY_BACKGROUND|DIRTY_TEXT|DIRTY_LINE|DIRTY_FILL
17
18 PSURFACE psurfDefaultBitmap = NULL;
19 PBRUSH pbrDefaultBrush = NULL;
20
21 // FIXME: these should go to floatobj.h or something
22 #define FLOATOBJ_0 {0x00000000, 0x00000000}
23 #define FLOATOBJ_1 {0x40000000, 0x00000002}
24 #define FLOATOBJ_16 {0x40000000, 0x00000006}
25 #define FLOATOBJ_1_16 {0x40000000, 0xfffffffe}
26
27 static const FLOATOBJ gef0 = FLOATOBJ_0;
28 static const FLOATOBJ gef1 = FLOATOBJ_1;
29 static const FLOATOBJ gef16 = FLOATOBJ_16;
30
31 static const MATRIX gmxWorldToDeviceDefault =
32 {
33 FLOATOBJ_16, FLOATOBJ_0,
34 FLOATOBJ_0, FLOATOBJ_16,
35 FLOATOBJ_0, FLOATOBJ_0,
36 0, 0, 0x4b
37 };
38
39 static const MATRIX gmxDeviceToWorldDefault =
40 {
41 FLOATOBJ_1_16, FLOATOBJ_0,
42 FLOATOBJ_0, FLOATOBJ_1_16,
43 FLOATOBJ_0, FLOATOBJ_0,
44 0, 0, 0x53
45 };
46
47 static const MATRIX gmxWorldToPageDefault =
48 {
49 FLOATOBJ_1, FLOATOBJ_0,
50 FLOATOBJ_0, FLOATOBJ_1,
51 FLOATOBJ_0, FLOATOBJ_0,
52 0, 0, 0x63
53 };
54
55 // HACK!! Fix XFORMOBJ then use 1:16 / 16:1
56 #define gmxWorldToDeviceDefault gmxWorldToPageDefault
57 #define gmxDeviceToWorldDefault gmxWorldToPageDefault
58
59 /** Internal functions ********************************************************/
60
61 NTSTATUS
62 InitDcImpl()
63 {
64 psurfDefaultBitmap = SURFACE_ShareLockSurface(StockObjects[DEFAULT_BITMAP]);
65 if (!psurfDefaultBitmap)
66 return STATUS_UNSUCCESSFUL;
67
68 pbrDefaultBrush = BRUSH_ShareLockBrush(StockObjects[BLACK_BRUSH]);
69 if (!pbrDefaultBrush)
70 return STATUS_UNSUCCESSFUL;
71
72 return STATUS_SUCCESS;
73 }
74
75
76 PDC
77 NTAPI
78 DC_AllocDcWithHandle()
79 {
80 PDC pdc;
81 pdc = (PDC)GDIOBJ_AllocObjWithHandle(GDILoObjType_LO_DC_TYPE);
82
83 pdc->pdcattr = &pdc->dcattr;
84
85 return pdc;
86 }
87
88
89 void
90 DC_InitHack(PDC pdc)
91 {
92 HRGN hVisRgn;
93
94 TextIntRealizeFont(pdc->pdcattr->hlfntNew,NULL);
95 pdc->pdcattr->iCS_CP = ftGdiGetTextCharsetInfo(pdc,NULL,0);
96
97 /* This should never fail */
98 ASSERT(pdc->dclevel.ppal);
99
100 /* Select regions */
101 // FIXME: too complicated, broken error handling
102 pdc->rosdc.hClipRgn = NULL;
103 pdc->rosdc.hGCClipRgn = NULL;
104 hVisRgn = NtGdiCreateRectRgn(0, 0, pdc->dclevel.sizl.cx, pdc->dclevel.sizl.cy);
105 ASSERT(hVisRgn);
106 GdiSelectVisRgn(pdc->BaseObject.hHmgr, hVisRgn);
107 GreDeleteObject(hVisRgn);
108 ASSERT(pdc->prgnVis);
109 pdc->rosdc.bitsPerPixel = pdc->ppdev->gdiinfo.cBitsPixel *
110 pdc->ppdev->gdiinfo.cPlanes;
111 }
112
113 VOID
114 NTAPI
115 DC_vInitDc(
116 PDC pdc,
117 DCTYPE dctype,
118 PPDEVOBJ ppdev)
119 {
120
121 /* Setup some basic fields */
122 pdc->dctype = dctype;
123 pdc->ppdev = ppdev;
124 pdc->dhpdev = ppdev->dhpdev;
125 pdc->hsem = ppdev->hsemDevLock;
126 pdc->flGraphicsCaps = ppdev->devinfo.flGraphicsCaps;
127 pdc->flGraphicsCaps2 = ppdev->devinfo.flGraphicsCaps2;
128 pdc->fs = DC_DIRTY_RAO;
129
130 /* Setup dc attribute */
131 pdc->pdcattr = &pdc->dcattr;
132 pdc->dcattr.pvLDC = NULL;
133 pdc->dcattr.ulDirty_ = DIRTY_DEFAULT;
134 if (ppdev == gppdevPrimary)
135 pdc->dcattr.ulDirty_ |= DC_PRIMARY_DISPLAY;
136
137 /* Setup the DC size */
138 if (dctype == DCTYPE_MEMORY)
139 {
140 /* Memory DCs have a 1 x 1 bitmap by default */
141 pdc->dclevel.sizl.cx = 1;
142 pdc->dclevel.sizl.cy = 1;
143 }
144 else
145 {
146 /* Other DC's are as big as the related PDEV */
147 pdc->dclevel.sizl.cx = ppdev->gdiinfo.ulHorzRes;
148 pdc->dclevel.sizl.cy = ppdev->gdiinfo.ulVertRes;
149 }
150
151 /* Setup Window rect based on DC size */
152 pdc->erclWindow.left = 0;
153 pdc->erclWindow.top = 0;
154 pdc->erclWindow.right = pdc->dclevel.sizl.cx;
155 pdc->erclWindow.bottom = pdc->dclevel.sizl.cy;
156
157 if (dctype == DCTYPE_DIRECT)
158 {
159 /* Direct DCs get the surface from the PDEV */
160 pdc->dclevel.pSurface = PDEVOBJ_pSurface(ppdev);
161
162 pdc->erclBounds.left = 0x7fffffff;
163 pdc->erclBounds.top = 0x7fffffff;
164 pdc->erclBounds.right = 0x80000000;
165 pdc->erclBounds.bottom = 0x80000000;
166 pdc->erclBoundsApp.left = 0xffffffff;
167 pdc->erclBoundsApp.top = 0xfffffffc;
168 pdc->erclBoundsApp.right = 0x00007ffc; // FIXME
169 pdc->erclBoundsApp.bottom = 0x00000333; // FIXME
170 pdc->erclClip = pdc->erclBounds;
171 // pdc->co
172
173 pdc->fs |= DC_SYNCHRONIZEACCESS | DC_ACCUM_APP | DC_PERMANANT | DC_DISPLAY;
174 }
175 else
176 {
177 /* Non-direct DCs don't have a surface by default */
178 pdc->dclevel.pSurface = NULL;
179
180 // FIXME: HACK, because our code expects a surface
181 pdc->dclevel.pSurface = SURFACE_ShareLockSurface(StockObjects[DEFAULT_BITMAP]);
182
183 pdc->erclBounds.left = 0;
184 pdc->erclBounds.top = 0;
185 pdc->erclBounds.right = 0;
186 pdc->erclBounds.bottom = 0;
187 pdc->erclBoundsApp = pdc->erclBounds;
188 pdc->erclClip = pdc->erclWindow;
189 // pdc->co = NULL
190 }
191
192 // pdc->dcattr.VisRectRegion:
193
194 /* Setup coordinate transformation data */
195 pdc->dclevel.mxWorldToDevice = gmxWorldToDeviceDefault;
196 pdc->dclevel.mxDeviceToWorld = gmxDeviceToWorldDefault;
197 pdc->dclevel.mxWorldToPage = gmxWorldToPageDefault;
198 pdc->dclevel.efM11PtoD = gef16;
199 pdc->dclevel.efM22PtoD = gef16;
200 pdc->dclevel.efDxPtoD = gef0;
201 pdc->dclevel.efDyPtoD = gef0;
202 pdc->dclevel.efM11_TWIPS = gef0;
203 pdc->dclevel.efM22_TWIPS = gef0;
204 pdc->dclevel.efPr11 = gef0;
205 pdc->dclevel.efPr22 = gef0;
206 pdc->dcattr.mxWorldToDevice = pdc->dclevel.mxWorldToDevice;
207 pdc->dcattr.mxDeviceToWorld = pdc->dclevel.mxDeviceToWorld;
208 pdc->dcattr.mxWorldToPage = pdc->dclevel.mxWorldToPage;
209 pdc->dcattr.efM11PtoD = pdc->dclevel.efM11PtoD;
210 pdc->dcattr.efM22PtoD = pdc->dclevel.efM22PtoD;
211 pdc->dcattr.efDxPtoD = pdc->dclevel.efDxPtoD;
212 pdc->dcattr.efDyPtoD = pdc->dclevel.efDyPtoD;
213 pdc->dcattr.iMapMode = MM_TEXT;
214 pdc->dcattr.dwLayout = 0;
215 pdc->dcattr.flXform = PAGE_TO_DEVICE_SCALE_IDENTITY |
216 PAGE_TO_DEVICE_IDENTITY |
217 WORLD_TO_PAGE_IDENTITY;
218
219 /* Setup more coordinates */
220 pdc->ptlDCOrig.x = 0;
221 pdc->ptlDCOrig.y = 0;
222 pdc->dcattr.lWindowOrgx = 0;
223 pdc->dcattr.ptlWindowOrg.x = 0;
224 pdc->dcattr.ptlWindowOrg.y = 0;
225 pdc->dcattr.szlWindowExt.cx = 1;
226 pdc->dcattr.szlWindowExt.cy = 1;
227 pdc->dcattr.ptlViewportOrg.x = 0;
228 pdc->dcattr.ptlViewportOrg.y = 0;
229 pdc->dcattr.szlViewportExt.cx = 1;
230 pdc->dcattr.szlViewportExt.cy = 1;
231 pdc->dcattr.szlVirtualDevicePixel.cx = 0;
232 pdc->dcattr.szlVirtualDevicePixel.cy = 0;
233 pdc->dcattr.szlVirtualDeviceMm.cx = 0;
234 pdc->dcattr.szlVirtualDeviceMm.cy = 0;
235 pdc->dcattr.szlVirtualDeviceSize.cx = 0;
236 pdc->dcattr.szlVirtualDeviceSize.cy = 0;
237
238 /* Setup regions */
239 pdc->prgnAPI = NULL;
240 pdc->prgnVis = NULL; // FIXME
241 pdc->prgnRao = NULL;
242
243 /* Setup palette */
244 pdc->dclevel.hpal = StockObjects[DEFAULT_PALETTE];
245 pdc->dclevel.ppal = PALETTE_ShareLockPalette(pdc->dclevel.hpal);
246
247 /* Setup path */
248 pdc->dclevel.hPath = NULL;
249 pdc->dclevel.flPath = 0;
250 // pdc->dclevel.lapath:
251
252 /* Setup colors */
253 pdc->dcattr.crBackgroundClr = RGB(0xff, 0xff, 0xff);
254 pdc->dcattr.ulBackgroundClr = RGB(0xff, 0xff, 0xff);
255 pdc->dcattr.crForegroundClr = RGB(0, 0, 0);
256 pdc->dcattr.ulForegroundClr = RGB(0, 0, 0);
257 pdc->dcattr.crBrushClr = RGB(0xff, 0xff, 0xff);
258 pdc->dcattr.ulBrushClr = RGB(0xff, 0xff, 0xff);
259 pdc->dcattr.crPenClr = RGB(0, 0, 0);
260 pdc->dcattr.ulPenClr = RGB(0, 0, 0);
261
262 /* Select the default fill and line brush */
263 pdc->dcattr.hbrush = StockObjects[WHITE_BRUSH];
264 pdc->dcattr.hpen = StockObjects[BLACK_PEN];
265 pdc->dclevel.pbrFill = BRUSH_ShareLockBrush(pdc->pdcattr->hbrush);
266 pdc->dclevel.pbrLine = PEN_ShareLockPen(pdc->pdcattr->hpen);
267 pdc->dclevel.ptlBrushOrigin.x = 0;
268 pdc->dclevel.ptlBrushOrigin.y = 0;
269 pdc->dcattr.ptlBrushOrigin = pdc->dclevel.ptlBrushOrigin;
270
271 /* Initialize EBRUSHOBJs */
272 EBRUSHOBJ_vInit(&pdc->eboFill, pdc->dclevel.pbrFill, pdc);
273 EBRUSHOBJ_vInit(&pdc->eboLine, pdc->dclevel.pbrLine, pdc);
274 EBRUSHOBJ_vInit(&pdc->eboText, pbrDefaultBrush, pdc);
275 EBRUSHOBJ_vInit(&pdc->eboBackground, pbrDefaultBrush, pdc);
276
277 /* Setup fill data */
278 pdc->dcattr.jROP2 = R2_COPYPEN;
279 pdc->dcattr.jBkMode = 2;
280 pdc->dcattr.lBkMode = 2;
281 pdc->dcattr.jFillMode = ALTERNATE;
282 pdc->dcattr.lFillMode = 1;
283 pdc->dcattr.jStretchBltMode = 1;
284 pdc->dcattr.lStretchBltMode = 1;
285 pdc->ptlFillOrigin.x = 0;
286 pdc->ptlFillOrigin.y = 0;
287
288 /* Setup drawing position */
289 pdc->dcattr.ptlCurrent.x = 0;
290 pdc->dcattr.ptlCurrent.y = 0;
291 pdc->dcattr.ptfxCurrent.x = 0;
292 pdc->dcattr.ptfxCurrent.y = 0;
293
294 /* Setup ICM data */
295 pdc->dclevel.lIcmMode = 0;
296 pdc->dcattr.lIcmMode = 0;
297 pdc->dcattr.hcmXform = NULL;
298 pdc->dcattr.flIcmFlags = 0;
299 pdc->dcattr.IcmBrushColor = CLR_INVALID;
300 pdc->dcattr.IcmPenColor = CLR_INVALID;
301 pdc->dcattr.pvLIcm = NULL;
302 pdc->dcattr.hColorSpace = NULL; // FIXME: 0189001f
303 pdc->dclevel.pColorSpace = NULL; // FIXME
304 pdc->pClrxFormLnk = NULL;
305 // pdc->dclevel.ca =
306
307 /* Setup font data */
308 pdc->hlfntCur = NULL; // FIXME: 2f0a0cf8
309 pdc->pPFFList = NULL;
310 pdc->flSimulationFlags = 0;
311 pdc->lEscapement = 0;
312 pdc->prfnt = NULL;
313 pdc->dcattr.flFontMapper = 0;
314 pdc->dcattr.flTextAlign = 0;
315 pdc->dcattr.lTextAlign = 0;
316 pdc->dcattr.lTextExtra = 0;
317 pdc->dcattr.lRelAbs = 1;
318 pdc->dcattr.lBreakExtra = 0;
319 pdc->dcattr.cBreak = 0;
320 pdc->dcattr.hlfntNew = StockObjects[SYSTEM_FONT];
321 // pdc->dclevel.pFont = LFONT_ShareLockFont(pdc->dcattr.hlfntNew);
322
323 /* Other stuff */
324 pdc->hdcNext = NULL;
325 pdc->hdcPrev = NULL;
326 pdc->ipfdDevMax = 0x0000ffff;
327 pdc->ulCopyCount = -1;
328 pdc->ptlDoBanding.x = 0;
329 pdc->ptlDoBanding.y = 0;
330 pdc->dclevel.lSaveDepth = 1;
331 pdc->dclevel.hdcSave = NULL;
332 pdc->dcattr.iGraphicsMode = GM_COMPATIBLE;
333 pdc->dcattr.iCS_CP = 0;
334 pdc->pSurfInfo = NULL;
335
336 }
337
338 BOOL
339 INTERNAL_CALL
340 DC_Cleanup(PVOID ObjectBody)
341 {
342 PDC pdc = (PDC)ObjectBody;
343
344 /* Free DC_ATTR */
345 DC_vFreeDcAttr(pdc);
346
347 /* Delete saved DCs */
348 DC_vRestoreDC(pdc, 1);
349
350 /* Deselect dc objects */
351 DC_vSelectSurface(pdc, NULL);
352 DC_vSelectFillBrush(pdc, NULL);
353 DC_vSelectLineBrush(pdc, NULL);
354 DC_vSelectPalette(pdc, NULL);
355
356 /* Cleanup the dc brushes */
357 EBRUSHOBJ_vCleanup(&pdc->eboFill);
358 EBRUSHOBJ_vCleanup(&pdc->eboLine);
359 EBRUSHOBJ_vCleanup(&pdc->eboText);
360 EBRUSHOBJ_vCleanup(&pdc->eboBackground);
361
362 /* Free regions */
363 if (pdc->rosdc.hClipRgn)
364 GreDeleteObject(pdc->rosdc.hClipRgn);
365 if (pdc->prgnVis)
366 REGION_FreeRgnByHandle(((PROSRGNDATA)pdc->prgnVis)->BaseObject.hHmgr);
367 ASSERT(pdc->rosdc.hGCClipRgn);
368 if (pdc->rosdc.hGCClipRgn)
369 GreDeleteObject(pdc->rosdc.hGCClipRgn);
370 if (NULL != pdc->rosdc.CombinedClip)
371 IntEngDeleteClipRegion(pdc->rosdc.CombinedClip);
372
373 PATH_Delete(pdc->dclevel.hPath);
374
375 return TRUE;
376 }
377
378 BOOL
379 FASTCALL
380 DC_SetOwnership(HDC hDC, PEPROCESS Owner)
381 {
382 INT Index;
383 PGDI_TABLE_ENTRY Entry;
384 PDC pDC;
385
386 /* FIXME: This function has broken error handling */
387
388 if (!GDIOBJ_SetOwnership(hDC, Owner))
389 {
390 DPRINT1("GDIOBJ_SetOwnership failed\n");
391 return FALSE;
392 }
393
394 pDC = DC_LockDc(hDC);
395 if (!pDC)
396 {
397 DPRINT1("Could not lock DC\n");
398 return FALSE;
399 }
400
401 /*
402 System Regions:
403 These regions do not use attribute sections and when allocated, use
404 gdiobj level functions.
405 */
406 if (pDC->rosdc.hClipRgn)
407 { // FIXME! HAX!!!
408 Index = GDI_HANDLE_GET_INDEX(pDC->rosdc.hClipRgn);
409 Entry = &GdiHandleTable->Entries[Index];
410 if (Entry->UserData) FreeObjectAttr(Entry->UserData);
411 Entry->UserData = NULL;
412 //
413 if (!GDIOBJ_SetOwnership(pDC->rosdc.hClipRgn, Owner)) return FALSE;
414 }
415 if (pDC->prgnVis)
416 { // FIXME! HAX!!!
417 Index = GDI_HANDLE_GET_INDEX(((PROSRGNDATA)pDC->prgnVis)->BaseObject.hHmgr);
418 Entry = &GdiHandleTable->Entries[Index];
419 if (Entry->UserData) FreeObjectAttr(Entry->UserData);
420 Entry->UserData = NULL;
421 //
422 if (!GDIOBJ_SetOwnership(((PROSRGNDATA)pDC->prgnVis)->BaseObject.hHmgr, Owner)) return FALSE;
423 }
424 if (pDC->rosdc.hGCClipRgn)
425 { // FIXME! HAX!!!
426 Index = GDI_HANDLE_GET_INDEX(pDC->rosdc.hGCClipRgn);
427 Entry = &GdiHandleTable->Entries[Index];
428 if (Entry->UserData) FreeObjectAttr(Entry->UserData);
429 Entry->UserData = NULL;
430 //
431 if (!GDIOBJ_SetOwnership(pDC->rosdc.hGCClipRgn, Owner)) return FALSE;
432 }
433 if (pDC->dclevel.hPath)
434 {
435 if (!GDIOBJ_SetOwnership(pDC->dclevel.hPath, Owner)) return FALSE;
436 }
437 DC_UnlockDc(pDC);
438
439 return TRUE;
440 }
441
442 HDC
443 NTAPI
444 GreOpenDCW(
445 PUNICODE_STRING pustrDevice,
446 DEVMODEW *pdmInit,
447 PUNICODE_STRING pustrLogAddr,
448 ULONG iType,
449 BOOL bDisplay,
450 HANDLE hspool,
451 VOID *pDriverInfo2,
452 VOID *pUMdhpdev)
453 {
454 PPDEVOBJ ppdev;
455 PDC pdc;
456 HDC hdc;
457
458 DPRINT("GreOpenDCW(%S, iType=%ld)\n",
459 pustrDevice ? pustrDevice->Buffer : NULL, iType);
460
461 /* Get a PDEVOBJ for the device */
462 ppdev = EngpGetPDEV(pustrDevice);
463 if (!ppdev)
464 {
465 DPRINT1("Didn't find a suitable PDEV\n");
466 return NULL;
467 }
468
469 DPRINT("GreOpenDCW - ppdev = %p\n", ppdev);
470
471 pdc = DC_AllocDcWithHandle();
472 if (!pdc)
473 {
474 DPRINT1("Could not Allocate a DC\n");
475 PDEVOBJ_vRelease(ppdev);
476 return NULL;
477 }
478 hdc = pdc->BaseObject.hHmgr;
479
480 DC_vInitDc(pdc, iType, ppdev);
481 /* FIXME: HACK! */
482 DC_InitHack(pdc);
483
484 DC_AllocDcAttr(pdc);
485
486 DC_UnlockDc(pdc);
487
488 DPRINT("returning hdc = %p\n", hdc);
489
490 return hdc;
491 }
492
493 HDC
494 APIENTRY
495 NtGdiOpenDCW(
496 PUNICODE_STRING pustrDevice,
497 DEVMODEW *pdmInit,
498 PUNICODE_STRING pustrLogAddr,
499 ULONG iType,
500 BOOL bDisplay,
501 HANDLE hspool,
502 VOID *pDriverInfo2,
503 VOID *pUMdhpdev)
504 {
505 UNICODE_STRING ustrDevice;
506 WCHAR awcDevice[CCHDEVICENAME];
507 DEVMODEW dmInit;
508 PVOID dhpdev;
509 HDC hdc;
510
511 /* Only if a devicename is given, we need any data */
512 if (pustrDevice)
513 {
514 /* Initialize destination string */
515 RtlInitEmptyUnicodeString(&ustrDevice, awcDevice, sizeof(awcDevice));
516
517 _SEH2_TRY
518 {
519 /* Probe the UNICODE_STRING and the buffer */
520 ProbeForRead(pustrDevice, sizeof(UNICODE_STRING), 1);
521 ProbeForRead(pustrDevice->Buffer, pustrDevice->Length, 1);
522
523 /* Copy the string */
524 RtlCopyUnicodeString(&ustrDevice, pustrDevice);
525
526 if (pdmInit)
527 {
528 /* FIXME: could be larger */
529 ProbeForRead(pdmInit, sizeof(DEVMODEW), 1);
530 RtlCopyMemory(&dmInit, pdmInit, sizeof(DEVMODEW));
531 }
532
533 if (pUMdhpdev)
534 {
535 ProbeForWrite(pUMdhpdev, sizeof(HANDLE), 1);
536 }
537 }
538 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
539 {
540 SetLastNtError(_SEH2_GetExceptionCode());
541 _SEH2_YIELD(return NULL);
542 }
543 _SEH2_END
544 }
545 else
546 {
547 pdmInit = NULL;
548 pUMdhpdev = NULL;
549 }
550
551 /* FIXME: HACK! */
552 if (pustrDevice)
553 {
554 UNICODE_STRING ustrDISPLAY = RTL_CONSTANT_STRING(L"DISPLAY");
555 if (RtlEqualUnicodeString(&ustrDevice, &ustrDISPLAY, TRUE))
556 {
557 pustrDevice = NULL;
558 }
559 }
560
561 /* Call the internal function */
562 hdc = GreOpenDCW(pustrDevice ? &ustrDevice : NULL,
563 pdmInit ? &dmInit : NULL,
564 NULL, // fixme pwszLogAddress
565 iType,
566 bDisplay,
567 hspool,
568 NULL, //FIXME: pDriverInfo2
569 pUMdhpdev ? &dhpdev : NULL);
570
571 /* If we got a HDC and a UM dhpdev is requested,... */
572 if (hdc && pUMdhpdev)
573 {
574 /* Copy dhpdev to caller (FIXME: use dhpdev?? */
575 _SEH2_TRY
576 {
577 /* Pointer was already probed */
578 *(HANDLE*)pUMdhpdev = dhpdev;
579 }
580 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
581 {
582 /* Ignore error */
583 }
584 _SEH2_END
585 }
586
587 return hdc;
588 }
589
590
591 HDC
592 APIENTRY
593 NtGdiCreateCompatibleDC(HDC hdc)
594 {
595 HDC hdcNew;
596 PPDEVOBJ ppdev;
597 PDC pdc, pdcNew;
598
599 DPRINT("NtGdiCreateCompatibleDC(0x%p)\n", hdc);
600
601 /* Did the caller provide a DC? */
602 if (hdc)
603 {
604 /* Yes, try to lock it */
605 pdc = DC_LockDc(hdc);
606 if (!pdc)
607 {
608 DPRINT1("Could not lock source DC %p\n", hdc);
609 return NULL;
610 }
611
612 /* Get the pdev from the DC */
613 ppdev = pdc->ppdev;
614 InterlockedIncrement(&ppdev->cPdevRefs);
615
616 /* Unlock the source DC */
617 DC_UnlockDc(pdc);
618 }
619 else
620 {
621 /* No DC given, get default device */
622 ppdev = EngpGetPDEV(NULL);
623 }
624
625 if (!ppdev)
626 {
627 DPRINT1("Didn't find a suitable PDEV\n");
628 return NULL;
629 }
630
631 /* Allocate a new DC */
632 pdcNew = DC_AllocDcWithHandle();
633 if (!pdcNew)
634 {
635 DPRINT1("Could not allocate a new DC\n");
636 PDEVOBJ_vRelease(ppdev);
637 return NULL;
638 }
639 hdcNew = pdcNew->BaseObject.hHmgr;
640
641 /* Initialize the new DC */
642 DC_vInitDc(pdcNew, DCTYPE_MEMORY, ppdev);
643 /* FIXME: HACK! */
644 DC_InitHack(pdcNew);
645
646 /* Allocate a dc attribute */
647 DC_AllocDcAttr(pdcNew);
648
649 PDEVOBJ_vRelease(ppdev);
650
651 // HACK!
652 DC_vSelectSurface(pdcNew, psurfDefaultBitmap);
653
654 DC_UnlockDc(pdcNew);
655
656 DPRINT("Leave NtGdiCreateCompatibleDC hdcNew = %p\n", hdcNew);
657
658 return hdcNew;
659 }
660
661 BOOL
662 FASTCALL
663 IntGdiDeleteDC(HDC hDC, BOOL Force)
664 {
665 PDC DCToDelete = DC_LockDc(hDC);
666
667 if (DCToDelete == NULL)
668 {
669 SetLastWin32Error(ERROR_INVALID_HANDLE);
670 return FALSE;
671 }
672
673 if (!Force)
674 {
675 if (DCToDelete->fs & DC_FLAG_PERMANENT)
676 {
677 DPRINT1("No! You Naughty Application!\n");
678 DC_UnlockDc(DCToDelete);
679 return UserReleaseDC(NULL, hDC, FALSE);
680 }
681 }
682
683 DC_UnlockDc(DCToDelete);
684
685 if (!IsObjectDead(hDC))
686 {
687 if (!GDIOBJ_FreeObjByHandle(hDC, GDI_OBJECT_TYPE_DC))
688 {
689 DPRINT1("DC_FreeDC failed\n");
690 }
691 }
692 else
693 {
694 DPRINT1("Attempted to Delete 0x%x currently being destroyed!!!\n", hDC);
695 }
696
697 return TRUE;
698 }
699
700 BOOL
701 APIENTRY
702 NtGdiDeleteObjectApp(HANDLE DCHandle)
703 {
704 /* Complete all pending operations */
705 NtGdiFlushUserBatch();
706
707 if (GDI_HANDLE_IS_STOCKOBJ(DCHandle)) return TRUE;
708
709 if (GDI_HANDLE_GET_TYPE(DCHandle) != GDI_OBJECT_TYPE_DC)
710 return GreDeleteObject((HGDIOBJ) DCHandle);
711
712 if (IsObjectDead((HGDIOBJ)DCHandle)) return TRUE;
713
714 if (!GDIOBJ_OwnedByCurrentProcess(DCHandle))
715 {
716 SetLastWin32Error(ERROR_INVALID_HANDLE);
717 return FALSE;
718 }
719
720 return IntGdiDeleteDC(DCHandle, FALSE);
721 }
722
723 BOOL
724 APIENTRY
725 NtGdiMakeInfoDC(
726 IN HDC hdc,
727 IN BOOL bSet)
728 {
729 UNIMPLEMENTED;
730 ASSERT(FALSE);
731 return FALSE;
732 }
733
734
735 HDC FASTCALL
736 IntGdiCreateDC(
737 PUNICODE_STRING Driver,
738 PUNICODE_STRING pustrDevice,
739 PVOID pUMdhpdev,
740 CONST PDEVMODEW pdmInit,
741 BOOL CreateAsIC)
742 {
743 HDC hdc;
744
745 hdc = GreOpenDCW(pustrDevice,
746 pdmInit,
747 NULL,
748 CreateAsIC ? DCTYPE_INFO :
749 (Driver ? DC_TYPE_DIRECT : DC_TYPE_DIRECT),
750 TRUE,
751 NULL,
752 NULL,
753 pUMdhpdev);
754
755 return hdc;
756 }
757
758 HDC FASTCALL
759 IntGdiCreateDisplayDC(HDEV hDev, ULONG DcType, BOOL EmptyDC)
760 {
761 HDC hDC;
762 UNIMPLEMENTED;
763 ASSERT(FALSE);
764
765 if (DcType == DC_TYPE_MEMORY)
766 hDC = NtGdiCreateCompatibleDC(NULL); // OH~ Yuck! I think I taste vomit in my mouth!
767 else
768 hDC = IntGdiCreateDC(NULL, NULL, NULL, NULL, (DcType == DC_TYPE_INFO));
769
770 return hDC;
771 }
772