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 /** Internal functions ********************************************************/
18 DC_AllocDC(PUNICODE_STRING Driver
)
29 Buf
= ExAllocatePoolWithTag(PagedPool
, Driver
->MaximumLength
, TAG_DC
);
32 DPRINT1("ExAllocatePoolWithTag failed\n");
35 RtlCopyMemory(Buf
, Driver
->Buffer
, Driver
->MaximumLength
);
38 NewDC
= (PDC
)GDIOBJ_AllocObjWithHandle(GDI_OBJECT_TYPE_DC
);
43 ExFreePoolWithTag(Buf
, TAG_DC
);
45 DPRINT1("GDIOBJ_AllocObjWithHandle failed\n");
49 hDC
= NewDC
->BaseObject
.hHmgr
;
51 NewDC
->pdcattr
= &NewDC
->dcattr
;
52 DC_AllocateDcAttr(hDC
);
56 RtlCopyMemory(&NewDC
->rosdc
.DriverName
, Driver
, sizeof(UNICODE_STRING
));
57 NewDC
->rosdc
.DriverName
.Buffer
= Buf
;
59 pdcattr
= NewDC
->pdcattr
;
61 // FIXME: no floating point in the kernel!
62 xformTemplate
.eM11
= 1.0f
;
63 xformTemplate
.eM12
= 0.0f
;
64 xformTemplate
.eM21
= 0.0f
;
65 xformTemplate
.eM22
= 1.0f
;
66 xformTemplate
.eDx
= 0.0f
;
67 xformTemplate
.eDy
= 0.0f
;
68 XForm2MatrixS(&NewDC
->dclevel
.mxWorldToDevice
, &xformTemplate
);
69 XForm2MatrixS(&NewDC
->dclevel
.mxDeviceToWorld
, &xformTemplate
);
70 XForm2MatrixS(&NewDC
->dclevel
.mxWorldToPage
, &xformTemplate
);
72 // Setup syncing bits for the dcattr data packets.
73 pdcattr
->flXform
= DEVICE_TO_PAGE_INVALID
;
75 pdcattr
->ulDirty_
= 0; // Server side
77 pdcattr
->iMapMode
= MM_TEXT
;
78 pdcattr
->iGraphicsMode
= GM_COMPATIBLE
;
79 pdcattr
->jFillMode
= ALTERNATE
;
81 pdcattr
->szlWindowExt
.cx
= 1; // Float to Int,,, WRONG!
82 pdcattr
->szlWindowExt
.cy
= 1;
83 pdcattr
->szlViewportExt
.cx
= 1;
84 pdcattr
->szlViewportExt
.cy
= 1;
86 pdcattr
->crForegroundClr
= 0;
87 pdcattr
->ulForegroundClr
= 0;
89 pdcattr
->ulBackgroundClr
= 0xffffff;
90 pdcattr
->crBackgroundClr
= 0xffffff;
92 pdcattr
->ulPenClr
= RGB(0, 0, 0);
93 pdcattr
->crPenClr
= RGB(0, 0, 0);
95 pdcattr
->ulBrushClr
= RGB(255, 255, 255); // Do this way too.
96 pdcattr
->crBrushClr
= RGB(255, 255, 255);
98 //// This fixes the default brush and pen settings. See DC_InitDC.
100 /* Create the default fill brush */
101 pdcattr
->hbrush
= NtGdiGetStockObject(WHITE_BRUSH
);
102 NewDC
->dclevel
.pbrFill
= BRUSH_ShareLockBrush(pdcattr
->hbrush
);
103 EBRUSHOBJ_vInit(&NewDC
->eboFill
, NewDC
->dclevel
.pbrFill
, NULL
);
105 /* Create the default pen / line brush */
106 pdcattr
->hpen
= NtGdiGetStockObject(BLACK_PEN
);
107 NewDC
->dclevel
.pbrLine
= PEN_ShareLockPen(pdcattr
->hpen
);
108 EBRUSHOBJ_vInit(&NewDC
->eboLine
, NewDC
->dclevel
.pbrLine
, NULL
);
110 /* Create the default text brush */
111 pbrush
= BRUSH_ShareLockBrush(NtGdiGetStockObject(BLACK_BRUSH
));
112 EBRUSHOBJ_vInit(&NewDC
->eboText
, pbrush
, NULL
);
113 pdcattr
->ulDirty_
|= DIRTY_TEXT
;
115 /* Create the default background brush */
116 pbrush
= BRUSH_ShareLockBrush(NtGdiGetStockObject(WHITE_BRUSH
));
117 EBRUSHOBJ_vInit(&NewDC
->eboBackground
, pbrush
, NULL
);
119 pdcattr
->hlfntNew
= NtGdiGetStockObject(SYSTEM_FONT
);
120 TextIntRealizeFont(pdcattr
->hlfntNew
,NULL
);
122 NewDC
->dclevel
.hpal
= NtGdiGetStockObject(DEFAULT_PALETTE
);
123 NewDC
->dclevel
.laPath
.eMiterLimit
= 10.0;
125 NewDC
->dclevel
.lSaveDepth
= 1;
131 DC_FreeDC(HDC DCToFree
)
133 DC_FreeDcAttr(DCToFree
);
134 if (!IsObjectDead(DCToFree
))
136 if (!GDIOBJ_FreeObjByHandle(DCToFree
, GDI_OBJECT_TYPE_DC
))
138 DPRINT1("DC_FreeDC failed\n");
143 DPRINT1("Attempted to Delete 0x%x currently being destroyed!!!\n",DCToFree
);
148 DC_Cleanup(PVOID ObjectBody
)
150 PDC pDC
= (PDC
)ObjectBody
;
152 /* Free driver name (HACK) */
153 if (pDC
->rosdc
.DriverName
.Buffer
)
154 ExFreePoolWithTag(pDC
->rosdc
.DriverName
.Buffer
, TAG_DC
);
156 /* Clean up selected objects */
157 DC_vSelectSurface(pDC
, NULL
);
158 DC_vSelectFillBrush(pDC
, NULL
);
159 DC_vSelectLineBrush(pDC
, NULL
);
161 /* Dereference default brushes */
162 BRUSH_ShareUnlockBrush(pDC
->eboText
.pbrush
);
163 BRUSH_ShareUnlockBrush(pDC
->eboBackground
.pbrush
);
170 DC_SetOwnership(HDC hDC
, PEPROCESS Owner
)
174 if (!GDIOBJ_SetOwnership(hDC
, Owner
)) return FALSE
;
175 pDC
= DC_LockDc(hDC
);
178 if (pDC
->rosdc
.hClipRgn
)
180 if (!GDIOBJ_SetOwnership(pDC
->rosdc
.hClipRgn
, Owner
)) return FALSE
;
182 if (pDC
->rosdc
.hVisRgn
)
184 if (!GDIOBJ_SetOwnership(pDC
->rosdc
.hVisRgn
, Owner
)) return FALSE
;
186 if (pDC
->rosdc
.hGCClipRgn
)
188 if (!GDIOBJ_SetOwnership(pDC
->rosdc
.hGCClipRgn
, Owner
)) return FALSE
;
190 if (pDC
->dclevel
.hPath
)
192 if (!GDIOBJ_SetOwnership(pDC
->dclevel
.hPath
, Owner
)) return FALSE
;
203 PUNICODE_STRING Driver
,
204 PUNICODE_STRING Device
,
206 CONST PDEVMODEW InitData
,
213 UNICODE_STRING StdDriver
;
217 RtlInitUnicodeString(&StdDriver
, L
"DISPLAY");
219 DPRINT("DriverName: %wZ, DeviceName: %wZ\n", Driver
, Device
);
221 if (NULL
== Driver
|| 0 == RtlCompareUnicodeString(Driver
, &StdDriver
, TRUE
))
225 if (! IntPrepareDriverIfNeeded())
227 /* Here, we have two possibilities:
228 * a) return NULL, and hope that the caller
229 * won't call us in a loop
230 * b) bugcheck, but caller is unable to
231 * react on the problem
233 /*DPRINT1("Unable to prepare graphics driver, returning NULL ic\n");
235 KeBugCheck(VIDEO_DRIVER_INIT_FAILURE
);
240 calledFromUser
= UserIsEntered();
243 UserEnterExclusive();
246 if (! co_IntGraphicsCheck(TRUE
))
252 DPRINT1("Unable to initialize graphics, returning NULL dc\n");
264 /* Check for existing DC object */
265 if ((hdc
= DC_FindOpenDC(Driver
)) != NULL
)
267 hdc
= NtGdiCreateCompatibleDC(hdc
);
269 DPRINT1("NtGdiCreateCompatibleDC() failed\n");
273 /* Allocate a DC object */
274 pdc
= DC_AllocDC(Driver
);
277 DPRINT1("DC_AllocDC() failed\n");
280 hdc
= pdc
->BaseObject
.hHmgr
;
281 pdcattr
= pdc
->pdcattr
;
283 pdc
->dctype
= DC_TYPE_DIRECT
;
285 pdc
->dhpdev
= PrimarySurface
.hPDev
;
286 if (pUMdhpdev
) pUMdhpdev
= pdc
->dhpdev
; // set DHPDEV for device.
287 pdc
->ppdev
= (PVOID
)&PrimarySurface
;
288 hsurf
= (HBITMAP
)PrimarySurface
.pSurface
; // <- what kind of haxx0ry is that?
289 pdc
->dclevel
.pSurface
= SURFACE_ShareLockSurface(hsurf
);
291 // ATM we only have one display.
292 pdcattr
->ulDirty_
|= DC_PRIMARY_DISPLAY
;
294 pdc
->rosdc
.bitsPerPixel
= pdc
->ppdev
->GDIInfo
.cBitsPixel
*
295 pdc
->ppdev
->GDIInfo
.cPlanes
;
296 DPRINT("Bits per pel: %u\n", pdc
->rosdc
.bitsPerPixel
);
298 pdc
->flGraphicsCaps
= PrimarySurface
.DevInfo
.flGraphicsCaps
;
299 pdc
->flGraphicsCaps2
= PrimarySurface
.DevInfo
.flGraphicsCaps2
;
301 pdc
->dclevel
.hpal
= NtGdiGetStockObject(DEFAULT_PALETTE
);
303 pdcattr
->jROP2
= R2_COPYPEN
;
305 pdc
->erclWindow
.top
= pdc
->erclWindow
.left
= 0;
306 pdc
->erclWindow
.right
= pdc
->ppdev
->GDIInfo
.ulHorzRes
;
307 pdc
->erclWindow
.bottom
= pdc
->ppdev
->GDIInfo
.ulVertRes
;
308 pdc
->dclevel
.flPath
&= ~DCPATH_CLOCKWISE
; // Default is CCW.
310 pdcattr
->iCS_CP
= ftGdiGetTextCharsetInfo(pdc
,NULL
,0);
312 hVisRgn
= NtGdiCreateRectRgn(0, 0, pdc
->ppdev
->GDIInfo
.ulHorzRes
,
313 pdc
->ppdev
->GDIInfo
.ulVertRes
);
317 pdc
->pSurfInfo
= NULL
;
318 // pdc->dclevel.pSurface =
321 /* Initialize the DC state */
323 IntGdiSetTextColor(hdc
, RGB(0, 0, 0));
324 IntGdiSetBkColor(hdc
, RGB(255, 255, 255));
329 The CreateIC function creates an information context for the specified device.
330 The information context provides a fast way to get information about the
331 device without creating a device context (DC). However, GDI drawing functions
332 cannot accept a handle to an information context.
334 pdc
->dctype
= DC_TYPE_INFO
;
336 DC_vSelectSurface(pdc
, NULL
);
337 pdcattr
->crBackgroundClr
= pdcattr
->ulBackgroundClr
= RGB(255, 255, 255);
338 pdcattr
->crForegroundClr
= RGB(0, 0, 0);
344 GdiSelectVisRgn(hdc
, hVisRgn
);
345 GreDeleteObject(hVisRgn
);
348 IntGdiSetTextAlign(hdc
, TA_TOP
);
349 IntGdiSetBkMode(hdc
, OPAQUE
);
357 PUNICODE_STRING Device
,
359 PUNICODE_STRING pustrLogAddr
,
366 UNICODE_STRING SafeDevice
;
367 DEVMODEW SafeInitData
;
370 NTSTATUS Status
= STATUS_SUCCESS
;
378 ProbeForWrite(pUMdhpdev
, sizeof(PVOID
), 1);
380 ProbeForRead(InitData
, sizeof(DEVMODEW
), 1);
381 RtlCopyMemory(&SafeInitData
, InitData
, sizeof(DEVMODEW
));
383 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
385 Status
= _SEH2_GetExceptionCode();
389 if (!NT_SUCCESS(Status
))
391 SetLastNtError(Status
);
394 /* FIXME - InitData can have some more bytes! */
399 Status
= IntSafeCopyUnicodeString(&SafeDevice
, Device
);
400 if (!NT_SUCCESS(Status
))
402 SetLastNtError(Status
);
407 Ret
= IntGdiCreateDC(Device
? &SafeDevice
: NULL
,
409 pUMdhpdev
? &Dhpdev
: NULL
,
410 InitData
? &SafeInitData
: NULL
,
411 (BOOL
) iType
); // FALSE 0 DCW, TRUE 1 ICW
414 if (pUMdhpdev
) pUMdhpdev
= Dhpdev
;
420 IntGdiCreateDisplayDC(HDEV hDev
, ULONG DcType
, BOOL EmptyDC
)
423 UNICODE_STRING DriverName
;
424 RtlInitUnicodeString(&DriverName
, L
"DISPLAY");
426 if (DcType
!= DC_TYPE_MEMORY
)
427 hDC
= IntGdiCreateDC(&DriverName
, NULL
, NULL
, NULL
, (DcType
== DC_TYPE_INFO
));
429 hDC
= NtGdiCreateCompatibleDC(NULL
); // OH~ Yuck! I think I taste vomit in my mouth!
431 // There is room to grow here~
435 // If NULL, first time through! Build the default (was window) dc!
436 // Setup clean DC state for the system.
438 if (hDC
&& !defaultDCstate
) // Ultra HAX! Dedicated to GvG!
439 { // This is a cheesy way to do this.
440 PDC dc
= DC_LockDc(hDC
);
441 defaultDCstate
= ExAllocatePoolWithTag(PagedPool
, sizeof(DC
), TAG_DC
);
447 RtlZeroMemory(defaultDCstate
, sizeof(DC
));
448 defaultDCstate
->pdcattr
= &defaultDCstate
->dcattr
;
449 DC_vCopyState(dc
, defaultDCstate
);
457 IntGdiDeleteDC(HDC hDC
, BOOL Force
)
459 PDC DCToDelete
= DC_LockDc(hDC
);
461 if (DCToDelete
== NULL
)
463 SetLastWin32Error(ERROR_INVALID_HANDLE
);
469 if (DCToDelete
->fs
& DC_FLAG_PERMANENT
)
471 DPRINT1("No! You Naughty Application!\n");
472 DC_UnlockDc(DCToDelete
);
473 return UserReleaseDC(NULL
, hDC
, FALSE
);
477 /* First delete all saved DCs */
478 while (DCToDelete
->dclevel
.lSaveDepth
> 1)
483 savedHDC
= DCToDelete
->hdcNext
;
484 savedDC
= DC_LockDc(savedHDC
);
489 DCToDelete
->hdcNext
= savedDC
->hdcNext
;
490 DCToDelete
->dclevel
.lSaveDepth
--;
491 DC_UnlockDc(savedDC
);
492 IntGdiDeleteDC(savedHDC
, Force
);
495 /* Free GDI resources allocated to this DC */
496 if (!(DCToDelete
->dclevel
.flPath
& DCPATH_SAVESTATE
))
499 NtGdiSelectPen (DCHandle, STOCK_BLACK_PEN);
500 NtGdiSelectBrush (DCHandle, STOCK_WHITE_BRUSH);
501 NtGdiSelectFont (DCHandle, STOCK_SYSTEM_FONT);
502 DC_LockDC (DCHandle); NtGdiSelectXxx does not recognize stock objects yet */
504 if (DCToDelete
->rosdc
.hClipRgn
)
506 GreDeleteObject(DCToDelete
->rosdc
.hClipRgn
);
508 if (DCToDelete
->rosdc
.hVisRgn
)
510 GreDeleteObject(DCToDelete
->rosdc
.hVisRgn
);
512 if (NULL
!= DCToDelete
->rosdc
.CombinedClip
)
514 IntEngDeleteClipRegion(DCToDelete
->rosdc
.CombinedClip
);
516 if (DCToDelete
->rosdc
.hGCClipRgn
)
518 GreDeleteObject(DCToDelete
->rosdc
.hGCClipRgn
);
520 PATH_Delete(DCToDelete
->dclevel
.hPath
);
522 DC_UnlockDc(DCToDelete
);
528 DC_FindOpenDC(PUNICODE_STRING Driver
)
534 * Initialize some common fields in the Device Context structure.
537 DC_InitDC(HDC DCHandle
)
539 // NtGdiRealizeDefaultPalette(DCHandle);
541 //// Removed for now.. See above brush and pen.
542 // NtGdiSelectBrush(DCHandle, NtGdiGetStockObject( WHITE_BRUSH ));
543 // NtGdiSelectPen(DCHandle, NtGdiGetStockObject( BLACK_PEN ));
545 //NtGdiSelectFont(DCHandle, hFont);
550 res = CLIPPING_UpdateGCRegion(DCToInit);
551 ASSERT ( res != ERROR );
570 NtGdiCreateCompatibleDC(HDC hDC
)
573 PDC_ATTR pdcattrNew
, pdcattrOld
;
574 HDC hdcNew
, DisplayDC
= NULL
;
576 UNICODE_STRING DriverName
;
582 RtlInitUnicodeString(&DriverName
, L
"DISPLAY");
583 DisplayDC
= IntGdiCreateDC(&DriverName
, NULL
, NULL
, NULL
, TRUE
);
584 if (NULL
== DisplayDC
)
586 DPRINT1("Failed to create DisplayDC\n");
592 /* Allocate a new DC based on the original DC's device */
593 pdcOld
= DC_LockDc(hDC
);
596 if (NULL
!= DisplayDC
)
598 NtGdiDeleteObjectApp(DisplayDC
);
600 DPRINT1("Failed to lock hDC\n");
603 pdcNew
= DC_AllocDC(&pdcOld
->rosdc
.DriverName
);
606 DPRINT1("Failed to create pdcNew\n");
610 NtGdiDeleteObjectApp(DisplayDC
);
614 hdcNew
= pdcNew
->BaseObject
.hHmgr
;
616 pdcattrOld
= pdcOld
->pdcattr
;
617 pdcattrNew
= pdcNew
->pdcattr
;
619 /* Copy information from original DC to new DC */
620 pdcNew
->dclevel
.hdcSave
= hdcNew
;
622 pdcNew
->dhpdev
= pdcOld
->dhpdev
;
624 pdcNew
->rosdc
.bitsPerPixel
= pdcOld
->rosdc
.bitsPerPixel
;
626 /* DriverName is copied in the AllocDC routine */
627 pdcattrNew
->ptlWindowOrg
= pdcattrOld
->ptlWindowOrg
;
628 pdcattrNew
->szlWindowExt
= pdcattrOld
->szlWindowExt
;
629 pdcattrNew
->ptlViewportOrg
= pdcattrOld
->ptlViewportOrg
;
630 pdcattrNew
->szlViewportExt
= pdcattrOld
->szlViewportExt
;
632 pdcNew
->dctype
= DC_TYPE_MEMORY
; // Always!
633 hsurf
= NtGdiGetStockObject(DEFAULT_BITMAP
);
634 pdcNew
->dclevel
.pSurface
= SURFACE_ShareLockSurface(hsurf
);
635 pdcNew
->ppdev
= pdcOld
->ppdev
;
636 pdcNew
->dclevel
.hpal
= pdcOld
->dclevel
.hpal
;
638 pdcattrNew
->lTextAlign
= pdcattrOld
->lTextAlign
;
639 pdcattrNew
->lBkMode
= pdcattrOld
->lBkMode
;
640 pdcattrNew
->jBkMode
= pdcattrOld
->jBkMode
;
641 pdcattrNew
->jROP2
= pdcattrOld
->jROP2
;
642 pdcattrNew
->dwLayout
= pdcattrOld
->dwLayout
;
643 if (pdcattrOld
->dwLayout
& LAYOUT_ORIENTATIONMASK
) Layout
= pdcattrOld
->dwLayout
;
644 pdcNew
->dclevel
.flPath
= pdcOld
->dclevel
.flPath
;
645 pdcattrNew
->ulDirty_
= pdcattrOld
->ulDirty_
;
646 pdcattrNew
->iCS_CP
= pdcattrOld
->iCS_CP
;
648 pdcNew
->erclWindow
= (RECTL
){0, 0, 1, 1};
652 if (NULL
!= DisplayDC
)
654 NtGdiDeleteObjectApp(DisplayDC
);
657 hVisRgn
= NtGdiCreateRectRgn(0, 0, 1, 1);
660 GdiSelectVisRgn(hdcNew
, hVisRgn
);
661 GreDeleteObject(hVisRgn
);
663 if (Layout
) NtGdiSetLayout(hdcNew
, -1, Layout
);
672 NtGdiDeleteObjectApp(HANDLE DCHandle
)
674 /* Complete all pending operations */
675 NtGdiFlushUserBatch();
677 if (GDI_HANDLE_IS_STOCKOBJ(DCHandle
)) return TRUE
;
679 if (GDI_HANDLE_GET_TYPE(DCHandle
) != GDI_OBJECT_TYPE_DC
)
680 return GreDeleteObject((HGDIOBJ
) DCHandle
);
682 if (IsObjectDead((HGDIOBJ
)DCHandle
)) return TRUE
;
684 if (!GDIOBJ_OwnedByCurrentProcess(DCHandle
))
686 SetLastWin32Error(ERROR_INVALID_HANDLE
);
690 return IntGdiDeleteDC(DCHandle
, FALSE
);
695 NewNtGdiDeleteObjectApp(HANDLE DCHandle
)
699 if (GDI_HANDLE_IS_STOCKOBJ(DCHandle
)) return TRUE
;
701 ObjType
= GDI_HANDLE_GET_TYPE(DCHandle
) >> GDI_ENTRY_UPPER_SHIFT
;
703 if (GreGetObjectOwner( DCHandle
, ObjType
))
707 case GDIObjType_DC_TYPE
:
708 return IntGdiDeleteDC(DCHandle
, FALSE
);
710 case GDIObjType_RGN_TYPE
:
711 case GDIObjType_SURF_TYPE
:
712 case GDIObjType_PAL_TYPE
:
713 case GDIObjType_LFONT_TYPE
:
714 case GDIObjType_BRUSH_TYPE
:
715 return GreDeleteObject((HGDIOBJ
) DCHandle
);
721 return (DCHandle
!= NULL
);