[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