]> git.ipfire.org Git - thirdparty/open-vm-tools.git/commitdiff
Internal branch sync. Included in this change:
authorVMware, Inc <>
Mon, 22 Mar 2010 22:30:08 +0000 (15:30 -0700)
committerMarcelo Vanzin <mvanzin@vmware.com>
Mon, 22 Mar 2010 22:30:08 +0000 (15:30 -0700)
. Unity: 'Interlock' minimize operations through the host.

. Close up va_list before exiting.

. Shutdown Linux Copy Paste and DnD on X IO error properly.

Signed-off-by: Marcelo Vanzin <mvanzin@vmware.com>
12 files changed:
open-vm-tools/lib/include/vm_version.h
open-vm-tools/lib/misc/posixPosix.c
open-vm-tools/lib/unity/unity.c
open-vm-tools/lib/unity/unityPlatform.h
open-vm-tools/lib/unity/unityPlatformX11.c
open-vm-tools/vmware-user/copyPasteDnDWrapper.cpp
open-vm-tools/vmware-user/copyPasteDnDWrapper.h
open-vm-tools/vmware-user/copyPasteUI.cpp
open-vm-tools/vmware-user/copyPasteUI.h
open-vm-tools/vmware-user/dndUI.cpp
open-vm-tools/vmware-user/dndUI.h
open-vm-tools/vmware-user/vmware-user.cpp

index 6e688278b366ff78db39033aeca3d1cd763935d5..ea960f1c4c102f4438ef2673184a2729787abf76 100644 (file)
 #define PRODUCT_VERSION_WORKSTATION_5 PRODUCT_WORKSTATION_BRIEF_NAME " 5.x"
 #define PRODUCT_VERSION_WORKSTATION_6 PRODUCT_WORKSTATION_BRIEF_NAME " 6.0"
 #define PRODUCT_VERSION_WORKSTATION_65 PRODUCT_WORKSTATION_BRIEF_NAME " 6.5"
-#define PRODUCT_VERSION_WORKSTATION_70 PRODUCT_WORKSTATION_BRIEF_NAME " 7.0"
+#define PRODUCT_VERSION_WORKSTATION_7 PRODUCT_WORKSTATION_BRIEF_NAME " 7.x"
 #define PRODUCT_VERSION_WORKSTATION_80 PRODUCT_WORKSTATION_BRIEF_NAME " 8.0"
 #define PRODUCT_VERSION_WORKSTATION_ENTERPRISE_1 "ACE 1.x"
 #define PRODUCT_VERSION_WORKSTATION_ENTERPRISE_2 "ACE 2.0"
