HGCM.cpp revision 6ef36e19210a6d8b4d90b881f155581cb3cb3979
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync * HGCM (Host-Guest Communication Manager)
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync * Copyright (C) 2006-2007 Oracle Corporation
cf5f6bf2704d4fff443139e10bccc6a0a7fa4b85vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
cf5f6bf2704d4fff443139e10bccc6a0a7fa4b85vboxsync * available from http://www.virtualbox.org. This file is free software;
cf5f6bf2704d4fff443139e10bccc6a0a7fa4b85vboxsync * you can redistribute it and/or modify it under the terms of the GNU
cf5f6bf2704d4fff443139e10bccc6a0a7fa4b85vboxsync * General Public License (GPL) as published by the Free Software
cf5f6bf2704d4fff443139e10bccc6a0a7fa4b85vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
cf5f6bf2704d4fff443139e10bccc6a0a7fa4b85vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
aef51041e0fe31e8ea903dd7e67fe12cef645654vboxsync * A service gets one thread, which synchronously delivers messages to
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync * the service. This is good for serialization.
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync * Some services may want to process messages asynchronously, and will want
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync * a next message to be delivered, while a previous message is still being
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync * processed.
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync * The dedicated service thread delivers a next message when service
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync * returns after fetching a previous one. The service will call a message
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync * completion callback when message is actually processed. So returning
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync * from the service call means only that the service is processing message.
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync * 'Message processed' condition is indicated by service, which call the
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync * callback, even if the callback is called synchronously in the dedicated
79baed6836ae36c5f15b182292387484dcf7a752vboxsync * This message completion callback is only valid for Call requests.
79baed6836ae36c5f15b182292387484dcf7a752vboxsync * Connect and Disconnect are processed synchronously by the service.
79baed6836ae36c5f15b182292387484dcf7a752vboxsync/* The maximum allowed size of a service name in bytes. */
79baed6836ae36c5f15b182292387484dcf7a752vboxsync /* The service name follows. */
aef51041e0fe31e8ea903dd7e67fe12cef645654vboxsync/** Internal helper service object. HGCM code would use it to
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync * hold information about services and communicate with services.
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync * The HGCMService is an (in future) abstract class that implements
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync * common functionality. There will be derived classes for specific
79baed6836ae36c5f15b182292387484dcf7a752vboxsync * service types.
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync friend DECLCALLBACK(void) hgcmServiceThread (HGCMTHREADHANDLE ThreadHandle, void *pvUser);
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync * Main HGCM thread methods.
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync int instanceCreate (const char *pszServiceLibrary, const char *pszServiceName);
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync int saveClientState(uint32_t u32ClientId, PSSMHANDLE pSSM);
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync int loadClientState(uint32_t u32ClientId, PSSMHANDLE pSSM);
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync static DECLCALLBACK(void) svcHlpCallComplete (VBOXHGCMCALLHANDLE callHandle, int32_t rc);
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync static DECLCALLBACK(void) svcHlpDisconnectClient (void *pvInstance, uint32_t u32ClientId);
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync * Main HGCM thread methods.
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync static int LoadService (const char *pszServiceLibrary, const char *pszServiceName);
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync static void UnloadAll (void);
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync static int ResolveService (HGCMService **ppsvc, const char *pszServiceName);
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync static void Reset (void);
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync int CreateAndConnectClient (uint32_t *pu32ClientIdOut, uint32_t u32ClientIdIn);
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync int DisconnectClient (uint32_t u32ClientId, bool fFromService);
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync int HostCall (uint32_t u32Function, uint32_t cParms, VBOXHGCMSVCPARM *paParms);
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync int HostFastCallAsync (uint32_t u32Function, VBOXHGCMSVCPARM *pParm, PHGCMHOSTFASTCALLCB pfnCompletion, void *pvCompletion);
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync uint32_t SizeOfClient (void) { return m_fntable.cbClient; };
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync int RegisterExtension (HGCMSVCEXTHANDLE handle, PFNHGCMSVCEXT pfnExtension, void *pvExtension);
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync void UnregisterExtension (HGCMSVCEXTHANDLE handle);
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync * The service thread methods.
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync int GuestCall (PPDMIHGCMPORT pHGCMPort, PVBOXHGCMCMD pCmd, uint32_t u32ClientId, uint32_t u32Function, uint32_t cParms, VBOXHGCMSVCPARM aParms[]);
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync HGCMClient () : HGCMObject(HGCMOBJ_CLIENT), pService(NULL),
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync /** Service that the client is connected to. */
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync /** Client specific data. */
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync#define HGCM_CLIENT_DATA(pService, pClient) (pClient->pvData)
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsyncstatic bool g_fResetting = false;
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsyncstatic bool g_fSaveState = false;
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync/** Helper function to load a local service DLL.
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync * @return VBox code
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync LogFlowFunc(("m_pszSvcLibrary = %s\n", m_pszSvcLibrary));
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync int rc = SUPR3HardenedLdrLoadAppPriv (m_pszSvcLibrary, &m_hLdrMod, szErr, sizeof(szErr));
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync LogFlowFunc(("successfully loaded the library.\n"));
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync rc = RTLdrGetSymbol (m_hLdrMod, VBOX_HGCM_SVCLOAD_NAME, (void**)&m_pfnLoad);
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync Log(("HGCMService::loadServiceDLL: Error resolving the service entry point %s, rc = %d, m_pfnLoad = %p\n", VBOX_HGCM_SVCLOAD_NAME, rc, m_pfnLoad));
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync /* m_pfnLoad was NULL */
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync Log(("HGCMService::loadServiceDLL: at least one of function pointers is NULL\n"));
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync LogRel(("HGCM: Failed to load the service library: [%s], rc = %Rrc - %s. The service will be not available.\n",
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync/** Helper function to free a local service DLL.
11d3005e2935c925665896fa26fde09b3e656d70vboxsync * @return VBox code
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync * Messages processed by service threads. These threads only call the service entry points.
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync#define SVC_MSG_LOAD (0) /* Load the service library and call VBOX_HGCM_SVCLOAD_NAME entry point. */
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync#define SVC_MSG_UNLOAD (1) /* call pfnUnload and unload the service library. */
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync#define SVC_MSG_QUIT (8) /* Terminate the thread. */
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync#define SVC_MSG_REGEXT (9) /* pfnRegisterExtension */
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync#define SVC_MSG_UNREGEXT (10) /* pfnRegisterExtension */
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync# define SVC_MSG_HOSTFASTCALLASYNC (21) /* pfnHostCall */
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync /* client identifier */
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync /* client identifier */
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync HGCMMsgHeader () : pCmd (NULL), pHGCMPort (NULL) {};
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync /* Command pointer/identifier. */
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync /* Port to be informed on message completion. */
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync /* client identifier */
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync /* function number */
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync /* number of parameters */
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsyncclass HGCMMsgLoadSaveStateClient: public HGCMMsgCore
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync /* function number */
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync /* number of parameters */
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsyncclass HGCMMsgSvcRegisterExtension: public HGCMMsgCore
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync /* Handle of the extension to be registered. */
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync /* The extension entry point. */
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync /* The extension pointer. */
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsyncclass HGCMMsgSvcUnregisterExtension: public HGCMMsgCore
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync /* Handle of the registered extension. */
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsyncclass HGCMMsgHostFastCallAsyncSvc: public HGCMMsgCore
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync /* function number */
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync /* parameter */
11d3005e2935c925665896fa26fde09b3e656d70vboxsync /* completion info */
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsyncstatic HGCMMsgCore *hgcmMessageAllocSvc (uint32_t u32MsgId)
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync case SVC_MSG_HOSTFASTCALLASYNC: return new HGCMMsgHostFastCallAsyncSvc ();
befced03fd84a13590b8ce8be8c2480e9bc568c6vboxsync case SVC_MSG_UNLOAD: return new HGCMMsgSvcUnload ();
befced03fd84a13590b8ce8be8c2480e9bc568c6vboxsync case SVC_MSG_CONNECT: return new HGCMMsgSvcConnect ();
befced03fd84a13590b8ce8be8c2480e9bc568c6vboxsync case SVC_MSG_DISCONNECT: return new HGCMMsgSvcDisconnect ();
befced03fd84a13590b8ce8be8c2480e9bc568c6vboxsync case SVC_MSG_HOSTCALL: return new HGCMMsgHostCallSvc ();
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync case SVC_MSG_SAVESTATE: return new HGCMMsgLoadSaveStateClient ();
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync case SVC_MSG_REGEXT: return new HGCMMsgSvcRegisterExtension ();
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync case SVC_MSG_UNREGEXT: return new HGCMMsgSvcUnregisterExtension ();
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync AssertReleaseMsgFailed(("Msg id = %08X\n", u32MsgId));
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync * The service thread. Loads the service library and calls the service entry points.
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsyncDECLCALLBACK(void) hgcmServiceThread (HGCMTHREADHANDLE ThreadHandle, void *pvUser)
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync bool fQuit = false;
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync /* The error means some serious unrecoverable problem in the hgcmMsg/hgcmThread layer. */
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync /* Cache required information to avoid unnecessary pMsgCore access. */
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync HGCMMsgHostFastCallAsyncSvc *pMsg = (HGCMMsgHostFastCallAsyncSvc *)pMsgCore;
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync LogFlowFunc(("SVC_MSG_HOSTFASTCALLASYNC u32Function = %d, pParm = %p\n", pMsg->u32Function, &pMsg->Param));
16d723d9d597f4872dd4c2c960af9cbca4ed63bdvboxsync rc = pSvc->m_fntable.pfnHostCall (pSvc->m_fntable.pvService, pMsg->u32Function, 1, &pMsg->Param);
16d723d9d597f4872dd4c2c960af9cbca4ed63bdvboxsync pSvc->m_fntable.pfnUnload (pSvc->m_fntable.pvService);
79baed6836ae36c5f15b182292387484dcf7a752vboxsync HGCMMsgSvcConnect *pMsg = (HGCMMsgSvcConnect *)pMsgCore;
79baed6836ae36c5f15b182292387484dcf7a752vboxsync LogFlowFunc(("SVC_MSG_CONNECT u32ClientId = %d\n", pMsg->u32ClientId));
79baed6836ae36c5f15b182292387484dcf7a752vboxsync HGCMClient *pClient = (HGCMClient *)hgcmObjReference (pMsg->u32ClientId, HGCMOBJ_CLIENT);
79baed6836ae36c5f15b182292387484dcf7a752vboxsync rc = pSvc->m_fntable.pfnConnect (pSvc->m_fntable.pvService, pMsg->u32ClientId, HGCM_CLIENT_DATA(pSvc, pClient));
79baed6836ae36c5f15b182292387484dcf7a752vboxsync HGCMMsgSvcDisconnect *pMsg = (HGCMMsgSvcDisconnect *)pMsgCore;
79baed6836ae36c5f15b182292387484dcf7a752vboxsync LogFlowFunc(("SVC_MSG_DISCONNECT u32ClientId = %d\n", pMsg->u32ClientId));
79baed6836ae36c5f15b182292387484dcf7a752vboxsync HGCMClient *pClient = (HGCMClient *)hgcmObjReference (pMsg->u32ClientId, HGCMOBJ_CLIENT);
79baed6836ae36c5f15b182292387484dcf7a752vboxsync rc = pSvc->m_fntable.pfnDisconnect (pSvc->m_fntable.pvService, pMsg->u32ClientId, HGCM_CLIENT_DATA(pSvc, pClient));
79baed6836ae36c5f15b182292387484dcf7a752vboxsync LogFlowFunc(("SVC_MSG_GUESTCALL u32ClientId = %d, u32Function = %d, cParms = %d, paParms = %p\n",
79baed6836ae36c5f15b182292387484dcf7a752vboxsync pMsg->u32ClientId, pMsg->u32Function, pMsg->cParms, pMsg->paParms));
79baed6836ae36c5f15b182292387484dcf7a752vboxsync HGCMClient *pClient = (HGCMClient *)hgcmObjReference (pMsg->u32ClientId, HGCMOBJ_CLIENT);
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync pSvc->m_fntable.pfnCall (pSvc->m_fntable.pvService, (VBOXHGCMCALLHANDLE)pMsg, pMsg->u32ClientId, HGCM_CLIENT_DATA(pSvc, pClient), pMsg->u32Function, pMsg->cParms, pMsg->paParms);
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync HGCMMsgHostCallSvc *pMsg = (HGCMMsgHostCallSvc *)pMsgCore;
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync LogFlowFunc(("SVC_MSG_HOSTCALL u32Function = %d, cParms = %d, paParms = %p\n", pMsg->u32Function, pMsg->cParms, pMsg->paParms));
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync rc = pSvc->m_fntable.pfnHostCall (pSvc->m_fntable.pvService, pMsg->u32Function, pMsg->cParms, pMsg->paParms);
79baed6836ae36c5f15b182292387484dcf7a752vboxsync HGCMMsgLoadSaveStateClient *pMsg = (HGCMMsgLoadSaveStateClient *)pMsgCore;
69c6eff4fcb6dc027e94a3e7908926c4e8ef5aefvboxsync HGCMClient *pClient = (HGCMClient *)hgcmObjReference (pMsg->u32ClientId, HGCMOBJ_CLIENT);
79baed6836ae36c5f15b182292387484dcf7a752vboxsync rc = pSvc->m_fntable.pfnLoadState (pSvc->m_fntable.pvService, pMsg->u32ClientId, HGCM_CLIENT_DATA(pSvc, pClient), pMsg->pSSM);
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync HGCMMsgLoadSaveStateClient *pMsg = (HGCMMsgLoadSaveStateClient *)pMsgCore;
79baed6836ae36c5f15b182292387484dcf7a752vboxsync HGCMClient *pClient = (HGCMClient *)hgcmObjReference (pMsg->u32ClientId, HGCMOBJ_CLIENT);
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync rc = pSvc->m_fntable.pfnSaveState (pSvc->m_fntable.pvService, pMsg->u32ClientId, HGCM_CLIENT_DATA(pSvc, pClient), pMsg->pSSM);
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync HGCMMsgSvcRegisterExtension *pMsg = (HGCMMsgSvcRegisterExtension *)pMsgCore;
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync LogFlowFunc(("SVC_MSG_REGEXT handle = %p, pfn = %p\n", pMsg->handle, pMsg->pfnExtension));
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync rc = pSvc->m_fntable.pfnRegisterExtension (pSvc->m_fntable.pvService, pMsg->pfnExtension, pMsg->pvExtension);
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync HGCMMsgSvcUnregisterExtension *pMsg = (HGCMMsgSvcUnregisterExtension *)pMsgCore;
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync LogFlowFunc(("SVC_MSG_UNREGEXT handle = %p\n", pMsg->handle));
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync rc = pSvc->m_fntable.pfnRegisterExtension (pSvc->m_fntable.pvService, NULL, NULL);
79baed6836ae36c5f15b182292387484dcf7a752vboxsync AssertMsgFailed(("hgcmServiceThread::Unsupported message number %08X\n", u32MsgId));
27152389a84c6dec057fba6fc21241991e079006vboxsync /* For SVC_MSG_GUESTCALL the service calls the completion helper.
27152389a84c6dec057fba6fc21241991e079006vboxsync * Other messages have to be completed here.
27152389a84c6dec057fba6fc21241991e079006vboxsync/* static */ DECLCALLBACK(void) HGCMService::svcHlpCallComplete (VBOXHGCMCALLHANDLE callHandle, int32_t rc)
27152389a84c6dec057fba6fc21241991e079006vboxsync /* Only call the completion for these messages. The helper
27152389a84c6dec057fba6fc21241991e079006vboxsync * is called by the service, and the service does not get
27152389a84c6dec057fba6fc21241991e079006vboxsync * any other messages.
27152389a84c6dec057fba6fc21241991e079006vboxsync/* static */ DECLCALLBACK(void) HGCMService::svcHlpDisconnectClient (void *pvInstance, uint32_t u32ClientId)
27152389a84c6dec057fba6fc21241991e079006vboxsync HGCMService *pService = static_cast <HGCMService *> (pvInstance);
27152389a84c6dec057fba6fc21241991e079006vboxsyncstatic DECLCALLBACK(void) hgcmMsgCompletionCallback (int32_t result, HGCMMsgCore *pMsgCore)
27152389a84c6dec057fba6fc21241991e079006vboxsync /* Call the VMMDev port interface to issue IRQ notification. */
27152389a84c6dec057fba6fc21241991e079006vboxsync HGCMMsgHeader *pMsgHdr = (HGCMMsgHeader *)pMsgCore;
27152389a84c6dec057fba6fc21241991e079006vboxsync LogFlow(("MAIN::hgcmMsgCompletionCallback: message %p\n", pMsgCore));
27152389a84c6dec057fba6fc21241991e079006vboxsync pMsgHdr->pHGCMPort->pfnCompleted (pMsgHdr->pHGCMPort, g_fSaveState? VINF_HGCM_SAVE_STATE: result, pMsgHdr->pCmd);
27152389a84c6dec057fba6fc21241991e079006vboxsync * The main HGCM methods of the service.
27152389a84c6dec057fba6fc21241991e079006vboxsyncint HGCMService::instanceCreate (const char *pszServiceLibrary, const char *pszServiceName)
27152389a84c6dec057fba6fc21241991e079006vboxsync LogFlowFunc(("name %s, lib %s\n", pszServiceName, pszServiceLibrary));
27152389a84c6dec057fba6fc21241991e079006vboxsync /* The maximum length of the thread name, allowed by the RT is 15. */
27152389a84c6dec057fba6fc21241991e079006vboxsync int rc = hgcmThreadCreate (&m_thread, achThreadName, hgcmServiceThread, this);
27152389a84c6dec057fba6fc21241991e079006vboxsync /* Initialize service helpers table. */
27152389a84c6dec057fba6fc21241991e079006vboxsync m_svcHelpers.pfnDisconnectClient = svcHlpDisconnectClient;
27152389a84c6dec057fba6fc21241991e079006vboxsync /* Execute the load request on the service thread. */
27152389a84c6dec057fba6fc21241991e079006vboxsync rc = hgcmMsgAlloc (m_thread, &hMsg, SVC_MSG_LOAD, hgcmMessageAllocSvc);
27152389a84c6dec057fba6fc21241991e079006vboxsync int rc = hgcmMsgAlloc (m_thread, &hMsg, SVC_MSG_UNLOAD, hgcmMessageAllocSvc);
27152389a84c6dec057fba6fc21241991e079006vboxsyncint HGCMService::saveClientState(uint32_t u32ClientId, PSSMHANDLE pSSM)
27152389a84c6dec057fba6fc21241991e079006vboxsync int rc = hgcmMsgAlloc (m_thread, &hMsg, SVC_MSG_SAVESTATE, hgcmMessageAllocSvc);
27152389a84c6dec057fba6fc21241991e079006vboxsync HGCMMsgLoadSaveStateClient *pMsg = (HGCMMsgLoadSaveStateClient *)hgcmObjReference (hMsg, HGCMOBJ_MSG);
27152389a84c6dec057fba6fc21241991e079006vboxsyncint HGCMService::loadClientState (uint32_t u32ClientId, PSSMHANDLE pSSM)
27152389a84c6dec057fba6fc21241991e079006vboxsync int rc = hgcmMsgAlloc (m_thread, &hMsg, SVC_MSG_LOADSTATE, hgcmMessageAllocSvc);
27152389a84c6dec057fba6fc21241991e079006vboxsync HGCMMsgLoadSaveStateClient *pMsg = (HGCMMsgLoadSaveStateClient *)hgcmObjReference (hMsg, HGCMOBJ_MSG);
27152389a84c6dec057fba6fc21241991e079006vboxsync/** The method creates a service and references it.
27152389a84c6dec057fba6fc21241991e079006vboxsync * @param pszServiceLibrary The library to be loaded.
27152389a84c6dec057fba6fc21241991e079006vboxsync * @param pszServiceName The name of the service.
27152389a84c6dec057fba6fc21241991e079006vboxsync * @return VBox rc.
27152389a84c6dec057fba6fc21241991e079006vboxsync * @thread main HGCM
27152389a84c6dec057fba6fc21241991e079006vboxsync/* static */ int HGCMService::LoadService (const char *pszServiceLibrary, const char *pszServiceName)
27152389a84c6dec057fba6fc21241991e079006vboxsync LogFlowFunc(("lib %s, name = %s\n", pszServiceLibrary, pszServiceName));
27152389a84c6dec057fba6fc21241991e079006vboxsync /* Look at already loaded services to avoid double loading. */
27152389a84c6dec057fba6fc21241991e079006vboxsync int rc = HGCMService::ResolveService (&pSvc, pszServiceName);
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync /* The service is already loaded. */
27152389a84c6dec057fba6fc21241991e079006vboxsync /* Create the new service. */
27152389a84c6dec057fba6fc21241991e079006vboxsync /* Load the library and call the initialization entry point. */
27152389a84c6dec057fba6fc21241991e079006vboxsync rc = pSvc->instanceCreate (pszServiceLibrary, pszServiceName);
27152389a84c6dec057fba6fc21241991e079006vboxsync /* Insert the just created service to list for future references. */
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync /* Reference the service (for first time) until it is unloaded on HGCM termination. */
27152389a84c6dec057fba6fc21241991e079006vboxsync/** The method unloads a service.
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync * @thread main HGCM
27152389a84c6dec057fba6fc21241991e079006vboxsync /* Remove the service from the list. */
27152389a84c6dec057fba6fc21241991e079006vboxsync /* The service must be unloaded only if all clients were disconnected. */
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync /* Now the service can be released. */
27152389a84c6dec057fba6fc21241991e079006vboxsync/** The method unloads all services.
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync * @thread main HGCM
27152389a84c6dec057fba6fc21241991e079006vboxsync/** The method obtains a referenced pointer to the service with
27152389a84c6dec057fba6fc21241991e079006vboxsync * specified name. The caller must call ReleaseService when
27152389a84c6dec057fba6fc21241991e079006vboxsync * the pointer is no longer needed.
27152389a84c6dec057fba6fc21241991e079006vboxsync * @param ppSvc Where to store the pointer to the service.
79baed6836ae36c5f15b182292387484dcf7a752vboxsync * @param pszServiceName The name of the service.
27152389a84c6dec057fba6fc21241991e079006vboxsync * @return VBox rc.
27152389a84c6dec057fba6fc21241991e079006vboxsync * @thread main HGCM
27152389a84c6dec057fba6fc21241991e079006vboxsync/* static */ int HGCMService::ResolveService (HGCMService **ppSvc, const char *pszServiceName)
27152389a84c6dec057fba6fc21241991e079006vboxsync if (strcmp (pSvc->m_pszSvcName, pszServiceName) == 0)
27152389a84c6dec057fba6fc21241991e079006vboxsync/** The method increases reference counter.
27152389a84c6dec057fba6fc21241991e079006vboxsync * @thread main HGCM
27152389a84c6dec057fba6fc21241991e079006vboxsync LogFlowFunc(("[%s] m_u32RefCnt = %d\n", m_pszSvcName, m_u32RefCnt));
27152389a84c6dec057fba6fc21241991e079006vboxsync/** The method dereferences a service and deletes it when no more refs.
27152389a84c6dec057fba6fc21241991e079006vboxsync * @thread main HGCM
27152389a84c6dec057fba6fc21241991e079006vboxsync uint32_t u32RefCnt = ASMAtomicDecU32 (&m_u32RefCnt);
27152389a84c6dec057fba6fc21241991e079006vboxsync LogFlowFunc(("u32RefCnt = %d, name %s\n", u32RefCnt, m_pszSvcName));
27152389a84c6dec057fba6fc21241991e079006vboxsync delete this;
27152389a84c6dec057fba6fc21241991e079006vboxsync/** The method is called when the VM is being reset or terminated
27152389a84c6dec057fba6fc21241991e079006vboxsync * and disconnects all clients from all services.
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync * @thread main HGCM
27152389a84c6dec057fba6fc21241991e079006vboxsync LogFlowFunc(("handle %d\n", pSvc->m_paClientIds[0]));
27152389a84c6dec057fba6fc21241991e079006vboxsync pSvc->DisconnectClient (pSvc->m_paClientIds[0], false);
27152389a84c6dec057fba6fc21241991e079006vboxsync /* @todo: could this actually happen that the service is destroyed on ReleaseService? */
27152389a84c6dec057fba6fc21241991e079006vboxsync/** The method saves the HGCM state.
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync * @param pSSM The saved state context.
27152389a84c6dec057fba6fc21241991e079006vboxsync * @return VBox rc.
27152389a84c6dec057fba6fc21241991e079006vboxsync * @thread main HGCM
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync/* static */ int HGCMService::SaveState (PSSMHANDLE pSSM)
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync /* Save the current handle count and restore afterwards to avoid client id conflicts. */
27152389a84c6dec057fba6fc21241991e079006vboxsync int rc = SSMR3PutU32(pSSM, hgcmObjQueryHandleCount());
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync LogFlowFunc(("%d services to be saved:\n", sm_cServices));
27152389a84c6dec057fba6fc21241991e079006vboxsync /* Save number of services. */
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync /* Save every service. */
27152389a84c6dec057fba6fc21241991e079006vboxsync LogFlowFunc(("Saving service [%s]\n", pSvc->m_pszSvcName));
27152389a84c6dec057fba6fc21241991e079006vboxsync /* Save the length of the service name. */
27152389a84c6dec057fba6fc21241991e079006vboxsync rc = SSMR3PutU32(pSSM, (uint32_t) strlen(pSvc->m_pszSvcName) + 1);
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync /* Save the name of the service. */
27152389a84c6dec057fba6fc21241991e079006vboxsync /* Save the number of clients. */
27152389a84c6dec057fba6fc21241991e079006vboxsync /* Call the service for every client. Normally a service must not have
27152389a84c6dec057fba6fc21241991e079006vboxsync * a global state to be saved: only per client info is relevant.
27152389a84c6dec057fba6fc21241991e079006vboxsync * The global state of a service is configured during VM startup.
895d68f6e6c15446ca98b8f6ec96ce19d7ea356fvboxsync /* Save the client id. */
27152389a84c6dec057fba6fc21241991e079006vboxsync /* Call the service, so the operation is executed by the service thread. */
27152389a84c6dec057fba6fc21241991e079006vboxsync/** The method loads saved HGCM state.
27152389a84c6dec057fba6fc21241991e079006vboxsync * @param pSSM The saved state context.
27152389a84c6dec057fba6fc21241991e079006vboxsync * @return VBox rc.
27152389a84c6dec057fba6fc21241991e079006vboxsync * @thread main HGCM
27152389a84c6dec057fba6fc21241991e079006vboxsync/* static */ int HGCMService::LoadState (PSSMHANDLE pSSM)
27152389a84c6dec057fba6fc21241991e079006vboxsync /* Restore handle count to avoid client id conflicts. */
27152389a84c6dec057fba6fc21241991e079006vboxsync /* Get the number of services. */
27152389a84c6dec057fba6fc21241991e079006vboxsync LogFlowFunc(("%d services to be restored:\n", cServices));
27152389a84c6dec057fba6fc21241991e079006vboxsync /* Get the length of the service name. */
ce9015004a47e95eb75e047ba42f2d3200d2d222vboxsync AssertReturn(u32 <= VBOX_HGCM_SVC_NAME_MAX_BYTES, VERR_SSM_UNEXPECTED_DATA);
27152389a84c6dec057fba6fc21241991e079006vboxsync /* Get the service name. */
27152389a84c6dec057fba6fc21241991e079006vboxsync LogRel(("HGCM: restoring [%s]\n", pszServiceName));
27152389a84c6dec057fba6fc21241991e079006vboxsync /* Resolve the service instance. */
27152389a84c6dec057fba6fc21241991e079006vboxsync AssertLogRelMsgReturn(pSvc, ("rc=%Rrc, %s\n", rc, pszServiceName), VERR_SSM_UNEXPECTED_DATA);
27152389a84c6dec057fba6fc21241991e079006vboxsync /* Get the number of clients. */
27152389a84c6dec057fba6fc21241991e079006vboxsync /* Get the client id. */
27152389a84c6dec057fba6fc21241991e079006vboxsync /* Connect the client. */
27152389a84c6dec057fba6fc21241991e079006vboxsync rc = pSvc->CreateAndConnectClient (NULL, u32ClientId);
27152389a84c6dec057fba6fc21241991e079006vboxsync AssertLogRelMsgFailed(("rc=%Rrc %s\n", rc, pszServiceName));
27152389a84c6dec057fba6fc21241991e079006vboxsync /* Call the service, so the operation is executed by the service thread. */
27152389a84c6dec057fba6fc21241991e079006vboxsync AssertLogRelMsgFailed(("rc=%Rrc %s\n", rc, pszServiceName));
27152389a84c6dec057fba6fc21241991e079006vboxsync/* Create a new client instance and connect it to the service.
27152389a84c6dec057fba6fc21241991e079006vboxsync * @param pu32ClientIdOut If not NULL, then the method must generate a new handle for the client.
27152389a84c6dec057fba6fc21241991e079006vboxsync * If NULL, use the given 'u32ClientIdIn' handle.
27152389a84c6dec057fba6fc21241991e079006vboxsync * @param u32ClientIdIn The handle for the client, when 'pu32ClientIdOut' is NULL.
27152389a84c6dec057fba6fc21241991e079006vboxsync * @return VBox rc.
27152389a84c6dec057fba6fc21241991e079006vboxsyncint HGCMService::CreateAndConnectClient (uint32_t *pu32ClientIdOut, uint32_t u32ClientIdIn)
27152389a84c6dec057fba6fc21241991e079006vboxsync LogFlowFunc(("pu32ClientIdOut = %p, u32ClientIdIn = %d\n", pu32ClientIdOut, u32ClientIdIn));
27152389a84c6dec057fba6fc21241991e079006vboxsync /* Allocate a client information structure. */
27152389a84c6dec057fba6fc21241991e079006vboxsync LogWarningFunc(("Could not allocate HGCMClient!!!\n"));
5558d00238c7e019ef8c0803358fae6edeba394evboxsync handle = hgcmObjAssignHandle (pClient, u32ClientIdIn);
27152389a84c6dec057fba6fc21241991e079006vboxsync /* Initialize the HGCM part of the client. */
ce9015004a47e95eb75e047ba42f2d3200d2d222vboxsync /* Call the service. */
ce9015004a47e95eb75e047ba42f2d3200d2d222vboxsync rc = hgcmMsgAlloc (m_thread, &hMsg, SVC_MSG_CONNECT, hgcmMessageAllocSvc);
27152389a84c6dec057fba6fc21241991e079006vboxsync HGCMMsgSvcConnect *pMsg = (HGCMMsgSvcConnect *)hgcmObjReference (hMsg, HGCMOBJ_MSG);
27152389a84c6dec057fba6fc21241991e079006vboxsync /* Add the client Id to the array. */
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync m_paClientIds = (uint32_t *)RTMemRealloc (m_paClientIds, (m_cClientsAllocated + 64) * sizeof (m_paClientIds[0]));
27152389a84c6dec057fba6fc21241991e079006vboxsync/* Disconnect the client from the service and delete the client handle.
feef019e08ac3cead66d03feb9094cac75d9bc0dvboxsync * @param u32ClientId The handle of the client.
feef019e08ac3cead66d03feb9094cac75d9bc0dvboxsync * @return VBox rc.
feef019e08ac3cead66d03feb9094cac75d9bc0dvboxsyncint HGCMService::DisconnectClient (uint32_t u32ClientId, bool fFromService)
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync LogFlowFunc(("client id = %d, fFromService = %d\n", u32ClientId, fFromService));
27152389a84c6dec057fba6fc21241991e079006vboxsync /* Call the service. */
27152389a84c6dec057fba6fc21241991e079006vboxsync rc = hgcmMsgAlloc (m_thread, &hMsg, SVC_MSG_DISCONNECT, hgcmMessageAllocSvc);
27152389a84c6dec057fba6fc21241991e079006vboxsync HGCMMsgSvcDisconnect *pMsg = (HGCMMsgSvcDisconnect *)hgcmObjReference (hMsg, HGCMOBJ_MSG);
27152389a84c6dec057fba6fc21241991e079006vboxsync LogRel(("(%d, %d) [%s] hgcmMsgAlloc(%p, SVC_MSG_DISCONNECT) failed %Rrc\n",
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync u32ClientId, fFromService, RT_VALID_PTR(m_pszSvcName)? m_pszSvcName: "", m_thread, rc));
27152389a84c6dec057fba6fc21241991e079006vboxsync /* Remove the client id from the array in any case, rc does not matter. */
27152389a84c6dec057fba6fc21241991e079006vboxsync for (i = 0; i < m_cClients; i++)
27152389a84c6dec057fba6fc21241991e079006vboxsync memmove (&m_paClientIds[i], &m_paClientIds[i + 1], sizeof (m_paClientIds[0]) * (m_cClients - i));
27152389a84c6dec057fba6fc21241991e079006vboxsync /* Delete the client handle. */
27152389a84c6dec057fba6fc21241991e079006vboxsync /* The service must be released. */
27152389a84c6dec057fba6fc21241991e079006vboxsyncint HGCMService::RegisterExtension (HGCMSVCEXTHANDLE handle,
27152389a84c6dec057fba6fc21241991e079006vboxsync /* Forward the message to the service thread. */
27152389a84c6dec057fba6fc21241991e079006vboxsync int rc = hgcmMsgAlloc (m_thread, &hMsg, SVC_MSG_REGEXT, hgcmMessageAllocSvc);
27152389a84c6dec057fba6fc21241991e079006vboxsync HGCMMsgSvcRegisterExtension *pMsg = (HGCMMsgSvcRegisterExtension *)hgcmObjReference (hMsg, HGCMOBJ_MSG);
27152389a84c6dec057fba6fc21241991e079006vboxsyncvoid HGCMService::UnregisterExtension (HGCMSVCEXTHANDLE handle)
27152389a84c6dec057fba6fc21241991e079006vboxsync /* Forward the message to the service thread. */
27152389a84c6dec057fba6fc21241991e079006vboxsync int rc = hgcmMsgAlloc (m_thread, &hMsg, SVC_MSG_UNREGEXT, hgcmMessageAllocSvc);
27152389a84c6dec057fba6fc21241991e079006vboxsync HGCMMsgSvcUnregisterExtension *pMsg = (HGCMMsgSvcUnregisterExtension *)hgcmObjReference (hMsg, HGCMOBJ_MSG);
27152389a84c6dec057fba6fc21241991e079006vboxsync/* Perform a guest call to the service.
27152389a84c6dec057fba6fc21241991e079006vboxsync * @param pHGCMPort The port to be used for completion confirmation.
27152389a84c6dec057fba6fc21241991e079006vboxsync * @param pCmd The VBox HGCM context.
27152389a84c6dec057fba6fc21241991e079006vboxsync * @param u32ClientId The client handle to be disconnected and deleted.
27152389a84c6dec057fba6fc21241991e079006vboxsync * @param u32Function The function number.
27152389a84c6dec057fba6fc21241991e079006vboxsync * @param cParms Number of parameters.
27152389a84c6dec057fba6fc21241991e079006vboxsync * @param paParms Pointer to array of parameters.
27152389a84c6dec057fba6fc21241991e079006vboxsync * @return VBox rc.
27152389a84c6dec057fba6fc21241991e079006vboxsyncint HGCMService::GuestCall (PPDMIHGCMPORT pHGCMPort, PVBOXHGCMCMD pCmd, uint32_t u32ClientId, uint32_t u32Function, uint32_t cParms, VBOXHGCMSVCPARM paParms[])
27152389a84c6dec057fba6fc21241991e079006vboxsync int rc = hgcmMsgAlloc (m_thread, &hMsg, SVC_MSG_GUESTCALL, hgcmMessageAllocSvc);
85e5ab5adbba74b522731762dd05ca88cb529140vboxsync HGCMMsgCall *pMsg = (HGCMMsgCall *)hgcmObjReference (hMsg, HGCMOBJ_MSG);
27152389a84c6dec057fba6fc21241991e079006vboxsync rc = hgcmMsgPost (hMsg, hgcmMsgCompletionCallback);
5558d00238c7e019ef8c0803358fae6edeba394evboxsync Log(("MAIN::HGCMService::Call: Message allocation failed: %Rrc\n", rc));
27152389a84c6dec057fba6fc21241991e079006vboxsync/* Perform a host call the service.
27152389a84c6dec057fba6fc21241991e079006vboxsync * @param u32Function The function number.
85e5ab5adbba74b522731762dd05ca88cb529140vboxsync * @param cParms Number of parameters.
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync * @param paParms Pointer to array of parameters.
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync * @return VBox rc.
27152389a84c6dec057fba6fc21241991e079006vboxsyncint HGCMService::HostCall (uint32_t u32Function, uint32_t cParms, VBOXHGCMSVCPARM *paParms)
27152389a84c6dec057fba6fc21241991e079006vboxsync LogFlowFunc(("%s u32Function = %d, cParms = %d, paParms = %p\n",
27152389a84c6dec057fba6fc21241991e079006vboxsync int rc = hgcmMsgAlloc (m_thread, &hMsg, SVC_MSG_HOSTCALL, hgcmMessageAllocSvc);
27152389a84c6dec057fba6fc21241991e079006vboxsync HGCMMsgHostCallSvc *pMsg = (HGCMMsgHostCallSvc *)hgcmObjReference (hMsg, HGCMOBJ_MSG);
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsyncstatic DECLCALLBACK(void) hgcmMsgFastCallCompletionCallback (int32_t result, HGCMMsgCore *pMsgCore)
27152389a84c6dec057fba6fc21241991e079006vboxsync /* Call the VMMDev port interface to issue IRQ notification. */
27152389a84c6dec057fba6fc21241991e079006vboxsync LogFlow(("MAIN::hgcmMsgFastCallCompletionCallback: message %p\n", pMsgCore));
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync HGCMMsgHostFastCallAsyncSvc *pMsg = (HGCMMsgHostFastCallAsyncSvc *)pMsgCore;
27152389a84c6dec057fba6fc21241991e079006vboxsync pMsg->pfnCompletion (result, pMsg->u32Function, &pMsg->Param, pMsg->pvCompletion);
27152389a84c6dec057fba6fc21241991e079006vboxsyncint HGCMService::HostFastCallAsync (uint32_t u32Function, VBOXHGCMSVCPARM *pParm, PHGCMHOSTFASTCALLCB pfnCompletion, void *pvCompletion)
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync int rc = hgcmMsgAlloc (m_thread, &hMsg, SVC_MSG_HOSTFASTCALLASYNC, hgcmMessageAllocSvc);
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync HGCMMsgHostFastCallAsyncSvc *pMsg = (HGCMMsgHostFastCallAsyncSvc *)hgcmObjReference (hMsg, HGCMOBJ_MSG);
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync rc = hgcmMsgPost(hMsg, hgcmMsgFastCallCompletionCallback);
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync * Main HGCM thread that manages services.
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync/* Messages processed by the main HGCM thread. */
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync#define HGCM_MSG_CONNECT (10) /* Connect a client to a service. */
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync#define HGCM_MSG_DISCONNECT (11) /* Disconnect the specified client id. */
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync#define HGCM_MSG_HOSTCALL (13) /* Call the service. */
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync#define HGCM_MSG_LOADSTATE (14) /* Load saved state for the specified service. */
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync#define HGCM_MSG_SAVESTATE (15) /* Save state for the specified service. */
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync#define HGCM_MSG_RESET (16) /* Disconnect all clients from the specified service. */
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync#define HGCM_MSG_QUIT (17) /* Unload all services and terminate the thread. */
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync#define HGCM_MSG_REGEXT (18) /* Register a service extension. */
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync#define HGCM_MSG_UNREGEXT (19) /* Unregister a service extension. */
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync# define HGCM_MSG_SVCAQUIRE (30) /* Acquire a service handle (for fast host calls) */
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync# define HGCM_MSG_SVCRELEASE (31) /* Release a service */
e68a2ad82506ee1197ef0a520d7ffebca1e33a0cvboxsync /* Service name. */
4d6b317d67ba577744e53cdfa0c7472d4223db5avboxsync /* Where to store the client handle. */
4d6b317d67ba577744e53cdfa0c7472d4223db5avboxsync /* Handle of the client to be disconnected. */
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync /* Name of the library to be loaded. */
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync /* Name to be assigned to the service. */
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync /* Which service to call. */
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync /* Function number. */
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync /* Number of the function parameters. */
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync /* Pointer to array of the function parameters. */
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync /* SSM context. */
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsyncclass HGCMMsgMainRegisterExtension: public HGCMMsgCore
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync /* Returned handle to be used in HGCMMsgMainUnregisterExtension. */
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync /* Name of the service. */
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync /* The extension entry point. */
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync /* The extension pointer. */
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsyncclass HGCMMsgMainUnregisterExtension: public HGCMMsgCore
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync /* Handle of the registered extension. */
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync /* Which service to call. */
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync /* Returned service. */
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync /* Svc . */
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsyncstatic HGCMMsgCore *hgcmMainMessageAlloc (uint32_t u32MsgId)
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync case HGCM_MSG_CONNECT: return new HGCMMsgMainConnect ();
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync case HGCM_MSG_DISCONNECT: return new HGCMMsgMainDisconnect ();
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync case HGCM_MSG_HOSTCALL: return new HGCMMsgMainHostCall ();
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync case HGCM_MSG_SAVESTATE: return new HGCMMsgMainLoadSaveState ();
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync case HGCM_MSG_RESET: return new HGCMMsgMainReset ();
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync case HGCM_MSG_REGEXT: return new HGCMMsgMainRegisterExtension ();
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync case HGCM_MSG_UNREGEXT: return new HGCMMsgMainUnregisterExtension ();
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync case HGCM_MSG_SVCAQUIRE: return new HGCMMsgMainSvcAcquire();
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync case HGCM_MSG_SVCRELEASE: return new HGCMMsgMainSvcRelease();
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync AssertReleaseMsgFailed(("Msg id = %08X\n", u32MsgId));
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync/* The main HGCM thread handler. */
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsyncstatic DECLCALLBACK(void) hgcmThread (HGCMTHREADHANDLE ThreadHandle, void *pvUser)
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync bool fQuit = false;
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync /* The error means some serious unrecoverable problem in the hgcmMsg/hgcmThread layer. */
e94f86f2aec0daf4cf0628157df1ded65bcd5769vboxsync HGCMMsgMainConnect *pMsg = (HGCMMsgMainConnect *)pMsgCore;
e94f86f2aec0daf4cf0628157df1ded65bcd5769vboxsync LogFlowFunc(("HGCM_MSG_CONNECT pszServiceName %s, pu32ClientId %p\n",
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync /* Resolve the service name to the pointer to service instance.
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync rc = HGCMService::ResolveService (&pService, pMsg->pszServiceName);
e94f86f2aec0daf4cf0628157df1ded65bcd5769vboxsync /* Call the service instance method. */
e94f86f2aec0daf4cf0628157df1ded65bcd5769vboxsync rc = pService->CreateAndConnectClient (pMsg->pu32ClientId, 0);
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync /* Release the service after resolve. */
0f7436d3bb787f4317851dd5b2b2ec1768618c2avboxsync HGCMMsgMainDisconnect *pMsg = (HGCMMsgMainDisconnect *)pMsgCore;
0f7436d3bb787f4317851dd5b2b2ec1768618c2avboxsync LogFlowFunc(("HGCM_MSG_DISCONNECT u32ClientId = %d\n",
0f7436d3bb787f4317851dd5b2b2ec1768618c2avboxsync HGCMClient *pClient = (HGCMClient *)hgcmObjReference (pMsg->u32ClientId, HGCMOBJ_CLIENT);
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync /* The service the client belongs to. */
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync /* Call the service instance to disconnect the client. */
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync rc = pService->DisconnectClient (pMsg->u32ClientId, false);
bd88a03fe4f970611c171f081be318fcd74e85e8vboxsync HGCMMsgMainLoad *pMsg = (HGCMMsgMainLoad *)pMsgCore;
bd88a03fe4f970611c171f081be318fcd74e85e8vboxsync LogFlowFunc(("HGCM_MSG_LOAD pszServiceName = %s, pMsg->pszServiceLibrary = %s\n",
bd88a03fe4f970611c171f081be318fcd74e85e8vboxsync rc = HGCMService::LoadService (pMsg->pszServiceLibrary, pMsg->pszServiceName);
bd88a03fe4f970611c171f081be318fcd74e85e8vboxsync HGCMMsgMainHostCall *pMsg = (HGCMMsgMainHostCall *)pMsgCore;
58461e707998a927c19da46b98748ee2b79f4190vboxsync LogFlowFunc(("HGCM_MSG_HOSTCALL pszServiceName %s, u32Function %d, cParms %d, paParms %p\n",
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync pMsg->pszServiceName, pMsg->u32Function, pMsg->cParms, pMsg->paParms));
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync /* Resolve the service name to the pointer to service instance. */
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync rc = HGCMService::ResolveService (&pService, pMsg->pszServiceName);
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync rc = pService->HostCall (pMsg->u32Function, pMsg->cParms, pMsg->paParms);
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync HGCMMsgMainSvcAcquire *pMsg = (HGCMMsgMainSvcAcquire *)pMsgCore;
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync LogFlowFunc(("HGCM_MSG_SVCAQUIRE pszServiceName %s\n", pMsg->pszServiceName));
e8d309b9da17d55dbaf8de632612470b4f16d926vboxsync /* Resolve the service name to the pointer to service instance. */
e8d309b9da17d55dbaf8de632612470b4f16d926vboxsync rc = HGCMService::ResolveService (&pService, pMsg->pszServiceName);
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync HGCMMsgMainSvcRelease *pMsg = (HGCMMsgMainSvcRelease *)pMsgCore;
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync LogFlowFunc(("HGCM_MSG_SVCARELEASE pService %p\n", pMsg->pService));
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync /* Resolve the service name to the pointer to service instance. */
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync HGCMMsgMainLoadSaveState *pMsg = (HGCMMsgMainLoadSaveState *)pMsgCore;
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync HGCMMsgMainLoadSaveState *pMsg = (HGCMMsgMainLoadSaveState *)pMsgCore;
85e5ab5adbba74b522731762dd05ca88cb529140vboxsync HGCMMsgMainRegisterExtension *pMsg = (HGCMMsgMainRegisterExtension *)pMsgCore;
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync /* Allocate the handle data. */
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync HGCMSVCEXTHANDLE handle = (HGCMSVCEXTHANDLE)RTMemAllocZ (sizeof (struct _HGCMSVCEXTHANDLEDATA)
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync + sizeof (char));
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync handle->pszServiceName = (char *)((uint8_t *)handle + sizeof (struct _HGCMSVCEXTHANDLEDATA));
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync strcpy (handle->pszServiceName, pMsg->pszServiceName);
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync rc = HGCMService::ResolveService (&pService, handle->pszServiceName);
ce9015004a47e95eb75e047ba42f2d3200d2d222vboxsync pService->RegisterExtension (handle, pMsg->pfnExtension, pMsg->pvExtension);
79baed6836ae36c5f15b182292387484dcf7a752vboxsync HGCMMsgMainUnregisterExtension *pMsg = (HGCMMsgMainUnregisterExtension *)pMsgCore;
79baed6836ae36c5f15b182292387484dcf7a752vboxsync rc = HGCMService::ResolveService (&pService, pMsg->handle->pszServiceName);
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync AssertMsgFailed(("hgcmThread: Unsupported message number %08X!!!\n", u32MsgId));
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync /* Complete the message processing. */
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync * The HGCM API.
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync/* The main hgcm thread. */
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync * Public HGCM functions.
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync * hgcmGuest* - called as a result of the guest HGCM requests.
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync * hgcmHost* - called by the host.
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync/* Load a HGCM service from the specified library.
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync * Assign the specified name to the service.
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync * @param pszServiceLibrary The library to be loaded.
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync * @param pszServiceName The name to be assigned to the service.
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync * @return VBox rc.
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync LogFlowFunc(("lib = %s, name = %s\n", pszServiceLibrary, pszServiceName));
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync /* Forward the request to the main hgcm thread. */
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync int rc = hgcmMsgAlloc (g_hgcmThread, &hMsg, HGCM_MSG_LOAD, hgcmMainMessageAlloc);
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync /* Initialize the message. Since the message is synchronous, use the supplied pointers. */
79baed6836ae36c5f15b182292387484dcf7a752vboxsync HGCMMsgMainLoad *pMsg = (HGCMMsgMainLoad *)hgcmObjReference (hMsg, HGCMOBJ_MSG);
const char *pszServiceName,
void *pvExtension)
LogFlowFunc(("pHandle = %p, name = %s, pfn = %p, rv = %p\n", pHandle, pszServiceName, pfnExtension, pvExtension));
return VERR_INVALID_PARAMETER;
HGCMMsgMainRegisterExtension *pMsg = (HGCMMsgMainRegisterExtension *)hgcmObjReference (hMsg, HGCMOBJ_MSG);
return rc;
HGCMMsgMainUnregisterExtension *pMsg = (HGCMMsgMainUnregisterExtension *)hgcmObjReference (hMsg, HGCMOBJ_MSG);
const char *pszServiceName,
return VERR_INVALID_PARAMETER;
return rc;
return VERR_INVALID_PARAMETER;
return rc;
return rc;
LogFlowFunc(("pHGCMPort = %p, pCmd = %p, u32ClientId = %d, u32Function = %d, cParms = %d, paParms = %p\n",
return VERR_INVALID_PARAMETER;
if (pClient)
return rc;
if (!pszServiceName)
return VERR_INVALID_PARAMETER;
return rc;
#ifdef VBOX_WITH_CRHGSMI
if (!pszServiceName)
return VERR_INVALID_PARAMETER;
if (!phSvc)
return VERR_INVALID_PARAMETER;
return rc;
if (!hSvc)
return VERR_INVALID_PARAMETER;
return rc;
int HGCMHostFastCallAsync (HGCMCVSHANDLE hSvc, uint32_t function, VBOXHGCMSVCPARM *pParm, PHGCMHOSTFASTCALLCB pfnCompletion, void *pvCompletion)
if (!hSvc)
return VERR_INVALID_PARAMETER;
return rc;
int HGCMHostReset (void)
return rc;
int HGCMHostInit (void)
return rc;
int HGCMHostShutdown (void)
g_hgcmThread = 0;
hgcmThreadUninit ();
return rc;