2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * PURPOSE: Functions for creation and destruction of DCs
5 * FILE: win32ss/gdi/ntgdi/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 const MATRIX gmxWorldToDeviceDefault
=
22 FLOATOBJ_16
, FLOATOBJ_0
,
23 FLOATOBJ_0
, FLOATOBJ_16
,
24 FLOATOBJ_0
, FLOATOBJ_0
,
28 const MATRIX gmxDeviceToWorldDefault
=
30 FLOATOBJ_1_16
, FLOATOBJ_0
,
31 FLOATOBJ_0
, FLOATOBJ_1_16
,
32 FLOATOBJ_0
, FLOATOBJ_0
,
36 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(GDILOOBJTYPE eDcObjType
)
73 NT_ASSERT((eDcObjType
== GDILoObjType_LO_DC_TYPE
) ||
74 (eDcObjType
== GDILoObjType_LO_ALTDC_TYPE
));
76 /* Allocate the object */
77 pdc
= (PDC
)GDIOBJ_AllocateObject(GDIObjType_DC_TYPE
,
82 DPRINT1("Could not allocate a DC.\n");
86 /* Set the actual DC type */
87 pdc
->BaseObject
.hHmgr
= UlongToHandle(eDcObjType
);
89 pdc
->pdcattr
= &pdc
->dcattr
;
91 /* Insert the object */
92 if (!GDIOBJ_hInsertObject(&pdc
->BaseObject
, GDI_OBJ_HMGR_POWNED
))
94 DPRINT1("Could not insert DC into handle table.\n");
95 GDIOBJ_vFreeObject(&pdc
->BaseObject
);
106 if (defaultDCstate
== NULL
)
108 defaultDCstate
= ExAllocatePoolWithTag(PagedPool
, sizeof(DC
), TAG_DC
);
109 ASSERT(defaultDCstate
);
110 RtlZeroMemory(defaultDCstate
, sizeof(DC
));
111 defaultDCstate
->pdcattr
= &defaultDCstate
->dcattr
;
112 DC_vCopyState(pdc
, defaultDCstate
, TRUE
);
115 if (prgnDefault
== NULL
)
117 prgnDefault
= IntSysCreateRectpRgn(0, 0, 0, 0);
120 TextIntRealizeFont(pdc
->pdcattr
->hlfntNew
,NULL
);
121 pdc
->pdcattr
->iCS_CP
= ftGdiGetTextCharsetInfo(pdc
,NULL
,0);
123 /* This should never fail */
124 ASSERT(pdc
->dclevel
.ppal
);
134 /* Setup some basic fields */
135 pdc
->dctype
= dctype
;
137 pdc
->dhpdev
= ppdev
->dhpdev
;
138 pdc
->hsem
= ppdev
->hsemDevLock
;
139 pdc
->flGraphicsCaps
= ppdev
->devinfo
.flGraphicsCaps
;
140 pdc
->flGraphicsCaps2
= ppdev
->devinfo
.flGraphicsCaps2
;
141 pdc
->fs
= DC_DIRTY_RAO
;
143 /* Setup dc attribute */
144 pdc
->pdcattr
= &pdc
->dcattr
;
145 pdc
->dcattr
.pvLDC
= NULL
;
146 pdc
->dcattr
.ulDirty_
= DIRTY_DEFAULT
;
147 if (ppdev
== gppdevPrimary
)
148 pdc
->dcattr
.ulDirty_
|= DC_PRIMARY_DISPLAY
;
150 /* Setup the DC size */
151 if (dctype
== DCTYPE_MEMORY
)
153 /* Memory DCs have a 1 x 1 bitmap by default */
154 pdc
->dclevel
.sizl
.cx
= 1;
155 pdc
->dclevel
.sizl
.cy
= 1;
159 /* Other DC's are as big as the related PDEV */
160 pdc
->dclevel
.sizl
.cx
= ppdev
->gdiinfo
.ulHorzRes
;
161 pdc
->dclevel
.sizl
.cy
= ppdev
->gdiinfo
.ulVertRes
;
164 /* Setup Window rect based on DC size */
165 pdc
->erclWindow
.left
= 0;
166 pdc
->erclWindow
.top
= 0;
167 pdc
->erclWindow
.right
= pdc
->dclevel
.sizl
.cx
;
168 pdc
->erclWindow
.bottom
= pdc
->dclevel
.sizl
.cy
;
170 if (dctype
== DCTYPE_DIRECT
)
172 /* Direct DCs get the surface from the PDEV */
173 pdc
->dclevel
.pSurface
= PDEVOBJ_pSurface(ppdev
);
175 pdc
->erclBounds
.left
= 0x7fffffff;
176 pdc
->erclBounds
.top
= 0x7fffffff;
177 pdc
->erclBounds
.right
= 0x80000000;
178 pdc
->erclBounds
.bottom
= 0x80000000;
179 pdc
->erclBoundsApp
.left
= 0xffffffff;
180 pdc
->erclBoundsApp
.top
= 0xfffffffc;
181 pdc
->erclBoundsApp
.right
= 0x00007ffc; // FIXME
182 pdc
->erclBoundsApp
.bottom
= 0x00000333; // FIXME
183 pdc
->erclClip
= pdc
->erclBounds
;
184 pdc
->co
= gxcoTrivial
;
188 /* Non-direct DCs don't have a surface by default */
189 pdc
->dclevel
.pSurface
= NULL
;
191 pdc
->erclBounds
.left
= 0;
192 pdc
->erclBounds
.top
= 0;
193 pdc
->erclBounds
.right
= 0;
194 pdc
->erclBounds
.bottom
= 0;
195 pdc
->erclBoundsApp
= pdc
->erclBounds
;
196 pdc
->erclClip
= pdc
->erclWindow
;
197 pdc
->co
= gxcoTrivial
;
200 //pdc->dcattr.VisRectRegion:
202 /* Setup coordinate transformation data */
203 pdc
->dclevel
.mxWorldToDevice
= gmxWorldToDeviceDefault
;
204 pdc
->dclevel
.mxDeviceToWorld
= gmxDeviceToWorldDefault
;
205 pdc
->dclevel
.mxWorldToPage
= gmxWorldToPageDefault
;
206 pdc
->dclevel
.efM11PtoD
= gef16
;
207 pdc
->dclevel
.efM22PtoD
= gef16
;
208 pdc
->dclevel
.efDxPtoD
= gef0
;
209 pdc
->dclevel
.efDyPtoD
= gef0
;
210 pdc
->dclevel
.efM11_TWIPS
= gef0
;
211 pdc
->dclevel
.efM22_TWIPS
= gef0
;
212 pdc
->dclevel
.efPr11
= gef0
;
213 pdc
->dclevel
.efPr22
= gef0
;
214 pdc
->dcattr
.mxWorldToDevice
= pdc
->dclevel
.mxWorldToDevice
;
215 pdc
->dcattr
.mxDeviceToWorld
= pdc
->dclevel
.mxDeviceToWorld
;
216 pdc
->dcattr
.mxWorldToPage
= pdc
->dclevel
.mxWorldToPage
;
217 pdc
->dcattr
.efM11PtoD
= pdc
->dclevel
.efM11PtoD
;
218 pdc
->dcattr
.efM22PtoD
= pdc
->dclevel
.efM22PtoD
;
219 pdc
->dcattr
.efDxPtoD
= pdc
->dclevel
.efDxPtoD
;
220 pdc
->dcattr
.efDyPtoD
= pdc
->dclevel
.efDyPtoD
;
221 pdc
->dcattr
.iMapMode
= MM_TEXT
;
222 pdc
->dcattr
.dwLayout
= 0;
223 pdc
->dcattr
.flXform
= PAGE_TO_DEVICE_SCALE_IDENTITY
|
224 PAGE_TO_DEVICE_IDENTITY
|
225 WORLD_TO_PAGE_IDENTITY
;
227 /* Setup more coordinates */
228 pdc
->ptlDCOrig
.x
= 0;
229 pdc
->ptlDCOrig
.y
= 0;
230 pdc
->dcattr
.lWindowOrgx
= 0;
231 pdc
->dcattr
.ptlWindowOrg
.x
= 0;
232 pdc
->dcattr
.ptlWindowOrg
.y
= 0;
233 pdc
->dcattr
.szlWindowExt
.cx
= 1;
234 pdc
->dcattr
.szlWindowExt
.cy
= 1;
235 pdc
->dcattr
.ptlViewportOrg
.x
= 0;
236 pdc
->dcattr
.ptlViewportOrg
.y
= 0;
237 pdc
->dcattr
.szlViewportExt
.cx
= 1;
238 pdc
->dcattr
.szlViewportExt
.cy
= 1;
239 pdc
->dcattr
.szlVirtualDevicePixel
.cx
= ppdev
->gdiinfo
.ulHorzRes
;
240 pdc
->dcattr
.szlVirtualDevicePixel
.cy
= ppdev
->gdiinfo
.ulVertRes
;
241 pdc
->dcattr
.szlVirtualDeviceMm
.cx
= ppdev
->gdiinfo
.ulHorzSize
;
242 pdc
->dcattr
.szlVirtualDeviceMm
.cy
= ppdev
->gdiinfo
.ulVertSize
;
243 pdc
->dcattr
.szlVirtualDeviceSize
.cx
= 0;
244 pdc
->dcattr
.szlVirtualDeviceSize
.cy
= 0;
249 pdc
->dclevel
.prgnClip
= NULL
;
250 pdc
->dclevel
.prgnMeta
= NULL
;
251 /* Allocate a Vis region */
252 pdc
->prgnVis
= IntSysCreateRectpRgn(0, 0, pdc
->dclevel
.sizl
.cx
, pdc
->dclevel
.sizl
.cy
);
253 ASSERT(pdc
->prgnVis
);
255 /* Setup Vis Region Attribute information */
258 /* Initialize Clip object */
259 IntEngInitClipObj(&pdc
->co
);
262 pdc
->dclevel
.hpal
= StockObjects
[DEFAULT_PALETTE
];
263 pdc
->dclevel
.ppal
= PALETTE_ShareLockPalette(pdc
->dclevel
.hpal
);
266 pdc
->dclevel
.hPath
= NULL
;
267 pdc
->dclevel
.flPath
= 0;
268 // pdc->dclevel.lapath:
271 pdc
->dcattr
.crBackgroundClr
= RGB(0xff, 0xff, 0xff);
272 pdc
->dcattr
.ulBackgroundClr
= RGB(0xff, 0xff, 0xff);
273 pdc
->dcattr
.crForegroundClr
= RGB(0, 0, 0);
274 pdc
->dcattr
.ulForegroundClr
= RGB(0, 0, 0);
275 pdc
->dcattr
.crBrushClr
= RGB(0xff, 0xff, 0xff);
276 pdc
->dcattr
.ulBrushClr
= RGB(0xff, 0xff, 0xff);
277 pdc
->dcattr
.crPenClr
= RGB(0, 0, 0);
278 pdc
->dcattr
.ulPenClr
= RGB(0, 0, 0);
280 /* Select the default fill and line brush */
281 pdc
->dcattr
.hbrush
= StockObjects
[WHITE_BRUSH
];
282 pdc
->dcattr
.hpen
= StockObjects
[BLACK_PEN
];
283 pdc
->dclevel
.pbrFill
= BRUSH_ShareLockBrush(pdc
->pdcattr
->hbrush
);
284 pdc
->dclevel
.pbrLine
= PEN_ShareLockPen(pdc
->pdcattr
->hpen
);
285 pdc
->dclevel
.ptlBrushOrigin
.x
= 0;
286 pdc
->dclevel
.ptlBrushOrigin
.y
= 0;
287 pdc
->dcattr
.ptlBrushOrigin
= pdc
->dclevel
.ptlBrushOrigin
;
289 /* Initialize EBRUSHOBJs */
290 EBRUSHOBJ_vInitFromDC(&pdc
->eboFill
, pdc
->dclevel
.pbrFill
, pdc
);
291 EBRUSHOBJ_vInitFromDC(&pdc
->eboLine
, pdc
->dclevel
.pbrLine
, pdc
);
292 EBRUSHOBJ_vInitFromDC(&pdc
->eboText
, pbrDefaultBrush
, pdc
);
293 EBRUSHOBJ_vInitFromDC(&pdc
->eboBackground
, pbrDefaultBrush
, pdc
);
295 /* Setup fill data */
296 pdc
->dcattr
.jROP2
= R2_COPYPEN
;
297 pdc
->dcattr
.jBkMode
= 2;
298 pdc
->dcattr
.lBkMode
= 2;
299 pdc
->dcattr
.jFillMode
= ALTERNATE
;
300 pdc
->dcattr
.lFillMode
= 1;
301 pdc
->dcattr
.jStretchBltMode
= 1;
302 pdc
->dcattr
.lStretchBltMode
= 1;
303 pdc
->ptlFillOrigin
.x
= 0;
304 pdc
->ptlFillOrigin
.y
= 0;
306 /* Setup drawing position */
307 pdc
->dcattr
.ptlCurrent
.x
= 0;
308 pdc
->dcattr
.ptlCurrent
.y
= 0;
309 pdc
->dcattr
.ptfxCurrent
.x
= 0;
310 pdc
->dcattr
.ptfxCurrent
.y
= 0;
313 pdc
->dclevel
.lIcmMode
= 0;
314 pdc
->dcattr
.lIcmMode
= 0;
315 pdc
->dcattr
.hcmXform
= NULL
;
316 pdc
->dcattr
.flIcmFlags
= 0;
317 pdc
->dcattr
.IcmBrushColor
= CLR_INVALID
;
318 pdc
->dcattr
.IcmPenColor
= CLR_INVALID
;
319 pdc
->dcattr
.pvLIcm
= NULL
;
320 pdc
->dcattr
.hColorSpace
= NULL
; // FIXME: 0189001f
321 pdc
->dclevel
.pColorSpace
= NULL
; // FIXME
322 pdc
->pClrxFormLnk
= NULL
;
325 /* Setup font data */
326 pdc
->hlfntCur
= NULL
; // FIXME: 2f0a0cf8
327 pdc
->pPFFList
= NULL
;
328 pdc
->flSimulationFlags
= 0;
329 pdc
->lEscapement
= 0;
331 pdc
->dcattr
.flFontMapper
= 0;
332 pdc
->dcattr
.flTextAlign
= 0;
333 pdc
->dcattr
.lTextAlign
= 0;
334 pdc
->dcattr
.lTextExtra
= 0;
335 pdc
->dcattr
.lRelAbs
= 1;
336 pdc
->dcattr
.lBreakExtra
= 0;
337 pdc
->dcattr
.cBreak
= 0;
338 pdc
->dcattr
.hlfntNew
= StockObjects
[SYSTEM_FONT
];
339 pdc
->dclevel
.plfnt
= LFONT_ShareLockFont(pdc
->dcattr
.hlfntNew
);
345 pdc
->ulCopyCount
= -1;
346 pdc
->ptlDoBanding
.x
= 0;
347 pdc
->ptlDoBanding
.y
= 0;
348 pdc
->dclevel
.lSaveDepth
= 1;
349 pdc
->dclevel
.hdcSave
= NULL
;
350 pdc
->dcattr
.iGraphicsMode
= GM_COMPATIBLE
;
351 pdc
->dcattr
.iCS_CP
= 0;
352 pdc
->pSurfInfo
= NULL
;
357 DC_vCleanup(PVOID ObjectBody
)
359 PDC pdc
= (PDC
)ObjectBody
;
364 /* Delete saved DCs */
365 DC_vRestoreDC(pdc
, 1);
367 /* Deselect dc objects */
368 DC_vSelectSurface(pdc
, NULL
);
369 DC_vSelectFillBrush(pdc
, NULL
);
370 DC_vSelectLineBrush(pdc
, NULL
);
371 DC_vSelectPalette(pdc
, NULL
);
373 /* Cleanup the dc brushes */
374 EBRUSHOBJ_vCleanup(&pdc
->eboFill
);
375 EBRUSHOBJ_vCleanup(&pdc
->eboLine
);
376 EBRUSHOBJ_vCleanup(&pdc
->eboText
);
377 EBRUSHOBJ_vCleanup(&pdc
->eboBackground
);
380 if (pdc
->dclevel
.plfnt
)
381 LFONT_ShareUnlockFont(pdc
->dclevel
.plfnt
);
384 if (pdc
->dclevel
.prgnClip
)
385 REGION_Delete(pdc
->dclevel
.prgnClip
);
386 if (pdc
->dclevel
.prgnMeta
)
387 REGION_Delete(pdc
->dclevel
.prgnMeta
);
389 REGION_Delete(pdc
->prgnVis
);
391 REGION_Delete(pdc
->prgnRao
);
393 REGION_Delete(pdc
->prgnAPI
);
395 /* Free CLIPOBJ resources */
396 IntEngFreeClipResources(&pdc
->co
);
398 if (pdc
->dclevel
.hPath
)
400 DPRINT("DC_vCleanup Path\n");
401 PATH_Delete(pdc
->dclevel
.hPath
);
402 pdc
->dclevel
.hPath
= 0;
403 pdc
->dclevel
.flPath
= 0;
405 if (pdc
->dclevel
.pSurface
)
406 SURFACE_ShareUnlockSurface(pdc
->dclevel
.pSurface
);
409 PDEVOBJ_vRelease(pdc
->ppdev
);
414 DC_vSetOwner(PDC pdc
, ULONG ulOwner
)
416 /* Delete saved DCs */
417 DC_vRestoreDC(pdc
, 1);
419 if (pdc
->dclevel
.hPath
)
421 GreSetObjectOwner(pdc
->dclevel
.hPath
, ulOwner
);
424 /* Dereference current brush and pen */
425 BRUSH_ShareUnlockBrush(pdc
->dclevel
.pbrFill
);
426 BRUSH_ShareUnlockBrush(pdc
->dclevel
.pbrLine
);
428 /* Select the default fill and line brush */
429 pdc
->dcattr
.hbrush
= StockObjects
[WHITE_BRUSH
];
430 pdc
->dcattr
.hpen
= StockObjects
[BLACK_PEN
];
431 pdc
->dclevel
.pbrFill
= BRUSH_ShareLockBrush(pdc
->pdcattr
->hbrush
);
432 pdc
->dclevel
.pbrLine
= PEN_ShareLockPen(pdc
->pdcattr
->hpen
);
434 /* Mark them as dirty */
435 pdc
->pdcattr
->ulDirty_
|= DIRTY_FILL
|DIRTY_LINE
;
437 /* Allocate or free DC attribute */
438 if (ulOwner
== GDI_OBJ_HMGR_PUBLIC
|| ulOwner
== GDI_OBJ_HMGR_NONE
)
440 if (pdc
->pdcattr
!= &pdc
->dcattr
)
443 else if (ulOwner
== GDI_OBJ_HMGR_POWNED
)
445 if (pdc
->pdcattr
== &pdc
->dcattr
)
446 DC_bAllocDcAttr(pdc
);
449 /* Set the DC's ownership */
450 GDIOBJ_vSetObjectOwner(&pdc
->BaseObject
, ulOwner
);
455 GreSetDCOwner(HDC hdc
, ULONG ulOwner
)
459 pdc
= DC_LockDc(hdc
);
462 DPRINT1("GreSetDCOwner: Could not lock DC\n");
466 /* Call the internal DC function */
467 DC_vSetOwner(pdc
, ulOwner
);
475 DC_vUpdateDC(PDC pdc
)
478 PPDEVOBJ ppdev
= pdc
->ppdev
;
480 pdc
->dhpdev
= ppdev
->dhpdev
;
482 SURFACE_ShareUnlockSurface(pdc
->dclevel
.pSurface
);
483 pdc
->dclevel
.pSurface
= PDEVOBJ_pSurface(ppdev
);
485 PDEVOBJ_sizl(pdc
->ppdev
, &pdc
->dclevel
.sizl
);
487 VisRgn
= IntSysCreateRectpRgn(0, 0, pdc
->dclevel
.sizl
.cx
, pdc
->dclevel
.sizl
.cy
);
489 GdiSelectVisRgn(pdc
->BaseObject
.hHmgr
, VisRgn
);
490 REGION_Delete(VisRgn
);
493 pdc
->flGraphicsCaps
= ppdev
->devinfo
.flGraphicsCaps
;
494 pdc
->flGraphicsCaps2
= ppdev
->devinfo
.flGraphicsCaps2
;
496 /* Mark EBRUSHOBJs as dirty */
497 pdc
->pdcattr
->ulDirty_
|= DIRTY_DEFAULT
;
500 /* Prepare a blit for up to 2 DCs */
501 /* rc1 and rc2 are the rectangles where we want to draw or
502 * from where we take pixels. */
505 DC_vPrepareDCsForBlit(
511 PDC pdcFirst
, pdcSecond
;
512 const RECT
*prcFirst
, *prcSecond
;
515 if (pdcDest
->pdcattr
->ulDirty_
& (DIRTY_FILL
| DC_BRUSH_DIRTY
))
516 DC_vUpdateFillBrush(pdcDest
);
517 if (pdcDest
->pdcattr
->ulDirty_
& (DIRTY_LINE
| DC_PEN_DIRTY
))
518 DC_vUpdateLineBrush(pdcDest
);
519 if(pdcDest
->pdcattr
->ulDirty_
& DIRTY_TEXT
)
520 DC_vUpdateTextBrush(pdcDest
);
522 /* Lock them in good order */
525 if((ULONG_PTR
)pdcDest
->ppdev
->hsemDevLock
>=
526 (ULONG_PTR
)pdcSrc
->ppdev
->hsemDevLock
)
549 if (pdcDest
->fs
& DC_FLAG_DIRTY_RAO
)
550 CLIPPING_UpdateGCRegion(pdcDest
);
552 /* Lock and update first DC */
553 if (pdcFirst
->dctype
== DCTYPE_DIRECT
)
555 EngAcquireSemaphore(pdcFirst
->ppdev
->hsemDevLock
);
557 /* Update surface if needed */
558 if (pdcFirst
->ppdev
->pSurface
!= pdcFirst
->dclevel
.pSurface
)
560 DC_vUpdateDC(pdcFirst
);
564 if (pdcFirst
->dctype
== DCTYPE_DIRECT
)
567 prcFirst
= &pdcFirst
->erclClip
;
569 MouseSafetyOnDrawStart(pdcFirst
->ppdev
,
577 pdcFirst
->fs
|= DC_PREPARED
;
583 /* Lock and update second DC */
584 if (pdcSecond
->dctype
== DCTYPE_DIRECT
)
586 EngAcquireSemaphore(pdcSecond
->ppdev
->hsemDevLock
);
588 /* Update surface if needed */
589 if (pdcSecond
->ppdev
->pSurface
!= pdcSecond
->dclevel
.pSurface
)
591 DC_vUpdateDC(pdcSecond
);
595 if (pdcSecond
->dctype
== DCTYPE_DIRECT
)
598 prcSecond
= &pdcSecond
->erclClip
;
599 MouseSafetyOnDrawStart(pdcSecond
->ppdev
,
607 pdcSecond
->fs
|= DC_PREPARED
;
611 /* Finishes a blit for one or two DCs */
614 DC_vFinishBlit(PDC pdc1
, PDC pdc2
)
616 if (pdc1
->dctype
== DCTYPE_DIRECT
)
618 MouseSafetyOnDrawEnd(pdc1
->ppdev
);
619 EngReleaseSemaphore(pdc1
->ppdev
->hsemDevLock
);
622 pdc1
->fs
&= ~DC_PREPARED
;
627 if (pdc2
->dctype
== DCTYPE_DIRECT
)
629 MouseSafetyOnDrawEnd(pdc2
->ppdev
);
630 EngReleaseSemaphore(pdc2
->ppdev
->hsemDevLock
);
633 pdc2
->fs
&= ~DC_PREPARED
;
641 PUNICODE_STRING pustrDevice
,
643 PUNICODE_STRING pustrLogAddr
,
654 DPRINT("GreOpenDCW(%S, iType=%lu)\n",
655 pustrDevice
? pustrDevice
->Buffer
: NULL
, iType
);
657 /* Get a PDEVOBJ for the device */
658 ppdev
= EngpGetPDEV(pustrDevice
);
661 DPRINT1("Didn't find a suitable PDEV\n");
665 DPRINT("GreOpenDCW - ppdev = %p\n", ppdev
);
667 pdc
= DC_AllocDcWithHandle(GDILoObjType_LO_DC_TYPE
);
670 DPRINT1("Could not Allocate a DC\n");
671 PDEVOBJ_vRelease(ppdev
);
674 hdc
= pdc
->BaseObject
.hHmgr
;
676 /* Lock ppdev and initialize the new DC */
677 DC_vInitDc(pdc
, iType
, ppdev
);
678 if (pUMdhpdev
) *pUMdhpdev
= ppdev
->dhpdev
;
682 DC_bAllocDcAttr(pdc
);
686 DPRINT("Returning hdc = %p\n", hdc
);
695 _In_opt_ PUNICODE_STRING pustrDevice
,
696 _In_ DEVMODEW
*pdmInit
,
697 _In_ PUNICODE_STRING pustrLogAddr
,
700 _In_opt_ HANDLE hspool
,
701 /*_In_opt_ DRIVER_INFO2W *pdDriverInfo2, Need this soon!!!! */
702 _At_((PUMDHPDEV
*)pUMdhpdev
, _Out_
) PVOID pUMdhpdev
)
704 UNICODE_STRING ustrDevice
;
705 WCHAR awcDevice
[CCHDEVICENAME
];
708 WORD dmSize
, dmDriverExtra
;
710 DEVMODEW
* _SEH2_VOLATILE pdmAllocated
= NULL
;
712 /* Only if a devicename is given, we need any data */
715 /* Initialize destination string */
716 RtlInitEmptyUnicodeString(&ustrDevice
, awcDevice
, sizeof(awcDevice
));
720 /* Probe the UNICODE_STRING and the buffer */
721 ProbeForRead(pustrDevice
, sizeof(UNICODE_STRING
), 1);
722 ProbeForRead(pustrDevice
->Buffer
, pustrDevice
->Length
, 1);
724 /* Copy the string */
725 RtlCopyUnicodeString(&ustrDevice
, pustrDevice
);
727 /* Allocate and store pdmAllocated if pdmInit is not NULL */
730 ProbeForRead(pdmInit
, sizeof(DEVMODEW
), 1);
732 dmSize
= pdmInit
->dmSize
;
733 dmDriverExtra
= pdmInit
->dmDriverExtra
;
734 Size
= dmSize
+ dmDriverExtra
;
735 ProbeForRead(pdmInit
, Size
, 1);
737 pdmAllocated
= ExAllocatePoolWithTag(PagedPool
| POOL_RAISE_IF_ALLOCATION_FAILURE
,
740 RtlCopyMemory(pdmAllocated
, pdmInit
, Size
);
741 pdmAllocated
->dmSize
= dmSize
;
742 pdmAllocated
->dmDriverExtra
= dmDriverExtra
;
747 ProbeForWrite(pUMdhpdev
, sizeof(HANDLE
), 1);
750 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
754 ExFreePoolWithTag(pdmAllocated
, TAG_DC
);
756 SetLastNtError(_SEH2_GetExceptionCode());
757 _SEH2_YIELD(return NULL
);
765 // return UserGetDesktopDC(iType, FALSE, TRUE);
771 UNICODE_STRING ustrDISPLAY
= RTL_CONSTANT_STRING(L
"DISPLAY");
772 if (RtlEqualUnicodeString(&ustrDevice
, &ustrDISPLAY
, TRUE
))
778 /* Call the internal function */
779 hdc
= GreOpenDCW(pustrDevice
? &ustrDevice
: NULL
,
781 NULL
, // FIXME: pwszLogAddress
785 NULL
, // FIXME: pDriverInfo2
786 pUMdhpdev
? &dhpdev
: NULL
);
788 /* If we got a HDC and a UM dhpdev is requested,... */
789 if (hdc
&& pUMdhpdev
)
791 /* Copy dhpdev to caller */
794 /* Pointer was already probed */
795 *(HANDLE
*)pUMdhpdev
= dhpdev
;
797 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
805 /* Free the allocated */
808 ExFreePoolWithTag(pdmAllocated
, TAG_DC
);
817 GreCreateCompatibleDC(HDC hdc
, BOOL bAltDc
)
819 GDILOOBJTYPE eDcObjType
;
824 DPRINT("NtGdiCreateCompatibleDC(0x%p)\n", hdc
);
826 /* Did the caller provide a DC? */
829 /* Yes, try to lock it */
830 pdc
= DC_LockDc(hdc
);
833 DPRINT1("Could not lock source DC %p\n", hdc
);
837 /* Get the pdev from the DC */
839 InterlockedIncrement(&ppdev
->cPdevRefs
);
841 /* Unlock the source DC */
846 /* No DC given, get default device */
847 ppdev
= EngpGetPDEV(NULL
);
852 DPRINT1("Didn't find a suitable PDEV\n");
856 /* Allocate a new DC */
857 eDcObjType
= bAltDc
? GDILoObjType_LO_ALTDC_TYPE
: GDILoObjType_LO_DC_TYPE
;
858 pdcNew
= DC_AllocDcWithHandle(eDcObjType
);
861 DPRINT1("Could not allocate a new DC\n");
862 PDEVOBJ_vRelease(ppdev
);
865 hdcNew
= pdcNew
->BaseObject
.hHmgr
;
867 /* Lock ppdev and initialize the new DC */
868 DC_vInitDc(pdcNew
, bAltDc
? DCTYPE_INFO
: DCTYPE_MEMORY
, ppdev
);
872 /* Allocate a dc attribute */
873 DC_bAllocDcAttr(pdcNew
);
877 DPRINT("Leave NtGdiCreateCompatibleDC hdcNew = %p\n", hdcNew
);
884 NtGdiCreateCompatibleDC(HDC hdc
)
886 /* Call the internal function to create a normal memory DC */
887 return GreCreateCompatibleDC(hdc
, FALSE
);
892 IntGdiDeleteDC(HDC hDC
, BOOL Force
)
894 PDC DCToDelete
= DC_LockDc(hDC
);
896 if (DCToDelete
== NULL
)
898 EngSetLastError(ERROR_INVALID_HANDLE
);
904 /* Windows permits NtGdiDeleteObjectApp to delete a permanent DC
905 * For some reason, it's still a valid handle, pointing to some kernel data.
906 * Not sure if this is a bug, a feature, some cache stuff... Who knows?
907 * See NtGdiDeleteObjectApp test for details */
908 if (DCToDelete
->fs
& DC_FLAG_PERMANENT
)
910 DC_UnlockDc(DCToDelete
);
911 if(UserReleaseDC(NULL
, hDC
, FALSE
))
913 /* ReactOS feature: Call UserReleaseDC
914 * I don't think Windows does it.
915 * Still, complain, no one should ever call DeleteDC
917 DPRINT1("No, you naughty application!\n");
922 /* This is not a window owned DC.
923 * Force its deletion */
924 return IntGdiDeleteDC(hDC
, TRUE
);
929 DC_UnlockDc(DCToDelete
);
931 if (GreIsHandleValid(hDC
))
933 if (!GreDeleteObject(hDC
))
935 DPRINT1("DC_FreeDC failed\n");
941 DPRINT1("Attempted to Delete 0x%p currently being destroyed!!!\n", hDC
);
950 NtGdiDeleteObjectApp(HANDLE hobj
)
952 /* Complete all pending operations */
953 NtGdiFlushUserBatch(); // FIXME: We shouldn't need this
955 if (GDI_HANDLE_IS_STOCKOBJ(hobj
)) return TRUE
;
957 if (GreGetObjectOwner(hobj
) != GDI_OBJ_HMGR_POWNED
)
959 EngSetLastError(ERROR_INVALID_HANDLE
);
963 if (GDI_HANDLE_GET_TYPE(hobj
) != GDI_OBJECT_TYPE_DC
)
964 return GreDeleteObject(hobj
);
966 // FIXME: Everything should be callback based
967 return IntGdiDeleteDC(hobj
, FALSE
);
972 MakeInfoDC(PDC pdc
, BOOL bSet
)
977 /* Can not be a display DC. */
978 if (pdc
->fs
& DC_FLAG_DISPLAY
) return FALSE
;
981 if (pdc
->fs
& DC_FLAG_TEMPINFODC
|| pdc
->dctype
== DC_TYPE_DIRECT
)
984 pSurface
= pdc
->dclevel
.pSurface
;
985 pdc
->fs
|= DC_FLAG_TEMPINFODC
;
986 pdc
->pSurfInfo
= pSurface
;
987 pdc
->dctype
= DC_TYPE_INFO
;
988 pdc
->dclevel
.pSurface
= NULL
;
990 PDEVOBJ_sizl(pdc
->ppdev
, &sizl
);
992 if ( sizl
.cx
== pdc
->dclevel
.sizl
.cx
&&
993 sizl
.cy
== pdc
->dclevel
.sizl
.cy
)
996 pdc
->dclevel
.sizl
.cx
= sizl
.cx
;
997 pdc
->dclevel
.sizl
.cy
= sizl
.cy
;
1001 if (!(pdc
->fs
& DC_FLAG_TEMPINFODC
) || pdc
->dctype
!= DC_TYPE_INFO
)
1004 pSurface
= pdc
->pSurfInfo
;
1005 pdc
->fs
&= ~DC_FLAG_TEMPINFODC
;
1006 pdc
->dclevel
.pSurface
= pSurface
;
1007 pdc
->dctype
= DC_TYPE_DIRECT
;
1008 pdc
->pSurfInfo
= NULL
;
1011 (pSurface
->SurfObj
.sizlBitmap
.cx
== pdc
->dclevel
.sizl
.cx
&&
1012 pSurface
->SurfObj
.sizlBitmap
.cy
== pdc
->dclevel
.sizl
.cy
) )
1015 pdc
->dclevel
.sizl
.cx
= pSurface
->SurfObj
.sizlBitmap
.cx
;
1016 pdc
->dclevel
.sizl
.cy
= pSurface
->SurfObj
.sizlBitmap
.cy
;
1018 return IntSetDefaultRegion(pdc
);
1031 PDC pdc
= DC_LockDc(hdc
);
1034 Ret
= MakeInfoDC(pdc
, bSet
);
1044 PUNICODE_STRING Driver
,
1045 PUNICODE_STRING pustrDevice
,
1047 CONST PDEVMODEW pdmInit
,
1052 hdc
= GreOpenDCW(pustrDevice
,
1055 CreateAsIC
? DCTYPE_INFO
:
1056 (Driver
? DC_TYPE_DIRECT
: DC_TYPE_DIRECT
),
1066 IntGdiCreateDisplayDC(HDEV hDev
, ULONG DcType
, BOOL EmptyDC
)
1072 if (DcType
== DC_TYPE_MEMORY
)
1073 hDC
= NtGdiCreateCompatibleDC(NULL
); // OH~ Yuck! I think I taste vomit in my mouth!
1075 hDC
= IntGdiCreateDC(NULL
, NULL
, NULL
, NULL
, (DcType
== DC_TYPE_INFO
));