user32: Retrieve available clipboard formats from the server.

Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Alexandre Julliard 2016-09-26 13:55:09 +09:00
parent 79f90e4e41
commit c69b4995c5
7 changed files with 186 additions and 26 deletions

View file

@ -836,11 +836,17 @@ done:
*/
INT WINAPI CountClipboardFormats(void)
{
INT count;
INT count = 0;
USER_Driver->pUpdateClipboard();
count = USER_Driver->pCountClipboardFormats();
SERVER_START_REQ( get_clipboard_formats )
{
wine_server_call( req );
count = reply->count;
}
SERVER_END_REQ;
TRACE("returning %d\n", count);
return count;
}
@ -853,14 +859,17 @@ UINT WINAPI EnumClipboardFormats( UINT format )
{
UINT ret = 0;
if (!(get_clipboard_flags() & CB_OPEN))
SERVER_START_REQ( enum_clipboard_formats )
{
WARN("Clipboard not opened by calling task.\n");
SetLastError(ERROR_CLIPBOARD_NOT_OPEN);
return 0;
req->previous = format;
if (!wine_server_call_err( req ))
{
ret = reply->format;
SetLastError( ERROR_SUCCESS );
}
}
SetLastError( 0 );
ret = USER_Driver->pEnumClipboardFormats( format );
SERVER_END_REQ;
TRACE( "%s -> %s\n", debugstr_format( format ), debugstr_format( ret ));
return ret;
}
@ -871,11 +880,18 @@ UINT WINAPI EnumClipboardFormats( UINT format )
*/
BOOL WINAPI IsClipboardFormatAvailable( UINT format )
{
BOOL ret;
BOOL ret = FALSE;
if (!format) return FALSE;
USER_Driver->pUpdateClipboard();
ret = USER_Driver->pIsClipboardFormatAvailable( format );
SERVER_START_REQ( get_clipboard_formats )
{
req->format = format;
if (!wine_server_call_err( req )) ret = (reply->count > 0);
}
SERVER_END_REQ;
TRACE( "%s -> %u\n", debugstr_format( format ), ret );
return ret;
}
@ -886,28 +902,27 @@ BOOL WINAPI IsClipboardFormatAvailable( UINT format )
*/
BOOL WINAPI GetUpdatedClipboardFormats( UINT *formats, UINT size, UINT *out_size )
{
UINT i = 0, cf = 0;
BOOL ret;
if (!out_size)
{
SetLastError( ERROR_NOACCESS );
return FALSE;
}
if (!(*out_size = CountClipboardFormats())) return TRUE; /* nothing else to do */
if (!formats)
USER_Driver->pUpdateClipboard();
SERVER_START_REQ( get_clipboard_formats )
{
SetLastError( ERROR_NOACCESS );
return FALSE;
if (formats) wine_server_set_reply( req, formats, size * sizeof(*formats) );
ret = !wine_server_call_err( req );
*out_size = reply->count;
}
if (size < *out_size)
{
SetLastError( ERROR_INSUFFICIENT_BUFFER );
return FALSE;
}
/* FIXME: format list could change in the meantime */
while ((cf = USER_Driver->pEnumClipboardFormats( cf ))) formats[i++] = cf;
return TRUE;
SERVER_END_REQ;
TRACE( "%p %u returning %u formats, ret %u\n", formats, size, *out_size, ret );
if (!ret && !formats && *out_size) SetLastError( ERROR_NOACCESS );
return ret;
}

View file

