VirtualBox

Changeset 1711 in vbox for trunk/src/VBox/Main


Ignore:
Timestamp:
Mar 27, 2007 8:35:21 AM (18 years ago)
Author:
vboxsync
Message:

HGCM cleanup.

Location:
trunk/src/VBox/Main
Files:
7 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Main/Makefile

    r1681 r1711  
    2121DEPTH = ../../..
    2222include $(PATH_KBUILD)/header.kmk
    23 
    24 DEFS       += HGCMSS
    2523
    2624ifdef VRDP_MC
  • trunk/src/VBox/Main/VMMDevInterface.cpp

    r1685 r1711  
    8787    AssertRC(rc);
    8888#ifdef VBOX_HGCM
    89     rc = hgcmInit ();
     89    rc = HGCMHostInit ();
    9090    AssertRC(rc);
    9191#endif /* VBOX_HGCM */
     
    9595VMMDev::~VMMDev()
    9696{
     97#ifdef VBOX_HGCM
     98    HGCMHostShutdown ();
     99#endif /* VBOX_HGCM */
    97100    RTSemEventDestroy (mCredentialsEvent);
    98101    if (mpDrv)
     
    301304
    302305    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);
    305315}
    306316
     
    311321    PDRVMAINVMMDEV pDrv = PDMIHGCMCONNECTOR_2_MAINVMMDEV(pInterface);
    312322
    313     return hgcmDisconnectInternal (pDrv->pHGCMPort, pCmd, u32ClientID, false);
     323    return HGCMGuestDisconnect (pDrv->pHGCMPort, pCmd, u32ClientID);
    314324}
    315325
     
    321331    PDRVMAINVMMDEV pDrv = PDMIHGCMCONNECTOR_2_MAINVMMDEV(pInterface);
    322332
    323     return hgcmGuestCallInternal (pDrv->pHGCMPort, pCmd, u32ClientID, u32Function, cParms, paParms, false);
     333    return HGCMGuestCall (pDrv->pHGCMPort, pCmd, u32ClientID, u32Function, cParms, paParms);
    324334}
    325335
     
    334344{
    335345    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);
    348347}
    349348
     
    361360    LogFlowFunc(("Enter\n"));
    362361
    363 #ifdef HGCMSS
    364362    if (u32Version != HGCM_SSM_VERSION)
    365363        return VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION;
    366364
    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);
    408366}
    409367
    410368int VMMDev::hgcmLoadService (const char *pszServiceName, const char *pszServiceLibrary)
    411369{
    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);
    423371}
    424372
     
    426374                          uint32_t cParms, PVBOXHGCMSVCPARM paParms)
    427375{
    428     return hgcmHostCallInternal (pszServiceName, u32Function, cParms, paParms);
    429 }
    430 
    431 #endif
     376    return HGCMHostCall (pszServiceName, u32Function, cParms, paParms);
     377}
     378#endif /* HGCM */
    432379
    433380
     
    471418    LogFlow(("VMMDev::drvDestruct: iInstance=%d\n", pDrvIns->iInstance));
    472419#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 */
    486422    if (pData->pVMMDev)
    487423    {
     
    498434DECLCALLBACK(void) VMMDev::drvReset(PPDMDRVINS pDrvIns)
    499435{
    500 #if defined(VBOX_HGCM) && !defined(HGCMSS)
    501     PDRVMAINVMMDEV pData = PDMINS2DATA(pDrvIns, PDRVMAINVMMDEV);
    502 #endif
    503436    LogFlow(("VMMDev::drvReset: iInstance=%d\n", pDrvIns->iInstance));
    504437#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 */
    538440}
    539441
     
    620522
    621523#ifdef VBOX_HGCM
    622 
    623 #ifdef HGCMSS
    624524    rc = pData->pVMMDev->hgcmLoadService ("VBoxSharedFolders", "VBoxSharedFolders");
    625525    pData->pVMMDev->fSharedFolderActive = VBOX_SUCCESS(rc);
     
    632532        LogRel(("Failed to load Shared Folders service %Vrc\n", rc));
    633533    }
    634 #else
    635     /* 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 */
    661534    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 */
    663536
    664537    return VINF_SUCCESS;
  • trunk/src/VBox/Main/hgcm/HGCM.cpp

    r1686 r1711  
    1818 * distribution, then only the terms of your commercial VirtualBox
    1919 * 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!
    2520 */
    2621
     
    5247
    5348/**
    54  *
    55  * Service location types:
    56  *
    57  *  LOCAL SERVICE
    58  *      service DLL is loaded by the VM process,
    59  *      and directly called by the VM HGCM instance.
    60  */
    61 
    62 /**
    6349 * A service gets one thread, which synchronously delivers messages to
    6450 * the service. This is good for serialization.
     
    7864 *
    7965 * 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
    10369
    10470/* The maximum allowed size of a service name in bytes. */
     
    10975 *  The HGCMService is an (in future) abstract class that implements
    11076 *  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
    11580class HGCMService
    11681{
     
    12186        static HGCMService *sm_pSvcListTail;
    12287
    123 #ifdef HGCMSS
    124        static int sm_cServices;
    125 #endif /* HGCMSS */
     88        static int sm_cServices;
    12689
    12790        HGCMTHREADHANDLE m_thread;
     
    13699        char *m_pszSvcLibrary;
    137100       
    138         PPDMIHGCMPORT m_pHGCMPort;
    139 
    140101        RTLDRMOD m_hLdrMod;
    141102        PFNVBOXHGCMSVCLOAD m_pfnLoad;
     
    151112        void unloadServiceDLL (void);
    152113
    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);
    155122
    156123        HGCMService ();
    157124        ~HGCMService () {};
    158 
    159         bool EqualToLoc (HGCMServiceLocation *loc);
    160125
    161126        static DECLCALLBACK(void) svcHlpCallComplete (VBOXHGCMCALLHANDLE callHandle, int32_t rc);
     
    163128    public:
    164129
     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
    165142        static void Reset (void);
    166143
    167 #ifdef HGCMSS
    168144        static int SaveState (PSSMHANDLE pSSM);
    169145        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);
    176151
    177152        uint32_t SizeOfClient (void) { return m_fntable.cbClient; };
    178153
    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[]);
    192159};
    193160
     
    234201
    235202
    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 HGCMMsgCore
    247 {
    248 };
    249 
    250 class HGCMMsgSvcUnload: public HGCMMsgCore
    251 {
    252 };
    253 
    254 class HGCMMsgSvcConnect: public HGCMMsgCore
    255 {
    256     public:
    257         /* client identifier */
    258         uint32_t u32ClientID;
    259 };
    260 
    261 class HGCMMsgSvcDisconnect: public HGCMMsgCore
    262 {
    263     public:
    264         /* client identifier */
    265         uint32_t u32ClientID;
    266 };
    267 
    268 class HGCMMsgHeader: public HGCMMsgCore
    269 {
    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 HGCMMsgHeader
    282 {
    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 HGCMMsgHeader
    310 {
    311     public:
    312         /* service location */
    313         HGCMSERVICELOCATION *pLoc;
    314 
    315         /* client identifier */
    316         uint32_t *pu32ClientID;
    317 
    318 };
    319 
    320 class HGCMMsgDisconnect: public HGCMMsgHeader
    321 {
    322     public:
    323         /* client identifier */
    324         uint32_t u32ClientID;
    325 };
    326 
    327 class HGCMMsgLoadSaveState: public HGCMMsgHeader
    328 {
    329     public:
    330         /* client identifier */
    331         uint32_t    u32ClientID;
    332         PSSMHANDLE  pSSM;
    333 };
    334 
    335 class HGCMMsgLoad: public HGCMMsgHeader
    336 {
    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 HGCMMsgHeader
    366 {
    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 HGCMMsgHeader
    380 {
    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_GUESTCALL
    388        || pMsgCore->MsgId () == HGCMMSGID_HOSTCALL)
    389    {
    390        /* Only call the completion for these messages. The helper
    391         * is called by the service, and the service does not get
    392         * any other messages.
    393         */
    394        hgcmMsgComplete (pMsgCore, rc);
    395    }
    396    else
    397    {
    398        AssertFailed ();
    399    }
    400 }
    401203
    402204HGCMService *HGCMService::sm_pSvcListHead = NULL;
    403205HGCMService *HGCMService::sm_pSvcListTail = NULL;
    404 #ifdef HGCMSS
    405206int HGCMService::sm_cServices = 0;
    406 #endif /* HGCMSS */
    407207
    408208HGCMService::HGCMService ()
     
    424224
    425225
    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 
    451226static bool g_fResetting = false;
    452227static bool g_fSaveState = false;
    453228
    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 */
     235int 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
    472244    int rc = VINF_SUCCESS;
    473245
     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 */
     317void 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
     343class HGCMMsgSvcLoad: public HGCMMsgCore
     344{
     345};
     346
     347class HGCMMsgSvcUnload: public HGCMMsgCore
     348{
     349};
     350
     351class HGCMMsgSvcConnect: public HGCMMsgCore
     352{
     353    public:
     354        /* client identifier */
     355        uint32_t u32ClientId;
     356};
     357
     358class HGCMMsgSvcDisconnect: public HGCMMsgCore
     359{
     360    public:
     361        /* client identifier */
     362        uint32_t u32ClientId;
     363};
     364
     365class 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
     378class 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
     393class HGCMMsgLoadSaveStateClient: public HGCMMsgCore
     394{
     395    public:
     396        uint32_t    u32ClientId;
     397        PSSMHANDLE  pSSM;
     398};
     399
     400class 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
     412static 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 */
     434static DECLCALLBACK(void) hgcmServiceThread (HGCMTHREADHANDLE ThreadHandle, void *pvUser)
     435{
    474436    HGCMService *pSvc = (HGCMService *)pvUser;
    475 
    476437    AssertRelease(pSvc != NULL);
    477438
    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);
    485445
    486446        if (VBOX_FAILURE (rc))
    487447        {
    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;
    493451        }
    494452
     
    498456        switch (u32MsgId)
    499457        {
    500             case HGCMMSGID_SVC_LOAD:
    501             {
    502                 LogFlow(("HGCMMSGID_SVC_LOAD\n"));
     458            case SVC_MSG_LOAD:
     459            {
     460                LogFlowFunc(("SVC_MSG_LOAD\n"));
    503461                rc = pSvc->loadServiceDLL ();
    504462            } break;
    505463
    506             case HGCMMSGID_SVC_UNLOAD:
    507             {
    508                 LogFlow(("HGCMMSGID_SVC_UNLOAD\n"));
     464            case SVC_MSG_UNLOAD:
     465            {
     466                LogFlowFunc(("SVC_MSG_UNLOAD\n"));
    509467                pSvc->unloadServiceDLL ();
    510                 bUnloaded = true;
     468                fQuit = true;
    511469            } break;
    512470
    513             case HGCMMSGID_SVC_CONNECT:
    514             {
    515                 LogFlow(("HGCMMSGID_SVC_CONNECT\n"));
    516 
     471            case SVC_MSG_CONNECT:
     472            {
    517473                HGCMMsgSvcConnect *pMsg = (HGCMMsgSvcConnect *)pMsgCore;
    518474
    519                 rc = VINF_SUCCESS;
    520 
    521                 HGCMClient *pClient = (HGCMClient *)hgcmObjReference (pMsg->u32ClientID, HGCMOBJ_CLIENT);
     475                LogFlowFunc(("SVC_MSG_CONNECT u32ClientId = %d\n", pMsg->u32ClientId));
     476
     477                HGCMClient *pClient = (HGCMClient *)hgcmObjReference (pMsg->u32ClientId, HGCMOBJ_CLIENT);
    522478
    523479                if (pClient)
    524480                {
    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));
    562482
    563483                    hgcmObjDereference (pClient);
     
    569489            } break;
    570490
    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                }
    580509            } break;
    581510
    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);
    590548
    591549                if (pClient)
     
    593551                    if (pSvc->m_fntable.pfnLoadState)
    594552                    {
    595                         rc = pSvc->m_fntable.pfnLoadState (pMsg->u32ClientID, HGCM_CLIENT_DATA(pSvc, pClient), pMsg->pSSM);
     553                        rc = pSvc->m_fntable.pfnLoadState (pMsg->u32ClientId, HGCM_CLIENT_DATA(pSvc, pClient), pMsg->pSSM);
    596554                    }
    597555
    598556                    hgcmObjDereference (pClient);
    599557                }
    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);
    609571
    610572                rc = VINF_SUCCESS;
     
    615577                    {
    616578                        g_fSaveState = true;
    617                         rc = pSvc->m_fntable.pfnSaveState (pMsg->u32ClientID, HGCM_CLIENT_DATA(pSvc, pClient), pMsg->pSSM);
     579                        rc = pSvc->m_fntable.pfnSaveState (pMsg->u32ClientId, HGCM_CLIENT_DATA(pSvc, pClient), pMsg->pSSM);
    618580                        g_fSaveState = false;
    619581                    }
     
    621583                    hgcmObjDereference (pClient);
    622584                }
    623                 break;
    624             }
     585                else
     586                {
     587                    rc = VERR_HGCM_INVALID_CLIENT_ID;
     588                }
     589            } break;
    625590
    626591            default:
    627592            {
    628                 Log(("hgcmServiceThread::Unsupported message number %08X\n", u32MsgId));
     593                AssertMsgFailed(("hgcmServiceThread::Unsupported message number %08X\n", u32MsgId));
    629594                rc = VERR_NOT_SUPPORTED;
    630595            } break;
    631596        }
    632597
    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.
    639602             */
    640603            hgcmMsgComplete (pMsgCore, rc);
    641604        }
    642605    }
    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
     626static 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
     643int 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);
    658654
    659655    if (VBOX_SUCCESS(rc))
     
    674670        else
    675671        {
    676             m_pHGCMPort = pHGCMPort;
    677            
     672            /* Initialize service helpers table. */
    678673            m_svcHelpers.pfnCallComplete = svcHlpCallComplete;
    679674            m_svcHelpers.pvInstance      = this;
     
    681676            /* Execute the load request on the service thread. */
    682677            HGCMMSGHANDLE hMsg;
    683 
    684             rc = hgcmMsgAlloc (m_thread, &hMsg, HGCMMSGID_SVC_LOAD, hgcmMessageAlloc);
     678            rc = hgcmMsgAlloc (m_thread, &hMsg, SVC_MSG_LOAD, hgcmMessageAllocSvc);
    685679
    686680            if (VBOX_SUCCESS(rc))
     
    690684        }
    691685    }
    692     else
    693     {
    694         Log(("HGCMService::InstanceCreate: FAILURE: service thread creation\n"));
    695     }
    696686
    697687    if (VBOX_FAILURE(rc))
    698688    {
    699         InstanceDestroy ();
    700     }
    701 
    702     LogFlow(("HGCMService::InstanceCreate rc = %Vrc\n", rc));
    703 
     689        instanceDestroy ();
     690    }
     691
     692    LogFlowFunc(("rc = %Vrc\n", rc));
    704693    return rc;
    705694}
    706695
    707 void HGCMService::InstanceDestroy (void)
    708 {
     696void HGCMService::instanceDestroy (void)
     697{
     698    LogFlowFunc(("%s\n", m_pszSvcName));
     699
    709700    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);
    714702
    715703    if (VBOX_SUCCESS(rc))
     
    720708    RTStrFree (m_pszSvcLibrary);
    721709    m_pszSvcLibrary = NULL;
     710
    722711    RTStrFree (m_pszSvcName);
    723712    m_pszSvcName = NULL;
     713}
     714
     715int 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
     739int 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);
    724780   
    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;
    822786    }
    823787    else
    824788    {
    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        {
    830794            rc = VERR_NO_MEMORY;
    831795        }
    832 
    833         if (VBOX_SUCCESS(rc))
    834         {
    835             rc = psvc->InstanceCreate (pszServiceLibrary, pszServiceName, pHGCMPort);
     796        else
     797        {
     798            /* Load the library and call the initialization entry point. */
     799            rc = pSvc->instanceCreate (pszServiceLibrary, pszServiceName);
    836800
    837801            if (VBOX_SUCCESS(rc))
    838802            {
    839803                /* Insert the just created service to list for future references. */
    840                 psvc->m_pSvcNext = sm_pSvcListHead;
    841                 psvc->m_pSvcPrev = NULL;
     804                pSvc->m_pSvcNext = sm_pSvcListHead;
     805                pSvc->m_pSvcPrev = NULL;
    842806               
    843807                if (sm_pSvcListHead)
    844808                {
    845                     sm_pSvcListHead->m_pSvcPrev = psvc;
     809                    sm_pSvcListHead->m_pSvcPrev = pSvc;
    846810                }
    847811                else
    848812                {
    849                     sm_pSvcListTail = psvc;
     813                    sm_pSvcListTail = pSvc;
    850814                }
    851815
    852                 sm_pSvcListHead = psvc;
    853                
    854 #ifdef HGCMSS
     816                sm_pSvcListHead = pSvc;
     817
    855818                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));
    859825            }
    860826        }
    861827    }
    862828
     829    LogFlowFunc(("rc = %Vrc\n", rc));
    863830    return rc;
    864831}
    865832
     833/** The method unloads a service.
     834 *
     835 * @thread main HGCM
     836 */
     837void 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 */
     931void 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 */
     941void 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 */
    866961/* static */ void HGCMService::Reset (void)
    867962{
    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    
    873963    g_fResetting = true;
    874964
    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
    884978    g_fResetting = false;
    885979}
    886980
    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 */
    888987/* static */ int HGCMService::SaveState (PSSMHANDLE pSSM)
    889988{
     
    9251024        for (i = 0; i < pSvc->m_cClients; i++)
    9261025        {
    927             uint32_t u32ClientID = pSvc->m_paClientIds[i];
    928 
    929             Log(("client id 0x%08X\n", u32ClientID));
     1026            uint32_t u32ClientId = pSvc->m_paClientIds[i];
     1027
     1028            Log(("client id 0x%08X\n", u32ClientId));
    9301029
    9311030            /* Save the client id. */
    932             rc = SSMR3PutU32(pSSM, u32ClientID);
     1031            rc = SSMR3PutU32(pSSM, u32ClientId);
    9331032            AssertRCReturn(rc, rc);
    9341033
    9351034            /* Call the service, so the operation is executed by the service thread. */
    936             rc = pSvc->SaveState (u32ClientID, pSSM);
     1035            rc = pSvc->saveClientState (u32ClientId, pSSM);
    9371036            AssertRCReturn(rc, rc);
    9381037        }
     
    9441043}
    9451044
     1045/** The method loads saved HGCM state.
     1046 *
     1047 * @param pSSM  The saved state context.
     1048 * @return VBox rc.
     1049 * @thread main HGCM
     1050 */
    9461051/* static */ int HGCMService::LoadState (PSSMHANDLE pSSM)
    9471052{
     
    9781083   
    9791084        /* Resolve the service instance. */
    980         HGCMService *pSvc = FindServiceByName (pszServiceName);
     1085        HGCMService *pSvc;
     1086        rc = ResolveService (&pSvc, pszServiceName);
    9811087        AssertReturn(pSvc, VERR_SSM_UNEXPECTED_DATA);
    9821088           
     
    9841090        uint32_t cClients;
    9851091        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
    9881099        while (cClients--)
    9891100        {
    9901101            /* 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            }
    9941110
    9951111            /* 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            }
    9981119
    9991120            /* 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 ();
    10031131    }
    10041132
    10051133    return VINF_SUCCESS;
    10061134}
    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
    11261136/* Create a new client instance and connect it to the service.
    11271137 *
     
    11291139 *                        If NULL, use the given 'u32ClientIdIn' handle.
    11301140 * @param u32ClientIdIn   The handle for the client, when 'pu32ClientIdOut' is NULL.
    1131  *
     1141 * @return VBox rc.
    11321142 */
    11331143int HGCMService::CreateAndConnectClient (uint32_t *pu32ClientIdOut, uint32_t u32ClientIdIn)
    11341144{
    1135     /* Allocate a client information structure */
     1145    LogFlowFunc(("pu32ClientIdOut = %p, u32ClientIdIn = %d", pu32ClientIdOut, u32ClientIdIn));
     1146
     1147    /* Allocate a client information structure. */
    11361148    HGCMClient *pClient = new HGCMClient ();
    11371149
     
    11531165    }
    11541166
     1167    LogFlowFunc(("client id = %d\n", handle));
     1168
    11551169    AssertRelease(handle);
    11561170
     1171    /* Initialize the HGCM part of the client. */
    11571172    int rc = pClient->Init (this);
    11581173
    11591174    if (VBOX_SUCCESS(rc))
    11601175    {
    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        }
    11621206    }
    11631207
     
    11721216            *pu32ClientIdOut = handle;
    11731217        }
     1218
     1219        ReferenceService ();
    11741220    }
    11751221   
     1222    LogFlowFunc(("rc = %Vrc\n", rc));
    11761223    return rc;
    11771224}
    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 */
     1231int HGCMService::DisconnectClient (uint32_t u32ClientId)
     1232{
     1233    LogFlowFunc(("client id = %d\n", u32ClientId));
     1234
     1235    /* Call the service. */
    11821236    HGCMMSGHANDLE hMsg;
    11831237
    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);
    11871239
    11881240    if (VBOX_SUCCESS(rc))
    11891241    {
    1190         HGCMMsgSvcConnect *pMsg = (HGCMMsgSvcConnect *)hgcmObjReference (hMsg, HGCMOBJ_MSG);
    1191 
     1242        HGCMMsgSvcDisconnect *pMsg = (HGCMMsgSvcDisconnect *)hgcmObjReference (hMsg, HGCMOBJ_MSG);
    11921243        AssertRelease(pMsg);
    11931244
    1194         pMsg->u32ClientID = u32ClientID;
     1245        pMsg->u32ClientId = u32ClientId;
    11951246
    11961247        hgcmObjDereference (pMsg);
     
    11981249        rc = hgcmMsgSend (hMsg);
    11991250       
    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. */
    12441252        int i;
     1253
    12451254        for (i = 0; i < m_cClients; i++)
    12461255        {
    1247             if (m_paClientIds[i] == u32ClientID)
     1256            if (m_paClientIds[i] == u32ClientId)
    12481257            {
    12491258                m_cClients--;
     
    12571266            }
    12581267        }
    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));
    12651277    return rc;
    12661278}
    12671279
    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 */
     1290int HGCMService::GuestCall (PPDMIHGCMPORT pHGCMPort, PVBOXHGCMCMD pCmd, uint32_t u32ClientId, uint32_t u32Function, uint32_t cParms, VBOXHGCMSVCPARM paParms[])
    12801291{
    12811292    HGCMMSGHANDLE hMsg = 0;
     
    12831294    LogFlow(("MAIN::HGCMService::Call\n"));
    12841295
    1285     int rc = hgcmMsgAlloc (m_thread, &hMsg, HGCMMSGID_GUESTCALL, hgcmMessageAlloc);
     1296    int rc = hgcmMsgAlloc (m_thread, &hMsg, SVC_MSG_GUESTCALL, hgcmMessageAllocSvc);
    12861297
    12871298    if (VBOX_SUCCESS(rc))
     
    12941305        pMsg->pHGCMPort = pHGCMPort;
    12951306
    1296         pMsg->u32ClientID      = u32ClientID;
    1297         pMsg->u32Function      = u32Function;
    1298         pMsg->cParms           = cParms;
    1299         pMsg->paParms = paParms;
     1307        pMsg->u32ClientId = u32ClientId;
     1308        pMsg->u32Function = u32Function;
     1309        pMsg->cParms      = cParms;
     1310        pMsg->paParms     = paParms;
    13001311
    13011312        hgcmObjDereference (pMsg);
    13021313
    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);
    13121315    }
    13131316    else
     
    13191322}
    13201323
    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 */
     1331int 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
    13251336    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);
    13301338
    13311339    if (VBOX_SUCCESS(rc))
    13321340    {
    1333         HGCMMsgHostCall *pMsg = (HGCMMsgHostCall *)hgcmObjReference (hMsg, HGCMOBJ_MSG);
    1334 
     1341        HGCMMsgHostCallSvc *pMsg = (HGCMMsgHostCallSvc *)hgcmObjReference (hMsg, HGCMOBJ_MSG);
    13351342        AssertRelease(pMsg);
    1336 
    1337         pMsg->pCmd      = NULL; /* Not used for host calls. */
    1338         pMsg->pHGCMPort = NULL; /* Not used for host calls. */
    13391343
    13401344        pMsg->u32Function      = u32Function;
     
    13461350        rc = hgcmMsgSend (hMsg);
    13471351    }
    1348     else
    1349     {
    1350         Log(("MAIN::HGCMService::Call: Message allocation failed: %Vrc\n", rc));
    1351     }
    1352 
     1352
     1353    LogFlowFunc(("rc = %Vrc\n", rc));
    13531354    return rc;
    13541355}
    13551356
    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
     1372class 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
     1381class HGCMMsgMainDisconnect: public HGCMMsgHeader
     1382{
     1383    public:
     1384        /* Handle of the client to be disconnected. */
     1385        uint32_t u32ClientId;
     1386};
     1387
     1388class 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
     1397class 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
     1410class HGCMMsgMainLoadSaveState: public HGCMMsgCore
     1411{
     1412    public:
     1413        /* SSM context. */
     1414        PSSMHANDLE pSSM;
     1415};
     1416
     1417class HGCMMsgMainReset: public HGCMMsgCore
     1418{
     1419};
     1420
     1421class HGCMMsgMainQuit: public HGCMMsgCore
     1422{
     1423};
     1424
     1425static 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. */
    14151446static DECLCALLBACK(void) hgcmThread (HGCMTHREADHANDLE ThreadHandle, void *pvUser)
    14161447{
     1448    LogFlowFunc(("ThreadHandle = %p, pvUser = %p\n",
     1449                 ThreadHandle, pvUser));
     1450
    14171451    NOREF(pvUser);
    14181452
    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);
    14281459
    14291460        if (VBOX_FAILURE (rc))
    14301461        {
    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;
    14341465        }
    14351466
     
    14381469        switch (u32MsgId)
    14391470        {
    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.
    14501479                 */
    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);
    14571482
    14581483                if (VBOX_SUCCESS (rc))
    14591484                {
    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 ();
    14951490                }
    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 
    15071491            } break;
    15081492
    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);
    15191501
    15201502                if (!pClient)
    15211503                {
    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;
    15241506                }
    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))
    15261539                {
    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 ();
    15591543                }
    15601544            } break;
    15611545
    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"));
    15671549
    15681550                HGCMService::Reset ();
    15691551            } break;
    15701552
    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"));
    15771558
    15781559                rc = HGCMService::LoadState (pMsg->pSSM);
    15791560            } break;
    15801561
    1581             case HGCMMSGID_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"));
    15861567
    15871568                rc = HGCMService::SaveState (pMsg->pSSM);
    15881569            } 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
    15911580            default:
    15921581            {
    1593                 Log(("hgcmThread: Unsupported message number %08X!!!\n", u32MsgId));
     1582                AssertMsgFailed(("hgcmThread: Unsupported message number %08X!!!\n", u32MsgId));
    15941583                rc = VERR_NOT_SUPPORTED;
    15951584            } break;
    15961585        }
    15971586
     1587        /* Complete the message processing. */
    15981588        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. */
    16041600static HGCMTHREADHANDLE g_hgcmThread = 0;
    16051601
    16061602/*
    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 */
     1616int HGCMHostLoad (const char *pszServiceName,
     1617                  const char *pszServiceLibrary)
     1618{
     1619    LogFlowFunc(("name = %s, lib = %s\n", pszServiceName, pszServiceLibrary));
     1620
     1621    if (!pszServiceName || !pszServiceLibrary)
    16181622    {
    16191623        return VERR_INVALID_PARAMETER;
    16201624    }
    16211625
     1626    /* Forward the request to the main hgcm thread. */
    16221627    HGCMMSGHANDLE hMsg = 0;
    16231628
    1624     rc = hgcmMsgAlloc (g_hgcmThread, &hMsg, HGCMMSGID_CONNECT, hgcmMessageAlloc);
     1629    int rc = hgcmMsgAlloc (g_hgcmThread, &hMsg, HGCM_MSG_LOAD, hgcmMainMessageAlloc);
    16251630
    16261631    if (VBOX_SUCCESS(rc))
    16271632    {
    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);
    16301635        AssertRelease(pMsg);
    16311636
    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;
    16421639
    16431640        hgcmObjDereference (pMsg);
    16441641
    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));
    16581646    return rc;
    16591647}
    16601648
    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 */
     1658int 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)
    16731667    {
    16741668        return VERR_INVALID_PARAMETER;
    16751669    }
    16761670
     1671    /* Forward the request to the main hgcm thread. */
    16771672    HGCMMSGHANDLE hMsg = 0;
    16781673
    1679     rc = hgcmMsgAlloc (g_hgcmThread, &hMsg, HGCMMSGID_DISCONNECT, hgcmMessageAlloc);
     1674    int rc = hgcmMsgAlloc (g_hgcmThread, &hMsg, HGCM_MSG_CONNECT, hgcmMainMessageAlloc);
    16801675
    16811676    if (VBOX_SUCCESS(rc))
    16821677    {
    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);
    16851683        AssertRelease(pMsg);
    16861684
    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;
    16961689
    16971690        hgcmObjDereference (pMsg);
    16981691
    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));
    17101696    return rc;
    17111697}
    17121698
    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 */
     1706int 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. */
    17191719    HGCMMSGHANDLE hMsg = 0;
    17201720
    1721     int rc = hgcmMsgAlloc (g_hgcmThread, &hMsg, u32MsgId, hgcmMessageAlloc);
     1721    int rc = hgcmMsgAlloc (g_hgcmThread, &hMsg, HGCM_MSG_DISCONNECT, hgcmMainMessageAlloc);
    17221722
    17231723    if (VBOX_SUCCESS(rc))
    17241724    {
    1725         HGCMMsgLoadSaveState *pMsg = (HGCMMsgLoadSaveState *)hgcmObjReference (hMsg, HGCMOBJ_MSG);
     1725        /* Initialize the message. */
     1726        HGCMMsgMainDisconnect *pMsg = (HGCMMsgMainDisconnect *)hgcmObjReference (hMsg, HGCMOBJ_MSG);
    17261727        AssertRelease(pMsg);
    17271728
    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 */
     1748static 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);
    17301765
    17311766        rc = hgcmMsgSend (hMsg);
    1732 
    1733         hgcmObjDereference (pMsg);
    17341767    }
    17351768
    17361769    LogFlowFunc(("rc = %Vrc\n", rc));
    1737 
    17381770    return rc;
    17391771}
    17401772
    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 */
     1778int 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 */
     1788int 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 */
     1803int 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));
    17711834    return rc;
    17721835}
    17731836
    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 */
     1845int 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)
    18051854    {
    18061855        return VERR_INVALID_PARAMETER;
     
    18091858    HGCMMSGHANDLE hMsg = 0;
    18101859
    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);
    18121867
    18131868    if (VBOX_SUCCESS(rc))
    18141869    {
    1815         HGCMMsgLoad *pMsg = (HGCMMsgLoad *)hgcmObjReference (hMsg, HGCMOBJ_MSG);
    1816 
     1870        HGCMMsgMainHostCall *pMsg = (HGCMMsgMainHostCall *)hgcmObjReference (hMsg, HGCMOBJ_MSG);
    18171871        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     else
    1833     {
    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. */
    19011872       
    19021873        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
    19071880        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));
    19181884    return rc;
    19191885}
    19201886
    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. */
     1887int 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
     1907int 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         */
    19371918
    19381919        rc = hgcmThreadCreate (&g_hgcmThread, "MainHGCMthread", hgcmThread, NULL);
     
    19401921        if (VBOX_FAILURE (rc))
    19411922        {
    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));
    19481928    return rc;
    19491929}
    19501930
    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));
     1931int 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));
    19811960    return rc;
    19821961}
  • trunk/src/VBox/Main/hgcm/HGCMThread.cpp

    r1681 r1711  
    647647int hgcmMsgAlloc (HGCMTHREADHANDLE hThread, HGCMMSGHANDLE *pHandle, uint32_t u32MsgId, PFNHGCMNEWMSGALLOC pfnNewMessage)
    648648{
    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)));
    650650
    651651    if (!pHandle)
     
    669669    }
    670670
    671     LogFlow(("MAIN::hgcmMsgAlloc: handle %d, rc = %Vrc\n", *pHandle, rc));
     671    LogFlow(("MAIN::hgcmMsgAlloc: handle 0x%08X, rc = %Vrc\n", *pHandle, rc));
    672672
    673673    return rc;
     
    676676static int hgcmMsgPostInternal (HGCMMSGHANDLE hMsg, PHGCMMSGCALLBACK pfnCallback, bool fWait)
    677677{
    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));
    679679
    680680    int rc = VINF_SUCCESS;
     
    693693    }
    694694
    695     LogFlow(("MAIN::hgcmMsgPostInternal: hMsg %d, rc = %Vrc\n", hMsg, rc));
     695    LogFlow(("MAIN::hgcmMsgPostInternal: hMsg 0x%08X, rc = %Vrc\n", hMsg, rc));
    696696
    697697    return rc;
     
    706706int hgcmMsgPost (HGCMMSGHANDLE hMsg, PHGCMMSGCALLBACK pfnCallback)
    707707{
    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;
    709716}
    710717
     
    722729int hgcmMsgGet (HGCMTHREADHANDLE hThread, HGCMMsgCore **ppMsg)
    723730{
    724     LogFlow(("MAIN::hgcmMsgGet: hThread = %d, ppMsg = %p\n", hThread, ppMsg));
     731    LogFlow(("MAIN::hgcmMsgGet: hThread = 0x%08X, ppMsg = %p\n", hThread, ppMsg));
    725732
    726733    if (!hThread || !ppMsg)
  • trunk/src/VBox/Main/include/VMMDev.h

    r1681 r1711  
    3737    struct DRVMAINVMMDEV *mpDrv;
    3838
    39 #ifdef HGCMSS
    4039    bool fSharedFolderActive;
    4140    bool isShFlActive()
     
    4342        return fSharedFolderActive;
    4443    }
    45 #else
    46     uint32_t mSharedFolderClientId;
    47     uint32_t getShFlClientId()
    48     {
    49         return mSharedFolderClientId;
    50     }
    51 #endif /* HGCMSS */
    5244
    5345    Console *getParent()
     
    6254
    6355    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);
    6656    int hgcmHostCall (const char *pszServiceName, uint32_t u32Function, uint32_t cParms, PVBOXHGCMSVCPARM paParms);
    6757
  • trunk/src/VBox/Main/include/hgcm/HGCM.h

    r1681 r1711  
    3434
    3535__BEGIN_DECLS
    36 int hgcmInit (void);
     36int HGCMHostInit (void);
     37int HGCMHostShutdown (void);
    3738
    38 int hgcmReset (void);
     39int HGCMHostReset (void);
    3940
    40 int hgcmLoadInternal (const char *pszServiceName, const char *pszServiceLibrary);
     41int HGCMHostLoad (const char *pszServiceName, const char *pszServiceLibrary);
    4142
    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[]);
     43int HGCMGuestConnect (PPDMIHGCMPORT pHGCMPort, PVBOXHGCMCMD pCmdPtr, const char *pszServiceName, uint32_t *pClientID);
     44int HGCMGuestDisconnect (PPDMIHGCMPORT pHGCMPort, PVBOXHGCMCMD pCmdPtr, uint32_t clientID);
     45int HGCMGuestCall (PPDMIHGCMPORT pHGCMPort, PVBOXHGCMCMD pCmdPtr, uint32_t clientID, uint32_t function, uint32_t cParms, VBOXHGCMSVCPARM *paParms);
    4646
    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 */
     47int HGCMHostCall (const char *pszServiceName, uint32_t function, uint32_t cParms, VBOXHGCMSVCPARM aParms[]);
     48
     49int HGCMHostSaveState (PSSMHANDLE pSSM);
     50int HGCMHostLoadState (PSSMHANDLE pSSM);
    5451
    5552__END_DECLS
  • trunk/src/VBox/Main/include/hgcm/HGCMThread.h

    r1681 r1711  
    124124 */
    125125int hgcmThreadInit (void);
     126void hgcmThreadUninit (void);
    126127
    127128
Note: See TracChangeset for help on using the changeset viewer.

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