BOOL NTAPI GreSetBitmapOwner( _In_ HBITMAP hbmp, _In_ ULONG ulOwner) { /* Check if we have the correct object type */ if (GDI_HANDLE_GET_TYPE(hbmp) != GDILoObjType_LO_BITMAP_TYPE) { DPRINT1("Incorrect type for hbmp: %p\n", hbmp); return FALSE; } /// FIXME: this is a hack and doesn't handle a race condition properly. /// It needs to be done in GDIOBJ_vSetObjectOwner atomically. /* Check if we set public or none */ if ((ulOwner == GDI_OBJ_HMGR_PUBLIC) || (ulOwner == GDI_OBJ_HMGR_NONE)) { /* Only allow this for owned objects */ if (GreGetObjectOwner(hbmp) != GDI_OBJ_HMGR_POWNED) { DPRINT1("Cannot change owner for non-powned hbmp\n"); return FALSE; } } return GreSetObjectOwner(hbmp, ulOwner); }
/* IntUpdateMonitorSize * * Reset size of the monitor using atached device * * Arguments * * PMONITOR * pGdiDevice Pointer to the PDEVOBJ, which size has changed * * Return value * Returns a NTSTATUS */ NTSTATUS IntUpdateMonitorSize(IN PDEVOBJ *pGdiDevice) { PMONITOR Monitor; for (Monitor = gMonitorList; Monitor != NULL; Monitor = Monitor->Next) { if (Monitor->GdiDevice == pGdiDevice) break; } if (Monitor == NULL) { /* no monitor for given device found */ return STATUS_INVALID_PARAMETER; } Monitor->rcMonitor.left = 0; Monitor->rcMonitor.top = 0; Monitor->rcMonitor.right = Monitor->rcMonitor.left + Monitor->GdiDevice->gdiinfo.ulHorzRes; Monitor->rcMonitor.bottom = Monitor->rcMonitor.top + Monitor->GdiDevice->gdiinfo.ulVertRes; Monitor->rcWork = Monitor->rcMonitor; if (Monitor->hrgnMonitor) { GreSetObjectOwner(Monitor->hrgnMonitor, GDI_OBJ_HMGR_POWNED); GreDeleteObject(Monitor->hrgnMonitor); } Monitor->hrgnMonitor = IntSysCreateRectRgnIndirect( &Monitor->rcMonitor ); IntGdiSetRegionOwner(Monitor->hrgnMonitor, GDI_OBJ_HMGR_PUBLIC); return STATUS_SUCCESS; }
HANDLE NTAPI UserSetClipboardData(UINT fmt, HANDLE hData, PSETCLIPBDATA scd) { HANDLE hRet = NULL; PWINSTATION_OBJECT pWinStaObj = NULL; pWinStaObj = IntGetWinStaForCbAccess(); if (!pWinStaObj) goto cleanup; /* If it's delayed rendering we don't have to open clipboard */ if ((pWinStaObj->fInDelayedRendering && pWinStaObj->spwndClipOwner->head.pti != PsGetCurrentThreadWin32Thread()) || !IntIsClipboardOpenByMe(pWinStaObj)) { ERR("Access denied!\n"); EngSetLastError(ERROR_CLIPBOARD_NOT_OPEN); goto cleanup; } if (scd->fIncSerialNumber) pWinStaObj->iClipSerialNumber++; /* Is it a delayed render? */ if (hData) { /* Is it a bitmap? */ if (fmt == CF_BITMAP) { /* Make bitmap public */ GreSetObjectOwner(hData, GDI_OBJ_HMGR_PUBLIC); } /* Save data in the clipboard */ IntAddFormatedData(pWinStaObj, fmt, hData, scd->fGlobalHandle, FALSE); TRACE("hData stored\n"); pWinStaObj->iClipSequenceNumber++; pWinStaObj->fClipboardChanged = TRUE; /* Note: Synthesized formats are added in NtUserCloseClipboard */ } else { /* This is a delayed render */ IntAddFormatedData(pWinStaObj, fmt, DATA_DELAYED, FALSE, FALSE); TRACE("SetClipboardData delayed format: %u\n", fmt); } /* Return hData on success */ hRet = hData; cleanup: TRACE("NtUserSetClipboardData returns: %p\n", hRet); if(pWinStaObj) ObDereferenceObject(pWinStaObj); return hRet; }
static VOID WINAPI IntSynthesizeBitmap(PWINSTATION_OBJECT pWinStaObj, PCLIP pBmEl) { HDC hdc = NULL; PBITMAPINFO pBmi, pConvertedBmi = NULL; HBITMAP hBm = NULL; PCLIPBOARDDATA pMemObj; PCLIP pDibEl; ULONG Offset; TRACE("IntSynthesizeBitmap(%p, %p)\n", pWinStaObj, pBmEl); pDibEl = IntIsFormatAvailable(pWinStaObj, CF_DIB); ASSERT(pDibEl && !IS_DATA_SYNTHESIZED(pDibEl)); if(!pDibEl->fGlobalHandle) return; pMemObj = (PCLIPBOARDDATA)UserGetObject(gHandleTable, pDibEl->hData, TYPE_CLIPDATA); if (!pMemObj) return; pBmi = (BITMAPINFO*)pMemObj->Data; if (pMemObj->cbData < sizeof(DWORD) && pMemObj->cbData < pBmi->bmiHeader.biSize) goto cleanup; pConvertedBmi = DIB_ConvertBitmapInfo(pBmi, DIB_RGB_COLORS); if (!pConvertedBmi) goto cleanup; Offset = DIB_BitmapInfoSize(pBmi, DIB_RGB_COLORS); hdc = UserGetDCEx(NULL, NULL, DCX_USESTYLE); if (!hdc) goto cleanup; hBm = GreCreateDIBitmapInternal(hdc, pConvertedBmi->bmiHeader.biWidth, pConvertedBmi->bmiHeader.biHeight, CBM_INIT, pMemObj->Data + Offset, pConvertedBmi, DIB_RGB_COLORS, 0, pMemObj->cbData - Offset, 0); if (hBm) { GreSetObjectOwner(hBm, GDI_OBJ_HMGR_PUBLIC); pBmEl->hData = hBm; } cleanup: if (hdc) UserReleaseDC(NULL, hdc, FALSE); if (pConvertedBmi) DIB_FreeConvertedBitmapInfo(pConvertedBmi, pBmi, -1); }
/* IntDestroyMonitorObject * * Destroys a MONITOR * You have to be the owner of the monitors lock to safely destroy it. * * Arguments * * pMonitor * Pointer to the MONITOR which shall be deleted */ static void IntDestroyMonitorObject(IN PMONITOR pMonitor) { /* Remove monitor region */ if (pMonitor->hrgnMonitor) { GreSetObjectOwner(pMonitor->hrgnMonitor, GDI_OBJ_HMGR_POWNED); GreDeleteObject(pMonitor->hrgnMonitor); } /* Destroy monitor object */ UserDereferenceObject(pMonitor); UserDeleteObject(UserHMGetHandle(pMonitor), TYPE_MONITOR); }
VOID NTAPI DC_vSetOwner(PDC pdc, ULONG ulOwner) { if (pdc->rosdc.hClipRgn) { IntGdiSetRegionOwner(pdc->rosdc.hClipRgn, ulOwner); } if (pdc->rosdc.hGCClipRgn) { IntGdiSetRegionOwner(pdc->rosdc.hGCClipRgn, ulOwner); } if (pdc->dclevel.hPath) { GreSetObjectOwner(pdc->dclevel.hPath, ulOwner); } /* Dereference current brush and pen */ BRUSH_ShareUnlockBrush(pdc->dclevel.pbrFill); BRUSH_ShareUnlockBrush(pdc->dclevel.pbrLine); /* Select the default fill and line brush */ pdc->dcattr.hbrush = StockObjects[WHITE_BRUSH]; pdc->dcattr.hpen = StockObjects[BLACK_PEN]; pdc->dclevel.pbrFill = BRUSH_ShareLockBrush(pdc->pdcattr->hbrush); pdc->dclevel.pbrLine = PEN_ShareLockPen(pdc->pdcattr->hpen); /* Mark them as dirty */ pdc->pdcattr->ulDirty_ |= DIRTY_FILL|DIRTY_LINE; /* Allocate or free DC attribute */ if (ulOwner == GDI_OBJ_HMGR_PUBLIC || ulOwner == GDI_OBJ_HMGR_NONE) { if (pdc->pdcattr != &pdc->dcattr) DC_vFreeDcAttr(pdc); } else if (ulOwner == GDI_OBJ_HMGR_POWNED) { if (pdc->pdcattr == &pdc->dcattr) DC_bAllocDcAttr(pdc); } /* Set the DC's ownership */ GDIOBJ_vSetObjectOwner(&pdc->BaseObject, ulOwner); }
static VOID FASTCALL IntFreeElementData(PCLIP pElement) { if (!IS_DATA_DELAYED(pElement) && !IS_DATA_SYNTHESIZED(pElement)) { if (pElement->fGlobalHandle) UserDeleteObject(pElement->hData, TYPE_CLIPDATA); else if (pElement->fmt == CF_BITMAP || pElement->fmt == CF_PALETTE || pElement->fmt == CF_DSPBITMAP) { GreSetObjectOwner(pElement->hData, GDI_OBJ_HMGR_POWNED); GreDeleteObject(pElement->hData); } } }
/* UserUpdateMonitorSize * * Reset size of the monitor using atached device * * Arguments * * PMONITOR * pGdiDevice Pointer to the PDEVOBJ, which size has changed * * Return value * Returns a NTSTATUS */ NTSTATUS NTAPI UserUpdateMonitorSize(IN HDEV hDev) { PMONITOR pMonitor; SIZEL DeviceSize; /* Find monitor attached to given device */ for (pMonitor = gMonitorList; pMonitor != NULL; pMonitor = pMonitor->pMonitorNext) { if (pMonitor->hDev == hDev) break; } if (pMonitor == NULL) { /* No monitor has been found */ return STATUS_INVALID_PARAMETER; } /* Get the size of the hdev */ PDEVOBJ_sizl((PPDEVOBJ)hDev, &DeviceSize); /* Update monitor size */ pMonitor->rcMonitor.left = 0; pMonitor->rcMonitor.top = 0; pMonitor->rcMonitor.right = pMonitor->rcMonitor.left + DeviceSize.cx; pMonitor->rcMonitor.bottom = pMonitor->rcMonitor.top + DeviceSize.cy; pMonitor->rcWork = pMonitor->rcMonitor; /* Destroy monitor region... */ if (pMonitor->hrgnMonitor) { GreSetObjectOwner(pMonitor->hrgnMonitor, GDI_OBJ_HMGR_POWNED); GreDeleteObject(pMonitor->hrgnMonitor); } /* ...and create new one */ pMonitor->hrgnMonitor = NtGdiCreateRectRgn( pMonitor->rcMonitor.left, pMonitor->rcMonitor.top, pMonitor->rcMonitor.right, pMonitor->rcMonitor.bottom); if (pMonitor->hrgnMonitor) IntGdiSetRegionOwner(pMonitor->hrgnMonitor, GDI_OBJ_HMGR_PUBLIC); return STATUS_SUCCESS; }
VOID NTAPI DC_vSetOwner(PDC pdc, ULONG ulOwner) { if (pdc->rosdc.hClipRgn) { IntGdiSetRegionOwner(pdc->rosdc.hClipRgn, ulOwner); } if (pdc->rosdc.hGCClipRgn) { IntGdiSetRegionOwner(pdc->rosdc.hGCClipRgn, ulOwner); } if (pdc->dclevel.hPath) { GreSetObjectOwner(pdc->dclevel.hPath, ulOwner); } IntGdiSetBrushOwner(pdc->dclevel.pbrFill, ulOwner); IntGdiSetBrushOwner(pdc->dclevel.pbrLine, ulOwner); /* Allocate or free DC attribute */ if (ulOwner == GDI_OBJ_HMGR_PUBLIC || ulOwner == GDI_OBJ_HMGR_NONE) { if (pdc->pdcattr != &pdc->dcattr) DC_vFreeDcAttr(pdc); } else if (ulOwner == GDI_OBJ_HMGR_POWNED) { if (pdc->pdcattr == &pdc->dcattr) DC_bAllocDcAttr(pdc); } /* Set the DC's ownership */ GDIOBJ_vSetObjectOwner(&pdc->BaseObject, ulOwner); }
/* * @implemented */ BOOL APIENTRY NtUserSetCursorIconData( _In_ HCURSOR Handle, _In_opt_ PUNICODE_STRING pustrModule, _In_opt_ PUNICODE_STRING pustrRsrc, _In_ const CURSORDATA* pCursorData) { PCURICON_OBJECT CurIcon; NTSTATUS Status = STATUS_SUCCESS; BOOLEAN Ret = FALSE; BOOLEAN IsShared = FALSE, IsAnim = FALSE; DWORD numFrames; UINT i = 0; TRACE("Enter NtUserSetCursorIconData\n"); UserEnterExclusive(); if (!(CurIcon = UserGetCurIconObject(Handle))) { UserLeave(); EngSetLastError(ERROR_INVALID_HANDLE); return FALSE; } _SEH2_TRY { ProbeForRead(pCursorData, sizeof(*pCursorData), 1); if(pCursorData->CURSORF_flags & CURSORF_ACON) { /* This is an animated cursor */ PACON AniCurIcon = (PACON)CurIcon; DWORD numSteps; numFrames = AniCurIcon->cpcur = pCursorData->cpcur; numSteps = AniCurIcon->cicur = pCursorData->cicur; AniCurIcon->iicur = pCursorData->iicur; AniCurIcon->rt = pCursorData->rt; /* Calculate size: one cursor object for each frame, and a frame index and jiffies for each "step" */ AniCurIcon->aspcur = ExAllocatePoolWithTag(PagedPool | POOL_RAISE_IF_ALLOCATION_FAILURE, /* Let SEH catch allocation failures */ numFrames * sizeof(CURICON_OBJECT*) + numSteps * (sizeof(DWORD) + sizeof(INT)), USERTAG_CURSOR); AniCurIcon->aicur = (DWORD*)(AniCurIcon->aspcur + numFrames); AniCurIcon->ajifRate = (INT*)(AniCurIcon->aicur + numSteps); RtlZeroMemory(AniCurIcon->aspcur, numFrames * sizeof(CURICON_OBJECT*)); ProbeForRead(pCursorData->aicur, numSteps * sizeof(DWORD), 1); RtlCopyMemory(AniCurIcon->aicur, pCursorData->aicur, numSteps * sizeof(DWORD)); ProbeForRead(pCursorData->ajifRate, numSteps * sizeof(INT), 1); RtlCopyMemory(AniCurIcon->ajifRate, pCursorData->ajifRate, numSteps * sizeof(INT)); AniCurIcon->CURSORF_flags = pCursorData->CURSORF_flags; pCursorData = pCursorData->aspcur; IsAnim = TRUE; } else { CurIcon->xHotspot = pCursorData->xHotspot; CurIcon->yHotspot = pCursorData->yHotspot; CurIcon->cx = pCursorData->cx; CurIcon->cy = pCursorData->cy; CurIcon->rt = pCursorData->rt; CurIcon->bpp = pCursorData->bpp; CurIcon->hbmMask = pCursorData->hbmMask; CurIcon->hbmColor = pCursorData->hbmColor; CurIcon->hbmAlpha = pCursorData->hbmAlpha; CurIcon->CURSORF_flags = pCursorData->CURSORF_flags; } } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { Status = _SEH2_GetExceptionCode(); } _SEH2_END if (!NT_SUCCESS(Status)) { SetLastNtError(Status); goto done; } if(IsAnim) { PACON AniCurIcon = (PACON)CurIcon; /* This is an animated cursor. Create a cursor object for each frame and set up the data */ for(i = 0; i < numFrames; i++) { HANDLE hCurFrame = IntCreateCurIconHandle(FALSE); if(!NtUserSetCursorIconData(hCurFrame, NULL, NULL, pCursorData)) goto done; AniCurIcon->aspcur[i] = UserGetCurIconObject(hCurFrame); if(!AniCurIcon->aspcur[i]) goto done; pCursorData++; } } if(CurIcon->CURSORF_flags & CURSORF_LRSHARED) { IsShared = TRUE; if(pustrRsrc && pustrModule) { UNICODE_STRING ustrModuleSafe; /* We use this convenient function, because INTRESOURCEs and ATOMs are the same */ Status = ProbeAndCaptureUnicodeStringOrAtom(&CurIcon->strName, pustrRsrc); if(!NT_SUCCESS(Status)) goto done; Status = ProbeAndCaptureUnicodeString(&ustrModuleSafe, UserMode, pustrModule); if(!NT_SUCCESS(Status)) goto done; Status = RtlAddAtomToAtomTable(gAtomTable, ustrModuleSafe.Buffer, &CurIcon->atomModName); ReleaseCapturedUnicodeString(&ustrModuleSafe, UserMode); if(!NT_SUCCESS(Status)) goto done; } } if(!CurIcon->hbmMask) { ERR("NtUserSetCursorIconData was got no hbmMask.\n"); EngSetLastError(ERROR_INVALID_PARAMETER); goto done; } GreSetObjectOwner(CurIcon->hbmMask, GDI_OBJ_HMGR_PUBLIC); if(CurIcon->hbmColor) GreSetObjectOwner(CurIcon->hbmColor, GDI_OBJ_HMGR_PUBLIC); if(CurIcon->hbmAlpha) GreSetObjectOwner(CurIcon->hbmAlpha, GDI_OBJ_HMGR_PUBLIC); if(IsShared) { /* Update process cache in case of shared cursor */ PPROCESSINFO ppi = CurIcon->head.ppi; UserReferenceObject(CurIcon); CurIcon->pcurNext = ppi->pCursorCache; ppi->pCursorCache = CurIcon; } Ret = TRUE; done: if(!Ret && IsShared) { if(!IS_INTRESOURCE(CurIcon->strName.Buffer)) ExFreePoolWithTag(CurIcon->strName.Buffer, TAG_STRING); } if(!Ret && IsAnim) { PACON AniCurIcon = (PACON)CurIcon; for(i = 0; i < numFrames; i++) { if(AniCurIcon->aspcur[i]) IntDestroyCurIconObject(AniCurIcon->aspcur[i], TRUE); } AniCurIcon->cicur = 0; AniCurIcon->cpcur = 0; ExFreePoolWithTag(AniCurIcon->aspcur, USERTAG_CURSOR); AniCurIcon->aspcur = NULL; AniCurIcon->aicur = NULL; AniCurIcon->ajifRate = NULL; } UserDereferenceObject(CurIcon); TRACE("Leave NtUserSetCursorIconData, ret=%i\n",Ret); UserLeave(); return Ret; }
/* * @implemented */ BOOL APIENTRY NtUserGetIconInfo( _In_ HANDLE hCurIcon, _Out_opt_ PICONINFO IconInfo, _Out_opt_ PUNICODE_STRING lpModule, // Optional _Out_opt_ PUNICODE_STRING lpResName, // Optional _Out_opt_ LPDWORD pbpp, // Optional _In_ BOOL bInternal) { ICONINFO ii; PCURICON_OBJECT CurIcon; NTSTATUS Status = STATUS_SUCCESS; BOOL Ret = FALSE; DWORD colorBpp = 0; TRACE("Enter NtUserGetIconInfo\n"); /* Check if something was actually asked */ if (!IconInfo && !lpModule && !lpResName) { WARN("Nothing to fill.\n"); EngSetLastError(ERROR_INVALID_PARAMETER); return FALSE; } UserEnterExclusive(); if (!(CurIcon = UserGetCurIconObject(hCurIcon))) { WARN("UserGetIconObject(0x%08x) Failed.\n", hCurIcon); UserLeave(); return FALSE; } /* Give back the icon information */ if(IconInfo) { PCURICON_OBJECT FrameCurIcon = CurIcon; if(CurIcon->CURSORF_flags & CURSORF_ACON) { /* Get information from first frame. */ FrameCurIcon = ((PACON)CurIcon)->aspcur[0]; } /* Fill data */ ii.fIcon = is_icon(FrameCurIcon); ii.xHotspot = FrameCurIcon->xHotspot; ii.yHotspot = FrameCurIcon->yHotspot; /* Copy bitmaps */ ii.hbmMask = BITMAP_CopyBitmap(FrameCurIcon->hbmMask); GreSetObjectOwner(ii.hbmMask, GDI_OBJ_HMGR_POWNED); ii.hbmColor = BITMAP_CopyBitmap(FrameCurIcon->hbmColor); GreSetObjectOwner(ii.hbmColor, GDI_OBJ_HMGR_POWNED); colorBpp = FrameCurIcon->bpp; /* Copy fields */ _SEH2_TRY { ProbeForWrite(IconInfo, sizeof(ICONINFO), 1); RtlCopyMemory(IconInfo, &ii, sizeof(ICONINFO)); if (pbpp) { ProbeForWrite(pbpp, sizeof(DWORD), 1); *pbpp = colorBpp; } } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { Status = _SEH2_GetExceptionCode(); } _SEH2_END if (!NT_SUCCESS(Status)) { WARN("Status: 0x%08x.\n", Status); SetLastNtError(Status); goto leave; } } /* Give back the module name */ if(lpModule) { ULONG BufLen = 0; if (!CurIcon->atomModName) goto leave; RtlQueryAtomInAtomTable(gAtomTable, CurIcon->atomModName, NULL, NULL, NULL, &BufLen); /* Get the module name from the atom table */ _SEH2_TRY { if (BufLen > (lpModule->MaximumLength * sizeof(WCHAR))) { lpModule->Length = 0; } else { ProbeForWrite(lpModule->Buffer, lpModule->MaximumLength, 1); BufLen = lpModule->MaximumLength * sizeof(WCHAR); RtlQueryAtomInAtomTable(gAtomTable, CurIcon->atomModName, NULL, NULL, lpModule->Buffer, &BufLen); lpModule->Length = BufLen/sizeof(WCHAR); } } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { Status = _SEH2_GetExceptionCode(); } _SEH2_END if (!NT_SUCCESS(Status)) { SetLastNtError(Status); goto leave; } } if (lpResName) { if (!CurIcon->strName.Buffer) goto leave; /* Copy it */ _SEH2_TRY { ProbeForWrite(lpResName, sizeof(UNICODE_STRING), 1); if (IS_INTRESOURCE(CurIcon->strName.Buffer)) { lpResName->Buffer = CurIcon->strName.Buffer; lpResName->Length = 0; } else if (lpResName->MaximumLength < CurIcon->strName.Length) { lpResName->Length = 0; } else { ProbeForWrite(lpResName->Buffer, lpResName->MaximumLength * sizeof(WCHAR), 1); RtlCopyMemory(lpResName->Buffer, CurIcon->strName.Buffer, lpResName->Length); } } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { Status = _SEH2_GetExceptionCode(); } _SEH2_END } if (!NT_SUCCESS(Status)) { SetLastNtError(Status); goto leave; } Ret = TRUE; leave: UserDereferenceObject(CurIcon); TRACE("Leave NtUserGetIconInfo, ret=%i\n", Ret); UserLeave(); return Ret; }
BOOLEAN FASTCALL IntDestroyCurIconObject(PCURICON_OBJECT CurIcon, BOOLEAN bForce) { if(CurIcon->CURSORF_flags & CURSORF_CURRENT) { /* Mark the object as destroyed, and fail, as per tests */ TRACE("Cursor is current, marking as destroyed.\n"); UserDeleteObject(CurIcon->head.h, TYPE_CURSOR); return FALSE; } if(CurIcon->head.ppi != PsGetCurrentProcessWin32Process()) { /* This object doesn't belong to the current process */ WARN("Trying to delete foreign cursor!\n"); UserDereferenceObject(CurIcon); EngSetLastError(ERROR_DESTROY_OBJECT_OF_OTHER_THREAD); return FALSE; } /* Do not destroy it if it is shared. (And we're not forced to) */ if((CurIcon->CURSORF_flags & CURSORF_LRSHARED) && !bForce) { /* Tests show this is a valid call */ WARN("Trying to destroy shared cursor!\n"); UserDereferenceObject(CurIcon); return TRUE; } if(!(CurIcon->CURSORF_flags & CURSORF_ACON)) { HBITMAP bmpMask = CurIcon->hbmMask; HBITMAP bmpColor = CurIcon->hbmColor; HBITMAP bmpAlpha = CurIcon->hbmAlpha; /* Delete bitmaps */ if (bmpMask) { GreSetObjectOwner(bmpMask, GDI_OBJ_HMGR_POWNED); GreDeleteObject(bmpMask); CurIcon->hbmMask = NULL; } if (bmpColor) { GreSetObjectOwner(bmpColor, GDI_OBJ_HMGR_POWNED); GreDeleteObject(bmpColor); CurIcon->hbmColor = NULL; } if (bmpAlpha) { GreSetObjectOwner(bmpAlpha, GDI_OBJ_HMGR_POWNED); GreDeleteObject(bmpAlpha); CurIcon->hbmAlpha = NULL; } } else { PACON AniCurIcon = (PACON)CurIcon; UINT i; for(i = 0; i < AniCurIcon->cpcur; i++) IntDestroyCurIconObject(AniCurIcon->aspcur[i], TRUE); ExFreePoolWithTag(AniCurIcon->aspcur, USERTAG_CURSOR); } if (CurIcon->CURSORF_flags & CURSORF_LRSHARED) { if (!IS_INTRESOURCE(CurIcon->strName.Buffer)) ExFreePoolWithTag(CurIcon->strName.Buffer, TAG_STRING); if (CurIcon->atomModName) RtlDeleteAtomFromAtomTable(gAtomTable, CurIcon->atomModName); CurIcon->strName.Buffer = NULL; CurIcon->atomModName = 0; } /* We were given a pointer, no need to keep the reference any longer! */ UserDereferenceObject(CurIcon); return UserDeleteObject(CurIcon->head.h, TYPE_CURSOR); }