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)
14 // FIXME: Windows uses 0x0012009f
15 #define DIRTY_DEFAULT DIRTY_CHARSET|DIRTY_BACKGROUND|DIRTY_TEXT|DIRTY_LINE|DIRTY_FILL
17 PSURFACE psurfDefaultBitmap
= NULL
;
18 PBRUSH pbrDefaultBrush
= NULL
;
20 static const MATRIX gmxWorldToDeviceDefault
=
22 FLOATOBJ_16
, FLOATOBJ_0
,
23 FLOATOBJ_0
, FLOATOBJ_16
,
24 FLOATOBJ_0
, FLOATOBJ_0
,
28 static const MATRIX gmxDeviceToWorldDefault
=
30 FLOATOBJ_1_16
, FLOATOBJ_0
,
31 FLOATOBJ_0
, FLOATOBJ_1_16
,
32 FLOATOBJ_0
, FLOATOBJ_0
,
36 static const MATRIX gmxWorldToPageDefault
=
38 FLOATOBJ_1
, FLOATOBJ_0
,
39 FLOATOBJ_0
, FLOATOBJ_1
,
40 FLOATOBJ_0
, FLOATOBJ_0
,
44 // HACK!! Fix XFORMOBJ then use 1:16 / 16:1
45 #define gmxWorldToDeviceDefault gmxWorldToPageDefault
46 #define gmxDeviceToWorldDefault gmxWorldToPageDefault
48 /** Internal functions ********************************************************/
55 psurfDefaultBitmap
= SURFACE_ShareLockSurface(StockObjects
[DEFAULT_BITMAP
]);
56 if (!psurfDefaultBitmap
)
57 return STATUS_UNSUCCESSFUL
;
59 pbrDefaultBrush
= BRUSH_ShareLockBrush(StockObjects
[BLACK_BRUSH
]);
61 return STATUS_UNSUCCESSFUL
;
63 return STATUS_SUCCESS
;
69 DC_AllocDcWithHandle()
73 pdc
= (PDC
)GDIOBJ_AllocateObject(GDIObjType_DC_TYPE
,
78 DPRINT1("Could not allocate a DC.\n");
82 if (!GDIOBJ_hInsertObject(&pdc
->BaseObject
, GDI_OBJ_HMGR_POWNED
))
84 DPRINT1("Could not insert DC into handle table.\n");
85 GDIOBJ_vFreeObject(&pdc
->BaseObject
);
89 pdc
->pdcattr
= &pdc
->dcattr
;
100 TextIntRealizeFont(pdc
->pdcattr
->hlfntNew
,NULL
);
101 pdc
->pdcattr
->iCS_CP
= ftGdiGetTextCharsetInfo(pdc
,NULL
,0);
103 /* This should never fail */
104 ASSERT(pdc
->dclevel
.ppal
);
107 pdc
->rosdc
.hClipRgn
= NULL
;
108 pdc
->rosdc
.hGCClipRgn
= NULL
;
110 hVisRgn
= IntSysCreateRectRgn(0, 0, 1, 1);
112 GdiSelectVisRgn(pdc
->BaseObject
.hHmgr
, hVisRgn
);
113 GreDeleteObject(hVisRgn
);
123 /* Setup some basic fields */
124 pdc
->dctype
= dctype
;
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
;
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
;
139 /* Setup the DC size */
140 if (dctype
== DCTYPE_MEMORY
)
142 /* Memory DCs have a 1 x 1 bitmap by default */
143 pdc
->dclevel
.sizl
.cx
= 1;
144 pdc
->dclevel
.sizl
.cy
= 1;
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
;
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
;
159 if (dctype
== DCTYPE_DIRECT
)
161 /* Direct DCs get the surface from the PDEV */
162 pdc
->dclevel
.pSurface
= PDEVOBJ_pSurface(ppdev
);
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
;
175 pdc
->fs
|= DC_SYNCHRONIZEACCESS
| DC_ACCUM_APP
| DC_PERMANANT
| DC_DISPLAY
;
179 /* Non-direct DCs don't have a surface by default */
180 pdc
->dclevel
.pSurface
= NULL
;
182 pdc
->erclBounds
.left
= 0;
183 pdc
->erclBounds
.top
= 0;
184 pdc
->erclBounds
.right
= 0;
185 pdc
->erclBounds
.bottom
= 0;
186 pdc
->erclBoundsApp
= pdc
->erclBounds
;
187 pdc
->erclClip
= pdc
->erclWindow
;
191 //pdc->dcattr.VisRectRegion:
193 /* Setup coordinate transformation data */
194 pdc
->dclevel
.mxWorldToDevice
= gmxWorldToDeviceDefault
;
195 pdc
->dclevel
.mxDeviceToWorld
= gmxDeviceToWorldDefault
;
196 pdc
->dclevel
.mxWorldToPage
= gmxWorldToPageDefault
;
197 pdc
->dclevel
.efM11PtoD
= gef16
;
198 pdc
->dclevel
.efM22PtoD
= gef16
;
199 pdc
->dclevel
.efDxPtoD
= gef0
;
200 pdc
->dclevel
.efDyPtoD
= gef0
;
201 pdc
->dclevel
.efM11_TWIPS
= gef0
;
202 pdc
->dclevel
.efM22_TWIPS
= gef0
;
203 pdc
->dclevel
.efPr11
= gef0
;
204 pdc
->dclevel
.efPr22
= gef0
;
205 pdc
->dcattr
.mxWorldToDevice
= pdc
->dclevel
.mxWorldToDevice
;
206 pdc
->dcattr
.mxDeviceToWorld
= pdc
->dclevel
.mxDeviceToWorld
;
207 pdc
->dcattr
.mxWorldToPage
= pdc
->dclevel
.mxWorldToPage
;
208 pdc
->dcattr
.efM11PtoD
= pdc
->dclevel
.efM11PtoD
;
209 pdc
->dcattr
.efM22PtoD
= pdc
->dclevel
.efM22PtoD
;
210 pdc
->dcattr
.efDxPtoD
= pdc
->dclevel
.efDxPtoD
;
211 pdc
->dcattr
.efDyPtoD
= pdc
->dclevel
.efDyPtoD
;
212 pdc
->dcattr
.iMapMode
= MM_TEXT
;
213 pdc
->dcattr
.dwLayout
= 0;
214 pdc
->dcattr
.flXform
= PAGE_TO_DEVICE_SCALE_IDENTITY
|
215 PAGE_TO_DEVICE_IDENTITY
|
216 WORLD_TO_PAGE_IDENTITY
;
218 /* Setup more coordinates */
219 pdc
->ptlDCOrig
.x
= 0;
220 pdc
->ptlDCOrig
.y
= 0;
221 pdc
->dcattr
.lWindowOrgx
= 0;
222 pdc
->dcattr
.ptlWindowOrg
.x
= 0;
223 pdc
->dcattr
.ptlWindowOrg
.y
= 0;
224 pdc
->dcattr
.szlWindowExt
.cx
= 1;
225 pdc
->dcattr
.szlWindowExt
.cy
= 1;
226 pdc
->dcattr
.ptlViewportOrg
.x
= 0;
227 pdc
->dcattr
.ptlViewportOrg
.y
= 0;
228 pdc
->dcattr
.szlViewportExt
.cx
= 1;
229 pdc
->dcattr
.szlViewportExt
.cy
= 1;
230 pdc
->dcattr
.szlVirtualDevicePixel
.cx
= ppdev
->gdiinfo
.ulHorzRes
;
231 pdc
->dcattr
.szlVirtualDevicePixel
.cy
= ppdev
->gdiinfo
.ulVertRes
;
232 pdc
->dcattr
.szlVirtualDeviceMm
.cx
= ppdev
->gdiinfo
.ulHorzSize
;
233 pdc
->dcattr
.szlVirtualDeviceMm
.cy
= ppdev
->gdiinfo
.ulVertSize
;
234 pdc
->dcattr
.szlVirtualDeviceSize
.cx
= 0;
235 pdc
->dcattr
.szlVirtualDeviceSize
.cy
= 0;
240 /* Allocate a Vis region */
241 pdc
->prgnVis
= IntSysCreateRectpRgn(0, 0, pdc
->dclevel
.sizl
.cx
, pdc
->dclevel
.sizl
.cy
);
242 ASSERT(pdc
->prgnVis
);
245 pdc
->dclevel
.hpal
= StockObjects
[DEFAULT_PALETTE
];
246 pdc
->dclevel
.ppal
= PALETTE_ShareLockPalette(pdc
->dclevel
.hpal
);
249 pdc
->dclevel
.hPath
= NULL
;
250 pdc
->dclevel
.flPath
= 0;
251 // pdc->dclevel.lapath:
254 pdc
->dcattr
.crBackgroundClr
= RGB(0xff, 0xff, 0xff);
255 pdc
->dcattr
.ulBackgroundClr
= RGB(0xff, 0xff, 0xff);
256 pdc
->dcattr
.crForegroundClr
= RGB(0, 0, 0);
257 pdc
->dcattr
.ulForegroundClr
= RGB(0, 0, 0);
258 pdc
->dcattr
.crBrushClr
= RGB(0xff, 0xff, 0xff);
259 pdc
->dcattr
.ulBrushClr
= RGB(0xff, 0xff, 0xff);
260 pdc
->dcattr
.crPenClr
= RGB(0, 0, 0);
261 pdc
->dcattr
.ulPenClr
= RGB(0, 0, 0);
263 /* Select the default fill and line brush */
264 pdc
->dcattr
.hbrush
= StockObjects
[WHITE_BRUSH
];
265 pdc
->dcattr
.hpen
= StockObjects
[BLACK_PEN
];
266 pdc
->dclevel
.pbrFill
= BRUSH_ShareLockBrush(pdc
->pdcattr
->hbrush
);
267 pdc
->dclevel
.pbrLine
= PEN_ShareLockPen(pdc
->pdcattr
->hpen
);
268 pdc
->dclevel
.ptlBrushOrigin
.x
= 0;
269 pdc
->dclevel
.ptlBrushOrigin
.y
= 0;
270 pdc
->dcattr
.ptlBrushOrigin
= pdc
->dclevel
.ptlBrushOrigin
;
272 /* Initialize EBRUSHOBJs */
273 EBRUSHOBJ_vInitFromDC(&pdc
->eboFill
, pdc
->dclevel
.pbrFill
, pdc
);
274 EBRUSHOBJ_vInitFromDC(&pdc
->eboLine
, pdc
->dclevel
.pbrLine
, pdc
);
275 EBRUSHOBJ_vInitFromDC(&pdc
->eboText
, pbrDefaultBrush
, pdc
);
276 EBRUSHOBJ_vInitFromDC(&pdc
->eboBackground
, pbrDefaultBrush
, pdc
);
278 /* Setup fill data */
279 pdc
->dcattr
.jROP2
= R2_COPYPEN
;
280 pdc
->dcattr
.jBkMode
= 2;
281 pdc
->dcattr
.lBkMode
= 2;
282 pdc
->dcattr
.jFillMode
= ALTERNATE
;
283 pdc
->dcattr
.lFillMode
= 1;
284 pdc
->dcattr
.jStretchBltMode
= 1;
285 pdc
->dcattr
.lStretchBltMode
= 1;
286 pdc
->ptlFillOrigin
.x
= 0;
287 pdc
->ptlFillOrigin
.y
= 0;
289 /* Setup drawing position */
290 pdc
->dcattr
.ptlCurrent
.x
= 0;
291 pdc
->dcattr
.ptlCurrent
.y
= 0;
292 pdc
->dcattr
.ptfxCurrent
.x
= 0;
293 pdc
->dcattr
.ptfxCurrent
.y
= 0;
296 pdc
->dclevel
.lIcmMode
= 0;
297 pdc
->dcattr
.lIcmMode
= 0;
298 pdc
->dcattr
.hcmXform
= NULL
;
299 pdc
->dcattr
.flIcmFlags
= 0;
300 pdc
->dcattr
.IcmBrushColor
= CLR_INVALID
;
301 pdc
->dcattr
.IcmPenColor
= CLR_INVALID
;
302 pdc
->dcattr
.pvLIcm
= NULL
;
303 pdc
->dcattr
.hColorSpace
= NULL
; // FIXME: 0189001f
304 pdc
->dclevel
.pColorSpace
= NULL
; // FIXME
305 pdc
->pClrxFormLnk
= NULL
;
308 /* Setup font data */
309 pdc
->hlfntCur
= NULL
; // FIXME: 2f0a0cf8
310 pdc
->pPFFList
= NULL
;
311 pdc
->flSimulationFlags
= 0;
312 pdc
->lEscapement
= 0;
314 pdc
->dcattr
.flFontMapper
= 0;
315 pdc
->dcattr
.flTextAlign
= 0;
316 pdc
->dcattr
.lTextAlign
= 0;
317 pdc
->dcattr
.lTextExtra
= 0;
318 pdc
->dcattr
.lRelAbs
= 1;
319 pdc
->dcattr
.lBreakExtra
= 0;
320 pdc
->dcattr
.cBreak
= 0;
321 pdc
->dcattr
.hlfntNew
= StockObjects
[SYSTEM_FONT
];
322 pdc
->dclevel
.plfnt
= LFONT_ShareLockFont(pdc
->dcattr
.hlfntNew
);
327 pdc
->ipfdDevMax
= 0x0000ffff;
328 pdc
->ulCopyCount
= -1;
329 pdc
->ptlDoBanding
.x
= 0;
330 pdc
->ptlDoBanding
.y
= 0;
331 pdc
->dclevel
.lSaveDepth
= 1;
332 pdc
->dclevel
.hdcSave
= NULL
;
333 pdc
->dcattr
.iGraphicsMode
= GM_COMPATIBLE
;
334 pdc
->dcattr
.iCS_CP
= 0;
335 pdc
->pSurfInfo
= NULL
;
337 if (defaultDCstate
== NULL
)
339 defaultDCstate
= ExAllocatePoolWithTag(PagedPool
, sizeof(DC
), TAG_DC
);
340 ASSERT(defaultDCstate
);
341 RtlZeroMemory(defaultDCstate
, sizeof(DC
));
342 defaultDCstate
->pdcattr
= &defaultDCstate
->dcattr
;
343 DC_vCopyState(pdc
, defaultDCstate
, TRUE
);
349 DC_Cleanup(PVOID ObjectBody
)
351 PDC pdc
= (PDC
)ObjectBody
;
356 /* Delete saved DCs */
357 DC_vRestoreDC(pdc
, 1);
359 /* Deselect dc objects */
360 DC_vSelectSurface(pdc
, NULL
);
361 DC_vSelectFillBrush(pdc
, NULL
);
362 DC_vSelectLineBrush(pdc
, NULL
);
363 DC_vSelectPalette(pdc
, NULL
);
365 /* Cleanup the dc brushes */
366 EBRUSHOBJ_vCleanup(&pdc
->eboFill
);
367 EBRUSHOBJ_vCleanup(&pdc
->eboLine
);
368 EBRUSHOBJ_vCleanup(&pdc
->eboText
);
369 EBRUSHOBJ_vCleanup(&pdc
->eboBackground
);
372 LFONT_ShareUnlockFont(pdc
->dclevel
.plfnt
);
375 if (pdc
->rosdc
.hClipRgn
&& GreIsHandleValid(pdc
->rosdc
.hClipRgn
))
376 GreDeleteObject(pdc
->rosdc
.hClipRgn
);
379 REGION_Delete(pdc
->prgnVis
);
381 if (pdc
->rosdc
.hGCClipRgn
&& GreIsHandleValid(pdc
->rosdc
.hGCClipRgn
))
383 GreDeleteObject(pdc
->rosdc
.hGCClipRgn
);
385 if (NULL
!= pdc
->rosdc
.CombinedClip
)
386 IntEngDeleteClipRegion(pdc
->rosdc
.CombinedClip
);
388 PATH_Delete(pdc
->dclevel
.hPath
);
390 if(pdc
->dclevel
.pSurface
)
391 SURFACE_ShareUnlockSurface(pdc
->dclevel
.pSurface
);
393 PDEVOBJ_vRelease(pdc
->ppdev
) ;
400 DC_vSetOwner(PDC pdc
, ULONG ulOwner
)
403 if (pdc
->rosdc
.hClipRgn
)
405 IntGdiSetRegionOwner(pdc
->rosdc
.hClipRgn
, ulOwner
);
408 if (pdc
->rosdc
.hGCClipRgn
)
410 IntGdiSetRegionOwner(pdc
->rosdc
.hGCClipRgn
, ulOwner
);
413 if (pdc
->dclevel
.hPath
)
415 GreSetObjectOwner(pdc
->dclevel
.hPath
, ulOwner
);
418 /* Dereference current brush and pen */
419 BRUSH_ShareUnlockBrush(pdc
->dclevel
.pbrFill
);
420 BRUSH_ShareUnlockBrush(pdc
->dclevel
.pbrLine
);
422 /* Select the default fill and line brush */
423 pdc
->dcattr
.hbrush
= StockObjects
[WHITE_BRUSH
];
424 pdc
->dcattr
.hpen
= StockObjects
[BLACK_PEN
];
425 pdc
->dclevel
.pbrFill
= BRUSH_ShareLockBrush(pdc
->pdcattr
->hbrush
);
426 pdc
->dclevel
.pbrLine
= PEN_ShareLockPen(pdc
->pdcattr
->hpen
);
428 /* Mark them as dirty */
429 pdc
->pdcattr
->ulDirty_
|= DIRTY_FILL
|DIRTY_LINE
;
431 /* Allocate or free DC attribute */
432 if (ulOwner
== GDI_OBJ_HMGR_PUBLIC
|| ulOwner
== GDI_OBJ_HMGR_NONE
)
434 if (pdc
->pdcattr
!= &pdc
->dcattr
)
437 else if (ulOwner
== GDI_OBJ_HMGR_POWNED
)
439 if (pdc
->pdcattr
== &pdc
->dcattr
)
440 DC_bAllocDcAttr(pdc
);
443 /* Set the DC's ownership */
444 GDIOBJ_vSetObjectOwner(&pdc
->BaseObject
, ulOwner
);
449 GreSetDCOwner(HDC hdc
, ULONG ulOwner
)
453 pdc
= DC_LockDc(hdc
);
456 DPRINT1("GreSetDCOwner: Could not lock DC\n");
460 /* Call the internal DC function */
461 DC_vSetOwner(pdc
, ulOwner
);
469 DC_vUpdateDC(PDC pdc
)
472 PPDEVOBJ ppdev
= pdc
->ppdev
;
474 pdc
->dhpdev
= ppdev
->dhpdev
;
476 SURFACE_ShareUnlockSurface(pdc
->dclevel
.pSurface
);
477 pdc
->dclevel
.pSurface
= PDEVOBJ_pSurface(ppdev
);
479 PDEVOBJ_sizl(pdc
->ppdev
, &pdc
->dclevel
.sizl
);
480 hVisRgn
= NtGdiCreateRectRgn(0, 0, pdc
->dclevel
.sizl
.cx
, pdc
->dclevel
.sizl
.cy
);
482 GdiSelectVisRgn(pdc
->BaseObject
.hHmgr
, hVisRgn
);
483 GreDeleteObject(hVisRgn
);
485 pdc
->flGraphicsCaps
= ppdev
->devinfo
.flGraphicsCaps
;
486 pdc
->flGraphicsCaps2
= ppdev
->devinfo
.flGraphicsCaps2
;
488 /* Mark EBRUSHOBJs as dirty */
489 pdc
->pdcattr
->ulDirty_
|= DIRTY_DEFAULT
;
492 /* Prepare a blit for up to 2 DCs */
493 /* rc1 and rc2 are the rectangles where we want to draw or
494 * from where we take pixels. */
497 DC_vPrepareDCsForBlit(PDC pdc1
,
502 PDC pdcFirst
, pdcSecond
;
503 PRECT prcFirst
, prcSecond
;
506 if (pdc1
->pdcattr
->ulDirty_
& (DIRTY_FILL
| DC_BRUSH_DIRTY
))
507 DC_vUpdateFillBrush(pdc1
);
508 if (pdc1
->pdcattr
->ulDirty_
& (DIRTY_LINE
| DC_PEN_DIRTY
))
509 DC_vUpdateLineBrush(pdc1
);
510 if(pdc1
->pdcattr
->ulDirty_
& DIRTY_TEXT
)
511 DC_vUpdateTextBrush(pdc1
);
513 /* Lock them in good order */
516 if((ULONG_PTR
)pdc1
->ppdev
->hsemDevLock
>= (ULONG_PTR
)pdc2
->ppdev
->hsemDevLock
)
539 if(pdcFirst
&& pdcFirst
->dctype
== DCTYPE_DIRECT
)
541 EngAcquireSemaphore(pdcFirst
->ppdev
->hsemDevLock
);
542 MouseSafetyOnDrawStart(pdcFirst
->ppdev
,
547 /* Update surface if needed */
548 if(pdcFirst
->ppdev
->pSurface
!= pdcFirst
->dclevel
.pSurface
)
550 DC_vUpdateDC(pdcFirst
);
553 if(pdcSecond
&& pdcSecond
->dctype
== DCTYPE_DIRECT
)
555 EngAcquireSemaphore(pdcSecond
->ppdev
->hsemDevLock
);
556 MouseSafetyOnDrawStart(pdcSecond
->ppdev
,
561 /* Update surface if needed */
562 if(pdcSecond
->ppdev
->pSurface
!= pdcSecond
->dclevel
.pSurface
)
564 DC_vUpdateDC(pdcSecond
);
569 /* Finishes a blit for one or two DCs */
572 DC_vFinishBlit(PDC pdc1
, PDC pdc2
)
574 if(pdc1
->dctype
== DCTYPE_DIRECT
)
576 MouseSafetyOnDrawEnd(pdc1
->ppdev
);
577 EngReleaseSemaphore(pdc1
->ppdev
->hsemDevLock
);
582 if(pdc2
->dctype
== DCTYPE_DIRECT
)
584 MouseSafetyOnDrawEnd(pdc2
->ppdev
);
585 EngReleaseSemaphore(pdc2
->ppdev
->hsemDevLock
);
593 PUNICODE_STRING pustrDevice
,
595 PUNICODE_STRING pustrLogAddr
,
606 DPRINT("GreOpenDCW(%S, iType=%lu)\n",
607 pustrDevice
? pustrDevice
->Buffer
: NULL
, iType
);
609 /* Get a PDEVOBJ for the device */
610 ppdev
= EngpGetPDEV(pustrDevice
);
613 DPRINT1("Didn't find a suitable PDEV\n");
617 DPRINT("GreOpenDCW - ppdev = %p\n", ppdev
);
619 pdc
= DC_AllocDcWithHandle();
622 DPRINT1("Could not Allocate a DC\n");
623 PDEVOBJ_vRelease(ppdev
);
626 hdc
= pdc
->BaseObject
.hHmgr
;
628 /* Lock ppdev and initialize the new DC */
629 DC_vInitDc(pdc
, iType
, ppdev
);
633 DC_bAllocDcAttr(pdc
);
637 DPRINT("Returning hdc = %p\n", hdc
);
645 PUNICODE_STRING pustrDevice
,
647 PUNICODE_STRING pustrLogAddr
,
654 UNICODE_STRING ustrDevice
;
655 WCHAR awcDevice
[CCHDEVICENAME
];
660 /* Only if a devicename is given, we need any data */
663 /* Initialize destination string */
664 RtlInitEmptyUnicodeString(&ustrDevice
, awcDevice
, sizeof(awcDevice
));
668 /* Probe the UNICODE_STRING and the buffer */
669 ProbeForRead(pustrDevice
, sizeof(UNICODE_STRING
), 1);
670 ProbeForRead(pustrDevice
->Buffer
, pustrDevice
->Length
, 1);
672 /* Copy the string */
673 RtlCopyUnicodeString(&ustrDevice
, pustrDevice
);
677 /* FIXME: could be larger */
678 ProbeForRead(pdmInit
, sizeof(DEVMODEW
), 1);
679 RtlCopyMemory(&dmInit
, pdmInit
, sizeof(DEVMODEW
));
684 ProbeForWrite(pUMdhpdev
, sizeof(HANDLE
), 1);
687 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
689 SetLastNtError(_SEH2_GetExceptionCode());
690 _SEH2_YIELD(return NULL
);
703 UNICODE_STRING ustrDISPLAY
= RTL_CONSTANT_STRING(L
"DISPLAY");
704 if (RtlEqualUnicodeString(&ustrDevice
, &ustrDISPLAY
, TRUE
))
710 /* Call the internal function */
711 hdc
= GreOpenDCW(pustrDevice
? &ustrDevice
: NULL
,
712 pdmInit
? &dmInit
: NULL
,
713 NULL
, // FIXME: pwszLogAddress
717 NULL
, // FIXME: pDriverInfo2
718 pUMdhpdev
? &dhpdev
: NULL
);
720 /* If we got a HDC and a UM dhpdev is requested,... */
721 if (hdc
&& pUMdhpdev
)
723 /* Copy dhpdev to caller (FIXME: use dhpdev?) */
726 /* Pointer was already probed */
727 *(HANDLE
*)pUMdhpdev
= dhpdev
;
729 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
743 NtGdiCreateCompatibleDC(HDC hdc
)
749 DPRINT("NtGdiCreateCompatibleDC(0x%p)\n", hdc
);
751 /* Did the caller provide a DC? */
754 /* Yes, try to lock it */
755 pdc
= DC_LockDc(hdc
);
758 DPRINT1("Could not lock source DC %p\n", hdc
);
762 /* Get the pdev from the DC */
764 InterlockedIncrement(&ppdev
->cPdevRefs
);
766 /* Unlock the source DC */
771 /* No DC given, get default device */
772 ppdev
= EngpGetPDEV(NULL
);
777 DPRINT1("Didn't find a suitable PDEV\n");
781 /* Allocate a new DC */
782 pdcNew
= DC_AllocDcWithHandle();
785 DPRINT1("Could not allocate a new DC\n");
786 PDEVOBJ_vRelease(ppdev
);
789 hdcNew
= pdcNew
->BaseObject
.hHmgr
;
791 /* Lock ppdev and initialize the new DC */
792 DC_vInitDc(pdcNew
, DCTYPE_MEMORY
, ppdev
);
796 /* Allocate a dc attribute */
797 DC_bAllocDcAttr(pdcNew
);
801 DPRINT("Leave NtGdiCreateCompatibleDC hdcNew = %p\n", hdcNew
);
808 IntGdiDeleteDC(HDC hDC
, BOOL Force
)
810 PDC DCToDelete
= DC_LockDc(hDC
);
812 if (DCToDelete
== NULL
)
814 EngSetLastError(ERROR_INVALID_HANDLE
);
820 /* Windows permits NtGdiDeleteObjectApp to delete a permanent DC
821 * For some reason, it's still a valid handle, pointing to some kernel data.
822 * Not sure if this is a bug, a feature, some cache stuff... Who knows?
823 * See NtGdiDeleteObjectApp test for details */
824 if (DCToDelete
->fs
& DC_FLAG_PERMANENT
)
826 DC_UnlockDc(DCToDelete
);
827 if(UserReleaseDC(NULL
, hDC
, FALSE
))
829 /* ReactOS feature: Call UserReleaseDC
830 * I don't think Windows does it.
831 * Still, complain, no one should ever call DeleteDC
833 DPRINT1("No, you naughty application!\n");
838 /* This is not a window owned DC.
839 * Force its deletion */
840 return IntGdiDeleteDC(hDC
, TRUE
);
845 DC_UnlockDc(DCToDelete
);
847 if (GreIsHandleValid(hDC
))
849 if (!GreDeleteObject(hDC
))
851 DPRINT1("DC_FreeDC failed\n");
856 DPRINT1("Attempted to Delete 0x%p currently being destroyed!!!\n", hDC
);
864 NtGdiDeleteObjectApp(HANDLE hobj
)
866 /* Complete all pending operations */
867 NtGdiFlushUserBatch(); // FIXME: We shouldn't need this
869 if (GDI_HANDLE_IS_STOCKOBJ(hobj
)) return TRUE
;
871 if (GreGetObjectOwner(hobj
) != GDI_OBJ_HMGR_POWNED
)
873 EngSetLastError(ERROR_INVALID_HANDLE
);
877 if (GDI_HANDLE_GET_TYPE(hobj
) != GDI_OBJECT_TYPE_DC
)
878 return GreDeleteObject(hobj
);
880 // FIXME: Everything should be callback based
881 return IntGdiDeleteDC(hobj
, FALSE
);
886 MakeInfoDC(PDC pdc
, BOOL bSet
)
891 /* Can not be a display DC. */
892 if (pdc
->fs
& DC_FLAG_DISPLAY
) return FALSE
;
895 if (pdc
->fs
& DC_FLAG_TEMPINFODC
|| pdc
->dctype
== DC_TYPE_DIRECT
)
898 pSurface
= pdc
->dclevel
.pSurface
;
899 pdc
->fs
|= DC_FLAG_TEMPINFODC
;
900 pdc
->pSurfInfo
= pSurface
;
901 pdc
->dctype
= DC_TYPE_INFO
;
902 pdc
->dclevel
.pSurface
= NULL
;
904 PDEVOBJ_sizl(pdc
->ppdev
, &sizl
);
906 if ( sizl
.cx
== pdc
->dclevel
.sizl
.cx
&&
907 sizl
.cy
== pdc
->dclevel
.sizl
.cy
)
910 pdc
->dclevel
.sizl
.cx
= sizl
.cx
;
911 pdc
->dclevel
.sizl
.cy
= sizl
.cy
;
915 if (!(pdc
->fs
& DC_FLAG_TEMPINFODC
) || pdc
->dctype
!= DC_TYPE_INFO
)
918 pSurface
= pdc
->pSurfInfo
;
919 pdc
->fs
&= ~DC_FLAG_TEMPINFODC
;
920 pdc
->dclevel
.pSurface
= pSurface
;
921 pdc
->dctype
= DC_TYPE_DIRECT
;
922 pdc
->pSurfInfo
= NULL
;
925 (pSurface
->SurfObj
.sizlBitmap
.cx
== pdc
->dclevel
.sizl
.cx
&&
926 pSurface
->SurfObj
.sizlBitmap
.cy
== pdc
->dclevel
.sizl
.cy
) )
929 pdc
->dclevel
.sizl
.cx
= pSurface
->SurfObj
.sizlBitmap
.cx
;
930 pdc
->dclevel
.sizl
.cy
= pSurface
->SurfObj
.sizlBitmap
.cy
;
932 return IntSetDefaultRegion(pdc
);
945 PDC pdc
= DC_LockDc(hdc
);
948 Ret
= MakeInfoDC(pdc
, bSet
);
958 PUNICODE_STRING Driver
,
959 PUNICODE_STRING pustrDevice
,
961 CONST PDEVMODEW pdmInit
,
966 hdc
= GreOpenDCW(pustrDevice
,
969 CreateAsIC
? DCTYPE_INFO
:
970 (Driver
? DC_TYPE_DIRECT
: DC_TYPE_DIRECT
),
980 IntGdiCreateDisplayDC(HDEV hDev
, ULONG DcType
, BOOL EmptyDC
)
986 if (DcType
== DC_TYPE_MEMORY
)
987 hDC
= NtGdiCreateCompatibleDC(NULL
); // OH~ Yuck! I think I taste vomit in my mouth!
989 hDC
= IntGdiCreateDC(NULL
, NULL
, NULL
, NULL
, (DcType
== DC_TYPE_INFO
));