index 6340664fb73ee7024e6dbe19d2defb5a6febe705..d5df87d4c8576ca3b5b3566ef1eebcea00011912 100644 (file)
@@ -957,6 +957,7 @@ Posix_Execl(ConstUnicode pathName,   // IN:
          va_start(vl, arg0);
          for (i = 1; i < count; i++) {
             if (!PosixConvertToCurrent(va_arg(vl, char *), &argv[i])) {
+               va_end(vl);
                goto exit;
             }
          }
@@ -1035,6 +1036,7 @@ Posix_Execlp(ConstUnicode fileName,  // IN:
          va_start(vl, arg0);
          for (i = 1; i < count; i++) {
             if (!PosixConvertToCurrent(va_arg(vl, char *), &argv[i])) {
+               va_end(vl);
                goto exit;
             }
          }
index 21192b7ed21930abe62a6462e8afad02a72d5df8..9cd56f486a569cf1a1014d617694965f8bd80966 100644 (file)
@@ -153,6 +153,12 @@ static Bool UnityTcloSetWindowDesktop(char const **result,
                                       const char *args,
                                       size_t argsSize,
                                       void *clientData);
+static Bool UnityTcloConfirmOperation(char const **result,
+                                      size_t *resultLen,
+                                      const char *name,
+                                      const char *args,
+                                      size_t argsSize,
+                                      void *clientData);
 
 static void UnitySetAddHiddenWindows(Bool enabled);
 static void UnitySetInterlockMinimizeOperation(Bool enabled);
@@ -482,6 +488,8 @@ Unity_InitBackdoor(struct RpcIn *rpcIn)   // IN
                              UnityTcloSetDesktopActive, NULL);
       RpcIn_RegisterCallback(rpcIn, UNITY_RPC_WINDOW_DESKTOP_SET,
                              UnityTcloSetWindowDesktop, NULL);
+      RpcIn_RegisterCallback(rpcIn, UNITY_RPC_CONFIRM_OPERATION,
+                             UnityTcloConfirmOperation, NULL);
 
       RpcIn_RegisterCallbackEx(rpcIn, UNITY_RPC_SET_OPTIONS,
                                UnityTcloSetUnityOptions, NULL);
@@ -1127,6 +1135,67 @@ UnityTcloGetUpdate(char const **result,     // OUT
 }
 
 
+/*
+ *----------------------------------------------------------------------------
+ *
+ * UnityTcloConfirmOperation --
+ *
+ *     RPC handler for 'unity.operation.confirm'.
+ *
+ * Results:
+ *     TRUE if the confirmation could be handled sucessfully.
+ *     FALSE otherwise.
+ *
+ * Side effects:
+ *     None.
+ *
+ *----------------------------------------------------------------------------
+ */
+
+static Bool
+UnityTcloConfirmOperation(char const **result,     // OUT
+                          size_t *resultLen,       // OUT
+                          const char *name,        // IN
+                          const char *args,        // IN
+                          size_t argsSize,         // IN
+                          void *clientData)        // ignored
+{
+   UnityConfirmOperation unityConfirmOpMsg = {0};
+   UnityConfirmOperationV1 *confirmV1 = NULL;
+   Bool retVal = FALSE;
+   unsigned int ret;
+   Debug("%s: Enter.\n", __FUNCTION__);
+
+   /*
+    * Deserialize the XDR data. Note that the data begins with args + 1 since
+    * there is a space between the RPC name and the XDR serialization.
+    */
+   if (!XdrUtil_Deserialize((char *)args + 1, argsSize - 1,
+                            xdr_UnityConfirmOperation, &unityConfirmOpMsg)) {
+      ret = RpcIn_SetRetVals(result, resultLen, "Failed to deserialize data", FALSE);
+      goto exit;
+   }
+
+   confirmV1 = unityConfirmOpMsg.UnityConfirmOperation_u.unityConfirmOpV1;
+   if (MINIMIZE == confirmV1->details.op) {
+      retVal = UnityPlatformConfirmMinimizeOperation(unity.up,
+                                                     confirmV1->windowId,
+                                                     confirmV1->sequence,
+                                                     confirmV1->allow);
+   } else {
+      Debug("%s: Confirmation for unknown operation ID = %d\n", __FUNCTION__,
+            confirmV1->details.op);
+   }
+   /* Free any memory allocated by XDR - we're done with unityConfirmOpMsg */
+   VMX_XDR_FREE(xdr_UnityConfirmOperation, &unityConfirmOpMsg);
+   ret = RpcIn_SetRetVals(result, resultLen, "", retVal);
+
+exit:
+   Debug("%s: Exit.\n", __FUNCTION__);
+   return ret;
+}
+
+
 /*
  *----------------------------------------------------------------------------
  *
@@ -1250,6 +1319,12 @@ UnityUpdateCallbackFn(void *param,          // IN: dynbuf
       break;
 
    case UNITY_UPDATE_REMOVE_WINDOW:
+      /*
+       * Let the platform know that this window has been removed. This is
+       * useful on platforms that must poll for window changes.
+       */
+      UnityPlatformWillRemoveWindow(unity.up, update->u.removeWindow.id);
+
       Str_Sprintf(data, sizeof data, "remove %u", update->u.removeWindow.id);
       DynBuf_AppendString(buf, data);
       break;
@@ -2111,8 +2186,8 @@ UnityTcloSetUnityOptions(RpcInData *data)
    while (unityFeatureTable[featureIndex].featureBit != 0) {
       if (featuresChanged & unityFeatureTable[featureIndex].featureBit) {
          unityFeatureTable[featureIndex].setter(
-            optionsMsg.UnityOptions_u.unityOptionsV1->featureMask &
-            unityFeatureTable[featureIndex].featureBit);
+            (optionsMsg.UnityOptions_u.unityOptionsV1->featureMask &
+            unityFeatureTable[featureIndex].featureBit) != 0);
       }
       featureIndex++;
    }
@@ -2261,6 +2336,76 @@ out:
 }
 
 
+/*
+ *----------------------------------------------------------------------------
+ *
+ * UnityXdrRequestOperation --
+ *
+ *    XDR encoder function for UnityRequestOperation.
+ *
+ *    See UnityXdrSendRpc().
+ *
+ * Results:
+ *    Returns true if the XDR struct was encoded successfully.
+ *
+ * Side-effects:
+ *    None.
+ *------------------------------------------------------------------------------
+ */
+
+Bool
+UnityXdrRequestOperation(XDR *xdrs,    // IN
+                         void *arg)    // IN
+{
+   ASSERT(xdrs);
+   ASSERT(arg);
+   return xdr_UnityRequestOperation(xdrs, (UnityRequestOperation *) arg);
+}
+
+
+/*
+ *------------------------------------------------------------------------------
+ *
+ * UnitySendRequestMinimizeOperation --
+ *
+ *     Send a request for a minimize operation to the host.
+ *
+ * Results:
+ *     TRUE if everything is successful.
+ *     FALSE otherwise.
+ *
+ * Side effects:
+ *     None.
+ *
+ *----------------------------------------------------------------------------
+ */
+
+Bool
+UnitySendRequestMinimizeOperation(UnityWindowId windowId,   // IN
+                                  uint32 sequence)          // IN
+{
+   Bool ret = FALSE;
+   UnityRequestOperation msg = { 0 };
+   UnityRequestOperationV1 v1 = { 0 };
+
+   Debug("%s: Enter.\n", __FUNCTION__);
+
+   v1.windowId = windowId;
+   v1.sequence = sequence;
+   v1.details.op = MINIMIZE;
+
+   msg.ver = UNITY_OP_V1;
+   msg.UnityRequestOperation_u.unityRequestOpV1 = &v1;
+
+   ret = UnityXdrSendRpc(UNITY_RPC_REQUEST_OPERATION,
+                         &UnityXdrRequestOperation,
+                         &msg);
+
+   Debug("%s: Exit.\n", __FUNCTION__);
+   return ret;
+}
+
+
 /*
  *----------------------------------------------------------------------------
  *
@@ -2407,6 +2552,7 @@ UnitySetInterlockMinimizeOperation(Bool enabled)
       Debug("%s: Do not interlock minimize operations through the host\n",
             __FUNCTION__);
    }
+   UnityPlatformSetInterlockMinimizeOperation(unity.up, enabled);
 }
 
 
index 5f686707b7fd329a984f5d60ec08966201c8f22c..ff9a26cc06ef3d1b2a679bdbdef0cf8181e0125a 100644 (file)
@@ -28,7 +28,6 @@
 #include "unityWindowTracker.h"
 #include "unity.h"
 
-
 /**
  * Container used to store and send Unity updates.
  */
@@ -122,6 +121,11 @@ Bool UnityPlatformStickWindow(UnityPlatform *up,
                               UnityWindowId windowId);
 Bool UnityPlatformUnstickWindow(UnityPlatform *up,
                                 UnityWindowId windowId);
