Changeset 75859 in vbox for trunk/src/VBox/HostServices/GuestControl/service.cpp
- Timestamp:
- Dec 1, 2018 10:53:50 PM (6 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/HostServices/GuestControl/service.cpp
r75853 r75859 60 60 * Header Files * 61 61 *********************************************************************************************************************************/ 62 //#define USE_PVCLIENT 62 63 #define LOG_GROUP LOG_GROUP_GUEST_CONTROL 63 64 #include <VBox/HostServices/GuestControlSvc.h> … … 190 191 * duplicated as well. 191 192 * 192 * @return IPRTstatus code.193 * @returns VBox status code. 193 194 * @param idFunction The host function (message) number, eHostFn. 194 195 * @param cParms Number of parameters in the HGCM request. … … 309 310 * current HGCM request. 310 311 * 311 * @return IPRTstatus code.312 * @returns VBox status code. 312 313 * @param paDstParms Array of parameters of HGCM request to fill the data into. 313 314 * @param cDstParms Number of parameters the HGCM request can handle. … … 867 868 /** @} */ 868 869 } ClientState; 870 #ifdef USE_PVCLIENT 871 typedef std::map< uint32_t, ClientState *> ClientStateMap; 872 typedef std::map< uint32_t, ClientState *>::iterator ClientStateMapIter; 873 typedef std::map< uint32_t, ClientState *>::const_iterator ClientStateMapIterConst; 874 #else 869 875 typedef std::map< uint32_t, ClientState > ClientStateMap; 870 876 typedef std::map< uint32_t, ClientState >::iterator ClientStateMapIter; 871 877 typedef std::map< uint32_t, ClientState >::const_iterator ClientStateMapIterConst; 878 #endif 872 879 873 880 /** … … 930 937 931 938 static DECLCALLBACK(int) svcUnload(void *pvService); 932 static DECLCALLBACK(int) svcConnect(void *pvService, uint32_t u32ClientID, void *pvClient,939 static DECLCALLBACK(int) svcConnect(void *pvService, uint32_t idClient, void *pvClient, 933 940 uint32_t fRequestor, bool fRestoring); 934 static DECLCALLBACK(int) svcDisconnect(void *pvService, uint32_t u32ClientID, void *pvClient);935 static DECLCALLBACK(void) svcCall(void *pvService, VBOXHGCMCALLHANDLE callHandle, uint32_t u32ClientID, void *pvClient,941 static DECLCALLBACK(int) svcDisconnect(void *pvService, uint32_t idClient, void *pvClient); 942 static DECLCALLBACK(void) svcCall(void *pvService, VBOXHGCMCALLHANDLE callHandle, uint32_t idClient, void *pvClient, 936 943 uint32_t u32Function, uint32_t cParms, VBOXHGCMSVCPARM paParms[], uint64_t tsArrival); 937 944 static DECLCALLBACK(int) svcHostCall(void *pvService, uint32_t u32Function, uint32_t cParms, VBOXHGCMSVCPARM paParms[]); … … 941 948 942 949 private: 943 int clientMakeMeMaster(uint32_t idClient, VBOXHGCMCALLHANDLE hCall, uint32_t cParms); 944 int clientMsgPeek(uint32_t idClient, VBOXHGCMCALLHANDLE hCall, uint32_t cParms, VBOXHGCMSVCPARM paParms[], bool fWait); 945 int clientMsgGet(uint32_t idClient, VBOXHGCMCALLHANDLE hCall, uint32_t cParms, VBOXHGCMSVCPARM paParms[]); 946 int clientMsgCancel(uint32_t idClient, uint32_t cParms); 947 int clientMsgSkip(uint32_t idClient, VBOXHGCMCALLHANDLE hCall, uint32_t cParms, VBOXHGCMSVCPARM paParms[]); 948 int clientSessionPrepare(uint32_t idClient, VBOXHGCMCALLHANDLE hCall, uint32_t cParms, VBOXHGCMSVCPARM paParms[]); 949 int clientSessionCancelPrepared(uint32_t idClient, uint32_t cParms, VBOXHGCMSVCPARM paParms[]); 950 int clientSessionAccept(uint32_t idClient, VBOXHGCMCALLHANDLE hCall, uint32_t cParms, VBOXHGCMSVCPARM paParms[]); 951 int clientSessionCloseOther(uint32_t idClient, uint32_t cParms, VBOXHGCMSVCPARM paParms[]); 952 953 int clientMsgOldGet(uint32_t u32ClientID, VBOXHGCMCALLHANDLE callHandle, uint32_t cParms, VBOXHGCMSVCPARM paParms[]); 954 int clientMsgOldFilterSet(uint32_t u32ClientID, uint32_t cParms, VBOXHGCMSVCPARM paParms[]); 955 int clientMsgOldSkip(uint32_t u32ClientID, uint32_t cParms); 956 957 int hostCallback(uint32_t eFunction, uint32_t cParms, VBOXHGCMSVCPARM paParms[]); 958 int hostProcessCommand(uint32_t eFunction, uint32_t cParms, VBOXHGCMSVCPARM paParms[]); 950 int clientMakeMeMaster(ClientState *pClient, VBOXHGCMCALLHANDLE hCall, uint32_t cParms); 951 int clientMsgPeek(ClientState *pClient, VBOXHGCMCALLHANDLE hCall, uint32_t cParms, VBOXHGCMSVCPARM paParms[], bool fWait); 952 int clientMsgGet(ClientState *pClient, VBOXHGCMCALLHANDLE hCall, uint32_t cParms, VBOXHGCMSVCPARM paParms[]); 953 int clientMsgCancel(ClientState *pClient, uint32_t cParms); 954 int clientMsgSkip(ClientState *pClient, VBOXHGCMCALLHANDLE hCall, uint32_t cParms, VBOXHGCMSVCPARM paParms[]); 955 int clientSessionPrepare(ClientState *pClient, VBOXHGCMCALLHANDLE hCall, uint32_t cParms, VBOXHGCMSVCPARM paParms[]); 956 int clientSessionCancelPrepared(ClientState *pClient, uint32_t cParms, VBOXHGCMSVCPARM paParms[]); 957 int clientSessionAccept(ClientState *pClient, VBOXHGCMCALLHANDLE hCall, uint32_t cParms, VBOXHGCMSVCPARM paParms[]); 958 int clientSessionCloseOther(ClientState *pClient, uint32_t cParms, VBOXHGCMSVCPARM paParms[]); 959 int clientToMain(ClientState *pClient, uint32_t idFunction, uint32_t cParms, VBOXHGCMSVCPARM paParms[]); 960 961 int clientMsgOldGet(ClientState *pClient, VBOXHGCMCALLHANDLE callHandle, uint32_t cParms, VBOXHGCMSVCPARM paParms[]); 962 int clientMsgOldFilterSet(ClientState *pClient, uint32_t cParms, VBOXHGCMSVCPARM paParms[]); 963 int clientMsgOldSkip(ClientState *pClient, uint32_t cParms); 964 965 int hostCallback(uint32_t idFunction, uint32_t cParms, VBOXHGCMSVCPARM paParms[]); 966 int hostProcessCommand(uint32_t idFunction, uint32_t cParms, VBOXHGCMSVCPARM paParms[]); 959 967 960 968 DECLARE_CLS_COPY_CTOR_ASSIGN_NOOP(GstCtrlService); … … 1000 1008 * Create client state. 1001 1009 */ 1010 ClientState *pClient; 1011 #ifdef USE_PVCLIENT 1002 1012 try 1003 1013 { 1014 pClient = new (pvClient) ClientState(pThis->mpHelpers, idClient); 1015 } 1016 catch (std::bad_alloc &) 1017 { 1018 return VERR_NO_MEMORY; 1019 } 1020 try 1021 { 1022 pThis->mClientStateMap[idClient] = pClient; 1023 } 1024 catch (std::bad_alloc &) 1025 { 1026 pClient->~ClientState(); 1027 return VERR_NO_MEMORY; 1028 } 1029 #else 1030 try 1031 { 1004 1032 pThis->mClientStateMap[idClient] = ClientState(pThis->mpHelpers, idClient); 1033 pClient = &pThis->mClientStateMap[idClient]; 1005 1034 } 1006 1035 catch (std::bad_alloc &) … … 1008 1037 return VERR_NO_MEMORY; 1009 1038 } 1010 ClientState &rClientState = pThis->mClientStateMap[idClient]; 1039 #endif 1011 1040 1012 1041 /* … … 1024 1053 LogFunc(("Picking %u as master for now.\n", idClient)); 1025 1054 pThis->m_idMasterClient = idClient; 1026 rClientState.m_fIsMaster = true;1055 pClient->m_fIsMaster = true; 1027 1056 } 1028 1057 } … … 1042 1071 GstCtrlService::svcDisconnect(void *pvService, uint32_t idClient, void *pvClient) 1043 1072 { 1044 RT_NOREF(pvClient);1045 AssertLogRelReturn(VALID_PTR(pvService), VERR_INVALID_PARAMETER);1046 1073 SELF *pThis = reinterpret_cast<SELF *>(pvService); 1047 1074 AssertPtrReturn(pThis, VERR_INVALID_POINTER); 1075 #ifdef USE_PVCLIENT 1076 ClientState *pClient = reinterpret_cast<ClientState *>(pvClient); 1077 AssertPtrReturn(pClient, VERR_INVALID_POINTER); 1078 #else 1079 RT_NOREF(pvClient); 1080 #endif 1048 1081 LogFlowFunc(("[Client %RU32] Disconnected (%zu clients total)\n", idClient, pThis->mClientStateMap.size())); 1049 1082 1083 #ifndef USE_PVCLIENT 1050 1084 ClientStateMapIter ItClientState = pThis->mClientStateMap.find(idClient); 1051 1085 AssertMsgReturn(ItClientState != pThis->mClientStateMap.end(), 1052 1086 ("Client ID=%RU32 not found in client list when it should be there\n", idClient), 1053 1087 VINF_SUCCESS); 1088 ClientState *pClient = ItClientState->second; 1089 #endif 1054 1090 1055 1091 /* 1056 1092 * Cancel all pending host commands, replying with GUEST_DISCONNECTED if final recipient. 1057 1093 */ 1058 { 1059 ClientState &rClientState = ItClientState->second; 1060 1061 while (!rClientState.mHostCmdList.empty()) 1062 { 1063 HostCommand *pHostCmd = *rClientState.mHostCmdList.begin(); 1064 rClientState.mHostCmdList.pop_front(); 1065 1066 uint32_t idFunction = pHostCmd->mMsgType; 1067 uint32_t idContext = pHostCmd->m_idContext; 1068 if (pHostCmd->SaneRelease() == 0) 1069 { 1070 VBOXHGCMSVCPARM Parm; 1071 HGCMSvcSetU32(&Parm, idContext); 1072 int rc2 = pThis->hostCallback(GUEST_DISCONNECTED, 1, &Parm); 1073 LogFlowFunc(("Cancelled host command %u (%s) with idContext=%#x -> %Rrc\n", 1074 idFunction, GstCtrlHostFnName((eHostFn)idFunction), idContext, rc2)); 1075 RT_NOREF(rc2, idFunction); 1076 } 1094 while (!pClient->mHostCmdList.empty()) 1095 { 1096 HostCommand *pHostCmd = *pClient->mHostCmdList.begin(); 1097 pClient->mHostCmdList.pop_front(); 1098 1099 uint32_t idFunction = pHostCmd->mMsgType; 1100 uint32_t idContext = pHostCmd->m_idContext; 1101 if (pHostCmd->SaneRelease() == 0) 1102 { 1103 VBOXHGCMSVCPARM Parm; 1104 HGCMSvcSetU32(&Parm, idContext); 1105 int rc2 = pThis->hostCallback(GUEST_DISCONNECTED, 1, &Parm); 1106 LogFlowFunc(("Cancelled host command %u (%s) with idContext=%#x -> %Rrc\n", 1107 idFunction, GstCtrlHostFnName((eHostFn)idFunction), idContext, rc2)); 1108 RT_NOREF(rc2, idFunction); 1077 1109 } 1078 1110 } … … 1081 1113 * Delete the client state. 1082 1114 */ 1115 #ifdef USE_PVCLIENT 1116 pThis->mClientStateMap.erase(idClient); 1117 pClient->~ClientState(); 1118 #else 1083 1119 pThis->mClientStateMap.erase(ItClientState); 1120 #endif 1121 pClient = NULL; 1084 1122 1085 1123 /* … … 1116 1154 * or defers the guest call until we have something from the host. 1117 1155 * 1118 * @return IPRT status code. 1119 * @param u32ClientID The client's ID. 1120 * @param callHandle The client's call handle. 1121 * @param cParms Number of parameters. 1122 * @param paParms Array of parameters. 1123 */ 1124 int GstCtrlService::clientMsgOldGet(uint32_t u32ClientID, VBOXHGCMCALLHANDLE callHandle, 1125 uint32_t cParms, VBOXHGCMSVCPARM paParms[]) 1126 { 1127 /* 1128 * Lookup client in our map so that we can assign the context ID of 1129 * a command to that client. 1130 */ 1131 ClientStateMapIter itClientState = mClientStateMap.find(u32ClientID); 1132 AssertMsg(itClientState != mClientStateMap.end(), ("Client with ID=%RU32 not found when it should be present\n", 1133 u32ClientID)); 1134 if (itClientState == mClientStateMap.end()) 1135 { 1136 /* Should never happen. Complete the call on the guest side though. */ 1137 AssertPtr(mpHelpers); 1138 mpHelpers->pfnCallComplete(callHandle, VERR_NOT_FOUND); 1139 1140 return VERR_NOT_FOUND; 1141 } 1142 1143 ClientState &clientState = itClientState->second; 1156 * @returns VBox status code. 1157 * @param pClient The client state. 1158 * @param hCall The client's call handle. 1159 * @param cParms Number of parameters. 1160 * @param paParms Array of parameters. 1161 */ 1162 int GstCtrlService::clientMsgOldGet(ClientState *pClient, VBOXHGCMCALLHANDLE hCall, uint32_t cParms, VBOXHGCMSVCPARM paParms[]) 1163 { 1164 ASSERT_GUEST(pClient->m_idSession != UINT32_MAX || pClient->m_fIsMaster); 1144 1165 1145 1166 /* Use the current (inbound) connection. */ 1146 1167 ClientConnection thisCon; 1147 thisCon.mHandle = callHandle;1168 thisCon.mHandle = hCall; 1148 1169 thisCon.mNumParms = cParms; 1149 1170 thisCon.mParms = paParms; 1150 1171 1151 return clientState.OldRunCurrent(&thisCon);1172 return pClient->OldRunCurrent(&thisCon); 1152 1173 } 1153 1174 … … 1161 1182 * @retval VERR_RESOURCE_BUSY if there is already a master. 1162 1183 * @retval VERR_VERSION_MISMATCH if VBoxGuest didn't supply requestor info. 1163 * @retval VERR_INVALID_CLIENT_ID1164 1184 * @retval VERR_WRONG_PARAMETER_COUNT 1165 1185 * 1166 * @param idClient The client's ID.1186 * @param pClient The client state. 1167 1187 * @param hCall The client's call handle. 1168 1188 * @param cParms Number of parameters. 1169 1189 */ 1170 int GstCtrlService::clientMakeMeMaster( uint32_t idClient, VBOXHGCMCALLHANDLE hCall, uint32_t cParms)1190 int GstCtrlService::clientMakeMeMaster(ClientState *pClient, VBOXHGCMCALLHANDLE hCall, uint32_t cParms) 1171 1191 { 1172 1192 /* … … 1182 1202 VERR_ACCESS_DENIED); 1183 1203 1184 ClientStateMapIter ItClientState = mClientStateMap.find(idClient);1185 ASSERT_GUEST_MSG_RETURN(ItClientState != mClientStateMap.end(), ("idClient=%RU32\n", idClient), VERR_INVALID_CLIENT_ID);1186 ClientState &rClientState = ItClientState->second;1187 1188 1204 /* 1189 1205 * Do the work. 1190 1206 */ 1191 ASSERT_GUEST_MSG_RETURN(m_idMasterClient == idClient|| m_idMasterClient == UINT32_MAX,1192 ("Already have master session %RU32, refusing %RU32.\n", m_idMasterClient, idClient),1207 ASSERT_GUEST_MSG_RETURN(m_idMasterClient == pClient->mID || m_idMasterClient == UINT32_MAX, 1208 ("Already have master session %RU32, refusing %RU32.\n", m_idMasterClient, pClient->mID), 1193 1209 VERR_RESOURCE_BUSY); 1194 1210 int rc = mpHelpers->pfnCallComplete(hCall, VINF_SUCCESS); 1195 1211 if (RT_SUCCESS(rc)) 1196 1212 { 1197 m_idMasterClient = idClient;1213 m_idMasterClient = pClient->mID; 1198 1214 m_fLegacyMode = false; 1199 rClientState.m_fIsMaster = true;1200 Log(("[Client %RU32] is master.\n", idClient));1215 pClient->m_fIsMaster = true; 1216 Log(("[Client %RU32] is master.\n", pClient->mID)); 1201 1217 } 1202 1218 else … … 1215 1231 * @retval VINF_HGCM_ASYNC_EXECUTE if message wait is pending. 1216 1232 * 1217 * @param idClient The client's ID.1233 * @param pClient The client state. 1218 1234 * @param hCall The client's call handle. 1219 1235 * @param cParms Number of parameters. … … 1222 1238 * immediately. 1223 1239 */ 1224 int GstCtrlService::clientMsgPeek( uint32_t idClient, VBOXHGCMCALLHANDLE hCall, uint32_t cParms, VBOXHGCMSVCPARM paParms[], bool fWait)1240 int GstCtrlService::clientMsgPeek(ClientState *pClient, VBOXHGCMCALLHANDLE hCall, uint32_t cParms, VBOXHGCMSVCPARM paParms[], bool fWait) 1225 1241 { 1226 1242 /* … … 1244 1260 } 1245 1261 1246 ClientStateMapIter ItClientState = mClientStateMap.find(idClient);1247 ASSERT_GUEST_MSG_RETURN(ItClientState != mClientStateMap.end(), ("idClient=%RU32\n", idClient), VERR_INVALID_CLIENT_ID);1248 ClientState &rClientState = ItClientState->second;1249 1250 1262 /* 1251 1263 * Check restore session ID. … … 1258 1270 paParms[0].u.uint32 = idRestore; 1259 1271 LogFlowFunc(("[Client %RU32] GUEST_MSG_PEEK_XXXX -> VERR_VM_RESTORED (%#RX64 -> %#RX64)\n", 1260 idClient, idRestoreCheck, idRestore));1272 pClient->mID, idRestoreCheck, idRestore)); 1261 1273 return VERR_VM_RESTORED; 1262 1274 } … … 1267 1279 * Return information about the first command if one is pending in the list. 1268 1280 */ 1269 HostCmdListIter itFirstCmd = rClientState.mHostCmdList.begin();1270 if (itFirstCmd != rClientState.mHostCmdList.end())1281 HostCmdListIter itFirstCmd = pClient->mHostCmdList.begin(); 1282 if (itFirstCmd != pClient->mHostCmdList.end()) 1271 1283 { 1272 1284 HostCommand *pFirstCmd = *itFirstCmd; 1273 1285 pFirstCmd->setPeekReturn(paParms, cParms); 1274 1286 LogFlowFunc(("[Client %RU32] GUEST_MSG_PEEK_XXXX -> VINF_SUCCESS (idMsg=%u (%s), cParms=%u)\n", 1275 idClient, pFirstCmd->mMsgType, GstCtrlHostFnName((eHostFn)pFirstCmd->mMsgType), pFirstCmd->mParmCount));1287 pClient->mID, pFirstCmd->mMsgType, GstCtrlHostFnName((eHostFn)pFirstCmd->mMsgType), pFirstCmd->mParmCount)); 1276 1288 return VINF_SUCCESS; 1277 1289 } … … 1282 1294 if (!fWait) 1283 1295 { 1284 LogFlowFunc(("[Client %RU32] GUEST_MSG_PEEK_NOWAIT -> VERR_TRY_AGAIN\n", idClient));1296 LogFlowFunc(("[Client %RU32] GUEST_MSG_PEEK_NOWAIT -> VERR_TRY_AGAIN\n", pClient->mID)); 1285 1297 return VERR_TRY_AGAIN; 1286 1298 } … … 1289 1301 * Wait for the host to queue a message for this client. 1290 1302 */ 1291 ASSERT_GUEST_MSG_RETURN( rClientState.mIsPending == 0, ("Already pending! (idClient=%RU32)\n", idClient), VERR_RESOURCE_BUSY);1292 rClientState.mPendingCon.mHandle = hCall;1293 rClientState.mPendingCon.mNumParms = cParms;1294 rClientState.mPendingCon.mParms = paParms;1295 rClientState.mIsPending = GUEST_MSG_PEEK_WAIT;1296 LogFlowFunc(("[Client %RU32] Is now in pending mode\n", idClient));1303 ASSERT_GUEST_MSG_RETURN(pClient->mIsPending == 0, ("Already pending! (idClient=%RU32)\n", pClient->mID), VERR_RESOURCE_BUSY); 1304 pClient->mPendingCon.mHandle = hCall; 1305 pClient->mPendingCon.mNumParms = cParms; 1306 pClient->mPendingCon.mParms = paParms; 1307 pClient->mIsPending = GUEST_MSG_PEEK_WAIT; 1308 LogFlowFunc(("[Client %RU32] Is now in pending mode\n", pClient->mID)); 1297 1309 return VINF_HGCM_ASYNC_EXECUTE; 1298 1310 } … … 1311 1323 * @retval VINF_HGCM_ASYNC_EXECUTE if message was completed already. 1312 1324 * 1313 * @param idClient The client's ID.1325 * @param pClient The client state. 1314 1326 * @param hCall The client's call handle. 1315 1327 * @param cParms Number of parameters. 1316 1328 * @param paParms Array of parameters. 1317 1329 */ 1318 int GstCtrlService::clientMsgGet( uint32_t idClient, VBOXHGCMCALLHANDLE hCall, uint32_t cParms, VBOXHGCMSVCPARM paParms[])1330 int GstCtrlService::clientMsgGet(ClientState *pClient, VBOXHGCMCALLHANDLE hCall, uint32_t cParms, VBOXHGCMSVCPARM paParms[]) 1319 1331 { 1320 1332 /* … … 1328 1340 : UINT32_MAX; 1329 1341 1330 ClientStateMapIter ItClientState = mClientStateMap.find(idClient);1331 ASSERT_GUEST_MSG_RETURN(ItClientState != mClientStateMap.end(), ("idClient=%RU32\n", idClient), VERR_INVALID_CLIENT_ID);1332 1333 ClientState &rClientState = ItClientState->second;1334 1335 1342 /* 1336 1343 * Return information aobut the first command if one is pending in the list. 1337 1344 */ 1338 HostCmdListIter itFirstCmd = rClientState.mHostCmdList.begin();1339 if (itFirstCmd != rClientState.mHostCmdList.end())1345 HostCmdListIter itFirstCmd = pClient->mHostCmdList.begin(); 1346 if (itFirstCmd != pClient->mHostCmdList.end()) 1340 1347 { 1341 1348 HostCommand *pFirstCmd = *itFirstCmd; … … 1405 1412 if (rc != VERR_CANCELLED) 1406 1413 { 1407 rClientState.mHostCmdList.erase(itFirstCmd);1414 pClient->mHostCmdList.erase(itFirstCmd); 1408 1415 pFirstCmd->SaneRelease(); 1409 1416 } … … 1417 1424 paParms[0].u.uint32 = 0; 1418 1425 paParms[1].u.uint32 = 0; 1419 LogFlowFunc(("[Client %RU32] GUEST_MSG_GET -> VERR_TRY_AGAIN\n", idClient));1426 LogFlowFunc(("[Client %RU32] GUEST_MSG_GET -> VERR_TRY_AGAIN\n", pClient->mID)); 1420 1427 return VERR_TRY_AGAIN; 1421 1428 } … … 1429 1436 * @retval VINF_HGCM_ASYNC_EXECUTE if message wait is pending. 1430 1437 * 1431 * @param idClient The client's ID.1438 * @param pClient The client state. 1432 1439 * @param cParms Number of parameters. 1433 1440 */ 1434 int GstCtrlService::clientMsgCancel( uint32_t idClient, uint32_t cParms)1441 int GstCtrlService::clientMsgCancel(ClientState *pClient, uint32_t cParms) 1435 1442 { 1436 1443 /* … … 1439 1446 ASSERT_GUEST_MSG_RETURN(cParms == 0, ("cParms=%u!\n", cParms), VERR_WRONG_PARAMETER_COUNT); 1440 1447 1441 ClientStateMapIter ItClientState = mClientStateMap.find(idClient); 1442 ASSERT_GUEST_MSG_RETURN(ItClientState != mClientStateMap.end(), ("idClient=%RU32\n", idClient), VERR_INVALID_CLIENT_ID); 1443 ClientState &rClientState = ItClientState->second; 1444 1445 if (rClientState.mIsPending != 0) 1446 { 1447 rClientState.CancelWaiting(); 1448 /* 1449 * Execute. 1450 */ 1451 if (pClient->mIsPending != 0) 1452 { 1453 pClient->CancelWaiting(); 1448 1454 return VINF_SUCCESS; 1449 1455 } … … 1459 1465 * @retval VERR_NOT_FOUND if no message pending. 1460 1466 * 1461 * @param idClient The client's ID.1467 * @param pClient The client state. 1462 1468 * @param hCall The call handle for completing it. 1463 1469 * @param cParms Number of parameters. 1464 1470 * @param paParms The parameters. 1465 1471 */ 1466 int GstCtrlService::clientMsgSkip( uint32_t idClient, VBOXHGCMCALLHANDLE hCall, uint32_t cParms, VBOXHGCMSVCPARM paParms[])1472 int GstCtrlService::clientMsgSkip(ClientState *pClient, VBOXHGCMCALLHANDLE hCall, uint32_t cParms, VBOXHGCMSVCPARM paParms[]) 1467 1473 { 1468 1474 /* … … 1485 1491 } 1486 1492 1487 ClientStateMapIter ItClientState = mClientStateMap.find(idClient);1488 ASSERT_GUEST_MSG_RETURN(ItClientState != mClientStateMap.end(), ("idClient=%RU32\n", idClient), VERR_INVALID_CLIENT_ID);1489 ClientState &rClientState = ItClientState->second;1490 1491 1493 /* 1492 1494 * Do the job. 1493 1495 */ 1494 if (! rClientState.mHostCmdList.empty())1495 { 1496 HostCommand *pFirstCmd = * rClientState.mHostCmdList.begin();1496 if (!pClient->mHostCmdList.empty()) 1497 { 1498 HostCommand *pFirstCmd = *pClient->mHostCmdList.begin(); 1497 1499 if ( pFirstCmd->mMsgType == idMsg 1498 1500 || idMsg == UINT32_MAX) … … 1504 1506 * Remove the command from the queue. 1505 1507 */ 1506 Assert(* rClientState.mHostCmdList.begin() == pFirstCmd);1507 rClientState.mHostCmdList.pop_front();1508 Assert(*pClient->mHostCmdList.begin() == pFirstCmd); 1509 pClient->mHostCmdList.pop_front(); 1508 1510 1509 1511 /* … … 1519 1521 HGCMSvcSetU32(&aReplyParams[3], rcSkip); /* flags / whatever */ 1520 1522 HGCMSvcSetPv(&aReplyParams[4], NULL, 0); /* data buffer */ 1521 GstCtrlService::hostCallback(GUEST_EXEC_STATUS, 5, aReplyParams);1523 hostCallback(GUEST_EXEC_STATUS, 5, aReplyParams); 1522 1524 break; 1523 1525 … … 1525 1527 HGCMSvcSetU32(&aReplyParams[1], GUEST_SESSION_NOTIFYTYPE_ERROR); /* type */ 1526 1528 HGCMSvcSetU32(&aReplyParams[2], rcSkip); /* result */ 1527 GstCtrlService::hostCallback(GUEST_SESSION_NOTIFY, 3, aReplyParams);1529 hostCallback(GUEST_SESSION_NOTIFY, 3, aReplyParams); 1528 1530 break; 1529 1531 … … 1533 1535 HGCMSvcSetU32(&aReplyParams[3], rcSkip); /* flags / whatever */ 1534 1536 HGCMSvcSetU32(&aReplyParams[4], 0); /* bytes consumed */ 1535 GstCtrlService::hostCallback(GUEST_EXEC_INPUT_STATUS, 5, aReplyParams);1537 hostCallback(GUEST_EXEC_INPUT_STATUS, 5, aReplyParams); 1536 1538 break; 1537 1539 … … 1540 1542 HGCMSvcSetU32(&aReplyParams[2], rcSkip); /* rc */ 1541 1543 HGCMSvcSetU32(&aReplyParams[3], VBOX_GUESTCTRL_CONTEXTID_GET_OBJECT(pFirstCmd->m_idContext)); /* handle */ 1542 GstCtrlService::hostCallback(GUEST_FILE_NOTIFY, 4, aReplyParams);1544 hostCallback(GUEST_FILE_NOTIFY, 4, aReplyParams); 1543 1545 break; 1544 1546 case HOST_FILE_CLOSE: 1545 1547 HGCMSvcSetU32(&aReplyParams[1], GUEST_FILE_NOTIFYTYPE_ERROR); /* type*/ 1546 1548 HGCMSvcSetU32(&aReplyParams[2], rcSkip); /* rc */ 1547 GstCtrlService::hostCallback(GUEST_FILE_NOTIFY, 3, aReplyParams);1549 hostCallback(GUEST_FILE_NOTIFY, 3, aReplyParams); 1548 1550 break; 1549 1551 case HOST_FILE_READ: … … 1552 1554 HGCMSvcSetU32(&aReplyParams[2], rcSkip); /* rc */ 1553 1555 HGCMSvcSetPv(&aReplyParams[3], NULL, 0); /* data buffer */ 1554 GstCtrlService::hostCallback(GUEST_FILE_NOTIFY, 4, aReplyParams);1556 hostCallback(GUEST_FILE_NOTIFY, 4, aReplyParams); 1555 1557 break; 1556 1558 case HOST_FILE_WRITE: … … 1559 1561 HGCMSvcSetU32(&aReplyParams[2], rcSkip); /* rc */ 1560 1562 HGCMSvcSetU32(&aReplyParams[3], 0); /* bytes written */ 1561 GstCtrlService::hostCallback(GUEST_FILE_NOTIFY, 4, aReplyParams);1563 hostCallback(GUEST_FILE_NOTIFY, 4, aReplyParams); 1562 1564 break; 1563 1565 case HOST_FILE_SEEK: … … 1565 1567 HGCMSvcSetU32(&aReplyParams[2], rcSkip); /* rc */ 1566 1568 HGCMSvcSetU64(&aReplyParams[3], 0); /* actual */ 1567 GstCtrlService::hostCallback(GUEST_FILE_NOTIFY, 4, aReplyParams);1569 hostCallback(GUEST_FILE_NOTIFY, 4, aReplyParams); 1568 1570 break; 1569 1571 case HOST_FILE_TELL: … … 1571 1573 HGCMSvcSetU32(&aReplyParams[2], rcSkip); /* rc */ 1572 1574 HGCMSvcSetU64(&aReplyParams[3], 0); /* actual */ 1573 GstCtrlService::hostCallback(GUEST_FILE_NOTIFY, 4, aReplyParams);1575 hostCallback(GUEST_FILE_NOTIFY, 4, aReplyParams); 1574 1576 break; 1575 1577 … … 1585 1587 HGCMSvcSetU32(&aReplyParams[2], (uint32_t)rcSkip); 1586 1588 HGCMSvcSetPv(&aReplyParams[3], NULL, 0); 1587 GstCtrlService::hostCallback(GUEST_MSG_REPLY, 4, aReplyParams);1589 hostCallback(GUEST_MSG_REPLY, 4, aReplyParams); 1588 1590 break; 1589 1591 } … … 1617 1619 * @retval VERR_DUPLICATE if the session ID has been prepared already. 1618 1620 * 1619 * @param idClient The client's ID.1621 * @param pClient The client state. 1620 1622 * @param hCall The call handle for completing it. 1621 1623 * @param cParms Number of parameters. 1622 1624 * @param paParms The parameters. 1623 1625 */ 1624 int GstCtrlService::clientSessionPrepare( uint32_t idClient, VBOXHGCMCALLHANDLE hCall, uint32_t cParms, VBOXHGCMSVCPARM paParms[])1626 int GstCtrlService::clientSessionPrepare(ClientState *pClient, VBOXHGCMCALLHANDLE hCall, uint32_t cParms, VBOXHGCMSVCPARM paParms[]) 1625 1627 { 1626 1628 /* … … 1639 1641 ASSERT_GUEST_RETURN(cbKey <= _16K, VERR_BUFFER_OVERFLOW); 1640 1642 1641 ClientStateMapIter ItClientState = mClientStateMap.find(idClient); 1642 ASSERT_GUEST_MSG_RETURN(ItClientState != mClientStateMap.end(), ("idClient=%RU32\n", idClient), VERR_INVALID_CLIENT_ID); 1643 ClientState &rClientState = ItClientState->second; 1644 ASSERT_GUEST_RETURN(rClientState.m_fIsMaster, VERR_ACCESS_DENIED); 1643 ASSERT_GUEST_RETURN(pClient->m_fIsMaster, VERR_ACCESS_DENIED); 1645 1644 ASSERT_GUEST_RETURN(!m_fLegacyMode, VERR_ACCESS_DENIED); 1646 Assert(m_idMasterClient == idClient);1645 Assert(m_idMasterClient == pClient->mID); 1647 1646 1648 1647 /* Now that we know it's the master, we can check for session ID duplicates. */ … … 1692 1691 * @retval VERR_ACCESS_DENIED if not master or in legacy mode. 1693 1692 * 1694 * @param idClient The client's ID.1693 * @param pClient The client state. 1695 1694 * @param cParms Number of parameters. 1696 1695 * @param paParms The parameters. 1697 1696 */ 1698 int GstCtrlService::clientSessionCancelPrepared( uint32_t idClient, uint32_t cParms, VBOXHGCMSVCPARM paParms[])1697 int GstCtrlService::clientSessionCancelPrepared(ClientState *pClient, uint32_t cParms, VBOXHGCMSVCPARM paParms[]) 1699 1698 { 1700 1699 /* … … 1705 1704 uint32_t const idSession = paParms[0].u.uint32; 1706 1705 1707 ClientStateMapIter ItClientState = mClientStateMap.find(idClient); 1708 ASSERT_GUEST_MSG_RETURN(ItClientState != mClientStateMap.end(), ("idClient=%RU32\n", idClient), VERR_INVALID_CLIENT_ID); 1709 ClientState &rClientState = ItClientState->second; 1710 ASSERT_GUEST_RETURN(rClientState.m_fIsMaster, VERR_ACCESS_DENIED); 1706 ASSERT_GUEST_RETURN(pClient->m_fIsMaster, VERR_ACCESS_DENIED); 1711 1707 ASSERT_GUEST_RETURN(!m_fLegacyMode, VERR_ACCESS_DENIED); 1712 Assert(m_idMasterClient == idClient);1708 Assert(m_idMasterClient == pClient->mID); 1713 1709 1714 1710 /* … … 1757 1753 * session. 1758 1754 * 1759 * @param idClient The client's ID.1755 * @param pClient The client state. 1760 1756 * @param hCall The call handle for completing it. 1761 1757 * @param cParms Number of parameters. 1762 1758 * @param paParms The parameters. 1763 1759 */ 1764 int GstCtrlService::clientSessionAccept( uint32_t idClient, VBOXHGCMCALLHANDLE hCall, uint32_t cParms, VBOXHGCMSVCPARM paParms[])1760 int GstCtrlService::clientSessionAccept(ClientState *pClient, VBOXHGCMCALLHANDLE hCall, uint32_t cParms, VBOXHGCMSVCPARM paParms[]) 1765 1761 { 1766 1762 /* … … 1779 1775 ASSERT_GUEST_RETURN(cbKey <= _16K, VERR_BUFFER_OVERFLOW); 1780 1776 1781 ClientStateMapIter ItClientState = mClientStateMap.find(idClient); 1782 ASSERT_GUEST_MSG_RETURN(ItClientState != mClientStateMap.end(), ("idClient=%RU32\n", idClient), VERR_INVALID_CLIENT_ID); 1783 ClientState &rClientState = ItClientState->second; 1784 ASSERT_GUEST_RETURN(!rClientState.m_fIsMaster, VERR_ACCESS_DENIED); 1777 ASSERT_GUEST_RETURN(!pClient->m_fIsMaster, VERR_ACCESS_DENIED); 1785 1778 ASSERT_GUEST_RETURN(!m_fLegacyMode, VERR_ACCESS_DENIED); 1786 Assert(m_idMasterClient != idClient);1787 ASSERT_GUEST_RETURN( rClientState.m_idSession == UINT32_MAX, VERR_RESOURCE_BUSY);1779 Assert(m_idMasterClient != pClient->mID); 1780 ASSERT_GUEST_RETURN(pClient->m_idSession == UINT32_MAX, VERR_RESOURCE_BUSY); 1788 1781 1789 1782 /* … … 1804 1797 if (RT_SUCCESS(rc)) 1805 1798 { 1806 rClientState.m_idSession = idSession;1799 pClient->m_idSession = idSession; 1807 1800 1808 1801 RTListNodeRemove(&pCur->ListEntry); 1809 1802 RTMemFree(pCur); 1810 1803 m_cPreparedSessions -= 1; 1811 Log(("[Client %RU32] accepted session id %u.\n", idClient, idSession));1804 Log(("[Client %RU32] accepted session id %u.\n", pClient->mID, idSession)); 1812 1805 } 1813 1806 else … … 1815 1808 return VINF_HGCM_ASYNC_EXECUTE; /* The caller must not complete it. */ 1816 1809 } 1817 LogFunc(("Key mismatch for %u!\n", idClient));1810 LogFunc(("Key mismatch for %u!\n", pClient->mID)); 1818 1811 return VERR_MISMATCH; 1819 1812 } 1820 1813 } 1821 1814 1822 LogFunc(("No client prepared for %u!\n", idClient));1815 LogFunc(("No client prepared for %u!\n", pClient->mID)); 1823 1816 return VERR_NOT_FOUND; 1824 1817 } … … 1828 1821 * Client asks another client (guest) session to close. 1829 1822 * 1830 * @return IPRTstatus code.1831 * @param idClient The client's ID.1823 * @returns VBox status code. 1824 * @param pClient The client state. 1832 1825 * @param cParms Number of parameters. 1833 1826 * @param paParms Array of parameters. 1834 1827 */ 1835 int GstCtrlService::clientSessionCloseOther( uint32_t idClient, uint32_t cParms, VBOXHGCMSVCPARM paParms[])1828 int GstCtrlService::clientSessionCloseOther(ClientState *pClient, uint32_t cParms, VBOXHGCMSVCPARM paParms[]) 1836 1829 { 1837 1830 /* … … 1845 1838 uint32_t const fFlags = paParms[1].u.uint32; 1846 1839 1847 ClientStateMapIter ItClientState = mClientStateMap.find(idClient); 1848 ASSERT_GUEST_MSG_RETURN(ItClientState != mClientStateMap.end(), ("idClient=%RU32\n", idClient), VERR_INVALID_CLIENT_ID); 1849 ClientState &rClientState = ItClientState->second; 1850 ASSERT_GUEST_RETURN(rClientState.m_fIsMaster, VERR_ACCESS_DENIED); 1840 ASSERT_GUEST_RETURN(pClient->m_fIsMaster, VERR_ACCESS_DENIED); 1851 1841 1852 1842 /* … … 1859 1849 int rc = hostProcessCommand(HOST_SESSION_CLOSE, RT_ELEMENTS(aParms), aParms); 1860 1850 1861 LogFlowFunc(("Closing guest context ID=%RU32 (from client ID=%RU32) returned with rc=%Rrc\n", idContext, idClient, rc));1851 LogFlowFunc(("Closing guest context ID=%RU32 (from client ID=%RU32) returned with rc=%Rrc\n", idContext, pClient->mID, rc)); 1862 1852 return rc; 1863 1853 } … … 1867 1857 * For compatiblity with old additions only - filtering / set session ID. 1868 1858 * 1869 * @return VBox status code.1870 * @param idClient The client's HGCM ID.1871 * @param cParmsNumber of parameters.1872 * @param paParmsArray of parameters.1873 */ 1874 int GstCtrlService::clientMsgOldFilterSet( uint32_t idClient, uint32_t cParms, VBOXHGCMSVCPARM paParms[])1859 * @return VBox status code. 1860 * @param pClient The client state. 1861 * @param cParms Number of parameters. 1862 * @param paParms Array of parameters. 1863 */ 1864 int GstCtrlService::clientMsgOldFilterSet(ClientState *pClient, uint32_t cParms, VBOXHGCMSVCPARM paParms[]) 1875 1865 { 1876 1866 /* … … 1886 1876 ASSERT_GUEST_RETURN(paParms[3].type == VBOX_HGCM_SVC_PARM_32BIT, VERR_WRONG_PARAMETER_TYPE); /* flags, unused */ 1887 1877 1888 ClientStateMapIter ItClientState = mClientStateMap.find(idClient);1889 ASSERT_GUEST_MSG_RETURN(ItClientState != mClientStateMap.end(), ("idClient=%RU32\n", idClient), VERR_INVALID_CLIENT_ID);1890 ClientState &rClientState = ItClientState->second;1891 1892 1878 /* 1893 1879 * We have a bunch of expectations here: … … 1899 1885 */ 1900 1886 ASSERT_GUEST_LOGREL_RETURN(m_fLegacyMode, VERR_WRONG_ORDER); 1901 ASSERT_GUEST_LOGREL_MSG_RETURN( rClientState.m_idSession == UINT32_MAX, ("m_idSession=%#x\n", rClientState.m_idSession),1887 ASSERT_GUEST_LOGREL_MSG_RETURN(pClient->m_idSession == UINT32_MAX, ("m_idSession=%#x\n", pClient->m_idSession), 1902 1888 VERR_WRONG_ORDER); 1903 ASSERT_GUEST_LOGREL_RETURN(! rClientState.m_fIsMaster, VERR_WRONG_ORDER);1889 ASSERT_GUEST_LOGREL_RETURN(!pClient->m_fIsMaster, VERR_WRONG_ORDER); 1904 1890 1905 1891 if (uValue == 0) … … 1918 1904 1919 1905 for (ClientStateMapIter It = mClientStateMap.begin(); It != mClientStateMap.end(); ++It) 1906 #ifdef USE_PVCLIENT 1907 ASSERT_GUEST_LOGREL_MSG_RETURN(It->second->m_idSession != idSession, 1908 ("idSession=%u uValue=%#x idClient=%u; conflicting with client %u\n", 1909 idSession, uValue, pClient->mID, It->second->mID), 1910 VERR_DUPLICATE); 1911 #else 1920 1912 ASSERT_GUEST_LOGREL_MSG_RETURN(It->second.m_idSession != idSession, 1921 1913 ("idSession=%u uValue=%#x idClient=%u; conflicting with client %u\n", 1922 idSession, uValue, idClient, It->second.mID),1914 idSession, uValue, pClient->mID, It->second.mID), 1923 1915 VERR_DUPLICATE); 1916 #endif 1924 1917 /* Commit it. */ 1925 rClientState.m_idSession = idSession;1918 pClient->m_idSession = idSession; 1926 1919 } 1927 1920 return VINF_SUCCESS; … … 1936 1929 * old additions code didn't give damn about VERR_INTERRUPT. 1937 1930 * 1938 * @return VBox status code.1939 * @param idClient The client's HGCM ID.1940 * @param cParmsNumber of parameters.1941 */ 1942 int GstCtrlService::clientMsgOldSkip( uint32_t idClient, uint32_t cParms)1931 * @return VBox status code. 1932 * @param pClient The client state. 1933 * @param cParms Number of parameters. 1934 */ 1935 int GstCtrlService::clientMsgOldSkip(ClientState *pClient, uint32_t cParms) 1943 1936 { 1944 1937 /* … … 1947 1940 ASSERT_GUEST_RETURN(cParms == 1, VERR_WRONG_PARAMETER_COUNT); 1948 1941 1949 ClientStateMapIter ItClientState = mClientStateMap.find(idClient);1950 ASSERT_GUEST_MSG_RETURN(ItClientState != mClientStateMap.end(), ("idClient=%RU32\n", idClient), VERR_INVALID_CLIENT_ID);1951 ClientState &rClientState = ItClientState->second;1952 1953 1942 /* 1954 1943 * Execute the request. 1955 1944 */ 1956 if (! rClientState.mHostCmdList.empty())1957 rClientState.OldDitchFirstHostCmd();1958 1959 LogFlowFunc(("[Client %RU32] Skipped current message - leagcy function\n", idClient));1945 if (!pClient->mHostCmdList.empty()) 1946 pClient->OldDitchFirstHostCmd(); 1947 1948 LogFlowFunc(("[Client %RU32] Skipped current message - leagcy function\n", pClient->mID)); 1960 1949 return VINF_SUCCESS; 1961 1950 } … … 1963 1952 1964 1953 /** 1965 * Notifies the host (using low-level HGCM callbacks) about an event 1966 * which was sent from the client. 1967 * 1968 * @return IPRT status code. 1954 * Forwards client call to the Main API. 1955 * 1956 * This is typically notifications and replys. 1957 * 1958 * @returns VBox status code. 1959 * @param pClient The client state. 1969 1960 * @param idFunction Function (event) that occured. 1970 1961 * @param cParms Number of parameters. 1971 1962 * @param paParms Array of parameters. 1972 1963 */ 1973 int GstCtrlService::hostCallback(uint32_t idFunction, uint32_t cParms, VBOXHGCMSVCPARM paParms[]) 1974 { 1975 LogFlowFunc(("idFunction=%u (%s), cParms=%ld, paParms=%p\n", idFunction, GstCtrlGuestFnName((eGuestFn)idFunction), cParms, paParms)); 1976 1977 int rc; 1978 if (mpfnHostCallback) 1979 { 1980 VBOXGUESTCTRLHOSTCALLBACK data(cParms, paParms); 1981 /** @todo Not sure if this try/catch is necessary, I pushed it down here from 1982 * GstCtrlService::call where it was not needed for anything else that I 1983 * could spot. I know this might be a tough, but I expect someone writing 1984 * this kind of code to know what can throw errors and handle them where it 1985 * is appropriate, rather than grand catch-all-at-the-top crap like this. 1986 * The reason why it is utter crap, is that you have no state cleanup code 1987 * where you might need it, which is why I despise exceptions in general */ 1988 try 1989 { 1990 rc = mpfnHostCallback(mpvHostData, idFunction, (void *)(&data), sizeof(data)); 1991 } 1992 catch (std::bad_alloc &) 1993 { 1994 rc = VERR_NO_MEMORY; 1995 } 1996 } 1997 else 1998 rc = VERR_NOT_SUPPORTED; 1999 2000 LogFlowFunc(("Returning rc=%Rrc\n", rc)); 2001 return rc; 2002 } 2003 2004 2005 /** 2006 * Processes a command received from the host side and re-routes it to 2007 * a connect client on the guest. 2008 * 2009 * @return IPRT status code. 2010 * @param idFunction Function code to process. 2011 * @param cParms Number of parameters. 2012 * @param paParms Array of parameters. 2013 */ 2014 int GstCtrlService::hostProcessCommand(uint32_t idFunction, uint32_t cParms, VBOXHGCMSVCPARM paParms[]) 2015 { 2016 /* 2017 * If no client is connected at all we don't buffer any host commands 2018 * and immediately return an error to the host. This avoids the host 2019 * waiting for a response from the guest side in case VBoxService on 2020 * the guest is not running/system is messed up somehow. 2021 */ 2022 if (mClientStateMap.empty()) 2023 { 2024 LogFlow(("GstCtrlService::hostProcessCommand: VERR_NOT_FOUND!\n")); 2025 return VERR_NOT_FOUND; 2026 } 2027 2028 HostCommand *pHostCmd = new (std::nothrow) HostCommand(); 2029 AssertReturn(pHostCmd, VERR_NO_MEMORY); 2030 2031 int rc = pHostCmd->Init(idFunction, cParms, paParms); 2032 if (RT_SUCCESS(rc)) 2033 { 2034 RTListAppend(&mHostCmdList, &pHostCmd->m_ListEntry); 2035 LogFlowFunc(("Handling host command m_idContextAndDst=%#RX64, idFunction=%RU32, cParms=%RU32, paParms=%p, cClients=%zu\n", 2036 pHostCmd->m_idContextAndDst, idFunction, cParms, paParms, mClientStateMap.size())); 2037 2038 /* 2039 * Find the message destination and post it to the client. If the 2040 * session ID doesn't match any particular client it goes to the master. 2041 */ 2042 AssertMsg(!mClientStateMap.empty(), ("Client state map is empty when it should not be!\n")); 2043 2044 /* Dispatch to the session. */ 2045 if (pHostCmd->m_idContextAndDst & VBOX_GUESTCTRL_DST_SESSION) 2046 { 2047 rc = VWRN_NOT_FOUND; 2048 uint32_t const idSession = VBOX_GUESTCTRL_CONTEXTID_GET_SESSION(pHostCmd->m_idContext); 2049 for (ClientStateMapIter It = mClientStateMap.begin(); It != mClientStateMap.end(); ++It) 2050 { 2051 ClientState &rClientState = It->second; 2052 if (rClientState.m_idSession == idSession) 2053 { 2054 rc = rClientState.EnqueueCommand(pHostCmd); 2055 if (RT_SUCCESS(rc)) 2056 { 2057 int rc2 = rClientState.Wakeup(); 2058 LogFlowFunc(("Woke up client ID=%RU32 -> rc=%Rrc\n", rClientState.mID, rc2)); 2059 RT_NOREF(rc2); 2060 } 2061 break; 2062 } 2063 } 2064 } 2065 2066 /* Does the message go to the root service? */ 2067 if ( (pHostCmd->m_idContextAndDst & VBOX_GUESTCTRL_DST_ROOT_SVC) 2068 && RT_SUCCESS(rc)) 2069 { 2070 ClientStateMapIter It = mClientStateMap.find(m_idMasterClient); 2071 if (It != mClientStateMap.end()) 2072 { 2073 ClientState &rClientState = It->second; 2074 int rc2 = rClientState.EnqueueCommand(pHostCmd); 2075 if (RT_SUCCESS(rc2)) 2076 { 2077 rc2 = rClientState.Wakeup(); 2078 LogFlowFunc(("Woke up client ID=%RU32 (master) -> rc=%Rrc\n", rClientState.mID, rc2)); 2079 } 2080 else 2081 rc = rc2; 2082 } 2083 else 2084 rc = VERR_NOT_FOUND; 2085 } 2086 } 2087 2088 /* Drop our command reference. */ 2089 pHostCmd->SaneRelease(); 2090 2091 if (RT_FAILURE(rc)) 2092 LogFunc(("Failed %Rrc (idFunction=%u, cParms=%u)\n", rc, idFunction, cParms)); 2093 return rc; 2094 } 2095 2096 2097 /** 2098 * @interface_method_impl{VBOXHGCMSVCFNTABLE,pfnHostCall, 2099 * Wraps to the hostProcessCommand() member function.} 2100 */ 2101 /*static*/ DECLCALLBACK(int) 2102 GstCtrlService::svcHostCall(void *pvService, uint32_t u32Function, uint32_t cParms, VBOXHGCMSVCPARM paParms[]) 2103 { 2104 AssertLogRelReturn(VALID_PTR(pvService), VERR_INVALID_PARAMETER); 2105 SELF *pThis = reinterpret_cast<SELF *>(pvService); 2106 AssertPtrReturn(pThis, VERR_INVALID_POINTER); 2107 2108 LogFlowFunc(("fn=%RU32, cParms=%RU32, paParms=0x%p\n", u32Function, cParms, paParms)); 2109 AssertReturn(u32Function != HOST_CANCEL_PENDING_WAITS, VERR_INVALID_FUNCTION); 2110 return pThis->hostProcessCommand(u32Function, cParms, paParms); 1964 int GstCtrlService::clientToMain(ClientState *pClient, uint32_t idFunction, uint32_t cParms, VBOXHGCMSVCPARM paParms[]) 1965 { 1966 /* 1967 * Do input validation. This class of messages all have a 32-bit context ID as 1968 * the first parameter, so make sure it is there and appropriate for the caller. 1969 */ 1970 ASSERT_GUEST_RETURN(cParms >= 1, VERR_WRONG_PARAMETER_COUNT); 1971 ASSERT_GUEST_RETURN(paParms[0].type == VBOX_HGCM_SVC_PARM_32BIT, VERR_WRONG_PARAMETER_COUNT); 1972 uint32_t const idContext = paParms[0].u.uint32; 1973 uint32_t const idSession = VBOX_GUESTCTRL_CONTEXTID_GET_SESSION(idContext); 1974 1975 ASSERT_GUEST_MSG_RETURN( pClient->m_idSession == idSession 1976 || pClient->m_fIsMaster 1977 || ( m_fLegacyMode /* (see bugref:9313#c16) */ 1978 && pClient->m_idSession == UINT32_MAX 1979 && ( idFunction == GUEST_EXEC_STATUS 1980 || idFunction == GUEST_SESSION_NOTIFY)), 1981 ("idSession=%u (CID=%#x) m_idSession=%u idClient=%u idFunction=%u (%s)\n", idSession, idContext, 1982 pClient->m_idSession, pClient->mID, idFunction, GstCtrlGuestFnName((eGuestFn)idFunction)), 1983 VERR_ACCESS_DENIED); 1984 1985 /* 1986 * It seems okay, so make the call. 1987 */ 1988 return hostCallback(idFunction, cParms, paParms); 2111 1989 } 2112 1990 … … 2126 2004 LogFlowFunc(("[Client %RU32] idFunction=%RU32 (%s), cParms=%RU32, paParms=0x%p\n", 2127 2005 idClient, idFunction, GstCtrlGuestFnName((eGuestFn)idFunction), cParms, paParms)); 2128 RT_NOREF(tsArrival, pvClient); 2129 2130 AssertLogRelReturnVoid(VALID_PTR(pvService)); 2131 SELF *pThis= reinterpret_cast<SELF *>(pvService); 2132 AssertPtrReturnVoid(pThis); 2133 2006 RT_NOREF(tsArrival); 2007 2008 /* 2009 * Convert opaque pointers to typed ones. 2010 */ 2011 SELF *pThis = reinterpret_cast<SELF *>(pvService); 2012 AssertReturnVoidStmt(pThis, pThis->mpHelpers->pfnCallComplete(hCall, VERR_INTERNAL_ERROR_5)); 2013 #ifdef USE_PVCLIENT 2014 ClientState *pClient = reinterpret_cast<ClientState *>(pvClient); 2015 AssertReturnVoidStmt(pClient, pThis->mpHelpers->pfnCallComplete(hCall, VERR_INVALID_CLIENT_ID)); 2016 #else 2017 ClientStateMapIter ItClientState = pThis->mClientStateMap.find(idClient); 2018 AssertReturnVoidStmt(ItClientState != pThis->mClientStateMap.end(), 2019 pThis->mpHelpers->pfnCallComplete(hCall, VERR_INVALID_CLIENT_ID)) 2020 ClientState *pClient = ItClientState->second; 2021 RT_NOREF(pvClient); 2022 #endif 2023 2024 /* 2025 * Do the dispatching. 2026 */ 2134 2027 int rc; 2135 2028 switch (idFunction) … … 2137 2030 case GUEST_MAKE_ME_MASTER: 2138 2031 LogFlowFunc(("[Client %RU32] GUEST_MAKE_ME_MASTER\n", idClient)); 2139 rc = pThis->clientMakeMeMaster( idClient, hCall, cParms);2032 rc = pThis->clientMakeMeMaster(pClient, hCall, cParms); 2140 2033 break; 2141 2034 case GUEST_MSG_PEEK_NOWAIT: 2142 2035 LogFlowFunc(("[Client %RU32] GUEST_MSG_PEEK_NOWAIT\n", idClient)); 2143 rc = pThis->clientMsgPeek( idClient, hCall, cParms, paParms, false /*fWait*/);2036 rc = pThis->clientMsgPeek(pClient, hCall, cParms, paParms, false /*fWait*/); 2144 2037 break; 2145 2038 case GUEST_MSG_PEEK_WAIT: 2146 2039 LogFlowFunc(("[Client %RU32] GUEST_MSG_PEEK_WAIT\n", idClient)); 2147 rc = pThis->clientMsgPeek( idClient, hCall, cParms, paParms, true /*fWait*/);2040 rc = pThis->clientMsgPeek(pClient, hCall, cParms, paParms, true /*fWait*/); 2148 2041 break; 2149 2042 case GUEST_MSG_GET: 2150 2043 LogFlowFunc(("[Client %RU32] GUEST_MSG_GET\n", idClient)); 2151 rc = pThis->clientMsgGet( idClient, hCall, cParms, paParms);2044 rc = pThis->clientMsgGet(pClient, hCall, cParms, paParms); 2152 2045 break; 2153 2046 case GUEST_MSG_CANCEL: 2154 2047 LogFlowFunc(("[Client %RU32] GUEST_MSG_CANCEL\n", idClient)); 2155 rc = pThis->clientMsgCancel( idClient, cParms);2048 rc = pThis->clientMsgCancel(pClient, cParms); 2156 2049 break; 2157 2050 case GUEST_MSG_SKIP: 2158 2051 LogFlowFunc(("[Client %RU32] GUEST_MSG_SKIP\n", idClient)); 2159 rc = pThis->clientMsgSkip( idClient, hCall, cParms, paParms);2052 rc = pThis->clientMsgSkip(pClient, hCall, cParms, paParms); 2160 2053 break; 2161 2054 case GUEST_SESSION_PREPARE: 2162 2055 LogFlowFunc(("[Client %RU32] GUEST_SESSION_PREPARE\n", idClient)); 2163 rc = pThis->clientSessionPrepare( idClient, hCall, cParms, paParms);2056 rc = pThis->clientSessionPrepare(pClient, hCall, cParms, paParms); 2164 2057 break; 2165 2058 case GUEST_SESSION_CANCEL_PREPARED: 2166 2059 LogFlowFunc(("[Client %RU32] GUEST_SESSION_CANCEL_PREPARED\n", idClient)); 2167 rc = pThis->clientSessionCancelPrepared( idClient, cParms, paParms);2060 rc = pThis->clientSessionCancelPrepared(pClient, cParms, paParms); 2168 2061 break; 2169 2062 case GUEST_SESSION_ACCEPT: 2170 2063 LogFlowFunc(("[Client %RU32] GUEST_SESSION_ACCEPT\n", idClient)); 2171 rc = pThis->clientSessionAccept( idClient, hCall, cParms, paParms);2064 rc = pThis->clientSessionAccept(pClient, hCall, cParms, paParms); 2172 2065 break; 2173 2066 case GUEST_SESSION_CLOSE: 2174 2067 LogFlowFunc(("[Client %RU32] GUEST_SESSION_CLOSE\n", idClient)); 2175 rc = pThis->clientSessionCloseOther( idClient, cParms, paParms);2068 rc = pThis->clientSessionCloseOther(pClient, cParms, paParms); 2176 2069 break; 2177 2070 … … 2179 2072 * Stuff the goes to various main objects: 2180 2073 */ 2181 case GUEST_DISCONNECTED:2182 2074 case GUEST_MSG_REPLY: 2183 2075 case GUEST_MSG_PROGRESS_UPDATE: … … 2189 2081 case GUEST_DIR_NOTIFY: 2190 2082 case GUEST_FILE_NOTIFY: 2191 rc = pThis->hostCallback(idFunction, cParms, paParms); 2083 LogFlowFunc(("[Client %RU32] %s\n", idClient, GstCtrlGuestFnName((eGuestFn)idFunction))); 2084 rc = pThis->clientToMain(pClient, idFunction, cParms, paParms); 2192 2085 Assert(rc != VINF_HGCM_ASYNC_EXECUTE); 2193 2086 break; … … 2199 2092 case GUEST_MSG_WAIT: 2200 2093 LogFlowFunc(("[Client %RU32] GUEST_MSG_WAIT\n", idClient)); 2201 pThis->clientMsgOldGet( idClient, hCall, cParms, paParms);2094 pThis->clientMsgOldGet(pClient, hCall, cParms, paParms); 2202 2095 rc = VINF_HGCM_ASYNC_EXECUTE; 2203 2096 break; … … 2205 2098 case GUEST_MSG_SKIP_OLD: 2206 2099 LogFlowFunc(("[Client %RU32] GUEST_MSG_SKIP_OLD\n", idClient)); 2207 rc = pThis->clientMsgOldSkip( idClient, cParms);2100 rc = pThis->clientMsgOldSkip(pClient, cParms); 2208 2101 break; 2209 2102 2210 2103 case GUEST_MSG_FILTER_SET: 2211 2104 LogFlowFunc(("[Client %RU32] GUEST_MSG_FILTER_SET\n", idClient)); 2212 rc = pThis->clientMsgOldFilterSet( idClient, cParms, paParms);2105 rc = pThis->clientMsgOldFilterSet(pClient, cParms, paParms); 2213 2106 break; 2214 2107 … … 2241 2134 2242 2135 /** 2243 * @interface_method_impl{VBOXHGCMSVCFNTABLE,pfnSaveState} 2136 * Notifies the host (using low-level HGCM callbacks) about an event 2137 * which was sent from the client. 2138 * 2139 * @returns VBox status code. 2140 * @param idFunction Function (event) that occured. 2141 * @param cParms Number of parameters. 2142 * @param paParms Array of parameters. 2143 */ 2144 int GstCtrlService::hostCallback(uint32_t idFunction, uint32_t cParms, VBOXHGCMSVCPARM paParms[]) 2145 { 2146 LogFlowFunc(("idFunction=%u (%s), cParms=%ld, paParms=%p\n", idFunction, GstCtrlGuestFnName((eGuestFn)idFunction), cParms, paParms)); 2147 2148 int rc; 2149 if (mpfnHostCallback) 2150 { 2151 VBOXGUESTCTRLHOSTCALLBACK data(cParms, paParms); 2152 /** @todo Not sure if this try/catch is necessary, I pushed it down here from 2153 * GstCtrlService::call where it was not needed for anything else that I 2154 * could spot. I know this might be a tough, but I expect someone writing 2155 * this kind of code to know what can throw errors and handle them where it 2156 * is appropriate, rather than grand catch-all-at-the-top crap like this. 2157 * The reason why it is utter crap, is that you have no state cleanup code 2158 * where you might need it, which is why I despise exceptions in general */ 2159 try 2160 { 2161 rc = mpfnHostCallback(mpvHostData, idFunction, &data, sizeof(data)); 2162 } 2163 catch (std::bad_alloc &) 2164 { 2165 rc = VERR_NO_MEMORY; 2166 } 2167 } 2168 else 2169 rc = VERR_NOT_SUPPORTED; 2170 2171 LogFlowFunc(("Returning rc=%Rrc\n", rc)); 2172 return rc; 2173 } 2174 2175 2176 /** 2177 * Processes a command received from the host side and re-routes it to 2178 * a connect client on the guest. 2179 * 2180 * @returns VBox status code. 2181 * @param idFunction Function code to process. 2182 * @param cParms Number of parameters. 2183 * @param paParms Array of parameters. 2184 */ 2185 int GstCtrlService::hostProcessCommand(uint32_t idFunction, uint32_t cParms, VBOXHGCMSVCPARM paParms[]) 2186 { 2187 /* 2188 * If no client is connected at all we don't buffer any host commands 2189 * and immediately return an error to the host. This avoids the host 2190 * waiting for a response from the guest side in case VBoxService on 2191 * the guest is not running/system is messed up somehow. 2192 */ 2193 if (mClientStateMap.empty()) 2194 { 2195 LogFlow(("GstCtrlService::hostProcessCommand: VERR_NOT_FOUND!\n")); 2196 return VERR_NOT_FOUND; 2197 } 2198 2199 HostCommand *pHostCmd = new (std::nothrow) HostCommand(); 2200 AssertReturn(pHostCmd, VERR_NO_MEMORY); 2201 2202 int rc = pHostCmd->Init(idFunction, cParms, paParms); 2203 if (RT_SUCCESS(rc)) 2204 { 2205 RTListAppend(&mHostCmdList, &pHostCmd->m_ListEntry); 2206 LogFlowFunc(("Handling host command m_idContextAndDst=%#RX64, idFunction=%RU32, cParms=%RU32, paParms=%p, cClients=%zu\n", 2207 pHostCmd->m_idContextAndDst, idFunction, cParms, paParms, mClientStateMap.size())); 2208 2209 /* 2210 * Find the message destination and post it to the client. If the 2211 * session ID doesn't match any particular client it goes to the master. 2212 */ 2213 AssertMsg(!mClientStateMap.empty(), ("Client state map is empty when it should not be!\n")); 2214 2215 /* Dispatch to the session. */ 2216 if (pHostCmd->m_idContextAndDst & VBOX_GUESTCTRL_DST_SESSION) 2217 { 2218 rc = VWRN_NOT_FOUND; 2219 uint32_t const idSession = VBOX_GUESTCTRL_CONTEXTID_GET_SESSION(pHostCmd->m_idContext); 2220 for (ClientStateMapIter It = mClientStateMap.begin(); It != mClientStateMap.end(); ++It) 2221 { 2222 #ifdef USE_PVCLIENT 2223 ClientState *pClient = It->second; 2224 #else 2225 ClientState *pClient = &It->second; 2226 #endif 2227 if (pClient->m_idSession == idSession) 2228 { 2229 rc = pClient->EnqueueCommand(pHostCmd); 2230 if (RT_SUCCESS(rc)) 2231 { 2232 int rc2 = pClient->Wakeup(); 2233 LogFlowFunc(("Woke up client ID=%RU32 -> rc=%Rrc\n", pClient->mID, rc2)); 2234 RT_NOREF(rc2); 2235 } 2236 break; 2237 } 2238 } 2239 } 2240 2241 /* Does the message go to the root service? */ 2242 if ( (pHostCmd->m_idContextAndDst & VBOX_GUESTCTRL_DST_ROOT_SVC) 2243 && RT_SUCCESS(rc)) 2244 { 2245 ClientStateMapIter It = mClientStateMap.find(m_idMasterClient); 2246 if (It != mClientStateMap.end()) 2247 { 2248 #ifdef USE_PVCLIENT 2249 ClientState *pClient = It->second; 2250 #else 2251 ClientState *pClient = &It->second; 2252 #endif 2253 int rc2 = pClient->EnqueueCommand(pHostCmd); 2254 if (RT_SUCCESS(rc2)) 2255 { 2256 rc2 = pClient->Wakeup(); 2257 LogFlowFunc(("Woke up client ID=%RU32 (master) -> rc=%Rrc\n", pClient->mID, rc2)); 2258 } 2259 else 2260 rc = rc2; 2261 } 2262 else 2263 rc = VERR_NOT_FOUND; 2264 } 2265 } 2266 2267 /* Drop our command reference. */ 2268 pHostCmd->SaneRelease(); 2269 2270 if (RT_FAILURE(rc)) 2271 LogFunc(("Failed %Rrc (idFunction=%u, cParms=%u)\n", rc, idFunction, cParms)); 2272 return rc; 2273 } 2274 2275 2276 /** 2277 * @interface_method_impl{VBOXHGCMSVCFNTABLE,pfnHostCall, 2278 * Wraps to the hostProcessCommand() member function.} 2244 2279 */ 2245 2280 /*static*/ DECLCALLBACK(int) 2246 GstCtrlService::svcSaveState(void *pvService, uint32_t idClient, void *pvClient, PSSMHANDLE pSSM) 2247 { 2248 RT_NOREF(pvClient); 2281 GstCtrlService::svcHostCall(void *pvService, uint32_t u32Function, uint32_t cParms, VBOXHGCMSVCPARM paParms[]) 2282 { 2249 2283 AssertLogRelReturn(VALID_PTR(pvService), VERR_INVALID_PARAMETER); 2250 2284 SELF *pThis = reinterpret_cast<SELF *>(pvService); 2251 2285 AssertPtrReturn(pThis, VERR_INVALID_POINTER); 2252 2286 2287 LogFlowFunc(("fn=%RU32, cParms=%RU32, paParms=0x%p\n", u32Function, cParms, paParms)); 2288 AssertReturn(u32Function != HOST_CANCEL_PENDING_WAITS, VERR_INVALID_FUNCTION); 2289 return pThis->hostProcessCommand(u32Function, cParms, paParms); 2290 } 2291 2292 2293 2294 2295 /** 2296 * @interface_method_impl{VBOXHGCMSVCFNTABLE,pfnSaveState} 2297 */ 2298 /*static*/ DECLCALLBACK(int) 2299 GstCtrlService::svcSaveState(void *pvService, uint32_t idClient, void *pvClient, PSSMHANDLE pSSM) 2300 { 2301 RT_NOREF(pvClient); 2302 SELF *pThis = reinterpret_cast<SELF *>(pvService); 2303 AssertPtrReturn(pThis, VERR_INVALID_POINTER); 2304 2253 2305 SSMR3PutU32(pSSM, 1); 2254 SSMR3PutBool(pSSM, idClient == pThis->m_idMasterClient);2255 return SSMR3PutBool(pSSM, pThis->m_fLegacyMode);2306 SSMR3PutBool(pSSM, pThis->m_fLegacyMode); 2307 return SSMR3PutBool(pSSM, idClient == pThis->m_idMasterClient); 2256 2308 } 2257 2309 … … 2264 2316 { 2265 2317 RT_NOREF(pvClient); 2266 AssertLogRelReturn(VALID_PTR(pvService), VERR_INVALID_PARAMETER);2267 2318 SELF *pThis = reinterpret_cast<SELF *>(pvService); 2268 2319 AssertPtrReturn(pThis, VERR_INVALID_POINTER); … … 2288 2339 ClientStateMapIter It = pThis->mClientStateMap.find(idClient); 2289 2340 if (It != pThis->mClientStateMap.end()) 2341 #ifdef USE_PVCLIENT 2342 It->second->m_fIsMaster = fIsMaster; 2343 #else 2290 2344 It->second.m_fIsMaster = fIsMaster; 2345 #endif 2291 2346 else 2292 2347 AssertFailed(); … … 2316 2371 /*static*/ DECLCALLBACK(int) GstCtrlService::svcRegisterExtension(void *pvService, PFNHGCMSVCEXT pfnExtension, void *pvExtension) 2317 2372 { 2318 AssertLogRelReturn(VALID_PTR(pvService), VERR_INVALID_PARAMETER);2319 2373 SELF *pThis = reinterpret_cast<SELF *>(pvService); 2320 2374 AssertPtrReturn(pThis, VERR_INVALID_POINTER); 2375 AssertPtrNullReturn(pfnExtension, VERR_INVALID_POINTER); 2321 2376 2322 2377 pThis->mpfnHostCallback = pfnExtension; 2323 pThis->mpvHostData = pvExtension;2378 pThis->mpvHostData = pvExtension; 2324 2379 return VINF_SUCCESS; 2325 2380 } … … 2371 2426 * because we're a class which can have members for that :-). 2372 2427 */ 2373 pTable->cbClient = 0; /** @todo this is where ClientState should live, isn't it? */2428 pTable->cbClient = sizeof(ClientState); 2374 2429 2375 2430 /* Register functions. */
Note:
See TracChangeset
for help on using the changeset viewer.