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
)
30 Buf
= ExAllocatePoolWithTag(PagedPool
, Driver
->MaximumLength
, TAG_DC
);
33 DPRINT1("ExAllocatePoolWithTag failed\n");
36 RtlCopyMemory(Buf
, Driver
->Buffer
, Driver
->MaximumLength
);
39 NewDC
= (PDC
)GDIOBJ_AllocObjWithHandle(GDI_OBJECT_TYPE_DC
);
44 ExFreePoolWithTag(Buf
, TAG_DC
);
46 DPRINT1("GDIOBJ_AllocObjWithHandle failed\n");
50 hDC
= NewDC
->BaseObject
.hHmgr
;
52 NewDC
->pdcattr
= &NewDC
->dcattr
;
53 DC_AllocateDcAttr(hDC
);
57 RtlCopyMemory(&NewDC
->rosdc
.DriverName
, Driver
, sizeof(UNICODE_STRING
));
58 NewDC
->rosdc
.DriverName
.Buffer
= Buf
;
60 pdcattr
= NewDC
->pdcattr
;
62 // FIXME: no floating point in the kernel!
63 xformTemplate
.eM11
= 1.0f
;
64 xformTemplate
.eM12
= 0.0f
;
65 xformTemplate
.eM21
= 0.0f
;
66 xformTemplate
.eM22
= 1.0f
;
67 xformTemplate
.eDx
= 0.0f
;
68 xformTemplate
.eDy
= 0.0f
;
69 XForm2MatrixS(&NewDC
->dclevel
.mxWorldToDevice
, &xformTemplate
);
70 XForm2MatrixS(&NewDC
->dclevel
.mxDeviceToWorld
, &xformTemplate
);
71 XForm2MatrixS(&NewDC
->dclevel
.mxWorldToPage
, &xformTemplate
);
73 // Setup syncing bits for the dcattr data packets.
74 pdcattr
->flXform
= DEVICE_TO_PAGE_INVALID
;
76 pdcattr
->ulDirty_
= 0; // Server side
78 pdcattr
->iMapMode
= MM_TEXT
;
79 pdcattr
->iGraphicsMode
= GM_COMPATIBLE
;
80 pdcattr
->jFillMode
= ALTERNATE
;
82 pdcattr
->szlWindowExt
.cx
= 1; // Float to Int,,, WRONG!
83 pdcattr
->szlWindowExt
.cy
= 1;
84 pdcattr
->szlViewportExt
.cx
= 1;
85 pdcattr
->szlViewportExt
.cy
= 1;
87 pdcattr
->crForegroundClr
= 0;
88 pdcattr
->ulForegroundClr
= 0;
90 pdcattr
->ulBackgroundClr
= 0xffffff;
91 pdcattr
->crBackgroundClr
= 0xffffff;
93 pdcattr
->ulPenClr
= RGB(0, 0, 0);
94 pdcattr
->crPenClr
= RGB(0, 0, 0);
96 pdcattr
->ulBrushClr
= RGB(255, 255, 255); // Do this way too.
97 pdcattr
->crBrushClr
= RGB(255, 255, 255);
99 //// This fixes the default brush and pen settings. See DC_InitDC.
101 /* Create the default fill brush */
102 pdcattr
->hbrush
= NtGdiGetStockObject(WHITE_BRUSH
);
103 NewDC
->dclevel
.pbrFill
= BRUSH_ShareLockBrush(pdcattr
->hbrush
);
104 EBRUSHOBJ_vInit(&NewDC
->eboFill
, NewDC
->dclevel
.pbrFill
, NewDC
);
106 /* Create the default pen / line brush */
107 pdcattr
->hpen
= NtGdiGetStockObject(BLACK_PEN
);
108 NewDC
->dclevel
.pbrLine
= PEN_ShareLockPen(pdcattr
->hpen
);
109 EBRUSHOBJ_vInit(&NewDC
->eboLine
, NewDC
->dclevel
.pbrLine
, NewDC
);
111 /* Create the default text brush */
112 pbrush
= BRUSH_ShareLockBrush(NtGdiGetStockObject(BLACK_BRUSH
));
113 EBRUSHOBJ_vInit(&NewDC
->eboText
, pbrush
, NewDC
);
114 pdcattr
->ulDirty_
|= DIRTY_TEXT
;
116 /* Create the default background brush */
117 pbrush
= BRUSH_ShareLockBrush(NtGdiGetStockObject(WHITE_BRUSH
));
118 EBRUSHOBJ_vInit(&NewDC
->eboBackground
, pbrush
, NewDC
);
120 pdcattr
->hlfntNew
= NtGdiGetStockObject(SYSTEM_FONT
);
121 TextIntRealizeFont(pdcattr
->hlfntNew
,NULL
);
123 NewDC
->dclevel
.hpal
= NtGdiGetStockObject(DEFAULT_PALETTE
);
124 NewDC
->dclevel
.ppal
= PALETTE_ShareLockPalette(NewDC
->dclevel
.hpal
);
125 /* This should never fail */
126 ASSERT(NewDC
->dclevel
.ppal
);
128 NewDC
->dclevel
.laPath
.eMiterLimit
= 10.0; // FIXME: use FLOATL or FLOATOBJ!
130 NewDC
->dclevel
.lSaveDepth
= 1;
132 hsurf
= (HBITMAP
)PrimarySurface
.pSurface
; // <- what kind of haxx0ry is that?
133 NewDC
->dclevel
.pSurface
= SURFACE_ShareLockSurface(hsurf
);
139 DC_FreeDC(HDC DCToFree
)
141 DC_FreeDcAttr(DCToFree
);
142 if (!IsObjectDead(DCToFree
))
144 if (!GDIOBJ_FreeObjByHandle(DCToFree
, GDI_OBJECT_TYPE_DC
))
146 DPRINT1("DC_FreeDC failed\n");
151 DPRINT1("Attempted to Delete 0x%x currently being destroyed!!!\n",DCToFree
);
156 DC_Cleanup(PVOID ObjectBody
)
158 PDC pDC
= (PDC
)ObjectBody
;
160 /* Free driver name (HACK) */
161 if (pDC
->rosdc
.DriverName
.Buffer
)
162 ExFreePoolWithTag(pDC
->rosdc
.DriverName
.Buffer
, TAG_DC
);
164 /* Deselect dc objects */
165 DC_vSelectSurface(pDC
, NULL
);
166 DC_vSelectFillBrush(pDC
, NULL
);
167 DC_vSelectLineBrush(pDC
, NULL
);
168 DC_vSelectPalette(pDC
, NULL
);
170 /* Dereference default brushes */
171 BRUSH_ShareUnlockBrush(pDC
->eboText
.pbrush
);
172 BRUSH_ShareUnlockBrush(pDC
->eboBackground
.pbrush
);
174 /* Cleanup the dc brushes */
175 EBRUSHOBJ_vCleanup(&pDC
->eboFill
);
176 EBRUSHOBJ_vCleanup(&pDC
->eboLine
);
177 EBRUSHOBJ_vCleanup(&pDC
->eboText
);
178 EBRUSHOBJ_vCleanup(&pDC
->eboBackground
);
185 DC_SetOwnership(HDC hDC
, PEPROCESS Owner
)
189 if (!GDIOBJ_SetOwnership(hDC
, Owner
)) return FALSE
;
190 pDC
= DC_LockDc(hDC
);
193 if (pDC
->rosdc
.hClipRgn
)
195 if (!GDIOBJ_SetOwnership(pDC
->rosdc
.hClipRgn
, Owner
)) return FALSE
;
197 if (pDC
->rosdc
.hVisRgn
)
199 if (!GDIOBJ_SetOwnership(pDC
->rosdc
.hVisRgn
, Owner
)) return FALSE
;
201 if (pDC
->rosdc
.hGCClipRgn
)
203 if (!GDIOBJ_SetOwnership(pDC
->rosdc
.hGCClipRgn
, Owner
)) return FALSE
;
205 if (pDC
->dclevel
.hPath
)
207 if (!GDIOBJ_SetOwnership(pDC
->dclevel
.hPath
, Owner
)) return FALSE
;
218 PUNICODE_STRING Driver
,
219 PUNICODE_STRING Device
,
221 CONST PDEVMODEW InitData
,
228 UNICODE_STRING StdDriver
;
231 RtlInitUnicodeString(&StdDriver
, L
"DISPLAY");
233 DPRINT("DriverName: %wZ, DeviceName: %wZ\n", Driver
, Device
);
235 if (NULL
== Driver
|| 0 == RtlCompareUnicodeString(Driver
, &StdDriver
, TRUE
))
239 if (! IntPrepareDriverIfNeeded())
241 /* Here, we have two possibilities:
242 * a) return NULL, and hope that the caller
243 * won't call us in a loop
244 * b) bugcheck, but caller is unable to
245 * react on the problem
247 /*DPRINT1("Unable to prepare graphics driver, returning NULL ic\n");
249 KeBugCheck(VIDEO_DRIVER_INIT_FAILURE
);
254 calledFromUser
= UserIsEntered();
257 UserEnterExclusive();
260 if (! co_IntGraphicsCheck(TRUE
))
266 DPRINT1("Unable to initialize graphics, returning NULL dc\n");
278 /* Check for existing DC object */
279 if ((hdc
= DC_FindOpenDC(Driver
)) != NULL
)
281 hdc
= NtGdiCreateCompatibleDC(hdc
);
283 DPRINT1("NtGdiCreateCompatibleDC() failed\n");
287 /* Allocate a DC object */
288 pdc
= DC_AllocDC(Driver
);
291 DPRINT1("DC_AllocDC() failed\n");
294 hdc
= pdc
->BaseObject
.hHmgr
;
295 pdcattr
= pdc
->pdcattr
;
297 pdc
->dctype
= DC_TYPE_DIRECT
;
299 pdc
->dhpdev
= PrimarySurface
.dhpdev
;
300 if (pUMdhpdev
) pUMdhpdev
= pdc
->dhpdev
; // set DHPDEV for device.
301 pdc
->ppdev
= (PVOID
)&PrimarySurface
;
303 // ATM we only have one display.
304 pdcattr
->ulDirty_
|= DC_PRIMARY_DISPLAY
;
306 pdc
->rosdc
.bitsPerPixel
= pdc
->ppdev
->gdiinfo
.cBitsPixel
*
307 pdc
->ppdev
->gdiinfo
.cPlanes
;
308 DPRINT("Bits per pel: %u\n", pdc
->rosdc
.bitsPerPixel
);
310 pdc
->flGraphicsCaps
= PrimarySurface
.devinfo
.flGraphicsCaps
;
311 pdc
->flGraphicsCaps2
= PrimarySurface
.devinfo
.flGraphicsCaps2
;
313 pdc
->dclevel
.hpal
= NtGdiGetStockObject(DEFAULT_PALETTE
);
315 pdcattr
->jROP2
= R2_COPYPEN
;
317 pdc
->erclWindow
.top
= pdc
->erclWindow
.left
= 0;
318 pdc
->erclWindow
.right
= pdc
->ppdev
->gdiinfo
.ulHorzRes
;
319 pdc
->erclWindow
.bottom
= pdc
->ppdev
->gdiinfo
.ulVertRes
;
320 pdc
->dclevel
.flPath
&= ~DCPATH_CLOCKWISE
; // Default is CCW.
322 pdcattr
->iCS_CP
= ftGdiGetTextCharsetInfo(pdc
,NULL
,0);
324 hVisRgn
= NtGdiCreateRectRgn(0, 0, pdc
->ppdev
->gdiinfo
.ulHorzRes
,
325 pdc
->ppdev
->gdiinfo
.ulVertRes
);
329 pdc
->pSurfInfo
= NULL
;
330 // pdc->dclevel.pSurface =
333 /* Initialize the DC state */
334 IntGdiSetTextColor(hdc
, RGB(0, 0, 0));
335 IntGdiSetBkColor(hdc
, RGB(255, 255, 255));
340 The CreateIC function creates an information context for the specified device.
341 The information context provides a fast way to get information about the
342 device without creating a device context (DC). However, GDI drawing functions
343 cannot accept a handle to an information context.
345 pdc
->dctype
= DC_TYPE_INFO
;
347 // DC_vSelectSurface(pdc, NULL);
348 pdcattr
->crBackgroundClr
= pdcattr
->ulBackgroundClr
= RGB(255, 255, 255);
349 pdcattr
->crForegroundClr
= RGB(0, 0, 0);
356 GdiSelectVisRgn(hdc
, hVisRgn
);
357 GreDeleteObject(hVisRgn
);
360 IntGdiSetTextAlign(hdc
, TA_TOP
);
361 IntGdiSetBkMode(hdc
, OPAQUE
);
369 PUNICODE_STRING Device
,
371 PUNICODE_STRING pustrLogAddr
,
378 UNICODE_STRING SafeDevice
;
379 DEVMODEW SafeInitData
;
382 NTSTATUS Status
= STATUS_SUCCESS
;
384 if (!Device
) return UserGetDesktopDC(iType
,FALSE
,TRUE
);
392 ProbeForWrite(pUMdhpdev
, sizeof(PVOID
), 1);
394 ProbeForRead(InitData
, sizeof(DEVMODEW
), 1);
395 RtlCopyMemory(&SafeInitData
, InitData
, sizeof(DEVMODEW
));
397 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
399 Status
= _SEH2_GetExceptionCode();
403 if (!NT_SUCCESS(Status
))
405 SetLastNtError(Status
);
408 /* FIXME - InitData can have some more bytes! */
413 Status
= IntSafeCopyUnicodeString(&SafeDevice
, Device
);
414 if (!NT_SUCCESS(Status
))
416 SetLastNtError(Status
);
421 Ret
= IntGdiCreateDC(Device
? &SafeDevice
: NULL
,
423 pUMdhpdev
? &Dhpdev
: NULL
,
424 InitData
? &SafeInitData
: NULL
,
425 (BOOL
) iType
); // FALSE 0 DCW, TRUE 1 ICW
428 if (pUMdhpdev
) pUMdhpdev
= Dhpdev
;
434 IntGdiCreateDisplayDC(HDEV hDev
, ULONG DcType
, BOOL EmptyDC
)
437 UNICODE_STRING DriverName
;
438 RtlInitUnicodeString(&DriverName
, L
"DISPLAY");
440 if (DcType
!= DC_TYPE_MEMORY
)
441 hDC
= IntGdiCreateDC(&DriverName
, NULL
, NULL
, NULL
, (DcType
== DC_TYPE_INFO
));
443 hDC
= NtGdiCreateCompatibleDC(NULL
); // OH~ Yuck! I think I taste vomit in my mouth!
445 // There is room to grow here~
449 // If NULL, first time through! Build the default (was window) dc!
450 // Setup clean DC state for the system.
452 if (hDC
&& !defaultDCstate
) // Ultra HAX! Dedicated to GvG!
453 { // This is a cheesy way to do this.
454 PDC dc
= DC_LockDc(hDC
);
456 defaultDCstate
= ExAllocatePoolWithTag(PagedPool
, sizeof(DC
), TAG_DC
);
462 RtlZeroMemory(defaultDCstate
, sizeof(DC
));
463 defaultDCstate
->pdcattr
= &defaultDCstate
->dcattr
;
464 hsurf
= (HSURF
)PrimarySurface
.pSurface
; // HAX²
465 defaultDCstate
->dclevel
.pSurface
= SURFACE_ShareLockSurface(hsurf
);
466 DC_vCopyState(dc
, defaultDCstate
);
474 IntGdiDeleteDC(HDC hDC
, BOOL Force
)
476 PDC DCToDelete
= DC_LockDc(hDC
);
478 if (DCToDelete
== NULL
)
480 SetLastWin32Error(ERROR_INVALID_HANDLE
);
486 if (DCToDelete
->fs
& DC_FLAG_PERMANENT
)
488 DPRINT1("No! You Naughty Application!\n");
489 DC_UnlockDc(DCToDelete
);
490 return UserReleaseDC(NULL
, hDC
, FALSE
);
494 /* First delete all saved DCs */
495 while (DCToDelete
->dclevel
.lSaveDepth
> 1)
500 savedHDC
= DCToDelete
->hdcNext
;
501 savedDC
= DC_LockDc(savedHDC
);
506 DCToDelete
->hdcNext
= savedDC
->hdcNext
;
507 DCToDelete
->dclevel
.lSaveDepth
--;
508 DC_UnlockDc(savedDC
);
509 IntGdiDeleteDC(savedHDC
, Force
);
512 /* Free GDI resources allocated to this DC */
513 if (!(DCToDelete
->dclevel
.flPath
& DCPATH_SAVESTATE
))
516 NtGdiSelectPen (DCHandle, STOCK_BLACK_PEN);
517 NtGdiSelectBrush (DCHandle, STOCK_WHITE_BRUSH);
518 NtGdiSelectFont (DCHandle, STOCK_SYSTEM_FONT);
519 DC_LockDC (DCHandle); NtGdiSelectXxx does not recognize stock objects yet */
521 if (DCToDelete
->rosdc
.hClipRgn
)
523 GreDeleteObject(DCToDelete
->rosdc
.hClipRgn
);
525 if (DCToDelete
->rosdc
.hVisRgn
)
527 GreDeleteObject(DCToDelete
->rosdc
.hVisRgn
);
529 if (NULL
!= DCToDelete
->rosdc
.CombinedClip
)
531 IntEngDeleteClipRegion(DCToDelete
->rosdc
.CombinedClip
);
533 if (DCToDelete
->rosdc
.hGCClipRgn
)
535 GreDeleteObject(DCToDelete
->rosdc
.hGCClipRgn
);
537 PATH_Delete(DCToDelete
->dclevel
.hPath
);
539 DC_UnlockDc(DCToDelete
);
545 DC_FindOpenDC(PUNICODE_STRING Driver
)
551 * Initialize some common fields in the Device Context structure.
554 DC_InitDC(HDC DCHandle
)
556 // NtGdiRealizeDefaultPalette(DCHandle);
558 //// Removed for now.. See above brush and pen.
559 // NtGdiSelectBrush(DCHandle, NtGdiGetStockObject( WHITE_BRUSH ));
560 // NtGdiSelectPen(DCHandle, NtGdiGetStockObject( BLACK_PEN ));
562 //NtGdiSelectFont(DCHandle, hFont);
567 res = CLIPPING_UpdateGCRegion(DCToInit);
568 ASSERT ( res != ERROR );
572 /* Set virtual resolution */
573 NtGdiSetVirtualResolution(DCHandle
, 0, 0, 0, 0);
590 NtGdiCreateCompatibleDC(HDC hDC
)
593 PDC_ATTR pdcattrNew
, pdcattrOld
;
594 HDC hdcNew
, DisplayDC
= NULL
;
596 UNICODE_STRING DriverName
;
602 RtlInitUnicodeString(&DriverName
, L
"DISPLAY");
603 DisplayDC
= IntGdiCreateDC(&DriverName
, NULL
, NULL
, NULL
, TRUE
);
604 if (NULL
== DisplayDC
)
606 DPRINT1("Failed to create DisplayDC\n");
612 /* Allocate a new DC based on the original DC's device */
613 pdcOld
= DC_LockDc(hDC
);
616 if (NULL
!= DisplayDC
)
618 NtGdiDeleteObjectApp(DisplayDC
);
620 DPRINT1("Failed to lock hDC\n");
623 pdcNew
= DC_AllocDC(&pdcOld
->rosdc
.DriverName
);
626 DPRINT1("Failed to create pdcNew\n");
630 NtGdiDeleteObjectApp(DisplayDC
);
634 hdcNew
= pdcNew
->BaseObject
.hHmgr
;
636 pdcattrOld
= pdcOld
->pdcattr
;
637 pdcattrNew
= pdcNew
->pdcattr
;
639 /* Copy information from original DC to new DC */
640 pdcNew
->dclevel
.hdcSave
= hdcNew
;
642 pdcNew
->dhpdev
= pdcOld
->dhpdev
;
644 pdcNew
->rosdc
.bitsPerPixel
= pdcOld
->rosdc
.bitsPerPixel
;
646 /* DriverName is copied in the AllocDC routine */
647 pdcattrNew
->ptlWindowOrg
= pdcattrOld
->ptlWindowOrg
;
648 pdcattrNew
->szlWindowExt
= pdcattrOld
->szlWindowExt
;
649 pdcattrNew
->ptlViewportOrg
= pdcattrOld
->ptlViewportOrg
;
650 pdcattrNew
->szlViewportExt
= pdcattrOld
->szlViewportExt
;
652 pdcNew
->dctype
= DC_TYPE_MEMORY
; // Always!
653 hsurf
= NtGdiGetStockObject(DEFAULT_BITMAP
);
654 pdcNew
->dclevel
.pSurface
= SURFACE_ShareLockSurface(hsurf
);
655 pdcNew
->ppdev
= pdcOld
->ppdev
;
656 pdcNew
->dclevel
.hpal
= pdcOld
->dclevel
.hpal
;
658 pdcattrNew
->lTextAlign
= pdcattrOld
->lTextAlign
;
659 pdcattrNew
->lBkMode
= pdcattrOld
->lBkMode
;
660 pdcattrNew
->jBkMode
= pdcattrOld
->jBkMode
;
661 pdcattrNew
->jROP2
= pdcattrOld
->jROP2
;
662 pdcattrNew
->dwLayout
= pdcattrOld
->dwLayout
;
663 if (pdcattrOld
->dwLayout
& LAYOUT_ORIENTATIONMASK
) Layout
= pdcattrOld
->dwLayout
;
664 pdcNew
->dclevel
.flPath
= pdcOld
->dclevel
.flPath
;
665 pdcattrNew
->ulDirty_
= pdcattrOld
->ulDirty_
;
666 pdcattrNew
->iCS_CP
= pdcattrOld
->iCS_CP
;
668 pdcNew
->erclWindow
.left
= pdcNew
->erclWindow
.top
= 0;
669 pdcNew
->erclWindow
.right
= pdcNew
->erclWindow
.bottom
= 1;
673 if (NULL
!= DisplayDC
)
675 NtGdiDeleteObjectApp(DisplayDC
);
678 hVisRgn
= NtGdiCreateRectRgn(0, 0, 1, 1);
681 GdiSelectVisRgn(hdcNew
, hVisRgn
);
682 GreDeleteObject(hVisRgn
);
684 if (Layout
) NtGdiSetLayout(hdcNew
, -1, Layout
);
693 NtGdiDeleteObjectApp(HANDLE DCHandle
)
695 /* Complete all pending operations */
696 NtGdiFlushUserBatch();
698 if (GDI_HANDLE_IS_STOCKOBJ(DCHandle
)) return TRUE
;
700 if (GDI_HANDLE_GET_TYPE(DCHandle
) != GDI_OBJECT_TYPE_DC
)
701 return GreDeleteObject((HGDIOBJ
) DCHandle
);
703 if (IsObjectDead((HGDIOBJ
)DCHandle
)) return TRUE
;
705 if (!GDIOBJ_OwnedByCurrentProcess(DCHandle
))
707 SetLastWin32Error(ERROR_INVALID_HANDLE
);
711 return IntGdiDeleteDC(DCHandle
, FALSE
);
716 NewNtGdiDeleteObjectApp(HANDLE DCHandle
)
720 if (GDI_HANDLE_IS_STOCKOBJ(DCHandle
)) return TRUE
;
722 ObjType
= GDI_HANDLE_GET_TYPE(DCHandle
) >> GDI_ENTRY_UPPER_SHIFT
;
724 if (GreGetObjectOwner( DCHandle
, ObjType
))
728 case GDIObjType_DC_TYPE
:
729 return IntGdiDeleteDC(DCHandle
, FALSE
);
731 case GDIObjType_RGN_TYPE
:
732 case GDIObjType_SURF_TYPE
:
733 case GDIObjType_PAL_TYPE
:
734 case GDIObjType_LFONT_TYPE
:
735 case GDIObjType_BRUSH_TYPE
:
736 return GreDeleteObject((HGDIOBJ
) DCHandle
);
742 return (DCHandle
!= NULL
);