VirtualBox

儲存庫 vbox 的更動 59832


忽略:
時間撮記:
2016-2-26 上午10:16:31 (9 年 以前)
作者:
vboxsync
訊息:

DnD/HostService: More code for host/guest side cancellation handling; simplified.

位置:
trunk/src/VBox/HostServices/DragAndDrop
檔案:
修改 2 筆資料

圖例:

未更動
新增
刪除
  • trunk/src/VBox/HostServices/DragAndDrop/dndmanager.cpp

    r58212 r59832  
    55
    66/*
    7  * Copyright (C) 2011-2015 Oracle Corporation
     7 * Copyright (C) 2011-2016 Oracle Corporation
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    4141int DnDManager::addMessage(uint32_t uMsg, uint32_t cParms, VBOXHGCMSVCPARM paParms[], bool fAppend /* = true */)
    4242{
    43     int rc = VINF_SUCCESS;
    44 
    45     LogFlowFunc(("uMsg=%RU32, cParms=%RU32, fAppend=%RTbool\n", uMsg, cParms, fAppend));
     43    int rc;
    4644
    4745    try
    4846    {
    49         DnDMessage *pMessage = NULL;
    50 
    51         switch (uMsg)
    52         {
    53             case DragAndDropSvc::HOST_DND_HG_EVT_ENTER:
    54             {
    55                 clear();
    56                 LogFlowFunc(("HOST_DND_HG_EVT_ENTER\n"));
    57                 break;
    58             }
    59 
    60             case DragAndDropSvc::HOST_DND_HG_EVT_MOVE:
    61             {
    62                 LogFlowFunc(("HOST_DND_HG_EVT_MOVE\n"));
    63                 break;
    64             }
    65 
    66             case DragAndDropSvc::HOST_DND_HG_EVT_LEAVE:
    67             {
    68                 LogFlowFunc(("HOST_DND_HG_EVT_LEAVE\n"));
    69                 break;
    70             }
    71 
    72             case DragAndDropSvc::HOST_DND_HG_EVT_DROPPED:
    73             {
    74                 LogFlowFunc(("HOST_DND_HG_EVT_DROPPED\n"));
    75                 break;
    76             }
    77 
    78             case DragAndDropSvc::HOST_DND_HG_EVT_CANCEL:
    79             {
    80                 LogFlowFunc(("HOST_DND_HG_EVT_CANCEL\n"));
    81 
    82                 pMessage = new DnDHGCancelMessage();
    83                 break;
    84             }
    85 
    86             case DragAndDropSvc::HOST_DND_HG_SND_DATA_HDR:
    87             {
    88                 LogFlowFunc(("HOST_DND_HG_SND_DATA_HDR\n"));
    89                 break;
    90             }
    91 
    92             case DragAndDropSvc::HOST_DND_HG_SND_DATA:
    93             {
    94                 LogFlowFunc(("HOST_DND_HG_SND_DATA\n"));
    95                 break;
    96             }
    97 
    98             case DragAndDropSvc::HOST_DND_HG_SND_DIR:
    99             {
    100                 LogFlowFunc(("HOST_DND_HG_SND_DIR\n"));
    101                 break;
    102             }
    103 
    104             /* New since protocol version 2 (VBox 5.0). */
    105             case DragAndDropSvc::HOST_DND_HG_SND_FILE_HDR:
    106             {
    107                 LogFlowFunc(("HOST_DND_HG_SND_FILE_HDR\n"));
    108                 break;
    109             }
    110 
    111             case DragAndDropSvc::HOST_DND_HG_SND_FILE_DATA:
    112             {
    113                 LogFlowFunc(("HOST_DND_HG_SND_FILE\n"));
    114 
    115                 /* No parameter verification here as, depending on the protocol version
    116                  * being used, the parameter count + types might change. */
    117                 break;
    118             }
    119 
    120 #ifdef VBOX_WITH_DRAG_AND_DROP_GH
    121             case DragAndDropSvc::HOST_DND_GH_REQ_PENDING:
    122             {
    123                 LogFlowFunc(("HOST_DND_GH_REQ_PENDING\n"));
    124                 break;
    125             }
    126 
    127             case DragAndDropSvc::HOST_DND_GH_EVT_DROPPED:
    128             {
    129                 LogFlowFunc(("HOST_DND_GH_EVT_DROPPED\n"));
    130                 break;
    131             }
    132 #endif /* VBOX_WITH_DRAG_AND_DROP_GH */
    133 
    134             default:
    135                 rc = VERR_NOT_IMPLEMENTED;
    136                 break;
    137         }
    138 
    139         if (RT_SUCCESS(rc))
    140         {
    141             if (!pMessage) /* Generic message needed? */
    142                 pMessage = new DnDGenericMessage(uMsg, cParms, paParms);
    143 
    144             if (fAppend)
    145                 m_dndMessageQueue.append(pMessage);
    146             else
    147                 m_dndMessageQueue.prepend(pMessage);
    148         }
     47        LogFlowFunc(("uMsg=%RU32, cParms=%RU32, fAppend=%RTbool\n", uMsg, cParms, fAppend));
     48
     49        DnDMessage *pMessage = new DnDGenericMessage(uMsg, cParms, paParms);
     50        if (fAppend)
     51            m_dndMessageQueue.append(pMessage);
     52        else
     53            m_dndMessageQueue.prepend(pMessage);
     54
     55        rc = VINF_SUCCESS;
    14956    }
    15057    catch(std::bad_alloc &)
     
    15360    }
    15461
     62    LogFlowFuncLeaveRC(rc);
    15563    return rc;
    15664}
     
    254162void DnDManager::clear(void)
    255163{
     164    LogFlowFuncEnter();
     165
    256166    if (m_pCurMsg)
    257167    {
  • trunk/src/VBox/HostServices/DragAndDrop/service.cpp

    r58329 r59832  
    55
    66/*
    7  * Copyright (C) 2011-2015 Oracle Corporation
     7 * Copyright (C) 2011-2016 Oracle Corporation
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    184184    RT_ZERO(data);
    185185    /** @todo Magic needed? */
     186    /** @todo Add context ID. */
    186187
    187188    if (m_SvcCtx.pfnHostCallback)
     
    987988            }
    988989#endif /* VBOX_WITH_DRAG_AND_DROP_GH */
     990
     991            /*
     992             * Note: This is a fire-and-forget message, as the host should
     993             *       not rely on an answer from the guest side in order to
     994             *       properly cancel the operation.
     995             */
     996            case HOST_DND_HG_EVT_CANCEL:
     997            {
     998                LogFlowFunc(("HOST_DND_HG_EVT_CANCEL\n"));
     999
     1000                VBOXDNDCBEVTERRORDATA data;
     1001                RT_ZERO(data);
     1002                data.hdr.uMagic = CB_MAGIC_DND_GH_EVT_ERROR;
     1003
     1004                switch (pClient->protocol())
     1005                {
     1006                    case 3:
     1007                    {
     1008                        /* Protocol v3+ at least requires the context ID. */
     1009                        if (cParms == 1)
     1010                            rc = paParms[0].getUInt32(&data.hdr.uContextID);
     1011
     1012                        break;
     1013                    }
     1014
     1015                    default:
     1016                        break;
     1017                }
     1018
     1019                /* Tell the host that the guest has cancelled the operation. */
     1020                data.rc = VERR_CANCELLED;
     1021
     1022                DO_HOST_CALLBACK();
     1023
     1024                /* Note: If the host is not prepared for handling the cancelling reply
     1025                 *       from the guest, don't report this back to the guest. */
     1026                if (RT_FAILURE(rc))
     1027                    rc = VINF_SUCCESS;
     1028                break;
     1029            }
     1030
    9891031            default:
    9901032            {
     
    9971039                        VBOXDNDCBHGGETNEXTHOSTMSGDATA data;
    9981040                        RT_ZERO(data);
     1041
    9991042                        data.hdr.uMagic = VBOX_DND_CB_MAGIC_MAKE(0 /* uFn */, 0 /* uVer */);
     1043
    10001044                        data.uMsg    = u32Function;
    10011045                        data.cParms  = cParms;
     
    10081052                            cParms  = data.cParms;
    10091053                            paParms = data.paParms;
     1054                        }
     1055                        else
     1056                        {
     1057                            /*
     1058                             * In case the guest is too fast asking for the next message
     1059                             * and the host did not supply it yet, just defer the client's
     1060                             * return until a response from the host available.
     1061                             */
     1062                            LogFlowFunc(("No new messages from the host (yet), deferring request: %Rrc\n", rc));
     1063                            rc = VINF_HGCM_ASYNC_EXECUTE;
    10101064                        }
    10111065                    }
     
    10401094        pClient->complete(callHandle, rc);
    10411095    else
     1096    {
     1097        AssertMsgFailed(("Guest call failed with %Rrc\n", rc));
    10421098        rc = VERR_NOT_IMPLEMENTED;
     1099    }
    10431100
    10441101    LogFlowFunc(("Returning rc=%Rrc\n", rc));
     
    10521109
    10531110    int rc;
    1054     if (u32Function == HOST_DND_SET_MODE)
    1055     {
    1056         if (cParms != 1)
    1057             rc = VERR_INVALID_PARAMETER;
    1058         else if (paParms[0].type != VBOX_HGCM_SVC_PARM_32BIT)
    1059             rc = VERR_INVALID_PARAMETER;
    1060         else
    1061             rc = modeSet(paParms[0].u.uint32);
    1062     }
    1063     else if (modeGet() != VBOX_DRAG_AND_DROP_MODE_OFF)
    1064     {
    1065         if (m_clientMap.size()) /* At least one client on the guest connected? */
     1111
     1112    do
     1113    {
     1114        bool fSendToGuest = false; /* Whether to send the message down to the guest side or not. */
     1115
     1116        switch (u32Function)
    10661117        {
     1118            case HOST_DND_SET_MODE:
     1119            {
     1120                if (cParms != 1)
     1121                    rc = VERR_INVALID_PARAMETER;
     1122                else if (paParms[0].type != VBOX_HGCM_SVC_PARM_32BIT)
     1123                    rc = VERR_INVALID_PARAMETER;
     1124                else
     1125                    rc = modeSet(paParms[0].u.uint32);
     1126                break;
     1127            }
     1128
     1129            case HOST_DND_HG_EVT_ENTER:
     1130            {
     1131                /* Clear the message queue as a new DnD operation just began. */
     1132                m_pManager->clear();
     1133
     1134                fSendToGuest = true;
     1135                break;
     1136            }
     1137
     1138            case HOST_DND_HG_EVT_CANCEL:
     1139            {
     1140                LogFlowFunc(("Cancelling all waiting clients ...\n"));
     1141
     1142                /* Clear the message queue as the host cancelled the whole operation. */
     1143                m_pManager->clear();
     1144
     1145                /*
     1146                 * Wake up all deferred clients and tell them to process
     1147                 * the cancelling message next.
     1148                 */
     1149                DnDClientQueue::iterator itQueue = m_clientQueue.begin();
     1150                while (itQueue != m_clientQueue.end())
     1151                {
     1152                    DnDClientMap::iterator itClient = m_clientMap.find(*itQueue);
     1153                    Assert(itClient != m_clientMap.end());
     1154
     1155                    DragAndDropClient *pClient = itClient->second;
     1156                    AssertPtr(pClient);
     1157
     1158                    int rc2 = pClient->addMessageInfo(HOST_DND_HG_EVT_CANCEL,
     1159                                                      /* Protocol v3+ also contains the context ID. */
     1160                                                      pClient->protocol() >= 3 ? 1 : 0);
     1161                    pClient->completeDeferred(rc2);
     1162
     1163                    m_clientQueue.erase(itQueue);
     1164                    itQueue = m_clientQueue.begin();
     1165                }
     1166
     1167                Assert(m_clientQueue.size() == 0);
     1168
     1169                /* Tell the host that everything went well. */
     1170                rc = VINF_SUCCESS;
     1171                break;
     1172            }
     1173
     1174            default:
     1175            {
     1176                fSendToGuest = true;
     1177                break;
     1178            }
     1179        }
     1180
     1181        if (fSendToGuest)
     1182        {
     1183            if (modeGet() == VBOX_DRAG_AND_DROP_MODE_OFF)
     1184            {
     1185                /* Tell the host that a wrong drag'n drop mode is set. */
     1186                rc = VERR_ACCESS_DENIED;
     1187                break;
     1188            }
     1189
     1190            if (m_clientMap.size() == 0) /* At least one client on the guest connected? */
     1191            {
     1192                /*
     1193                 * Tell the host that the guest does not support drag'n drop.
     1194                 * This might happen due to not installed Guest Additions or
     1195                 * not running VBoxTray/VBoxClient.
     1196                 */
     1197                rc = VERR_NOT_SUPPORTED;
     1198                break;
     1199            }
     1200
    10671201            rc = m_pManager->addMessage(u32Function, cParms, paParms, true /* fAppend */);
    1068             if (RT_SUCCESS(rc))
    1069             {
    1070                 if (m_clientQueue.size()) /* Any clients in our queue ready for processing the next command? */
    1071                 {
    1072                     uint32_t uClientNext = m_clientQueue.front();
    1073                     DnDClientMap::iterator itClientNext = m_clientMap.find(uClientNext);
    1074                     Assert(itClientNext != m_clientMap.end());
    1075 
    1076                     DragAndDropClient *pClient = itClientNext->second;
    1077                     AssertPtr(pClient);
    1078 
    1079                     /*
    1080                      * Check if this was a request for getting the next host
    1081                      * message. If so, return the message ID and the parameter
    1082                      * count. The message itself has to be queued.
    1083                      */
    1084                     uint32_t uMsg = pClient->message();
    1085                     if (uMsg == GUEST_DND_GET_NEXT_HOST_MSG)
    1086                     {
    1087                         LogFlowFunc(("Client %RU32 is waiting for next host msg\n", pClient->clientId()));
    1088 
    1089                         uint32_t uMsg1;
    1090                         uint32_t cParms1;
    1091                         rc = m_pManager->nextMessageInfo(&uMsg1, &cParms1);
    1092                         if (RT_SUCCESS(rc))
    1093                         {
    1094                             rc = pClient->addMessageInfo(uMsg1, cParms1);
    1095 
    1096                             /* Note: Report the current rc back to the guest. */
    1097                             pClient->completeDeferred(rc);
    1098 
    1099                             m_clientQueue.pop_front();
    1100                         }
    1101                     }
    1102                     else
    1103                         AssertMsgFailed(("Client ID=%RU32 in wrong state with uMsg=%RU32\n",
    1104                                          pClient->clientId(), uMsg));
    1105                 }
    1106                 else
    1107                     LogFlowFunc(("All clients busy; delaying execution\n"));
    1108             }
    1109             else
    1110                 AssertMsgFailed(("Adding new message of type=%RU32 failed with rc=%Rrc\n",
    1111                                  u32Function, rc));
    1112         }
    1113         else
    1114         {
     1202            if (RT_FAILURE(rc))
     1203            {
     1204                AssertMsgFailed(("Adding new message of type=%RU32 failed with rc=%Rrc\n", u32Function, rc));
     1205                break;
     1206            }
     1207
     1208            /* Any clients in our queue ready for processing the next command? */
     1209            if (m_clientQueue.size() == 0)
     1210            {
     1211                LogFlowFunc(("All clients (%zu) busy -- delaying execution\n", m_clientMap.size()));
     1212                break;
     1213            }
     1214
     1215            uint32_t uClientNext = m_clientQueue.front();
     1216            DnDClientMap::iterator itClientNext = m_clientMap.find(uClientNext);
     1217            Assert(itClientNext != m_clientMap.end());
     1218
     1219            DragAndDropClient *pClient = itClientNext->second;
     1220            AssertPtr(pClient);
     1221
    11151222            /*
    1116              * Tell the host that the guest does not support drag'n drop.
    1117              * This might happen due to not installed Guest Additions or
    1118              * not running VBoxTray/VBoxClient.
     1223             * Check if this was a request for getting the next host
     1224             * message. If so, return the message ID and the parameter
     1225             * count. The message itself has to be queued.
    11191226             */
    1120             rc = VERR_NOT_SUPPORTED;
    1121         }
    1122     }
    1123     else
    1124     {
    1125         /* Tell the host that a wrong drag'n drop mode is set. */
    1126         rc = VERR_ACCESS_DENIED;
    1127     }
     1227            uint32_t uMsgClient = pClient->message();
     1228
     1229            uint32_t uMsgNext   = 0;
     1230            uint32_t cParmsNext = 0;
     1231            int rcNext = m_pManager->nextMessageInfo(&uMsgNext, &cParmsNext);
     1232
     1233            LogFlowFunc(("uMsgClient=%RU32, uMsgNext=%RU32, cParmsNext=%RU32, rcNext=%Rrc\n",
     1234                         uMsgClient, uMsgNext, cParmsNext, rcNext));
     1235
     1236            if (RT_SUCCESS(rcNext))
     1237            {
     1238                if (uMsgClient == GUEST_DND_GET_NEXT_HOST_MSG)
     1239                {
     1240                    rc = pClient->addMessageInfo(uMsgNext, cParmsNext);
     1241
     1242                    /* Note: Report the current rc back to the guest. */
     1243                    pClient->completeDeferred(rc);
     1244
     1245                    m_clientQueue.pop_front();
     1246                }
     1247                /*
     1248                 * Does the message the client is waiting for match the message
     1249                 * next in the queue? Process it right away then.
     1250                 */
     1251                else if (uMsgClient == uMsgNext)
     1252                {
     1253                    rc = m_pManager->nextMessage(u32Function, cParms, paParms);
     1254
     1255                    /* Note: Report the current rc back to the guest. */
     1256                    pClient->completeDeferred(rc);
     1257                }
     1258                else /* Should not happen. */
     1259                    AssertMsgFailed(("Client ID=%RU32 in wrong state with uMsg=%RU32 (next message in queue: %RU32)\n",
     1260                                     pClient->clientId(), uMsgClient, uMsgNext));
     1261            }
     1262
     1263        } /* fSendToGuest */
     1264
     1265    } while (0); /* To use breaks. */
    11281266
    11291267    LogFlowFuncLeaveRC(rc);
注意: 瀏覽 TracChangeset 來幫助您使用更動檢視器

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette