[2/10] user: Create 32-bit cursor handles

H. Verbeet hverbeet at gmail.com
Sat Aug 5 16:38:53 CDT 2006


This makes user create 32-bit cursor handles, and adds code for
mapping between 16-bits and 32-bits cursor handles. It doesn't store
anything it the 32-bits cursors though, the next patch does that.
-------------- next part --------------
diff --git a/dlls/user/cursoricon.c b/dlls/user/cursoricon.c
index d563457..c644bc4 100644
--- a/dlls/user/cursoricon.c
+++ b/dlls/user/cursoricon.c
@@ -60,6 +60,8 @@ #include "wine/winbase16.h"
 #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);
@@ -132,6 +134,159 @@ static CRITICAL_SECTION IconCrst = { &cr
 
 static 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;
+
+    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
@@ -468,7 +623,7 @@ void CURSORICON_FreeModuleIcons( HMODULE
             ICONCACHE *freePtr = *ptr;
             *ptr = freePtr->next;
 
-            GlobalFree16(HICON_16(freePtr->hIcon));
+            destroy_cursor( freePtr->hIcon );
             HeapFree( GetProcessHeap(), 0, freePtr );
             continue;
         }
@@ -873,7 +1028,8 @@ HICON WINAPI CreateIconFromResourceEx( L
 
     DeleteObject( hAndBits );
     DeleteObject( hXorBits );
-    return HICON_32((HICON16)hObj);
+
+    return create_cursor( 1, 0, hObj );
 }
 
 
@@ -1025,7 +1181,8 @@ static HICON CURSORICON_Copy( HINSTANCE1
     memcpy( ptrNew, ptrOld, size );
     GlobalUnlock16( hOld );
     GlobalUnlock16( hNew );
-    return HICON_32(hNew);
+
+    return create_cursor( 1, 0, hNew );
 }
 
 /*************************************************************************
@@ -1346,7 +1503,7 @@ HGLOBAL16 WINAPI CreateCursorIconIndirec
     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 ));
 }
 
 
@@ -1415,7 +1572,7 @@ WORD WINAPI DestroyIcon32( HGLOBAL16 han
 
     /* Now assume non-shared cursor/icon */
 
-    retv = GlobalFree16( handle );
+    retv = destroy_cursor( HCURSOR_32(handle) );
     return (flags & CID_RESOURCE)? retv : TRUE;
 }
 
@@ -1862,7 +2019,8 @@ HICON WINAPI CreateIconIndirect(PICONINF
         if (iconinfo->hbmColor) GetBitmapBits( iconinfo->hbmColor, sizeXor, (char*)(info + 1) + sizeAnd );
         GlobalUnlock16( hObj );
     }
-    return HICON_32(hObj);
+
+    return create_cursor( 1, 0, hObj );
 }
 
 /******************************************************************************
diff --git a/dlls/user/user_private.h b/dlls/user/user_private.h
index ffb2796..9bd1d38 100644
--- a/dlls/user/user_private.h
+++ b/dlls/user/user_private.h
@@ -232,12 +232,15 @@ extern void SPY_ExitMessage( INT iFlag, 
 extern int SPY_Init(void);
 
 /* 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/user/wnd16.c b/dlls/user/wnd16.c
index ea68d62..a91d147 100644
--- a/dlls/user/wnd16.c
+++ b/dlls/user/wnd16.c
@@ -648,7 +648,17 @@ void WINAPI ValidateRgn16( HWND16 hwnd, 
  */
 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;
+    }
 }
 
 
@@ -657,7 +667,15 @@ WORD WINAPI GetClassWord16( HWND16 hwnd,
  */
 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 );
+    }
 }
 
 
@@ -670,6 +688,10 @@ LONG WINAPI GetClassLong16( HWND16 hwnd1
 
     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:
@@ -687,6 +709,10 @@ LONG WINAPI SetClassLong16( HWND16 hwnd1
 {
     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 );


More information about the wine-patches mailing list