From: Oliver Kurth Date: Fri, 2 Nov 2018 22:28:20 +0000 (-0700) Subject: Issue: Sometimes, there is a message "The system cannot find the file X-Git-Tag: stable-11.0.0~339 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=aa479bbdba6338d7988f5db9145b63d8796a926d;p=thirdparty%2Fopen-vm-tools.git Issue: Sometimes, there is a message "The system cannot find the file specified" popped up when drag and drop over multiple remote apps. Root cause: When drag over multiple remote apps, multiple pairs of dragEnter and dragLeave messages are sending. The DnD state or the dropSource/dataObject are messed up when handling the 2nd DragEnter with the 1st DragLeave at the same time. Solution: Besides fixing this issue, fixed several other issues also to enhance the handling for multiple pairs of messages in the same time: 1. In DnDController layer, avoid to reset the DnD state when handling the message responded from agent for previous sessions. 2. In agent, only set the DnD state to be Ready when the previous DoDragDrop is really cancelled by OLE. 3. In agent, only response to the button event when the drop is notified. 4. In agent, add a 2s timeout checking for cancelling process to avoid conflicting with another DnDThread to create dropSrouce. 5. In agent, add a 2s timeout checking for dragBegin process to avoid conflicting with previous dragBegin processing. 6. Add virtual prefix to the method "GetData". --- diff --git a/open-vm-tools/services/plugins/dndcp/dndGuest/vmGuestDnDMgr.cc b/open-vm-tools/services/plugins/dndcp/dndGuest/vmGuestDnDMgr.cc index 9c5020a83..1a7f0ca96 100644 --- a/open-vm-tools/services/plugins/dndcp/dndGuest/vmGuestDnDMgr.cc +++ b/open-vm-tools/services/plugins/dndcp/dndGuest/vmGuestDnDMgr.cc @@ -26,6 +26,7 @@ #include "dndRpcV4.hh" #include "tracer.hh" #include "vmGuestDnDMgr.hh" +#include "vmGuestDnDSrc.hh" extern "C" { #include "debug.h" @@ -122,3 +123,44 @@ VMGuestDnDMgr::CreateDnDRpcWithVersion(uint32 version) break; } } + + +/** + * Got srcDragBegin from rpc with valid data. Create mSrc if the state machine + * is ready. + * + * @param[in] sessionId active DnD session id + * @param[in] capability controller capability + * @param[in] clip cross-platform clipboard data. + */ + +void +VMGuestDnDMgr::OnRpcSrcDragBegin(uint32 sessionId, + const CPClipboard *clip) +{ + TRACE_CALL(); + + if (!mDnDAllowed) { + g_debug("%s: DnD is not allowed.\n", __FUNCTION__); + return; + } + + if (GUEST_DND_READY != mDnDState) { + g_debug("%s: Bad state: %d, reset\n", __FUNCTION__, mDnDState); + ResetDnD(); + return; + } + + if (mSrc) { + g_debug("%s: mSrc is not NULL\n", __FUNCTION__); + delete mSrc; + mSrc = NULL; + } + + SetSessionId(sessionId); + + ASSERT(clip); + + mSrc = new VMGuestDnDSrc(this); + mSrc->OnRpcDragBegin(clip); +} diff --git a/open-vm-tools/services/plugins/dndcp/dndGuest/vmGuestDnDMgr.hh b/open-vm-tools/services/plugins/dndcp/dndGuest/vmGuestDnDMgr.hh index 76f828ed7..36548cc01 100644 --- a/open-vm-tools/services/plugins/dndcp/dndGuest/vmGuestDnDMgr.hh +++ b/open-vm-tools/services/plugins/dndcp/dndGuest/vmGuestDnDMgr.hh @@ -43,6 +43,8 @@ protected: virtual void AddUnityDnDDetTimeoutEvent(); virtual void AddHideDetWndTimerEvent(); virtual void CreateDnDRpcWithVersion(uint32 version); + virtual void OnRpcSrcDragBegin(uint32 sessionId, + const CPClipboard *clip); private: ToolsAppCtx *mToolsAppCtx; diff --git a/open-vm-tools/services/plugins/dndcp/dndGuestBase/guestDnD.hh b/open-vm-tools/services/plugins/dndcp/dndGuestBase/guestDnD.hh index bf8603915..e452e7227 100644 --- a/open-vm-tools/services/plugins/dndcp/dndGuestBase/guestDnD.hh +++ b/open-vm-tools/services/plugins/dndcp/dndGuestBase/guestDnD.hh @@ -117,8 +117,8 @@ public: static gboolean DnDUnityDetTimeout(void *clientData); protected: - void OnRpcSrcDragBegin(uint32 sessionId, - const CPClipboard *clip); + virtual void OnRpcSrcDragBegin(uint32 sessionId, + const CPClipboard *clip) = 0; void OnRpcQueryExiting(uint32 sessionId, int32 x, int32 y); void OnRpcUpdateUnityDetWnd(uint32 sessionId, bool show, @@ -163,7 +163,7 @@ protected: /* Callbacks from rpc for DnD source. */ void OnRpcUpdateMouse(uint32 sessionId, int32 x, int32 y); void OnRpcDrop(uint32 sessionId, int32 x, int32 y); - void OnRpcCancel(uint32 sessionId); + virtual void OnRpcCancel(uint32 sessionId); void OnRpcGetFilesDone(uint32 sessionId, bool success, const uint8 *stagingDirCP, diff --git a/open-vm-tools/services/plugins/dndcp/dndGuestBase/guestDnDMgr.cc b/open-vm-tools/services/plugins/dndcp/dndGuestBase/guestDnDMgr.cc index 832590cef..be4cb4e09 100644 --- a/open-vm-tools/services/plugins/dndcp/dndGuestBase/guestDnDMgr.cc +++ b/open-vm-tools/services/plugins/dndcp/dndGuestBase/guestDnDMgr.cc @@ -26,12 +26,6 @@ #include "guestDnD.hh" #include "guestDnDCPMgr.hh" -#ifdef DND_VM -#include "vmGuestDnDSrc.hh" -#else -#include "crtGuestDnDSrc.hh" -#endif - extern "C" { #include "debug.h" } @@ -207,52 +201,6 @@ GuestDnDMgr::DestUIDragEnter(const CPClipboard *clip) } -/** - * Got srcDragBegin from rpc with valid data. Create mSrc if the state machine - * is ready. - * - * @param[in] sessionId active DnD session id - * @param[in] capability controller capability - * @param[in] clip cross-platform clipboard data. - */ - -void -GuestDnDMgr::OnRpcSrcDragBegin(uint32 sessionId, - const CPClipboard *clip) -{ - TRACE_CALL(); - - if (!mDnDAllowed) { - g_debug("%s: DnD is not allowed.\n", __FUNCTION__); - return; - } - - if (GUEST_DND_READY != mDnDState) { - g_debug("%s: Bad state: %d, reset\n", __FUNCTION__, mDnDState); - ResetDnD(); - return; - } - - if (mSrc) { - g_debug("%s: mSrc is not NULL\n", __FUNCTION__); - delete mSrc; - mSrc = NULL; - } - - SetSessionId(sessionId); - - ASSERT(clip); - -#ifdef DND_VM - mSrc = new VMGuestDnDSrc(this); -#else - mSrc = new CRTGuestDnDSrc(this); -#endif - - mSrc->OnRpcDragBegin(clip); -} - - /** * Got queryExiting from rpc. Show the detection window on (x, y) to try to * detect any pending GH DnD.