--- trunk/reactos/lib/user32/windows/bitmap.c 2005-01-02 23:46:28 UTC (rev 12741)
+++ trunk/reactos/lib/user32/windows/bitmap.c 2005-01-03 00:46:42 UTC (rev 12742)
@@ -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 @@
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 @@
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;
- }
+ 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;
- }
+ 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;
- }
+ 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.
+ /*
+ * 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.
*/
- hScreenDc = CreateCompatibleDC(0);
- if (hScreenDc == NULL)
- {
- UnmapViewOfFile(IconDIR);
- return NULL;
- }
+ if (ColorBits > 8)
+ ColorBits = 8;
+ }
- 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);
+ /* Pick the best size. */
+ dirEntry = (CURSORICONDIRENTRY *)CURSORICON_FindBestIcon(IconDIR, 32, 32, ColorBits);
+ if (!dirEntry)
+ {
+ UnmapViewOfFile(IconDIR);
+ return(NULL);
}
- //at this point we have a copy of the icon image to play with
+ SafeIconImage = RtlAllocateHeap(GetProcessHeap(), 0, dirEntry->dwBytesInRes);
+ memcpy(SafeIconImage, ((PBYTE)IconDIR) + dirEntry->dwImageOffset, dirEntry->dwBytesInRes);
- SafeIconImage->icHeader.biHeight = SafeIconImage->icHeader.biHeight /2;
+ /* at this point we have a copy of the icon image to play with */
- if (SafeIconImage->icHeader.biSize == sizeof(BITMAPCOREHEADER))
- {
+ 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 @@
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);
--- trunk/reactos/subsys/win32k/ntuser/cursoricon.c 2005-01-02 23:46:28 UTC (rev 12741)
+++ trunk/reactos/subsys/win32k/ntuser/cursoricon.c 2005-01-03 00:46:42 UTC (rev 12742)
@@ -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 <w32k.h>
+static PAGED_LOOKASIDE_LIST ProcessLookasideList;
+static LIST_ENTRY CurIconList;
+static FAST_MUTEX CurIconListLock;
+
PCURICON_OBJECT FASTCALL
IntGetCurIconObject(PWINSTATION_OBJECT WinStaObject, HANDLE Handle)
{
@@ -248,48 +271,97 @@
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;
+}
+
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 = CONTAINING_RECORD(CurrentEntry, CURICON_OBJECT, ListEntry);
+ CurrentEntry = CurrentEntry->Flink;
+ if((Object->hModule == hModule) && (Object->hRsrc == hRsrc))
{
- Object = (PCURICON_OBJECT)Current->Handles[i].ObjectBody;
- if(Object && (ObmReferenceObjectByPointer(Object, otCursorIcon) == STATUS_SUCCESS))
+ if(cx && ((cx != Object->Size.cx) || (cy != Object->Size.cy)))
{
- 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);
+ continue;
}
+ if (! ReferenceCurIconByProcess(Object))
+ {
+ ExReleaseFastMutex(&CurIconListLock);
+ return NULL;
+ }
+ ExReleaseFastMutex(&CurIconListLock);
+ return Object;
}
- CurrentEntry = CurrentEntry->Flink;
}
- ObmpUnlockHandleTable(HandleTable);
+ ExReleaseFastMutex(&CurIconListLock);
+
return NULL;
}
@@ -298,7 +370,6 @@
{
PCURICON_OBJECT Object;
HANDLE Handle;
- PW32PROCESS Win32Process;
Object = ObmCreateObject(WinStaObject->HandleTable, &Handle, otCursorIcon, sizeof(CURICON_OBJECT));
@@ -308,39 +379,90 @@
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);
if (CurInfo->CurrentCursorObject == Object)
@@ -351,15 +473,8 @@
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 @@
GDIOBJ_SetOwnership(bmpColor, PsGetCurrentProcess());
NtGdiDeleteObject(bmpColor);
}
-
- ObmDereferenceObject(Object);
return Ret;
}
@@ -382,23 +495,50 @@
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;
+ 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);
}
- ObDereferenceObject(WinStaObject);
}
+
+ ExReleaseFastMutex(&CurIconListLock);
+ ObDereferenceObject(WinStaObject);
}
/*
@@ -729,6 +869,8 @@
DWORD Unknown)
{
PWINSTATION_OBJECT WinStaObject;
+ PCURICON_OBJECT Object;
+ NTSTATUS Status;
WinStaObject = IntGetWinStaObj();
if(WinStaObject == NULL)
@@ -736,14 +878,24 @@
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;
}
+ ObmDereferenceObject(Object);
+ ObDereferenceObject(WinStaObject);
SetLastWin32Error(ERROR_INVALID_CURSOR_HANDLE);
- ObDereferenceObject(WinStaObject);
return FALSE;
}