Changeset 30607 in vbox
- Timestamp:
- Jul 5, 2010 12:29:12 PM (15 years ago)
- svn:sync-xref-src-repo-rev:
- 63333
- Location:
- trunk/src/VBox/Main/webservice
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Main/webservice/vboxweb.cpp
r30584 r30607 107 107 bool g_fDaemonize = false; // run in background. 108 108 #endif 109 110 const WSDLT_ID g_EmptyWSDLID; // for NULL MORs 109 111 110 112 /**************************************************************************** … … 1168 1170 } 1169 1171 1170 _pISession = new ManagedObjectRef(*this, g_pcszISession, session); 1172 ComPtr<IUnknown> p2 = session; 1173 _pISession = new ManagedObjectRef(*this, 1174 p2, // IUnknown *pobjUnknown 1175 session, // void *pobjInterface 1176 com::Guid(COM_IIDOF(ISession)), 1177 g_pcszISession); 1171 1178 1172 1179 if (g_fVerbose) 1173 1180 { 1174 1181 ISession *p = session; 1175 std::string strMOR = _pISession->toWSDL(); 1176 WEBDEBUG((" * %s: created session object with comptr 0x%lX, MOR = %s\n", __FUNCTION__, p, strMOR.c_str())); 1182 WEBDEBUG((" * %s: created session object with comptr 0x%lX, MOR = %s\n", __FUNCTION__, p, _pISession->getWSDLID().c_str())); 1177 1183 } 1178 1184 } while (0); … … 1197 1203 * @return The existing ManagedObjectRef that represents the COM object, or NULL if there's none yet. 1198 1204 */ 1199 ManagedObjectRef* WebServiceSession::findRefFromPtr(const ComPtr<IUnknown> &pcu)1205 ManagedObjectRef* WebServiceSession::findRefFromPtr(const IUnknown *pObject) 1200 1206 { 1201 1207 Assert(g_pSessionsLockHandle->isWriteLockOnCurrentThread()); 1202 1208 1203 IUnknown *p = pcu; 1204 uintptr_t ulp = (uintptr_t)p; 1205 ManagedObjectRef *pRef; 1209 uintptr_t ulp = (uintptr_t)pObject; 1206 1210 // WEBDEBUG((" %s: looking up 0x%lX\n", __FUNCTION__, ulp)); 1207 1211 ManagedObjectsMapByPtr::iterator it = _pp->_mapManagedObjectsByPtr.find(ulp); 1208 1212 if (it != _pp->_mapManagedObjectsByPtr.end()) 1209 1213 { 1210 pRef = it->second; 1211 WSDLT_ID id = pRef->toWSDL(); 1212 WEBDEBUG((" %s: found existing ref %s (%s) for COM obj 0x%lX\n", __FUNCTION__, id.c_str(), pRef->getInterfaceName(), ulp)); 1213 } 1214 else 1215 pRef = NULL; 1216 return pRef; 1214 ManagedObjectRef *pRef = it->second; 1215 WEBDEBUG((" %s: found existing ref %s (%s) for COM obj 0x%lX\n", __FUNCTION__, pRef->getWSDLID().c_str(), pRef->getInterfaceName(), ulp)); 1216 return pRef; 1217 } 1218 1219 return NULL; 1217 1220 } 1218 1221 … … 1247 1250 * 1248 1251 */ 1249 WSDLT_ID WebServiceSession::getSessionObject() const1250 { 1251 return _pISession-> toWSDL();1252 const WSDLT_ID& WebServiceSession::getSessionWSDLID() const 1253 { 1254 return _pISession->getWSDLID(); 1252 1255 } 1253 1256 … … 1266 1269 } 1267 1270 1268 /**1269 *1270 */1271 void WebServiceSession::DumpRefs()1272 {1273 WEBDEBUG((" dumping object refs:\n"));1274 ManagedObjectsIteratorById1275 iter = _pp->_mapManagedObjectsById.begin(),1276 end = _pp->_mapManagedObjectsById.end();1277 for (;1278 iter != end;1279 ++iter)1280 {1281 ManagedObjectRef *pRef = iter->second;1282 uint64_t id = pRef->getID();1283 void *p = pRef->getComPtr();1284 WEBDEBUG((" objid %llX: comptr 0x%lX\n", id, p));1285 }1286 }1287 1271 1288 1272 /**************************************************************************** … … 1309 1293 * instance already exists for a given COM pointer. 1310 1294 * 1295 * This constructor calls AddRef() on the given COM object, and 1296 * the destructor will call Release(). We require two input pointers 1297 * for that COM object, one generic IUnknown* pointer which is used 1298 * as the map key, and a specific interface pointer (e.g. IMachine*) 1299 * which must support the interface given in guidInterface. All 1300 * three values are returned by getPtr(), which gives future callers 1301 * a chance to reuse the specific interface pointer without having 1302 * to call QueryInterface, which can be expensive. 1303 * 1311 1304 * This does _not_ check whether another instance already 1312 1305 * exists in the hash. This gets called only from the 1313 * create RefFromObject() template function in vboxweb.h, which1306 * createOrFindRefFromComPtr() template function in vboxweb.h, which 1314 1307 * does perform that check. 1315 1308 * 1316 1309 * Preconditions: Caller must have locked g_pSessionsLockHandle. 1317 1310 * 1318 * @param pObj 1311 * @param session Session to which the MOR will be added. 1312 * @param pobjUnknown Pointer to IUnknown* interface for the COM object; this will be used in the hashes. 1313 * @param pobjInterface Pointer to a specific interface for the COM object, described by guidInterface. 1314 * @param guidInterface Interface which pobjInterface points to. 1315 * @param pcszInterface String representation of that interface (e.g. "IMachine") for readability and logging. 1319 1316 */ 1320 1317 ManagedObjectRef::ManagedObjectRef(WebServiceSession &session, 1321 const char *pcszInterface, 1322 const ComPtr<IUnknown> &pc) 1318 IUnknown *pobjUnknown, 1319 void *pobjInterface, 1320 const com::Guid &guidInterface, 1321 const char *pcszInterface) 1323 1322 : _session(session), 1324 _pObj(pc), 1323 _pobjUnknown(pobjUnknown), 1324 _pobjInterface(pobjInterface), 1325 _guidInterface(guidInterface), 1325 1326 _pcszInterface(pcszInterface) 1326 1327 { 1327 ComPtr<IUnknown> pcUnknown(pc); 1328 _ulp = (uintptr_t)(IUnknown*)pcUnknown; 1328 Assert(pobjUnknown); 1329 Assert(pobjInterface); 1330 1331 // keep both stubs alive while this MOR exists (matching Release() calls are in destructor) 1332 uint32_t cRefs1 = pobjUnknown->AddRef(); 1333 uint32_t cRefs2 = ((IUnknown*)pobjInterface)->AddRef(); 1334 _ulp = (uintptr_t)pobjUnknown; 1329 1335 1330 1336 Assert(g_pSessionsLockHandle->isWriteLockOnCurrentThread()); … … 1342 1348 session.touch(); 1343 1349 1344 WEBDEBUG((" * %s: MOR created for ulp 0x%lX (%s), new ID is %llX; now %lld objects total\n", __FUNCTION__, _ulp, pcszInterface, _id, cTotal)); 1350 WEBDEBUG((" * %s: MOR created for %s*=0x%lX (IUnknown*=0x%lX; COM refcount now %RI32/%RI32), new ID is %llX; now %lld objects total\n", 1351 __FUNCTION__, 1352 pcszInterface, 1353 pobjInterface, 1354 pobjUnknown, 1355 cRefs1, 1356 cRefs2, 1357 _id, 1358 cTotal)); 1345 1359 } 1346 1360 1347 1361 /** 1348 1362 * Destructor; removes the instance from the global hash of 1349 * managed objects. 1363 * managed objects. Calls Release() on the contained COM object. 1350 1364 * 1351 1365 * Preconditions: Caller must have locked g_pSessionsLockHandle. … … 1356 1370 ULONG64 cTotal = --g_cManagedObjects; 1357 1371 1358 WEBDEBUG((" * %s: deleting MOR for ID %llX (%s); now %lld objects total\n", __FUNCTION__, _id, _pcszInterface, cTotal)); 1372 Assert(_pobjUnknown); 1373 Assert(_pobjInterface); 1374 1375 // we called AddRef() on both interfaces, so call Release() on 1376 // both as well, but in reverse order 1377 uint32_t cRefs2 = ((IUnknown*)_pobjInterface)->Release(); 1378 uint32_t cRefs1 = _pobjUnknown->Release(); 1379 WEBDEBUG((" * %s: deleting MOR for ID %llX (%s; COM refcount now %RI32/%RI32); now %lld objects total\n", __FUNCTION__, _id, _pcszInterface, cRefs1, cRefs2, cTotal)); 1359 1380 1360 1381 // if we're being destroyed from the session's destructor, … … 1368 1389 WEBDEBUG((" WARNING: could not find %llX in _mapManagedObjectsByPtr\n", _ulp)); 1369 1390 } 1370 }1371 1372 /**1373 * Converts the ID of this managed object reference to string1374 * form, for returning with SOAP data or similar.1375 *1376 * @return The ID in string form.1377 */1378 WSDLT_ID ManagedObjectRef::toWSDL() const1379 {1380 return _strID;1381 1391 } 1382 1392 … … 1424 1434 } 1425 1435 1426 WEBDEBUG((" %s(): sessid %llX, objid %llX\n", __FUNCTION__, sessid, objid));1427 1436 SessionsMapIterator it = g_mapSessions.find(sessid); 1428 1437 if (it == g_mapSessions.end()) … … 1597 1606 // that it will be implicitly be included in all future requests of this 1598 1607 // webservice client 1599 ManagedObjectRef *pRef = new ManagedObjectRef(*pSession, g_pcszIVirtualBox, g_pVirtualBox); 1600 resp->returnval = pRef->toWSDL(); 1608 ComPtr<IUnknown> p2 = g_pVirtualBox; 1609 ManagedObjectRef *pRef = new ManagedObjectRef(*pSession, 1610 p2, // IUnknown *pobjUnknown 1611 g_pVirtualBox, // void *pobjInterface 1612 COM_IIDOF(IVirtualBox), 1613 g_pcszIVirtualBox); 1614 resp->returnval = pRef->getWSDLID(); 1601 1615 WEBDEBUG(("VirtualBox object ref is %s\n", resp->returnval.c_str())); 1602 1616 } … … 1627 1641 WebServiceSession* pSession; 1628 1642 if ((pSession = WebServiceSession::findSessionFromRef(req->refIVirtualBox))) 1629 resp->returnval = pSession->getSession Object();1643 resp->returnval = pSession->getSessionWSDLID(); 1630 1644 1631 1645 } while (0); … … 1672 1686 return SOAP_OK; 1673 1687 } 1688 -
trunk/src/VBox/Main/webservice/vboxweb.h
r30584 r30607 41 41 /**************************************************************************** 42 42 * 43 * global variables44 *45 ****************************************************************************/46 47 extern ComPtr<IVirtualBox> g_pVirtualBox;48 extern bool g_fVerbose;49 50 extern PRTSTREAM g_pstrLog;51 52 extern util::WriteLockHandle *g_pAuthLibLockHandle;53 extern util::WriteLockHandle *g_pSessionsLockHandle;54 55 /****************************************************************************56 *57 43 * typedefs 58 44 * … … 62 48 typedef std::string WSDLT_ID; // combined managed object ref (session ID plus object ID) 63 49 typedef std::string vbox__uuid; 50 51 /**************************************************************************** 52 * 53 * global variables 54 * 55 ****************************************************************************/ 56 57 extern ComPtr<IVirtualBox> g_pVirtualBox; 58 extern bool g_fVerbose; 59 60 extern PRTSTREAM g_pstrLog; 61 62 extern util::WriteLockHandle *g_pAuthLibLockHandle; 63 extern util::WriteLockHandle *g_pSessionsLockHandle; 64 65 extern const WSDLT_ID g_EmptyWSDLID; 64 66 65 67 /**************************************************************************** … … 121 123 const char *pcszPassword); 122 124 123 ManagedObjectRef* findRefFromPtr(const ComPtr<IUnknown> &pcu);125 ManagedObjectRef* findRefFromPtr(const IUnknown *pObject); 124 126 125 127 uint64_t getID() const … … 128 130 } 129 131 130 WSDLT_ID getSessionObject() const;132 const WSDLT_ID& getSessionWSDLID() const; 131 133 132 134 void touch(); … … 157 159 WebServiceSession &_session; 158 160 159 // value: 160 ComPtr<IUnknown> _pObj; 161 const char *_pcszInterface; 161 162 IUnknown *_pobjUnknown; // pointer to IUnknown interface for this MOR 163 164 void *_pobjInterface; // pointer to COM interface represented by _guidInterface, for which this MOR 165 // was created; this may be an IUnknown or something more specific 166 com::Guid _guidInterface; // the interface which _pvObj represents 167 168 const char *_pcszInterface; // string representation of that interface (e.g. "IMachine") 162 169 163 170 // keys: … … 170 177 public: 171 178 ManagedObjectRef(WebServiceSession &session, 172 const char *pcszInterface, 173 const ComPtr<IUnknown> &obj); 179 IUnknown *pobjUnknown, 180 void *pobjInterface, 181 const com::Guid &guidInterface, 182 const char *pcszInterface); 174 183 ~ManagedObjectRef(); 175 184 … … 179 188 } 180 189 181 ComPtr<IUnknown> getComPtr() 182 { 183 return _pObj; 184 } 185 186 WSDLT_ID toWSDL() const; 190 /** 191 * Returns the contained COM pointer and the UUID of the COM interface 192 * which it supports. 193 * @param 194 * @return 195 */ 196 const com::Guid& getPtr(void **ppobjInterface, 197 IUnknown **ppobjUnknown) 198 { 199 *ppobjInterface = _pobjInterface; 200 *ppobjUnknown = _pobjUnknown; 201 return _guidInterface; 202 } 203 204 /** 205 * Returns the ID of this managed object reference to string 206 * form, for returning with SOAP data or similar. 207 * 208 * @return The ID in string form. 209 */ 210 const WSDLT_ID& getWSDLID() const 211 { 212 return _strID; 213 } 214 187 215 const char* getInterfaceName() const 188 216 { … … 202 230 /** 203 231 * Template function that resolves a managed object reference to a COM pointer 204 * of the template class T. Gets called from tons of generated code in 205 * methodmaps.cpp. 232 * of the template class T. 233 * 234 * This gets called only from tons of generated code in methodmaps.cpp to 235 * resolve objects in *input* parameters to COM methods (i.e. translate 236 * MOR strings to COM objects which should exist already). 206 237 * 207 238 * This is a template function so that we can support ComPtr's for arbitrary 208 239 * interfaces and automatically verify that the managed object reference on 209 * the internal stack actually is of the expected interface. 240 * the internal stack actually is of the expected interface. We also now avoid 241 * calling QueryInterface for the case that the interface desired by the caller 242 * is the same as the interface for which the MOR was originally created. In 243 * that case, the lookup is very fast. 210 244 * 211 245 * @param soap … … 231 265 ManagedObjectRef *pRef; 232 266 if ((rc = ManagedObjectRef::findRefFromId(id, &pRef, fNullAllowed))) 267 // error: 233 268 RaiseSoapInvalidObjectFault(soap, id); 234 269 else … … 236 271 if (fNullAllowed && pRef == NULL) 237 272 { 273 WEBDEBUG((" %s(): returning NULL object as permitted\n", __FUNCTION__)); 238 274 pComPtr.setNull(); 239 275 return 0; 240 276 } 241 277 242 // pRef->getComPtr returns a ComPtr<IUnknown>; by casting it to 243 // ComPtr<T>, we implicitly do a COM queryInterface() call 244 if (pComPtr = pRef->getComPtr()) 278 const com::Guid &guidCaller = COM_IIDOF(T); 279 280 // pRef->getPtr returns both a void* for its specific interface pointer as well as a generic IUnknown* 281 void *pobjInterface; 282 IUnknown *pobjUnknown; 283 const com::Guid &guidInterface = pRef->getPtr(&pobjInterface, &pobjUnknown); 284 285 if (guidInterface == guidCaller) 286 { 287 // same interface: then no QueryInterface needed 288 WEBDEBUG((" %s(): returning original %s*=0x%lX (IUnknown*=0x%lX)\n", __FUNCTION__, pRef->getInterfaceName(), pobjInterface, pobjUnknown)); 289 pComPtr = (T*)pobjInterface; // this calls AddRef() once 245 290 return 0; 291 } 292 293 // QueryInterface tests whether p actually supports the templated T interface desired by caller 294 T *pT; 295 pobjUnknown->QueryInterface(guidCaller, (void**)&pT); // this adds a reference count 296 if (pT) 297 { 298 // assign to caller's ComPtr<T>; use asOutParam() to avoid adding another reference, QueryInterface() already added one 299 WEBDEBUG((" %s(): returning pointer 0x%lX for queried interface %RTuuid (IUnknown*=0x%lX)\n", __FUNCTION__, pT, guidCaller.raw(), pobjUnknown)); 300 *(pComPtr.asOutParam()) = pT; 301 return 0; 302 } 246 303 247 304 WEBDEBUG((" Interface not supported for object reference %s, which is of class %s\n", id.c_str(), pRef->getInterfaceName())); … … 254 311 255 312 /** 256 * Template function that creates a new managed object for the given COM 257 * pointer of the template class T. If a reference already exists for the 258 * given pointer, then that reference's ID is returned instead. 313 * Creates a new managed object for the given COM pointer. If a reference already exists 314 * for the given pointer, then that reference's ID is returned instead. 315 * 316 * This gets called from tons of generated code in methodmaps.cpp to 317 * resolve objects *returned* from COM methods (i.e. create MOR strings from COM objects 318 * which might have been newly created). 259 319 * 260 320 * @param idParent managed object reference of calling object; used to extract session ID … … 263 323 */ 264 324 template <class T> 265 WSDLT_IDcreateOrFindRefFromComPtr(const WSDLT_ID &idParent,266 const char *pcszInterface,267 constComPtr<T> &pc)325 const WSDLT_ID& createOrFindRefFromComPtr(const WSDLT_ID &idParent, 326 const char *pcszInterface, 327 ComPtr<T> &pc) 268 328 { 269 329 // NULL comptr should return NULL MOR 270 330 if (pc.isNull()) 271 331 { 272 WEBDEBUG((" createOrFindRefFromComPtr(): returning empty MOR for NULL %s pointer\n", pcszInterface));273 return "";332 WEBDEBUG((" createOrFindRefFromComPtr(): returning empty MOR for NULL COM pointer\n")); 333 return g_EmptyWSDLID; 274 334 } 275 335 … … 278 338 if ((pSession = WebServiceSession::findSessionFromRef(idParent))) 279 339 { 280 // WEBDEBUG(("\n-- found session for %s\n", idParent.c_str()));281 340 ManagedObjectRef *pRef; 282 if ( ((pRef = pSession->findRefFromPtr(pc))) 283 || ((pRef = new ManagedObjectRef(*pSession, pcszInterface, pc))) 341 342 // we need an IUnknown pointer for the MOR 343 ComPtr<IUnknown> pobjUnknown = pc; 344 345 if ( ((pRef = pSession->findRefFromPtr(pobjUnknown))) 346 || ((pRef = new ManagedObjectRef(*pSession, 347 pobjUnknown, // IUnknown *pobjUnknown 348 pc, // void *pobjInterface 349 COM_IIDOF(T), 350 pcszInterface))) 284 351 ) 285 return pRef-> toWSDL();352 return pRef->getWSDLID(); 286 353 } 287 354 288 355 // session has expired, return an empty MOR instead of allocating a 289 356 // new reference which couldn't be used anyway. 290 return "";357 return g_EmptyWSDLID; 291 358 } 292
Note:
See TracChangeset
for help on using the changeset viewer.