Commit 35537b1d authored by Alexandre Julliard's avatar Alexandre Julliard

server: Implement Add/RemoveClipboardFormatListener.

parent 19d16a7c
...@@ -471,8 +471,15 @@ DWORD WINAPI GetClipboardSequenceNumber(VOID) ...@@ -471,8 +471,15 @@ DWORD WINAPI GetClipboardSequenceNumber(VOID)
*/ */
BOOL WINAPI AddClipboardFormatListener(HWND hwnd) BOOL WINAPI AddClipboardFormatListener(HWND hwnd)
{ {
FIXME("%p: stub\n", hwnd); BOOL ret;
return TRUE;
SERVER_START_REQ( add_clipboard_listener )
{
req->window = wine_server_user_handle( hwnd );
ret = !wine_server_call_err( req );
}
SERVER_END_REQ;
return ret;
} }
/************************************************************************** /**************************************************************************
...@@ -480,6 +487,13 @@ BOOL WINAPI AddClipboardFormatListener(HWND hwnd) ...@@ -480,6 +487,13 @@ BOOL WINAPI AddClipboardFormatListener(HWND hwnd)
*/ */
BOOL WINAPI RemoveClipboardFormatListener(HWND hwnd) BOOL WINAPI RemoveClipboardFormatListener(HWND hwnd)
{ {
FIXME("%p: stub\n", hwnd); BOOL ret;
return TRUE;
SERVER_START_REQ( remove_clipboard_listener )
{
req->window = wine_server_user_handle( hwnd );
ret = !wine_server_call_err( req );
}
SERVER_END_REQ;
return ret;
} }
...@@ -598,12 +598,12 @@ static DWORD WINAPI clipboard_thread(void *param) ...@@ -598,12 +598,12 @@ static DWORD WINAPI clipboard_thread(void *param)
ok( r, "AddClipboardFormatListener failed err %d\n", GetLastError()); ok( r, "AddClipboardFormatListener failed err %d\n", GetLastError());
SetLastError( 0xdeadbeef ); SetLastError( 0xdeadbeef );
r = pAddClipboardFormatListener( win ); r = pAddClipboardFormatListener( win );
todo_wine ok( !r, "AddClipboardFormatListener succeeded\n" ); ok( !r, "AddClipboardFormatListener succeeded\n" );
todo_wine ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() ); ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
SetLastError( 0xdeadbeef ); SetLastError( 0xdeadbeef );
r = pAddClipboardFormatListener( (HWND)0xdead ); r = pAddClipboardFormatListener( (HWND)0xdead );
todo_wine ok( !r, "AddClipboardFormatListener succeeded\n" ); ok( !r, "AddClipboardFormatListener succeeded\n" );
todo_wine ok( GetLastError() == ERROR_INVALID_WINDOW_HANDLE, "wrong error %u\n", GetLastError() ); ok( GetLastError() == ERROR_INVALID_WINDOW_HANDLE, "wrong error %u\n", GetLastError() );
r = pAddClipboardFormatListener( GetDesktopWindow() ); r = pAddClipboardFormatListener( GetDesktopWindow() );
ok( r, "AddClipboardFormatListener failed err %d\n", GetLastError()); ok( r, "AddClipboardFormatListener failed err %d\n", GetLastError());
r = pRemoveClipboardFormatListener( GetDesktopWindow() ); r = pRemoveClipboardFormatListener( GetDesktopWindow() );
...@@ -926,12 +926,12 @@ static DWORD WINAPI clipboard_thread(void *param) ...@@ -926,12 +926,12 @@ static DWORD WINAPI clipboard_thread(void *param)
ok( r, "RemoveClipboardFormatListener failed err %d\n", GetLastError()); ok( r, "RemoveClipboardFormatListener failed err %d\n", GetLastError());
SetLastError( 0xdeadbeef ); SetLastError( 0xdeadbeef );
r = pRemoveClipboardFormatListener(win); r = pRemoveClipboardFormatListener(win);
todo_wine ok( !r, "RemoveClipboardFormatListener succeeded\n" ); ok( !r, "RemoveClipboardFormatListener succeeded\n" );
todo_wine ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() ); ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
SetLastError( 0xdeadbeef ); SetLastError( 0xdeadbeef );
r = pRemoveClipboardFormatListener( (HWND)0xdead ); r = pRemoveClipboardFormatListener( (HWND)0xdead );
todo_wine ok( !r, "RemoveClipboardFormatListener succeeded\n" ); ok( !r, "RemoveClipboardFormatListener succeeded\n" );
todo_wine ok( GetLastError() == ERROR_INVALID_WINDOW_HANDLE, "wrong error %u\n", GetLastError() ); ok( GetLastError() == ERROR_INVALID_WINDOW_HANDLE, "wrong error %u\n", GetLastError() );
} }
return 0; return 0;
} }
......
...@@ -4559,6 +4559,30 @@ struct set_clipboard_viewer_reply ...@@ -4559,6 +4559,30 @@ struct set_clipboard_viewer_reply
struct add_clipboard_listener_request
{
struct request_header __header;
user_handle_t window;
};
struct add_clipboard_listener_reply
{
struct reply_header __header;
};
struct remove_clipboard_listener_request
{
struct request_header __header;
user_handle_t window;
};
struct remove_clipboard_listener_reply
{
struct reply_header __header;
};
struct open_token_request struct open_token_request
{ {
struct request_header __header; struct request_header __header;
...@@ -5693,6 +5717,8 @@ enum request ...@@ -5693,6 +5717,8 @@ enum request
REQ_empty_clipboard, REQ_empty_clipboard,
REQ_get_clipboard_info, REQ_get_clipboard_info,
REQ_set_clipboard_viewer, REQ_set_clipboard_viewer,
REQ_add_clipboard_listener,
REQ_remove_clipboard_listener,
REQ_open_token, REQ_open_token,
REQ_set_global_windows, REQ_set_global_windows,
REQ_adjust_token_privileges, REQ_adjust_token_privileges,
...@@ -5977,6 +6003,8 @@ union generic_request ...@@ -5977,6 +6003,8 @@ union generic_request
struct empty_clipboard_request empty_clipboard_request; struct empty_clipboard_request empty_clipboard_request;
struct get_clipboard_info_request get_clipboard_info_request; struct get_clipboard_info_request get_clipboard_info_request;
struct set_clipboard_viewer_request set_clipboard_viewer_request; struct set_clipboard_viewer_request set_clipboard_viewer_request;
struct add_clipboard_listener_request add_clipboard_listener_request;
struct remove_clipboard_listener_request remove_clipboard_listener_request;
struct open_token_request open_token_request; struct open_token_request open_token_request;
struct set_global_windows_request set_global_windows_request; struct set_global_windows_request set_global_windows_request;
struct adjust_token_privileges_request adjust_token_privileges_request; struct adjust_token_privileges_request adjust_token_privileges_request;
...@@ -6259,6 +6287,8 @@ union generic_reply ...@@ -6259,6 +6287,8 @@ union generic_reply
struct empty_clipboard_reply empty_clipboard_reply; struct empty_clipboard_reply empty_clipboard_reply;
struct get_clipboard_info_reply get_clipboard_info_reply; struct get_clipboard_info_reply get_clipboard_info_reply;
struct set_clipboard_viewer_reply set_clipboard_viewer_reply; struct set_clipboard_viewer_reply set_clipboard_viewer_reply;
struct add_clipboard_listener_reply add_clipboard_listener_reply;
struct remove_clipboard_listener_reply remove_clipboard_listener_reply;
struct open_token_reply open_token_reply; struct open_token_reply open_token_reply;
struct set_global_windows_reply set_global_windows_reply; struct set_global_windows_reply set_global_windows_reply;
struct adjust_token_privileges_reply adjust_token_privileges_reply; struct adjust_token_privileges_reply adjust_token_privileges_reply;
...@@ -6318,6 +6348,6 @@ union generic_reply ...@@ -6318,6 +6348,6 @@ union generic_reply
struct terminate_job_reply terminate_job_reply; struct terminate_job_reply terminate_job_reply;
}; };
#define SERVER_PROTOCOL_VERSION 513 #define SERVER_PROTOCOL_VERSION 514
#endif /* __WINE_WINE_SERVER_PROTOCOL_H */ #endif /* __WINE_WINE_SERVER_PROTOCOL_H */
...@@ -3307,6 +3307,7 @@ WINUSERAPI BOOL WINAPI UpdateLayeredWindowIndirect(HWND,UPDATELAYEREDWIND ...@@ -3307,6 +3307,7 @@ WINUSERAPI BOOL WINAPI UpdateLayeredWindowIndirect(HWND,UPDATELAYEREDWIND
#endif /* defined(_WINGDI_) && !defined(NOGDI) */ #endif /* defined(_WINGDI_) && !defined(NOGDI) */
WINUSERAPI HKL WINAPI ActivateKeyboardLayout(HKL,UINT); WINUSERAPI HKL WINAPI ActivateKeyboardLayout(HKL,UINT);
WINUSERAPI BOOL WINAPI AddClipboardFormatListener(HWND);
WINUSERAPI BOOL WINAPI AdjustWindowRect(LPRECT,DWORD,BOOL); WINUSERAPI BOOL WINAPI AdjustWindowRect(LPRECT,DWORD,BOOL);
WINUSERAPI BOOL WINAPI AdjustWindowRectEx(LPRECT,DWORD,BOOL,DWORD); WINUSERAPI BOOL WINAPI AdjustWindowRectEx(LPRECT,DWORD,BOOL,DWORD);
WINUSERAPI BOOL WINAPI AllowSetForegroundWindow(DWORD); WINUSERAPI BOOL WINAPI AllowSetForegroundWindow(DWORD);
...@@ -3901,6 +3902,7 @@ WINUSERAPI UINT WINAPI RegisterWindowMessageW(LPCWSTR); ...@@ -3901,6 +3902,7 @@ WINUSERAPI UINT WINAPI RegisterWindowMessageW(LPCWSTR);
#define RegisterWindowMessage WINELIB_NAME_AW(RegisterWindowMessage) #define RegisterWindowMessage WINELIB_NAME_AW(RegisterWindowMessage)
WINUSERAPI BOOL WINAPI ReleaseCapture(void); WINUSERAPI BOOL WINAPI ReleaseCapture(void);
WINUSERAPI INT WINAPI ReleaseDC(HWND,HDC); WINUSERAPI INT WINAPI ReleaseDC(HWND,HDC);
WINUSERAPI BOOL WINAPI RemoveClipboardFormatListener(HWND);
WINUSERAPI BOOL WINAPI RemoveMenu(HMENU,UINT,UINT); WINUSERAPI BOOL WINAPI RemoveMenu(HMENU,UINT,UINT);
WINUSERAPI HANDLE WINAPI RemovePropA(HWND,LPCSTR); WINUSERAPI HANDLE WINAPI RemovePropA(HWND,LPCSTR);
WINUSERAPI HANDLE WINAPI RemovePropW(HWND,LPCWSTR); WINUSERAPI HANDLE WINAPI RemovePropW(HWND,LPCWSTR);
......
...@@ -46,9 +46,13 @@ struct clipboard ...@@ -46,9 +46,13 @@ struct clipboard
user_handle_t viewer; /* first window in clipboard viewer list */ user_handle_t viewer; /* first window in clipboard viewer list */
unsigned int seqno; /* clipboard change sequence number */ unsigned int seqno; /* clipboard change sequence number */
timeout_t seqno_timestamp; /* time stamp of last seqno increment */ timeout_t seqno_timestamp; /* time stamp of last seqno increment */
unsigned int listen_size; /* size of listeners array */
unsigned int listen_count; /* count of listeners */
user_handle_t *listeners; /* array of listener windows */
}; };
static void clipboard_dump( struct object *obj, int verbose ); static void clipboard_dump( struct object *obj, int verbose );
static void clipboard_destroy( struct object *obj );
static const struct object_ops clipboard_ops = static const struct object_ops clipboard_ops =
{ {
...@@ -69,7 +73,7 @@ static const struct object_ops clipboard_ops = ...@@ -69,7 +73,7 @@ static const struct object_ops clipboard_ops =
NULL, /* unlink_name */ NULL, /* unlink_name */
no_open_file, /* open_file */ no_open_file, /* open_file */
no_close_handle, /* close_handle */ no_close_handle, /* close_handle */
no_destroy /* destroy */ clipboard_destroy /* destroy */
}; };
...@@ -85,6 +89,13 @@ static void clipboard_dump( struct object *obj, int verbose ) ...@@ -85,6 +89,13 @@ static void clipboard_dump( struct object *obj, int verbose )
clipboard->owner_win, clipboard->viewer, clipboard->seqno ); clipboard->owner_win, clipboard->viewer, clipboard->seqno );
} }
static void clipboard_destroy( struct object *obj )
{
struct clipboard *clipboard = (struct clipboard *)obj;
free( clipboard->listeners );
}
/* retrieve the clipboard info for the current process, allocating it if needed */ /* retrieve the clipboard info for the current process, allocating it if needed */
static struct clipboard *get_process_clipboard(void) static struct clipboard *get_process_clipboard(void)
{ {
...@@ -104,6 +115,9 @@ static struct clipboard *get_process_clipboard(void) ...@@ -104,6 +115,9 @@ static struct clipboard *get_process_clipboard(void)
clipboard->viewer = 0; clipboard->viewer = 0;
clipboard->seqno = 0; clipboard->seqno = 0;
clipboard->seqno_timestamp = 0; clipboard->seqno_timestamp = 0;
clipboard->listen_size = 0;
clipboard->listen_count = 0;
clipboard->listeners = NULL;
winstation->clipboard = clipboard; winstation->clipboard = clipboard;
} }
} }
...@@ -111,6 +125,48 @@ static struct clipboard *get_process_clipboard(void) ...@@ -111,6 +125,48 @@ static struct clipboard *get_process_clipboard(void)
return clipboard; return clipboard;
} }
/* add a clipboard listener */
static void add_listener( struct clipboard *clipboard, user_handle_t window )
{
unsigned int i;
for (i = 0; i < clipboard->listen_count; i++)
{
if (clipboard->listeners[i] != window) continue;
set_error( STATUS_INVALID_PARAMETER ); /* already set */
return;
}
if (clipboard->listen_size == clipboard->listen_count)
{
unsigned int new_size = max( 8, clipboard->listen_size * 2 );
user_handle_t *new = realloc( clipboard->listeners, new_size * sizeof(*new) );
if (!new)
{
set_error( STATUS_NO_MEMORY );
return;
}
clipboard->listeners = new;
clipboard->listen_size = new_size;
}
clipboard->listeners[clipboard->listen_count++] = window;
}
/* remove a clipboard listener */
static int remove_listener( struct clipboard *clipboard, user_handle_t window )
{
unsigned int i;
for (i = 0; i < clipboard->listen_count; i++)
{
if (clipboard->listeners[i] != window) continue;
memmove( clipboard->listeners + i, clipboard->listeners + i + 1,
(clipboard->listen_count - i - 1) * sizeof(*clipboard->listeners) );
clipboard->listen_count--;
return 1;
}
return 0;
}
/* cleanup clipboard information upon window destruction */ /* cleanup clipboard information upon window destruction */
void cleanup_clipboard_window( struct desktop *desktop, user_handle_t window ) void cleanup_clipboard_window( struct desktop *desktop, user_handle_t window )
{ {
...@@ -129,6 +185,7 @@ void cleanup_clipboard_window( struct desktop *desktop, user_handle_t window ) ...@@ -129,6 +185,7 @@ void cleanup_clipboard_window( struct desktop *desktop, user_handle_t window )
clipboard->owner_thread = NULL; clipboard->owner_thread = NULL;
} }
if (clipboard->viewer == window) clipboard->viewer = 0; if (clipboard->viewer == window) clipboard->viewer = 0;
remove_listener( clipboard, window );
} }
/* Called when thread terminates to allow release of clipboard */ /* Called when thread terminates to allow release of clipboard */
...@@ -314,3 +371,39 @@ DECL_HANDLER(set_clipboard_viewer) ...@@ -314,3 +371,39 @@ DECL_HANDLER(set_clipboard_viewer)
else else
set_error( STATUS_PENDING ); /* need to send message instead */ set_error( STATUS_PENDING ); /* need to send message instead */
} }
/* add a clipboard listener window */
DECL_HANDLER(add_clipboard_listener)
{
struct clipboard *clipboard = get_process_clipboard();
user_handle_t win = req->window;
if (!clipboard) return;
if (!get_user_object_handle( &win, USER_WINDOW ))
{
set_win32_error( ERROR_INVALID_WINDOW_HANDLE );
return;
}
add_listener( clipboard, win );
}
/* remove a clipboard listener window */
DECL_HANDLER(remove_clipboard_listener)
{
struct clipboard *clipboard = get_process_clipboard();
user_handle_t win = req->window;
if (!clipboard) return;
if (!get_user_object_handle( &win, USER_WINDOW ))
{
set_win32_error( ERROR_INVALID_WINDOW_HANDLE );
return;
}
if (!remove_listener( clipboard, win )) set_error( STATUS_INVALID_PARAMETER );
}
...@@ -3220,6 +3220,18 @@ enum caret_state ...@@ -3220,6 +3220,18 @@ enum caret_state
@END @END
/* Add a clipboard listener window */
@REQ(add_clipboard_listener)
user_handle_t window; /* clipboard listener window */
@END
/* Remove a clipboard listener window */
@REQ(remove_clipboard_listener)
user_handle_t window; /* clipboard listener window */
@END
/* Open a security token */ /* Open a security token */
@REQ(open_token) @REQ(open_token)
obj_handle_t handle; /* handle to the thread or process */ obj_handle_t handle; /* handle to the thread or process */
......
...@@ -332,6 +332,8 @@ DECL_HANDLER(set_clipboard_info); ...@@ -332,6 +332,8 @@ DECL_HANDLER(set_clipboard_info);
DECL_HANDLER(empty_clipboard); DECL_HANDLER(empty_clipboard);
DECL_HANDLER(get_clipboard_info); DECL_HANDLER(get_clipboard_info);
DECL_HANDLER(set_clipboard_viewer); DECL_HANDLER(set_clipboard_viewer);
DECL_HANDLER(add_clipboard_listener);
DECL_HANDLER(remove_clipboard_listener);
DECL_HANDLER(open_token); DECL_HANDLER(open_token);
DECL_HANDLER(set_global_windows); DECL_HANDLER(set_global_windows);
DECL_HANDLER(adjust_token_privileges); DECL_HANDLER(adjust_token_privileges);
...@@ -615,6 +617,8 @@ static const req_handler req_handlers[REQ_NB_REQUESTS] = ...@@ -615,6 +617,8 @@ static const req_handler req_handlers[REQ_NB_REQUESTS] =
(req_handler)req_empty_clipboard, (req_handler)req_empty_clipboard,
(req_handler)req_get_clipboard_info, (req_handler)req_get_clipboard_info,
(req_handler)req_set_clipboard_viewer, (req_handler)req_set_clipboard_viewer,
(req_handler)req_add_clipboard_listener,
(req_handler)req_remove_clipboard_listener,
(req_handler)req_open_token, (req_handler)req_open_token,
(req_handler)req_set_global_windows, (req_handler)req_set_global_windows,
(req_handler)req_adjust_token_privileges, (req_handler)req_adjust_token_privileges,
...@@ -2049,6 +2053,10 @@ C_ASSERT( sizeof(struct set_clipboard_viewer_request) == 24 ); ...@@ -2049,6 +2053,10 @@ C_ASSERT( sizeof(struct set_clipboard_viewer_request) == 24 );
C_ASSERT( FIELD_OFFSET(struct set_clipboard_viewer_reply, old_viewer) == 8 ); C_ASSERT( FIELD_OFFSET(struct set_clipboard_viewer_reply, old_viewer) == 8 );
C_ASSERT( FIELD_OFFSET(struct set_clipboard_viewer_reply, owner) == 12 ); C_ASSERT( FIELD_OFFSET(struct set_clipboard_viewer_reply, owner) == 12 );
C_ASSERT( sizeof(struct set_clipboard_viewer_reply) == 16 ); C_ASSERT( sizeof(struct set_clipboard_viewer_reply) == 16 );
C_ASSERT( FIELD_OFFSET(struct add_clipboard_listener_request, window) == 12 );
C_ASSERT( sizeof(struct add_clipboard_listener_request) == 16 );
C_ASSERT( FIELD_OFFSET(struct remove_clipboard_listener_request, window) == 12 );
C_ASSERT( sizeof(struct remove_clipboard_listener_request) == 16 );
C_ASSERT( FIELD_OFFSET(struct open_token_request, handle) == 12 ); C_ASSERT( FIELD_OFFSET(struct open_token_request, handle) == 12 );
C_ASSERT( FIELD_OFFSET(struct open_token_request, access) == 16 ); C_ASSERT( FIELD_OFFSET(struct open_token_request, access) == 16 );
C_ASSERT( FIELD_OFFSET(struct open_token_request, attributes) == 20 ); C_ASSERT( FIELD_OFFSET(struct open_token_request, attributes) == 20 );
......
...@@ -3798,6 +3798,16 @@ static void dump_set_clipboard_viewer_reply( const struct set_clipboard_viewer_r ...@@ -3798,6 +3798,16 @@ static void dump_set_clipboard_viewer_reply( const struct set_clipboard_viewer_r
fprintf( stderr, ", owner=%08x", req->owner ); fprintf( stderr, ", owner=%08x", req->owner );
} }
static void dump_add_clipboard_listener_request( const struct add_clipboard_listener_request *req )
{
fprintf( stderr, " window=%08x", req->window );
}
static void dump_remove_clipboard_listener_request( const struct remove_clipboard_listener_request *req )
{
fprintf( stderr, " window=%08x", req->window );
}
static void dump_open_token_request( const struct open_token_request *req ) static void dump_open_token_request( const struct open_token_request *req )
{ {
fprintf( stderr, " handle=%04x", req->handle ); fprintf( stderr, " handle=%04x", req->handle );
...@@ -4627,6 +4637,8 @@ static const dump_func req_dumpers[REQ_NB_REQUESTS] = { ...@@ -4627,6 +4637,8 @@ static const dump_func req_dumpers[REQ_NB_REQUESTS] = {
(dump_func)dump_empty_clipboard_request, (dump_func)dump_empty_clipboard_request,
(dump_func)dump_get_clipboard_info_request, (dump_func)dump_get_clipboard_info_request,
(dump_func)dump_set_clipboard_viewer_request, (dump_func)dump_set_clipboard_viewer_request,
(dump_func)dump_add_clipboard_listener_request,
(dump_func)dump_remove_clipboard_listener_request,
(dump_func)dump_open_token_request, (dump_func)dump_open_token_request,
(dump_func)dump_set_global_windows_request, (dump_func)dump_set_global_windows_request,
(dump_func)dump_adjust_token_privileges_request, (dump_func)dump_adjust_token_privileges_request,
...@@ -4907,6 +4919,8 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = { ...@@ -4907,6 +4919,8 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = {
NULL, NULL,
(dump_func)dump_get_clipboard_info_reply, (dump_func)dump_get_clipboard_info_reply,
(dump_func)dump_set_clipboard_viewer_reply, (dump_func)dump_set_clipboard_viewer_reply,
NULL,
NULL,
(dump_func)dump_open_token_reply, (dump_func)dump_open_token_reply,
(dump_func)dump_set_global_windows_reply, (dump_func)dump_set_global_windows_reply,
(dump_func)dump_adjust_token_privileges_reply, (dump_func)dump_adjust_token_privileges_reply,
...@@ -5187,6 +5201,8 @@ static const char * const req_names[REQ_NB_REQUESTS] = { ...@@ -5187,6 +5201,8 @@ static const char * const req_names[REQ_NB_REQUESTS] = {
"empty_clipboard", "empty_clipboard",
"get_clipboard_info", "get_clipboard_info",
"set_clipboard_viewer", "set_clipboard_viewer",
"add_clipboard_listener",
"remove_clipboard_listener",
"open_token", "open_token",
"set_global_windows", "set_global_windows",
"adjust_token_privileges", "adjust_token_privileges",
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment