win32u: Move user_handles from user32.

Signed-off-by: Jacek Caban <jacek@codeweavers.com>
Signed-off-by: Huw Davies <huw@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Jacek Caban 2022-02-22 13:52:53 +01:00 committed by Alexandre Julliard
parent 3e4f83f762
commit 018f8014a3
7 changed files with 185 additions and 126 deletions

View file

@ -50,19 +50,6 @@ extern void USER_unload_driver(void) DECLSPEC_HIDDEN;
struct received_message_info;
struct user_object
{
HANDLE handle;
unsigned int type;
};
#define OBJ_OTHER_PROCESS ((void *)1) /* returned by get_user_handle_ptr on unknown handles */
HANDLE alloc_user_handle( struct user_object *ptr, unsigned int type ) DECLSPEC_HIDDEN;
void *get_user_handle_ptr( HANDLE handle, unsigned int type ) DECLSPEC_HIDDEN;
void release_user_handle_ptr( void *ptr ) DECLSPEC_HIDDEN;
void *free_user_handle( HANDLE handle, unsigned int type ) DECLSPEC_HIDDEN;
/* type of message-sending functions that need special WM_CHAR handling */
enum wm_char_mapping
{

View file

@ -36,9 +36,6 @@
WINE_DEFAULT_DEBUG_CHANNEL(win);
#define NB_USER_HANDLES ((LAST_USER_HANDLE - FIRST_USER_HANDLE + 1) >> 1)
#define USER_HANDLE_TO_INDEX(hwnd) ((LOWORD(hwnd) - FIRST_USER_HANDLE) >> 1)
static DWORD process_layout = ~0u;
@ -87,31 +84,12 @@ static inline void set_win_data( void *ptr, LONG_PTR val, UINT size )
}
static void *user_handles[NB_USER_HANDLES];
/***********************************************************************
* alloc_user_handle
*/
HANDLE alloc_user_handle( struct user_object *ptr, unsigned int type )
{
HANDLE handle = 0;
SERVER_START_REQ( alloc_user_handle )
{
if (!wine_server_call_err( req )) handle = wine_server_ptr_handle( reply->handle );
}
SERVER_END_REQ;
if (handle)
{
UINT index = USER_HANDLE_TO_INDEX( handle );
assert( index < NB_USER_HANDLES );
ptr->handle = handle;
ptr->type = type;
InterlockedExchangePointer( &user_handles[index], ptr );
}
return handle;
return UlongToHandle( NtUserCallTwoParam( (UINT_PTR)ptr, type, NtUserAllocHandle ));
}
@ -120,23 +98,7 @@ HANDLE alloc_user_handle( struct user_object *ptr, unsigned int type )
*/
void *get_user_handle_ptr( HANDLE handle, unsigned int type )
{
struct user_object *ptr;
WORD index = USER_HANDLE_TO_INDEX( handle );
if (index >= NB_USER_HANDLES) return NULL;
USER_Lock();
if ((ptr = user_handles[index]))
{
if (ptr->type == type &&
((UINT)(UINT_PTR)ptr->handle == (UINT)(UINT_PTR)handle ||
!HIWORD(handle) || HIWORD(handle) == 0xffff))
return ptr;
ptr = NULL;
}
else ptr = OBJ_OTHER_PROCESS;
USER_Unlock();
return ptr;
return (void *)NtUserCallTwoParam( HandleToUlong(handle), type, NtUserGetHandlePtr );
}
@ -155,21 +117,7 @@ void release_user_handle_ptr( void *ptr )
*/
void *free_user_handle( HANDLE handle, unsigned int type )
{
struct user_object *ptr;
WORD index = USER_HANDLE_TO_INDEX( handle );
if ((ptr = get_user_handle_ptr( handle, type )) && ptr != OBJ_OTHER_PROCESS)
{
SERVER_START_REQ( free_user_handle )
{
req->handle = wine_server_user_handle( handle );
if (wine_server_call( req )) ptr = NULL;
else InterlockedCompareExchangePointer( &user_handles[index], NULL, ptr );
}
SERVER_END_REQ;
USER_Unlock();
}
return ptr;
return UlongToHandle( NtUserCallTwoParam( HandleToUlong(handle), type, NtUserFreeHandle ));
}
@ -182,7 +130,6 @@ static WND *create_window_handle( HWND parent, HWND owner, LPCWSTR name,
HINSTANCE instance, BOOL unicode,
DWORD style, DWORD ex_style )
{
WORD index;
WND *win;
HWND handle = 0, full_parent = 0, full_owner = 0;
struct tagCLASS *class = NULL;
@ -253,8 +200,6 @@ static WND *create_window_handle( HWND parent, HWND owner, LPCWSTR name,
USER_Lock();
index = USER_HANDLE_TO_INDEX(handle);
assert( index < NB_USER_HANDLES );
win->obj.handle = handle;
win->obj.type = NTUSER_OBJ_WINDOW;
win->parent = full_parent;
@ -264,7 +209,7 @@ static WND *create_window_handle( HWND parent, HWND owner, LPCWSTR name,
win->cbWndExtra = extra_bytes;
win->dpi = dpi;
win->dpi_awareness = awareness;
InterlockedExchangePointer( &user_handles[index], win );
NtUserCallTwoParam( HandleToUlong(handle), (UINT_PTR)win, NtUserSetHandlePtr );
if (WINPROC_IsUnicode( win->winproc, unicode )) win->flags |= WIN_ISUNICODE;
return win;
}
@ -278,7 +223,6 @@ static WND *create_window_handle( HWND parent, HWND owner, LPCWSTR name,
static void free_window_handle( HWND hwnd )
{
struct user_object *ptr;
WORD index = USER_HANDLE_TO_INDEX(hwnd);
if ((ptr = get_user_handle_ptr( hwnd, NTUSER_OBJ_WINDOW )) && ptr != OBJ_OTHER_PROCESS)
{
@ -286,7 +230,7 @@ static void free_window_handle( HWND hwnd )
{
req->handle = wine_server_user_handle( hwnd );
wine_server_call( req );
InterlockedCompareExchangePointer( &user_handles[index], NULL, ptr );
NtUserCallTwoParam( HandleToUlong(hwnd), 0, NtUserSetHandlePtr );
}
SERVER_END_REQ;
USER_Unlock();
@ -1156,20 +1100,7 @@ LRESULT WIN_DestroyWindow( HWND hwnd )
*/
static WND *next_thread_window( HWND *hwnd )
{
struct user_object *ptr;
WND *win;
WORD index = *hwnd ? USER_HANDLE_TO_INDEX( *hwnd ) + 1 : 0;
while (index < NB_USER_HANDLES)
{
if (!(ptr = user_handles[index++])) continue;
if (ptr->type != NTUSER_OBJ_WINDOW) continue;
win = (WND *)ptr;
if (win->tid != GetCurrentThreadId()) continue;
*hwnd = ptr->handle;
return win;
}
return NULL;
return (WND *)NtUserCallOneParam( (UINT_PTR)hwnd, NtUserNextThreadWindow );
}
@ -1187,7 +1118,7 @@ void destroy_thread_windows(void)
while ((win = next_thread_window( &hwnd )))
{
free_dce( win->dce, win->obj.handle );
InterlockedCompareExchangePointer( &user_handles[USER_HANDLE_TO_INDEX(hwnd)], NULL, win );
NtUserCallTwoParam( HandleToUlong(hwnd), 0, NtUserSetHandlePtr );
win->obj.handle = *free_list_ptr;
free_list_ptr = (WND **)&win->obj.handle;
}

View file

@ -33,43 +33,6 @@
struct tagCLASS;
struct tagDIALOGINFO;
typedef struct tagWND
{
struct user_object obj; /* object header */
HWND parent; /* Window parent */
HWND owner; /* Window owner */
struct tagCLASS *class; /* Window class */
struct dce *dce; /* DCE pointer */
WNDPROC winproc; /* Window procedure */
DWORD tid; /* Owner thread id */
HINSTANCE hInstance; /* Window hInstance (from CreateWindow) */
RECT client_rect; /* Client area rel. to parent client area */
RECT window_rect; /* Whole window rel. to parent client area */
RECT visible_rect; /* Visible part of the whole rect, rel. to parent client area */
RECT normal_rect; /* Normal window rect saved when maximized/minimized */
POINT min_pos; /* Position for minimized window */
POINT max_pos; /* Position for maximized window */
LPWSTR text; /* Window text */
void *pScroll; /* Scroll-bar info */
DWORD dwStyle; /* Window style (from CreateWindow) */
DWORD dwExStyle; /* Extended style (from CreateWindowEx) */
UINT_PTR wIDmenu; /* ID or hmenu (from CreateWindow) */
DWORD helpContext; /* Help context ID */
UINT flags; /* Misc. flags (see below) */
HMENU hSysMenu; /* window's copy of System Menu */
HICON hIcon; /* window's icon */
HICON hIconSmall; /* window's small icon */
HICON hIconSmall2; /* window's secondary small icon, derived from hIcon */
UINT dpi; /* window DPI */
DPI_AWARENESS dpi_awareness; /* DPI awareness */
struct window_surface *surface; /* Window surface if any */
struct tagDIALOGINFO *dlgInfo;/* Dialog additional info (dialogs only) */
int pixel_format; /* Pixel format set by the graphics driver */
int cbWndExtra; /* class cbWndExtra at window creation */
DWORD_PTR userdata; /* User private data */
DWORD wExtra[1]; /* Window extra bytes */
} WND;
/* WND flags values */
#define WIN_RESTORE_MAX 0x0001 /* Maximize when restoring */
#define WIN_NEED_SIZE 0x0002 /* Internal WM_SIZE is needed */

View file

@ -34,6 +34,59 @@ struct user_callbacks
HWND (WINAPI *pWindowFromDC)( HDC );
};
struct user_object
{
HANDLE handle;
unsigned int type;
};
#define OBJ_OTHER_PROCESS ((void *)1) /* returned by get_user_handle_ptr on unknown handles */
HANDLE alloc_user_handle( struct user_object *ptr, unsigned int type ) DECLSPEC_HIDDEN;
void *get_user_handle_ptr( HANDLE handle, unsigned int type ) DECLSPEC_HIDDEN;
void set_user_handle_ptr( HANDLE handle, struct user_object *ptr ) DECLSPEC_HIDDEN;
void release_user_handle_ptr( void *ptr ) DECLSPEC_HIDDEN;
void *free_user_handle( HANDLE handle, unsigned int type ) DECLSPEC_HIDDEN;
typedef struct tagWND
{
struct user_object obj; /* object header */
HWND parent; /* Window parent */
HWND owner; /* Window owner */
struct tagCLASS *class; /* Window class */
struct dce *dce; /* DCE pointer */
WNDPROC winproc; /* Window procedure */
DWORD tid; /* Owner thread id */
HINSTANCE hInstance; /* Window hInstance (from CreateWindow) */
RECT client_rect; /* Client area rel. to parent client area */
RECT window_rect; /* Whole window rel. to parent client area */
RECT visible_rect; /* Visible part of the whole rect, rel. to parent client area */
RECT normal_rect; /* Normal window rect saved when maximized/minimized */
POINT min_pos; /* Position for minimized window */
POINT max_pos; /* Position for maximized window */
WCHAR *text; /* Window text */
void *pScroll; /* Scroll-bar info */
DWORD dwStyle; /* Window style (from CreateWindow) */
DWORD dwExStyle; /* Extended style (from CreateWindowEx) */
UINT_PTR wIDmenu; /* ID or hmenu (from CreateWindow) */
DWORD helpContext; /* Help context ID */
UINT flags; /* Misc. flags (see below) */
HMENU hSysMenu; /* window's copy of System Menu */
HICON hIcon; /* window's icon */
HICON hIconSmall; /* window's small icon */
HICON hIconSmall2; /* window's secondary small icon, derived from hIcon */
UINT dpi; /* window DPI */
DPI_AWARENESS dpi_awareness; /* DPI awareness */
struct window_surface *surface; /* Window surface if any */
struct tagDIALOGINFO *dlgInfo; /* Dialog additional info (dialogs only) */
int pixel_format; /* Pixel format set by the graphics driver */
int cbWndExtra; /* class cbWndExtra at window creation */
DWORD_PTR userdata; /* User private data */
DWORD wExtra[1]; /* Window extra bytes */
} WND;
WND *next_thread_window_ptr( HWND *hwnd );
/* this is the structure stored in TEB->Win32ClientInfo */
/* no attempt is made to keep the layout compatible with the Windows one */
struct user_thread_info

View file

@ -4589,6 +4589,8 @@ ULONG_PTR WINAPI NtUserCallOneParam( ULONG_PTR arg, ULONG code )
case 1: user_unlock(); return 0;
default: user_check_not_lock(); return 0;
}
case NtUserNextThreadWindow:
return (UINT_PTR)next_thread_window_ptr( (HWND *)arg );
case NtUserSetCallbacks:
return (UINT_PTR)InterlockedExchangePointer( (void **)&user_callbacks, (void *)arg );
default:
@ -4615,9 +4617,18 @@ ULONG_PTR WINAPI NtUserCallTwoParam( ULONG_PTR arg1, ULONG_PTR arg2, ULONG code
case NtUserUnhookWindowsHook:
return unhook_windows_hook( arg1, (HOOKPROC)arg2 );
/* temporary exports */
case NtUserAllocHandle:
return HandleToUlong( alloc_user_handle( (struct user_object *)arg1, arg2 ));
case NtUserFreeHandle:
return (UINT_PTR)free_user_handle( UlongToHandle(arg1), arg2 );
case NtUserGetHandlePtr:
return (UINT_PTR)get_user_handle_ptr( UlongToHandle(arg1), arg2 );
case NtUserRegisterWindowSurface:
register_window_surface( (struct window_surface *)arg1, (struct window_surface *)arg2 );
return 0;
case NtUserSetHandlePtr:
set_user_handle_ptr( UlongToHandle(arg1), (struct user_object *)arg2 );
return 0;
default:
FIXME( "invalid code %u\n", code );
return 0;

View file

@ -24,15 +24,124 @@
#endif
#include <pthread.h>
#include <assert.h>
#include "ntstatus.h"
#define WIN32_NO_STATUS
#include "win32u_private.h"
#include "ntuser_private.h"
#include "wine/server.h"
#define NB_USER_HANDLES ((LAST_USER_HANDLE - FIRST_USER_HANDLE + 1) >> 1)
#define USER_HANDLE_TO_INDEX(hwnd) ((LOWORD(hwnd) - FIRST_USER_HANDLE) >> 1)
static void *user_handles[NB_USER_HANDLES];
static struct list window_surfaces = LIST_INIT( window_surfaces );
static pthread_mutex_t surfaces_lock = PTHREAD_MUTEX_INITIALIZER;
/***********************************************************************
* alloc_user_handle
*/
HANDLE alloc_user_handle( struct user_object *ptr, unsigned int type )
{
HANDLE handle = 0;
SERVER_START_REQ( alloc_user_handle )
{
if (!wine_server_call_err( req )) handle = wine_server_ptr_handle( reply->handle );
}
SERVER_END_REQ;
if (handle)
{
UINT index = USER_HANDLE_TO_INDEX( handle );
assert( index < NB_USER_HANDLES );
ptr->handle = handle;
ptr->type = type;
InterlockedExchangePointer( &user_handles[index], ptr );
}
return handle;
}
/***********************************************************************
* get_user_handle_ptr
*/
void *get_user_handle_ptr( HANDLE handle, unsigned int type )
{
struct user_object *ptr;
WORD index = USER_HANDLE_TO_INDEX( handle );
if (index >= NB_USER_HANDLES) return NULL;
user_lock();
if ((ptr = user_handles[index]))
{
if (ptr->type == type &&
((UINT)(UINT_PTR)ptr->handle == (UINT)(UINT_PTR)handle ||
!HIWORD(handle) || HIWORD(handle) == 0xffff))
return ptr;
ptr = NULL;
}
else ptr = OBJ_OTHER_PROCESS;
user_unlock();
return ptr;
}
/***********************************************************************
* set_user_handle_ptr
*/
void set_user_handle_ptr( HANDLE handle, struct user_object *ptr )
{
WORD index = USER_HANDLE_TO_INDEX(handle);
assert( index < NB_USER_HANDLES );
InterlockedExchangePointer( &user_handles[index], ptr );
}
/***********************************************************************
* free_user_handle
*/
void *free_user_handle( HANDLE handle, unsigned int type )
{
struct user_object *ptr;
WORD index = USER_HANDLE_TO_INDEX( handle );
if ((ptr = get_user_handle_ptr( handle, type )) && ptr != OBJ_OTHER_PROCESS)
{
SERVER_START_REQ( free_user_handle )
{
req->handle = wine_server_user_handle( handle );
if (wine_server_call( req )) ptr = NULL;
else InterlockedCompareExchangePointer( &user_handles[index], NULL, ptr );
}
SERVER_END_REQ;
user_unlock();
}
return ptr;
}
/***********************************************************************
* next_thread_window
*/
WND *next_thread_window_ptr( HWND *hwnd )
{
struct user_object *ptr;
WND *win;
WORD index = *hwnd ? USER_HANDLE_TO_INDEX( *hwnd ) + 1 : 0;
while (index < NB_USER_HANDLES)
{
if (!(ptr = user_handles[index++])) continue;
if (ptr->type != NTUSER_OBJ_WINDOW) continue;
win = (WND *)ptr;
if (win->tid != GetCurrentThreadId()) continue;
*hwnd = ptr->handle;
return win;
}
return NULL;
}
/*******************************************************************
* register_window_surface
*

View file

@ -88,6 +88,7 @@ enum
NtUserGetDeskPattern,
NtUserIncrementKeyStateCounter,
NtUserLock,
NtUserNextThreadWindow,
NtUserSetCallbacks,
};
@ -100,7 +101,11 @@ enum
NtUserMonitorFromRect,
NtUserUnhookWindowsHook,
/* temporary exports */
NtUserAllocHandle,
NtUserFreeHandle,
NtUserGetHandlePtr,
NtUserRegisterWindowSurface,
NtUserSetHandlePtr,
};
/* color index used to retrieve system 55aa brush */