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_Cleanup(PVOID ObjectBody
)
141 PDC pDC
= (PDC
)ObjectBody
;
143 /* Free driver name (HACK) */
144 if (pDC
->rosdc
.DriverName
.Buffer
)
145 ExFreePoolWithTag(pDC
->rosdc
.DriverName
.Buffer
, TAG_DC
);
147 /* Deselect dc objects */
148 DC_vSelectSurface(pDC
, NULL
);
149 DC_vSelectFillBrush(pDC
, NULL
);
150 DC_vSelectLineBrush(pDC
, NULL
);
151 DC_vSelectPalette(pDC
, NULL
);
153 /* Dereference default brushes */
154 BRUSH_ShareUnlockBrush(pDC
->eboText
.pbrush
);
155 BRUSH_ShareUnlockBrush(pDC
->eboBackground
.pbrush
);
157 /* Cleanup the dc brushes */
158 EBRUSHOBJ_vCleanup(&pDC
->eboFill
);
159 EBRUSHOBJ_vCleanup(&pDC
->eboLine
);
160 EBRUSHOBJ_vCleanup(&pDC
->eboText
);
161 EBRUSHOBJ_vCleanup(&pDC
->eboBackground
);
168 DC_SetOwnership(HDC hDC
, PEPROCESS Owner
)
171 PGDI_TABLE_ENTRY Entry
;
174 if (!GDIOBJ_SetOwnership(hDC
, Owner
)) return FALSE
;
175 pDC
= DC_LockDc(hDC
);
180 These regions do not use attribute sections and when allocated, use
181 gdiobj level functions.
183 if (pDC
->rosdc
.hClipRgn
)
185 Index
= GDI_HANDLE_GET_INDEX(pDC
->rosdc
.hClipRgn
);
186 Entry
= &GdiHandleTable
->Entries
[Index
];
187 if (Entry
->UserData
) FreeObjectAttr(Entry
->UserData
);
188 Entry
->UserData
= NULL
;
190 if (!GDIOBJ_SetOwnership(pDC
->rosdc
.hClipRgn
, Owner
)) return FALSE
;
192 if (pDC
->rosdc
.hVisRgn
)
194 Index
= GDI_HANDLE_GET_INDEX(pDC
->rosdc
.hVisRgn
);
195 Entry
= &GdiHandleTable
->Entries
[Index
];
196 if (Entry
->UserData
) FreeObjectAttr(Entry
->UserData
);
197 Entry
->UserData
= NULL
;
199 if (!GDIOBJ_SetOwnership(pDC
->rosdc
.hVisRgn
, Owner
)) return FALSE
;
201 if (pDC
->rosdc
.hGCClipRgn
)
203 Index
= GDI_HANDLE_GET_INDEX(pDC
->rosdc
.hGCClipRgn
);
204 Entry
= &GdiHandleTable
->Entries
[Index
];
205 if (Entry
->UserData
) FreeObjectAttr(Entry
->UserData
);
206 Entry
->UserData
= NULL
;
208 if (!GDIOBJ_SetOwnership(pDC
->rosdc
.hGCClipRgn
, Owner
)) return FALSE
;
210 if (pDC
->dclevel
.hPath
)
212 if (!GDIOBJ_SetOwnership(pDC
->dclevel
.hPath
, Owner
)) return FALSE
;
223 PUNICODE_STRING Driver
,
224 PUNICODE_STRING Device
,
226 CONST PDEVMODEW InitData
,
233 UNICODE_STRING StdDriver
;
236 RtlInitUnicodeString(&StdDriver
, L
"DISPLAY");
238 DPRINT("DriverName: %wZ, DeviceName: %wZ\n", Driver
, Device
);
240 if (NULL
== Driver
|| 0 == RtlCompareUnicodeString(Driver
, &StdDriver
, TRUE
))
244 if (! IntPrepareDriverIfNeeded())
246 /* Here, we have two possibilities:
247 * a) return NULL, and hope that the caller
248 * won't call us in a loop
249 * b) bugcheck, but caller is unable to
250 * react on the problem
252 /*DPRINT1("Unable to prepare graphics driver, returning NULL ic\n");
254 KeBugCheck(VIDEO_DRIVER_INIT_FAILURE
);
259 calledFromUser
= UserIsEntered();
262 UserEnterExclusive();
265 if (! co_IntGraphicsCheck(TRUE
))
271 DPRINT1("Unable to initialize graphics, returning NULL dc\n");
283 /* Check for existing DC object */
284 if ((hdc
= DC_FindOpenDC(Driver
)) != NULL
)
286 hdc
= NtGdiCreateCompatibleDC(hdc
);
288 DPRINT1("NtGdiCreateCompatibleDC() failed\n");
292 /* Allocate a DC object */
293 pdc
= DC_AllocDC(Driver
);
296 DPRINT1("DC_AllocDC() failed\n");
299 hdc
= pdc
->BaseObject
.hHmgr
;
300 pdcattr
= pdc
->pdcattr
;
302 pdc
->dctype
= DC_TYPE_DIRECT
;
304 pdc
->dhpdev
= PrimarySurface
.dhpdev
;
305 if (pUMdhpdev
) pUMdhpdev
= pdc
->dhpdev
; // set DHPDEV for device.
306 pdc
->ppdev
= (PVOID
)&PrimarySurface
;
308 // ATM we only have one display.
309 pdcattr
->ulDirty_
|= DC_PRIMARY_DISPLAY
;
311 pdc
->rosdc
.bitsPerPixel
= pdc
->ppdev
->gdiinfo
.cBitsPixel
*
312 pdc
->ppdev
->gdiinfo
.cPlanes
;
313 DPRINT("Bits per pel: %u\n", pdc
->rosdc
.bitsPerPixel
);
315 pdc
->flGraphicsCaps
= PrimarySurface
.devinfo
.flGraphicsCaps
;
316 pdc
->flGraphicsCaps2
= PrimarySurface
.devinfo
.flGraphicsCaps2
;
318 pdc
->dclevel
.hpal
= NtGdiGetStockObject(DEFAULT_PALETTE
);
320 pdcattr
->jROP2
= R2_COPYPEN
;
322 pdc
->erclWindow
.top
= pdc
->erclWindow
.left
= 0;
323 pdc
->erclWindow
.right
= pdc
->ppdev
->gdiinfo
.ulHorzRes
;
324 pdc
->erclWindow
.bottom
= pdc
->ppdev
->gdiinfo
.ulVertRes
;
325 pdc
->dclevel
.flPath
&= ~DCPATH_CLOCKWISE
; // Default is CCW.
327 pdcattr
->iCS_CP
= ftGdiGetTextCharsetInfo(pdc
,NULL
,0);
329 hVisRgn
= IntSysCreateRectRgn(0, 0, pdc
->ppdev
->gdiinfo
.ulHorzRes
,
330 pdc
->ppdev
->gdiinfo
.ulVertRes
);
334 pdc
->pSurfInfo
= NULL
;
335 // pdc->dclevel.pSurface =
338 /* Initialize the DC state */
339 IntGdiSetTextColor(hdc
, RGB(0, 0, 0));
340 IntGdiSetBkColor(hdc
, RGB(255, 255, 255));
345 The CreateIC function creates an information context for the specified device.
346 The information context provides a fast way to get information about the
347 device without creating a device context (DC). However, GDI drawing functions
348 cannot accept a handle to an information context.
350 pdc
->dctype
= DC_TYPE_INFO
;
352 // DC_vSelectSurface(pdc, NULL);
353 pdcattr
->crBackgroundClr
= pdcattr
->ulBackgroundClr
= RGB(255, 255, 255);
354 pdcattr
->crForegroundClr
= RGB(0, 0, 0);
361 GdiSelectVisRgn(hdc
, hVisRgn
);
362 REGION_FreeRgnByHandle(hVisRgn
);
365 IntGdiSetTextAlign(hdc
, TA_TOP
);
366 IntGdiSetBkMode(hdc
, OPAQUE
);
374 PUNICODE_STRING Device
,
376 PUNICODE_STRING pustrLogAddr
,
383 UNICODE_STRING SafeDevice
;
384 DEVMODEW SafeInitData
;
387 NTSTATUS Status
= STATUS_SUCCESS
;
389 if (!Device
) return UserGetDesktopDC(iType
,FALSE
,TRUE
);
397 ProbeForWrite(pUMdhpdev
, sizeof(PVOID
), 1);
399 ProbeForRead(InitData
, sizeof(DEVMODEW
), 1);
400 RtlCopyMemory(&SafeInitData
, InitData
, sizeof(DEVMODEW
));
402 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
404 Status
= _SEH2_GetExceptionCode();
408 if (!NT_SUCCESS(Status
))
410 SetLastNtError(Status
);
413 /* FIXME - InitData can have some more bytes! */
418 Status
= IntSafeCopyUnicodeString(&SafeDevice
, Device
);
419 if (!NT_SUCCESS(Status
))
421 SetLastNtError(Status
);
426 Ret
= IntGdiCreateDC(Device
? &SafeDevice
: NULL
,
428 pUMdhpdev
? &Dhpdev
: NULL
,
429 InitData
? &SafeInitData
: NULL
,
430 (BOOL
) iType
); // FALSE 0 DCW, TRUE 1 ICW
433 if (pUMdhpdev
) pUMdhpdev
= Dhpdev
;
439 IntGdiCreateDisplayDC(HDEV hDev
, ULONG DcType
, BOOL EmptyDC
)
442 UNICODE_STRING DriverName
;
443 RtlInitUnicodeString(&DriverName
, L
"DISPLAY");
445 if (DcType
!= DC_TYPE_MEMORY
)
446 hDC
= IntGdiCreateDC(&DriverName
, NULL
, NULL
, NULL
, (DcType
== DC_TYPE_INFO
));
448 hDC
= NtGdiCreateCompatibleDC(NULL
); // OH~ Yuck! I think I taste vomit in my mouth!
450 // There is room to grow here~
454 // If NULL, first time through! Build the default (was window) dc!
455 // Setup clean DC state for the system.
457 if (hDC
&& !defaultDCstate
) // Ultra HAX! Dedicated to GvG!
458 { // This is a cheesy way to do this.
459 PDC dc
= DC_LockDc(hDC
);
461 defaultDCstate
= ExAllocatePoolWithTag(PagedPool
, sizeof(DC
), TAG_DC
);
467 RtlZeroMemory(defaultDCstate
, sizeof(DC
));
468 defaultDCstate
->pdcattr
= &defaultDCstate
->dcattr
;
469 hsurf
= (HSURF
)PrimarySurface
.pSurface
; // HAX²
470 defaultDCstate
->dclevel
.pSurface
= SURFACE_ShareLockSurface(hsurf
);
471 DC_vCopyState(dc
, defaultDCstate
, TRUE
);
479 IntGdiDeleteDC(HDC hDC
, BOOL Force
)
481 PDC DCToDelete
= DC_LockDc(hDC
);
483 if (DCToDelete
== NULL
)
485 SetLastWin32Error(ERROR_INVALID_HANDLE
);
491 if (DCToDelete
->fs
& DC_FLAG_PERMANENT
)
493 DPRINT1("No! You Naughty Application!\n");
494 DC_UnlockDc(DCToDelete
);
495 return UserReleaseDC(NULL
, hDC
, FALSE
);
499 /* First delete all saved DCs */
500 while (DCToDelete
->dclevel
.lSaveDepth
> 1)
505 savedHDC
= DCToDelete
->hdcNext
;
506 savedDC
= DC_LockDc(savedHDC
);
511 DCToDelete
->hdcNext
= savedDC
->hdcNext
;
512 DCToDelete
->dclevel
.lSaveDepth
--;
513 DC_UnlockDc(savedDC
);
514 IntGdiDeleteDC(savedHDC
, Force
);
517 /* Free GDI resources allocated to this DC */
518 if (!(DCToDelete
->dclevel
.flPath
& DCPATH_SAVESTATE
))
521 NtGdiSelectPen (DCHandle, STOCK_BLACK_PEN);
522 NtGdiSelectBrush (DCHandle, STOCK_WHITE_BRUSH);
523 NtGdiSelectFont (DCHandle, STOCK_SYSTEM_FONT);
524 DC_LockDC (DCHandle); NtGdiSelectXxx does not recognize stock objects yet */
526 if (DCToDelete
->rosdc
.hClipRgn
)
528 GreDeleteObject(DCToDelete
->rosdc
.hClipRgn
);
530 if (DCToDelete
->rosdc
.hVisRgn
)
532 GreDeleteObject(DCToDelete
->rosdc
.hVisRgn
);
534 if (NULL
!= DCToDelete
->rosdc
.CombinedClip
)
536 IntEngDeleteClipRegion(DCToDelete
->rosdc
.CombinedClip
);
538 if (DCToDelete
->rosdc
.hGCClipRgn
)
540 GreDeleteObject(DCToDelete
->rosdc
.hGCClipRgn
);
542 if (DCToDelete
->dclevel
.prgnMeta
)
544 GreDeleteObject(((PROSRGNDATA
)DCToDelete
->dclevel
.prgnMeta
)->BaseObject
.hHmgr
);
546 if (DCToDelete
->prgnAPI
)
548 GreDeleteObject(((PROSRGNDATA
)DCToDelete
->prgnAPI
)->BaseObject
.hHmgr
);
550 PATH_Delete(DCToDelete
->dclevel
.hPath
);
552 DC_UnlockDc(DCToDelete
);
553 GreDeleteObject(hDC
);
558 DC_FindOpenDC(PUNICODE_STRING Driver
)
564 * Initialize some common fields in the Device Context structure.
567 DC_InitDC(HDC DCHandle
)
569 // NtGdiRealizeDefaultPalette(DCHandle);
571 //// Removed for now.. See above brush and pen.
572 // NtGdiSelectBrush(DCHandle, NtGdiGetStockObject( WHITE_BRUSH ));
573 // NtGdiSelectPen(DCHandle, NtGdiGetStockObject( BLACK_PEN ));
575 //NtGdiSelectFont(DCHandle, hFont);
580 res = CLIPPING_UpdateGCRegion(DCToInit);
581 ASSERT ( res != ERROR );
585 /* Set virtual resolution */
586 NtGdiSetVirtualResolution(DCHandle
, 0, 0, 0, 0);
603 NtGdiCreateCompatibleDC(HDC hDC
)
606 PDC_ATTR pdcattrNew
, pdcattrOld
;
607 HDC hdcNew
, DisplayDC
= NULL
;
609 UNICODE_STRING DriverName
;
615 RtlInitUnicodeString(&DriverName
, L
"DISPLAY");
616 DisplayDC
= IntGdiCreateDC(&DriverName
, NULL
, NULL
, NULL
, TRUE
);
617 if (NULL
== DisplayDC
)
619 DPRINT1("Failed to create DisplayDC\n");
625 /* Allocate a new DC based on the original DC's device */
626 pdcOld
= DC_LockDc(hDC
);
629 if (NULL
!= DisplayDC
)
631 NtGdiDeleteObjectApp(DisplayDC
);
633 DPRINT1("Failed to lock hDC\n");
636 pdcNew
= DC_AllocDC(&pdcOld
->rosdc
.DriverName
);
639 DPRINT1("Failed to create pdcNew\n");
643 NtGdiDeleteObjectApp(DisplayDC
);
647 hdcNew
= pdcNew
->BaseObject
.hHmgr
;
649 pdcattrOld
= pdcOld
->pdcattr
;
650 pdcattrNew
= pdcNew
->pdcattr
;
652 /* Copy information from original DC to new DC */
653 pdcNew
->dclevel
.hdcSave
= hdcNew
;
655 pdcNew
->dhpdev
= pdcOld
->dhpdev
;
657 pdcNew
->rosdc
.bitsPerPixel
= pdcOld
->rosdc
.bitsPerPixel
;
659 /* DriverName is copied in the AllocDC routine */
660 pdcattrNew
->ptlWindowOrg
= pdcattrOld
->ptlWindowOrg
;
661 pdcattrNew
->szlWindowExt
= pdcattrOld
->szlWindowExt
;
662 pdcattrNew
->ptlViewportOrg
= pdcattrOld
->ptlViewportOrg
;
663 pdcattrNew
->szlViewportExt
= pdcattrOld
->szlViewportExt
;
665 pdcNew
->dctype
= DC_TYPE_MEMORY
; // Always!
666 hsurf
= NtGdiGetStockObject(DEFAULT_BITMAP
);
667 pdcNew
->dclevel
.pSurface
= SURFACE_ShareLockSurface(hsurf
);
668 pdcNew
->ppdev
= pdcOld
->ppdev
;
669 pdcNew
->dclevel
.hpal
= pdcOld
->dclevel
.hpal
;
671 pdcattrNew
->lTextAlign
= pdcattrOld
->lTextAlign
;
672 pdcattrNew
->lBkMode
= pdcattrOld
->lBkMode
;
673 pdcattrNew
->jBkMode
= pdcattrOld
->jBkMode
;
674 pdcattrNew
->jROP2
= pdcattrOld
->jROP2
;
675 pdcattrNew
->dwLayout
= pdcattrOld
->dwLayout
;
676 if (pdcattrOld
->dwLayout
& LAYOUT_ORIENTATIONMASK
) Layout
= pdcattrOld
->dwLayout
;
677 pdcNew
->dclevel
.flPath
= pdcOld
->dclevel
.flPath
;
678 pdcattrNew
->ulDirty_
= pdcattrOld
->ulDirty_
;
679 pdcattrNew
->iCS_CP
= pdcattrOld
->iCS_CP
;
681 pdcNew
->erclWindow
.left
= pdcNew
->erclWindow
.top
= 0;
682 pdcNew
->erclWindow
.right
= pdcNew
->erclWindow
.bottom
= 1;
686 if (NULL
!= DisplayDC
)
688 NtGdiDeleteObjectApp(DisplayDC
);
691 hVisRgn
= IntSysCreateRectRgn(0, 0, 1, 1);
694 GdiSelectVisRgn(hdcNew
, hVisRgn
);
695 REGION_FreeRgnByHandle(hVisRgn
);
697 if (Layout
) NtGdiSetLayout(hdcNew
, -1, Layout
);
706 NtGdiDeleteObjectApp(HANDLE DCHandle
)
708 /* Complete all pending operations */
709 NtGdiFlushUserBatch();
711 if (GDI_HANDLE_IS_STOCKOBJ(DCHandle
)) return TRUE
;
713 if (GDI_HANDLE_GET_TYPE(DCHandle
) != GDI_OBJECT_TYPE_DC
)
714 return GreDeleteObject((HGDIOBJ
) DCHandle
);
716 if (IsObjectDead((HGDIOBJ
)DCHandle
)) return TRUE
;
718 if (!GDIOBJ_OwnedByCurrentProcess(DCHandle
))
720 SetLastWin32Error(ERROR_INVALID_HANDLE
);
724 return IntGdiDeleteDC(DCHandle
, FALSE
);
729 NewNtGdiDeleteObjectApp(HANDLE DCHandle
)
733 if (GDI_HANDLE_IS_STOCKOBJ(DCHandle
)) return TRUE
;
735 ObjType
= GDI_HANDLE_GET_TYPE(DCHandle
) >> GDI_ENTRY_UPPER_SHIFT
;
737 if (GreGetObjectOwner( DCHandle
, ObjType
))
741 case GDIObjType_DC_TYPE
:
742 return IntGdiDeleteDC(DCHandle
, FALSE
);
744 case GDIObjType_RGN_TYPE
:
745 case GDIObjType_SURF_TYPE
:
746 case GDIObjType_PAL_TYPE
:
747 case GDIObjType_LFONT_TYPE
:
748 case GDIObjType_BRUSH_TYPE
:
749 return GreDeleteObject((HGDIOBJ
) DCHandle
);
755 return (DCHandle
!= NULL
);