Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-winehq
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wine
wine-winehq
Commits
f0fbf1a9
Commit
f0fbf1a9
authored
Sep 26, 2016
by
Alexandre Julliard
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
user32: Cache clipboard data on the client side.
Signed-off-by:
Alexandre Julliard
<
julliard@winehq.org
>
parent
9ed8f5e8
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
224 additions
and
25 deletions
+224
-25
clipboard.c
dlls/user32/clipboard.c
+177
-4
clipboard.c
dlls/user32/tests/clipboard.c
+8
-10
server_protocol.h
include/wine/server_protocol.h
+7
-3
clipboard.c
server/clipboard.c
+9
-3
protocol.def
server/protocol.def
+6
-1
request.h
server/request.h
+7
-2
trace.c
server/trace.c
+10
-2
No files found.
dlls/user32/clipboard.c
View file @
f0fbf1a9
...
@@ -46,13 +46,34 @@
...
@@ -46,13 +46,34 @@
#include "user_private.h"
#include "user_private.h"
#include "win.h"
#include "win.h"
#include "wine/
debug
.h"
#include "wine/
list
.h"
#include "wine/unicode.h"
#include "wine/unicode.h"
#include "wine/server.h"
#include "wine/server.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL
(
clipboard
);
WINE_DEFAULT_DEBUG_CHANNEL
(
clipboard
);
struct
cached_format
{
struct
list
entry
;
/* entry in cache list */
UINT
format
;
/* format id */
UINT
seqno
;
/* sequence number when the data was set */
HANDLE
handle
;
/* original data handle */
};
static
struct
list
cached_formats
=
LIST_INIT
(
cached_formats
);
static
struct
list
formats_to_free
=
LIST_INIT
(
formats_to_free
);
static
CRITICAL_SECTION
clipboard_cs
;
static
CRITICAL_SECTION_DEBUG
critsect_debug
=
{
0
,
0
,
&
clipboard_cs
,
{
&
critsect_debug
.
ProcessLocksList
,
&
critsect_debug
.
ProcessLocksList
},
0
,
0
,
{
(
DWORD_PTR
)(
__FILE__
": clipboard_cs"
)
}
};
static
CRITICAL_SECTION
clipboard_cs
=
{
&
critsect_debug
,
-
1
,
0
,
0
,
0
,
0
};
/* get a debug string for a format id */
/* get a debug string for a format id */
static
const
char
*
debugstr_format
(
UINT
id
)
static
const
char
*
debugstr_format
(
UINT
id
)
{
{
...
@@ -200,6 +221,115 @@ static HANDLE unmarshal_data( UINT format, void *data, data_size_t size )
...
@@ -200,6 +221,115 @@ static HANDLE unmarshal_data( UINT format, void *data, data_size_t size )
return
handle
;
return
handle
;
}
}
/* retrieve a data format from the cache */
static
struct
cached_format
*
get_cached_format
(
UINT
format
)
{
struct
cached_format
*
cache
;
LIST_FOR_EACH_ENTRY
(
cache
,
&
cached_formats
,
struct
cached_format
,
entry
)
if
(
cache
->
format
==
format
)
return
cache
;
return
NULL
;
}
/* store data in the cache, or reuse the existing one if available */
static
HANDLE
cache_data
(
UINT
format
,
HANDLE
data
,
data_size_t
size
,
UINT
seqno
,
struct
cached_format
*
cache
)
{
if
(
cache
)
{
if
(
seqno
==
cache
->
seqno
)
/* we can reuse the cached data */
{
GlobalFree
(
data
);
return
cache
->
handle
;
}
/* cache entry is stale, remove it */
list_remove
(
&
cache
->
entry
);
list_add_tail
(
&
formats_to_free
,
&
cache
->
entry
);
}
/* allocate new cache entry */
if
(
!
(
cache
=
HeapAlloc
(
GetProcessHeap
(),
0
,
sizeof
(
*
cache
)
)))
{
GlobalFree
(
data
);
return
0
;
}
cache
->
format
=
format
;
cache
->
seqno
=
seqno
;
cache
->
handle
=
unmarshal_data
(
format
,
data
,
size
);
list_add_tail
(
&
cached_formats
,
&
cache
->
entry
);
return
cache
->
handle
;
}
/* free a single cached format */
static
void
free_cached_data
(
struct
cached_format
*
cache
)
{
void
*
ptr
;
switch
(
cache
->
format
)
{
case
CF_BITMAP
:
case
CF_DSPBITMAP
:
case
CF_PALETTE
:
DeleteObject
(
cache
->
handle
);
break
;
case
CF_ENHMETAFILE
:
case
CF_DSPENHMETAFILE
:
DeleteEnhMetaFile
(
cache
->
handle
);
break
;
case
CF_METAFILEPICT
:
case
CF_DSPMETAFILEPICT
:
if
((
ptr
=
GlobalLock
(
cache
->
handle
)))
{
DeleteMetaFile
(
((
METAFILEPICT
*
)
ptr
)
->
hMF
);
GlobalUnlock
(
cache
->
handle
);
}
GlobalFree
(
cache
->
handle
);
break
;
default:
if
((
ptr
=
GlobalLock
(
cache
->
handle
))
&&
ptr
!=
cache
->
handle
)
{
GlobalUnlock
(
cache
->
handle
);
GlobalFree
(
cache
->
handle
);
}
break
;
}
list_remove
(
&
cache
->
entry
);
HeapFree
(
GetProcessHeap
(),
0
,
cache
);
}
/* clear global memory formats; special types are freed on EmptyClipboard */
static
void
invalidate_memory_formats
(
void
)
{
struct
cached_format
*
cache
,
*
next
;
LIST_FOR_EACH_ENTRY_SAFE
(
cache
,
next
,
&
cached_formats
,
struct
cached_format
,
entry
)
{
switch
(
cache
->
format
)
{
case
CF_BITMAP
:
case
CF_DSPBITMAP
:
case
CF_PALETTE
:
case
CF_ENHMETAFILE
:
case
CF_DSPENHMETAFILE
:
case
CF_METAFILEPICT
:
case
CF_DSPMETAFILEPICT
:
continue
;
default:
free_cached_data
(
cache
);
break
;
}
}
}
/* free all the data in the cache */
static
void
free_cached_formats
(
void
)
{
struct
list
*
ptr
;
list_move_tail
(
&
formats_to_free
,
&
cached_formats
);
while
((
ptr
=
list_head
(
&
formats_to_free
)))
free_cached_data
(
LIST_ENTRY
(
ptr
,
struct
cached_format
,
entry
));
}
/* get the clipboard locale stored in the CF_LOCALE format */
/* get the clipboard locale stored in the CF_LOCALE format */
static
LCID
get_clipboard_locale
(
void
)
static
LCID
get_clipboard_locale
(
void
)
...
@@ -518,18 +648,25 @@ INT WINAPI GetClipboardFormatNameA( UINT format, LPSTR buffer, INT maxlen )
...
@@ -518,18 +648,25 @@ INT WINAPI GetClipboardFormatNameA( UINT format, LPSTR buffer, INT maxlen )
BOOL
WINAPI
OpenClipboard
(
HWND
hwnd
)
BOOL
WINAPI
OpenClipboard
(
HWND
hwnd
)
{
{
BOOL
ret
;
BOOL
ret
;
HWND
owner
;
TRACE
(
"%p
\n
"
,
hwnd
);
TRACE
(
"%p
\n
"
,
hwnd
);
USER_Driver
->
pUpdateClipboard
();
USER_Driver
->
pUpdateClipboard
();
EnterCriticalSection
(
&
clipboard_cs
);
SERVER_START_REQ
(
open_clipboard
)
SERVER_START_REQ
(
open_clipboard
)
{
{
req
->
window
=
wine_server_user_handle
(
hwnd
);
req
->
window
=
wine_server_user_handle
(
hwnd
);
ret
=
!
wine_server_call_err
(
req
);
ret
=
!
wine_server_call_err
(
req
);
owner
=
wine_server_ptr_handle
(
reply
->
owner
);
}
}
SERVER_END_REQ
;
SERVER_END_REQ
;
if
(
ret
&&
!
WIN_IsCurrentProcess
(
owner
))
invalidate_memory_formats
();
LeaveCriticalSection
(
&
clipboard_cs
);
return
ret
;
return
ret
;
}
}
...
@@ -572,12 +709,17 @@ BOOL WINAPI EmptyClipboard(void)
...
@@ -572,12 +709,17 @@ BOOL WINAPI EmptyClipboard(void)
if
(
owner
)
SendMessageTimeoutW
(
owner
,
WM_DESTROYCLIPBOARD
,
0
,
0
,
SMTO_ABORTIFHUNG
,
5000
,
NULL
);
if
(
owner
)
SendMessageTimeoutW
(
owner
,
WM_DESTROYCLIPBOARD
,
0
,
0
,
SMTO_ABORTIFHUNG
,
5000
,
NULL
);
EnterCriticalSection
(
&
clipboard_cs
);
SERVER_START_REQ
(
empty_clipboard
)
SERVER_START_REQ
(
empty_clipboard
)
{
{
ret
=
!
wine_server_call_err
(
req
);
ret
=
!
wine_server_call_err
(
req
);
}
}
SERVER_END_REQ
;
SERVER_END_REQ
;
if
(
ret
)
free_cached_formats
();
LeaveCriticalSection
(
&
clipboard_cs
);
return
ret
;
return
ret
;
}
}
...
@@ -696,6 +838,7 @@ BOOL WINAPI ChangeClipboardChain( HWND hwnd, HWND next )
...
@@ -696,6 +838,7 @@ BOOL WINAPI ChangeClipboardChain( HWND hwnd, HWND next )
*/
*/
HANDLE
WINAPI
SetClipboardData
(
UINT
format
,
HANDLE
data
)
HANDLE
WINAPI
SetClipboardData
(
UINT
format
,
HANDLE
data
)
{
{
struct
cached_format
*
cache
=
NULL
;
void
*
ptr
=
NULL
;
void
*
ptr
=
NULL
;
data_size_t
size
=
0
;
data_size_t
size
=
0
;
HANDLE
handle
=
data
,
retval
=
0
;
HANDLE
handle
=
data
,
retval
=
0
;
...
@@ -707,19 +850,37 @@ HANDLE WINAPI SetClipboardData( UINT format, HANDLE data )
...
@@ -707,19 +850,37 @@ HANDLE WINAPI SetClipboardData( UINT format, HANDLE data )
{
{
if
(
!
(
handle
=
marshal_data
(
format
,
data
,
&
size
)))
return
0
;
if
(
!
(
handle
=
marshal_data
(
format
,
data
,
&
size
)))
return
0
;
if
(
!
(
ptr
=
GlobalLock
(
handle
)))
goto
done
;
if
(
!
(
ptr
=
GlobalLock
(
handle
)))
goto
done
;
if
(
!
(
cache
=
HeapAlloc
(
GetProcessHeap
(),
0
,
sizeof
(
*
cache
)
)))
goto
done
;
cache
->
format
=
format
;
cache
->
handle
=
data
;
}
}
EnterCriticalSection
(
&
clipboard_cs
);
SERVER_START_REQ
(
set_clipboard_data
)
SERVER_START_REQ
(
set_clipboard_data
)
{
{
req
->
format
=
format
;
req
->
format
=
format
;
req
->
lcid
=
GetUserDefaultLCID
();
req
->
lcid
=
GetUserDefaultLCID
();
wine_server_add_data
(
req
,
ptr
,
size
);
wine_server_add_data
(
req
,
ptr
,
size
);
ret
=
!
wine_server_call_err
(
req
);
if
((
ret
=
!
wine_server_call_err
(
req
)))
{
if
(
cache
)
cache
->
seqno
=
reply
->
seqno
;
}
}
}
SERVER_END_REQ
;
SERVER_END_REQ
;
if
(
ret
)
if
(
ret
)
{
/* free the previous entry if any */
struct
cached_format
*
prev
;
if
((
prev
=
get_cached_format
(
format
)))
free_cached_data
(
prev
);
if
(
cache
)
list_add_tail
(
&
cached_formats
,
&
cache
->
entry
);
retval
=
data
;
retval
=
data
;
}
else
HeapFree
(
GetProcessHeap
(),
0
,
cache
);
LeaveCriticalSection
(
&
clipboard_cs
);
done:
done:
if
(
ptr
)
GlobalUnlock
(
ptr
);
if
(
ptr
)
GlobalUnlock
(
ptr
);
...
@@ -828,8 +989,9 @@ BOOL WINAPI GetUpdatedClipboardFormats( UINT *formats, UINT size, UINT *out_size
...
@@ -828,8 +989,9 @@ BOOL WINAPI GetUpdatedClipboardFormats( UINT *formats, UINT size, UINT *out_size
*/
*/
HANDLE
WINAPI
GetClipboardData
(
UINT
format
)
HANDLE
WINAPI
GetClipboardData
(
UINT
format
)
{
{
struct
cached_format
*
cache
;
NTSTATUS
status
;
NTSTATUS
status
;
UINT
from
;
UINT
from
,
data_seqno
;
HWND
owner
;
HWND
owner
;
HANDLE
data
;
HANDLE
data
;
UINT
size
=
1024
;
UINT
size
=
1024
;
...
@@ -839,23 +1001,34 @@ HANDLE WINAPI GetClipboardData( UINT format )
...
@@ -839,23 +1001,34 @@ HANDLE WINAPI GetClipboardData( UINT format )
{
{
if
(
!
(
data
=
GlobalAlloc
(
GMEM_FIXED
,
size
)))
return
0
;
if
(
!
(
data
=
GlobalAlloc
(
GMEM_FIXED
,
size
)))
return
0
;
EnterCriticalSection
(
&
clipboard_cs
);
cache
=
get_cached_format
(
format
);
SERVER_START_REQ
(
get_clipboard_data
)
SERVER_START_REQ
(
get_clipboard_data
)
{
{
req
->
format
=
format
;
req
->
format
=
format
;
if
(
cache
)
{
req
->
cached
=
1
;
req
->
seqno
=
cache
->
seqno
;
}
wine_server_set_reply
(
req
,
data
,
size
);
wine_server_set_reply
(
req
,
data
,
size
);
status
=
wine_server_call
(
req
);
status
=
wine_server_call
(
req
);
from
=
reply
->
from
;
from
=
reply
->
from
;
size
=
reply
->
total
;
size
=
reply
->
total
;
data_seqno
=
reply
->
seqno
;
owner
=
wine_server_ptr_handle
(
reply
->
owner
);
owner
=
wine_server_ptr_handle
(
reply
->
owner
);
}
}
SERVER_END_REQ
;
SERVER_END_REQ
;
if
(
!
status
&&
size
)
if
(
!
status
&&
size
)
{
{
data
=
unmarshal_data
(
format
,
data
,
size
);
data
=
cache_data
(
format
,
data
,
size
,
data_seqno
,
cache
);
LeaveCriticalSection
(
&
clipboard_cs
);
TRACE
(
"%s returning %p
\n
"
,
debugstr_format
(
format
),
data
);
TRACE
(
"%s returning %p
\n
"
,
debugstr_format
(
format
),
data
);
return
data
;
return
data
;
}
}
LeaveCriticalSection
(
&
clipboard_cs
);
GlobalFree
(
data
);
GlobalFree
(
data
);
if
(
status
==
STATUS_BUFFER_OVERFLOW
)
continue
;
/* retry with the new size */
if
(
status
==
STATUS_BUFFER_OVERFLOW
)
continue
;
/* retry with the new size */
...
...
dlls/user32/tests/clipboard.c
View file @
f0fbf1a9
...
@@ -1755,11 +1755,11 @@ static void test_handles( HWND hwnd )
...
@@ -1755,11 +1755,11 @@ static void test_handles( HWND hwnd )
/* and now they are freed, unless we are the owner */
/* and now they are freed, unless we are the owner */
if
(
!
is_owner
)
if
(
!
is_owner
)
{
{
todo_wine
ok
(
is_freed
(
htext
),
"expected freed mem %p
\n
"
,
htext
);
ok
(
is_freed
(
htext
),
"expected freed mem %p
\n
"
,
htext
);
todo_wine
ok
(
is_freed
(
htext2
),
"expected freed mem %p
\n
"
,
htext2
);
ok
(
is_freed
(
htext2
),
"expected freed mem %p
\n
"
,
htext2
);
todo_wine
ok
(
is_freed
(
htext3
),
"expected freed mem %p
\n
"
,
htext3
);
ok
(
is_freed
(
htext3
),
"expected freed mem %p
\n
"
,
htext3
);
todo_wine
ok
(
is_freed
(
htext4
),
"expected freed mem %p
\n
"
,
htext4
);
ok
(
is_freed
(
htext4
),
"expected freed mem %p
\n
"
,
htext4
);
todo_wine
ok
(
is_freed
(
hmoveable
),
"expected freed mem %p
\n
"
,
hmoveable
);
ok
(
is_freed
(
hmoveable
),
"expected freed mem %p
\n
"
,
hmoveable
);
data
=
GetClipboardData
(
CF_TEXT
);
data
=
GetClipboardData
(
CF_TEXT
);
ok
(
is_fixed
(
data
),
"expected fixed mem %p
\n
"
,
data
);
ok
(
is_fixed
(
data
),
"expected fixed mem %p
\n
"
,
data
);
...
@@ -1935,7 +1935,7 @@ static void test_handles_process( const char *str )
...
@@ -1935,7 +1935,7 @@ static void test_handles_process( const char *str )
r
=
OpenClipboard
(
0
);
r
=
OpenClipboard
(
0
);
ok
(
r
,
"gle %d
\n
"
,
GetLastError
()
);
ok
(
r
,
"gle %d
\n
"
,
GetLastError
()
);
h
=
GetClipboardData
(
CF_TEXT
);
h
=
GetClipboardData
(
CF_TEXT
);
todo_wine_if
(
!
h
)
ok
(
is_fixed
(
h
),
"expected fixed mem %p
\n
"
,
h
);
ok
(
is_fixed
(
h
),
"expected fixed mem %p
\n
"
,
h
);
ptr
=
GlobalLock
(
h
);
ptr
=
GlobalLock
(
h
);
ok
(
!
strcmp
(
str
,
ptr
),
"wrong data '%.5s'
\n
"
,
ptr
);
ok
(
!
strcmp
(
str
,
ptr
),
"wrong data '%.5s'
\n
"
,
ptr
);
GlobalUnlock
(
h
);
GlobalUnlock
(
h
);
...
@@ -1945,13 +1945,13 @@ static void test_handles_process( const char *str )
...
@@ -1945,13 +1945,13 @@ static void test_handles_process( const char *str )
if
(
ptr
)
ok
(
!
strcmp
(
str
,
ptr
),
"wrong data '%.5s'
\n
"
,
ptr
);
if
(
ptr
)
ok
(
!
strcmp
(
str
,
ptr
),
"wrong data '%.5s'
\n
"
,
ptr
);
GlobalUnlock
(
h
);
GlobalUnlock
(
h
);
h
=
GetClipboardData
(
CF_GDIOBJFIRST
+
3
);
h
=
GetClipboardData
(
CF_GDIOBJFIRST
+
3
);
todo_wine_if
(
!
h
)
ok
(
is_fixed
(
h
),
"expected fixed mem %p
\n
"
,
h
);
ok
(
is_fixed
(
h
),
"expected fixed mem %p
\n
"
,
h
);
ptr
=
GlobalLock
(
h
);
ptr
=
GlobalLock
(
h
);
ok
(
!
strcmp
(
str
,
ptr
),
"wrong data '%.5s'
\n
"
,
ptr
);
ok
(
!
strcmp
(
str
,
ptr
),
"wrong data '%.5s'
\n
"
,
ptr
);
GlobalUnlock
(
h
);
GlobalUnlock
(
h
);
trace
(
"gdiobj %p
\n
"
,
h
);
trace
(
"gdiobj %p
\n
"
,
h
);
h
=
GetClipboardData
(
CF_PRIVATEFIRST
+
7
);
h
=
GetClipboardData
(
CF_PRIVATEFIRST
+
7
);
todo_wine_if
(
!
h
)
ok
(
is_fixed
(
h
),
"expected fixed mem %p
\n
"
,
h
);
ok
(
is_fixed
(
h
),
"expected fixed mem %p
\n
"
,
h
);
ptr
=
GlobalLock
(
h
);
ptr
=
GlobalLock
(
h
);
ok
(
!
strcmp
(
str
,
ptr
),
"wrong data '%.5s'
\n
"
,
ptr
);
ok
(
!
strcmp
(
str
,
ptr
),
"wrong data '%.5s'
\n
"
,
ptr
);
GlobalUnlock
(
h
);
GlobalUnlock
(
h
);
...
@@ -1972,13 +1972,11 @@ static void test_handles_process( const char *str )
...
@@ -1972,13 +1972,11 @@ static void test_handles_process( const char *str )
trace
(
"palette %p
\n
"
,
h
);
trace
(
"palette %p
\n
"
,
h
);
h
=
GetClipboardData
(
CF_METAFILEPICT
);
h
=
GetClipboardData
(
CF_METAFILEPICT
);
ok
(
is_fixed
(
h
),
"expected fixed mem %p
\n
"
,
h
);
ok
(
is_fixed
(
h
),
"expected fixed mem %p
\n
"
,
h
);
if
(
h
)
ok
(
GetObjectType
(
((
METAFILEPICT
*
)
h
)
->
hMF
)
==
OBJ_METAFILE
,
ok
(
GetObjectType
(
((
METAFILEPICT
*
)
h
)
->
hMF
)
==
OBJ_METAFILE
,
"wrong object %p
\n
"
,
((
METAFILEPICT
*
)
h
)
->
hMF
);
"wrong object %p
\n
"
,
((
METAFILEPICT
*
)
h
)
->
hMF
);
trace
(
"metafile %p
\n
"
,
h
);
trace
(
"metafile %p
\n
"
,
h
);
h
=
GetClipboardData
(
CF_DSPMETAFILEPICT
);
h
=
GetClipboardData
(
CF_DSPMETAFILEPICT
);
ok
(
is_fixed
(
h
),
"expected fixed mem %p
\n
"
,
h
);
ok
(
is_fixed
(
h
),
"expected fixed mem %p
\n
"
,
h
);
if
(
h
)
ok
(
GetObjectType
(
((
METAFILEPICT
*
)
h
)
->
hMF
)
==
OBJ_METAFILE
,
ok
(
GetObjectType
(
((
METAFILEPICT
*
)
h
)
->
hMF
)
==
OBJ_METAFILE
,
"wrong object %p
\n
"
,
((
METAFILEPICT
*
)
h
)
->
hMF
);
"wrong object %p
\n
"
,
((
METAFILEPICT
*
)
h
)
->
hMF
);
trace
(
"metafile2 %p
\n
"
,
h
);
trace
(
"metafile2 %p
\n
"
,
h
);
...
...
include/wine/server_protocol.h
View file @
f0fbf1a9
...
@@ -4468,7 +4468,7 @@ struct open_clipboard_request
...
@@ -4468,7 +4468,7 @@ struct open_clipboard_request
struct
open_clipboard_reply
struct
open_clipboard_reply
{
{
struct
reply_header
__header
;
struct
reply_header
__header
;
int
owner
;
user_handle_t
owner
;
char
__pad_12
[
4
];
char
__pad_12
[
4
];
};
};
...
@@ -4538,6 +4538,8 @@ struct set_clipboard_data_request
...
@@ -4538,6 +4538,8 @@ struct set_clipboard_data_request
struct
set_clipboard_data_reply
struct
set_clipboard_data_reply
{
{
struct
reply_header
__header
;
struct
reply_header
__header
;
unsigned
int
seqno
;
char
__pad_12
[
4
];
};
};
...
@@ -4546,15 +4548,17 @@ struct get_clipboard_data_request
...
@@ -4546,15 +4548,17 @@ struct get_clipboard_data_request
{
{
struct
request_header
__header
;
struct
request_header
__header
;
unsigned
int
format
;
unsigned
int
format
;
int
cached
;
unsigned
int
seqno
;
};
};
struct
get_clipboard_data_reply
struct
get_clipboard_data_reply
{
{
struct
reply_header
__header
;
struct
reply_header
__header
;
unsigned
int
from
;
unsigned
int
from
;
user_handle_t
owner
;
user_handle_t
owner
;
unsigned
int
seqno
;
data_size_t
total
;
data_size_t
total
;
/* VARARG(data,bytes); */
/* VARARG(data,bytes); */
char
__pad_20
[
4
];
};
};
...
@@ -6438,6 +6442,6 @@ union generic_reply
...
@@ -6438,6 +6442,6 @@ union generic_reply
struct
terminate_job_reply
terminate_job_reply
;
struct
terminate_job_reply
terminate_job_reply
;
};
};
#define SERVER_PROTOCOL_VERSION 52
1
#define SERVER_PROTOCOL_VERSION 52
2
#endif
/* __WINE_WINE_SERVER_PROTOCOL_H */
#endif
/* __WINE_WINE_SERVER_PROTOCOL_H */
server/clipboard.c
View file @
f0fbf1a9
...
@@ -42,6 +42,7 @@ struct clip_format
...
@@ -42,6 +42,7 @@ struct clip_format
struct
list
entry
;
/* entry in format list */
struct
list
entry
;
/* entry in format list */
unsigned
int
id
;
/* format id */
unsigned
int
id
;
/* format id */
unsigned
int
from
;
/* for synthesized data, format to generate it from */
unsigned
int
from
;
/* for synthesized data, format to generate it from */
unsigned
int
seqno
;
/* sequence number when the data was set */
data_size_t
size
;
/* size of the data block */
data_size_t
size
;
/* size of the data block */
void
*
data
;
/* data contents, or NULL for delay-rendered */
void
*
data
;
/* data contents, or NULL for delay-rendered */
};
};
...
@@ -207,7 +208,7 @@ static int synthesize_formats( struct clipboard *clipboard )
...
@@ -207,7 +208,7 @@ static int synthesize_formats( struct clipboard *clipboard )
void
*
data
=
memdup
(
&
clipboard
->
lcid
,
sizeof
(
clipboard
->
lcid
)
);
void
*
data
=
memdup
(
&
clipboard
->
lcid
,
sizeof
(
clipboard
->
lcid
)
);
if
((
format
=
add_format
(
clipboard
,
CF_LOCALE
)))
if
((
format
=
add_format
(
clipboard
,
CF_LOCALE
)))
{
{
clipboard
->
seqno
++
;
format
->
seqno
=
clipboard
->
seqno
++
;
format
->
data
=
data
;
format
->
data
=
data
;
format
->
size
=
sizeof
(
clipboard
->
lcid
);
format
->
size
=
sizeof
(
clipboard
->
lcid
);
}
}
...
@@ -222,6 +223,7 @@ static int synthesize_formats( struct clipboard *clipboard )
...
@@ -222,6 +223,7 @@ static int synthesize_formats( struct clipboard *clipboard )
else
continue
;
else
continue
;
if
(
!
(
format
=
add_format
(
clipboard
,
formats
[
i
][
0
]
)))
continue
;
if
(
!
(
format
=
add_format
(
clipboard
,
formats
[
i
][
0
]
)))
continue
;
format
->
from
=
from
;
format
->
from
=
from
;
format
->
seqno
=
clipboard
->
seqno
;
total
++
;
total
++
;
}
}
return
total
;
return
total
;
...
@@ -385,7 +387,7 @@ DECL_HANDLER(open_clipboard)
...
@@ -385,7 +387,7 @@ DECL_HANDLER(open_clipboard)
clipboard
->
open_win
=
win
;
clipboard
->
open_win
=
win
;
clipboard
->
open_thread
=
current
;
clipboard
->
open_thread
=
current
;
reply
->
owner
=
(
clipboard
->
owner_thread
&&
clipboard
->
owner_thread
->
process
==
current
->
process
)
;
reply
->
owner
=
clipboard
->
owner_win
;
}
}
...
@@ -459,13 +461,15 @@ DECL_HANDLER(set_clipboard_data)
...
@@ -459,13 +461,15 @@ DECL_HANDLER(set_clipboard_data)
}
}
}
}
clipboard
->
seqno
++
;
format
->
from
=
0
;
format
->
from
=
0
;
format
->
seqno
=
clipboard
->
seqno
++
;
format
->
size
=
get_req_data_size
();
format
->
size
=
get_req_data_size
();
format
->
data
=
data
;
format
->
data
=
data
;
if
(
req
->
format
==
CF_TEXT
||
req
->
format
==
CF_OEMTEXT
||
req
->
format
==
CF_UNICODETEXT
)
if
(
req
->
format
==
CF_TEXT
||
req
->
format
==
CF_OEMTEXT
||
req
->
format
==
CF_UNICODETEXT
)
clipboard
->
lcid
=
req
->
lcid
;
clipboard
->
lcid
=
req
->
lcid
;
reply
->
seqno
=
format
->
seqno
;
}
}
...
@@ -489,7 +493,9 @@ DECL_HANDLER(get_clipboard_data)
...
@@ -489,7 +493,9 @@ DECL_HANDLER(get_clipboard_data)
}
}
reply
->
from
=
format
->
from
;
reply
->
from
=
format
->
from
;
reply
->
total
=
format
->
size
;
reply
->
total
=
format
->
size
;
reply
->
seqno
=
format
->
seqno
;
if
(
!
format
->
data
&&
!
format
->
from
)
reply
->
owner
=
clipboard
->
owner_win
;
if
(
!
format
->
data
&&
!
format
->
from
)
reply
->
owner
=
clipboard
->
owner_win
;
if
(
req
->
cached
&&
req
->
seqno
==
format
->
seqno
)
return
;
/* client-side cache still valid */
if
(
format
->
size
<=
get_reply_max_size
())
set_reply_data
(
format
->
data
,
format
->
size
);
if
(
format
->
size
<=
get_reply_max_size
())
set_reply_data
(
format
->
data
,
format
->
size
);
else
set_error
(
STATUS_BUFFER_OVERFLOW
);
else
set_error
(
STATUS_BUFFER_OVERFLOW
);
}
}
...
...
server/protocol.def
View file @
f0fbf1a9
...
@@ -3162,7 +3162,7 @@ enum caret_state
...
@@ -3162,7 +3162,7 @@ enum caret_state
@REQ(open_clipboard)
@REQ(open_clipboard)
user_handle_t window; /* clipboard window */
user_handle_t window; /* clipboard window */
@REPLY
@REPLY
int owner; /* is the process already the owner?
*/
user_handle_t owner; /* current clipboard owner
*/
@END
@END
...
@@ -3204,15 +3204,20 @@ enum caret_state
...
@@ -3204,15 +3204,20 @@ enum caret_state
unsigned int format; /* clipboard format of the data */
unsigned int format; /* clipboard format of the data */
unsigned int lcid; /* locale id to use for synthesizing text formats */
unsigned int lcid; /* locale id to use for synthesizing text formats */
VARARG(data,bytes); /* data contents */
VARARG(data,bytes); /* data contents */
@REPLY
unsigned int seqno; /* sequence number for the set data */
@END
@END
/* Fetch a data format from the clipboard */
/* Fetch a data format from the clipboard */
@REQ(get_clipboard_data)
@REQ(get_clipboard_data)
unsigned int format; /* clipboard format of the data */
unsigned int format; /* clipboard format of the data */
int cached; /* do we already have it in the client-side cache? */
unsigned int seqno; /* sequence number for the data in the cache */
@REPLY
@REPLY
unsigned int from; /* for synthesized data, format to generate it from */
unsigned int from; /* for synthesized data, format to generate it from */
user_handle_t owner; /* clipboard owner for delayed-rendered formats */
user_handle_t owner; /* clipboard owner for delayed-rendered formats */
unsigned int seqno; /* sequence number for the originally set data */
data_size_t total; /* total data size */
data_size_t total; /* total data size */
VARARG(data,bytes); /* data contents */
VARARG(data,bytes); /* data contents */
@END
@END
...
...
server/request.h
View file @
f0fbf1a9
...
@@ -2053,11 +2053,16 @@ C_ASSERT( sizeof(struct empty_clipboard_request) == 16 );
...
@@ -2053,11 +2053,16 @@ C_ASSERT( sizeof(struct empty_clipboard_request) == 16 );
C_ASSERT
(
FIELD_OFFSET
(
struct
set_clipboard_data_request
,
format
)
==
12
);
C_ASSERT
(
FIELD_OFFSET
(
struct
set_clipboard_data_request
,
format
)
==
12
);
C_ASSERT
(
FIELD_OFFSET
(
struct
set_clipboard_data_request
,
lcid
)
==
16
);
C_ASSERT
(
FIELD_OFFSET
(
struct
set_clipboard_data_request
,
lcid
)
==
16
);
C_ASSERT
(
sizeof
(
struct
set_clipboard_data_request
)
==
24
);
C_ASSERT
(
sizeof
(
struct
set_clipboard_data_request
)
==
24
);
C_ASSERT
(
FIELD_OFFSET
(
struct
set_clipboard_data_reply
,
seqno
)
==
8
);
C_ASSERT
(
sizeof
(
struct
set_clipboard_data_reply
)
==
16
);
C_ASSERT
(
FIELD_OFFSET
(
struct
get_clipboard_data_request
,
format
)
==
12
);
C_ASSERT
(
FIELD_OFFSET
(
struct
get_clipboard_data_request
,
format
)
==
12
);
C_ASSERT
(
sizeof
(
struct
get_clipboard_data_request
)
==
16
);
C_ASSERT
(
FIELD_OFFSET
(
struct
get_clipboard_data_request
,
cached
)
==
16
);
C_ASSERT
(
FIELD_OFFSET
(
struct
get_clipboard_data_request
,
seqno
)
==
20
);
C_ASSERT
(
sizeof
(
struct
get_clipboard_data_request
)
==
24
);
C_ASSERT
(
FIELD_OFFSET
(
struct
get_clipboard_data_reply
,
from
)
==
8
);
C_ASSERT
(
FIELD_OFFSET
(
struct
get_clipboard_data_reply
,
from
)
==
8
);
C_ASSERT
(
FIELD_OFFSET
(
struct
get_clipboard_data_reply
,
owner
)
==
12
);
C_ASSERT
(
FIELD_OFFSET
(
struct
get_clipboard_data_reply
,
owner
)
==
12
);
C_ASSERT
(
FIELD_OFFSET
(
struct
get_clipboard_data_reply
,
total
)
==
16
);
C_ASSERT
(
FIELD_OFFSET
(
struct
get_clipboard_data_reply
,
seqno
)
==
16
);
C_ASSERT
(
FIELD_OFFSET
(
struct
get_clipboard_data_reply
,
total
)
==
20
);
C_ASSERT
(
sizeof
(
struct
get_clipboard_data_reply
)
==
24
);
C_ASSERT
(
sizeof
(
struct
get_clipboard_data_reply
)
==
24
);
C_ASSERT
(
FIELD_OFFSET
(
struct
get_clipboard_formats_request
,
format
)
==
12
);
C_ASSERT
(
FIELD_OFFSET
(
struct
get_clipboard_formats_request
,
format
)
==
12
);
C_ASSERT
(
sizeof
(
struct
get_clipboard_formats_request
)
==
16
);
C_ASSERT
(
sizeof
(
struct
get_clipboard_formats_request
)
==
16
);
...
...
server/trace.c
View file @
f0fbf1a9
...
@@ -3741,7 +3741,7 @@ static void dump_open_clipboard_request( const struct open_clipboard_request *re
...
@@ -3741,7 +3741,7 @@ static void dump_open_clipboard_request( const struct open_clipboard_request *re
static
void
dump_open_clipboard_reply
(
const
struct
open_clipboard_reply
*
req
)
static
void
dump_open_clipboard_reply
(
const
struct
open_clipboard_reply
*
req
)
{
{
fprintf
(
stderr
,
" owner=%
d
"
,
req
->
owner
);
fprintf
(
stderr
,
" owner=%
08x
"
,
req
->
owner
);
}
}
static
void
dump_close_clipboard_request
(
const
struct
close_clipboard_request
*
req
)
static
void
dump_close_clipboard_request
(
const
struct
close_clipboard_request
*
req
)
...
@@ -3780,15 +3780,23 @@ static void dump_set_clipboard_data_request( const struct set_clipboard_data_req
...
@@ -3780,15 +3780,23 @@ static void dump_set_clipboard_data_request( const struct set_clipboard_data_req
dump_varargs_bytes
(
", data="
,
cur_size
);
dump_varargs_bytes
(
", data="
,
cur_size
);
}
}
static
void
dump_set_clipboard_data_reply
(
const
struct
set_clipboard_data_reply
*
req
)
{
fprintf
(
stderr
,
" seqno=%08x"
,
req
->
seqno
);
}
static
void
dump_get_clipboard_data_request
(
const
struct
get_clipboard_data_request
*
req
)
static
void
dump_get_clipboard_data_request
(
const
struct
get_clipboard_data_request
*
req
)
{
{
fprintf
(
stderr
,
" format=%08x"
,
req
->
format
);
fprintf
(
stderr
,
" format=%08x"
,
req
->
format
);
fprintf
(
stderr
,
", cached=%d"
,
req
->
cached
);
fprintf
(
stderr
,
", seqno=%08x"
,
req
->
seqno
);
}
}
static
void
dump_get_clipboard_data_reply
(
const
struct
get_clipboard_data_reply
*
req
)
static
void
dump_get_clipboard_data_reply
(
const
struct
get_clipboard_data_reply
*
req
)
{
{
fprintf
(
stderr
,
" from=%08x"
,
req
->
from
);
fprintf
(
stderr
,
" from=%08x"
,
req
->
from
);
fprintf
(
stderr
,
", owner=%08x"
,
req
->
owner
);
fprintf
(
stderr
,
", owner=%08x"
,
req
->
owner
);
fprintf
(
stderr
,
", seqno=%08x"
,
req
->
seqno
);
fprintf
(
stderr
,
", total=%u"
,
req
->
total
);
fprintf
(
stderr
,
", total=%u"
,
req
->
total
);
dump_varargs_bytes
(
", data="
,
cur_size
);
dump_varargs_bytes
(
", data="
,
cur_size
);
}
}
...
@@ -4973,7 +4981,7 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = {
...
@@ -4973,7 +4981,7 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = {
(
dump_func
)
dump_close_clipboard_reply
,
(
dump_func
)
dump_close_clipboard_reply
,
(
dump_func
)
dump_set_clipboard_info_reply
,
(
dump_func
)
dump_set_clipboard_info_reply
,
NULL
,
NULL
,
NULL
,
(
dump_func
)
dump_set_clipboard_data_reply
,
(
dump_func
)
dump_get_clipboard_data_reply
,
(
dump_func
)
dump_get_clipboard_data_reply
,
(
dump_func
)
dump_get_clipboard_formats_reply
,
(
dump_func
)
dump_get_clipboard_formats_reply
,
(
dump_func
)
dump_enum_clipboard_formats_reply
,
(
dump_func
)
dump_enum_clipboard_formats_reply
,
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment