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

server: Implement Add/RemoveClipboardFormatListener.

parent 19d16a7c
......@@ -471,8 +471,15 @@ DWORD WINAPI GetClipboardSequenceNumber(VOID)
*/
BOOL WINAPI AddClipboardFormatListener(HWND hwnd)
{
FIXME("%p: stub\n", hwnd);
return TRUE;
BOOL ret;
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)
*/
BOOL WINAPI RemoveClipboardFormatListener(HWND hwnd)
{
FIXME("%p: stub\n", hwnd);
return TRUE;
BOOL ret;
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)
ok( r, "AddClipboardFormatListener failed err %d\n", GetLastError());
SetLastError( 0xdeadbeef );
r = pAddClipboardFormatListener( win );
todo_wine ok( !r, "AddClipboardFormatListener succeeded\n" );
todo_wine ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
ok( !r, "AddClipboardFormatListener succeeded\n" );
ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
SetLastError( 0xdeadbeef );
r = pAddClipboardFormatListener( (HWND)0xdead );
todo_wine ok( !r, "AddClipboardFormatListener succeeded\n" );
todo_wine ok( GetLastError() == ERROR_INVALID_WINDOW_HANDLE, "wrong error %u\n", GetLastError() );
ok( !r, "AddClipboardFormatListener succeeded\n" );
ok( GetLastError() == ERROR_INVALID_WINDOW_HANDLE, "wrong error %u\n", GetLastError() );
r = pAddClipboardFormatListener( GetDesktopWindow() );
ok( r, "AddClipboardFormatListener failed err %d\n", GetLastError());
r = pRemoveClipboardFormatListener( GetDesktopWindow() );
......@@ -926,12 +926,12 @@ static DWORD WINAPI clipboard_thread(void *param)
ok( r, "RemoveClipboardFormatListener failed err %d\n", GetLastError());
SetLastError( 0xdeadbeef );
r = pRemoveClipboardFormatListener(win);
todo_wine ok( !r, "RemoveClipboardFormatListener succeeded\n" );
todo_wine ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
ok( !r, "RemoveClipboardFormatListener succeeded\n" );
ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
SetLastError( 0xdeadbeef );
r = pRemoveClipboardFormatListener( (HWND)0xdead );
todo_wine ok( !r, "RemoveClipboardFormatListener succeeded\n" );
todo_wine ok( GetLastError() == ERROR_INVALID_WINDOW_HANDLE, "wrong error %u\n", GetLastError() );
ok( !r, "RemoveClipboardFormatListener succeeded\n" );
ok( GetLastError() == ERROR_INVALID_WINDOW_HANDLE, "wrong error %u\n", GetLastError() );
}
return 0;
}
......
......@@ -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 request_header __header;
......@@ -5693,6 +5717,8 @@ enum request
REQ_empty_clipboard,
REQ_get_clipboard_info,
REQ_set_clipboard_viewer,
REQ_add_clipboard_listener,
REQ_remove_clipboard_listener,
REQ_open_token,
REQ_set_global_windows,
REQ_adjust_token_privileges,
......@@ -5977,6 +6003,8 @@ union generic_request
struct empty_clipboard_request empty_clipboard_request;
struct get_clipboard_info_request get_clipboard_info_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 set_global_windows_request set_global_windows_request;
struct adjust_token_privileges_request adjust_token_privileges_request;
......@@ -6259,6 +6287,8 @@ union generic_reply
struct empty_clipboard_reply empty_clipboard_reply;
struct get_clipboard_info_reply get_clipboard_info_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 set_global_windows_reply set_global_windows_reply;
struct adjust_token_privileges_reply adjust_token_privileges_reply;
......@@ -6318,6 +6348,6 @@ union generic_reply
struct terminate_job_reply terminate_job_reply;
};
#define SERVER_PROTOCOL_VERSION 513
#define SERVER_PROTOCOL_VERSION 514
#endif /* __WINE_WINE_SERVER_PROTOCOL_H */
......@@ -3307,6 +3307,7 @@ WINUSERAPI BOOL WINAPI UpdateLayeredWindowIndirect(HWND,UPDATELAYEREDWIND
#endif /* defined(_WINGDI_) && !defined(NOGDI) */
WINUSERAPI HKL WINAPI ActivateKeyboardLayout(HKL,UINT);
WINUSERAPI BOOL WINAPI AddClipboardFormatListener(HWND);
WINUSERAPI BOOL WINAPI AdjustWindowRect(LPRECT,DWORD,BOOL);
WINUSERAPI BOOL WINAPI AdjustWindowRectEx(LPRECT,DWORD,BOOL,DWORD);
WINUSERAPI BOOL WINAPI AllowSetForegroundWindow(DWORD);
......@@ -3901,6 +3902,7 @@ WINUSERAPI UINT WINAPI RegisterWindowMessageW(LPCWSTR);
#define RegisterWindowMessage WINELIB_NAME_AW(RegisterWindowMessage)
WINUSERAPI BOOL WINAPI ReleaseCapture(void);
WINUSERAPI INT WINAPI ReleaseDC(HWND,HDC);
WINUSERAPI BOOL WINAPI RemoveClipboardFormatListener(HWND);
WINUSERAPI BOOL WINAPI RemoveMenu(HMENU,UINT,UINT);
WINUSERAPI HANDLE WINAPI RemovePropA(HWND,LPCSTR);
WINUSERAPI HANDLE WINAPI RemovePropW(HWND,LPCWSTR);
......
......@@ -46,9 +46,13 @@ struct clipboard
user_handle_t viewer; /* first window in clipboard viewer list */
unsigned int seqno; /* clipboard change sequence number */
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_destroy( struct object *obj );
static const struct object_ops clipboard_ops =
{
......@@ -69,7 +73,7 @@ static const struct object_ops clipboard_ops =
NULL, /* unlink_name */
no_open_file, /* open_file */
no_close_handle, /* close_handle */
no_destroy /* destroy */
clipboard_destroy /* destroy */
};
......@@ -85,6 +89,13 @@ static void clipboard_dump( struct object *obj, int verbose )
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 */
static struct clipboard *get_process_clipboard(void)
{
......@@ -104,6 +115,9 @@ static struct clipboard *get_process_clipboard(void)
clipboard->viewer = 0;
clipboard->seqno = 0;
clipboard->seqno_timestamp = 0;
clipboard->listen_size = 0;
clipboard->listen_count = 0;
clipboard->listeners = NULL;
winstation->clipboard = clipboard;
}
}
......@@ -111,6 +125,48 @@ static struct clipboard *get_process_clipboard(void)
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 */
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;
}
if (clipboard->viewer == window) clipboard->viewer = 0;
remove_listener( clipboard, window );
}
/* Called when thread terminates to allow release of clipboard */
......@@ -314,3 +371,39 @@ DECL_HANDLER(set_clipboard_viewer)
else
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
@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 */
@REQ(open_token)
obj_handle_t handle; /* handle to the thread or process */
......
......@@ -332,6 +332,8 @@ DECL_HANDLER(set_clipboard_info);
DECL_HANDLER(empty_clipboard);
DECL_HANDLER(get_clipboard_info);
DECL_HANDLER(set_clipboard_viewer);
DECL_HANDLER(add_clipboard_listener);
DECL_HANDLER(remove_clipboard_listener);
DECL_HANDLER(open_token);
DECL_HANDLER(set_global_windows);
DECL_HANDLER(adjust_token_privileges);
......@@ -615,6 +617,8 @@ static const req_handler req_handlers[REQ_NB_REQUESTS] =
(req_handler)req_empty_clipboard,
(req_handler)req_get_clipboard_info,
(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_set_global_windows,
(req_handler)req_adjust_token_privileges,
......@@ -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, owner) == 12 );
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, access) == 16 );
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
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 )
{
fprintf( stderr, " handle=%04x", req->handle );
......@@ -4627,6 +4637,8 @@ static const dump_func req_dumpers[REQ_NB_REQUESTS] = {
(dump_func)dump_empty_clipboard_request,
(dump_func)dump_get_clipboard_info_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_set_global_windows_request,
(dump_func)dump_adjust_token_privileges_request,
......@@ -4907,6 +4919,8 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = {
NULL,
(dump_func)dump_get_clipboard_info_reply,
(dump_func)dump_set_clipboard_viewer_reply,
NULL,
NULL,
(dump_func)dump_open_token_reply,
(dump_func)dump_set_global_windows_reply,
(dump_func)dump_adjust_token_privileges_reply,
......@@ -5187,6 +5201,8 @@ static const char * const req_names[REQ_NB_REQUESTS] = {
"empty_clipboard",
"get_clipboard_info",
"set_clipboard_viewer",
"add_clipboard_listener",
"remove_clipboard_listener",
"open_token",
"set_global_windows",
"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