Changeset 1711
- Timestamp:
- 03/27/07 10:35:21 (2 years ago)
- Files:
-
- trunk/include/VBox/err.h (modified) (1 diff)
- trunk/include/VBox/hgcmsvc.h (modified) (2 diffs)
- trunk/src/VBox/Main/Makefile (modified) (1 diff)
- trunk/src/VBox/Main/VMMDevInterface.cpp (modified) (12 diffs)
- trunk/src/VBox/Main/hgcm/HGCM.cpp (modified) (35 diffs)
- trunk/src/VBox/Main/hgcm/HGCMThread.cpp (modified) (6 diffs)
- trunk/src/VBox/Main/include/VMMDev.h (modified) (3 diffs)
- trunk/src/VBox/Main/include/hgcm/HGCM.h (modified) (1 diff)
- trunk/src/VBox/Main/include/hgcm/HGCMThread.h (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/include/VBox/err.h
r1650 r1711 914 914 /** The HGCM is saving state. */ 915 915 #define VINF_HGCM_SAVE_STATE (2906) 916 /** Requested service already exists. */ 917 #define VERR_HGCM_SERVICE_EXISTS (-2907) 916 918 917 919 /** @} */ trunk/include/VBox/hgcmsvc.h
r905 r1711 45 45 * 1.1->2.1 Because the pfnConnect now also has the pvClient parameter. 46 46 * 2.1->2.2 Because pfnSaveState and pfnLoadState were added 47 * 2.2->3.1 Because pfnHostCall is now synchronous, returns rc, and parameters were changed 47 48 */ 48 49 #define VBOX_HGCM_SVC_VERSION_MINOR (0x0001) 49 #define VBOX_HGCM_SVC_VERSION_MAJOR (0x000 2)50 #define VBOX_HGCM_SVC_VERSION_MAJOR (0x0003) 50 51 #define VBOX_HGCM_SVC_VERSION ((VBOX_HGCM_SVC_VERSION_MAJOR << 16) + VBOX_HGCM_SVC_VERSION_MINOR) 51 52 … … 139 140 * Return code is passed to pfnCallComplete callback. 140 141 */ 141 DECLCALLBACKMEMBER( void, pfnHostCall) (VBOXHGCMCALLHANDLE callHandle, uint32_t u32ClientID, void *pvClient,uint32_t function, uint32_t cParms, VBOXHGCMSVCPARM paParms[]);142 DECLCALLBACKMEMBER(int, pfnHostCall) (uint32_t function, uint32_t cParms, VBOXHGCMSVCPARM paParms[]); 142 143 143 144 /** Inform the service about a VM save operation. */ trunk/src/VBox/Main/Makefile
r1681 r1711 21 21 DEPTH = ../../.. 22 22 include $(PATH_KBUILD)/header.kmk 23 24 DEFS += HGCMSS25 23 26 24 ifdef VRDP_MC trunk/src/VBox/Main/VMMDevInterface.cpp
r1685 r1711 87 87 AssertRC(rc); 88 88 #ifdef VBOX_HGCM 89 rc = hgcmInit ();89 rc = HGCMHostInit (); 90 90 AssertRC(rc); 91 91 #endif /* VBOX_HGCM */ … … 95 95 VMMDev::~VMMDev() 96 96 { 97 #ifdef VBOX_HGCM 98 HGCMHostShutdown (); 99 #endif /* VBOX_HGCM */ 97 100 RTSemEventDestroy (mCredentialsEvent); 98 101 if (mpDrv) … … 301 304 302 305 PDRVMAINVMMDEV pDrv = PDMIHGCMCONNECTOR_2_MAINVMMDEV(pInterface); 303 304 return hgcmConnectInternal (pDrv->pHGCMPort, pCmd, pServiceLocation, pu32ClientID, false); 306 307 if ( !pServiceLocation 308 || ( pServiceLocation->type != VMMDevHGCMLoc_LocalHost 309 && pServiceLocation->type != VMMDevHGCMLoc_LocalHost_Existing)) 310 { 311 return VERR_INVALID_PARAMETER; 312 } 313 314 return HGCMGuestConnect (pDrv->pHGCMPort, pCmd, pServiceLocation->u.host.achName, pu32ClientID); 305 315 } 306 316 … … 311 321 PDRVMAINVMMDEV pDrv = PDMIHGCMCONNECTOR_2_MAINVMMDEV(pInterface); 312 322 313 return hgcmDisconnectInternal (pDrv->pHGCMPort, pCmd, u32ClientID, false);323 return HGCMGuestDisconnect (pDrv->pHGCMPort, pCmd, u32ClientID); 314 324 } 315 325 … … 321 331 PDRVMAINVMMDEV pDrv = PDMIHGCMCONNECTOR_2_MAINVMMDEV(pInterface); 322 332 323 return hgcmGuestCallInternal (pDrv->pHGCMPort, pCmd, u32ClientID, u32Function, cParms, paParms, false);333 return HGCMGuestCall (pDrv->pHGCMPort, pCmd, u32ClientID, u32Function, cParms, paParms); 324 334 } 325 335 … … 334 344 { 335 345 LogFlowFunc(("Enter\n")); 336 337 #ifdef HGCMSS 338 return hgcmSaveStateInternal (pSSM); 339 #else 340 PDRVMAINVMMDEV pDrv = PDMINS2DATA(pDrvIns, PDRVMAINVMMDEV); 341 342 /* Save the current handle count and restore afterwards to avoid client id conflicts. */ 343 int rc = SSMR3PutU32(pSSM, hgcmObjQueryHandleCount()); 344 AssertRCReturn(rc, rc); 345 346 return hgcmSaveStateInternal (pDrv->pVMMDev->mSharedFolderClientId, pSSM); 347 #endif /* HGCMSS */ 346 return HGCMHostSaveState (pSSM); 348 347 } 349 348 … … 361 360 LogFlowFunc(("Enter\n")); 362 361 363 #ifdef HGCMSS364 362 if (u32Version != HGCM_SSM_VERSION) 365 363 return VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION; 366 364 367 return hgcmLoadStateInternal (pSSM); 368 #else 369 PDRVMAINVMMDEV pDrv = PDMINS2DATA(pDrvIns, PDRVMAINVMMDEV); 370 uint32_t u32HandleCount; 371 372 if (u32Version != HGCM_SSM_VERSION) 373 return VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION; 374 375 /* Save the current handle count and restore afterwards to avoid client id conflicts. */ 376 int rc = SSMR3GetU32(pSSM, &u32HandleCount); 377 AssertRCReturn(rc, rc); 378 hgcmObjSetHandleCount(u32HandleCount); 379 380 /* Unload all HGCM services to refresh client ids. */ 381 /** @todo shared clipboard too! */ 382 /** @todo need other solution! */ 383 if (pDrv->pVMMDev->mSharedFolderClientId) 384 { 385 uint64_t dummy = 0; 386 PVBOXHGCMCMD cmd = (PVBOXHGCMCMD)&dummy; 387 388 pDrv->pVMMDev->hgcmDisconnect(cmd, pDrv->pVMMDev->getShFlClientId()); 389 390 /* Reload Shared Folder HGCM service */ 391 HGCMSERVICELOCATION loc; 392 393 cmd = (PVBOXHGCMCMD)&dummy; 394 395 Log(("Connect to Shared Folders service\n")); 396 pDrv->pVMMDev->mSharedFolderClientId = 0; 397 loc.type = VMMDevHGCMLoc_LocalHost; 398 strcpy(loc.u.host.achName, "VBoxSharedFolders"); 399 int rc = pDrv->pVMMDev->hgcmConnect(cmd, &loc, &pDrv->pVMMDev->mSharedFolderClientId); 400 if (rc != VINF_SUCCESS) 401 { 402 AssertMsgFailed(("hgcmConnect returned %Vrc\n", rc)); 403 } 404 } 405 406 return hgcmLoadStateInternal (pDrv->pVMMDev->mSharedFolderClientId, pSSM); 407 #endif /* HGCMSS */ 365 return HGCMHostLoadState (pSSM); 408 366 } 409 367 410 368 int VMMDev::hgcmLoadService (const char *pszServiceName, const char *pszServiceLibrary) 411 369 { 412 return hgcmLoadInternal (pszServiceName, pszServiceLibrary); 413 } 414 415 int VMMDev::hgcmConnect (PVBOXHGCMCMD pCmd, PHGCMSERVICELOCATION pServiceLocation, uint32_t *pu32ClientID) 416 { 417 return hgcmConnectInternal (mpDrv->pHGCMPort, pCmd, pServiceLocation, pu32ClientID, true); 418 } 419 420 int VMMDev::hgcmDisconnect (PVBOXHGCMCMD pCmd, uint32_t u32ClientID) 421 { 422 return hgcmDisconnectInternal (mpDrv->pHGCMPort, pCmd, u32ClientID, true); 370 return HGCMHostLoad (pszServiceName, pszServiceLibrary); 423 371 } 424 372 … … 426 374 uint32_t cParms, PVBOXHGCMSVCPARM paParms) 427 375 { 428 return hgcmHostCallInternal (pszServiceName, u32Function, cParms, paParms); 429 } 430 431 #endif 376 return HGCMHostCall (pszServiceName, u32Function, cParms, paParms); 377 } 378 #endif /* HGCM */ 432 379 433 380 … … 471 418 LogFlow(("VMMDev::drvDestruct: iInstance=%d\n", pDrvIns->iInstance)); 472 419 #ifdef VBOX_HGCM 473 #ifndef HGCMSS 474 /* Unload Shared Folder HGCM service */ 475 if (pData->pVMMDev->mSharedFolderClientId) 476 { 477 uint64_t dummy = 0; 478 PVBOXHGCMCMD cmd = (PVBOXHGCMCMD)&dummy; 479 480 pData->pVMMDev->hgcmDisconnect(cmd, pData->pVMMDev->getShFlClientId()); 481 } 482 #endif /* !HGCMSS */ 483 484 hgcmReset (); 485 #endif 420 /* HGCM is shut down on the VMMDev destructor. */ 421 #endif /* VBOX_HGCM */ 486 422 if (pData->pVMMDev) 487 423 { … … 498 434 DECLCALLBACK(void) VMMDev::drvReset(PPDMDRVINS pDrvIns) 499 435 { 500 #if defined(VBOX_HGCM) && !defined(HGCMSS)501 PDRVMAINVMMDEV pData = PDMINS2DATA(pDrvIns, PDRVMAINVMMDEV);502 #endif503 436 LogFlow(("VMMDev::drvReset: iInstance=%d\n", pDrvIns->iInstance)); 504 437 #ifdef VBOX_HGCM 505 #ifndef HGCMSS 506 /* Unload Shared Folder HGCM service */ 507 uint64_t dummy = 0; 508 PVBOXHGCMCMD cmd = (PVBOXHGCMCMD)&dummy; 509 510 if (pData->pVMMDev->mSharedFolderClientId) 511 { 512 pData->pVMMDev->hgcmDisconnect(cmd, pData->pVMMDev->getShFlClientId()); 513 } 514 #endif /* !HGCMSS */ 515 516 hgcmReset (); 517 518 #ifndef HGCMSS 519 if (pData->pVMMDev->mSharedFolderClientId) 520 { 521 /* Reload Shared Folder HGCM service */ 522 HGCMSERVICELOCATION loc; 523 524 cmd = (PVBOXHGCMCMD)&dummy; 525 526 Log(("Connect to Shared Folders service\n")); 527 pData->pVMMDev->mSharedFolderClientId = 0; 528 loc.type = VMMDevHGCMLoc_LocalHost; 529 strcpy(loc.u.host.achName, "VBoxSharedFolders"); 530 int rc = pData->pVMMDev->hgcmConnect(cmd, &loc, &pData->pVMMDev->mSharedFolderClientId); 531 if (rc != VINF_SUCCESS) 532 { 533 AssertMsgFailed(("hgcmConnect returned %Vrc\n", rc)); 534 } 535 } 536 #endif /* !HGCMSS */ 537 #endif 438 HGCMHostReset (); 439 #endif /* VBOX_HGCM */ 538 440 } 539 441 … … 620 522 621 523 #ifdef VBOX_HGCM 622 623 #ifdef HGCMSS624 524 rc = pData->pVMMDev->hgcmLoadService ("VBoxSharedFolders", "VBoxSharedFolders"); 625 525 pData->pVMMDev->fSharedFolderActive = VBOX_SUCCESS(rc); … … 632 532 LogRel(("Failed to load Shared Folders service %Vrc\n", rc)); 633 533 } 634 #else635 /* Load Shared Folder HGCM service */636 HGCMSERVICELOCATION loc;637 uint64_t dummy = 0;638 PVBOXHGCMCMD pCmd = (PVBOXHGCMCMD)&dummy;639 640 Log(("Connect to Shared Folders service\n"));641 pData->pVMMDev->mSharedFolderClientId = 0;642 643 rc = pData->pVMMDev->hgcmLoadService ("VBoxSharedFolders", "VBoxSharedFolders");644 645 if (rc == VINF_SUCCESS)646 {647 loc.type = VMMDevHGCMLoc_LocalHost;648 strcpy(loc.u.host.achName, "VBoxSharedFolders");649 rc = pData->pVMMDev->hgcmConnect(pCmd, &loc, &pData->pVMMDev->mSharedFolderClientId);650 }651 652 if (rc != VINF_SUCCESS)653 {654 Log(("hgcmConnect returned %Vrc, shared folders are unavailable!!!\n", rc));655 656 /* This is not a fatal error; the shared folder dll can e.g. be missing */657 rc = VINF_SUCCESS;658 pData->pVMMDev->mSharedFolderClientId = 0;659 }660 #endif /* HGCMSS */661 534 pDrvIns->pDrvHlp->pfnSSMRegister(pDrvIns, "HGCM", 0, HGCM_SSM_VERSION, 4096/* bad guess */, NULL, iface_hgcmSave, NULL, NULL, iface_hgcmLoad, NULL); 662 #endif 535 #endif /* VBOX_HGCM */ 663 536 664 537 return VINF_SUCCESS; trunk/src/VBox/Main/hgcm/HGCM.cpp
r1686 r1711 18 18 * distribution, then only the terms of your commercial VirtualBox 19 19 * license agreement apply instead of the previous paragraph. 20 */21 22 23 /*24 * NOT FOR REVIEWING YET. A LOT OF TODO/MISSED/INCOMPLETE/SKETCH CODE INSIDE!25 20 */ 26 21 … … 52 47 53 48 /** 54 *55 * Service location types:56 *57 * LOCAL SERVICE58 * service DLL is loaded by the VM process,59 * and directly called by the VM HGCM instance.60 */61 62 /**63 49 * A service gets one thread, which synchronously delivers messages to 64 50 * the service. This is good for serialization. … … 78 64 * 79 65 * This message completion callback is only valid for Call requests. 80 * Connect and Disconnect are processed sznchronously by service. 81 * 82 */ 83 84 /** @todo services registration, only registered service dll can be loaded */ 85 86 /** @todo a registered LOCAL service must also get a thread, for now 87 * a thread per service (later may be there will be an option to 88 * have a thread per client for a service, however I do not think it's 89 * really necessary). 90 * The requests will be queued and executed by the service thread, 91 * an IRQ notification will be ussued when a request is completed. 92 * 93 * May be other services (like VRDP acceleration) should still use 94 * the EMT thread, because they have their own threads for long 95 * operations. 96 * So we have to distinguish those services during 97 * registration process (external/internal registration). 98 * External dlls will always have its own thread, 99 * internal (trusted) services will choose between having executed 100 * on EMT or on a separate thread. 101 * 102 */ 66 * Connect and Disconnect are processed synchronously by the service. 67 */ 68 103 69 104 70 /* The maximum allowed size of a service name in bytes. */ … … 109 75 * The HGCMService is an (in future) abstract class that implements 110 76 * common functionality. There will be derived classes for specific 111 * service types (Local, etc). 112 */ 113 114 /** @todo should be HGCMObject */ 77 * service types. 78 */ 79 115 80 class HGCMService 116 81 { … … 121 86 static HGCMService *sm_pSvcListTail; 122 87 123 #ifdef HGCMSS 124 static int sm_cServices; 125 #endif /* HGCMSS */ 88 static int sm_cServices; 126 89 127 90 HGCMTHREADHANDLE m_thread; … … 136 99 char *m_pszSvcLibrary; 137 100 138 PPDMIHGCMPORT m_pHGCMPort;139 140 101 RTLDRMOD m_hLdrMod; 141 102 PFNVBOXHGCMSVCLOAD m_pfnLoad; … … 151 112 void unloadServiceDLL (void); 152 113 153 int InstanceCreate (const char *pszServiceLibrary, const char *pszServiceName, PPDMIHGCMPORT pHGCMPort); 154 void InstanceDestroy (void); 114 /* 115 * Main HGCM thread methods. 116 */ 117 int instanceCreate (const char *pszServiceLibrary, const char *pszServiceName); 118 void instanceDestroy (void); 119 120 int saveClientState(uint32_t u32ClientId, PSSMHANDLE pSSM); 121 int loadClientState(uint32_t u32ClientId, PSSMHANDLE pSSM); 155 122 156 123 HGCMService (); 157 124 ~HGCMService () {}; 158 159 bool EqualToLoc (HGCMServiceLocation *loc);160 125 161 126 static DECLCALLBACK(void) svcHlpCallComplete (VBOXHGCMCALLHANDLE callHandle, int32_t rc); … … 163 128 public: 164 129 130 /* 131 * Main HGCM thread methods. 132 */ 133 static int LoadService (const char *pszServiceLibrary, const char *pszServiceName); 134 void UnloadService (); 135 136 static void UnloadAll (void); 137 138 static int ResolveService (HGCMService **ppsvc, const char *pszServiceName); 139 void ReferenceService (void); 140 void ReleaseService (void); 141 165 142 static void Reset (void); 166 143 167 #ifdef HGCMSS168 144 static int SaveState (PSSMHANDLE pSSM); 169 145 static int LoadState (PSSMHANDLE pSSM); 170 #endif /* HGCMSS */ 171 172 static int FindService (HGCMService **ppsvc, HGCMServiceLocation *loc); 173 static HGCMService *FindServiceByName (const char *pszServiceName); 174 static int LoadService (const char *pszServiceLibrary, const char *pszServiceName, PPDMIHGCMPORT pHGCMPort); 175 void ReleaseService (void); 146 147 int CreateAndConnectClient (uint32_t *pu32ClientIdOut, uint32_t u32ClientIdIn); 148 int DisconnectClient (uint32_t u32ClientId); 149 150 int HostCall (uint32_t u32Function, uint32_t cParms, VBOXHGCMSVCPARM *paParms); 176 151 177 152 uint32_t SizeOfClient (void) { return m_fntable.cbClient; }; 178 153 179 void DisconnectAll (void); 180 181 #ifdef HGCMSS 182 int CreateAndConnectClient (uint32_t *pu32ClientIdOut, uint32_t u32ClientIdIn); 183 #endif /* HGCMSS */ 184 185 int Connect (uint32_t u32ClientID); 186 int Disconnect (uint32_t u32ClientID); 187 int GuestCall (PPDMIHGCMPORT pHGCMPort, PVBOXHGCMCMD pCmd, uint32_t u32ClientID, uint32_t u32Function, uint32_t cParms, VBOXHGCMSVCPARM aParms[], bool fBlock); 188 int HostCall (PVBOXHGCMCMD pCmd, uint32_t u32ClientID, uint32_t u32Function, uint32_t cParms, VBOXHGCMSVCPARM aParms[]); 189 190 int SaveState(uint32_t u32ClientID, PSSMHANDLE pSSM); 191 int LoadState(uint32_t u32ClientID, PSSMHANDLE pSSM); 154 /* 155 * The service thread methods. 156 */ 157 158 int GuestCall (PPDMIHGCMPORT pHGCMPort, PVBOXHGCMCMD pCmd, uint32_t u32ClientId, uint32_t u32Function, uint32_t cParms, VBOXHGCMSVCPARM aParms[]); 192 159 }; 193 160 … … 234 201 235 202 236 /*237 * Messages processed by worker threads.238 */239 240 #define HGCMMSGID_SVC_LOAD (0)241 #define HGCMMSGID_SVC_UNLOAD (1)242 #define HGCMMSGID_SVC_CONNECT (2)243 #define HGCMMSGID_SVC_DISCONNECT (3)244 #define HGCMMSGID_GUESTCALL (4)245 246 class HGCMMsgSvcLoad: public HGCMMsgCore247 {248 };249 250 class HGCMMsgSvcUnload: public HGCMMsgCore251 {252 };253 254 class HGCMMsgSvcConnect: public HGCMMsgCore255 {256 public:257 /* client identifier */258 uint32_t u32ClientID;259 };260 261 class HGCMMsgSvcDisconnect: public HGCMMsgCore262 {263 public:264 /* client identifier */265 uint32_t u32ClientID;266 };267 268 class HGCMMsgHeader: public HGCMMsgCore269 {270 public:271 HGCMMsgHeader () : pCmd (NULL), pHGCMPort (NULL) {};272 273 /* Command pointer/identifier. */274 PVBOXHGCMCMD pCmd;275 276 /* Port to be informed on message completion. */277 PPDMIHGCMPORT pHGCMPort;278 };279 280 281 class HGCMMsgCall: public HGCMMsgHeader282 {283 public:284 /* client identifier */285 uint32_t u32ClientID;286 287 /* function number */288 uint32_t u32Function;289 290 /* number of parameters */291 uint32_t cParms;292 293 VBOXHGCMSVCPARM *paParms;294 };295 296 297 /*298 * Messages processed by main HGCM thread.299 */300 301 #define HGCMMSGID_CONNECT (10)302 #define HGCMMSGID_DISCONNECT (11)303 #define HGCMMSGID_LOAD (12)304 #define HGCMMSGID_HOSTCALL (13)305 #define HGCMMSGID_LOADSTATE (14)306 #define HGCMMSGID_SAVESTATE (15)307 #define HGCMMSGID_RESET (16)308 309 class HGCMMsgConnect: public HGCMMsgHeader310 {311 public:312 /* service location */313 HGCMSERVICELOCATION *pLoc;314 315 /* client identifier */316 uint32_t *pu32ClientID;317 318 };319 320 class HGCMMsgDisconnect: public HGCMMsgHeader321 {322 public:323 /* client identifier */324 uint32_t u32ClientID;325 };326 327 class HGCMMsgLoadSaveState: public HGCMMsgHeader328 {329 public:330 /* client identifier */331 uint32_t u32ClientID;332 PSSMHANDLE pSSM;333 };334 335 class HGCMMsgLoad: public HGCMMsgHeader336 {337 public:338 virtual ~HGCMMsgLoad ()339 {340 RTStrFree (pszServiceLibrary);341 RTStrFree (pszServiceName);342 }343 344 int Init (const char *pszName, const char *pszLibrary)345 {346 pszServiceName = RTStrDup (pszName);347 pszServiceLibrary = RTStrDup (pszLibrary);348 349 if (!pszServiceName || !pszServiceLibrary)350 {351 RTStrFree (pszServiceLibrary);352 RTStrFree (pszServiceName);353 pszServiceLibrary = NULL;354 pszServiceName = NULL;355 return VERR_NO_MEMORY;356 }357 358 return VINF_SUCCESS;359 }360 361 char *pszServiceName;362 char *pszServiceLibrary;363 };364 365 class HGCMMsgHostCall: public HGCMMsgHeader366 {367 public:368 char *pszServiceName;369 370 /* function number */371 uint32_t u32Function;372 373 /* number of parameters */374 uint32_t cParms;375 376 VBOXHGCMSVCPARM *paParms;377 };378 379 class HGCMMsgReset: public HGCMMsgHeader380 {381 };382 383 /* static */ DECLCALLBACK(void) HGCMService::svcHlpCallComplete (VBOXHGCMCALLHANDLE callHandle, int32_t rc)384 {385 HGCMMsgCore *pMsgCore = (HGCMMsgCore *)callHandle;386 387 if ( pMsgCore->MsgId () == HGCMMSGID_GUESTCALL388 || pMsgCore->MsgId () == HGCMMSGID_HOSTCALL)389 {390 /* Only call the completion for these messages. The helper391 * is called by the service, and the service does not get392 * any other messages.393 */394 hgcmMsgComplete (pMsgCore, rc);395 }396 else397 {398 AssertFailed ();399 }400 }401 203 402 204 HGCMService *HGCMService::sm_pSvcListHead = NULL; 403 205 HGCMService *HGCMService::sm_pSvcListTail = NULL; 404 #ifdef HGCMSS405 206 int HGCMService::sm_cServices = 0; 406 #endif /* HGCMSS */407 207 408 208 HGCMService::HGCMService () … … 424 224 425 225 426 HGCMMsgCore *hgcmMessageAlloc (uint32_t u32MsgId)427 {428 switch (u32MsgId)429 {430 case HGCMMSGID_SVC_LOAD: return new HGCMMsgSvcLoad ();431 case HGCMMSGID_SVC_UNLOAD: return new HGCMMsgSvcUnload ();432 case HGCMMSGID_SVC_CONNECT: return new HGCMMsgSvcConnect ();433 case HGCMMSGID_SVC_DISCONNECT: return new HGCMMsgSvcDisconnect ();434 case HGCMMSGID_GUESTCALL: return new HGCMMsgCall ();435 436 case HGCMMSGID_CONNECT: return new HGCMMsgConnect ();437 case HGCMMSGID_DISCONNECT: return new HGCMMsgDisconnect ();438 case HGCMMSGID_LOAD: return new HGCMMsgLoad ();439 case HGCMMSGID_HOSTCALL: return new HGCMMsgHostCall ();440 case HGCMMSGID_LOADSTATE:441 case HGCMMSGID_SAVESTATE: return new HGCMMsgLoadSaveState ();442 case HGCMMSGID_RESET: return new HGCMMsgReset ();443 default:444 Log(("hgcmMessageAlloc::Unsupported message number %08X\n", u32MsgId));445 AssertReleaseMsgFailed(("Msg id = %08X\n", u32MsgId));446 }447 448 return NULL;449 }450 451 226 static bool g_fResetting = false; 452 227 static bool g_fSaveState = false; 453 228 454 static DECLCALLBACK(void) hgcmMsgCompletionCallback (int32_t result, HGCMMsgCore *pMsgCore) 455 { 456 /* Call the VMMDev port interface to issue IRQ notification. */ 457 HGCMMsgHeader *pMsgHdr = (HGCMMsgHeader *)pMsgCore; 458 459 LogFlow(("MAIN::hgcmMsgCompletionCallback: message %p\n", pMsgCore)); 460 461 if (pMsgHdr->pHGCMPort && !g_fResetting) 462 { 463 pMsgHdr->pHGCMPort->pfnCompleted (pMsgHdr->pHGCMPort, g_fSaveState? VINF_HGCM_SAVE_STATE: result, pMsgHdr->pCmd); 464 } 465 466 return; 467 } 468 469 470 DECLCALLBACK(void) hgcmServiceThread (HGCMTHREADHANDLE ThreadHandle, void *pvUser) 471 { 229 230 231 /** Helper function to load a local service DLL. 232 * 233 * @return VBox code 234 */ 235 int HGCMService::loadServiceDLL (void) 236 { 237 LogFlow(("HGCMService::loadServiceDLL: m_pszSvcLibrary = %s\n", m_pszSvcLibrary)); 238 239 if (m_pszSvcLibrary == NULL) 240 { 241 return VERR_INVALID_PARAMETER; 242 } 243 472 244 int rc = VINF_SUCCESS; 473 245 246 rc = RTLdrLoad (m_pszSvcLibrary, &m_hLdrMod); 247 248 if (VBOX_SUCCESS(rc)) 249 { 250 LogFlow(("HGCMService::loadServiceDLL: successfully loaded the library.\n")); 251 252 m_pfnLoad = NULL; 253 254 rc = RTLdrGetSymbol (m_hLdrMod, VBOX_HGCM_SVCLOAD_NAME, (void**)&m_pfnLoad); 255 256 if (VBOX_FAILURE (rc) || !m_pfnLoad) 257 { 258 Log(("HGCMService::loadServiceDLL: Error resolving the service entry point %s, rc = %d, m_pfnLoad = %p\n", VBOX_HGCM_SVCLOAD_NAME, rc, m_pfnLoad)); 259 260 if (VBOX_SUCCESS(rc)) 261 { 262 /* m_pfnLoad was NULL */ 263 rc = VERR_SYMBOL_NOT_FOUND; 264 } 265 } 266 267 if (VBOX_SUCCESS(rc)) 268 { 269 memset (&m_fntable, 0, sizeof (m_fntable)); 270 271 m_fntable.cbSize = sizeof (m_fntable); 272 m_fntable.u32Version = VBOX_HGCM_SVC_VERSION; 273 m_fntable.pHelpers = &m_svcHelpers; 274 275 rc = m_pfnLoad (&m_fntable); 276 277 LogFlow(("HGCMService::loadServiceDLL: m_pfnLoad rc = %Vrc\n", rc)); 278 279 if (VBOX_SUCCESS (rc)) 280 { 281 if ( m_fntable.pfnUnload == NULL 282 || m_fntable.pfnConnect == NULL 283 || m_fntable.pfnDisconnect == NULL 284 || m_fntable.pfnCall == NULL 285 ) 286 { 287 Log(("HGCMService::loadServiceDLL: at least one of function pointers is NULL\n")); 288 289 rc = VERR_INVALID_PARAMETER; 290 291 if (m_fntable.pfnUnload) 292 { 293 m_fntable.pfnUnload (); 294 } 295 } 296 } 297 } 298 } 299 else 300 { 301 LogFlow(("HGCMService::loadServiceDLL: failed to load service library. The service is not available.\n")); 302 m_hLdrMod = NIL_RTLDRMOD; 303 } 304 305 if (VBOX_FAILURE(rc)) 306 { 307 unloadServiceDLL (); 308 } 309 310 return rc; 311 } 312 313 /** Helper function to free a local service DLL. 314 * 315 * @return VBox code 316 */ 317 void HGCMService::unloadServiceDLL (void) 318 { 319 if (m_hLdrMod) 320 { 321 RTLdrClose (m_hLdrMod); 322 } 323 324 memset (&m_fntable, 0, sizeof (m_fntable)); 325 m_pfnLoad = NULL; 326 m_hLdrMod = NIL_RTLDRMOD; 327 } 328 329 /* 330 * Messages processed by service threads. These threads only call the service entry points. 331 */ 332 333 #define SVC_MSG_LOAD (0) /* Load the service library and call VBOX_HGCM_SVCLOAD_NAME entry point. */ 334 #define SVC_MSG_UNLOAD (1) /* call pfnUnload and unload the service library. */ 335 #define SVC_MSG_CONNECT (2) /* pfnConnect */ 336 #define SVC_MSG_DISCONNECT (3) /* pfnDisconnect */ 337 #define SVC_MSG_GUESTCALL (4) /* pfnGuestCall */ 338 #define SVC_MSG_HOSTCALL (5) /* pfnHostCall */ 339 #define SVC_MSG_LOADSTATE (6) /* pfnLoadState. */ 340 #define SVC_MSG_SAVESTATE (7) /* pfnSaveState. */ 341 #define SVC_MSG_QUIT (8) /* Terminate the thread. */ 342 343 class HGCMMsgSvcLoad: public HGCMMsgCore 344 { 345 }; 346 347 class HGCMMsgSvcUnload: public HGCMMsgCore 348 { 349 }; 350 351 class HGCMMsgSvcConnect: public HGCMMsgCore 352 { 353 public: 354 /* client identifier */ 355 uint32_t u32ClientId; 356 }; 357 358 class HGCMMsgSvcDisconnect: public HGCMMsgCore 359 { 360 public: 361 /* client identifier */ 362 uint32_t u32ClientId; 363 }; 364 365 class HGCMMsgHeader: public HGCMMsgCore 366 { 367 public: 368 HGCMMsgHeader () : pCmd (NULL), pHGCMPort (NULL) {}; 369 370 /* Command pointer/identifier. */ 371 PVBOXHGCMCMD pCmd; 372 373 /* Port to be informed on message completion. */ 374 PPDMIHGCMPORT pHGCMPort; 375 }; 376 377 378 class HGCMMsgCall: public HGCMMsgHeader 379 { 380 public: 381 /* client identifier */ 382 uint32_t u32ClientId; 383 384 /* function number */ 385 uint32_t u32Function; 386 387 /* number of parameters */ 388 uint32_t cParms; 389 390 VBOXHGCMSVCPARM *paParms; 391 }; 392 393 class HGCMMsgLoadSaveStateClient: public HGCMMsgCore 394 { 395 public: 396 uint32_t u32ClientId; 397 PSSMHANDLE pSSM; 398 }; 399 400 class HGCMMsgHostCallSvc: public HGCMMsgCore 401 { 402 public: 403 /* function number */ 404 uint32_t u32Function; 405 406 /* number of parameters */ 407 uint32_t cParms; 408 409 VBOXHGCMSVCPARM *paParms; 410 }; 411 412 static HGCMMsgCore *hgcmMessageAllocSvc (uint32_t u32MsgId) 413 { 414 switch (u32MsgId) 415 { 416 case SVC_MSG_LOAD: return new HGCMMsgSvcLoad (); 417 case SVC_MSG_UNLOAD: return new HGCMMsgSvcUnload (); 418 case SVC_MSG_CONNECT: return new HGCMMsgSvcConnect (); 419 case SVC_MSG_DISCONNECT: return new HGCMMsgSvcDisconnect (); 420 case SVC_MSG_HOSTCALL: return new HGCMMsgHostCallSvc (); 421 case SVC_MSG_GUESTCALL: return new HGCMMsgCall (); 422 case SVC_MSG_LOADSTATE: 423 case SVC_MSG_SAVESTATE: return new HGCMMsgLoadSaveStateClient (); 424 default: 425 AssertReleaseMsgFailed(("Msg id = %08X\n", u32MsgId)); 426 } 427 428 return NULL; 429 } 430 431 /* 432 * The service thread. Loads the service library and calls the service entry points. 433 */ 434 static DECLCALLBACK(void) hgcmServiceThread (HGCMTHREADHANDLE ThreadHandle, void *pvUser) 435 { 474 436 HGCMService *pSvc = (HGCMService *)pvUser; 475 476 437 AssertRelease(pSvc != NULL); 477 438 478 HGCMMsgCore *pMsgCore = NULL; 479 480 bool bUnloaded = false; 481 482 while (!bUnloaded) 483 { 484 rc = hgcmMsgGet (ThreadHandle, &pMsgCore); 439 bool fQuit = false; 440 441 while (!fQuit) 442 { 443 HGCMMsgCore *pMsgCore; 444 int rc = hgcmMsgGet (ThreadHandle, &pMsgCore); 485 445 486 446 if (VBOX_FAILURE (rc)) 487 447 { 488 Log(("hgcmServiceThread: message get failed, rc = %Vrc\n", rc)); 489 490 RTThreadSleep(100); 491 492 continue; 448 /* The error means some serious unrecoverable problem in the hgcmMsg/hgcmThread layer. */ 449 AssertMsgFailed (("%Vrc\n", rc)); 450 break; 493 451 } 494 452 … … 498 456 switch (u32MsgId) 499 457 { 500 case HGCMMSGID_SVC_LOAD:501 { 502 LogFlow (("HGCMMSGID_SVC_LOAD\n"));458 case SVC_MSG_LOAD: 459 { 460 LogFlowFunc(("SVC_MSG_LOAD\n")); 503 461 rc = pSvc->loadServiceDLL (); 504 462 } break; 505 463 506 case HGCMMSGID_SVC_UNLOAD:507 { 508 LogFlow (("HGCMMSGID_SVC_UNLOAD\n"));464 case SVC_MSG_UNLOAD: 465 { 466 LogFlowFunc(("SVC_MSG_UNLOAD\n")); 509 467 pSvc->unloadServiceDLL (); 510 bUnloaded= true;468 fQuit = true; 511 469 } break; 512 470 513 case HGCMMSGID_SVC_CONNECT: 514 { 515 LogFlow(("HGCMMSGID_SVC_CONNECT\n")); 516 471 case SVC_MSG_CONNECT: 472 { 517 473 HGCMMsgSvcConnect *pMsg = (HGCMMsgSvcConnect *)pMsgCore; 518 474 519 rc = VINF_SUCCESS;520 521 HGCMClient *pClient = (HGCMClient *)hgcmObjReference (pMsg->u32ClientI D, HGCMOBJ_CLIENT);475 LogFlowFunc(("SVC_MSG_CONNECT u32ClientId = %d\n", pMsg->u32ClientId)); 476 477 HGCMClient *pClient = (HGCMClient *)hgcmObjReference (pMsg->u32ClientId, HGCMOBJ_CLIENT); 522 478 523 479 if (pClient) 524 480 { 525 rc = pSvc->m_fntable.pfnConnect (pMsg->u32ClientID, HGCM_CLIENT_DATA(pSvc, pClient)); 526 527 hgcmObjDereference (pClient); 528 } 529 } break; 530 531 case HGCMMSGID_SVC_DISCONNECT: 532 { 533 LogFlow(("HGCMMSGID_SVC_DISCONNECT\n")); 534 535 HGCMMsgSvcDisconnect *pMsg = (HGCMMsgSvcDisconnect *)pMsgCore; 536 537 rc = VINF_SUCCESS; 538 539 HGCMClient *pClient = (HGCMClient *)hgcmObjReference (pMsg->u32ClientID, HGCMOBJ_CLIENT); 540 541 if (pClient) 542 { 543 rc = pSvc->m_fntable.pfnDisconnect (pMsg->u32ClientID, HGCM_CLIENT_DATA(pSvc, pClient)); 544 545 hgcmObjDereference (pClient); 546 } 547 } break; 548 549 case HGCMMSGID_GUESTCALL: 550 { 551 LogFlow(("HGCMMSGID_GUESTCALL\n")); 552 553 HGCMMsgCall *pMsg = (HGCMMsgCall *)pMsgCore; 554 555 rc = VINF_SUCCESS; 556 557 HGCMClient *pClient = (HGCMClient *)hgcmObjReference (pMsg->u32ClientID, HGCMOBJ_CLIENT); 558 559 if (pClient) 560 { 561 pSvc->m_fntable.pfnCall ((VBOXHGCMCALLHANDLE)pMsg, pMsg->u32ClientID, HGCM_CLIENT_DATA(pSvc, pClient), pMsg->u32Function, pMsg->cParms, pMsg->paParms); 481 rc = pSvc->m_fntable.pfnConnect (pMsg->u32ClientId, HGCM_CLIENT_DATA(pSvc, pClient)); 562 482 563 483 hgcmObjDereference (pClient); … … 569 489 } break; 570 490 571 case HGCMMSGID_HOSTCALL: 572 { 573 LogFlow(("HGCMMSGID_HOSTCALL\n")); 574 575 HGCMMsgHostCall *pMsg = (HGCMMsgHostCall *)pMsgCore; 576 577 pSvc->m_fntable.pfnHostCall ((VBOXHGCMCALLHANDLE)pMsg, 0, NULL, pMsg->u32Function, pMsg->cParms, pMsg->paParms); 578 579 rc = VINF_SUCCESS; 491 case SVC_MSG_DISCONNECT: 492 { 493 HGCMMsgSvcDisconnect *pMsg = (HGCMMsgSvcDisconnect *)pMsgCore; 494 495 LogFlowFunc(("SVC_MSG_DISCONNECT u32ClientId = %d\n", pMsg->u32ClientId)); 496 497 HGCMClient *pClient = (HGCMClient *)hgcmObjReference (pMsg->u32ClientId, HGCMOBJ_CLIENT); 498 499 if (pClient) 500 { 501 rc = pSvc->m_fntable.pfnDisconnect (pMsg->u32ClientId, HGCM_CLIENT_DATA(pSvc, pClient)); 502 503 hgcmObjDereference (pClient); 504 } 505 else 506 { 507 rc = VERR_HGCM_INVALID_CLIENT_ID; 508 } 580 509 } break; 581 510 582 case HGCMMSGID_LOADSTATE: 583 { 584 LogFlow(("HGCMMSGID_LOADSTATE\n")); 585 586 HGCMMsgLoadSaveState *pMsg = (HGCMMsgLoadSaveState *)pMsgCore; 587 HGCMClient *pClient = (HGCMClient *)hgcmObjReference (pMsg->u32ClientID, HGCMOBJ_CLIENT); 588 589 rc = VINF_SUCCESS; 511 case SVC_MSG_GUESTCALL: 512 { 513 HGCMMsgCall *pMsg = (HGCMMsgCall *)pMsgCore; 514 515 LogFlowFunc(("SVC_MSG_GUESTCALL u32ClientId = %d, u32Function = %d, cParms = %d, paParms = %p\n", 516 pMsg->u32ClientId, pMsg->u32Function, pMsg->cParms, pMsg->paParms)); 517 518 HGCMClient *pClient = (HGCMClient *)hgcmObjReference (pMsg->u32ClientId, HGCMOBJ_CLIENT); 519 520 if (pClient) 521 { 522 pSvc->m_fntable.pfnCall ((VBOXHGCMCALLHANDLE)pMsg, pMsg->u32ClientId, HGCM_CLIENT_DATA(pSvc, pClient), pMsg->u32Function, pMsg->cParms, pMsg->paParms); 523 524 hgcmObjDereference (pClient); 525 } 526 else 527 { 528 rc = VERR_HGCM_INVALID_CLIENT_ID; 529 } 530 } break; 531 532 case SVC_MSG_HOSTCALL: 533 { 534