+void UnityPlatformSetInterlockMinimizeOperation(UnityPlatform *up,Bool enabled);
+Bool UnityPlatformConfirmMinimizeOperation(UnityPlatform *up,
+                                           UnityWindowId windowId,
+                                           uint32 sequence,
+                                           Bool allow);
 Bool UnityPlatformIsUnityRunning(UnityPlatform *up);
 Bool UnityPlatformStartHelperThreads(UnityPlatform *up);
 void UnityPlatformKillHelperThreads(UnityPlatform *up);
@@ -139,11 +143,20 @@ Bool UnityPlatformRequestWindowContents(UnityPlatform *up,
                                         UnityWindowId windowIds[],
                                         uint32 numWindowIds);
 
+/*
+ * Function called by UnityUpdateCallbackFn whenever a window is removed from
+ * the tracker.
+ *
+ * NOTE: This function is called with the platform lock held.
+ */
+void UnityPlatformWillRemoveWindow(UnityPlatform *up, UnityWindowId windowId);
+
 /* Functions implemented in unity.c for use by the platform-specific code. */
 void UnityGetUpdateCommon(int flags, DynBuf *buf);
 Bool UnityUpdateChannelInit(UnityUpdateChannel *updateChannel);
 void UnityUpdateChannelCleanup(UnityUpdateChannel *updateChannel);
 Bool UnitySendUpdates(UnityUpdateChannel *updateChannel);
