From 8c1121a5beb4f7239c1399243dd4ab89739a3633 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A9=20van=20Geldorp?= Date: Mon, 3 Jan 2005 00:46:42 +0000 Subject: [PATCH] Don't destroy cursors/icons prematurely. svn path=/trunk/; revision=12742 --- reactos/include/napi/win32.h | 2 - reactos/lib/user32/windows/bitmap.c | 158 +++++------ reactos/subsys/win32k/include/cursoricon.h | 11 +- reactos/subsys/win32k/main/dllmain.c | 5 +- reactos/subsys/win32k/ntuser/cursoricon.c | 316 +++++++++++++++------ 5 files changed, 322 insertions(+), 170 deletions(-) diff --git a/reactos/include/napi/win32.h b/reactos/include/napi/win32.h index 3807f97b7af..0c04b2b76c3 100644 --- a/reactos/include/napi/win32.h +++ b/reactos/include/napi/win32.h @@ -28,8 +28,6 @@ typedef struct _W32PROCESS LIST_ENTRY MenuListHead; FAST_MUTEX PrivateFontListLock; LIST_ENTRY PrivateFontListHead; - FAST_MUTEX CursorIconListLock; - LIST_ENTRY CursorIconListHead; struct _KBDTABLES* KeyboardLayout; ULONG Flags; LONG GDIObjects; diff --git a/reactos/lib/user32/windows/bitmap.c b/reactos/lib/user32/windows/bitmap.c index 88021e92876..26fae34e3ea 100644 --- a/reactos/lib/user32/windows/bitmap.c +++ b/reactos/lib/user32/windows/bitmap.c @@ -16,7 +16,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/* $Id: bitmap.c,v 1.34 2004/12/19 05:00:22 royce Exp $ +/* $Id$ * * PROJECT: ReactOS user32.dll * FILE: lib/user32/windows/input.c @@ -149,7 +149,7 @@ LoadCursorImage(HINSTANCE hinst, LPCWSTR lpszName, UINT fuLoad) hIcon = (HANDLE)CreateIconFromResourceEx((PBYTE)ResIcon, SizeofResource(hinst, h2Resource), FALSE, 0x00030000, 32, 32, fuLoad & (LR_DEFAULTCOLOR | LR_MONOCHROME)); - if (hIcon) + if (hIcon && 0 != (fuLoad & LR_SHARED)) { NtUserSetCursorIconData((HICON)hIcon, NULL, NULL, hinst, (HRSRC)hfRes, (HRSRC)NULL); @@ -157,100 +157,98 @@ LoadCursorImage(HINSTANCE hinst, LPCWSTR lpszName, UINT fuLoad) return hIcon; } - else + + if (fuLoad & LR_SHARED) { - if (fuLoad & LR_SHARED) - { - DbgPrint("FIXME: need LR_SHARED support loading cursor images from files\n"); - } + DbgPrint("FIXME: need LR_SHARED support loading cursor images from files\n"); + } - hFile = CreateFileW(lpszName, GENERIC_READ, FILE_SHARE_READ, NULL, - OPEN_EXISTING, 0, NULL); - if (hFile == NULL) - { - return NULL; - } - - hSection = CreateFileMappingW(hFile, NULL, PAGE_READONLY, 0, 0, NULL); - CloseHandle(hFile); - if (hSection == NULL) - { - return NULL; - } - - IconDIR = MapViewOfFile(hSection, FILE_MAP_READ, 0, 0, 0); - CloseHandle(hSection); - if (IconDIR == NULL || 0 != IconDIR->idReserved - || (IMAGE_ICON != IconDIR->idType && IMAGE_CURSOR != IconDIR->idType)) - { - return NULL; - } - - /* - * Get a handle to the screen dc, the icon we create is going to be - * compatable with it. - */ - hScreenDc = CreateCompatibleDC(0); - if (hScreenDc == NULL) - { - UnmapViewOfFile(IconDIR); - return NULL; - } - - if (fuLoad & LR_MONOCHROME) - { - ColorBits = 1; - } - else - { - ColorBits = GetDeviceCaps(hScreenDc, BITSPIXEL); - /* - * FIXME: - * Remove this after proper support for alpha icons will be finished. - */ - if (ColorBits > 8) - ColorBits = 8; - } - - /* Pick the best size. */ - dirEntry = (CURSORICONDIRENTRY *)CURSORICON_FindBestIcon(IconDIR, 32, 32, ColorBits); - if (!dirEntry) - { - UnmapViewOfFile(IconDIR); - return(NULL); - } - - SafeIconImage = RtlAllocateHeap(GetProcessHeap(), 0, dirEntry->dwBytesInRes); - memcpy(SafeIconImage, ((PBYTE)IconDIR) + dirEntry->dwImageOffset, dirEntry->dwBytesInRes); + hFile = CreateFileW(lpszName, GENERIC_READ, FILE_SHARE_READ, NULL, + OPEN_EXISTING, 0, NULL); + if (hFile == NULL) + { + return NULL; } - //at this point we have a copy of the icon image to play with + hSection = CreateFileMappingW(hFile, NULL, PAGE_READONLY, 0, 0, NULL); + CloseHandle(hFile); + if (hSection == NULL) + { + return NULL; + } - SafeIconImage->icHeader.biHeight = SafeIconImage->icHeader.biHeight /2; + IconDIR = MapViewOfFile(hSection, FILE_MAP_READ, 0, 0, 0); + CloseHandle(hSection); + if (IconDIR == NULL || 0 != IconDIR->idReserved + || (IMAGE_ICON != IconDIR->idType && IMAGE_CURSOR != IconDIR->idType)) + { + return NULL; + } - if (SafeIconImage->icHeader.biSize == sizeof(BITMAPCOREHEADER)) - { + /* + * Get a handle to the screen dc, the icon we create is going to be + * compatable with it. + */ + hScreenDc = CreateCompatibleDC(0); + if (hScreenDc == NULL) + { + UnmapViewOfFile(IconDIR); + return NULL; + } + + if (fuLoad & LR_MONOCHROME) + { + ColorBits = 1; + } + else + { + ColorBits = GetDeviceCaps(hScreenDc, BITSPIXEL); + /* + * FIXME: + * Remove this after proper support for alpha icons will be finished. + */ + if (ColorBits > 8) + ColorBits = 8; + } + + /* Pick the best size. */ + dirEntry = (CURSORICONDIRENTRY *)CURSORICON_FindBestIcon(IconDIR, 32, 32, ColorBits); + if (!dirEntry) + { + UnmapViewOfFile(IconDIR); + return(NULL); + } + + SafeIconImage = RtlAllocateHeap(GetProcessHeap(), 0, dirEntry->dwBytesInRes); + memcpy(SafeIconImage, ((PBYTE)IconDIR) + dirEntry->dwImageOffset, dirEntry->dwBytesInRes); + + /* at this point we have a copy of the icon image to play with */ + + SafeIconImage->icHeader.biHeight = SafeIconImage->icHeader.biHeight /2; + + if (SafeIconImage->icHeader.biSize == sizeof(BITMAPCOREHEADER)) + { BITMAPCOREHEADER* Core = (BITMAPCOREHEADER*)SafeIconImage; ColorCount = (Core->bcBitCount <= 8) ? (1 << Core->bcBitCount) : 0; HeaderSize = sizeof(BITMAPCOREHEADER) + ColorCount * sizeof(RGBTRIPLE); - } - else - { + } + else + { ColorCount = SafeIconImage->icHeader.biClrUsed; if (ColorCount == 0 && SafeIconImage->icHeader.biBitCount <= 8) { ColorCount = 1 << SafeIconImage->icHeader.biBitCount; } HeaderSize = sizeof(BITMAPINFOHEADER) + ColorCount * sizeof(RGBQUAD); - } + } - //make data point to the start of the XOR image data - Data = (PBYTE)SafeIconImage + HeaderSize; + /* make data point to the start of the XOR image data */ + Data = (PBYTE)SafeIconImage + HeaderSize; - hIcon = ICON_CreateCursorFromData(hScreenDc, Data, SafeIconImage, 32, 32, dirEntry->Info.cursor.wXHotspot, dirEntry->Info.cursor.wYHotspot); - DeleteDC(hScreenDc); - RtlFreeHeap(GetProcessHeap(), 0, SafeIconImage); - return hIcon; + hIcon = ICON_CreateCursorFromData(hScreenDc, Data, SafeIconImage, 32, 32, dirEntry->Info.cursor.wXHotspot, dirEntry->Info.cursor.wYHotspot); + DeleteDC(hScreenDc); + RtlFreeHeap(GetProcessHeap(), 0, SafeIconImage); + return hIcon; } @@ -326,7 +324,7 @@ LoadIconImage(HINSTANCE hinst, LPCWSTR lpszName, INT width, INT height, UINT fuL hIcon = (HANDLE)CreateIconFromResourceEx((PBYTE) ResIcon, SizeofResource(hinst, h2Resource), TRUE, 0x00030000, width, height, fuLoad & (LR_DEFAULTCOLOR | LR_MONOCHROME)); - if(hIcon) + if (hIcon && 0 != (fuLoad & LR_SHARED)) { NtUserSetCursorIconData((HICON)hIcon, NULL, NULL, hinst, (HRSRC)hfRes, (HRSRC)NULL); diff --git a/reactos/subsys/win32k/include/cursoricon.h b/reactos/subsys/win32k/include/cursoricon.h index 620799c4cbd..8507630cc96 100644 --- a/reactos/subsys/win32k/include/cursoricon.h +++ b/reactos/subsys/win32k/include/cursoricon.h @@ -3,11 +3,18 @@ #define MAXCURICONHANDLES 4096 -typedef struct _CURICON_OBJECT +typedef struct tagCURICON_PROCESS { - HANDLE Self; LIST_ENTRY ListEntry; PW32PROCESS Process; +} CURICON_PROCESS, *PCURICON_PROCESS; + +typedef struct _CURICON_OBJECT +{ + LIST_ENTRY ListEntry; + HANDLE Self; + FAST_MUTEX Lock; + LIST_ENTRY ProcessList; HMODULE hModule; HRSRC hRsrc; HRSRC hGroupRsrc; diff --git a/reactos/subsys/win32k/main/dllmain.c b/reactos/subsys/win32k/main/dllmain.c index ef624d43774..7645c45bd23 100644 --- a/reactos/subsys/win32k/main/dllmain.c +++ b/reactos/subsys/win32k/main/dllmain.c @@ -16,7 +16,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/* $Id: dllmain.c,v 1.86 2004/12/29 19:55:01 gvg Exp $ +/* $Id$ * * Entry Point for win32k.sys */ @@ -71,9 +71,6 @@ Win32kProcessCallback (struct _EPROCESS *Process, InitializeListHead(&Win32Process->PrivateFontListHead); ExInitializeFastMutex(&Win32Process->PrivateFontListLock); - InitializeListHead(&Win32Process->CursorIconListHead); - ExInitializeFastMutex(&Win32Process->CursorIconListLock); - Win32Process->KeyboardLayout = W32kGetDefaultKeyLayout(); /* setup process flags */ diff --git a/reactos/subsys/win32k/ntuser/cursoricon.c b/reactos/subsys/win32k/ntuser/cursoricon.c index 3d83602772e..b456b72cdcb 100644 --- a/reactos/subsys/win32k/ntuser/cursoricon.c +++ b/reactos/subsys/win32k/ntuser/cursoricon.c @@ -16,9 +16,32 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/* $Id: cursoricon.c,v 1.5 2004/12/30 02:32:18 navaraf Exp $ */ + +/* + * We handle two types of cursors/icons: + * - Private + * Loaded without LR_SHARED flag + * Private to a process + * Can be deleted by calling NtDestroyCursorIcon() + * CurIcon->hModule, CurIcon->hRsrc and CurIcon->hGroupRsrc set to NULL + * - Shared + * Loaded with LR_SHARED flag + * Possibly shared by multiple processes + * Immune to NtDestroyCursorIcon() + * CurIcon->hModule, CurIcon->hRsrc and CurIcon->hGroupRsrc are valid + * There's a M:N relationship between processes and (shared) cursor/icons. + * A process can have multiple cursor/icons and a cursor/icon can be used + * by multiple processes. To keep track of this we keep a list of all + * cursor/icons (CurIconList) and per cursor/icon we keep a list of + * CURICON_PROCESS structs starting at CurIcon->ProcessList. + */ + #include +static PAGED_LOOKASIDE_LIST ProcessLookasideList; +static LIST_ENTRY CurIconList; +static FAST_MUTEX CurIconListLock; + PCURICON_OBJECT FASTCALL IntGetCurIconObject(PWINSTATION_OBJECT WinStaObject, HANDLE Handle) { @@ -248,6 +271,61 @@ IntSetCursor(PWINSTATION_OBJECT WinStaObject, PCURICON_OBJECT NewCursor, BOOL FASTCALL IntSetupCurIconHandles(PWINSTATION_OBJECT WinStaObject) { + ExInitializePagedLookasideList(&ProcessLookasideList, + NULL, + NULL, + 0, + sizeof(CURICON_PROCESS), + 0, + 128); + InitializeListHead(&CurIconList); + ExInitializeFastMutex(&CurIconListLock); + + return TRUE; +} + +/* + * We have to register that this object is in use by the current + * process. The only way to do that seems to be to walk the list + * of cursor/icon objects starting at W32Process->CursorIconListHead. + * If the object is already present in the list, we don't have to do + * anything, if it's not present we add it and inc the ProcessCount + * in the object. Having to walk the list kind of sucks, but that's + * life... + */ +static BOOLEAN FASTCALL +ReferenceCurIconByProcess(PCURICON_OBJECT Object) +{ + PW32PROCESS Win32Process; + PLIST_ENTRY Search; + PCURICON_PROCESS Current; + + Win32Process = PsGetWin32Process(); + + ExAcquireFastMutex(&Object->Lock); + Search = Object->ProcessList.Flink; + while (Search != &Object->ProcessList) + { + Current = CONTAINING_RECORD(Search, CURICON_PROCESS, ListEntry); + if (Current->Process == Win32Process) + { + /* Already registered for this process */ + ExReleaseFastMutex(&Object->Lock); + return TRUE; + } + Search = Search->Flink; + } + + /* Not registered yet */ + Current = ExAllocateFromPagedLookasideList(&ProcessLookasideList); + if (NULL == Current) + { + return FALSE; + } + InsertHeadList(&Object->ProcessList, &Current->ListEntry); + Current->Process = Win32Process; + + ExReleaseFastMutex(&Object->Lock); return TRUE; } @@ -255,41 +333,35 @@ PCURICON_OBJECT FASTCALL IntFindExistingCurIconObject(PWINSTATION_OBJECT WinStaObject, HMODULE hModule, HRSRC hRsrc, LONG cx, LONG cy) { - PUSER_HANDLE_TABLE HandleTable; PLIST_ENTRY CurrentEntry; - PUSER_HANDLE_BLOCK Current; PCURICON_OBJECT Object; - ULONG i; - - HandleTable = (PUSER_HANDLE_TABLE)WinStaObject->HandleTable; - ObmpLockHandleTable(HandleTable); - - CurrentEntry = HandleTable->ListHead.Flink; - while(CurrentEntry != &HandleTable->ListHead) + + ExAcquireFastMutex(&CurIconListLock); + + CurrentEntry = CurIconList.Flink; + while (CurrentEntry != &CurIconList) { - Current = CONTAINING_RECORD(CurrentEntry, USER_HANDLE_BLOCK, ListEntry); - for(i = 0; i < HANDLE_BLOCK_ENTRIES; i++) - { - Object = (PCURICON_OBJECT)Current->Handles[i].ObjectBody; - if(Object && (ObmReferenceObjectByPointer(Object, otCursorIcon) == STATUS_SUCCESS)) - { - if((Object->hModule == hModule) && (Object->hRsrc == hRsrc)) - { - if(cx && ((cx != Object->Size.cx) || (cy != Object->Size.cy))) - { - ObmDereferenceObject(Object); - continue; - } - ObmpUnlockHandleTable(HandleTable); - return Object; - } - ObmDereferenceObject(Object); - } - } + Object = CONTAINING_RECORD(CurrentEntry, CURICON_OBJECT, ListEntry); CurrentEntry = CurrentEntry->Flink; + if((Object->hModule == hModule) && (Object->hRsrc == hRsrc)) + { + if(cx && ((cx != Object->Size.cx) || (cy != Object->Size.cy))) + { + ObmDereferenceObject(Object); + continue; + } + if (! ReferenceCurIconByProcess(Object)) + { + ExReleaseFastMutex(&CurIconListLock); + return NULL; + } + ExReleaseFastMutex(&CurIconListLock); + return Object; + } } - ObmpUnlockHandleTable(HandleTable); + ExReleaseFastMutex(&CurIconListLock); + return NULL; } @@ -298,7 +370,6 @@ IntCreateCurIconHandle(PWINSTATION_OBJECT WinStaObject) { PCURICON_OBJECT Object; HANDLE Handle; - PW32PROCESS Win32Process; Object = ObmCreateObject(WinStaObject->HandleTable, &Handle, otCursorIcon, sizeof(CURICON_OBJECT)); @@ -308,38 +379,89 @@ IntCreateCurIconHandle(PWINSTATION_OBJECT WinStaObject) return FALSE; } - Win32Process = PsGetWin32Process(); - - IntLockProcessCursorIcons(Win32Process); - InsertTailList(&Win32Process->CursorIconListHead, &Object->ListEntry); - IntUnLockProcessCursorIcons(Win32Process); - Object->Self = Handle; - Object->Process = PsGetWin32Process(); - + ExInitializeFastMutex(&Object->Lock); + InitializeListHead(&Object->ProcessList); + + if (! ReferenceCurIconByProcess(Object)) + { + DPRINT1("Failed to add process\n"); + ObmCloseHandle(WinStaObject->HandleTable, Handle); + ObmDereferenceObject(Object); + return NULL; + } + + ExAcquireFastMutex(&CurIconListLock); + InsertHeadList(&CurIconList, &Object->ListEntry); + ExReleaseFastMutex(&CurIconListLock); + + ObmDereferenceObject(Object); + return Object; } -BOOL FASTCALL -IntDestroyCurIconObject(PWINSTATION_OBJECT WinStaObject, HANDLE Handle, BOOL RemoveFromProcess) +BOOLEAN FASTCALL +IntDestroyCurIconObject(PWINSTATION_OBJECT WinStaObject, PCURICON_OBJECT Object, BOOL ProcessCleanup) { PSYSTEM_CURSORINFO CurInfo; - PCURICON_OBJECT Object; HBITMAP bmpMask, bmpColor; - NTSTATUS Status; - BOOL Ret; - - Status = ObmReferenceObjectByHandle(WinStaObject->HandleTable, Handle, otCursorIcon, (PVOID*)&Object); - if(!NT_SUCCESS(Status)) - { - return FALSE; - } - - if (Object->Process != PsGetWin32Process()) - { - ObmDereferenceObject(Object); - return FALSE; - } + BOOLEAN Ret; + PLIST_ENTRY Search; + PCURICON_PROCESS Current; + PW32PROCESS W32Process = PsGetWin32Process(); + + ExAcquireFastMutex(&Object->Lock); + + /* Private objects can only be destroyed by their own process */ + if (NULL == Object->hModule) + { + ASSERT(Object->ProcessList.Flink->Flink == &Object->ProcessList); + Current = CONTAINING_RECORD(Object->ProcessList.Flink, CURICON_PROCESS, ListEntry); + if (Current->Process != W32Process) + { + ExReleaseFastMutex(&Object->Lock); + DPRINT1("Trying to destroy private icon/cursor of another process\n"); + return FALSE; + } + } + else if (! ProcessCleanup) + { + ExReleaseFastMutex(&Object->Lock); + DPRINT("Trying to destroy shared icon/cursor\n"); + return FALSE; + } + + /* Now find this process in the list of processes referencing this object and + remove it from that list */ + Search = Object->ProcessList.Flink; + while (Search != &Object->ProcessList) + { + Current = CONTAINING_RECORD(Object->ProcessList.Flink, CURICON_PROCESS, ListEntry); + if (Current->Process == W32Process) + { + break; + } + Search = Search->Flink; + } + ASSERT(Search != &Object->ProcessList); + RemoveEntryList(Search); + ExFreeToPagedLookasideList(&ProcessLookasideList, Current); + + /* If there are still processes referencing this object we can't destroy it yet */ + if (! IsListEmpty(&Object->ProcessList)) + { + ExReleaseFastMutex(&Object->Lock); + return TRUE; + } + + ExReleaseFastMutex(&Object->Lock); + + if (! ProcessCleanup) + { + ExAcquireFastMutex(&CurIconListLock); + RemoveEntryList(&Object->ListEntry); + ExReleaseFastMutex(&CurIconListLock); + } CurInfo = IntGetSysCursorInfo(WinStaObject); @@ -351,15 +473,8 @@ IntDestroyCurIconObject(PWINSTATION_OBJECT WinStaObject, HANDLE Handle, BOOL Rem bmpMask = Object->IconInfo.hbmMask; bmpColor = Object->IconInfo.hbmColor; - - if (Object->Process && RemoveFromProcess) - { - IntLockProcessCursorIcons(Object->Process); - RemoveEntryList(&Object->ListEntry); - IntUnLockProcessCursorIcons(Object->Process); - } - Ret = NT_SUCCESS(ObmCloseHandle(WinStaObject->HandleTable, Handle)); + Ret = NT_SUCCESS(ObmCloseHandle(WinStaObject->HandleTable, Object->Self)); /* delete bitmaps */ if(bmpMask) @@ -372,8 +487,6 @@ IntDestroyCurIconObject(PWINSTATION_OBJECT WinStaObject, HANDLE Handle, BOOL Rem GDIOBJ_SetOwnership(bmpColor, PsGetCurrentProcess()); NtGdiDeleteObject(bmpColor); } - - ObmDereferenceObject(Object); return Ret; } @@ -382,23 +495,50 @@ VOID FASTCALL IntCleanupCurIcons(struct _EPROCESS *Process, PW32PROCESS Win32Process) { PWINSTATION_OBJECT WinStaObject; - PCURICON_OBJECT Current; - PLIST_ENTRY CurrentEntry, NextEntry; - + PLIST_ENTRY CurrentEntry; + PCURICON_OBJECT Object; + PLIST_ENTRY ProcessEntry; + PCURICON_PROCESS ProcessData; + WinStaObject = IntGetWinStaObj(); - if(WinStaObject != NULL) + if(WinStaObject == NULL) { - CurrentEntry = Win32Process->CursorIconListHead.Flink; - while(CurrentEntry != &Win32Process->CursorIconListHead) - { - NextEntry = CurrentEntry->Flink; - Current = CONTAINING_RECORD(CurrentEntry, CURICON_OBJECT, ListEntry); - RemoveEntryList(&Current->ListEntry); - IntDestroyCurIconObject(WinStaObject, Current->Self, FALSE); - CurrentEntry = NextEntry; - } - ObDereferenceObject(WinStaObject); + return; } + + ExAcquireFastMutex(&CurIconListLock); + + CurrentEntry = CurIconList.Flink; + while (CurrentEntry != &CurIconList) + { + Object = CONTAINING_RECORD(CurrentEntry, CURICON_OBJECT, ListEntry); + CurrentEntry = CurrentEntry->Flink; + if(NT_SUCCESS(ObmReferenceObjectByPointer(Object, otCursorIcon))) + { + ExAcquireFastMutex(&Object->Lock); + ProcessEntry = Object->ProcessList.Flink; + while (ProcessEntry != &Object->ProcessList) + { + ProcessData = CONTAINING_RECORD(ProcessEntry, CURICON_PROCESS, ListEntry); + if (Win32Process == ProcessData->Process) + { + ExReleaseFastMutex(&Object->Lock); + RemoveEntryList(&Object->ListEntry); + IntDestroyCurIconObject(WinStaObject, Object, TRUE); + break; + } + ProcessEntry = ProcessEntry->Flink; + } + if (ProcessEntry == &Object->ProcessList) + { + ExReleaseFastMutex(&Object->Lock); + } + ObmDereferenceObject(Object); + } + } + + ExReleaseFastMutex(&CurIconListLock); + ObDereferenceObject(WinStaObject); } /* @@ -729,6 +869,8 @@ NtUserDestroyCursorIcon( DWORD Unknown) { PWINSTATION_OBJECT WinStaObject; + PCURICON_OBJECT Object; + NTSTATUS Status; WinStaObject = IntGetWinStaObj(); if(WinStaObject == NULL) @@ -736,14 +878,24 @@ NtUserDestroyCursorIcon( return FALSE; } - if(IntDestroyCurIconObject(WinStaObject, Handle, TRUE)) + Status = ObmReferenceObjectByHandle(WinStaObject->HandleTable, Handle, otCursorIcon, (PVOID*)&Object); + if(!NT_SUCCESS(Status)) { + ObDereferenceObject(WinStaObject); + SetLastNtError(Status); + return FALSE; + } + + if(IntDestroyCurIconObject(WinStaObject, Object, FALSE)) + { + ObmDereferenceObject(Object); ObDereferenceObject(WinStaObject); return TRUE; } - SetLastWin32Error(ERROR_INVALID_CURSOR_HANDLE); + ObmDereferenceObject(Object); ObDereferenceObject(WinStaObject); + SetLastWin32Error(ERROR_INVALID_CURSOR_HANDLE); return FALSE; }