@ -105,7 +105,6 @@ static void set_clipboard_data_process( int arg )
SetLastError( 0xdeadbeef );
if (arg)
{
todo_wine_if( arg == 1 || arg == 3 )
ok( IsClipboardFormatAvailable( CF_WAVE ), "process %u: CF_WAVE not available\n", arg );
ret = SetClipboardData( CF_WAVE, GlobalAlloc( GMEM_DDESHARE | GMEM_ZEROINIT, 100 ));
ok( ret != 0, "process %u: SetClipboardData failed err %u\n", arg, GetLastError() );
@ -321,7 +320,7 @@ static void test_ClipboardOwner(void)
ok(!GetClipboardOwner() && GetLastError() == 0xdeadbeef, "clipboard should not be owned\n");
ok(!GetClipboardViewer() && GetLastError() == 0xdeadbeef, "viewer still exists\n");
ok(!GetOpenClipboardWindow() && GetLastError() == 0xdeadbeef, "clipboard should not be open\n");
todo_wine ok( !IsClipboardFormatAvailable( CF_WAVE ), "CF_WAVE available\n" );
ok( !IsClipboardFormatAvailable( CF_WAVE ), "CF_WAVE available\n" );
SetLastError( 0xdeadbeef );
ret = CloseClipboard();

View file

@ -4540,6 +4540,35 @@ struct set_clipboard_data_reply
struct get_clipboard_formats_request
{
struct request_header __header;
unsigned int format;
};
struct get_clipboard_formats_reply
{
struct reply_header __header;
unsigned int count;
/* VARARG(formats,uints); */
char __pad_12[4];
};
struct enum_clipboard_formats_request
{
struct request_header __header;
unsigned int previous;
};
struct enum_clipboard_formats_reply
{
struct reply_header __header;
unsigned int format;
char __pad_12[4];
};
struct release_clipboard_request
{
struct request_header __header;
@ -5743,6 +5772,8 @@ enum request
REQ_set_clipboard_info,
REQ_empty_clipboard,
REQ_set_clipboard_data,
REQ_get_clipboard_formats,
REQ_enum_clipboard_formats,
REQ_release_clipboard,
REQ_get_clipboard_info,
REQ_set_clipboard_viewer,
@ -6031,6 +6062,8 @@ union generic_request
struct set_clipboard_info_request set_clipboard_info_request;
struct empty_clipboard_request empty_clipboard_request;
struct set_clipboard_data_request set_clipboard_data_request;
struct get_clipboard_formats_request get_clipboard_formats_request;
struct enum_clipboard_formats_request enum_clipboard_formats_request;
struct release_clipboard_request release_clipboard_request;
struct get_clipboard_info_request get_clipboard_info_request;
struct set_clipboard_viewer_request set_clipboard_viewer_request;
@ -6317,6 +6350,8 @@ union generic_reply
struct set_clipboard_info_reply set_clipboard_info_reply;
struct empty_clipboard_reply empty_clipboard_reply;
struct set_clipboard_data_reply set_clipboard_data_reply;
struct get_clipboard_formats_reply get_clipboard_formats_reply;
struct enum_clipboard_formats_reply enum_clipboard_formats_reply;
struct release_clipboard_reply release_clipboard_reply;
struct get_clipboard_info_reply get_clipboard_info_reply;
struct set_clipboard_viewer_reply set_clipboard_viewer_reply;
@ -6381,6 +6416,6 @@ union generic_reply
struct terminate_job_reply terminate_job_reply;
};
#define SERVER_PROTOCOL_VERSION 518
#define SERVER_PROTOCOL_VERSION 519
#endif /* __WINE_WINE_SERVER_PROTOCOL_H */

View file

@ -411,6 +411,61 @@ DECL_HANDLER(set_clipboard_data)
}
/* retrieve a list of available formats */
DECL_HANDLER(get_clipboard_formats)
{
struct clipboard *clipboard = get_process_clipboard();
if (!clipboard) return;
if (!req->format)
{
struct clip_format *format;
unsigned int i = 0, *ptr;
data_size_t size = clipboard->format_count * sizeof(unsigned int);
reply->count = clipboard->format_count;
if (size <= get_reply_max_size())
{
if ((ptr = mem_alloc( size )))
{
LIST_FOR_EACH_ENTRY( format, &clipboard->formats, struct clip_format, entry )
ptr[i++] = format->id;
assert( i == clipboard->format_count );
set_reply_data_ptr( ptr, size );
}
}
else set_error( STATUS_BUFFER_TOO_SMALL );
}
else reply->count = (get_format( clipboard, req->format ) != NULL); /* query a single format */
}
/* retrieve the next available format */
DECL_HANDLER(enum_clipboard_formats)
{
struct list *ptr;
struct clipboard *clipboard = get_process_clipboard();
if (!clipboard) return;
if (clipboard->open_thread != current)
{
set_win32_error( ERROR_CLIPBOARD_NOT_OPEN );
return;
}
ptr = list_head( &clipboard->formats );
if (req->previous)
{
while (ptr && LIST_ENTRY( ptr, struct clip_format, entry )->id != req->previous)
ptr = list_next( &clipboard->formats, ptr );
if (ptr) ptr = list_next( &clipboard->formats, ptr );
}
if (ptr) reply->format = LIST_ENTRY( ptr, struct clip_format, entry )->id;
}
/* empty the clipboard and grab ownership */
DECL_HANDLER(empty_clipboard)
{

View file

@ -3206,6 +3206,23 @@ enum caret_state
@END
/* Retrieve a list of available formats */
@REQ(get_clipboard_formats)
unsigned int format; /* specific format to query, return all if 0 */
@REPLY
unsigned int count; /* count of available formats */
VARARG(formats,uints); /* array of available formats */
@END
/* Retrieve the next available format */
@REQ(enum_clipboard_formats)
unsigned int previous; /* previous format, or first if 0 */
@REPLY
unsigned int format; /* next format */
@END
/* Release ownership of the clipboard */
@REQ(release_clipboard)
user_handle_t owner; /* clipboard owner to release */

View file

@ -331,6 +331,8 @@ DECL_HANDLER(close_clipboard);
DECL_HANDLER(set_clipboard_info);
DECL_HANDLER(empty_clipboard);
DECL_HANDLER(set_clipboard_data);
DECL_HANDLER(get_clipboard_formats);
DECL_HANDLER(enum_clipboard_formats);
DECL_HANDLER(release_clipboard);
DECL_HANDLER(get_clipboard_info);
DECL_HANDLER(set_clipboard_viewer);
@ -618,6 +620,8 @@ static const req_handler req_handlers[REQ_NB_REQUESTS] =
(req_handler)req_set_clipboard_info,
(req_handler)req_empty_clipboard,
(req_handler)req_set_clipboard_data,
(req_handler)req_get_clipboard_formats,
(req_handler)req_enum_clipboard_formats,
(req_handler)req_release_clipboard,
(req_handler)req_get_clipboard_info,
(req_handler)req_set_clipboard_viewer,
@ -2046,6 +2050,14 @@ C_ASSERT( sizeof(struct set_clipboard_info_reply) == 32 );
C_ASSERT( sizeof(struct empty_clipboard_request) == 16 );
C_ASSERT( FIELD_OFFSET(struct set_clipboard_data_request, format) == 12 );
C_ASSERT( sizeof(struct set_clipboard_data_request) == 16 );
C_ASSERT( FIELD_OFFSET(struct get_clipboard_formats_request, format) == 12 );
C_ASSERT( sizeof(struct get_clipboard_formats_request) == 16 );
C_ASSERT( FIELD_OFFSET(struct get_clipboard_formats_reply, count) == 8 );
C_ASSERT( sizeof(struct get_clipboard_formats_reply) == 16 );
C_ASSERT( FIELD_OFFSET(struct enum_clipboard_formats_request, previous) == 12 );
C_ASSERT( sizeof(struct enum_clipboard_formats_request) == 16 );
C_ASSERT( FIELD_OFFSET(struct enum_clipboard_formats_reply, format) == 8 );
C_ASSERT( sizeof(struct enum_clipboard_formats_reply) == 16 );
C_ASSERT( FIELD_OFFSET(struct release_clipboard_request, owner) == 12 );
C_ASSERT( sizeof(struct release_clipboard_request) == 16 );
C_ASSERT( FIELD_OFFSET(struct release_clipboard_reply, viewer) == 8 );

View file

@ -3779,6 +3779,27 @@ static void dump_set_clipboard_data_request( const struct set_clipboard_data_req
dump_varargs_bytes( ", data=", cur_size );
}
static void dump_get_clipboard_formats_request( const struct get_clipboard_formats_request *req )
{
fprintf( stderr, " format=%08x", req->format );
}
static void dump_get_clipboard_formats_reply( const struct get_clipboard_formats_reply *req )
{
fprintf( stderr, " count=%08x", req->count );
dump_varargs_uints( ", formats=", cur_size );
}
static void dump_enum_clipboard_formats_request( const struct enum_clipboard_formats_request *req )
{
fprintf( stderr, " previous=%08x", req->previous );
}
static void dump_enum_clipboard_formats_reply( const struct enum_clipboard_formats_reply *req )
{
fprintf( stderr, " format=%08x", req->format );
}
static void dump_release_clipboard_request( const struct release_clipboard_request *req )
{
fprintf( stderr, " owner=%08x", req->owner );
@ -4652,6 +4673,8 @@ static const dump_func req_dumpers[REQ_NB_REQUESTS] = {
(dump_func)dump_set_clipboard_info_request,
(dump_func)dump_empty_clipboard_request,
(dump_func)dump_set_clipboard_data_request,
(dump_func)dump_get_clipboard_formats_request,
(dump_func)dump_enum_clipboard_formats_request,
(dump_func)dump_release_clipboard_request,
(dump_func)dump_get_clipboard_info_request,
(dump_func)dump_set_clipboard_viewer_request,
@ -4936,6 +4959,8 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = {
(dump_func)dump_set_clipboard_info_reply,
NULL,
NULL,
(dump_func)dump_get_clipboard_formats_reply,
(dump_func)dump_enum_clipboard_formats_reply,
(dump_func)dump_release_clipboard_reply,
(dump_func)dump_get_clipboard_info_reply,
(dump_func)dump_set_clipboard_viewer_reply,
@ -5220,6 +5245,8 @@ static const char * const req_names[REQ_NB_REQUESTS] = {
"set_clipboard_info",
"empty_clipboard",
"set_clipboard_data",
"get_clipboard_formats",
"enum_clipboard_formats",
"release_clipboard",
"get_clipboard_info",
"set_clipboard_viewer",