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)
15 //FIXME: windows uses 0x0012009f
16 #define DIRTY_DEFAULT DIRTY_CHARSET|DIRTY_BACKGROUND|DIRTY_TEXT|DIRTY_LINE|DIRTY_FILL
18 PSURFACE psurfDefaultBitmap
= NULL
;
19 PBRUSH pbrDefaultBrush
= NULL
;
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}
27 static const FLOATOBJ gef0
= FLOATOBJ_0
;
28 static const FLOATOBJ gef1
= FLOATOBJ_1
;
29 static const FLOATOBJ gef16
= FLOATOBJ_16
;
31 static const MATRIX gmxWorldToDeviceDefault
=
33 FLOATOBJ_16
, FLOATOBJ_0
,
34 FLOATOBJ_0
, FLOATOBJ_16
,
35 FLOATOBJ_0
, FLOATOBJ_0
,
39 static const MATRIX gmxDeviceToWorldDefault
=
41 FLOATOBJ_1_16
, FLOATOBJ_0
,
42 FLOATOBJ_0
, FLOATOBJ_1_16
,
43 FLOATOBJ_0
, FLOATOBJ_0
,
47 static const MATRIX gmxWorldToPageDefault
=
49 FLOATOBJ_1
, FLOATOBJ_0
,
50 FLOATOBJ_0
, FLOATOBJ_1
,
51 FLOATOBJ_0
, FLOATOBJ_0
,
55 // HACK!! Fix XFORMOBJ then use 1:16 / 16:1
56 #define gmxWorldToDeviceDefault gmxWorldToPageDefault
57 #define gmxDeviceToWorldDefault gmxWorldToPageDefault
59 /** Internal functions ********************************************************/
66 psurfDefaultBitmap
= SURFACE_ShareLockSurface(StockObjects
[DEFAULT_BITMAP
]);
67 if (!psurfDefaultBitmap
)
68 return STATUS_UNSUCCESSFUL
;
70 pbrDefaultBrush
= BRUSH_ShareLockBrush(StockObjects
[BLACK_BRUSH
]);
72 return STATUS_UNSUCCESSFUL
;
74 return STATUS_SUCCESS
;
80 DC_AllocDcWithHandle()
83 pdc
= (PDC
)GDIOBJ_AllocObjWithHandle(GDILoObjType_LO_DC_TYPE
);
85 pdc
->pdcattr
= &pdc
->dcattr
;
94 TextIntRealizeFont(pdc
->pdcattr
->hlfntNew
,NULL
);
95 pdc
->pdcattr
->iCS_CP
= ftGdiGetTextCharsetInfo(pdc
,NULL
,0);
97 /* This should never fail */
98 ASSERT(pdc
->dclevel
.ppal
);
101 pdc
->rosdc
.hClipRgn
= NULL
;
102 pdc
->rosdc
.hGCClipRgn
= NULL
;
112 /* Setup some basic fields */
113 pdc
->dctype
= dctype
;
115 pdc
->dhpdev
= ppdev
->dhpdev
;
116 pdc
->hsem
= ppdev
->hsemDevLock
;
117 pdc
->flGraphicsCaps
= ppdev
->devinfo
.flGraphicsCaps
;
118 pdc
->flGraphicsCaps2
= ppdev
->devinfo
.flGraphicsCaps2
;
119 pdc
->fs
= DC_DIRTY_RAO
;
121 /* Setup dc attribute */
122 pdc
->pdcattr
= &pdc
->dcattr
;
123 pdc
->dcattr
.pvLDC
= NULL
;
124 pdc
->dcattr
.ulDirty_
= DIRTY_DEFAULT
;
125 if (ppdev
== gppdevPrimary
)
126 pdc
->dcattr
.ulDirty_
|= DC_PRIMARY_DISPLAY
;
128 /* Setup the DC size */
129 if (dctype
== DCTYPE_MEMORY
)
131 /* Memory DCs have a 1 x 1 bitmap by default */
132 pdc
->dclevel
.sizl
.cx
= 1;
133 pdc
->dclevel
.sizl
.cy
= 1;
137 /* Other DC's are as big as the related PDEV */
138 pdc
->dclevel
.sizl
.cx
= ppdev
->gdiinfo
.ulHorzRes
;
139 pdc
->dclevel
.sizl
.cy
= ppdev
->gdiinfo
.ulVertRes
;
142 /* Setup Window rect based on DC size */
143 pdc
->erclWindow
.left
= 0;
144 pdc
->erclWindow
.top
= 0;
145 pdc
->erclWindow
.right
= pdc
->dclevel
.sizl
.cx
;
146 pdc
->erclWindow
.bottom
= pdc
->dclevel
.sizl
.cy
;
148 if (dctype
== DCTYPE_DIRECT
)
150 /* Direct DCs get the surface from the PDEV */
151 pdc
->dclevel
.pSurface
= PDEVOBJ_pSurface(ppdev
);
153 pdc
->erclBounds
.left
= 0x7fffffff;
154 pdc
->erclBounds
.top
= 0x7fffffff;
155 pdc
->erclBounds
.right
= 0x80000000;
156 pdc
->erclBounds
.bottom
= 0x80000000;
157 pdc
->erclBoundsApp
.left
= 0xffffffff;
158 pdc
->erclBoundsApp
.top
= 0xfffffffc;
159 pdc
->erclBoundsApp
.right
= 0x00007ffc; // FIXME
160 pdc
->erclBoundsApp
.bottom
= 0x00000333; // FIXME
161 pdc
->erclClip
= pdc
->erclBounds
;
164 pdc
->fs
|= DC_SYNCHRONIZEACCESS
| DC_ACCUM_APP
| DC_PERMANANT
| DC_DISPLAY
;
168 /* Non-direct DCs don't have a surface by default */
169 pdc
->dclevel
.pSurface
= NULL
;
171 // FIXME: HACK, because our code expects a surface
172 pdc
->dclevel
.pSurface
= SURFACE_ShareLockSurface(StockObjects
[DEFAULT_BITMAP
]);
174 pdc
->erclBounds
.left
= 0;
175 pdc
->erclBounds
.top
= 0;
176 pdc
->erclBounds
.right
= 0;
177 pdc
->erclBounds
.bottom
= 0;
178 pdc
->erclBoundsApp
= pdc
->erclBounds
;
179 pdc
->erclClip
= pdc
->erclWindow
;
183 // pdc->dcattr.VisRectRegion:
185 /* Setup coordinate transformation data */
186 pdc
->dclevel
.mxWorldToDevice
= gmxWorldToDeviceDefault
;
187 pdc
->dclevel
.mxDeviceToWorld
= gmxDeviceToWorldDefault
;
188 pdc
->dclevel
.mxWorldToPage
= gmxWorldToPageDefault
;
189 pdc
->dclevel
.efM11PtoD
= gef16
;
190 pdc
->dclevel
.efM22PtoD
= gef16
;
191 pdc
->dclevel
.efDxPtoD
= gef0
;
192 pdc
->dclevel
.efDyPtoD
= gef0
;
193 pdc
->dclevel
.efM11_TWIPS
= gef0
;
194 pdc
->dclevel
.efM22_TWIPS
= gef0
;
195 pdc
->dclevel
.efPr11
= gef0
;
196 pdc
->dclevel
.efPr22
= gef0
;
197 pdc
->dcattr
.mxWorldToDevice
= pdc
->dclevel
.mxWorldToDevice
;
198 pdc
->dcattr
.mxDeviceToWorld
= pdc
->dclevel
.mxDeviceToWorld
;
199 pdc
->dcattr
.mxWorldToPage
= pdc
->dclevel
.mxWorldToPage
;
200 pdc
->dcattr
.efM11PtoD
= pdc
->dclevel
.efM11PtoD
;
201 pdc
->dcattr
.efM22PtoD
= pdc
->dclevel
.efM22PtoD
;
202 pdc
->dcattr
.efDxPtoD
= pdc
->dclevel
.efDxPtoD
;
203 pdc
->dcattr
.efDyPtoD
= pdc
->dclevel
.efDyPtoD
;
204 pdc
->dcattr
.iMapMode
= MM_TEXT
;
205 pdc
->dcattr
.dwLayout
= 0;
206 pdc
->dcattr
.flXform
= PAGE_TO_DEVICE_SCALE_IDENTITY
|
207 PAGE_TO_DEVICE_IDENTITY
|
208 WORLD_TO_PAGE_IDENTITY
;
210 /* Setup more coordinates */
211 pdc
->ptlDCOrig
.x
= 0;
212 pdc
->ptlDCOrig
.y
= 0;
213 pdc
->dcattr
.lWindowOrgx
= 0;
214 pdc
->dcattr
.ptlWindowOrg
.x
= 0;
215 pdc
->dcattr
.ptlWindowOrg
.y
= 0;
216 pdc
->dcattr
.szlWindowExt
.cx
= 1;
217 pdc
->dcattr
.szlWindowExt
.cy
= 1;
218 pdc
->dcattr
.ptlViewportOrg
.x
= 0;
219 pdc
->dcattr
.ptlViewportOrg
.y
= 0;
220 pdc
->dcattr
.szlViewportExt
.cx
= 1;
221 pdc
->dcattr
.szlViewportExt
.cy
= 1;
222 pdc
->dcattr
.szlVirtualDevicePixel
.cx
= ppdev
->gdiinfo
.ulHorzRes
;
223 pdc
->dcattr
.szlVirtualDevicePixel
.cy
= ppdev
->gdiinfo
.ulVertRes
;
224 pdc
->dcattr
.szlVirtualDeviceMm
.cx
= ppdev
->gdiinfo
.ulHorzSize
;
225 pdc
->dcattr
.szlVirtualDeviceMm
.cy
= ppdev
->gdiinfo
.ulVertSize
;
226 pdc
->dcattr
.szlVirtualDeviceSize
.cx
= 0;
227 pdc
->dcattr
.szlVirtualDeviceSize
.cy
= 0;
232 /* Allocate a Vis region */
233 pdc
->prgnVis
= IntSysCreateRectpRgn(0, 0, pdc
->dclevel
.sizl
.cx
, pdc
->dclevel
.sizl
.cy
);
234 ASSERT(pdc
->prgnVis
);
235 GDIOBJ_CopyOwnership(pdc
->BaseObject
.hHmgr
, pdc
->prgnVis
->BaseObject
.hHmgr
);
238 pdc
->dclevel
.hpal
= StockObjects
[DEFAULT_PALETTE
];
239 pdc
->dclevel
.ppal
= PALETTE_ShareLockPalette(pdc
->dclevel
.hpal
);
242 pdc
->dclevel
.hPath
= NULL
;
243 pdc
->dclevel
.flPath
= 0;
244 // pdc->dclevel.lapath:
247 pdc
->dcattr
.crBackgroundClr
= RGB(0xff, 0xff, 0xff);
248 pdc
->dcattr
.ulBackgroundClr
= RGB(0xff, 0xff, 0xff);
249 pdc
->dcattr
.crForegroundClr
= RGB(0, 0, 0);
250 pdc
->dcattr
.ulForegroundClr
= RGB(0, 0, 0);
251 pdc
->dcattr
.crBrushClr
= RGB(0xff, 0xff, 0xff);
252 pdc
->dcattr
.ulBrushClr
= RGB(0xff, 0xff, 0xff);
253 pdc
->dcattr
.crPenClr
= RGB(0, 0, 0);
254 pdc
->dcattr
.ulPenClr
= RGB(0, 0, 0);
256 /* Select the default fill and line brush */
257 pdc
->dcattr
.hbrush
= StockObjects
[WHITE_BRUSH
];
258 pdc
->dcattr
.hpen
= StockObjects
[BLACK_PEN
];
259 pdc
->dclevel
.pbrFill
= BRUSH_ShareLockBrush(pdc
->pdcattr
->hbrush
);
260 pdc
->dclevel
.pbrLine
= PEN_ShareLockPen(pdc
->pdcattr
->hpen
);
261 pdc
->dclevel
.ptlBrushOrigin
.x
= 0;
262 pdc
->dclevel
.ptlBrushOrigin
.y
= 0;
263 pdc
->dcattr
.ptlBrushOrigin
= pdc
->dclevel
.ptlBrushOrigin
;
265 /* Initialize EBRUSHOBJs */
266 EBRUSHOBJ_vInit(&pdc
->eboFill
, pdc
->dclevel
.pbrFill
, pdc
);
267 EBRUSHOBJ_vInit(&pdc
->eboLine
, pdc
->dclevel
.pbrLine
, pdc
);
268 EBRUSHOBJ_vInit(&pdc
->eboText
, pbrDefaultBrush
, pdc
);
269 EBRUSHOBJ_vInit(&pdc
->eboBackground
, pbrDefaultBrush
, pdc
);
271 /* Setup fill data */
272 pdc
->dcattr
.jROP2
= R2_COPYPEN
;
273 pdc
->dcattr
.jBkMode
= 2;
274 pdc
->dcattr
.lBkMode
= 2;
275 pdc
->dcattr
.jFillMode
= ALTERNATE
;
276 pdc
->dcattr
.lFillMode
= 1;
277 pdc
->dcattr
.jStretchBltMode
= 1;
278 pdc
->dcattr
.lStretchBltMode
= 1;
279 pdc
->ptlFillOrigin
.x
= 0;
280 pdc
->ptlFillOrigin
.y
= 0;
282 /* Setup drawing position */
283 pdc
->dcattr
.ptlCurrent
.x
= 0;
284 pdc
->dcattr
.ptlCurrent
.y
= 0;
285 pdc
->dcattr
.ptfxCurrent
.x
= 0;
286 pdc
->dcattr
.ptfxCurrent
.y
= 0;
289 pdc
->dclevel
.lIcmMode
= 0;
290 pdc
->dcattr
.lIcmMode
= 0;
291 pdc
->dcattr
.hcmXform
= NULL
;
292 pdc
->dcattr
.flIcmFlags
= 0;
293 pdc
->dcattr
.IcmBrushColor
= CLR_INVALID
;
294 pdc
->dcattr
.IcmPenColor
= CLR_INVALID
;
295 pdc
->dcattr
.pvLIcm
= NULL
;
296 pdc
->dcattr
.hColorSpace
= NULL
; // FIXME: 0189001f
297 pdc
->dclevel
.pColorSpace
= NULL
; // FIXME
298 pdc
->pClrxFormLnk
= NULL
;
301 /* Setup font data */
302 pdc
->hlfntCur
= NULL
; // FIXME: 2f0a0cf8
303 pdc
->pPFFList
= NULL
;
304 pdc
->flSimulationFlags
= 0;
305 pdc
->lEscapement
= 0;
307 pdc
->dcattr
.flFontMapper
= 0;
308 pdc
->dcattr
.flTextAlign
= 0;
309 pdc
->dcattr
.lTextAlign
= 0;
310 pdc
->dcattr
.lTextExtra
= 0;
311 pdc
->dcattr
.lRelAbs
= 1;
312 pdc
->dcattr
.lBreakExtra
= 0;
313 pdc
->dcattr
.cBreak
= 0;
314 pdc
->dcattr
.hlfntNew
= StockObjects
[SYSTEM_FONT
];
315 // pdc->dclevel.pFont = LFONT_ShareLockFont(pdc->dcattr.hlfntNew);
320 pdc
->ipfdDevMax
= 0x0000ffff;
321 pdc
->ulCopyCount
= -1;
322 pdc
->ptlDoBanding
.x
= 0;
323 pdc
->ptlDoBanding
.y
= 0;
324 pdc
->dclevel
.lSaveDepth
= 1;
325 pdc
->dclevel
.hdcSave
= NULL
;
326 pdc
->dcattr
.iGraphicsMode
= GM_COMPATIBLE
;
327 pdc
->dcattr
.iCS_CP
= 0;
328 pdc
->pSurfInfo
= NULL
;
334 DC_Cleanup(PVOID ObjectBody
)
336 PDC pdc
= (PDC
)ObjectBody
;
341 /* Delete saved DCs */
342 DC_vRestoreDC(pdc
, 1);
344 /* Deselect dc objects */
345 DC_vSelectSurface(pdc
, NULL
);
346 DC_vSelectFillBrush(pdc
, NULL
);
347 DC_vSelectLineBrush(pdc
, NULL
);
348 DC_vSelectPalette(pdc
, NULL
);
350 /* Cleanup the dc brushes */
351 EBRUSHOBJ_vCleanup(&pdc
->eboFill
);
352 EBRUSHOBJ_vCleanup(&pdc
->eboLine
);
353 EBRUSHOBJ_vCleanup(&pdc
->eboText
);
354 EBRUSHOBJ_vCleanup(&pdc
->eboBackground
);
357 if (pdc
->rosdc
.hClipRgn
)
358 GreDeleteObject(pdc
->rosdc
.hClipRgn
);
360 REGION_FreeRgnByHandle(pdc
->prgnVis
->BaseObject
.hHmgr
);
361 if (pdc
->rosdc
.hGCClipRgn
)
362 GreDeleteObject(pdc
->rosdc
.hGCClipRgn
);
363 if (NULL
!= pdc
->rosdc
.CombinedClip
)
364 IntEngDeleteClipRegion(pdc
->rosdc
.CombinedClip
);
366 PATH_Delete(pdc
->dclevel
.hPath
);
368 if(pdc
->dclevel
.pSurface
)
369 SURFACE_ShareUnlockSurface(pdc
->dclevel
.pSurface
);
371 PDEVOBJ_vRelease(pdc
->ppdev
) ;
378 DC_SetOwnership(HDC hDC
, PEPROCESS Owner
)
381 PGDI_TABLE_ENTRY Entry
;
385 if (!GDIOBJ_SetOwnership(hDC
, Owner
))
387 DPRINT1("GDIOBJ_SetOwnership failed\n");
391 pDC
= DC_LockDc(hDC
);
394 DPRINT1("Could not lock DC\n");
400 These regions do not use attribute sections and when allocated, use
401 gdiobj level functions.
403 if (pDC
->rosdc
.hClipRgn
)
405 Index
= GDI_HANDLE_GET_INDEX(pDC
->rosdc
.hClipRgn
);
406 Entry
= &GdiHandleTable
->Entries
[Index
];
407 if (Entry
->UserData
) FreeObjectAttr(Entry
->UserData
);
408 Entry
->UserData
= NULL
;
410 if (!GDIOBJ_SetOwnership(pDC
->rosdc
.hClipRgn
, Owner
)) goto leave
;
414 Index
= GDI_HANDLE_GET_INDEX(pDC
->prgnVis
->BaseObject
.hHmgr
);
415 Entry
= &GdiHandleTable
->Entries
[Index
];
416 if (Entry
->UserData
) FreeObjectAttr(Entry
->UserData
);
417 Entry
->UserData
= NULL
;
419 if (!GDIOBJ_SetOwnership(pDC
->prgnVis
->BaseObject
.hHmgr
, Owner
)) goto leave
;
421 if (pDC
->rosdc
.hGCClipRgn
)
423 Index
= GDI_HANDLE_GET_INDEX(pDC
->rosdc
.hGCClipRgn
);
424 Entry
= &GdiHandleTable
->Entries
[Index
];
425 if (Entry
->UserData
) FreeObjectAttr(Entry
->UserData
);
426 Entry
->UserData
= NULL
;
428 if (!GDIOBJ_SetOwnership(pDC
->rosdc
.hGCClipRgn
, Owner
)) goto leave
;
430 if (pDC
->dclevel
.hPath
)
432 if (!GDIOBJ_SetOwnership(pDC
->dclevel
.hPath
, Owner
)) goto leave
;
444 CLIPPING_UpdateGCRegion(DC
* Dc
);
448 DC_vUpdateDC(PDC pdc
)
451 PPDEVOBJ ppdev
= pdc
->ppdev
;
453 pdc
->dhpdev
= ppdev
->dhpdev
;
455 SURFACE_ShareUnlockSurface(pdc
->dclevel
.pSurface
);
456 pdc
->dclevel
.pSurface
= PDEVOBJ_pSurface(ppdev
);
458 PDEVOBJ_sizl(pdc
->ppdev
, &pdc
->dclevel
.sizl
);
459 hVisRgn
= NtGdiCreateRectRgn(0, 0, pdc
->dclevel
.sizl
.cx
, pdc
->dclevel
.sizl
.cy
);
461 GdiSelectVisRgn(pdc
->BaseObject
.hHmgr
, hVisRgn
);
462 GreDeleteObject(hVisRgn
);
464 pdc
->flGraphicsCaps
= ppdev
->devinfo
.flGraphicsCaps
;
465 pdc
->flGraphicsCaps2
= ppdev
->devinfo
.flGraphicsCaps2
;
467 /* Mark EBRUSHOBJs as dirty */
468 pdc
->pdcattr
->ulDirty_
|= DIRTY_DEFAULT
;
471 /* Prepare a blit for up to 2 DCs */
472 /* rc1 and rc2 are the rectangles where we want to draw or
473 * from where we take pixels. */
476 DC_vPrepareDCsForBlit(PDC pdc1
,
481 PDC pdcFirst
, pdcSecond
;
482 PRECT prcFirst
, prcSecond
;
485 if (pdc1
->pdcattr
->ulDirty_
& (DIRTY_FILL
| DC_BRUSH_DIRTY
))
486 DC_vUpdateFillBrush(pdc1
);
487 if (pdc1
->pdcattr
->ulDirty_
& (DIRTY_LINE
| DC_PEN_DIRTY
))
488 DC_vUpdateLineBrush(pdc1
);
489 if(pdc1
->pdcattr
->ulDirty_
& DIRTY_TEXT
)
490 DC_vUpdateTextBrush(pdc1
);
492 /* Lock them in good order */
495 if((ULONG_PTR
)pdc1
->ppdev
->hsemDevLock
>= (ULONG_PTR
)pdc2
->ppdev
->hsemDevLock
)
518 if(pdcFirst
&& pdcFirst
->dctype
== DCTYPE_DIRECT
)
520 EngAcquireSemaphore(pdcFirst
->ppdev
->hsemDevLock
);
521 MouseSafetyOnDrawStart(pdcFirst
->ppdev
,
526 /* Update surface if needed */
527 if(pdcFirst
->ppdev
->pSurface
!= pdcFirst
->dclevel
.pSurface
)
529 DC_vUpdateDC(pdcFirst
);
532 if(pdcSecond
&& pdcSecond
->dctype
== DCTYPE_DIRECT
)
534 EngAcquireSemaphore(pdcSecond
->ppdev
->hsemDevLock
);
535 MouseSafetyOnDrawStart(pdcSecond
->ppdev
,
540 /* Update surface if needed */
541 if(pdcSecond
->ppdev
->pSurface
!= pdcSecond
->dclevel
.pSurface
)
543 DC_vUpdateDC(pdcSecond
);
548 /* Finishes a blit for one or two DCs */
551 DC_vFinishBlit(PDC pdc1
, PDC pdc2
)
553 if(pdc1
->dctype
== DCTYPE_DIRECT
)
555 MouseSafetyOnDrawEnd(pdc1
->ppdev
);
556 EngReleaseSemaphore(pdc1
->ppdev
->hsemDevLock
);
561 if(pdc2
->dctype
== DCTYPE_DIRECT
)
563 MouseSafetyOnDrawEnd(pdc2
->ppdev
);
564 EngReleaseSemaphore(pdc2
->ppdev
->hsemDevLock
);
572 PUNICODE_STRING pustrDevice
,
574 PUNICODE_STRING pustrLogAddr
,
585 DPRINT("GreOpenDCW(%S, iType=%ld)\n",
586 pustrDevice
? pustrDevice
->Buffer
: NULL
, iType
);
588 /* Get a PDEVOBJ for the device */
589 ppdev
= EngpGetPDEV(pustrDevice
);
592 DPRINT1("Didn't find a suitable PDEV\n");
596 DPRINT("GreOpenDCW - ppdev = %p\n", ppdev
);
598 pdc
= DC_AllocDcWithHandle();
601 DPRINT1("Could not Allocate a DC\n");
602 PDEVOBJ_vRelease(ppdev
);
605 hdc
= pdc
->BaseObject
.hHmgr
;
607 /* Lock ppdev and initialize the new DC */
608 DC_vInitDc(pdc
, iType
, ppdev
);
616 DPRINT("returning hdc = %p\n", hdc
);
624 PUNICODE_STRING pustrDevice
,
626 PUNICODE_STRING pustrLogAddr
,
633 UNICODE_STRING ustrDevice
;
634 WCHAR awcDevice
[CCHDEVICENAME
];
639 /* Only if a devicename is given, we need any data */
642 /* Initialize destination string */
643 RtlInitEmptyUnicodeString(&ustrDevice
, awcDevice
, sizeof(awcDevice
));
647 /* Probe the UNICODE_STRING and the buffer */
648 ProbeForRead(pustrDevice
, sizeof(UNICODE_STRING
), 1);
649 ProbeForRead(pustrDevice
->Buffer
, pustrDevice
->Length
, 1);
651 /* Copy the string */
652 RtlCopyUnicodeString(&ustrDevice
, pustrDevice
);
656 /* FIXME: could be larger */
657 ProbeForRead(pdmInit
, sizeof(DEVMODEW
), 1);
658 RtlCopyMemory(&dmInit
, pdmInit
, sizeof(DEVMODEW
));
663 ProbeForWrite(pUMdhpdev
, sizeof(HANDLE
), 1);
666 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
668 SetLastNtError(_SEH2_GetExceptionCode());
669 _SEH2_YIELD(return NULL
);
682 UNICODE_STRING ustrDISPLAY
= RTL_CONSTANT_STRING(L
"DISPLAY");
683 if (RtlEqualUnicodeString(&ustrDevice
, &ustrDISPLAY
, TRUE
))
689 /* Call the internal function */
690 hdc
= GreOpenDCW(pustrDevice
? &ustrDevice
: NULL
,
691 pdmInit
? &dmInit
: NULL
,
692 NULL
, // fixme pwszLogAddress
696 NULL
, //FIXME: pDriverInfo2
697 pUMdhpdev
? &dhpdev
: NULL
);
699 /* If we got a HDC and a UM dhpdev is requested,... */
700 if (hdc
&& pUMdhpdev
)
702 /* Copy dhpdev to caller (FIXME: use dhpdev?? */
705 /* Pointer was already probed */
706 *(HANDLE
*)pUMdhpdev
= dhpdev
;
708 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
721 NtGdiCreateCompatibleDC(HDC hdc
)
727 DPRINT("NtGdiCreateCompatibleDC(0x%p)\n", hdc
);
729 /* Did the caller provide a DC? */
732 /* Yes, try to lock it */
733 pdc
= DC_LockDc(hdc
);
736 DPRINT1("Could not lock source DC %p\n", hdc
);
740 /* Get the pdev from the DC */
742 InterlockedIncrement(&ppdev
->cPdevRefs
);
744 /* Unlock the source DC */
749 /* No DC given, get default device */
750 ppdev
= EngpGetPDEV(NULL
);
755 DPRINT1("Didn't find a suitable PDEV\n");
759 /* Allocate a new DC */
760 pdcNew
= DC_AllocDcWithHandle();
763 DPRINT1("Could not allocate a new DC\n");
764 PDEVOBJ_vRelease(ppdev
);
767 hdcNew
= pdcNew
->BaseObject
.hHmgr
;
769 /* Lock ppdev and initialize the new DC */
770 DC_vInitDc(pdcNew
, DCTYPE_MEMORY
, ppdev
);
774 /* Allocate a dc attribute */
775 DC_AllocDcAttr(pdcNew
);
778 DC_vSelectSurface(pdcNew
, psurfDefaultBitmap
);
782 DPRINT("Leave NtGdiCreateCompatibleDC hdcNew = %p\n", hdcNew
);
789 IntGdiDeleteDC(HDC hDC
, BOOL Force
)
791 PDC DCToDelete
= DC_LockDc(hDC
);
793 if (DCToDelete
== NULL
)
795 EngSetLastError(ERROR_INVALID_HANDLE
);
801 /* Windows permits NtGdiDeleteObjectApp to delete a permanent DC
802 * For some reason, it's still a valid handle, pointing to some kernel data.
803 * Not sure if this is a bug, a feature, some cache stuff... Who knows?
804 * See NtGdiDeleteObjectApp test for details */
805 if (DCToDelete
->fs
& DC_FLAG_PERMANENT
)
807 DC_UnlockDc(DCToDelete
);
808 if(UserReleaseDC(NULL
, hDC
, FALSE
))
810 /* ReactOs feature : call UserReleaseDC
811 * I don't think windows does it.
812 * Still, complain, no one should ever call DeleteDC
814 DPRINT1("No, you naughty application!\n");
819 /* This is not a window owned DC.
820 * Force its deletion */
821 return IntGdiDeleteDC(hDC
, TRUE
);
826 DC_UnlockDc(DCToDelete
);
828 if (!IsObjectDead(hDC
))
830 if (!GDIOBJ_FreeObjByHandle(hDC
, GDI_OBJECT_TYPE_DC
))
832 DPRINT1("DC_FreeDC failed\n");
837 DPRINT1("Attempted to Delete 0x%x currently being destroyed!!!\n", hDC
);
845 NtGdiDeleteObjectApp(HANDLE DCHandle
)
847 /* Complete all pending operations */
848 NtGdiFlushUserBatch();
850 if (GDI_HANDLE_IS_STOCKOBJ(DCHandle
)) return TRUE
;
852 if (GDI_HANDLE_GET_TYPE(DCHandle
) != GDI_OBJECT_TYPE_DC
)
853 return GreDeleteObject((HGDIOBJ
) DCHandle
);
855 if (IsObjectDead((HGDIOBJ
)DCHandle
)) return TRUE
;
857 if (!GDIOBJ_OwnedByCurrentProcess(DCHandle
))
859 EngSetLastError(ERROR_INVALID_HANDLE
);
863 return IntGdiDeleteDC(DCHandle
, FALSE
);
868 MakeInfoDC(PDC pdc
, BOOL bSet
)
873 /* Can not be a display DC. */
874 if (pdc
->fs
& DC_FLAG_DISPLAY
) return FALSE
;
877 if (pdc
->fs
& DC_FLAG_TEMPINFODC
|| pdc
->dctype
== DC_TYPE_DIRECT
)
880 pSurface
= pdc
->dclevel
.pSurface
;
881 pdc
->fs
|= DC_FLAG_TEMPINFODC
;
882 pdc
->pSurfInfo
= pSurface
;
883 pdc
->dctype
= DC_TYPE_INFO
;
884 pdc
->dclevel
.pSurface
= NULL
;
886 PDEVOBJ_sizl(pdc
->ppdev
, &sizl
);
888 if ( sizl
.cx
== pdc
->dclevel
.sizl
.cx
&&
889 sizl
.cy
== pdc
->dclevel
.sizl
.cy
)
892 pdc
->dclevel
.sizl
.cx
= sizl
.cx
;
893 pdc
->dclevel
.sizl
.cy
= sizl
.cy
;
897 if (!(pdc
->fs
& DC_FLAG_TEMPINFODC
) || pdc
->dctype
!= DC_TYPE_INFO
)
900 pSurface
= pdc
->pSurfInfo
;
901 pdc
->fs
&= ~DC_FLAG_TEMPINFODC
;
902 pdc
->dclevel
.pSurface
= pSurface
;
903 pdc
->dctype
= DC_TYPE_DIRECT
;
904 pdc
->pSurfInfo
= NULL
;
907 (pSurface
->SurfObj
.sizlBitmap
.cx
== pdc
->dclevel
.sizl
.cx
&&
908 pSurface
->SurfObj
.sizlBitmap
.cy
== pdc
->dclevel
.sizl
.cy
) )
911 pdc
->dclevel
.sizl
.cx
= pSurface
->SurfObj
.sizlBitmap
.cx
;
912 pdc
->dclevel
.sizl
.cy
= pSurface
->SurfObj
.sizlBitmap
.cy
;
914 return IntSetDefaultRegion(pdc
);
927 PDC pdc
= DC_LockDc(hdc
);
930 Ret
= MakeInfoDC(pdc
, bSet
);
940 PUNICODE_STRING Driver
,
941 PUNICODE_STRING pustrDevice
,
943 CONST PDEVMODEW pdmInit
,
948 hdc
= GreOpenDCW(pustrDevice
,
951 CreateAsIC
? DCTYPE_INFO
:
952 (Driver
? DC_TYPE_DIRECT
: DC_TYPE_DIRECT
),
962 IntGdiCreateDisplayDC(HDEV hDev
, ULONG DcType
, BOOL EmptyDC
)
968 if (DcType
== DC_TYPE_MEMORY
)
969 hDC
= NtGdiCreateCompatibleDC(NULL
); // OH~ Yuck! I think I taste vomit in my mouth!
971 hDC
= IntGdiCreateDC(NULL
, NULL
, NULL
, NULL
, (DcType
== DC_TYPE_INFO
));
978 IntGdiSetDCOwnerEx( HDC hDC
, DWORD OwnerMask
, BOOL NoSetBrush
)
983 if (!hDC
|| (GDI_HANDLE_GET_TYPE(hDC
) != GDI_OBJECT_TYPE_DC
)) return FALSE
;
985 if ((OwnerMask
== GDI_OBJ_HMGR_PUBLIC
) || OwnerMask
== GDI_OBJ_HMGR_NONE
)
987 pDC
= DC_LockDc ( hDC
);
988 MmCopyFromCaller(&pDC
->dcattr
, pDC
->pdcattr
, sizeof(DC_ATTR
));
992 if (!DC_SetOwnership( hDC
, NULL
)) // This hDC is inaccessible!
996 if (OwnerMask
== GDI_OBJ_HMGR_POWNED
)
998 pDC
= DC_LockDc ( hDC
);
999 ASSERT(pDC
->pdcattr
== &pDC
->dcattr
);
1002 if (!DC_SetOwnership( hDC
, PsGetCurrentProcess() )) return Ret
;
1004 DC_AllocateDcAttr( hDC
); // Allocate new dcattr
1006 DCU_SynchDcAttrtoUser( hDC
); // Copy data from dc to dcattr
1009 if ((OwnerMask
!= GDI_OBJ_HMGR_NONE
) && !NoSetBrush
)
1011 pDC
= DC_LockDc ( hDC
);
1012 if (IntGdiSetBrushOwner((PBRUSH
)pDC
->dclevel
.pbrFill
, OwnerMask
))
1013 IntGdiSetBrushOwner((PBRUSH
)pDC
->dclevel
.pbrLine
, OwnerMask
);