From b728b897616f4df463c57b36721534f41d375425 Mon Sep 17 00:00:00 2001 From: "H. Verbeet" Date: Mon, 17 Nov 2008 01:19:04 +0100 Subject: [PATCH] [02/10] user: Create 32-bit cursor handles --- dlls/user32/cursoricon.c | 170 +++++++++++++++++++++++++++++++++++++++++++-- dlls/user32/user_private.h | 11 +-- dlls/user32/wnd16.c | 30 +++++++- 3 files changed, 199 insertions(+), 12 deletions(-) diff --git a/dlls/user32/cursoricon.c b/dlls/user32/cursoricon.c index d8543516611..bb5dcdff1ad 100644 --- a/dlls/user32/cursoricon.c +++ b/dlls/user32/cursoricon.c @@ -55,6 +55,8 @@ #include "wine/winuser16.h" #include "wine/exception.h" #include "wine/debug.h" +#include "wine/list.h" +#include "wine/server.h" #include "user_private.h" WINE_DEFAULT_DEBUG_CHANNEL(cursor); @@ -127,6 +129,159 @@ static CRITICAL_SECTION IconCrst = { &critsect_debug, -1, 0, 0, 0, 0 }; static const WORD ICON_HOTSPOT = 0x4242; +/* What is a good table size? */ +#define CURSOR_HASH_SIZE 97 + +typedef struct { + HCURSOR16 cursor16; + HCURSOR cursor32; + struct list entry16; + struct list entry32; +} cursor_map_entry_t; + +static struct list cursor16to32[CURSOR_HASH_SIZE]; +static struct list cursor32to16[CURSOR_HASH_SIZE]; + +static inline int hash_cursor_handle( DWORD handle ) +{ + return handle % CURSOR_HASH_SIZE; +} + +static void add_cursor16to32_entry( cursor_map_entry_t *entry ) +{ + int idx = hash_cursor_handle( entry->cursor16 ); + + if (!cursor16to32[idx].next) list_init( &cursor16to32[idx] ); + + list_add_head( &cursor16to32[idx], &entry->entry16 ); +} + +static void add_cursor32to16_entry( cursor_map_entry_t *entry ) +{ + int idx = hash_cursor_handle( (DWORD)entry->cursor32 ); + + if (!cursor32to16[idx].next) list_init( &cursor32to16[idx] ); + + list_add_head( &cursor32to16[idx], &entry->entry32 ); +} + +static cursor_map_entry_t *remove_cursor16to32_entry( HCURSOR16 cursor16 ) +{ + cursor_map_entry_t *entry = NULL; + int idx = hash_cursor_handle( cursor16 ); + + if (cursor16to32[idx].next) + { + LIST_FOR_EACH_ENTRY( entry, &cursor16to32[idx], cursor_map_entry_t, entry16 ) + if (entry->cursor16 == cursor16) + { + list_remove( &entry->entry16 ); + return entry; + } + } + + return entry; +} + +static cursor_map_entry_t *remove_cursor32to16_entry( HCURSOR cursor32 ) +{ + cursor_map_entry_t *entry = NULL; + int idx = hash_cursor_handle( (DWORD)cursor32 ); + + if (cursor32to16[idx].next) + { + LIST_FOR_EACH_ENTRY( entry, &cursor32to16[idx], cursor_map_entry_t, entry32 ) + if (entry->cursor32 == cursor32) + { + list_remove( &entry->entry32 ); + return entry; + } + } + + return entry; +} + +static HCURSOR create_cursor( unsigned int num_frames, unsigned int delay, HCURSOR16 cursor16 ) +{ + HCURSOR cursor = 0; + + SERVER_START_REQ(create_cursor) + { + req->num_frames = num_frames; + req->delay = delay; + if (!wine_server_call_err( req )) cursor = reply->handle; + } + SERVER_END_REQ; + + if (cursor) + { + cursor_map_entry_t *entry = HeapAlloc( GetProcessHeap(), 0, sizeof(cursor_map_entry_t) ); + entry->cursor16 = cursor16; + entry->cursor32 = cursor; + + add_cursor16to32_entry( entry ); + add_cursor32to16_entry( entry ); + } + + return cursor; +} + +static HCURSOR16 destroy_cursor( HCURSOR cursor ) +{ + cursor_map_entry_t *entry; + HCURSOR16 cursor16 = 0; + + if (!cursor) return 0; + + SERVER_START_REQ(destroy_cursor) + { + req->handle = cursor; + wine_server_call( req ); + } + SERVER_END_REQ; + + entry = remove_cursor32to16_entry( cursor ); + if (entry) + { + cursor16 = entry->cursor16; + remove_cursor16to32_entry( cursor16 ); + HeapFree( GetProcessHeap(), 0, entry ); + } + + return GlobalFree16( cursor16 ); +} + +HCURSOR16 get_cursor_handle16( HCURSOR cursor32 ) +{ + cursor_map_entry_t *entry; + int idx = hash_cursor_handle( (DWORD)cursor32 ); + + if (!cursor32) return 0; + + if (cursor32to16[idx].next) + { + LIST_FOR_EACH_ENTRY( entry, &cursor32to16[idx], cursor_map_entry_t, entry32 ) + if (entry->cursor32 == cursor32) return entry->cursor16; + } + + return 0; +} + +HCURSOR get_cursor_handle32( HCURSOR16 cursor16 ) +{ + cursor_map_entry_t *entry; + int idx = hash_cursor_handle( cursor16 ); + + if (!cursor16) return 0; + + if (cursor16to32[idx].next) + { + LIST_FOR_EACH_ENTRY( entry, &cursor16to32[idx], cursor_map_entry_t, entry16 ) + if (entry->cursor16 == cursor16) return entry->cursor32; + } + + return 0; +} /*********************************************************************** * map_fileW @@ -463,7 +618,7 @@ void CURSORICON_FreeModuleIcons( HMODULE16 hMod16 ) ICONCACHE *freePtr = *ptr; *ptr = freePtr->next; - GlobalFree16(HICON_16(freePtr->hIcon)); + destroy_cursor( freePtr->hIcon ); HeapFree( GetProcessHeap(), 0, freePtr ); continue; } @@ -847,7 +1002,8 @@ static HICON CURSORICON_CreateIconFromBMI( BITMAPINFO *bmi, DeleteObject( hAndBits ); DeleteObject( hXorBits ); - return HICON_32(hObj); + + return create_cursor( 1, 0, hObj ); } @@ -1231,7 +1387,8 @@ static HICON CURSORICON_Copy( HINSTANCE16 hInst16, HICON hIcon ) memcpy( ptrNew, ptrOld, size ); GlobalUnlock16( hOld ); GlobalUnlock16( hNew ); - return HICON_32(hNew); + + return create_cursor( 1, 0, hNew ); } /************************************************************************* @@ -1500,7 +1657,7 @@ HGLOBAL16 WINAPI CreateCursorIconIndirect16( HINSTANCE16 hInstance, memcpy( ptr + sizeof(CURSORICONINFO), lpANDbits, sizeAnd ); memcpy( ptr + sizeof(CURSORICONINFO) + sizeAnd, lpXORbits, sizeXor ); GlobalUnlock16( handle ); - return handle; + return HICON_16(create_cursor( 1, 0, handle )); } @@ -1569,7 +1726,7 @@ WORD WINAPI DestroyIcon32( HGLOBAL16 handle, UINT16 flags ) /* Now assume non-shared cursor/icon */ - retv = GlobalFree16( handle ); + retv = destroy_cursor( HCURSOR_32(handle) ); return (flags & CID_RESOURCE)? retv : TRUE; } @@ -2139,7 +2296,8 @@ HICON WINAPI CreateIconIndirect(PICONINFO iconinfo) } GlobalUnlock16( hObj ); } - return HICON_32(hObj); + + return create_cursor( 1, 0, hObj ); } /****************************************************************************** diff --git a/dlls/user32/user_private.h b/dlls/user32/user_private.h index 744a1412c4a..a8f2c0c0337 100644 --- a/dlls/user32/user_private.h +++ b/dlls/user32/user_private.h @@ -307,12 +307,15 @@ extern void SPY_ExitMessage( INT iFlag, HWND hwnd, UINT msg, extern int SPY_Init(void) DECLSPEC_HIDDEN; /* HANDLE16 <-> HANDLE conversions */ -#define HCURSOR_16(h32) (LOWORD(h32)) -#define HICON_16(h32) (LOWORD(h32)) +HCURSOR16 get_cursor_handle16( HCURSOR cursor32 ); +HCURSOR get_cursor_handle32( HCURSOR16 cursor16 ); + +#define HCURSOR_16(h32) get_cursor_handle16(h32) +#define HICON_16(h32) get_cursor_handle16(h32) #define HINSTANCE_16(h32) (LOWORD(h32)) -#define HCURSOR_32(h16) ((HCURSOR)(ULONG_PTR)(h16)) -#define HICON_32(h16) ((HICON)(ULONG_PTR)(h16)) +#define HCURSOR_32(h16) get_cursor_handle32(h16) +#define HICON_32(h16) get_cursor_handle32(h16) #define HINSTANCE_32(h16) ((HINSTANCE)(ULONG_PTR)(h16)) #define HMODULE_32(h16) ((HMODULE)(ULONG_PTR)(h16)) diff --git a/dlls/user32/wnd16.c b/dlls/user32/wnd16.c index 1f7b0b00e77..d6f6c272822 100644 --- a/dlls/user32/wnd16.c +++ b/dlls/user32/wnd16.c @@ -647,7 +647,17 @@ void WINAPI ValidateRgn16( HWND16 hwnd, HRGN16 hrgn ) */ WORD WINAPI GetClassWord16( HWND16 hwnd, INT16 offset ) { - return GetClassWord( WIN_Handle32(hwnd), offset ); + WORD ret = GetClassWord( WIN_Handle32(hwnd), offset ); + + switch (offset) + { + case GCLP_HCURSOR: + case GCLP_HICON: + case GCLP_HICONSM: + return HCURSOR_16((HCURSOR)(LONG_PTR)ret); + default: + return ret; + } } @@ -656,7 +666,15 @@ WORD WINAPI GetClassWord16( HWND16 hwnd, INT16 offset ) */ WORD WINAPI SetClassWord16( HWND16 hwnd, INT16 offset, WORD newval ) { - return SetClassWord( WIN_Handle32(hwnd), offset, newval ); + switch (offset) + { + case GCLP_HCURSOR: + case GCLP_HICON: + case GCLP_HICONSM: + return HCURSOR_16((HCURSOR)SetClassLongW( WIN_Handle32(hwnd), offset, (LONG_PTR)HCURSOR_32(newval) )); + default: + return SetClassWord( WIN_Handle32(hwnd), offset, newval ); + } } @@ -669,6 +687,10 @@ LONG WINAPI GetClassLong16( HWND16 hwnd16, INT16 offset ) switch( offset ) { + case GCLP_HCURSOR: + case GCLP_HICON: + case GCLP_HICONSM: + return HCURSOR_16((HCURSOR)ret); case GCLP_WNDPROC: return (LONG_PTR)WINPROC_GetProc16( (WNDPROC)ret, FALSE ); case GCLP_MENUNAME: @@ -686,6 +708,10 @@ LONG WINAPI SetClassLong16( HWND16 hwnd16, INT16 offset, LONG newval ) { switch( offset ) { + case GCLP_HCURSOR: + case GCLP_HICON: + case GCLP_HICONSM: + return HCURSOR_16((HCURSOR)SetClassLongW( WIN_Handle32(hwnd16), offset, (LONG_PTR)HCURSOR_32( newval ) )); case GCLP_WNDPROC: { WNDPROC new_proc = WINPROC_AllocProc16( (WNDPROC16)newval ); -- 2.11.4.GIT