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