summaryrefslogtreecommitdiff
path: root/vdagent/vdagent.cpp
diff options
context:
space:
mode:
authorArnon Gilboa <agilboa@redhat.com>2013-03-18 13:16:22 +0200
committerArnon Gilboa <agilboa@redhat.com>2013-03-18 13:16:22 +0200
commit482a4980f4a162787baa46aaffe989796e2dfd1a (patch)
tree409a18ae5ca6fdcbede5046b7b609bf00ff6fb09 /vdagent/vdagent.cpp
parent877e52386e6a98ec5c5bd54af13a984b571674ea (diff)
vdagent: for Win7 class, use ClipboardFormatListener api
(Win7 class includes Win8/Vista/Server2012/Server2008/R2) This new api was introduced in Vista/2K8 to keep track of clipboard changes, without the need to trust the (mis)behavior of other applications registered to the clipboard. If the issue is reproduced on XP as well, it can be hacked by a periodic call to ChangeClipboardChain & SetClipboardViewer as described in http://social.msdn.microsoft.com/Forums/en-US/csharplanguage/thread/ 521183dc-7872-472e-8104-8c0d75b1bf53 rhbz #919451
Diffstat (limited to 'vdagent/vdagent.cpp')
-rw-r--r--vdagent/vdagent.cpp40
1 files changed, 38 insertions, 2 deletions
diff --git a/vdagent/vdagent.cpp b/vdagent/vdagent.cpp
index 1dcfd1a..b5d65cd 100644
--- a/vdagent/vdagent.cpp
+++ b/vdagent/vdagent.cpp
@@ -65,6 +65,8 @@ typedef struct ALIGN_VC VDIChunk {
#define VD_MESSAGE_HEADER_SIZE (sizeof(VDIChunk) + sizeof(VDAgentMessage))
#define VD_READ_BUF_SIZE (sizeof(VDIChunk) + VD_AGENT_MAX_DATA_SIZE)
+typedef BOOL (WINAPI *PCLIPBOARD_OP)(HWND);
+
class VDAgent {
public:
static VDAgent* get();
@@ -120,6 +122,10 @@ private:
static VDAgent* _singleton;
HWND _hwnd;
HWND _hwnd_next_viewer;
+ HMODULE _user_lib;
+ PCLIPBOARD_OP _add_clipboard_listener;
+ PCLIPBOARD_OP _remove_clipboard_listener;
+ int _system_version;
int _clipboard_owner;
DWORD _clipboard_tick;
DWORD _buttons_state;
@@ -174,6 +180,9 @@ VDAgent* VDAgent::get()
VDAgent::VDAgent()
: _hwnd (NULL)
, _hwnd_next_viewer (NULL)
+ , _user_lib (NULL)
+ , _add_clipboard_listener (NULL)
+ , _remove_clipboard_listener (NULL)
, _clipboard_owner (owner_none)
, _clipboard_tick (0)
, _buttons_state (0)
@@ -201,6 +210,7 @@ VDAgent::VDAgent()
TCHAR log_path[MAX_PATH];
TCHAR temp_path[MAX_PATH];
+ _system_version = supported_system_version();
if (GetTempPath(MAX_PATH, temp_path)) {
swprintf_s(log_path, MAX_PATH, VD_AGENT_LOG_PATH, temp_path);
_log = VDLog::get(log_path);
@@ -262,6 +272,22 @@ bool VDAgent::run()
if (!SetProcessShutdownParameters(0x100, 0)) {
vd_printf("SetProcessShutdownParameters failed %lu", GetLastError());
}
+ if (_system_version == SYS_VER_WIN_7_CLASS) {
+ _user_lib = LoadLibrary(L"User32.dll");
+ if (!_user_lib) {
+ vd_printf("LoadLibrary failed %lu", GetLastError());
+ return false;
+ }
+ _add_clipboard_listener =
+ (PCLIPBOARD_OP)GetProcAddress(_user_lib, "AddClipboardFormatListener");
+ _remove_clipboard_listener =
+ (PCLIPBOARD_OP)GetProcAddress(_user_lib, "RemoveClipboardFormatListener");
+ if (!_add_clipboard_listener || !_remove_clipboard_listener) {
+ vd_printf("GetProcAddress failed %lu", GetLastError());
+ cleanup();
+ return false;
+ }
+ }
_control_event = CreateEvent(NULL, FALSE, FALSE, NULL);
if (!_control_event) {
vd_printf("CreateEvent() failed: %lu", GetLastError());
@@ -320,6 +346,7 @@ bool VDAgent::run()
void VDAgent::cleanup()
{
+ FreeLibrary(_user_lib);
CloseHandle(_stop_event);
CloseHandle(_control_event);
CloseHandle(_vio_serial);
@@ -420,7 +447,11 @@ void VDAgent::input_desktop_message_loop()
if (!WTSRegisterSessionNotification(_hwnd, NOTIFY_FOR_ALL_SESSIONS)) {
vd_printf("WTSRegisterSessionNotification() failed: %lu", GetLastError());
}
- _hwnd_next_viewer = SetClipboardViewer(_hwnd);
+ if (_system_version == SYS_VER_WIN_7_CLASS) {
+ _add_clipboard_listener(_hwnd);
+ } else {
+ _hwnd_next_viewer = SetClipboardViewer(_hwnd);
+ }
while (_running && !_desktop_switch) {
event_dispatcher(INFINITE, QS_ALLINPUT);
}
@@ -429,7 +460,11 @@ void VDAgent::input_desktop_message_loop()
KillTimer(_hwnd, VD_TIMER_ID);
_pending_input = false;
}
- ChangeClipboardChain(_hwnd, _hwnd_next_viewer);
+ if (_system_version == SYS_VER_WIN_7_CLASS) {
+ _remove_clipboard_listener(_hwnd);
+ } else {
+ ChangeClipboardChain(_hwnd, _hwnd_next_viewer);
+ }
WTSUnRegisterSessionNotification(_hwnd);
DestroyWindow(_hwnd);
CloseDesktop(hdesk);
@@ -1343,6 +1378,7 @@ LRESULT CALLBACK VDAgent::wnd_proc(HWND hwnd, UINT message, WPARAM wparam, LPARA
SendMessage(a->_hwnd_next_viewer, message, wparam, lparam);
}
break;
+ case WM_CLIPBOARDUPDATE:
case WM_DRAWCLIPBOARD:
if (a->_hwnd != GetClipboardOwner()) {
a->set_clipboard_owner(a->owner_none);