Changeset 1711 in vbox for trunk/src/VBox/Main
- Timestamp:
- Mar 27, 2007 8:35:21 AM (18 years ago)
- Location:
- trunk/src/VBox/Main
- Files:
-
- 7 edited
Legend:
- Unmodified
- Added
- Removed
-
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 HGCMMsgHostCallSvc *pMsg = (HGCMMsgHostCallSvc *)pMsgCore; 535 536 LogFlowFunc(("SVC_MSG_HOSTCALL u32Function = %d, cParms = %d, paParms = %p\n", pMsg->u32Function, pMsg->cParms, pMsg->paParms)); 537 538 rc = pSvc->m_fntable.pfnHostCall (pMsg->u32Function, pMsg->cParms, pMsg->paParms); 539 } break; 540 541 case SVC_MSG_LOADSTATE: 542 { 543 HGCMMsgLoadSaveStateClient *pMsg = (HGCMMsgLoadSaveStateClient *)pMsgCore; 544 545 LogFlowFunc(("SVC_MSG_LOADSTATE\n")); 546 547 HGCMClient *pClient = (HGCMClient *)hgcmObjReference (pMsg->u32ClientId, HGCMOBJ_CLIENT); 590 548 591 549 if (pClient) … … 593 551 if (pSvc->m_fntable.pfnLoadState) 594 552 { 595 rc = pSvc->m_fntable.pfnLoadState (pMsg->u32ClientI D, HGCM_CLIENT_DATA(pSvc, pClient), pMsg->pSSM);553 rc = pSvc->m_fntable.pfnLoadState (pMsg->u32ClientId, HGCM_CLIENT_DATA(pSvc, pClient), pMsg->pSSM); 596 554 } 597 555 598 556 hgcmObjDereference (pClient); 599 557 } 600 break; 601 } 602 603 case HGCMMSGID_SAVESTATE: 604 { 605 LogFlow(("HGCMMSGID_SAVESTATE\n")); 606 607 HGCMMsgLoadSaveState *pMsg = (HGCMMsgLoadSaveState *)pMsgCore; 608 HGCMClient *pClient = (HGCMClient *)hgcmObjReference (pMsg->u32ClientID, HGCMOBJ_CLIENT); 558 else 559 { 560 rc = VERR_HGCM_INVALID_CLIENT_ID; 561 } 562 } break; 563 564 case SVC_MSG_SAVESTATE: 565 { 566 HGCMMsgLoadSaveStateClient *pMsg = (HGCMMsgLoadSaveStateClient *)pMsgCore; 567 568 LogFlowFunc(("SVC_MSG_SAVESTATE\n")); 569 570 HGCMClient *pClient = (HGCMClient *)hgcmObjReference (pMsg->u32ClientId, HGCMOBJ_CLIENT); 609 571 610 572 rc = VINF_SUCCESS; … … 615 577 { 616 578 g_fSaveState = true; 617 rc = pSvc->m_fntable.pfnSaveState (pMsg->u32ClientI D, HGCM_CLIENT_DATA(pSvc, pClient), pMsg->pSSM);579 rc = pSvc->m_fntable.pfnSaveState (pMsg->u32ClientId, HGCM_CLIENT_DATA(pSvc, pClient), pMsg->pSSM); 618 580 g_fSaveState = false; 619 581 } … … 621 583 hgcmObjDereference (pClient); 622 584 } 623 break; 624 } 585 else 586 { 587 rc = VERR_HGCM_INVALID_CLIENT_ID; 588 } 589 } break; 625 590 626 591 default: 627 592 { 628 Log(("hgcmServiceThread::Unsupported message number %08X\n", u32MsgId));593 AssertMsgFailed(("hgcmServiceThread::Unsupported message number %08X\n", u32MsgId)); 629 594 rc = VERR_NOT_SUPPORTED; 630 595 } break; 631 596 } 632 597 633 if ( u32MsgId != HGCMMSGID_GUESTCALL 634 && u32MsgId != HGCMMSGID_HOSTCALL) 635 { 636 /* For HGCMMSGID_GUESTCALL & HGCMMSGID_HOSTCALL the service 637 * calls the completion helper. Other messages have to be 638 * completed here. 598 if (u32MsgId != SVC_MSG_GUESTCALL) 599 { 600 /* For SVC_MSG_GUESTCALL the service calls the completion helper. 601 * Other messages have to be completed here. 639 602 */ 640 603 hgcmMsgComplete (pMsgCore, rc); 641 604 } 642 605 } 643 644 return; 645 } 646 647 int HGCMService::InstanceCreate (const char *pszServiceLibrary, const char *pszServiceName, PPDMIHGCMPORT pHGCMPort) 648 { 649 int rc = VINF_SUCCESS; 650 651 LogFlow(("HGCMService::InstanceCreate: name %s, lib %s\n", pszServiceName, pszServiceLibrary)); 652 653 char achThreadName[14]; 654 655 RTStrPrintf (achThreadName, sizeof (achThreadName), "HGCM%08X", this); 656 657 rc = hgcmThreadCreate (&m_thread, achThreadName, hgcmServiceThread, this); 606 } 607 608 /* static */ DECLCALLBACK(void) HGCMService::svcHlpCallComplete (VBOXHGCMCALLHANDLE callHandle, int32_t rc) 609 { 610 HGCMMsgCore *pMsgCore = (HGCMMsgCore *)callHandle; 611 612 if (pMsgCore->MsgId () == SVC_MSG_GUESTCALL) 613 { 614 /* Only call the completion for these messages. The helper 615 * is called by the service, and the service does not get 616 * any other messages. 617 */ 618 hgcmMsgComplete (pMsgCore, rc); 619 } 620 else 621 { 622 AssertFailed (); 623 } 624 } 625 626 static DECLCALLBACK(void) hgcmMsgCompletionCallback (int32_t result, HGCMMsgCore *pMsgCore) 627 { 628 /* Call the VMMDev port interface to issue IRQ notification. */ 629 HGCMMsgHeader *pMsgHdr = (HGCMMsgHeader *)pMsgCore; 630 631 LogFlow(("MAIN::hgcmMsgCompletionCallback: message %p\n", pMsgCore)); 632 633 if (pMsgHdr->pHGCMPort && !g_fResetting) 634 { 635 pMsgHdr->pHGCMPort->pfnCompleted (pMsgHdr->pHGCMPort, g_fSaveState? VINF_HGCM_SAVE_STATE: result, pMsgHdr->pCmd); 636 } 637 } 638 639 /* 640 * The main HGCM methods of the service. 641 */ 642 643 int HGCMService::instanceCreate (const char *pszServiceLibrary, const char *pszServiceName) 644 { 645 LogFlowFunc(("name %s, lib %s\n", pszServiceName, pszServiceLibrary)); 646 647 /* The maximum length of the thread name, allowed by the RT is 15. */ 648 char achThreadName[16]; 649 650 strncpy (achThreadName, pszServiceName, 15); 651 achThreadName[15] = 0; 652 653 int rc = hgcmThreadCreate (&m_thread, achThreadName, hgcmServiceThread, this); 658 654 659 655 if (VBOX_SUCCESS(rc)) … … 674 670 else 675 671 { 676 m_pHGCMPort = pHGCMPort; 677 672 /* Initialize service helpers table. */ 678 673 m_svcHelpers.pfnCallComplete = svcHlpCallComplete; 679 674 m_svcHelpers.pvInstance = this; … … 681 676 /* Execute the load request on the service thread. */ 682 677 HGCMMSGHANDLE hMsg; 683 684 rc = hgcmMsgAlloc (m_thread, &hMsg, HGCMMSGID_SVC_LOAD, hgcmMessageAlloc); 678 rc = hgcmMsgAlloc (m_thread, &hMsg, SVC_MSG_LOAD, hgcmMessageAllocSvc); 685 679 686 680 if (VBOX_SUCCESS(rc)) … … 690 684 } 691 685 } 692 else693 {694 Log(("HGCMService::InstanceCreate: FAILURE: service thread creation\n"));695 }696 686 697 687 if (VBOX_FAILURE(rc)) 698 688 { 699 InstanceDestroy (); 700 } 701 702 LogFlow(("HGCMService::InstanceCreate rc = %Vrc\n", rc)); 703 689 instanceDestroy (); 690 } 691 692 LogFlowFunc(("rc = %Vrc\n", rc)); 704 693 return rc; 705 694 } 706 695 707 void HGCMService::InstanceDestroy (void) 708 { 696 void HGCMService::instanceDestroy (void) 697 { 698 LogFlowFunc(("%s\n", m_pszSvcName)); 699 709 700 HGCMMSGHANDLE hMsg; 710 711 LogFlow(("HGCMService::InstanceDestroy\n")); 712 713 int rc = hgcmMsgAlloc (m_thread, &hMsg, HGCMMSGID_SVC_UNLOAD, hgcmMessageAlloc); 701 int rc = hgcmMsgAlloc (m_thread, &hMsg, SVC_MSG_UNLOAD, hgcmMessageAllocSvc); 714 702 715 703 if (VBOX_SUCCESS(rc)) … … 720 708 RTStrFree (m_pszSvcLibrary); 721 709 m_pszSvcLibrary = NULL; 710 722 711 RTStrFree (m_pszSvcName); 723 712 m_pszSvcName = NULL; 713 } 714 715 int HGCMService::saveClientState(uint32_t u32ClientId, PSSMHANDLE pSSM) 716 { 717 LogFlowFunc(("%s\n", m_pszSvcName)); 718 719 HGCMMSGHANDLE hMsg; 720 int rc = hgcmMsgAlloc (m_thread, &hMsg, SVC_MSG_SAVESTATE, hgcmMessageAllocSvc); 721 722 if (VBOX_SUCCESS(rc)) 723 { 724 HGCMMsgLoadSaveStateClient *pMsg = (HGCMMsgLoadSaveStateClient *)hgcmObjReference (hMsg, HGCMOBJ_MSG); 725 AssertRelease(pMsg); 726 727 pMsg->u32ClientId = u32ClientId; 728 pMsg->pSSM = pSSM; 729 730 hgcmObjDereference (pMsg); 731 732 rc = hgcmMsgSend (hMsg); 733 } 734 735 LogFlowFunc(("rc = %Vrc\n", rc)); 736 return rc; 737 } 738 739 int HGCMService::loadClientState (uint32_t u32ClientId, PSSMHANDLE pSSM) 740 { 741 LogFlowFunc(("%s\n", m_pszSvcName)); 742 743 HGCMMSGHANDLE hMsg; 744 int rc = hgcmMsgAlloc (m_thread, &hMsg, SVC_MSG_LOADSTATE, hgcmMessageAllocSvc); 745 746 if (VBOX_SUCCESS(rc)) 747 { 748 HGCMMsgLoadSaveStateClient *pMsg = (HGCMMsgLoadSaveStateClient *)hgcmObjReference (hMsg, HGCMOBJ_MSG); 749 750 AssertRelease(pMsg); 751 752 pMsg->u32ClientId = u32ClientId; 753 pMsg->pSSM = pSSM; 754 755 hgcmObjDereference (pMsg); 756 757 rc = hgcmMsgSend (hMsg); 758 } 759 760 LogFlowFunc(("rc = %Vrc\n", rc)); 761 return rc; 762 } 763 764 765 /** The method creates a service and references it. 766 * 767 * @param pszServcieLibrary The library to be loaded. 768 * @param pszServiceName The name of the service. 769 * @return VBox rc. 770 * @thread main HGCM 771 */ 772 /* static */ int HGCMService::LoadService (const char *pszServiceLibrary, const char *pszServiceName) 773 { 774 LogFlowFunc(("name = %s, lib %s\n", pszServiceName, pszServiceLibrary)); 775 776 /* Look at already loaded services to avoid double loading. */ 777 778 HGCMService *pSvc; 779 int rc = HGCMService::ResolveService (&pSvc, pszServiceName); 724 780 725 // @todo Adjust the list sm_cServices--; 726 727 LogFlow(("HGCMService::InstanceDestroy completed\n")); 728 } 729 730 bool HGCMService::EqualToLoc (HGCMServiceLocation *loc) 731 { 732 if (!loc || (loc->type != VMMDevHGCMLoc_LocalHost && loc->type != VMMDevHGCMLoc_LocalHost_Existing)) 733 { 734 return false; 735 } 736 737 if (strcmp (m_pszSvcName, loc->u.host.achName) != 0) 738 { 739 return false; 740 } 741 742 return true; 743 } 744 745 /** Services are searched by FindService function which is called 746 * by the main HGCM thread during CONNECT message processing. 747 * Reference count of the service is increased. 748 * Services are loaded by the LoadService function. 749 * Note: both methods are executed by the main HGCM thread. 750 */ 751 /* static */ int HGCMService::FindService (HGCMService **ppsvc, HGCMServiceLocation *loc) 752 { 753 HGCMService *psvc = NULL; 754 755 LogFlow(("HGCMService::FindService: loc = %p\n", loc)); 756 757 if (!loc || (loc->type != VMMDevHGCMLoc_LocalHost && loc->type != VMMDevHGCMLoc_LocalHost_Existing)) 758 { 759 return VERR_INVALID_PARAMETER; 760 } 761 762 LogFlow(("HGCMService::FindService: name %s\n", loc->u.host.achName)); 763 764 /* Look at already loaded services. */ 765 psvc = sm_pSvcListHead; 766 767 while (psvc) 768 { 769 if (psvc->EqualToLoc (loc)) 770 { 771 break; 772 } 773 774 psvc = psvc->m_pSvcNext; 775 } 776 777 LogFlow(("HGCMService::FindService: lookup in the list is %p\n", psvc)); 778 779 if (psvc) 780 { 781 ASMAtomicIncU32 (&psvc->m_u32RefCnt); 782 783 *ppsvc = psvc; 784 785 return VINF_SUCCESS; 786 } 787 788 return VERR_ACCESS_DENIED; 789 } 790 791 /* static */ HGCMService *HGCMService::FindServiceByName (const char *pszServiceName) 792 { 793 HGCMService *psvc = sm_pSvcListHead; 794 795 while (psvc) 796 { 797 if (strcmp (psvc->m_pszSvcName, pszServiceName) == 0) 798 { 799 break; 800 } 801 802 psvc = psvc->m_pSvcNext; 803 } 804 805 return psvc; 806 } 807 808 /* static */ int HGCMService::LoadService (const char *pszServiceLibrary, const char *pszServiceName, PPDMIHGCMPORT pHGCMPort) 809 { 810 int rc = VINF_SUCCESS; 811 812 HGCMService *psvc = NULL; 813 814 LogFlow(("HGCMService::LoadService: name = %s, lib %s\n", pszServiceName, pszServiceLibrary)); 815 816 /* Look at already loaded services to avoid double loading. */ 817 psvc = FindServiceByName (pszServiceName); 818 819 if (psvc) 820 { 821 LogFlow(("HGCMService::LoadService: Service already exists %p!!!\n", psvc)); 781 if (VBOX_SUCCESS (rc)) 782 { 783 /* The service is already loaded. */ 784 pSvc->ReleaseService (); 785 rc = VERR_HGCM_SERVICE_EXISTS; 822 786 } 823 787 else 824 788 { 825 psvc = new HGCMService ();826 827 if (!psvc) 828 {829 Log(("HGCMService::Load: memory allocation for the service failed!!!\n"));789 /* Create the new service. */ 790 pSvc = new HGCMService (); 791 792 if (!pSvc) 793 { 830 794 rc = VERR_NO_MEMORY; 831 795 } 832 833 if (VBOX_SUCCESS(rc))834 {835 rc = p svc->InstanceCreate (pszServiceLibrary, pszServiceName, pHGCMPort);796 else 797 { 798 /* Load the library and call the initialization entry point. */ 799 rc = pSvc->instanceCreate (pszServiceLibrary, pszServiceName); 836 800 837 801 if (VBOX_SUCCESS(rc)) 838 802 { 839 803 /* Insert the just created service to list for future references. */ 840 p svc->m_pSvcNext = sm_pSvcListHead;841 p svc->m_pSvcPrev = NULL;804 pSvc->m_pSvcNext = sm_pSvcListHead; 805 pSvc->m_pSvcPrev = NULL; 842 806 843 807 if (sm_pSvcListHead) 844 808 { 845 sm_pSvcListHead->m_pSvcPrev = p svc;809 sm_pSvcListHead->m_pSvcPrev = pSvc; 846 810 } 847 811 else 848 812 { 849 sm_pSvcListTail = p svc;813 sm_pSvcListTail = pSvc; 850 814 } 851 815 852 sm_pSvcListHead = psvc; 853 854 #ifdef HGCMSS 816 sm_pSvcListHead = pSvc; 817 855 818 sm_cServices++; 856 #endif /* HGCMSS */ 857 858 LogFlow(("HGCMService::LoadService: service %p\n", psvc)); 819 820 /* Reference the service (for first time) until it is unloaded on HGCM termination. */ 821 AssertRelease (pSvc->m_u32RefCnt == 0); 822 pSvc->ReferenceService (); 823 824 LogFlowFunc(("service %p\n", pSvc)); 859 825 } 860 826 } 861 827 } 862 828 829 LogFlowFunc(("rc = %Vrc\n", rc)); 863 830 return rc; 864 831 } 865 832 833 /** The method unloads a service. 834 * 835 * @thread main HGCM 836 */ 837 void HGCMService::UnloadService (void) 838 { 839 LogFlowFunc(("name = %s\n", m_pszSvcName)); 840 841 /* Remove the service from the list. */ 842 if (m_pSvcNext) 843 { 844 m_pSvcNext->m_pSvcPrev = m_pSvcPrev; 845 } 846 else 847 { 848 sm_pSvcListTail = m_pSvcPrev; 849 } 850 851 if (m_pSvcPrev) 852 { 853 m_pSvcPrev->m_pSvcNext = m_pSvcNext; 854 } 855 else 856 { 857 sm_pSvcListHead = m_pSvcNext; 858 } 859 860 sm_cServices--; 861 862 /* The service must be unloaded only if all clients were disconnected. */ 863 LogFlowFunc(("m_u32RefCnt = %d\n", m_u32RefCnt)); 864 AssertRelease (m_u32RefCnt == 1); 865 866 /* Now the service can be released. */ 867 ReleaseService (); 868 } 869 870 /** The method unloads all services. 871 * 872 * @thread main HGCM 873 */ 874 /* static */ void HGCMService::UnloadAll (void) 875 { 876 while (sm_pSvcListHead) 877 { 878 sm_pSvcListHead->UnloadService (); 879 } 880 } 881 882 /** The method obtains a referenced pointer to the service with 883 * specified name. The caller must call ReleaseService when 884 * the pointer is no longer needed. 885 * 886 * @param ppSvc Where to store the pointer to the service. 887 * @param pszServiceName The name of the service. 888 * @return VBox rc. 889 * @thread main HGCM 890 */ 891 /* static */ int HGCMService::ResolveService (HGCMService **ppSvc, const char *pszServiceName) 892 { 893 LogFlowFunc(("ppSvc = %p name = %s\n", 894 ppSvc, pszServiceName)); 895 896 if (!ppSvc || !pszServiceName) 897 { 898 return VERR_INVALID_PARAMETER; 899 } 900 901 HGCMService *pSvc = sm_pSvcListHead; 902 903 while (pSvc) 904 { 905 if (strcmp (pSvc->m_pszSvcName, pszServiceName) == 0) 906 { 907 break; 908 } 909 910 pSvc = pSvc->m_pSvcNext; 911 } 912 913 LogFlowFunc(("lookup in the list is %p\n", pSvc)); 914 915 if (pSvc == NULL) 916 { 917 return VERR_HGCM_SERVICE_NOT_FOUND; 918 } 919 920 pSvc->ReferenceService (); 921 922 *ppSvc = pSvc; 923 924 return VINF_SUCCESS; 925 } 926 927 /** The method increases reference counter. 928 * 929 * @thread main HGCM 930 */ 931 void HGCMService::ReferenceService (void) 932 { 933 ASMAtomicIncU32 (&m_u32RefCnt); 934 LogFlowFunc(("m_u32RefCnt = %d\n", m_u32RefCnt)); 935 } 936 937 /** The method dereferences a service and deletes it when no more refs. 938 * 939 * @thread main HGCM 940 */ 941 void HGCMService::ReleaseService (void) 942 { 943 LogFlowFunc(("m_u32RefCnt = %d\n", m_u32RefCnt)); 944 uint32_t u32RefCnt = ASMAtomicDecU32 (&m_u32RefCnt); 945 AssertRelease(u32RefCnt != ~0U); 946 947 LogFlowFunc(("u32RefCnt = %d, name %s\n", u32RefCnt, m_pszSvcName)); 948 949 if (u32RefCnt == 0) 950 { 951 instanceDestroy (); 952 delete this; 953 } 954 } 955 956 /** The method is called when the VM is being reset or terminated 957 * and disconnects all clients from all services. 958 * 959 * @thread main HGCM 960 */ 866 961 /* static */ void HGCMService::Reset (void) 867 962 { 868 /* This is called when the VM is being reset,869 * that is no more requests from guest is expected.870 * Scan al services and disconnect all clients.871 */872 873 963 g_fResetting = true; 874 964 875 HGCMService *psvc = sm_pSvcListHead; 876 877 while (psvc) 878 { 879 psvc->DisconnectAll (); 880 881 psvc = psvc->m_pSvcNext; 882 } 883 965 HGCMService *pSvc = sm_pSvcListHead; 966 967 while (pSvc) 968 { 969 while (pSvc->m_cClients && pSvc->m_paClientIds) 970 { 971 LogFlowFunc(("handle %d\n", pSvc->m_paClientIds[0])); 972 pSvc->DisconnectClient (pSvc->m_paClientIds[0]); 973 } 974 975 pSvc = pSvc->m_pSvcNext; 976 } 977 884 978 g_fResetting = false; 885 979 } 886 980 887 #ifdef HGCMSS 981 /** The method saves the HGCM state. 982 * 983 * @param pSSM The saved state context. 984 * @return VBox rc. 985 * @thread main HGCM 986 */ 888 987 /* static */ int HGCMService::SaveState (PSSMHANDLE pSSM) 889 988 { … … 925 1024 for (i = 0; i < pSvc->m_cClients; i++) 926 1025 { 927 uint32_t u32ClientI D= pSvc->m_paClientIds[i];928 929 Log(("client id 0x%08X\n", u32ClientI D));1026 uint32_t u32ClientId = pSvc->m_paClientIds[i]; 1027 1028 Log(("client id 0x%08X\n", u32ClientId)); 930 1029 931 1030 /* Save the client id. */ 932 rc = SSMR3PutU32(pSSM, u32ClientI D);1031 rc = SSMR3PutU32(pSSM, u32ClientId); 933 1032 AssertRCReturn(rc, rc); 934 1033 935 1034 /* Call the service, so the operation is executed by the service thread. */ 936 rc = pSvc-> SaveState (u32ClientID, pSSM);1035 rc = pSvc->saveClientState (u32ClientId, pSSM); 937 1036 AssertRCReturn(rc, rc); 938 1037 } … … 944 1043 } 945 1044 1045 /** The method loads saved HGCM state. 1046 * 1047 * @param pSSM The saved state context. 1048 * @return VBox rc. 1049 * @thread main HGCM 1050 */ 946 1051 /* static */ int HGCMService::LoadState (PSSMHANDLE pSSM) 947 1052 { … … 978 1083 979 1084 /* Resolve the service instance. */ 980 HGCMService *pSvc = FindServiceByName (pszServiceName); 1085 HGCMService *pSvc; 1086 rc = ResolveService (&pSvc, pszServiceName); 981 1087 AssertReturn(pSvc, VERR_SSM_UNEXPECTED_DATA); 982 1088 … … 984 1090 uint32_t cClients; 985 1091 rc = SSMR3GetU32(pSSM, &cClients); 986 AssertRCReturn(rc, rc); 987 1092 if (VBOX_FAILURE(rc)) 1093 { 1094 pSvc->ReleaseService (); 1095 AssertFailed(); 1096 return rc; 1097 } 1098 988 1099 while (cClients--) 989 1100 { 990 1101 /* Get the client id. */ 991 uint32_t u32ClientID; 992 rc = SSMR3GetU32(pSSM, &u32ClientID); 993 AssertRCReturn(rc, rc); 1102 uint32_t u32ClientId; 1103 rc = SSMR3GetU32(pSSM, &u32ClientId); 1104 if (VBOX_FAILURE(rc)) 1105 { 1106 pSvc->ReleaseService (); 1107 AssertFailed(); 1108 return rc; 1109 } 994 1110 995 1111 /* Connect the client. */ 996 rc = pSvc->CreateAndConnectClient (NULL, u32ClientID); 997 AssertRCReturn(rc, rc); 1112 rc = pSvc->CreateAndConnectClient (NULL, u32ClientId); 1113 if (VBOX_FAILURE(rc)) 1114 { 1115 pSvc->ReleaseService (); 1116 AssertFailed(); 1117 return rc; 1118 } 998 1119 999 1120 /* Call the service, so the operation is executed by the service thread. */ 1000 rc = pSvc->LoadState (u32ClientID, pSSM); 1001 AssertRCReturn(rc, rc); 1002 } 1121 rc = pSvc->loadClientState (u32ClientId, pSSM); 1122 if (VBOX_FAILURE(rc)) 1123 { 1124 pSvc->ReleaseService (); 1125 AssertFailed(); 1126 return rc; 1127 } 1128 } 1129 1130 pSvc->ReleaseService (); 1003 1131 } 1004 1132 1005 1133 return VINF_SUCCESS; 1006 1134 } 1007 #endif /* HGCMSS */ 1008 1009 void HGCMService::ReleaseService (void) 1010 { 1011 uint32_t u32RefCnt = ASMAtomicDecU32 (&m_u32RefCnt); 1012 1013 AssertRelease(u32RefCnt != ~0U); 1014 1015 if (u32RefCnt == 0) 1016 { 1017 /** @todo We do not unload services. Cache them all. Unloading will be later. HGCMObject! */ 1018 1019 LogFlow(("HGCMService::ReleaseService: no more references.\n")); 1020 1021 // InstanceDestroy (); 1022 1023 // delete this; 1024 } 1025 } 1026 1027 /** Helper function to load a local service DLL. 1028 * 1029 * @return VBox code 1030 */ 1031 int HGCMService::loadServiceDLL (void) 1032 { 1033 LogFlow(("HGCMService::loadServiceDLL: m_pszSvcLibrary = %s\n", m_pszSvcLibrary)); 1034 1035 if (m_pszSvcLibrary == NULL) 1036 { 1037 return VERR_INVALID_PARAMETER; 1038 } 1039 1040 int rc = VINF_SUCCESS; 1041 1042 rc = RTLdrLoad (m_pszSvcLibrary, &m_hLdrMod); 1043 1044 if (VBOX_SUCCESS(rc)) 1045 { 1046 LogFlow(("HGCMService::loadServiceDLL: successfully loaded the library.\n")); 1047 1048 m_pfnLoad = NULL; 1049 1050 rc = RTLdrGetSymbol (m_hLdrMod, VBOX_HGCM_SVCLOAD_NAME, (void**)&m_pfnLoad); 1051 1052 if (VBOX_FAILURE (rc) || !m_pfnLoad) 1053 { 1054 Log(("HGCMService::loadServiceDLL: Error resolving the service entry point %s, rc = %d, m_pfnLoad = %p\n", VBOX_HGCM_SVCLOAD_NAME, rc, m_pfnLoad)); 1055 1056 if (VBOX_SUCCESS(rc)) 1057 { 1058 /* m_pfnLoad was NULL */ 1059 rc = VERR_SYMBOL_NOT_FOUND; 1060 } 1061 } 1062 1063 if (VBOX_SUCCESS(rc)) 1064 { 1065 memset (&m_fntable, 0, sizeof (m_fntable)); 1066 1067 m_fntable.cbSize = sizeof (m_fntable); 1068 m_fntable.u32Version = VBOX_HGCM_SVC_VERSION; 1069 m_fntable.pHelpers = &m_svcHelpers; 1070 1071 rc = m_pfnLoad (&m_fntable); 1072 1073 LogFlow(("HGCMService::loadServiceDLL: m_pfnLoad rc = %Vrc\n", rc)); 1074 1075 if (VBOX_SUCCESS (rc)) 1076 { 1077 if ( m_fntable.pfnUnload == NULL 1078 || m_fntable.pfnConnect == NULL 1079 || m_fntable.pfnDisconnect == NULL 1080 || m_fntable.pfnCall == NULL 1081 ) 1082 { 1083 Log(("HGCMService::loadServiceDLL: at least one of function pointers is NULL\n")); 1084 1085 rc = VERR_INVALID_PARAMETER; 1086 1087 if (m_fntable.pfnUnload) 1088 { 1089 m_fntable.pfnUnload (); 1090 } 1091 } 1092 } 1093 } 1094 } 1095 else 1096 { 1097 LogFlow(("HGCMService::loadServiceDLL: failed to load service library. The service is not available.\n")); 1098 m_hLdrMod = NIL_RTLDRMOD; 1099 } 1100 1101 if (VBOX_FAILURE(rc)) 1102 { 1103 unloadServiceDLL (); 1104 } 1105 1106 return rc; 1107 } 1108 1109 /** Helper function to free a local service DLL. 1110 * 1111 * @return VBox code 1112 */ 1113 void HGCMService::unloadServiceDLL (void) 1114 { 1115 if (m_hLdrMod) 1116 { 1117 RTLdrClose (m_hLdrMod); 1118 } 1119 1120 memset (&m_fntable, 0, sizeof (m_fntable)); 1121 m_pfnLoad = NULL; 1122 m_hLdrMod = NIL_RTLDRMOD; 1123 } 1124 1125 #ifdef HGCMSS 1135 1126 1136 /* Create a new client instance and connect it to the service. 1127 1137 * … … 1129 1139 * If NULL, use the given 'u32ClientIdIn' handle. 1130 1140 * @param u32ClientIdIn The handle for the client, when 'pu32ClientIdOut' is NULL. 1131 * 1141 * @return VBox rc. 1132 1142 */ 1133 1143 int HGCMService::CreateAndConnectClient (uint32_t *pu32ClientIdOut, uint32_t u32ClientIdIn) 1134 1144 { 1135 /* Allocate a client information structure */ 1145 LogFlowFunc(("pu32ClientIdOut = %p, u32ClientIdIn = %d", pu32ClientIdOut, u32ClientIdIn)); 1146 1147 /* Allocate a client information structure. */ 1136 1148 HGCMClient *pClient = new HGCMClient (); 1137 1149 … … 1153 1165 } 1154 1166 1167 LogFlowFunc(("client id = %d\n", handle)); 1168 1155 1169 AssertRelease(handle); 1156 1170 1171 /* Initialize the HGCM part of the client. */ 1157 1172 int rc = pClient->Init (this); 1158 1173 1159 1174 if (VBOX_SUCCESS(rc)) 1160 1175 { 1161 rc = Connect (handle); 1176 /* Call the service. */ 1177 HGCMMSGHANDLE hMsg; 1178 1179 rc = hgcmMsgAlloc (m_thread, &hMsg, SVC_MSG_CONNECT, hgcmMessageAllocSvc); 1180 1181 if (VBOX_SUCCESS(rc)) 1182 { 1183 HGCMMsgSvcConnect *pMsg = (HGCMMsgSvcConnect *)hgcmObjReference (hMsg, HGCMOBJ_MSG); 1184 AssertRelease(pMsg); 1185 1186 pMsg->u32ClientId = handle; 1187 1188 hgcmObjDereference (pMsg); 1189 1190 rc = hgcmMsgSend (hMsg); 1191 1192 if (VBOX_SUCCESS (rc)) 1193 { 1194 /* Add the client Id to the array. */ 1195 if (m_cClients == m_cClientsAllocated) 1196 { 1197 m_paClientIds = (uint32_t *)RTMemRealloc (m_paClientIds, (m_cClientsAllocated + 64) * sizeof (m_paClientIds[0])); 1198 Assert(m_paClientIds); 1199 m_cClientsAllocated += 64; 1200 } 1201 1202 m_paClientIds[m_cClients] = handle; 1203 m_cClients++; 1204 } 1205 } 1162 1206 } 1163 1207 … … 1172 1216 *pu32ClientIdOut = handle; 1173 1217 } 1218 1219 ReferenceService (); 1174 1220 } 1175 1221 1222 LogFlowFunc(("rc = %Vrc\n", rc)); 1176 1223 return rc; 1177 1224 } 1178 #endif /* HGCMSS */ 1179 1180 int HGCMService::Connect (uint32_t u32ClientID) 1181 { 1225 1226 /* Disconnect the client from the service and delete the client handle. 1227 * 1228 * @param u32ClientId The handle of the client. 1229 * @return VBox rc. 1230 */ 1231 int HGCMService::DisconnectClient (uint32_t u32ClientId) 1232 { 1233 LogFlowFunc(("client id = %d\n", u32ClientId)); 1234 1235 /* Call the service. */ 1182 1236 HGCMMSGHANDLE hMsg; 1183 1237 1184 LogFlow(("MAIN::HGCMService::Connect: client id = %d\n", u32ClientID)); 1185 1186 int rc = hgcmMsgAlloc (m_thread, &hMsg, HGCMMSGID_SVC_CONNECT, hgcmMessageAlloc); 1238 int rc = hgcmMsgAlloc (m_thread, &hMsg, SVC_MSG_DISCONNECT, hgcmMessageAllocSvc); 1187 1239 1188 1240 if (VBOX_SUCCESS(rc)) 1189 1241 { 1190 HGCMMsgSvcConnect *pMsg = (HGCMMsgSvcConnect *)hgcmObjReference (hMsg, HGCMOBJ_MSG); 1191 1242 HGCMMsgSvcDisconnect *pMsg = (HGCMMsgSvcDisconnect *)hgcmObjReference (hMsg, HGCMOBJ_MSG); 1192 1243 AssertRelease(pMsg); 1193 1244 1194 pMsg->u32ClientI D = u32ClientID;1245 pMsg->u32ClientId = u32ClientId; 1195 1246 1196 1247 hgcmObjDereference (pMsg); … … 1198 1249 rc = hgcmMsgSend (hMsg); 1199 1250 1200 if (VBOX_SUCCESS (rc)) 1201 { 1202 /* Add the client Id to the array. */ 1203 if (m_cClients == m_cClientsAllocated) 1204 { 1205 m_paClientIds = (uint32_t *)RTMemRealloc (m_paClientIds, (m_cClientsAllocated + 64) * sizeof (m_paClientIds[0])); 1206 Assert(m_paClientIds); 1207 } 1208 1209 m_paClientIds[m_cClients] = u32ClientID; 1210 m_cClients++; 1211 } 1212 } 1213 else 1214 { 1215 Log(("MAIN::HGCMService::Connect: Message allocation failed: %Vrc\n", rc)); 1216 } 1217 1218 return rc; 1219 } 1220 1221 int HGCMService::Disconnect (uint32_t u32ClientID) 1222 { 1223 int rc = VINF_SUCCESS; 1224 1225 LogFlow(("MAIN::HGCMService::Disconnect: client id = %d\n", u32ClientID)); 1226 1227 HGCMMSGHANDLE hMsg; 1228 1229 rc = hgcmMsgAlloc (m_thread, &hMsg, HGCMMSGID_SVC_DISCONNECT, hgcmMessageAlloc); 1230 1231 if (VBOX_SUCCESS(rc)) 1232 { 1233 HGCMMsgSvcDisconnect *pMsg = (HGCMMsgSvcDisconnect *)hgcmObjReference (hMsg, HGCMOBJ_MSG); 1234 1235 AssertRelease(pMsg); 1236 1237 pMsg->u32ClientID = u32ClientID; 1238 1239 hgcmObjDereference (pMsg); 1240 1241 rc = hgcmMsgSend (hMsg); 1242 1243 /* Remove the client id from the array. */ 1251 /* Remove the client id from the array in any case. */ 1244 1252 int i; 1253 1245 1254 for (i = 0; i < m_cClients; i++) 1246 1255 { 1247 if (m_paClientIds[i] == u32ClientI D)1256 if (m_paClientIds[i] == u32ClientId) 1248 1257 { 1249 1258 m_cClients--; … … 1257 1266 } 1258 1267 } 1259 } 1260 else 1261 { 1262 Log(("MAIN::HGCMService::Disconnect: Message allocation failed: %Vrc\n", rc)); 1263 } 1264 1268 1269 /* Delete the client handle. */ 1270 hgcmObjDeleteHandle (u32ClientId); 1271 1272 /* The service must be released. */ 1273 ReleaseService (); 1274 } 1275 1276 LogFlowFunc(("rc = %Vrc\n", rc)); 1265 1277 return rc; 1266 1278 } 1267 1279 1268 void HGCMService::DisconnectAll (void) 1269 { 1270 while (m_cClients && m_paClientIds) 1271 { 1272 Log(("MAIN::HGCMService::DisconnectAll: id %d\n", m_paClientIds[0])); 1273 Disconnect (m_paClientIds[0]); 1274 } 1275 } 1276 1277 /* Forward the call request to the dedicated service thread. 1278 */ 1279 int HGCMService::GuestCall (PPDMIHGCMPORT pHGCMPort, PVBOXHGCMCMD pCmd, uint32_t u32ClientID, uint32_t u32Function, uint32_t cParms, VBOXHGCMSVCPARM paParms[], bool fBlock) 1280 /* Perform a host call the service. 1281 * 1282 * @param pHGCMPort The port to be used for completion confirmation. 1283 * @param pCmd The VBox HGCM context. 1284 * @param u32ClientId The client handle to be disconnected and deleted. 1285 * @param u32Function The function number. 1286 * @param cParms Number of parameters. 1287 * @param paParms Pointer to array of parameters. 1288 * @return VBox rc. 1289 */ 1290 int HGCMService::GuestCall (PPDMIHGCMPORT pHGCMPort, PVBOXHGCMCMD pCmd, uint32_t u32ClientId, uint32_t u32Function, uint32_t cParms, VBOXHGCMSVCPARM paParms[]) 1280 1291 { 1281 1292 HGCMMSGHANDLE hMsg = 0; … … 1283 1294 LogFlow(("MAIN::HGCMService::Call\n")); 1284 1295 1285 int rc = hgcmMsgAlloc (m_thread, &hMsg, HGCMMSGID_GUESTCALL, hgcmMessageAlloc);1296 int rc = hgcmMsgAlloc (m_thread, &hMsg, SVC_MSG_GUESTCALL, hgcmMessageAllocSvc); 1286 1297 1287 1298 if (VBOX_SUCCESS(rc)) … … 1294 1305 pMsg->pHGCMPort = pHGCMPort; 1295 1306 1296 pMsg->u32ClientI D = u32ClientID;1297 pMsg->u32Function 1298 pMsg->cParms 1299 pMsg->paParms = paParms;1307 pMsg->u32ClientId = u32ClientId; 1308 pMsg->u32Function = u32Function; 1309 pMsg->cParms = cParms; 1310 pMsg->paParms = paParms; 1300 1311 1301 1312 hgcmObjDereference (pMsg); 1302 1313 1303 if (fBlock) 1304 rc = hgcmMsgSend (hMsg); 1305 else 1306 rc = hgcmMsgPost (hMsg, hgcmMsgCompletionCallback); 1307 1308 if (!fBlock && VBOX_SUCCESS(rc)) 1309 { 1310 rc = VINF_HGCM_ASYNC_EXECUTE; 1311 } 1314 rc = hgcmMsgPost (hMsg, hgcmMsgCompletionCallback); 1312 1315 } 1313 1316 else … … 1319 1322 } 1320 1323 1321 /* Forward the call request to the dedicated service thread. 1322 */ 1323 int HGCMService::HostCall (PVBOXHGCMCMD pCmd, uint32_t u32ClientID, uint32_t u32Function, uint32_t cParms, VBOXHGCMSVCPARM paParms[]) 1324 { 1324 /* Perform a host call the service. 1325 * 1326 * @param u32Function The function number. 1327 * @param cParms Number of parameters. 1328 * @param paParms Pointer to array of parameters. 1329 * @return VBox rc. 1330 */ 1331 int HGCMService::HostCall (uint32_t u32Function, uint32_t cParms, VBOXHGCMSVCPARM *paParms) 1332 { 1333 LogFlowFunc(("%s u32Function = %d, cParms = %d, paParms = %p\n", 1334 m_pszSvcName, u32Function, cParms, paParms)); 1335 1325 1336 HGCMMSGHANDLE hMsg = 0; 1326 1327 LogFlow(("MAIN::HGCMService::HostCall %s\n", m_pszSvcName)); 1328 1329 int rc = hgcmMsgAlloc (m_thread, &hMsg, HGCMMSGID_HOSTCALL, hgcmMessageAlloc); 1337 int rc = hgcmMsgAlloc (m_thread, &hMsg, SVC_MSG_HOSTCALL, hgcmMessageAllocSvc); 1330 1338 1331 1339 if (VBOX_SUCCESS(rc)) 1332 1340 { 1333 HGCMMsgHostCall *pMsg = (HGCMMsgHostCall *)hgcmObjReference (hMsg, HGCMOBJ_MSG); 1334 1341 HGCMMsgHostCallSvc *pMsg = (HGCMMsgHostCallSvc *)hgcmObjReference (hMsg, HGCMOBJ_MSG); 1335 1342 AssertRelease(pMsg); 1336 1337 pMsg->pCmd = NULL; /* Not used for host calls. */1338 pMsg->pHGCMPort = NULL; /* Not used for host calls. */1339 1343 1340 1344 pMsg->u32Function = u32Function; … … 1346 1350 rc = hgcmMsgSend (hMsg); 1347 1351 } 1348 else 1349 { 1350 Log(("MAIN::HGCMService::Call: Message allocation failed: %Vrc\n", rc)); 1351 } 1352 1352 1353 LogFlowFunc(("rc = %Vrc\n", rc)); 1353 1354 return rc; 1354 1355 } 1355 1356 1356 int HGCMService::SaveState(uint32_t u32ClientID, PSSMHANDLE pSSM) 1357 { 1358 HGCMMSGHANDLE hMsg = 0; 1359 1360 LogFlow(("MAIN::HGCMService::SaveState %s\n", m_pszSvcName)); 1361 1362 int rc = hgcmMsgAlloc (m_thread, &hMsg, HGCMMSGID_SAVESTATE, hgcmMessageAlloc); 1363 1364 if (VBOX_SUCCESS(rc)) 1365 { 1366 HGCMMsgLoadSaveState *pMsg = (HGCMMsgLoadSaveState *)hgcmObjReference (hMsg, HGCMOBJ_MSG); 1367 1368 AssertRelease(pMsg); 1369 1370 pMsg->u32ClientID = u32ClientID; 1371 pMsg->pSSM = pSSM; 1372 1373 hgcmObjDereference (pMsg); 1374 1375 rc = hgcmMsgSend (hMsg); 1376 } 1377 else 1378 { 1379 Log(("MAIN::HGCMService::SaveState: Message allocation failed: %Vrc\n", rc)); 1380 } 1381 1382 return rc; 1383 } 1384 1385 int HGCMService::LoadState (uint32_t u32ClientID, PSSMHANDLE pSSM) 1386 { 1387 HGCMMSGHANDLE hMsg = 0; 1388 1389 LogFlow(("MAIN::HGCMService::LoadState %s\n", m_pszSvcName)); 1390 1391 int rc = hgcmMsgAlloc (m_thread, &hMsg, HGCMMSGID_LOADSTATE, hgcmMessageAlloc); 1392 1393 if (VBOX_SUCCESS(rc)) 1394 { 1395 HGCMMsgLoadSaveState *pMsg = (HGCMMsgLoadSaveState *)hgcmObjReference (hMsg, HGCMOBJ_MSG); 1396 1397 AssertRelease(pMsg); 1398 1399 pMsg->u32ClientID = u32ClientID; 1400 pMsg->pSSM = pSSM; 1401 1402 hgcmObjDereference (pMsg); 1403 1404 rc = hgcmMsgSend (hMsg); 1405 } 1406 else 1407 { 1408 Log(("MAIN::HGCMService::LoadState: Message allocation failed: %Vrc\n", rc)); 1409 } 1410 1411 return rc; 1412 } 1413 1414 /* Main HGCM thread that processes CONNECT/DISCONNECT requests. */ 1357 1358 /* 1359 * Main HGCM thread that manages services. 1360 */ 1361 1362 /* Messages processed by the main HGCM thread. */ 1363 #define HGCM_MSG_CONNECT (10) /* Connect a client to a service. */ 1364 #define HGCM_MSG_DISCONNECT (11) /* Disconnect the specified client id. */ 1365 #define HGCM_MSG_LOAD (12) /* Load the service. */ 1366 #define HGCM_MSG_HOSTCALL (13) /* Call the service. */ 1367 #define HGCM_MSG_LOADSTATE (14) /* Load saved state for the specified service. */ 1368 #define HGCM_MSG_SAVESTATE (15) /* Save state for the specified service. */ 1369 #define HGCM_MSG_RESET (16) /* Disconnect all clients from the specified service. */ 1370 #define HGCM_MSG_QUIT (17) /* Unload all services and terminate the thread. */ 1371 1372 class HGCMMsgMainConnect: public HGCMMsgHeader 1373 { 1374 public: 1375 /* Service name. */ 1376 const char *pszServiceName; 1377 /* Where to store the client handle. */ 1378 uint32_t *pu32ClientId; 1379 }; 1380 1381 class HGCMMsgMainDisconnect: public HGCMMsgHeader 1382 { 1383 public: 1384 /* Handle of the client to be disconnected. */ 1385 uint32_t u32ClientId; 1386 }; 1387 1388 class HGCMMsgMainLoad: public HGCMMsgCore 1389 { 1390 public: 1391 /* Name of the library to be loaded. */ 1392 const char *pszServiceLibrary; 1393 /* Name to be assigned to the service. */ 1394 const char *pszServiceName; 1395 }; 1396 1397 class HGCMMsgMainHostCall: public HGCMMsgCore 1398 { 1399 public: 1400 /* Which service to call. */ 1401 const char *pszServiceName; 1402 /* Function number. */ 1403 uint32_t u32Function; 1404 /* Number of the function parameters. */ 1405 uint32_t cParms; 1406 /* Pointer to array of the function parameters. */ 1407 VBOXHGCMSVCPARM *paParms; 1408 }; 1409 1410 class HGCMMsgMainLoadSaveState: public HGCMMsgCore 1411 { 1412 public: 1413 /* SSM context. */ 1414 PSSMHANDLE pSSM; 1415 }; 1416 1417 class HGCMMsgMainReset: public HGCMMsgCore 1418 { 1419 }; 1420 1421 class HGCMMsgMainQuit: public HGCMMsgCore 1422 { 1423 }; 1424 1425 static HGCMMsgCore *hgcmMainMessageAlloc (uint32_t u32MsgId) 1426 { 1427 switch (u32MsgId) 1428 { 1429 case HGCM_MSG_CONNECT: return new HGCMMsgMainConnect (); 1430 case HGCM_MSG_DISCONNECT: return new HGCMMsgMainDisconnect (); 1431 case HGCM_MSG_LOAD: return new HGCMMsgMainLoad (); 1432 case HGCM_MSG_HOSTCALL: return new HGCMMsgMainHostCall (); 1433 case HGCM_MSG_LOADSTATE: 1434 case HGCM_MSG_SAVESTATE: return new HGCMMsgMainLoadSaveState (); 1435 case HGCM_MSG_RESET: return new HGCMMsgMainReset (); 1436 case HGCM_MSG_QUIT: return new HGCMMsgMainQuit (); 1437 default: 1438 AssertReleaseMsgFailed(("Msg id = %08X\n", u32MsgId)); 1439 } 1440 1441 return NULL; 1442 } 1443 1444 1445 /* The main HGCM thread handler. */ 1415 1446 static DECLCALLBACK(void) hgcmThread (HGCMTHREADHANDLE ThreadHandle, void *pvUser) 1416 1447 { 1448 LogFlowFunc(("ThreadHandle = %p, pvUser = %p\n", 1449 ThreadHandle, pvUser)); 1450 1417 1451 NOREF(pvUser); 1418 1452 1419 int rc = VINF_SUCCESS; 1420 1421 HGCMMsgCore *pMsgCore = NULL; 1422 1423 for (;;) 1424 { 1425 LogFlow(("hgcmThread: Going to get a message\n")); 1426 1427 rc = hgcmMsgGet (ThreadHandle, &pMsgCore); 1453 bool fQuit = false; 1454 1455 while (!fQuit) 1456 { 1457 HGCMMsgCore *pMsgCore; 1458 int rc = hgcmMsgGet (ThreadHandle, &pMsgCore); 1428 1459 1429 1460 if (VBOX_FAILURE (rc)) 1430 1461 { 1431 Log(("hgcmThread: message get failed, rc = %Vrc\n"));1432 RTThreadSleep(100);1433 continue;1462 /* The error means some serious unrecoverable problem in the hgcmMsg/hgcmThread layer. */ 1463 AssertMsgFailed (("%Vrc\n", rc)); 1464 break; 1434 1465 } 1435 1466 … … 1438 1469 switch (u32MsgId) 1439 1470 { 1440 case HGCMMSGID_CONNECT: 1441 { 1442 LogFlow(("HGCMMSGID_CONNECT\n")); 1443 1444 HGCMMsgConnect *pMsg = (HGCMMsgConnect *)pMsgCore; 1445 1446 /* Search if the service exists. 1447 * Create an information structure for the client. 1448 * Inform the service about the client. 1449 * Generate and return the client id. 1471 case HGCM_MSG_CONNECT: 1472 { 1473 HGCMMsgMainConnect *pMsg = (HGCMMsgMainConnect *)pMsgCore; 1474 1475 LogFlowFunc(("HGCM_MSG_CONNECT pszServiceName %s, pu32ClientId %p\n", 1476 pMsg->pszServiceName, pMsg->pu32ClientId)); 1477 1478 /* Resolve the service name to the pointer to service instance. 1450 1479 */ 1451 1452 Log(("MAIN::hgcmThread:HGCMMSGID_CONNECT: location type = %d\n", pMsg->pLoc->type)); 1453 1454 HGCMService *pService = NULL; 1455 1456 rc = HGCMService::FindService (&pService, pMsg->pLoc); 1480 HGCMService *pService; 1481 rc = HGCMService::ResolveService (&pService, pMsg->pszServiceName); 1457 1482 1458 1483 if (VBOX_SUCCESS (rc)) 1459 1484 { 1460 #ifdef HGCMSS 1461 rc = pService->CreateAndConnectClient (pMsg->pu32ClientID, 0); 1462 #else 1463 /* Allocate a client information structure */ 1464 1465 HGCMClient *pClient = new HGCMClient (); 1466 1467 if (!pClient) 1468 { 1469 Log(("hgcmConnect::Could not allocate HGCMClient\n")); 1470 rc = VERR_NO_MEMORY; 1471 } 1472 else 1473 { 1474 uint32_t handle = hgcmObjGenerateHandle (pClient); 1475 1476 AssertRelease(handle); 1477 1478 rc = pClient->Init (pService); 1479 1480 if (VBOX_SUCCESS(rc)) 1481 { 1482 rc = pService->Connect (handle); 1483 } 1484 1485 if (VBOX_FAILURE(rc)) 1486 { 1487 hgcmObjDeleteHandle (handle); 1488 } 1489 else 1490 { 1491 *pMsg->pu32ClientID = handle; 1492 } 1493 } 1494 #endif /* HGCMSS */ 1485 /* Call the service instance method. */ 1486 rc = pService->CreateAndConnectClient (pMsg->pu32ClientId, 0); 1487 1488 /* Release the service after resolve. */ 1489 pService->ReleaseService (); 1495 1490 } 1496 1497 if (VBOX_FAILURE(rc))1498 {1499 LogFlow(("HGCMMSGID_CONNECT: FAILURE rc = %Vrc\n", rc));1500 1501 if (pService)1502 {1503 pService->ReleaseService ();1504 }1505 }1506 1507 1491 } break; 1508 1492 1509 case HGCMMSGID_DISCONNECT: 1510 { 1511 LogFlow(("HGCMMSGID_DISCONNECT\n")); 1512 1513 HGCMMsgDisconnect *pMsg = (HGCMMsgDisconnect *)pMsgCore; 1514 1515 Log(("MAIN::hgcmThread:HGCMMSGID_DISCONNECT: client id = %d\n", pMsg->u32ClientID)); 1516 1517 /* Forward call to the service dedicated HGCM thread. */ 1518 HGCMClient *pClient = (HGCMClient *)hgcmObjReference (pMsg->u32ClientID, HGCMOBJ_CLIENT); 1493 case HGCM_MSG_DISCONNECT: 1494 { 1495 HGCMMsgMainDisconnect *pMsg = (HGCMMsgMainDisconnect *)pMsgCore; 1496 1497 LogFlowFunc(("HGCM_MSG_DISCONNECT u32ClientId = %d\n", 1498 pMsg->u32ClientId)); 1499 1500 HGCMClient *pClient = (HGCMClient *)hgcmObjReference (pMsg->u32ClientId, HGCMOBJ_CLIENT); 1519 1501 1520 1502 if (!pClient) 1521 1503 { 1522 Log(("MAIN::hgcmThread:HGCMMSGID_DISCONNECT: FAILURE resolving client id\n"));1523 rc = VERR_INVALID_PARAMETER;1504 rc = VERR_HGCM_INVALID_CLIENT_ID; 1505 break; 1524 1506 } 1525 else 1507 1508 /* The service the client belongs to. */ 1509 HGCMService *pService = pClient->pService; 1510 1511 /* Call the service instance to disconnect the client. */ 1512 rc = pService->DisconnectClient (pMsg->u32ClientId); 1513 1514 hgcmObjDereference (pClient); 1515 } break; 1516 1517 case HGCM_MSG_LOAD: 1518 { 1519 HGCMMsgMainLoad *pMsg = (HGCMMsgMainLoad *)pMsgCore; 1520 1521 LogFlowFunc(("HGCM_MSG_LOAD pszServiceName = %s, pMsg->pszServiceLibrary = %s\n", 1522 pMsg->pszServiceName, pMsg->pszServiceLibrary)); 1523 1524 rc = HGCMService::LoadService (pMsg->pszServiceName, pMsg->pszServiceLibrary); 1525 } break; 1526 1527 case HGCM_MSG_HOSTCALL: 1528 { 1529 HGCMMsgMainHostCall *pMsg = (HGCMMsgMainHostCall *)pMsgCore; 1530 1531 LogFlowFunc(("HGCM_MSG_HOSTCALL pszServiceName %s, u32Function %d, cParms %d, paParms %p\n", 1532 pMsg->pszServiceName, pMsg->u32Function, pMsg->cParms, pMsg->paParms)); 1533 1534 /* Resolve the service name to the pointer to service instance. */ 1535 HGCMService *pService; 1536 rc = HGCMService::ResolveService (&pService, pMsg->pszServiceName); 1537 1538 if (VBOX_SUCCESS (rc)) 1526 1539 { 1527 rc = pClient->pService->Disconnect (pMsg->u32ClientID); 1528 1529 pClient->pService->ReleaseService (); 1530 1531 hgcmObjDereference (pClient); 1532 1533 hgcmObjDeleteHandle (pMsg->u32ClientID); 1534 } 1535 1536 } break; 1537 1538 case HGCMMSGID_LOAD: 1539 { 1540 LogFlow(("HGCMMSGID_LOAD\n")); 1541 1542 HGCMMsgLoad *pMsg = (HGCMMsgLoad *)pMsgCore; 1543 1544 rc = HGCMService::LoadService (pMsg->pszServiceName, pMsg->pszServiceLibrary, pMsg->pHGCMPort); 1545 } break; 1546 1547 case HGCMMSGID_HOSTCALL: 1548 { 1549 LogFlow(("HGCMMSGID_HOSTCALL at hgcmThread\n")); 1550 1551 HGCMMsgHostCall *pMsg = (HGCMMsgHostCall *)pMsgCore; 1552 1553 HGCMService *pService = HGCMService::FindServiceByName (pMsg->pszServiceName); 1554 1555 if (pService) 1556 { 1557 LogFlow(("HGCMMSGID_HOSTCALL found service, forwarding the call.\n")); 1558 pService->HostCall (NULL, 0, pMsg->u32Function, pMsg->cParms, pMsg->paParms); 1540 rc = pService->HostCall (pMsg->u32Function, pMsg->cParms, pMsg->paParms); 1541 1542 pService->ReleaseService (); 1559 1543 } 1560 1544 } break; 1561 1545 1562 case HGCMMSGID_RESET: 1563 { 1564 LogFlow(("HGCMMSGID_RESET\n")); 1565 1566 /* HGCMMsgReset *pMsg = (HGCMMsgReset *)pMsgCore; */ 1546 case HGCM_MSG_RESET: 1547 { 1548 LogFlowFunc(("HGCM_MSG_RESET\n")); 1567 1549 1568 1550 HGCMService::Reset (); 1569 1551 } break; 1570 1552 1571 #ifdef HGCMSS 1572 case HGCMMSGID_LOADSTATE: 1573 { 1574 LogFlow(("HGCMMSGID_LOADSTATE\n")); 1575 1576 HGCMMsgLoadSaveState *pMsg = (HGCMMsgLoadSaveState *)pMsgCore; 1553 case HGCM_MSG_LOADSTATE: 1554 { 1555 HGCMMsgMainLoadSaveState *pMsg = (HGCMMsgMainLoadSaveState *)pMsgCore; 1556 1557 LogFlowFunc(("HGCM_MSG_LOADSTATE\n")); 1577 1558 1578 1559 rc = HGCMService::LoadState (pMsg->pSSM); 1579 1560 } break; 1580 1561 1581 case HGCM MSGID_SAVESTATE:1582 { 1583 LogFlow(("HGCMMSGID_SAVESTATE\n"));1584 1585 HGCMMsgLoadSaveState *pMsg = (HGCMMsgLoadSaveState *)pMsgCore;1562 case HGCM_MSG_SAVESTATE: 1563 { 1564 HGCMMsgMainLoadSaveState *pMsg = (HGCMMsgMainLoadSaveState *)pMsgCore; 1565 1566 LogFlowFunc(("HGCM_MSG_SAVESTATE\n")); 1586 1567 1587 1568 rc = HGCMService::SaveState (pMsg->pSSM); 1588 1569 } break; 1589 #endif /* HGCMSS */ 1590 1570 1571 case HGCM_MSG_QUIT: 1572 { 1573 LogFlowFunc(("HGCM_MSG_QUIT\n")); 1574 1575 HGCMService::UnloadAll (); 1576 1577 fQuit = true; 1578 } break; 1579 1591 1580 default: 1592 1581 { 1593 Log(("hgcmThread: Unsupported message number %08X!!!\n", u32MsgId));1582 AssertMsgFailed(("hgcmThread: Unsupported message number %08X!!!\n", u32MsgId)); 1594 1583 rc = VERR_NOT_SUPPORTED; 1595 1584 } break; 1596 1585 } 1597 1586 1587 /* Complete the message processing. */ 1598 1588 hgcmMsgComplete (pMsgCore, rc); 1599 } 1600 1601 return; 1602 } 1603 1589 1590 LogFlowFunc(("message processed %Vrc\n", rc)); 1591 } 1592 } 1593 1594 1595 /* 1596 * The HGCM API. 1597 */ 1598 1599 /* The main hgcm thread. */ 1604 1600 static HGCMTHREADHANDLE g_hgcmThread = 0; 1605 1601 1606 1602 /* 1607 * Find a service and inform it about a client connection. 1608 * Main HGCM thread will process this request for serialization. 1609 */ 1610 int hgcmConnectInternal (PPDMIHGCMPORT pHGCMPort, PVBOXHGCMCMD pCmd, PHGCMSERVICELOCATION pLoc, uint32_t *pu32ClientID, bool fBlock) 1611 { 1612 int rc = VINF_SUCCESS; 1613 1614 LogFlow(("MAIN::hgcmConnectInternal: pHGCMPort = %p, pCmd = %p, loc = %p, pu32ClientID = %p\n", 1615 pHGCMPort, pCmd, pLoc, pu32ClientID)); 1616 1617 if (!pHGCMPort || !pCmd || !pLoc || !pu32ClientID) 1603 * Public HGCM functions. 1604 * 1605 * hgcmGuest* - called as a result of the guest HGCM requests. 1606 * hgcmHost* - called by the host. 1607 */ 1608 1609 /* Load a HGCM service from the specified library. 1610 * Assign the specified name to the service. 1611 * 1612 * @param pszServiceName The name to be assigned to the service. 1613 * @param pszServiceLibrary The library to be loaded. 1614 * @return VBox rc. 1615 */ 1616 int HGCMHostLoad (const char *pszServiceName, 1617 const char *pszServiceLibrary) 1618 { 1619 LogFlowFunc(("name = %s, lib = %s\n", pszServiceName, pszServiceLibrary)); 1620 1621 if (!pszServiceName || !pszServiceLibrary) 1618 1622 { 1619 1623 return VERR_INVALID_PARAMETER; 1620 1624 } 1621 1625 1626 /* Forward the request to the main hgcm thread. */ 1622 1627 HGCMMSGHANDLE hMsg = 0; 1623 1628 1624 rc = hgcmMsgAlloc (g_hgcmThread, &hMsg, HGCMMSGID_CONNECT, hgcmMessageAlloc);1629 int rc = hgcmMsgAlloc (g_hgcmThread, &hMsg, HGCM_MSG_LOAD, hgcmMainMessageAlloc); 1625 1630 1626 1631 if (VBOX_SUCCESS(rc)) 1627 1632 { 1628 HGCMMsgConnect *pMsg = (HGCMMsgConnect *)hgcmObjReference (hMsg, HGCMOBJ_MSG);1629 1633 /* Initialize the message. Since the message is synchronous, use the supplied pointers. */ 1634 HGCMMsgMainLoad *pMsg = (HGCMMsgMainLoad *)hgcmObjReference (hMsg, HGCMOBJ_MSG); 1630 1635 AssertRelease(pMsg); 1631 1636 1632 pMsg->pCmd = pCmd; 1633 pMsg->pHGCMPort = pHGCMPort; 1634 1635 pMsg->pLoc = pLoc; 1636 pMsg->pu32ClientID = pu32ClientID; 1637 1638 if (fBlock) 1639 rc = hgcmMsgSend (hMsg); 1640 else 1641 rc = hgcmMsgPost (hMsg, hgcmMsgCompletionCallback); 1637 pMsg->pszServiceName = pszServiceName; 1638 pMsg->pszServiceLibrary = pszServiceLibrary; 1642 1639 1643 1640 hgcmObjDereference (pMsg); 1644 1641 1645 LogFlow(("MAIN::hgcmConnectInternal: hgcmMsgPost returned %Vrc\n", rc)); 1646 1647 if (!fBlock && VBOX_SUCCESS(rc)) 1648 { 1649 rc = VINF_HGCM_ASYNC_EXECUTE; 1650 } 1651 } 1652 else 1653 { 1654 Log(("MAIN::hgcmConnectInternal:Message allocation failed: %Vrc\n", rc)); 1655 } 1656 1657 1642 rc = hgcmMsgSend (hMsg); 1643 } 1644 1645 LogFlowFunc(("rc = %Vrc\n", rc)); 1658 1646 return rc; 1659 1647 } 1660 1648 1661 /* 1662 * Tell a service that the client is disconnecting. 1663 * Main HGCM thread will process this request for serialization. 1664 */ 1665 int hgcmDisconnectInternal (PPDMIHGCMPORT pHGCMPort, PVBOXHGCMCMD pCmd, uint32_t u32ClientID, bool fBlock) 1666 { 1667 int rc = VINF_SUCCESS; 1668 1669 LogFlow(("MAIN::hgcmDisconnectInternal: pHGCMPort = %p, pCmd = %p, u32ClientID = %d\n", 1670 pHGCMPort, pCmd, u32ClientID)); 1671 1672 if (!pHGCMPort || !pCmd) 1649 1650 /* Find a service and inform it about a client connection, create a client handle. 1651 * 1652 * @param pHGCMPort The port to be used for completion confirmation. 1653 * @param pCmd The VBox HGCM context. 1654 * @param pszServiceName The name of the service to be connected to. 1655 * @param pu32ClientId Where the store the created client handle. 1656 * @return VBox rc. 1657 */ 1658 int HGCMGuestConnect (PPDMIHGCMPORT pHGCMPort, 1659 PVBOXHGCMCMD pCmd, 1660 const char *pszServiceName, 1661 uint32_t *pu32ClientId) 1662 { 1663 LogFlowFunc(("pHGCMPort = %p, pCmd = %p, name = %s, pu32ClientId = %p\n", 1664 pHGCMPort, pCmd, pszServiceName, pu32ClientId)); 1665 1666 if (pHGCMPort == NULL || pCmd == NULL || pszServiceName == NULL || pu32ClientId == NULL) 1673 1667 { 1674 1668 return VERR_INVALID_PARAMETER; 1675 1669 } 1676 1670 1671 /* Forward the request to the main hgcm thread. */ 1677 1672 HGCMMSGHANDLE hMsg = 0; 1678 1673 1679 rc = hgcmMsgAlloc (g_hgcmThread, &hMsg, HGCMMSGID_DISCONNECT, hgcmMessageAlloc);1674 int rc = hgcmMsgAlloc (g_hgcmThread, &hMsg, HGCM_MSG_CONNECT, hgcmMainMessageAlloc); 1680 1675 1681 1676 if (VBOX_SUCCESS(rc)) 1682 1677 { 1683 HGCMMsgDisconnect *pMsg = (HGCMMsgDisconnect *)hgcmObjReference (hMsg, HGCMOBJ_MSG); 1684 1678 /* Initialize the message. Since 'pszServiceName' and 'pu32ClientId' 1679 * will not be deallocated by the caller until the message is completed, 1680 * use the supplied pointers. 1681 */ 1682 HGCMMsgMainConnect *pMsg = (HGCMMsgMainConnect *)hgcmObjReference (hMsg, HGCMOBJ_MSG); 1685 1683 AssertRelease(pMsg); 1686 1684 1687 pMsg->pCmd = pCmd; 1688 pMsg->pHGCMPort = pHGCMPort; 1689 1690 pMsg->u32ClientID = u32ClientID; 1691 1692 if (fBlock) 1693 rc = hgcmMsgSend (hMsg); 1694 else 1695 rc = hgcmMsgPost (hMsg, hgcmMsgCompletionCallback); 1685 pMsg->pHGCMPort = pHGCMPort; 1686 pMsg->pCmd = pCmd; 1687 pMsg->pszServiceName = pszServiceName; 1688 pMsg->pu32ClientId = pu32ClientId; 1696 1689 1697 1690 hgcmObjDereference (pMsg); 1698 1691 1699 if (!fBlock && VBOX_SUCCESS(rc)) 1700 { 1701 rc = VINF_HGCM_ASYNC_EXECUTE; 1702 } 1703 } 1704 else 1705 { 1706 Log(("MAIN::hgcmDisconnectInternal: Message allocation failed: %Vrc\n", rc)); 1707 } 1708 1709 1692 rc = hgcmMsgPost (hMsg, hgcmMsgCompletionCallback); 1693 } 1694 1695 LogFlowFunc(("rc = %Vrc\n", rc)); 1710 1696 return rc; 1711 1697 } 1712 1698 1713 #ifdef HGCMSS 1714 static int hgcmLoadSaveStateSend (PSSMHANDLE pSSM, uint32_t u32MsgId) 1715 { 1716 /* Forward the request to the main HGCM thread. */ 1717 LogFlowFunc(("u32MsgId = %d\n", u32MsgId)); 1718 1699 /* Tell a service that the client is disconnecting, destroy the client handle. 1700 * 1701 * @param pHGCMPort The port to be used for completion confirmation. 1702 * @param pCmd The VBox HGCM context. 1703 * @param u32ClientId The client handle to be disconnected and deleted. 1704 * @return VBox rc. 1705 */ 1706 int HGCMGuestDisconnect (PPDMIHGCMPORT pHGCMPort, 1707 PVBOXHGCMCMD pCmd, 1708 uint32_t u32ClientId) 1709 { 1710 LogFlowFunc(("pHGCMPort = %p, pCmd = %p, u32ClientId = %d\n", 1711 pHGCMPort, pCmd, u32ClientId)); 1712 1713 if (!pHGCMPort || !pCmd || !u32ClientId) 1714 { 1715 return VERR_INVALID_PARAMETER; 1716 } 1717 1718 /* Forward the request to the main hgcm thread. */ 1719 1719 HGCMMSGHANDLE hMsg = 0; 1720 1720 1721 int rc = hgcmMsgAlloc (g_hgcmThread, &hMsg, u32MsgId, hgcmMessageAlloc);1721 int rc = hgcmMsgAlloc (g_hgcmThread, &hMsg, HGCM_MSG_DISCONNECT, hgcmMainMessageAlloc); 1722 1722 1723 1723 if (VBOX_SUCCESS(rc)) 1724 1724 { 1725 HGCMMsgLoadSaveState *pMsg = (HGCMMsgLoadSaveState *)hgcmObjReference (hMsg, HGCMOBJ_MSG); 1725 /* Initialize the message. */ 1726 HGCMMsgMainDisconnect *pMsg = (HGCMMsgMainDisconnect *)hgcmObjReference (hMsg, HGCMOBJ_MSG); 1726 1727 AssertRelease(pMsg); 1727 1728 1728 pMsg->u32ClientID = 0; /* @todo not used. */ 1729 pMsg->pSSM = pSSM; 1729 pMsg->pCmd = pCmd; 1730 pMsg->pHGCMPort = pHGCMPort; 1731 pMsg->u32ClientId = u32ClientId; 1732 1733 hgcmObjDereference (pMsg); 1734 1735 rc = hgcmMsgPost (hMsg, hgcmMsgCompletionCallback); 1736 } 1737 1738 LogFlowFunc(("rc = %Vrc\n", rc)); 1739 return rc; 1740 } 1741 1742 /* Helper to send either HGCM_MSG_SAVESTATE or HGCM_MSG_LOADSTATE messages to the main HGCM thread. 1743 * 1744 * @param pSSM The SSM handle. 1745 * @param u32MsgId The message to be sent: HGCM_MSG_SAVESTATE or HGCM_MSG_LOADSTATE. 1746 * @return VBox rc. 1747 */ 1748 static int hgcmHostLoadSaveState (PSSMHANDLE pSSM, 1749 uint32_t u32MsgId) 1750 { 1751 LogFlowFunc(("pSSM = %p, u32MsgId = %d\n", pSSM, u32MsgId)); 1752 1753 HGCMMSGHANDLE hMsg = 0; 1754 1755 int rc = hgcmMsgAlloc (g_hgcmThread, &hMsg, u32MsgId, hgcmMainMessageAlloc); 1756 1757 if (VBOX_SUCCESS(rc)) 1758 { 1759 HGCMMsgMainLoadSaveState *pMsg = (HGCMMsgMainLoadSaveState *)hgcmObjReference (hMsg, HGCMOBJ_MSG); 1760 AssertRelease(pMsg); 1761 1762 pMsg->pSSM = pSSM; 1763 1764 hgcmObjDereference (pMsg); 1730 1765 1731 1766 rc = hgcmMsgSend (hMsg); 1732 1733 hgcmObjDereference (pMsg);1734 1767 } 1735 1768 1736 1769 LogFlowFunc(("rc = %Vrc\n", rc)); 1737 1738 1770 return rc; 1739 1771 } 1740 1772 1741 int hgcmSaveStateInternal (PSSMHANDLE pSSM) 1742 { 1743 return hgcmLoadSaveStateSend (pSSM, HGCMMSGID_SAVESTATE); 1744 } 1745 1746 int hgcmLoadStateInternal (PSSMHANDLE pSSM) 1747 { 1748 return hgcmLoadSaveStateSend (pSSM, HGCMMSGID_LOADSTATE); 1749 } 1750 #else 1751 int hgcmSaveStateInternal (uint32_t u32ClientID, PSSMHANDLE pSSM) 1752 { 1753 int rc = VINF_SUCCESS; 1754 1755 LogFlow(("MAIN::hgcmSaveStateInternal: u32ClientID = %d\n", u32ClientID)); 1756 1757 HGCMClient *pClient = (HGCMClient *)hgcmObjReference (u32ClientID, HGCMOBJ_CLIENT); 1758 1759 if (!pClient) 1760 { 1761 Log(("MAIN::hgcmCallInternal: FAILURE resolving client id %d\n", u32ClientID)); 1762 return VERR_HGCM_INVALID_CLIENT_ID; 1763 } 1764 1765 AssertRelease(pClient->pService); 1766 1767 rc = pClient->pService->SaveState (u32ClientID, pSSM); 1768 1769 hgcmObjDereference (pClient); 1770 1773 /* Save the state of services. 1774 * 1775 * @param pSSM The SSM handle. 1776 * @return VBox rc. 1777 */ 1778 int HGCMHostSaveState (PSSMHANDLE pSSM) 1779 { 1780 return hgcmHostLoadSaveState (pSSM, HGCM_MSG_SAVESTATE); 1781 } 1782 1783 /* Load the state of services. 1784 * 1785 * @param pSSM The SSM handle. 1786 * @return VBox rc. 1787 */ 1788 int HGCMHostLoadState (PSSMHANDLE pSSM) 1789 { 1790 return hgcmHostLoadSaveState (pSSM, HGCM_MSG_LOADSTATE); 1791 } 1792 1793 /* The guest calls the service. 1794 * 1795 * @param pHGCMPort The port to be used for completion confirmation. 1796 * @param pCmd The VBox HGCM context. 1797 * @param u32ClientId The client handle to be disconnected and deleted. 1798 * @param u32Function The function number. 1799 * @param cParms Number of parameters. 1800 * @param paParms Pointer to array of parameters. 1801 * @return VBox rc. 1802 */ 1803 int HGCMGuestCall (PPDMIHGCMPORT pHGCMPort, 1804 PVBOXHGCMCMD pCmd, 1805 uint32_t u32ClientId, 1806 uint32_t u32Function, 1807 uint32_t cParms, 1808 VBOXHGCMSVCPARM *paParms) 1809 { 1810 LogFlowFunc(("pHGCMPort = %p, pCmd = %p, u32ClientId = %d, u32Function = %d, cParms = %d, paParms = %p\n", 1811 pHGCMPort, pCmd, u32ClientId, u32Function, cParms, paParms)); 1812 1813 if (!pHGCMPort || !pCmd || u32ClientId == 0) 1814 { 1815 return VERR_INVALID_PARAMETER; 1816 } 1817 1818 int rc = VERR_HGCM_INVALID_CLIENT_ID; 1819 1820 /* Resolve the client handle to the client instance pointer. */ 1821 HGCMClient *pClient = (HGCMClient *)hgcmObjReference (u32ClientId, HGCMOBJ_CLIENT); 1822 1823 if (pClient) 1824 { 1825 AssertRelease(pClient->pService); 1826 1827 /* Forward the message to the service thread. */ 1828 rc = pClient->pService->GuestCall (pHGCMPort, pCmd, u32ClientId, u32Function, cParms, paParms); 1829 1830 hgcmObjDereference (pClient); 1831 } 1832 1833 LogFlowFunc(("rc = %Vrc\n", rc)); 1771 1834 return rc; 1772 1835 } 1773 1836 1774 int hgcmLoadStateInternal (uint32_t u32ClientID, PSSMHANDLE pSSM) 1775 { 1776 int rc = VINF_SUCCESS; 1777 1778 LogFlow(("MAIN::hgcmLoadStateInternal: u32ClientID = %d\n", u32ClientID)); 1779 1780 HGCMClient *pClient = (HGCMClient *)hgcmObjReference (u32ClientID, HGCMOBJ_CLIENT); 1781 1782 if (!pClient) 1783 { 1784 Log(("MAIN::hgcmCallInternal: FAILURE resolving client id %d\n", u32ClientID)); 1785 return VERR_HGCM_INVALID_CLIENT_ID; 1786 } 1787 1788 AssertRelease(pClient->pService); 1789 1790 rc = pClient->pService->LoadState (u32ClientID, pSSM); 1791 1792 hgcmObjDereference (pClient); 1793 return rc; 1794 } 1795 #endif /* HGCMSS */ 1796 1797 int hgcmLoadInternal (const char *pszServiceName, const char *pszServiceLibrary) 1798 { 1799 int rc = VINF_SUCCESS; 1800 1801 LogFlow(("MAIN::hgcmLoadInternal: name = %s, lib = %s\n", 1802 pszServiceName, pszServiceLibrary)); 1803 1804 if (!pszServiceName || !pszServiceLibrary) 1837 /* The host calls the service. 1838 * 1839 * @param pszServiceName The service name to be called. 1840 * @param u32Function The function number. 1841 * @param cParms Number of parameters. 1842 * @param paParms Pointer to array of parameters. 1843 * @return VBox rc. 1844 */ 1845 int HGCMHostCall (const char *pszServiceName, 1846 uint32_t u32Function, 1847 uint32_t cParms, 1848 VBOXHGCMSVCPARM *paParms) 1849 { 1850 LogFlowFunc(("name = %s, u32Function = %d, cParms = %d, paParms = %p\n", 1851 pszServiceName, u32Function, cParms, paParms)); 1852 1853 if (!pszServiceName) 1805 1854 { 1806 1855 return VERR_INVALID_PARAMETER; … … 1809 1858 HGCMMSGHANDLE hMsg = 0; 1810 1859 1811 rc = hgcmMsgAlloc (g_hgcmThread, &hMsg, HGCMMSGID_LOAD, hgcmMessageAlloc); 1860 /* Host calls go to main HGCM thread that resolves the service name to the 1861 * service instance pointer and then, using the service pointer, forwards 1862 * the message to the service thread. 1863 * So it is slow but host calls are intended mostly for configuration and 1864 * other non-time-critical functions. 1865 */ 1866 int rc = hgcmMsgAlloc (g_hgcmThread, &hMsg, HGCM_MSG_HOSTCALL, hgcmMainMessageAlloc); 1812 1867 1813 1868 if (VBOX_SUCCESS(rc)) 1814 1869 { 1815 HGCMMsgLoad *pMsg = (HGCMMsgLoad *)hgcmObjReference (hMsg, HGCMOBJ_MSG); 1816 1870 HGCMMsgMainHostCall *pMsg = (HGCMMsgMainHostCall *)hgcmObjReference (hMsg, HGCMOBJ_MSG); 1817 1871 AssertRelease(pMsg); 1818 1819 pMsg->pHGCMPort = NULL; /* Not used by the call. */1820 1821 rc = pMsg->Init (pszServiceName, pszServiceLibrary);1822 1823 if (VBOX_SUCCESS (rc))1824 {1825 rc = hgcmMsgSend (hMsg);1826 }1827 1828 hgcmObjDereference (pMsg);1829 1830 LogFlow(("MAIN::hgcm:LoadInternal: hgcmMsgSend returned %Vrc\n", rc));1831 }1832 else1833 {1834 Log(("MAIN::hgcmLoadInternal:Message allocation failed: %Vrc\n", rc));1835 }1836 1837 1838 return rc;1839 }1840 1841 /*1842 * Call a service.1843 * The service dedicated thread will process this request.1844 */1845 int hgcmGuestCallInternal (PPDMIHGCMPORT pHGCMPort, PVBOXHGCMCMD pCmd, uint32_t u32ClientID, uint32_t u32Function, uint32_t cParms, VBOXHGCMSVCPARM aParms[], bool fBlock)1846 {1847 int rc = VINF_SUCCESS;1848 1849 LogFlow(("MAIN::hgcmCallInternal: pHGCMPort = %p, pCmd = %p, u32ClientID = %d, u32Function = %d, cParms = %d, aParms = %p\n",1850 pHGCMPort, pCmd, u32ClientID, u32Function, cParms, aParms));1851 1852 if (!pHGCMPort || !pCmd)1853 {1854 return VERR_INVALID_PARAMETER;1855 }1856 1857 HGCMClient *pClient = (HGCMClient *)hgcmObjReference (u32ClientID, HGCMOBJ_CLIENT);1858 1859 if (!pClient)1860 {1861 Log(("MAIN::hgcmCallInternal: FAILURE resolving client id %d\n", u32ClientID));1862 return VERR_HGCM_INVALID_CLIENT_ID;1863 }1864 1865 AssertRelease(pClient->pService);1866 1867 rc = pClient->pService->GuestCall (pHGCMPort, pCmd, u32ClientID, u32Function, cParms, aParms, fBlock);1868 1869 hgcmObjDereference (pClient);1870 1871 return rc;1872 }1873 1874 /*1875 * Call a service.1876 * The service dedicated thread will process this request.1877 */1878 int hgcmHostCallInternal (const char *pszServiceName, uint32_t u32Function, uint32_t cParms, VBOXHGCMSVCPARM aParms[])1879 {1880 int rc = VINF_SUCCESS;1881 1882 LogFlow(("MAIN::hgcmHostCallInternal: service = %s, u32Function = %d, cParms = %d, aParms = %p\n",1883 pszServiceName, u32Function, cParms, aParms));1884 1885 if (!pszServiceName)1886 {1887 return VERR_INVALID_PARAMETER;1888 }1889 1890 HGCMMSGHANDLE hMsg = 0;1891 1892 rc = hgcmMsgAlloc (g_hgcmThread, &hMsg, HGCMMSGID_HOSTCALL, hgcmMessageAlloc);1893 1894 if (VBOX_SUCCESS(rc))1895 {1896 HGCMMsgHostCall *pMsg = (HGCMMsgHostCall *)hgcmObjReference (hMsg, HGCMOBJ_MSG);1897 1898 AssertRelease(pMsg);1899 1900 pMsg->pHGCMPort = NULL; /* Not used. */1901 1872 1902 1873 pMsg->pszServiceName = (char *)pszServiceName; 1903 pMsg->u32Function = u32Function; 1904 pMsg->cParms = cParms; 1905 pMsg->paParms = &aParms[0]; 1906 1874 pMsg->u32Function = u32Function; 1875 pMsg->cParms = cParms; 1876 pMsg->paParms = paParms; 1877 1878 hgcmObjDereference (pMsg); 1879 1907 1880 rc = hgcmMsgSend (hMsg); 1908 1909 hgcmObjDereference (pMsg); 1910 1911 LogFlow(("MAIN::hgcm:HostCallInternal: hgcmMsgSend returned %Vrc\n", rc)); 1912 } 1913 else 1914 { 1915 Log(("MAIN::hgcmHostCallInternal:Message allocation failed: %Vrc\n", rc)); 1916 } 1917 1881 } 1882 1883 LogFlowFunc(("rc = %Vrc\n", rc)); 1918 1884 return rc; 1919 1885 } 1920 1886 1921 1922 int hgcmInit (void) 1923 { 1924 int rc = VINF_SUCCESS; 1925 1926 Log(("MAIN::hgcmInit\n")); 1927 1928 rc = hgcmThreadInit (); 1929 1930 if (VBOX_FAILURE(rc)) 1931 { 1932 Log(("FAILURE: Can't init worker threads.\n")); 1933 } 1934 else 1935 { 1936 /* Start main HGCM thread that will process Connect/Disconnect requests. */ 1887 int HGCMHostReset (void) 1888 { 1889 LogFlowFunc(("\n")); 1890 1891 /* Disconnect all clients. 1892 */ 1893 1894 HGCMMSGHANDLE hMsg = 0; 1895 1896 int rc = hgcmMsgAlloc (g_hgcmThread, &hMsg, HGCM_MSG_RESET, hgcmMainMessageAlloc); 1897 1898 if (VBOX_SUCCESS(rc)) 1899 { 1900 rc = hgcmMsgSend (hMsg); 1901 } 1902 1903 LogFlowFunc(("rc = %Vrc\n", rc)); 1904 return rc; 1905 } 1906 1907 int HGCMHostInit (void) 1908 { 1909 LogFlowFunc(("\n")); 1910 1911 int rc = hgcmThreadInit (); 1912 1913 if (VBOX_SUCCESS(rc)) 1914 { 1915 /* 1916 * Start main HGCM thread. 1917 */ 1937 1918 1938 1919 rc = hgcmThreadCreate (&g_hgcmThread, "MainHGCMthread", hgcmThread, NULL); … … 1940 1921 if (VBOX_FAILURE (rc)) 1941 1922 { 1942 Log(("FAILURE: HGCM initialization.\n")); 1943 } 1944 } 1945 1946 LogFlow(("MAIN::hgcmInit: rc = %Vrc\n", rc)); 1947 1923 LogRel(("Failed to start HGCM thread. HGCM services will be unavailable!!! rc = %Vrc\n", rc)); 1924 } 1925 } 1926 1927 LogFlowFunc(("rc = %Vrc\n", rc)); 1948 1928 return rc; 1949 1929 } 1950 1930 1951 int hgcmReset (void) 1952 { 1953 int rc = VINF_SUCCESS; 1954 Log(("MAIN::hgcmReset\n")); 1955 1956 /* Disconnect all clients. */ 1957 HGCMMSGHANDLE hMsg = 0; 1958 1959 rc = hgcmMsgAlloc (g_hgcmThread, &hMsg, HGCMMSGID_RESET, hgcmMessageAlloc); 1960 1961 if (VBOX_SUCCESS(rc)) 1962 { 1963 HGCMMsgReset *pMsg = (HGCMMsgReset *)hgcmObjReference (hMsg, HGCMOBJ_MSG); 1964 1965 AssertRelease(pMsg); 1966 1967 pMsg->pHGCMPort = NULL; /* Not used by the call. */ 1968 1969 rc = hgcmMsgSend (hMsg); 1970 1971 hgcmObjDereference (pMsg); 1972 1973 LogFlow(("MAIN::hgcmReset: hgcmMsgSend returned %Vrc\n", rc)); 1974 } 1975 else 1976 { 1977 Log(("MAIN::hgcmReset:Message allocation failed: %Vrc\n", rc)); 1978 } 1979 1980 LogFlow(("MAIN::hgcmReset: rc = %Vrc\n", rc)); 1931 int HGCMHostShutdown (void) 1932 { 1933 LogFlowFunc(("\n")); 1934 1935 /* 1936 * Do HGCMReset and then unload all services. 1937 */ 1938 1939 int rc = HGCMHostReset (); 1940 1941 if (VBOX_SUCCESS (rc)) 1942 { 1943 /* Send the quit message to the main hgcmThread. */ 1944 HGCMMSGHANDLE hMsg = 0; 1945 1946 rc = hgcmMsgAlloc (g_hgcmThread, &hMsg, HGCM_MSG_QUIT, hgcmMainMessageAlloc); 1947 1948 if (VBOX_SUCCESS(rc)) 1949 { 1950 rc = hgcmMsgSend (hMsg); 1951 1952 if (VBOX_SUCCESS (rc)) 1953 { 1954 hgcmThreadUninit (); 1955 } 1956 } 1957 } 1958 1959 LogFlowFunc(("rc = %Vrc\n", rc)); 1981 1960 return rc; 1982 1961 } -
trunk/src/VBox/Main/hgcm/HGCMThread.cpp
r1681 r1711 647 647 int hgcmMsgAlloc (HGCMTHREADHANDLE hThread, HGCMMSGHANDLE *pHandle, uint32_t u32MsgId, PFNHGCMNEWMSGALLOC pfnNewMessage) 648 648 { 649 LogFlow(("hgcmMsgAlloc: thread handle = %d, pHandle = %p, sizeof (HGCMMsgCore) = %d\n", hThread, pHandle, sizeof (HGCMMsgCore)));649 LogFlow(("hgcmMsgAlloc: thread handle = 0x%08X, pHandle = %p, sizeof (HGCMMsgCore) = %d\n", hThread, pHandle, sizeof (HGCMMsgCore))); 650 650 651 651 if (!pHandle) … … 669 669 } 670 670 671 LogFlow(("MAIN::hgcmMsgAlloc: handle %d, rc = %Vrc\n", *pHandle, rc));671 LogFlow(("MAIN::hgcmMsgAlloc: handle 0x%08X, rc = %Vrc\n", *pHandle, rc)); 672 672 673 673 return rc; … … 676 676 static int hgcmMsgPostInternal (HGCMMSGHANDLE hMsg, PHGCMMSGCALLBACK pfnCallback, bool fWait) 677 677 { 678 LogFlow(("MAIN::hgcmMsgPostInternal: hMsg = %d, pfnCallback = %p, fWait = %d\n", hMsg, pfnCallback, fWait));678 LogFlow(("MAIN::hgcmMsgPostInternal: hMsg = 0x%08X, pfnCallback = %p, fWait = %d\n", hMsg, pfnCallback, fWait)); 679 679 680 680 int rc = VINF_SUCCESS; … … 693 693 } 694 694 695 LogFlow(("MAIN::hgcmMsgPostInternal: hMsg %d, rc = %Vrc\n", hMsg, rc));695 LogFlow(("MAIN::hgcmMsgPostInternal: hMsg 0x%08X, rc = %Vrc\n", hMsg, rc)); 696 696 697 697 return rc; … … 706 706 int hgcmMsgPost (HGCMMSGHANDLE hMsg, PHGCMMSGCALLBACK pfnCallback) 707 707 { 708 return hgcmMsgPostInternal (hMsg, pfnCallback, false); 708 int rc = hgcmMsgPostInternal (hMsg, pfnCallback, false); 709 710 if (VBOX_SUCCESS (rc)) 711 { 712 rc = VINF_HGCM_ASYNC_EXECUTE; 713 } 714 715 return rc; 709 716 } 710 717 … … 722 729 int hgcmMsgGet (HGCMTHREADHANDLE hThread, HGCMMsgCore **ppMsg) 723 730 { 724 LogFlow(("MAIN::hgcmMsgGet: hThread = %d, ppMsg = %p\n", hThread, ppMsg));731 LogFlow(("MAIN::hgcmMsgGet: hThread = 0x%08X, ppMsg = %p\n", hThread, ppMsg)); 725 732 726 733 if (!hThread || !ppMsg) -
trunk/src/VBox/Main/include/VMMDev.h
r1681 r1711 37 37 struct DRVMAINVMMDEV *mpDrv; 38 38 39 #ifdef HGCMSS40 39 bool fSharedFolderActive; 41 40 bool isShFlActive() … … 43 42 return fSharedFolderActive; 44 43 } 45 #else46 uint32_t mSharedFolderClientId;47 uint32_t getShFlClientId()48 {49 return mSharedFolderClientId;50 }51 #endif /* HGCMSS */52 44 53 45 Console *getParent() … … 62 54 63 55 int hgcmLoadService (const char *pszServiceName, const char *pszServiceLibrary); 64 int hgcmConnect (PVBOXHGCMCMD pCmd, PHGCMSERVICELOCATION pServiceLocation, uint32_t *pu32ClientID);65 int hgcmDisconnect (PVBOXHGCMCMD pCmd, uint32_t u32ClientID);66 56 int hgcmHostCall (const char *pszServiceName, uint32_t u32Function, uint32_t cParms, PVBOXHGCMSVCPARM paParms); 67 57 -
trunk/src/VBox/Main/include/hgcm/HGCM.h
r1681 r1711 34 34 35 35 __BEGIN_DECLS 36 int hgcmInit (void); 36 int HGCMHostInit (void); 37 int HGCMHostShutdown (void); 37 38 38 int hgcmReset (void);39 int HGCMHostReset (void); 39 40 40 int hgcmLoadInternal(const char *pszServiceName, const char *pszServiceLibrary);41 int HGCMHostLoad (const char *pszServiceName, const char *pszServiceLibrary); 41 42 42 int hgcmConnectInternal (PPDMIHGCMPORT pHGCMPort, PVBOXHGCMCMD pCmdPtr, PHGCMSERVICELOCATION pLoc, uint32_t *pClientID, bool fBlock); 43 int hgcmDisconnectInternal (PPDMIHGCMPORT pHGCMPort, PVBOXHGCMCMD pCmdPtr, uint32_t clientID, bool fBlock); 44 int hgcmGuestCallInternal (PPDMIHGCMPORT pHGCMPort, PVBOXHGCMCMD pCmdPtr, uint32_t clientID, uint32_t function, uint32_t cParms, VBOXHGCMSVCPARM aParms[], bool fBlock); 45 int hgcmHostCallInternal (const char *pszServiceName, uint32_t function, uint32_t cParms, VBOXHGCMSVCPARM aParms[]); 43 int HGCMGuestConnect (PPDMIHGCMPORT pHGCMPort, PVBOXHGCMCMD pCmdPtr, const char *pszServiceName, uint32_t *pClientID); 44 int HGCMGuestDisconnect (PPDMIHGCMPORT pHGCMPort, PVBOXHGCMCMD pCmdPtr, uint32_t clientID); 45 int HGCMGuestCall (PPDMIHGCMPORT pHGCMPort, PVBOXHGCMCMD pCmdPtr, uint32_t clientID, uint32_t function, uint32_t cParms, VBOXHGCMSVCPARM *paParms); 46 46 47 #ifdef HGCMSS 48 int hgcmSaveStateInternal (PSSMHANDLE pSSM); 49 int hgcmLoadStateInternal (PSSMHANDLE pSSM); 50 #else 51 int hgcmSaveStateInternal (uint32_t clientID, PSSMHANDLE pSSM); 52 int hgcmLoadStateInternal (uint32_t clientID, PSSMHANDLE pSSM); 53 #endif /* HGCMSS */ 47 int HGCMHostCall (const char *pszServiceName, uint32_t function, uint32_t cParms, VBOXHGCMSVCPARM aParms[]); 48 49 int HGCMHostSaveState (PSSMHANDLE pSSM); 50 int HGCMHostLoadState (PSSMHANDLE pSSM); 54 51 55 52 __END_DECLS -
trunk/src/VBox/Main/include/hgcm/HGCMThread.h
r1681 r1711 124 124 */ 125 125 int hgcmThreadInit (void); 126 void hgcmThreadUninit (void); 126 127 127 128
Note:
See TracChangeset
for help on using the changeset viewer.