VirtualBox

Changeset 1711

Show
Ignore:
Timestamp:
03/27/07 10:35:21 (2 years ago)
Author:
vboxsync
Message:

HGCM cleanup.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/include/VBox/err.h

    r1650 r1711  
    914914/** The HGCM is saving state. */ 
    915915#define VINF_HGCM_SAVE_STATE                        (2906) 
     916/** Requested service already exists. */ 
     917#define VERR_HGCM_SERVICE_EXISTS                    (-2907) 
    916918 
    917919/** @} */ 
  • trunk/include/VBox/hgcmsvc.h

    r905 r1711  
    4545 * 1.1->2.1 Because the pfnConnect now also has the pvClient parameter. 
    4646 * 2.1->2.2 Because pfnSaveState and pfnLoadState were added 
     47 * 2.2->3.1 Because pfnHostCall is now synchronous, returns rc, and parameters were changed 
    4748 */ 
    4849#define VBOX_HGCM_SVC_VERSION_MINOR (0x0001) 
    49 #define VBOX_HGCM_SVC_VERSION_MAJOR (0x0002
     50#define VBOX_HGCM_SVC_VERSION_MAJOR (0x0003
    5051#define VBOX_HGCM_SVC_VERSION ((VBOX_HGCM_SVC_VERSION_MAJOR << 16) + VBOX_HGCM_SVC_VERSION_MINOR) 
    5152 
     
    139140     *  Return code is passed to pfnCallComplete callback. 
    140141     */ 
    141     DECLCALLBACKMEMBER(void, pfnHostCall) (VBOXHGCMCALLHANDLE callHandle, uint32_t u32ClientID, void *pvClient, uint32_t function, uint32_t cParms, VBOXHGCMSVCPARM paParms[]); 
     142    DECLCALLBACKMEMBER(int, pfnHostCall) (uint32_t function, uint32_t cParms, VBOXHGCMSVCPARM paParms[]); 
    142143  
    143144    /** Inform the service about a VM save operation. */ 
  • 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