+Bool UnitySendRequestMinimizeOperation(UnityWindowId windowId, uint32 sequence);
 
 /* Sends the provided window contents to the host. */
 Bool UnitySendWindowContents(UnityWindowId windowID,
index fe6ef1ba9c437db6b90e2c1b031a127c7dc1f865..abd5f943d7ea2d8df68974780dad7fa587dd3dce 100644 (file)
@@ -3083,6 +3083,82 @@ UnityPlatformRequestWindowContents(UnityPlatform *up,
 }
 
 
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * UnityPlatformConfirmMinimizeOperation --
+ *
+ *     Minimize a window (if allowed) by the host.
+ *
+ * Results:
+ *     Returns TRUE if successful, and FALSE otherwise.
+ *
+ * Side effects:
+ *     None.
+ *
+ *------------------------------------------------------------------------------
+ */
+
+Bool
+UnityPlatformConfirmMinimizeOperation(UnityPlatform *up,        // IN
+                                      UnityWindowId windowId,   // IN
+                                      uint32 sequence,          // IN
+                                      Bool allow)               // IN
+{
+   ASSERT(up);
+   return FALSE;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * UnityPlatformSetInterlockMinimizeOperation --
+ *
+ *     Enable (or Disable) the interlocking (relaying) of minimize operations
+ *     through the host.
+ *
+ * Results:
+ *     None.
+ *
+ * Side effects:
+ *     None.
+ *
+ *------------------------------------------------------------------------------
+ */
+
+void UnityPlatformSetInterlockMinimizeOperation(UnityPlatform *up,   // IN
+                                                Bool enabled)        // IN
+{
+   ASSERT(up);
+}
+
+
+/*
+ *------------------------------------------------------------------------------
+ *
+ * UnityPlatformWillRemoveWindow --
+ *
+ *    Called when a window is removed from the UnityWindowTracker.
+ *
+ *    NOTE: This function is called with the platform lock held.
+ *
+ * Results:
+ *    None.
+ *
+ * Side effects:
+ *    None.
+ *------------------------------------------------------------------------------
+ */
+
+void
+UnityPlatformWillRemoveWindow(UnityPlatform *up,      // IN
+                              UnityWindowId windowId) // IN
+{
+   ASSERT(up);
+}
+
+
 /*
  ******************************************************************************
  * Begin file-scope functions.
index fe9f1c639735b059148dcc1b66bc2346537bdaf2..65d64f8fdf622d051b4133287eec9c295a64629a 100644 (file)
@@ -220,6 +220,25 @@ CopyPasteDnDWrapper::RegisterCP()
 }
 
 
+/**
+ *
+ * Cancel DnD and copy paste.
+ */
+
+void
+CopyPasteDnDWrapper::Cancel()
+{
+#if defined(HAVE_GTKMM)
+   if (m_dndUI) {
+      m_dndUI->Cancel();
+   }
+   if (m_copyPasteUI) {
+      m_copyPasteUI->Cancel();
+   }
+#endif
+}
+
+
 /**
  *
  * Register DnD capabilities with the VMX. Try newest version
index 0e6c8f774bbbb8accea85ff76fa2abbb734daed6..474c67251770b3b0b6254c18ea433b39b89ffe28 100644 (file)
@@ -61,6 +61,7 @@ public:
    void SetDnDIsRegistered(bool isRegistered);
    bool IsDnDRegistered();
    void OnReset();
+   void Cancel();
    void SetBlockControl(DnDBlockControl *blockCtrl);
    void SetUserData(const void *userData);
    void SetHGWnd(GtkWidget *wnd) {m_hgWnd = wnd;};
index 8ffb5909fe4d1fb0457d2bdeca8beaa07e26b318..46f9236255baed22df42c64ed7b2e6c8561d2092 100644 (file)
@@ -150,6 +150,37 @@ CopyPasteUI::~CopyPasteUI()
 }
 
 
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * CopyPasteUI::Cancel --
+ *
+ *    Cancel file transfer and remove block.
+ *
+ * Results:
+ *    None.
+ *
+ * Side effects:
+ *    None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+void
+CopyPasteUI::Cancel()
+{
+   Debug("%s: enter\n", __FUNCTION__);
+   if (mBlockAdded) {
+      DnD_DeleteStagingFiles(mHGStagingDir.c_str(), FALSE);
+      Debug("%s: removing block for %s\n", __FUNCTION__, mHGStagingDir.c_str());
+      mBlockCtrl->RemoveBlock(mBlockCtrl->fd, mHGStagingDir.c_str());
+      mBlockAdded = false;
+   }
+
+   mFileTransferDone = true;
+}
+
+
 /*
  *-----------------------------------------------------------------------------
  *
index 66d856a5b1c42a3ec644cddcba9240e678f8894c..5bb4a7907b895abfc65454ada6871c19bc50b6c7 100644 (file)
@@ -60,6 +60,7 @@ public:
    void SetCopyPasteAllowed(bool isCopyPasteAllowed)
       { mCP.SetCopyPasteAllowed(isCopyPasteAllowed); }
    void Reset(void);
+   void Cancel(void);
    void SetBlockControl(DnDBlockControl *blockCtrl)
       { Debug("Setting mBlockCtrl to %p\n", blockCtrl);
         mBlockCtrl = blockCtrl; }
index 7598c75b120bc78ae1cf12c2952f1ef8ee01abc5..94a88c4f1608e88bd0a62a21701306b9bf897406 100644 (file)
@@ -271,6 +271,26 @@ DnDUI::CommonResetCB(void)
 }
 
 
+/**
+ *
+ * Cancel any DnD file transfers and reset.
+ */
+
+void
+DnDUI::Cancel()
+{
+   Debug("%s: enter\n", __FUNCTION__);
+   if (m_blockAdded) {
+      /*
+       * If we don't do this, the destination will have something to
+       * copy, and likely truncated. So remove it.
+       */
+      DnD_DeleteStagingFiles(m_HGStagingDir.c_str(), false);
+   }
+   CommonResetCB();
+}
+
+
 /* Source functions for HG DnD. */
 
 /**
@@ -499,6 +519,10 @@ DnDUI::CommonUpdateDetWndCB(bool bShow,
                             int32 x,
                             int32 y)
 {
+   Debug("%s: enter 0x%lx show %d x %d y %d\n",
+         __FUNCTION__,
+         (unsigned long) m_detWnd->get_window()->gobj(), bShow, x, y);
+
    /* If the window is being shown, move it to the right place. */
    if (bShow) {
       x = MAX(x - DRAG_DET_WINDOW_WIDTH / 2, 0);
@@ -538,6 +562,10 @@ DnDUI::CommonUpdateUnityDetWndCB(bool bShow,
                                  uint32 unityWndId,
                                  bool bottom)
 {
+   Debug("%s: enter 0x%lx unityID 0x%x\n",
+         __FUNCTION__,
+         (unsigned long) m_detWnd->get_window()->gobj(),
+         unityWndId);
    if (bShow && ((unityWndId > 0) || bottom)) {
       int width = m_detWnd->GetScreenWidth();
       int height = m_detWnd->GetScreenHeight();
@@ -650,9 +678,9 @@ DnDUI::GtkDestDragMotionCB(const Glib::RefPtr<Gdk::DragContext> &dc,
    /*
     * If this is a Host to Guest drag, we are done here, so return.
     */
-   Debug("%s: enter", __FUNCTION__);
-
    unsigned long curTime = GetTimeInMillis();
+   Debug("%s: enter dc %p, m_dc %p\n", __FUNCTION__,
+         dc ? dc->gobj() : NULL, m_dc ? m_dc : NULL);
    if (curTime - m_destDropTime <= 1000) {
       Debug("%s: ignored %ld %ld %ld\n", __FUNCTION__,
             curTime, m_destDropTime, curTime - m_destDropTime);
@@ -763,7 +791,21 @@ void
 DnDUI::GtkDestDragLeaveCB(const Glib::RefPtr<Gdk::DragContext> &dc,
                           guint time)
 {
-   Debug("%s: enter\n", __FUNCTION__);
+   Debug("%s: enter dc %p, m_dc %p\n", __FUNCTION__,
+         dc ? dc->gobj() : NULL, m_dc ? m_dc : NULL);
+
+   /*
+    * If we reach here after reset DnD, or we are getting a late
+    * DnD drag leave signal (we have started another DnD), then
+    * finish the old DnD. Otherwise, Gtk will not reset and a new
+    * DnD will not start until Gtk+ times out (which appears to
+    * be 5 minutes).
+    * See http://bugzilla.eng.vmware.com/show_bug.cgi?id=528320
+    */
+   if (!m_dc || dc->gobj() != m_dc) {
+      Debug("%s: calling drag_finish\n", __FUNCTION__);
+      dc->drag_finish(true, false, time);
+   }
 }
 
 
@@ -822,7 +864,9 @@ DnDUI::GtkSourceDragDataGetCB(const Glib::RefPtr<Gdk::DragContext> &dc,
 
    selection_data.set(target.c_str(), "");
 
-   Debug("%s: enter with target %s\n", __FUNCTION__, target.c_str());
+   Debug("%s: enter dc %p, m_dc %p with target %s\n", __FUNCTION__,
+         dc ? dc->gobj() : NULL, m_dc ? m_dc : NULL,
+         target.c_str());
 
    if (!m_inHGDrag) {
       Debug("%s: not in drag, return\n", __FUNCTION__);
@@ -994,7 +1038,8 @@ DnDUI::GtkDestDragDataReceivedCB(const Glib::RefPtr<Gdk::DragContext> &dc,
                                  guint info,
                                  guint time)
 {
-   Debug("%s: enter\n", __FUNCTION__);
+   Debug("%s: enter dc %p, m_dc %p\n", __FUNCTION__,
+         dc ? dc->gobj() : NULL, m_dc ? m_dc : NULL);
    /* The GH DnD may already finish before we got response. */
    if (!m_GHDnDInProgress) {
       Debug("%s: not valid\n", __FUNCTION__);
@@ -1060,7 +1105,8 @@ DnDUI::GtkDestDragDropCB(const Glib::RefPtr<Gdk::DragContext> &dc,
                          int y,
                          guint time)
 {
-   Debug("%s: enter x %d y %d\n", __FUNCTION__, x, y);
+   Debug("%s: enter dc %p, m_dc %p x %d y %d\n", __FUNCTION__,
+         (dc ? dc->gobj() : NULL), (m_dc ? m_dc : NULL), x, y);
 
    Glib::ustring target;
 
index 233086c257bd7fbfbe6f79c66de8b3a2ed36f431..ab9925a9a60708fa3ed5d2d35e9a6362c81b3fd6 100644 (file)
@@ -67,6 +67,7 @@ public:
    void SetBlockControl(DnDBlockControl *blockCtrl);
    void SetUnityMode(Bool mode)
       {m_unityMode = mode;};
+   void Cancel();
 
    DragDetWnd *GetFullDetWnd() {return m_detWnd;}
    GtkWidget *GetDetWndAsWidget();
index 3ebd2f3bd9d223ba9ad6f42778a824d8ab18a683..28ac5c25e9c01dbab3c116d7fc4cd7fe392757e4 100644 (file)
@@ -176,8 +176,9 @@ static int const gSignals[] = {
  *-----------------------------------------------------------------------------
  */
 
-void VMwareUserCleanupRpc(void)
+void VMwareUserCleanupRpc(Bool isXError) // IN
 {
+   Debug("%s: enter\n", __FUNCTION__);
    if (gRpcIn) {
       Unity_UnregisterCaps();
       GHI_Cleanup();
@@ -190,7 +191,7 @@ void VMwareUserCleanupRpc(void)
       }
 
       if (!RpcIn_stop(gRpcIn)) {
-         Debug("Failed to stop RpcIn loop\n");
+         Debug("%s: failed to stop RpcIn loop\n", __FUNCTION__);
       }
       if (gOpenUrlRegistered) {
          FoundryToolsDaemon_UnregisterOpenUrl();
@@ -198,10 +199,23 @@ void VMwareUserCleanupRpc(void)
       }
 
       CopyPasteDnDWrapper *p = CopyPasteDnDWrapper::GetInstance();
+
+      /*
+       * We can't call the normal APIs to tear down DnD/CP because they
+       * involve Xlib calls that can't be made after X IO error. So, use
+       * an entry point that performs a subset of the cleanup we normally
+       * do on a reset, to ensure that any file transfers in flight get
+       * failed properly. See bug 458626.
+       */
       if (p) {
-         p->UnregisterDnD();
-         p->UnregisterCP();
+         if (!isXError) {
+            p->UnregisterDnD();
+            p->UnregisterCP();
+         } else {
+            p->Cancel();
+         }
       }
+
       RpcIn_Destruct(gRpcIn);
       gRpcIn = NULL;
    }
@@ -241,7 +255,7 @@ void VMwareUserSignalHandler(int sig) // IN
    }
 
    if (gSigExit) {
-      VMwareUserCleanupRpc();
+      VMwareUserCleanupRpc(FALSE);
    }
 
 #if defined(HAVE_GTKMM)
@@ -273,7 +287,7 @@ void
 VMwareUser_OnDestroy(GtkWidget *widget, // IN: Unused
                      gpointer data)     // IN: Unused
 {
-   VMwareUserCleanupRpc();
+   VMwareUserCleanupRpc(FALSE);
 #if defined(HAVE_GTKMM)
    Gtk::Main::quit();
 #else
@@ -653,13 +667,13 @@ int VMwareUserXIOErrorHandler(Display *dpy)
     * watching the process being run.  When it dies, it will come
     * through here, so we don't want to let it shut down the Rpc
     */
-   Debug("> VMwareUserXIOErrorHandler\n");
+   Debug("> %s\n", __FUNCTION__);
    if (my_pid == gParentPid) {
-      VMwareUserCleanupRpc();
+      VMwareUserCleanupRpc(TRUE);
       ReloadSelf();
       exit(EXIT_FAILURE);
    } else {
-      Debug("VMwareUserXIOErrorHandler hit from forked() child, not cleaning Rpc\n");
+      Debug("%s hit from forked() child, not cleaning Rpc\n", __FUNCTION__);
       _exit(EXIT_FAILURE);
    }