[1/2] USER: Use 32-bit user handles for cursors / icons

H. Verbeet hverbeet at gmail.com
Sun May 28 16:46:38 CDT 2006


This patch makes cursors and icons use 32-bit user handles. For now,
the only thing we store in the handle is the 16-bit handle to the
memory block.

Changelog:
  - Use 32-bit user handles for cursors / icons
-------------- next part --------------
diff --git a/dlls/user/cursoricon.c b/dlls/user/cursoricon.c
index d563457..e1e952f 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,117 @@ static CRITICAL_SECTION IconCrst = { &cr
 
 static WORD ICON_HOTSPOT = 0x4242;
 
+#define CURSOR_HASH_SIZE 97
+
+typedef struct cursor16to32_t
+{
+    HCURSOR16       cursor16;
+    HCURSOR         cursor32;
+    struct list     entry;
+} cursor16to32_t;
+
+static struct list cursor16to32[CURSOR_HASH_SIZE];
+
+static inline int hash_cursor_handle( HCURSOR16 cursor16 )
+{
+    return cursor16 % CURSOR_HASH_SIZE;
+}
+
+static void add_cursor16to32_entry( HCURSOR16 cursor16, HCURSOR cursor32 )
+{
+    cursor16to32_t *e = HeapAlloc( GetProcessHeap(), 0, sizeof(cursor16to32_t) );
+    int idx = hash_cursor_handle( cursor16 );
+
+    if (!cursor16to32[idx].next) list_init( &cursor16to32[idx] );
+
+    e->cursor16 = cursor16;
+    e->cursor32 = cursor32;
+    list_add_head( &cursor16to32[idx], &e->entry );
+}
+
+static void remove_cursor16to32_entry( HCURSOR16 cursor16 )
+{
+    cursor16to32_t *e;
+    int idx = hash_cursor_handle( cursor16 );
+
+    if (cursor16to32[idx].next)
+    {
+        LIST_FOR_EACH_ENTRY( e, &cursor16to32[idx], cursor16to32_t, entry )
+            if (e->cursor16 == cursor16)
+            {
+                list_remove( &e->entry );
+                HeapFree(GetProcessHeap(), 0, e);
+            }
+    }
+}
+
+static cursor_object *get_cursor_object( HCURSOR handle )
+{
+    cursor_object *cursor = NULL;
+
+    SERVER_START_REQ(get_cursor)
+    {
+        req->handle = handle;
+        if (!wine_server_call_err( req )) cursor = reply->cursor;
+    }
+    SERVER_END_REQ;
+
+    return cursor;
+}
+
+static HCURSOR create_cursor_handle( cursor_object *cursor )
+{
+    HCURSOR handle = INVALID_HANDLE_VALUE;
+
+    SERVER_START_REQ(create_cursor)
+    {
+        req->cursor = cursor;
+        if (!wine_server_call_err( req )) handle = reply->handle;
+    }
+    SERVER_END_REQ;
+
+    add_cursor16to32_entry( cursor->cursor16, handle );
+
+    return handle;
+}
+
+static HCURSOR16 destroy_cursor( HCURSOR handle )
+{
+    cursor_object *cursor = NULL;
+
+    SERVER_START_REQ(destroy_cursor)
+    {
+        req->handle = handle;
+        if (!wine_server_call_err( req )) cursor = reply->cursor;
+    }
+    SERVER_END_REQ;
+
+    remove_cursor16to32_entry( cursor->cursor16 );
+    return GlobalFree16( cursor->cursor16 );
+}
+
+HCURSOR get_cursor_handle32( HCURSOR16 cursor16 )
+{
+    cursor16to32_t *e;
+    int idx = hash_cursor_handle( cursor16 );
+
+    if (cursor16to32[idx].next)
+    {
+        LIST_FOR_EACH_ENTRY( e, &cursor16to32[idx], cursor16to32_t, entry )
+            if (e->cursor16 == cursor16) return e->cursor32;
+    }
+
+    return INVALID_HANDLE_VALUE;
+}
+
+HCURSOR16 get_cursor_handle16( HCURSOR handle )
+{
+    cursor_object *cursor = get_cursor_object( handle );
+
+    if (!cursor) return INVALID_HANDLE_VALUE16;
+
+    return cursor->cursor16;
+}
 
 /***********************************************************************
  *             map_fileW
@@ -468,7 +581,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;
         }
@@ -678,6 +791,7 @@ HICON WINAPI CreateIconFromResourceEx( L
                                        UINT cFlag )
 {
     HGLOBAL16 hObj;
+    cursor_object *cursor;
     static HDC hdcMem;
     int sizeAnd, sizeXor;
     HBITMAP hAndBits = 0, hXorBits = 0; /* error condition for later */
@@ -873,7 +987,10 @@ HICON WINAPI CreateIconFromResourceEx( L
 
     DeleteObject( hAndBits );
     DeleteObject( hXorBits );
-    return HICON_32((HICON16)hObj);
+
+    cursor = HeapAlloc( GetProcessHeap(), 0, sizeof(cursor_object) );
+    cursor->cursor16 = hObj;
+    return create_cursor_handle( cursor );
 }
 
 
@@ -1011,6 +1128,7 @@ static HICON CURSORICON_Load(HINSTANCE h
  */
 static HICON CURSORICON_Copy( HINSTANCE16 hInst16, HICON hIcon )
 {
+    cursor_object *cursor;
     char *ptrOld, *ptrNew;
     int size;
     HICON16 hOld = HICON_16(hIcon);
@@ -1025,7 +1143,10 @@ static HICON CURSORICON_Copy( HINSTANCE1
     memcpy( ptrNew, ptrOld, size );
     GlobalUnlock16( hOld );
     GlobalUnlock16( hNew );
-    return HICON_32(hNew);
+
+    cursor = HeapAlloc( GetProcessHeap(), 0, sizeof(cursor_object) );
+    cursor->cursor16 = hNew;
+    return create_cursor_handle( cursor );
 }
 
 /*************************************************************************
@@ -1415,7 +1536,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;
 }
 
@@ -1809,6 +1930,7 @@ BOOL WINAPI GetIconInfo(HICON hIcon, PIC
  */
 HICON WINAPI CreateIconIndirect(PICONINFO iconinfo)
 {
+    cursor_object *cursor;
     BITMAP bmpXor,bmpAnd;
     HICON16 hObj;
     int	sizeXor,sizeAnd;
@@ -1862,7 +1984,10 @@ HICON WINAPI CreateIconIndirect(PICONINF
         if (iconinfo->hbmColor) GetBitmapBits( iconinfo->hbmColor, sizeXor, (char*)(info + 1) + sizeAnd );
         GlobalUnlock16( hObj );
     }
-    return HICON_32(hObj);
+
+    cursor = HeapAlloc( GetProcessHeap(), 0, sizeof(cursor_object) );
+    cursor->cursor16 = hObj;
+    return create_cursor_handle( cursor );
 }
 
 /******************************************************************************
diff --git a/dlls/user/user_private.h b/dlls/user/user_private.h
index a58ba5e..ab504a7 100644
--- a/dlls/user/user_private.h
+++ b/dlls/user/user_private.h
@@ -233,12 +233,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 handle );
+HCURSOR get_cursor_handle32( HCURSOR16 handle );
+
+#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..075bd1f 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)SetClassLongA( 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)SetClassLongA( WIN_Handle32(hwnd16), offset, (LONG_PTR)HCURSOR_32( newval ) ));
     case GCLP_WNDPROC:
         {
             WNDPROC new_proc = WINPROC_AllocProc16( (WNDPROC16)newval );
diff --git a/include/wine/winuser16.h b/include/wine/winuser16.h
index 8ed9965..b229e4e 100644
--- a/include/wine/winuser16.h
+++ b/include/wine/winuser16.h
@@ -148,6 +148,11 @@ typedef struct
 
 /* Cursors / Icons */
 
+typedef struct cursor_object
+{
+    HCURSOR16   cursor16;
+} cursor_object;
+
 typedef struct tagCURSORICONINFO
 {
     POINT16 ptHotSpot;
diff --git a/server/protocol.def b/server/protocol.def
index 0e18ab3..1d1be46 100644
--- a/server/protocol.def
+++ b/server/protocol.def
@@ -1787,6 +1787,30 @@ #define NAMED_PIPE_SERVER_END           
 @END
 
 
+/* Create a cursor */
+ at REQ(create_cursor)
+    void*           cursor;
+ at REPLY
+    user_handle_t   handle;
+ at END
+
+
+/* Destroy a cursor */
+ at REQ(destroy_cursor)
+    user_handle_t   handle;
+ at REPLY
+    void*           cursor;
+ at END
+
+
+/* Get the cursor from the handle */
+ at REQ(get_cursor)
+    user_handle_t   handle;
+ at REPLY
+    void*           cursor;
+ at END
+
+
 /* Create a window */
 @REQ(create_window)
     user_handle_t  parent;      /* parent window */
diff --git a/server/user.c b/server/user.c
index ff5b670..1b75259 100644
--- a/server/user.c
+++ b/server/user.c
@@ -18,6 +18,7 @@
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  */
 
+#include "request.h"
 #include "thread.h"
 #include "user.h"
 
@@ -164,3 +165,21 @@ void *next_user_handle( user_handle_t *h
     }
     return NULL;
 }
+
+/* create a cursor */
+DECL_HANDLER(create_cursor)
+{
+    reply->handle = alloc_user_handle( req->cursor, USER_CURSOR );
+}
+
+/* destroy a cursor */
+DECL_HANDLER(destroy_cursor)
+{
+    reply->cursor = free_user_handle( req->handle );
+}
+
+/* get the cursor from the handle */
+DECL_HANDLER(get_cursor)
+{
+    reply->cursor = get_user_object( req->handle, USER_CURSOR );
+}
diff --git a/server/user.h b/server/user.h
index da169c1..809fefc 100644
--- a/server/user.h
+++ b/server/user.h
@@ -35,7 +35,8 @@ struct clipboard;
 enum user_object
 {
     USER_WINDOW = 1,
-    USER_HOOK
+    USER_HOOK,
+    USER_CURSOR
 };
 
 #define DESKTOP_ATOM  ((atom_t)32769)






More information about the wine-patches mailing list