HGCM.cpp revision 6ef36e19210a6d8b4d90b881f155581cb3cb3979
11d3005e2935c925665896fa26fde09b3e656d70vboxsync/** @file
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync *
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync * HGCM (Host-Guest Communication Manager)
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync */
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
e64031e20c39650a7bc902a3e1aba613b9415deevboxsync/*
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync * Copyright (C) 2006-2007 Oracle Corporation
cf5f6bf2704d4fff443139e10bccc6a0a7fa4b85vboxsync *
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.
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync */
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
43747b1f0bc8302a238fb35e55857a5e9aa1933dvboxsync#define LOG_GROUP_MAIN_OVERRIDE LOG_GROUP_HGCM
43747b1f0bc8302a238fb35e55857a5e9aa1933dvboxsync#include "Logging.h"
43747b1f0bc8302a238fb35e55857a5e9aa1933dvboxsync
43747b1f0bc8302a238fb35e55857a5e9aa1933dvboxsync#include "hgcm/HGCM.h"
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync#include "hgcm/HGCMThread.h"
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync#include <VBox/err.h>
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync#include <VBox/hgcmsvc.h>
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync#include <iprt/alloc.h>
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync#include <iprt/alloca.h>
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync#include <iprt/avl.h>
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync#include <iprt/critsect.h>
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync#include <iprt/asm.h>
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync#include <iprt/ldr.h>
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync#include <iprt/param.h>
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync#include <iprt/path.h>
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync#include <iprt/string.h>
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync#include <iprt/semaphore.h>
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync#include <iprt/thread.h>
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync#include <VBox/VMMDev.h>
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync/**
aef51041e0fe31e8ea903dd7e67fe12cef645654vboxsync * A service gets one thread, which synchronously delivers messages to
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync * the service. This is good for serialization.
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync *
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.
aef51041e0fe31e8ea903dd7e67fe12cef645654vboxsync *
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 *
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync * 'Message processed' condition is indicated by service, which call the
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync * callback, even if the callback is called synchronously in the dedicated
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync * thread.
79baed6836ae36c5f15b182292387484dcf7a752vboxsync *
79baed6836ae36c5f15b182292387484dcf7a752vboxsync * This message completion callback is only valid for Call requests.
79baed6836ae36c5f15b182292387484dcf7a752vboxsync * Connect and Disconnect are processed synchronously by the service.
79baed6836ae36c5f15b182292387484dcf7a752vboxsync */
79baed6836ae36c5f15b182292387484dcf7a752vboxsync
79baed6836ae36c5f15b182292387484dcf7a752vboxsync
79baed6836ae36c5f15b182292387484dcf7a752vboxsync/* The maximum allowed size of a service name in bytes. */
79baed6836ae36c5f15b182292387484dcf7a752vboxsync#define VBOX_HGCM_SVC_NAME_MAX_BYTES 1024
79baed6836ae36c5f15b182292387484dcf7a752vboxsync
79baed6836ae36c5f15b182292387484dcf7a752vboxsyncstruct _HGCMSVCEXTHANDLEDATA
79baed6836ae36c5f15b182292387484dcf7a752vboxsync{
79baed6836ae36c5f15b182292387484dcf7a752vboxsync char *pszServiceName;
79baed6836ae36c5f15b182292387484dcf7a752vboxsync /* The service name follows. */
79baed6836ae36c5f15b182292387484dcf7a752vboxsync};
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
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 */
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsyncclass HGCMService
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync{
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync private:
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync VBOXHGCMSVCHELPERS m_svcHelpers;
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync static HGCMService *sm_pSvcListHead;
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync static HGCMService *sm_pSvcListTail;
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync static int sm_cServices;
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync HGCMTHREADHANDLE m_thread;
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync friend DECLCALLBACK(void) hgcmServiceThread (HGCMTHREADHANDLE ThreadHandle, void *pvUser);
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync uint32_t volatile m_u32RefCnt;
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync HGCMService *m_pSvcNext;
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync HGCMService *m_pSvcPrev;
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync char *m_pszSvcName;
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync char *m_pszSvcLibrary;
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync RTLDRMOD m_hLdrMod;
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync PFNVBOXHGCMSVCLOAD m_pfnLoad;
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync VBOXHGCMSVCFNTABLE m_fntable;
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync int m_cClients;
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync int m_cClientsAllocated;
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync uint32_t *m_paClientIds;
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync#ifdef VBOX_WITH_CRHGSMI
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync uint32_t m_cHandleAcquires;
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync#endif
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync HGCMSVCEXTHANDLE m_hExtension;
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync int loadServiceDLL (void);
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync void unloadServiceDLL (void);
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync /*
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync * Main HGCM thread methods.
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync */
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync int instanceCreate (const char *pszServiceLibrary, const char *pszServiceName);
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync void instanceDestroy (void);
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync int saveClientState(uint32_t u32ClientId, PSSMHANDLE pSSM);
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync int loadClientState(uint32_t u32ClientId, PSSMHANDLE pSSM);
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync HGCMService ();
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync ~HGCMService () {};
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync static DECLCALLBACK(void) svcHlpCallComplete (VBOXHGCMCALLHANDLE callHandle, int32_t rc);
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync static DECLCALLBACK(void) svcHlpDisconnectClient (void *pvInstance, uint32_t u32ClientId);
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync public:
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync /*
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync * Main HGCM thread methods.
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync */
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync static int LoadService (const char *pszServiceLibrary, const char *pszServiceName);
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync void UnloadService (void);
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync static void UnloadAll (void);
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync static int ResolveService (HGCMService **ppsvc, const char *pszServiceName);
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync void ReferenceService (void);
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync void ReleaseService (void);
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync static void Reset (void);
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync static int SaveState (PSSMHANDLE pSSM);
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync static int LoadState (PSSMHANDLE pSSM);
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync int CreateAndConnectClient (uint32_t *pu32ClientIdOut, uint32_t u32ClientIdIn);
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync int DisconnectClient (uint32_t u32ClientId, bool fFromService);
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync int HostCall (uint32_t u32Function, uint32_t cParms, VBOXHGCMSVCPARM *paParms);
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync#ifdef VBOX_WITH_CRHGSMI
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync int HandleAcquired();
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync int HandleReleased();
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync int HostFastCallAsync (uint32_t u32Function, VBOXHGCMSVCPARM *pParm, PHGCMHOSTFASTCALLCB pfnCompletion, void *pvCompletion);
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync#endif
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync uint32_t SizeOfClient (void) { return m_fntable.cbClient; };
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync int RegisterExtension (HGCMSVCEXTHANDLE handle, PFNHGCMSVCEXT pfnExtension, void *pvExtension);
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync void UnregisterExtension (HGCMSVCEXTHANDLE handle);
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync /*
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync * The service thread methods.
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync */
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync int GuestCall (PPDMIHGCMPORT pHGCMPort, PVBOXHGCMCMD pCmd, uint32_t u32ClientId, uint32_t u32Function, uint32_t cParms, VBOXHGCMSVCPARM aParms[]);
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync};
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsyncclass HGCMClient: public HGCMObject
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync{
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync public:
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync HGCMClient () : HGCMObject(HGCMOBJ_CLIENT), pService(NULL),
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync pvData(NULL) {};
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync ~HGCMClient ();
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync int Init (HGCMService *pSvc);
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync /** Service that the client is connected to. */
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync HGCMService *pService;
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync /** Client specific data. */
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync void *pvData;
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync};
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsyncHGCMClient::~HGCMClient ()
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync{
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync if (pService->SizeOfClient () > 0)
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync RTMemFree (pvData);
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync}
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsyncint HGCMClient::Init (HGCMService *pSvc)
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync{
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync pService = pSvc;
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync if (pService->SizeOfClient () > 0)
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync {
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync pvData = RTMemAllocZ (pService->SizeOfClient ());
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync if (!pvData)
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync {
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync return VERR_NO_MEMORY;
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync }
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync }
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync return VINF_SUCCESS;
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync}
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync#define HGCM_CLIENT_DATA(pService, pClient) (pClient->pvData)
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsyncHGCMService *HGCMService::sm_pSvcListHead = NULL;
ad27e1d5e48ca41245120c331cc88b50464813cevboxsyncHGCMService *HGCMService::sm_pSvcListTail = NULL;
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsyncint HGCMService::sm_cServices = 0;
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsyncHGCMService::HGCMService ()
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync :
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync m_thread (0),
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync m_u32RefCnt (0),
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync m_pSvcNext (NULL),
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync m_pSvcPrev (NULL),
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync m_pszSvcName (NULL),
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync m_pszSvcLibrary (NULL),
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync m_hLdrMod (NIL_RTLDRMOD),
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync m_pfnLoad (NULL),
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync m_cClients (0),
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync m_cClientsAllocated (0),
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync m_paClientIds (NULL),
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync#ifdef VBOX_WITH_CRHGSMI
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync m_cHandleAcquires (0),
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync#endif
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync m_hExtension (NULL)
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync{
ad27e1d5e48ca41245120c331cc88b50464813cevboxsync memset (&m_fntable, 0, sizeof (m_fntable));
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync}
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsyncstatic bool g_fResetting = false;
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsyncstatic bool g_fSaveState = false;
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync/** Helper function to load a local service DLL.
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync *
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync * @return VBox code
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync */
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsyncint HGCMService::loadServiceDLL (void)
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync{
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync LogFlowFunc(("m_pszSvcLibrary = %s\n", m_pszSvcLibrary));
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync if (m_pszSvcLibrary == NULL)
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync {
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync return VERR_INVALID_PARAMETER;
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync }
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync char szErr[8192];
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync szErr[0] = '\0';
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync int rc = SUPR3HardenedLdrLoadAppPriv (m_pszSvcLibrary, &m_hLdrMod, szErr, sizeof(szErr));
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync if (RT_SUCCESS(rc))
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync {
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync LogFlowFunc(("successfully loaded the library.\n"));
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync m_pfnLoad = NULL;
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync rc = RTLdrGetSymbol (m_hLdrMod, VBOX_HGCM_SVCLOAD_NAME, (void**)&m_pfnLoad);
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync if (RT_FAILURE(rc) || !m_pfnLoad)
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync {
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
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync if (RT_SUCCESS(rc))
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync {
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync /* m_pfnLoad was NULL */
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync rc = VERR_SYMBOL_NOT_FOUND;
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync }
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync }
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync if (RT_SUCCESS(rc))
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync {
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync memset (&m_fntable, 0, sizeof (m_fntable));
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync m_fntable.cbSize = sizeof (m_fntable);
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync m_fntable.u32Version = VBOX_HGCM_SVC_VERSION;
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync m_fntable.pHelpers = &m_svcHelpers;
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync rc = m_pfnLoad (&m_fntable);
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync LogFlowFunc(("m_pfnLoad rc = %Rrc\n", rc));
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync if (RT_SUCCESS(rc))
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync {
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync if ( m_fntable.pfnUnload == NULL
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync || m_fntable.pfnConnect == NULL
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync || m_fntable.pfnDisconnect == NULL
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync || m_fntable.pfnCall == NULL
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync )
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync {
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync Log(("HGCMService::loadServiceDLL: at least one of function pointers is NULL\n"));
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync rc = VERR_INVALID_PARAMETER;
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync if (m_fntable.pfnUnload)
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync {
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync m_fntable.pfnUnload (m_fntable.pvService);
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync }
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync }
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync }
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync }
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync }
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync else
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync {
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync LogRel(("HGCM: Failed to load the service library: [%s], rc = %Rrc - %s. The service will be not available.\n",
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync m_pszSvcLibrary, rc, szErr));
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync m_hLdrMod = NIL_RTLDRMOD;
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync }
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync if (RT_FAILURE(rc))
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync {
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync unloadServiceDLL ();
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync }
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync return rc;
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync}
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync/** Helper function to free a local service DLL.
58ab0ad45444e80bdd970ddeb468d0872dbbbb47vboxsync *
11d3005e2935c925665896fa26fde09b3e656d70vboxsync * @return VBox code
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync */
58ab0ad45444e80bdd970ddeb468d0872dbbbb47vboxsyncvoid HGCMService::unloadServiceDLL (void)
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync{
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync if (m_hLdrMod)
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync {
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync RTLdrClose (m_hLdrMod);
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync }
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync memset (&m_fntable, 0, sizeof (m_fntable));
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync m_pfnLoad = NULL;
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync m_hLdrMod = NIL_RTLDRMOD;
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync}
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync/*
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync * Messages processed by service threads. These threads only call the service entry points.
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync */
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
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_CONNECT (2) /* pfnConnect */
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync#define SVC_MSG_DISCONNECT (3) /* pfnDisconnect */
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync#define SVC_MSG_GUESTCALL (4) /* pfnGuestCall */
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync#define SVC_MSG_HOSTCALL (5) /* pfnHostCall */
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync#define SVC_MSG_LOADSTATE (6) /* pfnLoadState. */
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync#define SVC_MSG_SAVESTATE (7) /* pfnSaveState. */
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync#define SVC_MSG_QUIT (8) /* Terminate the thread. */
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync#define SVC_MSG_REGEXT (9) /* pfnRegisterExtension */
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync#define SVC_MSG_UNREGEXT (10) /* pfnRegisterExtension */
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync#ifdef VBOX_WITH_CRHGSMI
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync# define SVC_MSG_HOSTFASTCALLASYNC (21) /* pfnHostCall */
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync#endif
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsyncclass HGCMMsgSvcLoad: public HGCMMsgCore
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync{
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync};
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsyncclass HGCMMsgSvcUnload: public HGCMMsgCore
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync{
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync};
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsyncclass HGCMMsgSvcConnect: public HGCMMsgCore
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync{
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync public:
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync /* client identifier */
58ab0ad45444e80bdd970ddeb468d0872dbbbb47vboxsync uint32_t u32ClientId;
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync};
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsyncclass HGCMMsgSvcDisconnect: public HGCMMsgCore
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync{
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync public:
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync /* client identifier */
58ab0ad45444e80bdd970ddeb468d0872dbbbb47vboxsync uint32_t u32ClientId;
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync};
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsyncclass HGCMMsgHeader: public HGCMMsgCore
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync{
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync public:
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync HGCMMsgHeader () : pCmd (NULL), pHGCMPort (NULL) {};
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync /* Command pointer/identifier. */
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync PVBOXHGCMCMD pCmd;
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync /* Port to be informed on message completion. */
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync PPDMIHGCMPORT pHGCMPort;
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync};
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsyncclass HGCMMsgCall: public HGCMMsgHeader
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync{
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync public:
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync /* client identifier */
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync uint32_t u32ClientId;
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync /* function number */
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync uint32_t u32Function;
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync /* number of parameters */
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync uint32_t cParms;
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync VBOXHGCMSVCPARM *paParms;
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync};
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsyncclass HGCMMsgLoadSaveStateClient: public HGCMMsgCore
58ab0ad45444e80bdd970ddeb468d0872dbbbb47vboxsync{
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync public:
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync uint32_t u32ClientId;
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync PSSMHANDLE pSSM;
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync};
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsyncclass HGCMMsgHostCallSvc: public HGCMMsgCore
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync{
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync public:
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync /* function number */
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync uint32_t u32Function;
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync /* number of parameters */
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync uint32_t cParms;
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync VBOXHGCMSVCPARM *paParms;
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync};
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsyncclass HGCMMsgSvcRegisterExtension: public HGCMMsgCore
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync{
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync public:
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync /* Handle of the extension to be registered. */
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync HGCMSVCEXTHANDLE handle;
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync /* The extension entry point. */
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync PFNHGCMSVCEXT pfnExtension;
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync /* The extension pointer. */
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync void *pvExtension;
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync};
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsyncclass HGCMMsgSvcUnregisterExtension: public HGCMMsgCore
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync{
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync public:
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync /* Handle of the registered extension. */
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync HGCMSVCEXTHANDLE handle;
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync};
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync#ifdef VBOX_WITH_CRHGSMI
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsyncclass HGCMMsgHostFastCallAsyncSvc: public HGCMMsgCore
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync{
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync public:
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync /* function number */
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync uint32_t u32Function;
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync /* parameter */
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync VBOXHGCMSVCPARM Param;
11d3005e2935c925665896fa26fde09b3e656d70vboxsync /* completion info */
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync PHGCMHOSTFASTCALLCB pfnCompletion;
11d3005e2935c925665896fa26fde09b3e656d70vboxsync void *pvCompletion;
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync};
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync#endif
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsyncstatic HGCMMsgCore *hgcmMessageAllocSvc (uint32_t u32MsgId)
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync{
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync switch (u32MsgId)
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync {
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync#ifdef VBOX_WITH_CRHGSMI
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync case SVC_MSG_HOSTFASTCALLASYNC: return new HGCMMsgHostFastCallAsyncSvc ();
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync#endif
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync case SVC_MSG_LOAD: return new HGCMMsgSvcLoad ();
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_GUESTCALL: return new HGCMMsgCall ();
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync case SVC_MSG_LOADSTATE:
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 default:
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync AssertReleaseMsgFailed(("Msg id = %08X\n", u32MsgId));
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync }
befced03fd84a13590b8ce8be8c2480e9bc568c6vboxsync
e6a3673a23c632af5208dcc8a37f45d7a20b0554vboxsync return NULL;
befced03fd84a13590b8ce8be8c2480e9bc568c6vboxsync}
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync/*
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync * The service thread. Loads the service library and calls the service entry points.
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync */
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsyncDECLCALLBACK(void) hgcmServiceThread (HGCMTHREADHANDLE ThreadHandle, void *pvUser)
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync{
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync HGCMService *pSvc = (HGCMService *)pvUser;
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync AssertRelease(pSvc != NULL);
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync bool fQuit = false;
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync while (!fQuit)
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync {
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync HGCMMsgCore *pMsgCore;
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync int rc = hgcmMsgGet (ThreadHandle, &pMsgCore);
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync if (RT_FAILURE(rc))
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync {
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync /* The error means some serious unrecoverable problem in the hgcmMsg/hgcmThread layer. */
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync AssertMsgFailed (("%Rrc\n", rc));
befced03fd84a13590b8ce8be8c2480e9bc568c6vboxsync break;
befced03fd84a13590b8ce8be8c2480e9bc568c6vboxsync }
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync /* Cache required information to avoid unnecessary pMsgCore access. */
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync uint32_t u32MsgId = pMsgCore->MsgId ();
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync switch (u32MsgId)
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync {
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync#ifdef VBOX_WITH_CRHGSMI
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync case SVC_MSG_HOSTFASTCALLASYNC:
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync {
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync HGCMMsgHostFastCallAsyncSvc *pMsg = (HGCMMsgHostFastCallAsyncSvc *)pMsgCore;
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync LogFlowFunc(("SVC_MSG_HOSTFASTCALLASYNC u32Function = %d, pParm = %p\n", pMsg->u32Function, &pMsg->Param));
16d723d9d597f4872dd4c2c960af9cbca4ed63bdvboxsync
16d723d9d597f4872dd4c2c960af9cbca4ed63bdvboxsync rc = pSvc->m_fntable.pfnHostCall (pSvc->m_fntable.pvService, pMsg->u32Function, 1, &pMsg->Param);
16d723d9d597f4872dd4c2c960af9cbca4ed63bdvboxsync } break;
16d723d9d597f4872dd4c2c960af9cbca4ed63bdvboxsync#endif
16d723d9d597f4872dd4c2c960af9cbca4ed63bdvboxsync case SVC_MSG_LOAD:
16d723d9d597f4872dd4c2c960af9cbca4ed63bdvboxsync {
16d723d9d597f4872dd4c2c960af9cbca4ed63bdvboxsync LogFlowFunc(("SVC_MSG_LOAD\n"));
16d723d9d597f4872dd4c2c960af9cbca4ed63bdvboxsync rc = pSvc->loadServiceDLL ();
16d723d9d597f4872dd4c2c960af9cbca4ed63bdvboxsync } break;
16d723d9d597f4872dd4c2c960af9cbca4ed63bdvboxsync
16d723d9d597f4872dd4c2c960af9cbca4ed63bdvboxsync case SVC_MSG_UNLOAD:
16d723d9d597f4872dd4c2c960af9cbca4ed63bdvboxsync {
16d723d9d597f4872dd4c2c960af9cbca4ed63bdvboxsync LogFlowFunc(("SVC_MSG_UNLOAD\n"));
16d723d9d597f4872dd4c2c960af9cbca4ed63bdvboxsync if (pSvc->m_fntable.pfnUnload)
16d723d9d597f4872dd4c2c960af9cbca4ed63bdvboxsync {
16d723d9d597f4872dd4c2c960af9cbca4ed63bdvboxsync pSvc->m_fntable.pfnUnload (pSvc->m_fntable.pvService);
16d723d9d597f4872dd4c2c960af9cbca4ed63bdvboxsync }
16d723d9d597f4872dd4c2c960af9cbca4ed63bdvboxsync
16d723d9d597f4872dd4c2c960af9cbca4ed63bdvboxsync pSvc->unloadServiceDLL ();
79baed6836ae36c5f15b182292387484dcf7a752vboxsync fQuit = true;
79baed6836ae36c5f15b182292387484dcf7a752vboxsync } break;
79baed6836ae36c5f15b182292387484dcf7a752vboxsync
79baed6836ae36c5f15b182292387484dcf7a752vboxsync case SVC_MSG_CONNECT:
79baed6836ae36c5f15b182292387484dcf7a752vboxsync {
79baed6836ae36c5f15b182292387484dcf7a752vboxsync HGCMMsgSvcConnect *pMsg = (HGCMMsgSvcConnect *)pMsgCore;
79baed6836ae36c5f15b182292387484dcf7a752vboxsync
79baed6836ae36c5f15b182292387484dcf7a752vboxsync LogFlowFunc(("SVC_MSG_CONNECT u32ClientId = %d\n", pMsg->u32ClientId));
79baed6836ae36c5f15b182292387484dcf7a752vboxsync
79baed6836ae36c5f15b182292387484dcf7a752vboxsync HGCMClient *pClient = (HGCMClient *)hgcmObjReference (pMsg->u32ClientId, HGCMOBJ_CLIENT);
79baed6836ae36c5f15b182292387484dcf7a752vboxsync
79baed6836ae36c5f15b182292387484dcf7a752vboxsync if (pClient)
79baed6836ae36c5f15b182292387484dcf7a752vboxsync {
79baed6836ae36c5f15b182292387484dcf7a752vboxsync rc = pSvc->m_fntable.pfnConnect (pSvc->m_fntable.pvService, pMsg->u32ClientId, HGCM_CLIENT_DATA(pSvc, pClient));
79baed6836ae36c5f15b182292387484dcf7a752vboxsync
79baed6836ae36c5f15b182292387484dcf7a752vboxsync hgcmObjDereference (pClient);
79baed6836ae36c5f15b182292387484dcf7a752vboxsync }
79baed6836ae36c5f15b182292387484dcf7a752vboxsync else
79baed6836ae36c5f15b182292387484dcf7a752vboxsync {
79baed6836ae36c5f15b182292387484dcf7a752vboxsync rc = VERR_HGCM_INVALID_CLIENT_ID;
79baed6836ae36c5f15b182292387484dcf7a752vboxsync }
79baed6836ae36c5f15b182292387484dcf7a752vboxsync } break;
79baed6836ae36c5f15b182292387484dcf7a752vboxsync
79baed6836ae36c5f15b182292387484dcf7a752vboxsync case SVC_MSG_DISCONNECT:
79baed6836ae36c5f15b182292387484dcf7a752vboxsync {
79baed6836ae36c5f15b182292387484dcf7a752vboxsync HGCMMsgSvcDisconnect *pMsg = (HGCMMsgSvcDisconnect *)pMsgCore;
79baed6836ae36c5f15b182292387484dcf7a752vboxsync
79baed6836ae36c5f15b182292387484dcf7a752vboxsync LogFlowFunc(("SVC_MSG_DISCONNECT u32ClientId = %d\n", pMsg->u32ClientId));
79baed6836ae36c5f15b182292387484dcf7a752vboxsync
79baed6836ae36c5f15b182292387484dcf7a752vboxsync HGCMClient *pClient = (HGCMClient *)hgcmObjReference (pMsg->u32ClientId, HGCMOBJ_CLIENT);
79baed6836ae36c5f15b182292387484dcf7a752vboxsync
79baed6836ae36c5f15b182292387484dcf7a752vboxsync if (pClient)
79baed6836ae36c5f15b182292387484dcf7a752vboxsync {
79baed6836ae36c5f15b182292387484dcf7a752vboxsync rc = pSvc->m_fntable.pfnDisconnect (pSvc->m_fntable.pvService, pMsg->u32ClientId, HGCM_CLIENT_DATA(pSvc, pClient));
79baed6836ae36c5f15b182292387484dcf7a752vboxsync
79baed6836ae36c5f15b182292387484dcf7a752vboxsync hgcmObjDereference (pClient);
79baed6836ae36c5f15b182292387484dcf7a752vboxsync }
79baed6836ae36c5f15b182292387484dcf7a752vboxsync else
79baed6836ae36c5f15b182292387484dcf7a752vboxsync {
79baed6836ae36c5f15b182292387484dcf7a752vboxsync rc = VERR_HGCM_INVALID_CLIENT_ID;
79baed6836ae36c5f15b182292387484dcf7a752vboxsync }
79baed6836ae36c5f15b182292387484dcf7a752vboxsync } break;
79baed6836ae36c5f15b182292387484dcf7a752vboxsync
79baed6836ae36c5f15b182292387484dcf7a752vboxsync case SVC_MSG_GUESTCALL:
79baed6836ae36c5f15b182292387484dcf7a752vboxsync {
79baed6836ae36c5f15b182292387484dcf7a752vboxsync HGCMMsgCall *pMsg = (HGCMMsgCall *)pMsgCore;
79baed6836ae36c5f15b182292387484dcf7a752vboxsync
79baed6836ae36c5f15b182292387484dcf7a752vboxsync LogFlowFunc(("SVC_MSG_GUESTCALL u32ClientId = %d, u32Function = %d, cParms = %d, paParms = %p\n",
79baed6836ae36c5f15b182292387484dcf7a752vboxsync pMsg->u32ClientId, pMsg->u32Function, pMsg->cParms, pMsg->paParms));
79baed6836ae36c5f15b182292387484dcf7a752vboxsync
79baed6836ae36c5f15b182292387484dcf7a752vboxsync HGCMClient *pClient = (HGCMClient *)hgcmObjReference (pMsg->u32ClientId, HGCMOBJ_CLIENT);
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync if (pClient)
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync {
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
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync hgcmObjDereference (pClient);
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync }
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync else
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync {
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync rc = VERR_HGCM_INVALID_CLIENT_ID;
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync }
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync } break;
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
11d3005e2935c925665896fa26fde09b3e656d70vboxsync case SVC_MSG_HOSTCALL:
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync {
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync HGCMMsgHostCallSvc *pMsg = (HGCMMsgHostCallSvc *)pMsgCore;
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync LogFlowFunc(("SVC_MSG_HOSTCALL u32Function = %d, cParms = %d, paParms = %p\n", pMsg->u32Function, pMsg->cParms, pMsg->paParms));
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync rc = pSvc->m_fntable.pfnHostCall (pSvc->m_fntable.pvService, pMsg->u32Function, pMsg->cParms, pMsg->paParms);
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync } break;
79baed6836ae36c5f15b182292387484dcf7a752vboxsync
79baed6836ae36c5f15b182292387484dcf7a752vboxsync case SVC_MSG_LOADSTATE:
79baed6836ae36c5f15b182292387484dcf7a752vboxsync {
79baed6836ae36c5f15b182292387484dcf7a752vboxsync HGCMMsgLoadSaveStateClient *pMsg = (HGCMMsgLoadSaveStateClient *)pMsgCore;
79baed6836ae36c5f15b182292387484dcf7a752vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync LogFlowFunc(("SVC_MSG_LOADSTATE\n"));
69c6eff4fcb6dc027e94a3e7908926c4e8ef5aefvboxsync
69c6eff4fcb6dc027e94a3e7908926c4e8ef5aefvboxsync HGCMClient *pClient = (HGCMClient *)hgcmObjReference (pMsg->u32ClientId, HGCMOBJ_CLIENT);
69c6eff4fcb6dc027e94a3e7908926c4e8ef5aefvboxsync
69c6eff4fcb6dc027e94a3e7908926c4e8ef5aefvboxsync if (pClient)
69c6eff4fcb6dc027e94a3e7908926c4e8ef5aefvboxsync {
69c6eff4fcb6dc027e94a3e7908926c4e8ef5aefvboxsync if (pSvc->m_fntable.pfnLoadState)
79baed6836ae36c5f15b182292387484dcf7a752vboxsync {
79baed6836ae36c5f15b182292387484dcf7a752vboxsync rc = pSvc->m_fntable.pfnLoadState (pSvc->m_fntable.pvService, pMsg->u32ClientId, HGCM_CLIENT_DATA(pSvc, pClient), pMsg->pSSM);
79baed6836ae36c5f15b182292387484dcf7a752vboxsync }
79baed6836ae36c5f15b182292387484dcf7a752vboxsync
79baed6836ae36c5f15b182292387484dcf7a752vboxsync hgcmObjDereference (pClient);
79baed6836ae36c5f15b182292387484dcf7a752vboxsync }
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync else
79baed6836ae36c5f15b182292387484dcf7a752vboxsync {
79baed6836ae36c5f15b182292387484dcf7a752vboxsync rc = VERR_HGCM_INVALID_CLIENT_ID;
79baed6836ae36c5f15b182292387484dcf7a752vboxsync }
79baed6836ae36c5f15b182292387484dcf7a752vboxsync } break;
79baed6836ae36c5f15b182292387484dcf7a752vboxsync
79baed6836ae36c5f15b182292387484dcf7a752vboxsync case SVC_MSG_SAVESTATE:
79baed6836ae36c5f15b182292387484dcf7a752vboxsync {
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync HGCMMsgLoadSaveStateClient *pMsg = (HGCMMsgLoadSaveStateClient *)pMsgCore;
79baed6836ae36c5f15b182292387484dcf7a752vboxsync
79baed6836ae36c5f15b182292387484dcf7a752vboxsync LogFlowFunc(("SVC_MSG_SAVESTATE\n"));
79baed6836ae36c5f15b182292387484dcf7a752vboxsync
79baed6836ae36c5f15b182292387484dcf7a752vboxsync HGCMClient *pClient = (HGCMClient *)hgcmObjReference (pMsg->u32ClientId, HGCMOBJ_CLIENT);
79baed6836ae36c5f15b182292387484dcf7a752vboxsync
79baed6836ae36c5f15b182292387484dcf7a752vboxsync rc = VINF_SUCCESS;
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
79baed6836ae36c5f15b182292387484dcf7a752vboxsync if (pClient)
79baed6836ae36c5f15b182292387484dcf7a752vboxsync {
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync if (pSvc->m_fntable.pfnSaveState)
79baed6836ae36c5f15b182292387484dcf7a752vboxsync {
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync g_fSaveState = true;
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync rc = pSvc->m_fntable.pfnSaveState (pSvc->m_fntable.pvService, pMsg->u32ClientId, HGCM_CLIENT_DATA(pSvc, pClient), pMsg->pSSM);
79baed6836ae36c5f15b182292387484dcf7a752vboxsync g_fSaveState = false;
79baed6836ae36c5f15b182292387484dcf7a752vboxsync }
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync hgcmObjDereference (pClient);
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync }
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync else
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync {
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync rc = VERR_HGCM_INVALID_CLIENT_ID;
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync }
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync } break;
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync case SVC_MSG_REGEXT:
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync {
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync HGCMMsgSvcRegisterExtension *pMsg = (HGCMMsgSvcRegisterExtension *)pMsgCore;
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync LogFlowFunc(("SVC_MSG_REGEXT handle = %p, pfn = %p\n", pMsg->handle, pMsg->pfnExtension));
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync if (pSvc->m_hExtension)
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync {
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync rc = VERR_NOT_SUPPORTED;
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync }
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync else
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync {
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync if (pSvc->m_fntable.pfnRegisterExtension)
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync {
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync rc = pSvc->m_fntable.pfnRegisterExtension (pSvc->m_fntable.pvService, pMsg->pfnExtension, pMsg->pvExtension);
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync }
58461e707998a927c19da46b98748ee2b79f4190vboxsync else
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync {
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync rc = VERR_NOT_SUPPORTED;
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync }
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync if (RT_SUCCESS(rc))
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync {
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync pSvc->m_hExtension = pMsg->handle;
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync }
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync }
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync } break;
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync case SVC_MSG_UNREGEXT:
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync {
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync HGCMMsgSvcUnregisterExtension *pMsg = (HGCMMsgSvcUnregisterExtension *)pMsgCore;
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync LogFlowFunc(("SVC_MSG_UNREGEXT handle = %p\n", pMsg->handle));
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync if (pSvc->m_hExtension != pMsg->handle)
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync {
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync rc = VERR_NOT_SUPPORTED;
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync }
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync else
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync {
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync if (pSvc->m_fntable.pfnRegisterExtension)
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync {
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync rc = pSvc->m_fntable.pfnRegisterExtension (pSvc->m_fntable.pvService, NULL, NULL);
11d3005e2935c925665896fa26fde09b3e656d70vboxsync }
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync else
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync {
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync rc = VERR_NOT_SUPPORTED;
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync }
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync pSvc->m_hExtension = NULL;
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync }
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync } break;
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync default:
79baed6836ae36c5f15b182292387484dcf7a752vboxsync {
79baed6836ae36c5f15b182292387484dcf7a752vboxsync AssertMsgFailed(("hgcmServiceThread::Unsupported message number %08X\n", u32MsgId));
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync rc = VERR_NOT_SUPPORTED;
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync } break;
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync }
27152389a84c6dec057fba6fc21241991e079006vboxsync
27152389a84c6dec057fba6fc21241991e079006vboxsync if (u32MsgId != SVC_MSG_GUESTCALL)
27152389a84c6dec057fba6fc21241991e079006vboxsync {
27152389a84c6dec057fba6fc21241991e079006vboxsync /* For SVC_MSG_GUESTCALL the service calls the completion helper.
27152389a84c6dec057fba6fc21241991e079006vboxsync * Other messages have to be completed here.
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync */
27152389a84c6dec057fba6fc21241991e079006vboxsync hgcmMsgComplete (pMsgCore, rc);
27152389a84c6dec057fba6fc21241991e079006vboxsync }
27152389a84c6dec057fba6fc21241991e079006vboxsync }
27152389a84c6dec057fba6fc21241991e079006vboxsync}
27152389a84c6dec057fba6fc21241991e079006vboxsync
27152389a84c6dec057fba6fc21241991e079006vboxsync/* static */ DECLCALLBACK(void) HGCMService::svcHlpCallComplete (VBOXHGCMCALLHANDLE callHandle, int32_t rc)
27152389a84c6dec057fba6fc21241991e079006vboxsync{
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync HGCMMsgCore *pMsgCore = (HGCMMsgCore *)callHandle;
27152389a84c6dec057fba6fc21241991e079006vboxsync
27152389a84c6dec057fba6fc21241991e079006vboxsync if (pMsgCore->MsgId () == SVC_MSG_GUESTCALL)
27152389a84c6dec057fba6fc21241991e079006vboxsync {
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 */
27152389a84c6dec057fba6fc21241991e079006vboxsync hgcmMsgComplete (pMsgCore, rc);
27152389a84c6dec057fba6fc21241991e079006vboxsync }
27152389a84c6dec057fba6fc21241991e079006vboxsync else
27152389a84c6dec057fba6fc21241991e079006vboxsync {
27152389a84c6dec057fba6fc21241991e079006vboxsync AssertFailed ();
27152389a84c6dec057fba6fc21241991e079006vboxsync }
27152389a84c6dec057fba6fc21241991e079006vboxsync}
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
27152389a84c6dec057fba6fc21241991e079006vboxsync/* static */ DECLCALLBACK(void) HGCMService::svcHlpDisconnectClient (void *pvInstance, uint32_t u32ClientId)
27152389a84c6dec057fba6fc21241991e079006vboxsync{
27152389a84c6dec057fba6fc21241991e079006vboxsync HGCMService *pService = static_cast <HGCMService *> (pvInstance);
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
27152389a84c6dec057fba6fc21241991e079006vboxsync if (pService)
27152389a84c6dec057fba6fc21241991e079006vboxsync {
27152389a84c6dec057fba6fc21241991e079006vboxsync pService->DisconnectClient (u32ClientId, true);
27152389a84c6dec057fba6fc21241991e079006vboxsync }
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync}
27152389a84c6dec057fba6fc21241991e079006vboxsync
27152389a84c6dec057fba6fc21241991e079006vboxsyncstatic DECLCALLBACK(void) hgcmMsgCompletionCallback (int32_t result, HGCMMsgCore *pMsgCore)
27152389a84c6dec057fba6fc21241991e079006vboxsync{
27152389a84c6dec057fba6fc21241991e079006vboxsync /* Call the VMMDev port interface to issue IRQ notification. */
27152389a84c6dec057fba6fc21241991e079006vboxsync HGCMMsgHeader *pMsgHdr = (HGCMMsgHeader *)pMsgCore;
27152389a84c6dec057fba6fc21241991e079006vboxsync
27152389a84c6dec057fba6fc21241991e079006vboxsync LogFlow(("MAIN::hgcmMsgCompletionCallback: message %p\n", pMsgCore));
27152389a84c6dec057fba6fc21241991e079006vboxsync
27152389a84c6dec057fba6fc21241991e079006vboxsync if (pMsgHdr->pHGCMPort && !g_fResetting)
27152389a84c6dec057fba6fc21241991e079006vboxsync {
27152389a84c6dec057fba6fc21241991e079006vboxsync pMsgHdr->pHGCMPort->pfnCompleted (pMsgHdr->pHGCMPort, g_fSaveState? VINF_HGCM_SAVE_STATE: result, pMsgHdr->pCmd);
27152389a84c6dec057fba6fc21241991e079006vboxsync }
27152389a84c6dec057fba6fc21241991e079006vboxsync}
27152389a84c6dec057fba6fc21241991e079006vboxsync
27152389a84c6dec057fba6fc21241991e079006vboxsync/*
27152389a84c6dec057fba6fc21241991e079006vboxsync * The main HGCM methods of the service.
27152389a84c6dec057fba6fc21241991e079006vboxsync */
27152389a84c6dec057fba6fc21241991e079006vboxsync
27152389a84c6dec057fba6fc21241991e079006vboxsyncint HGCMService::instanceCreate (const char *pszServiceLibrary, const char *pszServiceName)
27152389a84c6dec057fba6fc21241991e079006vboxsync{
27152389a84c6dec057fba6fc21241991e079006vboxsync LogFlowFunc(("name %s, lib %s\n", pszServiceName, pszServiceLibrary));
27152389a84c6dec057fba6fc21241991e079006vboxsync
27152389a84c6dec057fba6fc21241991e079006vboxsync /* The maximum length of the thread name, allowed by the RT is 15. */
27152389a84c6dec057fba6fc21241991e079006vboxsync char achThreadName[16];
27152389a84c6dec057fba6fc21241991e079006vboxsync
27152389a84c6dec057fba6fc21241991e079006vboxsync strncpy (achThreadName, pszServiceName, 15);
27152389a84c6dec057fba6fc21241991e079006vboxsync achThreadName[15] = 0;
27152389a84c6dec057fba6fc21241991e079006vboxsync
27152389a84c6dec057fba6fc21241991e079006vboxsync int rc = hgcmThreadCreate (&m_thread, achThreadName, hgcmServiceThread, this);
27152389a84c6dec057fba6fc21241991e079006vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync if (RT_SUCCESS(rc))
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync {
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync m_pszSvcName = RTStrDup (pszServiceName);
27152389a84c6dec057fba6fc21241991e079006vboxsync m_pszSvcLibrary = RTStrDup (pszServiceLibrary);
27152389a84c6dec057fba6fc21241991e079006vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync if (!m_pszSvcName || !m_pszSvcLibrary)
27152389a84c6dec057fba6fc21241991e079006vboxsync {
27152389a84c6dec057fba6fc21241991e079006vboxsync RTStrFree (m_pszSvcLibrary);
27152389a84c6dec057fba6fc21241991e079006vboxsync m_pszSvcLibrary = NULL;
27152389a84c6dec057fba6fc21241991e079006vboxsync
27152389a84c6dec057fba6fc21241991e079006vboxsync RTStrFree (m_pszSvcName);
27152389a84c6dec057fba6fc21241991e079006vboxsync m_pszSvcName = NULL;
27152389a84c6dec057fba6fc21241991e079006vboxsync
27152389a84c6dec057fba6fc21241991e079006vboxsync rc = VERR_NO_MEMORY;
27152389a84c6dec057fba6fc21241991e079006vboxsync }
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync else
27152389a84c6dec057fba6fc21241991e079006vboxsync {
27152389a84c6dec057fba6fc21241991e079006vboxsync /* Initialize service helpers table. */
27152389a84c6dec057fba6fc21241991e079006vboxsync m_svcHelpers.pfnCallComplete = svcHlpCallComplete;
27152389a84c6dec057fba6fc21241991e079006vboxsync m_svcHelpers.pvInstance = this;
27152389a84c6dec057fba6fc21241991e079006vboxsync m_svcHelpers.pfnDisconnectClient = svcHlpDisconnectClient;
27152389a84c6dec057fba6fc21241991e079006vboxsync
27152389a84c6dec057fba6fc21241991e079006vboxsync /* Execute the load request on the service thread. */
27152389a84c6dec057fba6fc21241991e079006vboxsync HGCMMSGHANDLE hMsg;
27152389a84c6dec057fba6fc21241991e079006vboxsync rc = hgcmMsgAlloc (m_thread, &hMsg, SVC_MSG_LOAD, hgcmMessageAllocSvc);
27152389a84c6dec057fba6fc21241991e079006vboxsync
27152389a84c6dec057fba6fc21241991e079006vboxsync if (RT_SUCCESS(rc))
27152389a84c6dec057fba6fc21241991e079006vboxsync {
27152389a84c6dec057fba6fc21241991e079006vboxsync rc = hgcmMsgSend (hMsg);
27152389a84c6dec057fba6fc21241991e079006vboxsync }
27152389a84c6dec057fba6fc21241991e079006vboxsync }
27152389a84c6dec057fba6fc21241991e079006vboxsync }
27152389a84c6dec057fba6fc21241991e079006vboxsync
27152389a84c6dec057fba6fc21241991e079006vboxsync if (RT_FAILURE(rc))
27152389a84c6dec057fba6fc21241991e079006vboxsync {
27152389a84c6dec057fba6fc21241991e079006vboxsync instanceDestroy ();
27152389a84c6dec057fba6fc21241991e079006vboxsync }
27152389a84c6dec057fba6fc21241991e079006vboxsync
27152389a84c6dec057fba6fc21241991e079006vboxsync LogFlowFunc(("rc = %Rrc\n", rc));
27152389a84c6dec057fba6fc21241991e079006vboxsync return rc;
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync}
27152389a84c6dec057fba6fc21241991e079006vboxsync
27152389a84c6dec057fba6fc21241991e079006vboxsyncvoid HGCMService::instanceDestroy (void)
27152389a84c6dec057fba6fc21241991e079006vboxsync{
27152389a84c6dec057fba6fc21241991e079006vboxsync LogFlowFunc(("%s\n", m_pszSvcName));
27152389a84c6dec057fba6fc21241991e079006vboxsync
27152389a84c6dec057fba6fc21241991e079006vboxsync HGCMMSGHANDLE hMsg;
27152389a84c6dec057fba6fc21241991e079006vboxsync int rc = hgcmMsgAlloc (m_thread, &hMsg, SVC_MSG_UNLOAD, hgcmMessageAllocSvc);
27152389a84c6dec057fba6fc21241991e079006vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync if (RT_SUCCESS(rc))
27152389a84c6dec057fba6fc21241991e079006vboxsync {
27152389a84c6dec057fba6fc21241991e079006vboxsync rc = hgcmMsgSend (hMsg);
27152389a84c6dec057fba6fc21241991e079006vboxsync
27152389a84c6dec057fba6fc21241991e079006vboxsync if (RT_SUCCESS(rc))
27152389a84c6dec057fba6fc21241991e079006vboxsync {
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync hgcmThreadWait (m_thread);
27152389a84c6dec057fba6fc21241991e079006vboxsync }
27152389a84c6dec057fba6fc21241991e079006vboxsync }
27152389a84c6dec057fba6fc21241991e079006vboxsync
27152389a84c6dec057fba6fc21241991e079006vboxsync RTStrFree (m_pszSvcLibrary);
27152389a84c6dec057fba6fc21241991e079006vboxsync m_pszSvcLibrary = NULL;
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
27152389a84c6dec057fba6fc21241991e079006vboxsync RTStrFree (m_pszSvcName);
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync m_pszSvcName = NULL;
27152389a84c6dec057fba6fc21241991e079006vboxsync}
27152389a84c6dec057fba6fc21241991e079006vboxsync
27152389a84c6dec057fba6fc21241991e079006vboxsyncint HGCMService::saveClientState(uint32_t u32ClientId, PSSMHANDLE pSSM)
27152389a84c6dec057fba6fc21241991e079006vboxsync{
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync LogFlowFunc(("%s\n", m_pszSvcName));
27152389a84c6dec057fba6fc21241991e079006vboxsync
27152389a84c6dec057fba6fc21241991e079006vboxsync HGCMMSGHANDLE hMsg;
27152389a84c6dec057fba6fc21241991e079006vboxsync int rc = hgcmMsgAlloc (m_thread, &hMsg, SVC_MSG_SAVESTATE, hgcmMessageAllocSvc);
27152389a84c6dec057fba6fc21241991e079006vboxsync
27152389a84c6dec057fba6fc21241991e079006vboxsync if (RT_SUCCESS(rc))
27152389a84c6dec057fba6fc21241991e079006vboxsync {
27152389a84c6dec057fba6fc21241991e079006vboxsync HGCMMsgLoadSaveStateClient *pMsg = (HGCMMsgLoadSaveStateClient *)hgcmObjReference (hMsg, HGCMOBJ_MSG);
27152389a84c6dec057fba6fc21241991e079006vboxsync AssertRelease(pMsg);
27152389a84c6dec057fba6fc21241991e079006vboxsync
27152389a84c6dec057fba6fc21241991e079006vboxsync pMsg->u32ClientId = u32ClientId;
27152389a84c6dec057fba6fc21241991e079006vboxsync pMsg->pSSM = pSSM;
27152389a84c6dec057fba6fc21241991e079006vboxsync
27152389a84c6dec057fba6fc21241991e079006vboxsync hgcmObjDereference (pMsg);
27152389a84c6dec057fba6fc21241991e079006vboxsync
27152389a84c6dec057fba6fc21241991e079006vboxsync rc = hgcmMsgSend (hMsg);
27152389a84c6dec057fba6fc21241991e079006vboxsync }
27152389a84c6dec057fba6fc21241991e079006vboxsync
27152389a84c6dec057fba6fc21241991e079006vboxsync LogFlowFunc(("rc = %Rrc\n", rc));
27152389a84c6dec057fba6fc21241991e079006vboxsync return rc;
27152389a84c6dec057fba6fc21241991e079006vboxsync}
27152389a84c6dec057fba6fc21241991e079006vboxsync
27152389a84c6dec057fba6fc21241991e079006vboxsyncint HGCMService::loadClientState (uint32_t u32ClientId, PSSMHANDLE pSSM)
27152389a84c6dec057fba6fc21241991e079006vboxsync{
27152389a84c6dec057fba6fc21241991e079006vboxsync LogFlowFunc(("%s\n", m_pszSvcName));
27152389a84c6dec057fba6fc21241991e079006vboxsync
27152389a84c6dec057fba6fc21241991e079006vboxsync HGCMMSGHANDLE hMsg;
27152389a84c6dec057fba6fc21241991e079006vboxsync int rc = hgcmMsgAlloc (m_thread, &hMsg, SVC_MSG_LOADSTATE, hgcmMessageAllocSvc);
27152389a84c6dec057fba6fc21241991e079006vboxsync
27152389a84c6dec057fba6fc21241991e079006vboxsync if (RT_SUCCESS(rc))
27152389a84c6dec057fba6fc21241991e079006vboxsync {
27152389a84c6dec057fba6fc21241991e079006vboxsync HGCMMsgLoadSaveStateClient *pMsg = (HGCMMsgLoadSaveStateClient *)hgcmObjReference (hMsg, HGCMOBJ_MSG);
27152389a84c6dec057fba6fc21241991e079006vboxsync
27152389a84c6dec057fba6fc21241991e079006vboxsync AssertRelease(pMsg);
27152389a84c6dec057fba6fc21241991e079006vboxsync
27152389a84c6dec057fba6fc21241991e079006vboxsync pMsg->u32ClientId = u32ClientId;
27152389a84c6dec057fba6fc21241991e079006vboxsync pMsg->pSSM = pSSM;
27152389a84c6dec057fba6fc21241991e079006vboxsync
27152389a84c6dec057fba6fc21241991e079006vboxsync hgcmObjDereference (pMsg);
27152389a84c6dec057fba6fc21241991e079006vboxsync
27152389a84c6dec057fba6fc21241991e079006vboxsync rc = hgcmMsgSend (hMsg);
27152389a84c6dec057fba6fc21241991e079006vboxsync }
27152389a84c6dec057fba6fc21241991e079006vboxsync
27152389a84c6dec057fba6fc21241991e079006vboxsync LogFlowFunc(("rc = %Rrc\n", rc));
27152389a84c6dec057fba6fc21241991e079006vboxsync return rc;
27152389a84c6dec057fba6fc21241991e079006vboxsync}
27152389a84c6dec057fba6fc21241991e079006vboxsync
27152389a84c6dec057fba6fc21241991e079006vboxsync
27152389a84c6dec057fba6fc21241991e079006vboxsync/** The method creates a service and references it.
27152389a84c6dec057fba6fc21241991e079006vboxsync *
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 */
27152389a84c6dec057fba6fc21241991e079006vboxsync/* static */ int HGCMService::LoadService (const char *pszServiceLibrary, const char *pszServiceName)
27152389a84c6dec057fba6fc21241991e079006vboxsync{
27152389a84c6dec057fba6fc21241991e079006vboxsync LogFlowFunc(("lib %s, name = %s\n", pszServiceLibrary, pszServiceName));
27152389a84c6dec057fba6fc21241991e079006vboxsync
27152389a84c6dec057fba6fc21241991e079006vboxsync /* Look at already loaded services to avoid double loading. */
27152389a84c6dec057fba6fc21241991e079006vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync HGCMService *pSvc;
27152389a84c6dec057fba6fc21241991e079006vboxsync int rc = HGCMService::ResolveService (&pSvc, pszServiceName);
27152389a84c6dec057fba6fc21241991e079006vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync if (RT_SUCCESS(rc))
27152389a84c6dec057fba6fc21241991e079006vboxsync {
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync /* The service is already loaded. */
27152389a84c6dec057fba6fc21241991e079006vboxsync pSvc->ReleaseService ();
79baed6836ae36c5f15b182292387484dcf7a752vboxsync rc = VERR_HGCM_SERVICE_EXISTS;
27152389a84c6dec057fba6fc21241991e079006vboxsync }
27152389a84c6dec057fba6fc21241991e079006vboxsync else
27152389a84c6dec057fba6fc21241991e079006vboxsync {
27152389a84c6dec057fba6fc21241991e079006vboxsync /* Create the new service. */
27152389a84c6dec057fba6fc21241991e079006vboxsync pSvc = new HGCMService ();
27152389a84c6dec057fba6fc21241991e079006vboxsync
79baed6836ae36c5f15b182292387484dcf7a752vboxsync if (!pSvc)
79baed6836ae36c5f15b182292387484dcf7a752vboxsync {
27152389a84c6dec057fba6fc21241991e079006vboxsync rc = VERR_NO_MEMORY;
27152389a84c6dec057fba6fc21241991e079006vboxsync }
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync else
27152389a84c6dec057fba6fc21241991e079006vboxsync {
27152389a84c6dec057fba6fc21241991e079006vboxsync /* Load the library and call the initialization entry point. */
27152389a84c6dec057fba6fc21241991e079006vboxsync rc = pSvc->instanceCreate (pszServiceLibrary, pszServiceName);
27152389a84c6dec057fba6fc21241991e079006vboxsync
27152389a84c6dec057fba6fc21241991e079006vboxsync if (RT_SUCCESS(rc))
27152389a84c6dec057fba6fc21241991e079006vboxsync {
27152389a84c6dec057fba6fc21241991e079006vboxsync /* Insert the just created service to list for future references. */
27152389a84c6dec057fba6fc21241991e079006vboxsync pSvc->m_pSvcNext = sm_pSvcListHead;
27152389a84c6dec057fba6fc21241991e079006vboxsync pSvc->m_pSvcPrev = NULL;
27152389a84c6dec057fba6fc21241991e079006vboxsync
27152389a84c6dec057fba6fc21241991e079006vboxsync if (sm_pSvcListHead)
27152389a84c6dec057fba6fc21241991e079006vboxsync {
27152389a84c6dec057fba6fc21241991e079006vboxsync sm_pSvcListHead->m_pSvcPrev = pSvc;
27152389a84c6dec057fba6fc21241991e079006vboxsync }
27152389a84c6dec057fba6fc21241991e079006vboxsync else
27152389a84c6dec057fba6fc21241991e079006vboxsync {
27152389a84c6dec057fba6fc21241991e079006vboxsync sm_pSvcListTail = pSvc;
27152389a84c6dec057fba6fc21241991e079006vboxsync }
27152389a84c6dec057fba6fc21241991e079006vboxsync
27152389a84c6dec057fba6fc21241991e079006vboxsync sm_pSvcListHead = pSvc;
27152389a84c6dec057fba6fc21241991e079006vboxsync
27152389a84c6dec057fba6fc21241991e079006vboxsync sm_cServices++;
27152389a84c6dec057fba6fc21241991e079006vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync /* Reference the service (for first time) until it is unloaded on HGCM termination. */
27152389a84c6dec057fba6fc21241991e079006vboxsync AssertRelease (pSvc->m_u32RefCnt == 0);
27152389a84c6dec057fba6fc21241991e079006vboxsync pSvc->ReferenceService ();
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
27152389a84c6dec057fba6fc21241991e079006vboxsync LogFlowFunc(("service %p\n", pSvc));
27152389a84c6dec057fba6fc21241991e079006vboxsync }
27152389a84c6dec057fba6fc21241991e079006vboxsync }
27152389a84c6dec057fba6fc21241991e079006vboxsync }
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync LogFlowFunc(("rc = %Rrc\n", rc));
27152389a84c6dec057fba6fc21241991e079006vboxsync return rc;
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync}
27152389a84c6dec057fba6fc21241991e079006vboxsync
27152389a84c6dec057fba6fc21241991e079006vboxsync/** The method unloads a service.
27152389a84c6dec057fba6fc21241991e079006vboxsync *
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync * @thread main HGCM
27152389a84c6dec057fba6fc21241991e079006vboxsync */
27152389a84c6dec057fba6fc21241991e079006vboxsyncvoid HGCMService::UnloadService (void)
27152389a84c6dec057fba6fc21241991e079006vboxsync{
27152389a84c6dec057fba6fc21241991e079006vboxsync LogFlowFunc(("name = %s\n", m_pszSvcName));
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
27152389a84c6dec057fba6fc21241991e079006vboxsync /* Remove the service from the list. */
27152389a84c6dec057fba6fc21241991e079006vboxsync if (m_pSvcNext)
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync {
27152389a84c6dec057fba6fc21241991e079006vboxsync m_pSvcNext->m_pSvcPrev = m_pSvcPrev;
27152389a84c6dec057fba6fc21241991e079006vboxsync }
27152389a84c6dec057fba6fc21241991e079006vboxsync else
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync {
27152389a84c6dec057fba6fc21241991e079006vboxsync sm_pSvcListTail = m_pSvcPrev;
27152389a84c6dec057fba6fc21241991e079006vboxsync }
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync if (m_pSvcPrev)
27152389a84c6dec057fba6fc21241991e079006vboxsync {
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync m_pSvcPrev->m_pSvcNext = m_pSvcNext;
27152389a84c6dec057fba6fc21241991e079006vboxsync }
27152389a84c6dec057fba6fc21241991e079006vboxsync else
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync {
27152389a84c6dec057fba6fc21241991e079006vboxsync sm_pSvcListHead = m_pSvcNext;
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync }
27152389a84c6dec057fba6fc21241991e079006vboxsync
27152389a84c6dec057fba6fc21241991e079006vboxsync sm_cServices--;
27152389a84c6dec057fba6fc21241991e079006vboxsync
27152389a84c6dec057fba6fc21241991e079006vboxsync /* The service must be unloaded only if all clients were disconnected. */
27152389a84c6dec057fba6fc21241991e079006vboxsync LogFlowFunc(("m_u32RefCnt = %d\n", m_u32RefCnt));
27152389a84c6dec057fba6fc21241991e079006vboxsync AssertRelease (m_u32RefCnt == 1);
27152389a84c6dec057fba6fc21241991e079006vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync /* Now the service can be released. */
27152389a84c6dec057fba6fc21241991e079006vboxsync ReleaseService ();
27152389a84c6dec057fba6fc21241991e079006vboxsync}
27152389a84c6dec057fba6fc21241991e079006vboxsync
27152389a84c6dec057fba6fc21241991e079006vboxsync/** The method unloads all services.
27152389a84c6dec057fba6fc21241991e079006vboxsync *
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync * @thread main HGCM
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync */
27152389a84c6dec057fba6fc21241991e079006vboxsync/* static */ void HGCMService::UnloadAll (void)
79baed6836ae36c5f15b182292387484dcf7a752vboxsync{
27152389a84c6dec057fba6fc21241991e079006vboxsync while (sm_pSvcListHead)
27152389a84c6dec057fba6fc21241991e079006vboxsync {
27152389a84c6dec057fba6fc21241991e079006vboxsync sm_pSvcListHead->UnloadService ();
79baed6836ae36c5f15b182292387484dcf7a752vboxsync }
27152389a84c6dec057fba6fc21241991e079006vboxsync}
27152389a84c6dec057fba6fc21241991e079006vboxsync
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 *
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 */
27152389a84c6dec057fba6fc21241991e079006vboxsync/* static */ int HGCMService::ResolveService (HGCMService **ppSvc, const char *pszServiceName)
27152389a84c6dec057fba6fc21241991e079006vboxsync{
79baed6836ae36c5f15b182292387484dcf7a752vboxsync LogFlowFunc(("ppSvc = %p name = %s\n",
79baed6836ae36c5f15b182292387484dcf7a752vboxsync ppSvc, pszServiceName));
79baed6836ae36c5f15b182292387484dcf7a752vboxsync
79baed6836ae36c5f15b182292387484dcf7a752vboxsync if (!ppSvc || !pszServiceName)
27152389a84c6dec057fba6fc21241991e079006vboxsync {
79baed6836ae36c5f15b182292387484dcf7a752vboxsync return VERR_INVALID_PARAMETER;
27152389a84c6dec057fba6fc21241991e079006vboxsync }
79baed6836ae36c5f15b182292387484dcf7a752vboxsync
27152389a84c6dec057fba6fc21241991e079006vboxsync HGCMService *pSvc = sm_pSvcListHead;
27152389a84c6dec057fba6fc21241991e079006vboxsync
27152389a84c6dec057fba6fc21241991e079006vboxsync while (pSvc)
27152389a84c6dec057fba6fc21241991e079006vboxsync {
27152389a84c6dec057fba6fc21241991e079006vboxsync if (strcmp (pSvc->m_pszSvcName, pszServiceName) == 0)
79baed6836ae36c5f15b182292387484dcf7a752vboxsync {
27152389a84c6dec057fba6fc21241991e079006vboxsync break;
79baed6836ae36c5f15b182292387484dcf7a752vboxsync }
27152389a84c6dec057fba6fc21241991e079006vboxsync
79baed6836ae36c5f15b182292387484dcf7a752vboxsync pSvc = pSvc->m_pSvcNext;
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync }
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
27152389a84c6dec057fba6fc21241991e079006vboxsync LogFlowFunc(("lookup in the list is %p\n", pSvc));
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
27152389a84c6dec057fba6fc21241991e079006vboxsync if (pSvc == NULL)
27152389a84c6dec057fba6fc21241991e079006vboxsync {
79baed6836ae36c5f15b182292387484dcf7a752vboxsync *ppSvc = NULL;
27152389a84c6dec057fba6fc21241991e079006vboxsync return VERR_HGCM_SERVICE_NOT_FOUND;
79baed6836ae36c5f15b182292387484dcf7a752vboxsync }
27152389a84c6dec057fba6fc21241991e079006vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync pSvc->ReferenceService ();
27152389a84c6dec057fba6fc21241991e079006vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync *ppSvc = pSvc;
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
27152389a84c6dec057fba6fc21241991e079006vboxsync return VINF_SUCCESS;
895d68f6e6c15446ca98b8f6ec96ce19d7ea356fvboxsync}
27152389a84c6dec057fba6fc21241991e079006vboxsync
27152389a84c6dec057fba6fc21241991e079006vboxsync/** The method increases reference counter.
27152389a84c6dec057fba6fc21241991e079006vboxsync *
27152389a84c6dec057fba6fc21241991e079006vboxsync * @thread main HGCM
895d68f6e6c15446ca98b8f6ec96ce19d7ea356fvboxsync */
27152389a84c6dec057fba6fc21241991e079006vboxsyncvoid HGCMService::ReferenceService (void)
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync{
27152389a84c6dec057fba6fc21241991e079006vboxsync ASMAtomicIncU32 (&m_u32RefCnt);
27152389a84c6dec057fba6fc21241991e079006vboxsync LogFlowFunc(("[%s] m_u32RefCnt = %d\n", m_pszSvcName, m_u32RefCnt));
27152389a84c6dec057fba6fc21241991e079006vboxsync}
27152389a84c6dec057fba6fc21241991e079006vboxsync
27152389a84c6dec057fba6fc21241991e079006vboxsync/** The method dereferences a service and deletes it when no more refs.
27152389a84c6dec057fba6fc21241991e079006vboxsync *
27152389a84c6dec057fba6fc21241991e079006vboxsync * @thread main HGCM
27152389a84c6dec057fba6fc21241991e079006vboxsync */
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsyncvoid HGCMService::ReleaseService (void)
27152389a84c6dec057fba6fc21241991e079006vboxsync{
27152389a84c6dec057fba6fc21241991e079006vboxsync LogFlowFunc(("m_u32RefCnt = %d\n", m_u32RefCnt));
27152389a84c6dec057fba6fc21241991e079006vboxsync uint32_t u32RefCnt = ASMAtomicDecU32 (&m_u32RefCnt);
27152389a84c6dec057fba6fc21241991e079006vboxsync AssertRelease(u32RefCnt != ~0U);
27152389a84c6dec057fba6fc21241991e079006vboxsync
27152389a84c6dec057fba6fc21241991e079006vboxsync LogFlowFunc(("u32RefCnt = %d, name %s\n", u32RefCnt, m_pszSvcName));
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
27152389a84c6dec057fba6fc21241991e079006vboxsync if (u32RefCnt == 0)
27152389a84c6dec057fba6fc21241991e079006vboxsync {
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync instanceDestroy ();
27152389a84c6dec057fba6fc21241991e079006vboxsync delete this;
27152389a84c6dec057fba6fc21241991e079006vboxsync }
27152389a84c6dec057fba6fc21241991e079006vboxsync}
27152389a84c6dec057fba6fc21241991e079006vboxsync
27152389a84c6dec057fba6fc21241991e079006vboxsync/** The method is called when the VM is being reset or terminated
27152389a84c6dec057fba6fc21241991e079006vboxsync * and disconnects all clients from all services.
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync *
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync * @thread main HGCM
27152389a84c6dec057fba6fc21241991e079006vboxsync */
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync/* static */ void HGCMService::Reset (void)
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync{
27152389a84c6dec057fba6fc21241991e079006vboxsync g_fResetting = true;
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
27152389a84c6dec057fba6fc21241991e079006vboxsync HGCMService *pSvc = sm_pSvcListHead;
27152389a84c6dec057fba6fc21241991e079006vboxsync
27152389a84c6dec057fba6fc21241991e079006vboxsync while (pSvc)
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync {
27152389a84c6dec057fba6fc21241991e079006vboxsync while (pSvc->m_cClients && pSvc->m_paClientIds)
27152389a84c6dec057fba6fc21241991e079006vboxsync {
27152389a84c6dec057fba6fc21241991e079006vboxsync LogFlowFunc(("handle %d\n", pSvc->m_paClientIds[0]));
27152389a84c6dec057fba6fc21241991e079006vboxsync pSvc->DisconnectClient (pSvc->m_paClientIds[0], false);
27152389a84c6dec057fba6fc21241991e079006vboxsync }
27152389a84c6dec057fba6fc21241991e079006vboxsync
e66911cff9c18da76d9bddb0505ad329a9ccd795vboxsync#ifdef VBOX_WITH_CRHGSMI
27152389a84c6dec057fba6fc21241991e079006vboxsync /* @todo: could this actually happen that the service is destroyed on ReleaseService? */
27152389a84c6dec057fba6fc21241991e079006vboxsync HGCMService *pNextSvc = pSvc->m_pSvcNext;
27152389a84c6dec057fba6fc21241991e079006vboxsync while (pSvc->m_cHandleAcquires)
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync {
27152389a84c6dec057fba6fc21241991e079006vboxsync pSvc->HandleReleased ();
27152389a84c6dec057fba6fc21241991e079006vboxsync pSvc->ReleaseService ();
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync }
27152389a84c6dec057fba6fc21241991e079006vboxsync pSvc = pNextSvc;
27152389a84c6dec057fba6fc21241991e079006vboxsync#else
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync pSvc = pSvc->m_pSvcNext;
27152389a84c6dec057fba6fc21241991e079006vboxsync#endif
27152389a84c6dec057fba6fc21241991e079006vboxsync }
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
27152389a84c6dec057fba6fc21241991e079006vboxsync g_fResetting = false;
27152389a84c6dec057fba6fc21241991e079006vboxsync}
27152389a84c6dec057fba6fc21241991e079006vboxsync
27152389a84c6dec057fba6fc21241991e079006vboxsync/** The method saves the HGCM state.
27152389a84c6dec057fba6fc21241991e079006vboxsync *
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync * @param pSSM The saved state context.
27152389a84c6dec057fba6fc21241991e079006vboxsync * @return VBox rc.
27152389a84c6dec057fba6fc21241991e079006vboxsync * @thread main HGCM
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync */
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync/* static */ int HGCMService::SaveState (PSSMHANDLE pSSM)
27152389a84c6dec057fba6fc21241991e079006vboxsync{
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync /* Save the current handle count and restore afterwards to avoid client id conflicts. */
27152389a84c6dec057fba6fc21241991e079006vboxsync int rc = SSMR3PutU32(pSSM, hgcmObjQueryHandleCount());
27152389a84c6dec057fba6fc21241991e079006vboxsync AssertRCReturn(rc, rc);
27152389a84c6dec057fba6fc21241991e079006vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync LogFlowFunc(("%d services to be saved:\n", sm_cServices));
27152389a84c6dec057fba6fc21241991e079006vboxsync
27152389a84c6dec057fba6fc21241991e079006vboxsync /* Save number of services. */
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync rc = SSMR3PutU32(pSSM, sm_cServices);
27152389a84c6dec057fba6fc21241991e079006vboxsync AssertRCReturn(rc, rc);
27152389a84c6dec057fba6fc21241991e079006vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync /* Save every service. */
27152389a84c6dec057fba6fc21241991e079006vboxsync HGCMService *pSvc = sm_pSvcListHead;
27152389a84c6dec057fba6fc21241991e079006vboxsync
27152389a84c6dec057fba6fc21241991e079006vboxsync while (pSvc)
27152389a84c6dec057fba6fc21241991e079006vboxsync {
27152389a84c6dec057fba6fc21241991e079006vboxsync LogFlowFunc(("Saving service [%s]\n", pSvc->m_pszSvcName));
27152389a84c6dec057fba6fc21241991e079006vboxsync
27152389a84c6dec057fba6fc21241991e079006vboxsync /* Save the length of the service name. */
27152389a84c6dec057fba6fc21241991e079006vboxsync rc = SSMR3PutU32(pSSM, (uint32_t) strlen(pSvc->m_pszSvcName) + 1);
27152389a84c6dec057fba6fc21241991e079006vboxsync AssertRCReturn(rc, rc);
27152389a84c6dec057fba6fc21241991e079006vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync /* Save the name of the service. */
27152389a84c6dec057fba6fc21241991e079006vboxsync rc = SSMR3PutStrZ(pSSM, pSvc->m_pszSvcName);
27152389a84c6dec057fba6fc21241991e079006vboxsync AssertRCReturn(rc, rc);
27152389a84c6dec057fba6fc21241991e079006vboxsync
27152389a84c6dec057fba6fc21241991e079006vboxsync /* Save the number of clients. */
27152389a84c6dec057fba6fc21241991e079006vboxsync rc = SSMR3PutU32(pSSM, pSvc->m_cClients);
27152389a84c6dec057fba6fc21241991e079006vboxsync AssertRCReturn(rc, rc);
895d68f6e6c15446ca98b8f6ec96ce19d7ea356fvboxsync
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.
27152389a84c6dec057fba6fc21241991e079006vboxsync */
27152389a84c6dec057fba6fc21241991e079006vboxsync int i;
27152389a84c6dec057fba6fc21241991e079006vboxsync
27152389a84c6dec057fba6fc21241991e079006vboxsync for (i = 0; i < pSvc->m_cClients; i++)
27152389a84c6dec057fba6fc21241991e079006vboxsync {
27152389a84c6dec057fba6fc21241991e079006vboxsync uint32_t u32ClientId = pSvc->m_paClientIds[i];
27152389a84c6dec057fba6fc21241991e079006vboxsync
27152389a84c6dec057fba6fc21241991e079006vboxsync Log(("client id 0x%08X\n", u32ClientId));
27152389a84c6dec057fba6fc21241991e079006vboxsync
895d68f6e6c15446ca98b8f6ec96ce19d7ea356fvboxsync /* Save the client id. */
27152389a84c6dec057fba6fc21241991e079006vboxsync rc = SSMR3PutU32(pSSM, u32ClientId);
27152389a84c6dec057fba6fc21241991e079006vboxsync AssertRCReturn(rc, rc);
895d68f6e6c15446ca98b8f6ec96ce19d7ea356fvboxsync
27152389a84c6dec057fba6fc21241991e079006vboxsync /* Call the service, so the operation is executed by the service thread. */
27152389a84c6dec057fba6fc21241991e079006vboxsync rc = pSvc->saveClientState (u32ClientId, pSSM);
27152389a84c6dec057fba6fc21241991e079006vboxsync AssertRCReturn(rc, rc);
27152389a84c6dec057fba6fc21241991e079006vboxsync }
27152389a84c6dec057fba6fc21241991e079006vboxsync
c9a51cded51b8f691f24de730e190ef573344bfcvboxsync pSvc = pSvc->m_pSvcNext;
27152389a84c6dec057fba6fc21241991e079006vboxsync }
27152389a84c6dec057fba6fc21241991e079006vboxsync
27152389a84c6dec057fba6fc21241991e079006vboxsync return VINF_SUCCESS;
27152389a84c6dec057fba6fc21241991e079006vboxsync}
27152389a84c6dec057fba6fc21241991e079006vboxsync
27152389a84c6dec057fba6fc21241991e079006vboxsync/** The method loads saved HGCM state.
c9a51cded51b8f691f24de730e190ef573344bfcvboxsync *
27152389a84c6dec057fba6fc21241991e079006vboxsync * @param pSSM The saved state context.
27152389a84c6dec057fba6fc21241991e079006vboxsync * @return VBox rc.
27152389a84c6dec057fba6fc21241991e079006vboxsync * @thread main HGCM
27152389a84c6dec057fba6fc21241991e079006vboxsync */
27152389a84c6dec057fba6fc21241991e079006vboxsync/* static */ int HGCMService::LoadState (PSSMHANDLE pSSM)
27152389a84c6dec057fba6fc21241991e079006vboxsync{
27152389a84c6dec057fba6fc21241991e079006vboxsync /* Restore handle count to avoid client id conflicts. */
27152389a84c6dec057fba6fc21241991e079006vboxsync uint32_t u32;
27152389a84c6dec057fba6fc21241991e079006vboxsync
27152389a84c6dec057fba6fc21241991e079006vboxsync int rc = SSMR3GetU32(pSSM, &u32);
27152389a84c6dec057fba6fc21241991e079006vboxsync AssertRCReturn(rc, rc);
27152389a84c6dec057fba6fc21241991e079006vboxsync
27152389a84c6dec057fba6fc21241991e079006vboxsync hgcmObjSetHandleCount(u32);
27152389a84c6dec057fba6fc21241991e079006vboxsync
27152389a84c6dec057fba6fc21241991e079006vboxsync /* Get the number of services. */
27152389a84c6dec057fba6fc21241991e079006vboxsync uint32_t cServices;
27152389a84c6dec057fba6fc21241991e079006vboxsync
27152389a84c6dec057fba6fc21241991e079006vboxsync rc = SSMR3GetU32(pSSM, &cServices);
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync AssertRCReturn(rc, rc);
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
27152389a84c6dec057fba6fc21241991e079006vboxsync LogFlowFunc(("%d services to be restored:\n", cServices));
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
27152389a84c6dec057fba6fc21241991e079006vboxsync while (cServices--)
ce9015004a47e95eb75e047ba42f2d3200d2d222vboxsync {
27152389a84c6dec057fba6fc21241991e079006vboxsync /* Get the length of the service name. */
27152389a84c6dec057fba6fc21241991e079006vboxsync rc = SSMR3GetU32(pSSM, &u32);
27152389a84c6dec057fba6fc21241991e079006vboxsync AssertRCReturn(rc, rc);
ce9015004a47e95eb75e047ba42f2d3200d2d222vboxsync AssertReturn(u32 <= VBOX_HGCM_SVC_NAME_MAX_BYTES, VERR_SSM_UNEXPECTED_DATA);
27152389a84c6dec057fba6fc21241991e079006vboxsync
27152389a84c6dec057fba6fc21241991e079006vboxsync char *pszServiceName = (char *)alloca (u32);
895d68f6e6c15446ca98b8f6ec96ce19d7ea356fvboxsync
27152389a84c6dec057fba6fc21241991e079006vboxsync /* Get the service name. */
ce9015004a47e95eb75e047ba42f2d3200d2d222vboxsync rc = SSMR3GetStrZ(pSSM, pszServiceName, u32);
27152389a84c6dec057fba6fc21241991e079006vboxsync AssertRCReturn(rc, rc);
27152389a84c6dec057fba6fc21241991e079006vboxsync
27152389a84c6dec057fba6fc21241991e079006vboxsync LogRel(("HGCM: restoring [%s]\n", pszServiceName));
27152389a84c6dec057fba6fc21241991e079006vboxsync
27152389a84c6dec057fba6fc21241991e079006vboxsync /* Resolve the service instance. */
27152389a84c6dec057fba6fc21241991e079006vboxsync HGCMService *pSvc;
27152389a84c6dec057fba6fc21241991e079006vboxsync rc = ResolveService (&pSvc, pszServiceName);
27152389a84c6dec057fba6fc21241991e079006vboxsync AssertLogRelMsgReturn(pSvc, ("rc=%Rrc, %s\n", rc, pszServiceName), VERR_SSM_UNEXPECTED_DATA);
27152389a84c6dec057fba6fc21241991e079006vboxsync
27152389a84c6dec057fba6fc21241991e079006vboxsync /* Get the number of clients. */
27152389a84c6dec057fba6fc21241991e079006vboxsync uint32_t cClients;
27152389a84c6dec057fba6fc21241991e079006vboxsync rc = SSMR3GetU32(pSSM, &cClients);
27152389a84c6dec057fba6fc21241991e079006vboxsync if (RT_FAILURE(rc))
27152389a84c6dec057fba6fc21241991e079006vboxsync {
27152389a84c6dec057fba6fc21241991e079006vboxsync pSvc->ReleaseService ();
27152389a84c6dec057fba6fc21241991e079006vboxsync AssertFailed();
27152389a84c6dec057fba6fc21241991e079006vboxsync return rc;
895d68f6e6c15446ca98b8f6ec96ce19d7ea356fvboxsync }
27152389a84c6dec057fba6fc21241991e079006vboxsync
895d68f6e6c15446ca98b8f6ec96ce19d7ea356fvboxsync while (cClients--)
27152389a84c6dec057fba6fc21241991e079006vboxsync {
27152389a84c6dec057fba6fc21241991e079006vboxsync /* Get the client id. */
27152389a84c6dec057fba6fc21241991e079006vboxsync uint32_t u32ClientId;
27152389a84c6dec057fba6fc21241991e079006vboxsync rc = SSMR3GetU32(pSSM, &u32ClientId);
27152389a84c6dec057fba6fc21241991e079006vboxsync if (RT_FAILURE(rc))
27152389a84c6dec057fba6fc21241991e079006vboxsync {
27152389a84c6dec057fba6fc21241991e079006vboxsync pSvc->ReleaseService ();
27152389a84c6dec057fba6fc21241991e079006vboxsync AssertFailed();
895d68f6e6c15446ca98b8f6ec96ce19d7ea356fvboxsync return rc;
27152389a84c6dec057fba6fc21241991e079006vboxsync }
27152389a84c6dec057fba6fc21241991e079006vboxsync
27152389a84c6dec057fba6fc21241991e079006vboxsync /* Connect the client. */
27152389a84c6dec057fba6fc21241991e079006vboxsync rc = pSvc->CreateAndConnectClient (NULL, u32ClientId);
27152389a84c6dec057fba6fc21241991e079006vboxsync if (RT_FAILURE(rc))
27152389a84c6dec057fba6fc21241991e079006vboxsync {
27152389a84c6dec057fba6fc21241991e079006vboxsync pSvc->ReleaseService ();
27152389a84c6dec057fba6fc21241991e079006vboxsync AssertLogRelMsgFailed(("rc=%Rrc %s\n", rc, pszServiceName));
27152389a84c6dec057fba6fc21241991e079006vboxsync return rc;
27152389a84c6dec057fba6fc21241991e079006vboxsync }
27152389a84c6dec057fba6fc21241991e079006vboxsync
27152389a84c6dec057fba6fc21241991e079006vboxsync /* Call the service, so the operation is executed by the service thread. */
27152389a84c6dec057fba6fc21241991e079006vboxsync rc = pSvc->loadClientState (u32ClientId, pSSM);
27152389a84c6dec057fba6fc21241991e079006vboxsync if (RT_FAILURE(rc))
27152389a84c6dec057fba6fc21241991e079006vboxsync {
27152389a84c6dec057fba6fc21241991e079006vboxsync pSvc->ReleaseService ();
27152389a84c6dec057fba6fc21241991e079006vboxsync AssertLogRelMsgFailed(("rc=%Rrc %s\n", rc, pszServiceName));
27152389a84c6dec057fba6fc21241991e079006vboxsync return rc;
895d68f6e6c15446ca98b8f6ec96ce19d7ea356fvboxsync }
27152389a84c6dec057fba6fc21241991e079006vboxsync }
27152389a84c6dec057fba6fc21241991e079006vboxsync
c9a51cded51b8f691f24de730e190ef573344bfcvboxsync pSvc->ReleaseService ();
27152389a84c6dec057fba6fc21241991e079006vboxsync }
27152389a84c6dec057fba6fc21241991e079006vboxsync
c9a51cded51b8f691f24de730e190ef573344bfcvboxsync return VINF_SUCCESS;
27152389a84c6dec057fba6fc21241991e079006vboxsync}
27152389a84c6dec057fba6fc21241991e079006vboxsync
27152389a84c6dec057fba6fc21241991e079006vboxsync/* Create a new client instance and connect it to the service.
27152389a84c6dec057fba6fc21241991e079006vboxsync *
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.
27152389a84c6dec057fba6fc21241991e079006vboxsync */
27152389a84c6dec057fba6fc21241991e079006vboxsyncint HGCMService::CreateAndConnectClient (uint32_t *pu32ClientIdOut, uint32_t u32ClientIdIn)
27152389a84c6dec057fba6fc21241991e079006vboxsync{
27152389a84c6dec057fba6fc21241991e079006vboxsync LogFlowFunc(("pu32ClientIdOut = %p, u32ClientIdIn = %d\n", pu32ClientIdOut, u32ClientIdIn));
27152389a84c6dec057fba6fc21241991e079006vboxsync
27152389a84c6dec057fba6fc21241991e079006vboxsync /* Allocate a client information structure. */
27152389a84c6dec057fba6fc21241991e079006vboxsync HGCMClient *pClient = new HGCMClient ();
27152389a84c6dec057fba6fc21241991e079006vboxsync
27152389a84c6dec057fba6fc21241991e079006vboxsync if (!pClient)
27152389a84c6dec057fba6fc21241991e079006vboxsync {
27152389a84c6dec057fba6fc21241991e079006vboxsync LogWarningFunc(("Could not allocate HGCMClient!!!\n"));
27152389a84c6dec057fba6fc21241991e079006vboxsync return VERR_NO_MEMORY;
27152389a84c6dec057fba6fc21241991e079006vboxsync }
27152389a84c6dec057fba6fc21241991e079006vboxsync
27152389a84c6dec057fba6fc21241991e079006vboxsync uint32_t handle;
27152389a84c6dec057fba6fc21241991e079006vboxsync
27152389a84c6dec057fba6fc21241991e079006vboxsync if (pu32ClientIdOut != NULL)
27152389a84c6dec057fba6fc21241991e079006vboxsync {
27152389a84c6dec057fba6fc21241991e079006vboxsync handle = hgcmObjGenerateHandle (pClient);
27152389a84c6dec057fba6fc21241991e079006vboxsync }
27152389a84c6dec057fba6fc21241991e079006vboxsync else
27152389a84c6dec057fba6fc21241991e079006vboxsync {
5558d00238c7e019ef8c0803358fae6edeba394evboxsync handle = hgcmObjAssignHandle (pClient, u32ClientIdIn);
5558d00238c7e019ef8c0803358fae6edeba394evboxsync }
5558d00238c7e019ef8c0803358fae6edeba394evboxsync
5558d00238c7e019ef8c0803358fae6edeba394evboxsync LogFlowFunc(("client id = %d\n", handle));
5558d00238c7e019ef8c0803358fae6edeba394evboxsync
5558d00238c7e019ef8c0803358fae6edeba394evboxsync AssertRelease(handle);
5558d00238c7e019ef8c0803358fae6edeba394evboxsync
27152389a84c6dec057fba6fc21241991e079006vboxsync /* Initialize the HGCM part of the client. */
27152389a84c6dec057fba6fc21241991e079006vboxsync int rc = pClient->Init (this);
27152389a84c6dec057fba6fc21241991e079006vboxsync
5558d00238c7e019ef8c0803358fae6edeba394evboxsync if (RT_SUCCESS(rc))
27152389a84c6dec057fba6fc21241991e079006vboxsync {
ce9015004a47e95eb75e047ba42f2d3200d2d222vboxsync /* Call the service. */
27152389a84c6dec057fba6fc21241991e079006vboxsync HGCMMSGHANDLE hMsg;
27152389a84c6dec057fba6fc21241991e079006vboxsync
ce9015004a47e95eb75e047ba42f2d3200d2d222vboxsync rc = hgcmMsgAlloc (m_thread, &hMsg, SVC_MSG_CONNECT, hgcmMessageAllocSvc);
ce9015004a47e95eb75e047ba42f2d3200d2d222vboxsync
27152389a84c6dec057fba6fc21241991e079006vboxsync if (RT_SUCCESS(rc))
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync {
27152389a84c6dec057fba6fc21241991e079006vboxsync HGCMMsgSvcConnect *pMsg = (HGCMMsgSvcConnect *)hgcmObjReference (hMsg, HGCMOBJ_MSG);
27152389a84c6dec057fba6fc21241991e079006vboxsync AssertRelease(pMsg);
27152389a84c6dec057fba6fc21241991e079006vboxsync
27152389a84c6dec057fba6fc21241991e079006vboxsync pMsg->u32ClientId = handle;
27152389a84c6dec057fba6fc21241991e079006vboxsync
27152389a84c6dec057fba6fc21241991e079006vboxsync hgcmObjDereference (pMsg);
27152389a84c6dec057fba6fc21241991e079006vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync rc = hgcmMsgSend (hMsg);
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync if (RT_SUCCESS(rc))
27152389a84c6dec057fba6fc21241991e079006vboxsync {
27152389a84c6dec057fba6fc21241991e079006vboxsync /* Add the client Id to the array. */
27152389a84c6dec057fba6fc21241991e079006vboxsync if (m_cClients == m_cClientsAllocated)
27152389a84c6dec057fba6fc21241991e079006vboxsync {
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync m_paClientIds = (uint32_t *)RTMemRealloc (m_paClientIds, (m_cClientsAllocated + 64) * sizeof (m_paClientIds[0]));
27152389a84c6dec057fba6fc21241991e079006vboxsync Assert(m_paClientIds);
27152389a84c6dec057fba6fc21241991e079006vboxsync m_cClientsAllocated += 64;
895d68f6e6c15446ca98b8f6ec96ce19d7ea356fvboxsync }
27152389a84c6dec057fba6fc21241991e079006vboxsync
27152389a84c6dec057fba6fc21241991e079006vboxsync m_paClientIds[m_cClients] = handle;
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync m_cClients++;
27152389a84c6dec057fba6fc21241991e079006vboxsync }
27152389a84c6dec057fba6fc21241991e079006vboxsync }
27152389a84c6dec057fba6fc21241991e079006vboxsync }
27152389a84c6dec057fba6fc21241991e079006vboxsync
27152389a84c6dec057fba6fc21241991e079006vboxsync if (RT_FAILURE(rc))
27152389a84c6dec057fba6fc21241991e079006vboxsync {
27152389a84c6dec057fba6fc21241991e079006vboxsync hgcmObjDeleteHandle (handle);
895d68f6e6c15446ca98b8f6ec96ce19d7ea356fvboxsync }
27152389a84c6dec057fba6fc21241991e079006vboxsync else
27152389a84c6dec057fba6fc21241991e079006vboxsync {
27152389a84c6dec057fba6fc21241991e079006vboxsync if (pu32ClientIdOut != NULL)
27152389a84c6dec057fba6fc21241991e079006vboxsync {
895d68f6e6c15446ca98b8f6ec96ce19d7ea356fvboxsync *pu32ClientIdOut = handle;
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync }
27152389a84c6dec057fba6fc21241991e079006vboxsync
c9a51cded51b8f691f24de730e190ef573344bfcvboxsync ReferenceService ();
c9a51cded51b8f691f24de730e190ef573344bfcvboxsync }
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
feef019e08ac3cead66d03feb9094cac75d9bc0dvboxsync LogFlowFunc(("rc = %Rrc\n", rc));
feef019e08ac3cead66d03feb9094cac75d9bc0dvboxsync return rc;
27152389a84c6dec057fba6fc21241991e079006vboxsync}
feef019e08ac3cead66d03feb9094cac75d9bc0dvboxsync
27152389a84c6dec057fba6fc21241991e079006vboxsync/* Disconnect the client from the service and delete the client handle.
feef019e08ac3cead66d03feb9094cac75d9bc0dvboxsync *
feef019e08ac3cead66d03feb9094cac75d9bc0dvboxsync * @param u32ClientId The handle of the client.
feef019e08ac3cead66d03feb9094cac75d9bc0dvboxsync * @return VBox rc.
feef019e08ac3cead66d03feb9094cac75d9bc0dvboxsync */
feef019e08ac3cead66d03feb9094cac75d9bc0dvboxsyncint HGCMService::DisconnectClient (uint32_t u32ClientId, bool fFromService)
27152389a84c6dec057fba6fc21241991e079006vboxsync{
27152389a84c6dec057fba6fc21241991e079006vboxsync int rc = VINF_SUCCESS;
feef019e08ac3cead66d03feb9094cac75d9bc0dvboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync LogFlowFunc(("client id = %d, fFromService = %d\n", u32ClientId, fFromService));
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
27152389a84c6dec057fba6fc21241991e079006vboxsync if (!fFromService)
f5b7890acb8ed84648facc56aa99ef3c6dbf90c7vboxsync {
27152389a84c6dec057fba6fc21241991e079006vboxsync /* Call the service. */
27152389a84c6dec057fba6fc21241991e079006vboxsync HGCMMSGHANDLE hMsg;
27152389a84c6dec057fba6fc21241991e079006vboxsync
27152389a84c6dec057fba6fc21241991e079006vboxsync rc = hgcmMsgAlloc (m_thread, &hMsg, SVC_MSG_DISCONNECT, hgcmMessageAllocSvc);
27152389a84c6dec057fba6fc21241991e079006vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync if (RT_SUCCESS(rc))
27152389a84c6dec057fba6fc21241991e079006vboxsync {
27152389a84c6dec057fba6fc21241991e079006vboxsync HGCMMsgSvcDisconnect *pMsg = (HGCMMsgSvcDisconnect *)hgcmObjReference (hMsg, HGCMOBJ_MSG);
27152389a84c6dec057fba6fc21241991e079006vboxsync AssertRelease(pMsg);
27152389a84c6dec057fba6fc21241991e079006vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync pMsg->u32ClientId = u32ClientId;
27152389a84c6dec057fba6fc21241991e079006vboxsync
27152389a84c6dec057fba6fc21241991e079006vboxsync hgcmObjDereference (pMsg);
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
27152389a84c6dec057fba6fc21241991e079006vboxsync rc = hgcmMsgSend (hMsg);
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync }
27152389a84c6dec057fba6fc21241991e079006vboxsync else
27152389a84c6dec057fba6fc21241991e079006vboxsync {
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));
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync }
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync }
27152389a84c6dec057fba6fc21241991e079006vboxsync
27152389a84c6dec057fba6fc21241991e079006vboxsync /* Remove the client id from the array in any case, rc does not matter. */
27152389a84c6dec057fba6fc21241991e079006vboxsync int i;
85e5ab5adbba74b522731762dd05ca88cb529140vboxsync
27152389a84c6dec057fba6fc21241991e079006vboxsync for (i = 0; i < m_cClients; i++)
27152389a84c6dec057fba6fc21241991e079006vboxsync {
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync if (m_paClientIds[i] == u32ClientId)
27152389a84c6dec057fba6fc21241991e079006vboxsync {
27152389a84c6dec057fba6fc21241991e079006vboxsync m_cClients--;
27152389a84c6dec057fba6fc21241991e079006vboxsync
27152389a84c6dec057fba6fc21241991e079006vboxsync if (m_cClients > i)
27152389a84c6dec057fba6fc21241991e079006vboxsync {
27152389a84c6dec057fba6fc21241991e079006vboxsync memmove (&m_paClientIds[i], &m_paClientIds[i + 1], sizeof (m_paClientIds[0]) * (m_cClients - i));
27152389a84c6dec057fba6fc21241991e079006vboxsync }
27152389a84c6dec057fba6fc21241991e079006vboxsync
27152389a84c6dec057fba6fc21241991e079006vboxsync /* Delete the client handle. */
27152389a84c6dec057fba6fc21241991e079006vboxsync hgcmObjDeleteHandle (u32ClientId);
27152389a84c6dec057fba6fc21241991e079006vboxsync
27152389a84c6dec057fba6fc21241991e079006vboxsync /* The service must be released. */
27152389a84c6dec057fba6fc21241991e079006vboxsync ReleaseService ();
27152389a84c6dec057fba6fc21241991e079006vboxsync
27152389a84c6dec057fba6fc21241991e079006vboxsync break;
27152389a84c6dec057fba6fc21241991e079006vboxsync }
27152389a84c6dec057fba6fc21241991e079006vboxsync }
27152389a84c6dec057fba6fc21241991e079006vboxsync
27152389a84c6dec057fba6fc21241991e079006vboxsync LogFlowFunc(("rc = %Rrc\n", rc));
27152389a84c6dec057fba6fc21241991e079006vboxsync return rc;
27152389a84c6dec057fba6fc21241991e079006vboxsync}
27152389a84c6dec057fba6fc21241991e079006vboxsync
27152389a84c6dec057fba6fc21241991e079006vboxsyncint HGCMService::RegisterExtension (HGCMSVCEXTHANDLE handle,
27152389a84c6dec057fba6fc21241991e079006vboxsync PFNHGCMSVCEXT pfnExtension,
27152389a84c6dec057fba6fc21241991e079006vboxsync void *pvExtension)
27152389a84c6dec057fba6fc21241991e079006vboxsync{
27152389a84c6dec057fba6fc21241991e079006vboxsync LogFlowFunc(("%s\n", handle->pszServiceName));
27152389a84c6dec057fba6fc21241991e079006vboxsync
27152389a84c6dec057fba6fc21241991e079006vboxsync /* Forward the message to the service thread. */
27152389a84c6dec057fba6fc21241991e079006vboxsync HGCMMSGHANDLE hMsg = 0;
27152389a84c6dec057fba6fc21241991e079006vboxsync int rc = hgcmMsgAlloc (m_thread, &hMsg, SVC_MSG_REGEXT, hgcmMessageAllocSvc);
27152389a84c6dec057fba6fc21241991e079006vboxsync
27152389a84c6dec057fba6fc21241991e079006vboxsync if (RT_SUCCESS(rc))
27152389a84c6dec057fba6fc21241991e079006vboxsync {
27152389a84c6dec057fba6fc21241991e079006vboxsync HGCMMsgSvcRegisterExtension *pMsg = (HGCMMsgSvcRegisterExtension *)hgcmObjReference (hMsg, HGCMOBJ_MSG);
27152389a84c6dec057fba6fc21241991e079006vboxsync AssertRelease(pMsg);
27152389a84c6dec057fba6fc21241991e079006vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync pMsg->handle = handle;
27152389a84c6dec057fba6fc21241991e079006vboxsync pMsg->pfnExtension = pfnExtension;
27152389a84c6dec057fba6fc21241991e079006vboxsync pMsg->pvExtension = pvExtension;
27152389a84c6dec057fba6fc21241991e079006vboxsync
27152389a84c6dec057fba6fc21241991e079006vboxsync hgcmObjDereference (pMsg);
27152389a84c6dec057fba6fc21241991e079006vboxsync
27152389a84c6dec057fba6fc21241991e079006vboxsync rc = hgcmMsgSend (hMsg);
27152389a84c6dec057fba6fc21241991e079006vboxsync }
27152389a84c6dec057fba6fc21241991e079006vboxsync
27152389a84c6dec057fba6fc21241991e079006vboxsync LogFlowFunc(("rc = %Rrc\n", rc));
27152389a84c6dec057fba6fc21241991e079006vboxsync return rc;
27152389a84c6dec057fba6fc21241991e079006vboxsync}
27152389a84c6dec057fba6fc21241991e079006vboxsync
27152389a84c6dec057fba6fc21241991e079006vboxsyncvoid HGCMService::UnregisterExtension (HGCMSVCEXTHANDLE handle)
27152389a84c6dec057fba6fc21241991e079006vboxsync{
27152389a84c6dec057fba6fc21241991e079006vboxsync /* Forward the message to the service thread. */
27152389a84c6dec057fba6fc21241991e079006vboxsync HGCMMSGHANDLE hMsg = 0;
27152389a84c6dec057fba6fc21241991e079006vboxsync int rc = hgcmMsgAlloc (m_thread, &hMsg, SVC_MSG_UNREGEXT, hgcmMessageAllocSvc);
27152389a84c6dec057fba6fc21241991e079006vboxsync
27152389a84c6dec057fba6fc21241991e079006vboxsync if (RT_SUCCESS(rc))
27152389a84c6dec057fba6fc21241991e079006vboxsync {
27152389a84c6dec057fba6fc21241991e079006vboxsync HGCMMsgSvcUnregisterExtension *pMsg = (HGCMMsgSvcUnregisterExtension *)hgcmObjReference (hMsg, HGCMOBJ_MSG);
27152389a84c6dec057fba6fc21241991e079006vboxsync AssertRelease(pMsg);
27152389a84c6dec057fba6fc21241991e079006vboxsync
27152389a84c6dec057fba6fc21241991e079006vboxsync pMsg->handle = handle;
27152389a84c6dec057fba6fc21241991e079006vboxsync
27152389a84c6dec057fba6fc21241991e079006vboxsync hgcmObjDereference (pMsg);
27152389a84c6dec057fba6fc21241991e079006vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync rc = hgcmMsgSend (hMsg);
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync }
27152389a84c6dec057fba6fc21241991e079006vboxsync
27152389a84c6dec057fba6fc21241991e079006vboxsync LogFlowFunc(("rc = %Rrc\n", rc));
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync}
27152389a84c6dec057fba6fc21241991e079006vboxsync
27152389a84c6dec057fba6fc21241991e079006vboxsync/* Perform a guest call to the service.
27152389a84c6dec057fba6fc21241991e079006vboxsync *
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.
27152389a84c6dec057fba6fc21241991e079006vboxsync */
27152389a84c6dec057fba6fc21241991e079006vboxsyncint HGCMService::GuestCall (PPDMIHGCMPORT pHGCMPort, PVBOXHGCMCMD pCmd, uint32_t u32ClientId, uint32_t u32Function, uint32_t cParms, VBOXHGCMSVCPARM paParms[])
27152389a84c6dec057fba6fc21241991e079006vboxsync{
27152389a84c6dec057fba6fc21241991e079006vboxsync HGCMMSGHANDLE hMsg = 0;
27152389a84c6dec057fba6fc21241991e079006vboxsync
27152389a84c6dec057fba6fc21241991e079006vboxsync LogFlow(("MAIN::HGCMService::Call\n"));
27152389a84c6dec057fba6fc21241991e079006vboxsync
27152389a84c6dec057fba6fc21241991e079006vboxsync int rc = hgcmMsgAlloc (m_thread, &hMsg, SVC_MSG_GUESTCALL, hgcmMessageAllocSvc);
85e5ab5adbba74b522731762dd05ca88cb529140vboxsync
27152389a84c6dec057fba6fc21241991e079006vboxsync if (RT_SUCCESS(rc))
27152389a84c6dec057fba6fc21241991e079006vboxsync {
85e5ab5adbba74b522731762dd05ca88cb529140vboxsync HGCMMsgCall *pMsg = (HGCMMsgCall *)hgcmObjReference (hMsg, HGCMOBJ_MSG);
27152389a84c6dec057fba6fc21241991e079006vboxsync
85e5ab5adbba74b522731762dd05ca88cb529140vboxsync AssertRelease(pMsg);
27152389a84c6dec057fba6fc21241991e079006vboxsync
27152389a84c6dec057fba6fc21241991e079006vboxsync pMsg->pCmd = pCmd;
27152389a84c6dec057fba6fc21241991e079006vboxsync pMsg->pHGCMPort = pHGCMPort;
85e5ab5adbba74b522731762dd05ca88cb529140vboxsync
85e5ab5adbba74b522731762dd05ca88cb529140vboxsync pMsg->u32ClientId = u32ClientId;
85e5ab5adbba74b522731762dd05ca88cb529140vboxsync pMsg->u32Function = u32Function;
27152389a84c6dec057fba6fc21241991e079006vboxsync pMsg->cParms = cParms;
27152389a84c6dec057fba6fc21241991e079006vboxsync pMsg->paParms = paParms;
27152389a84c6dec057fba6fc21241991e079006vboxsync
27152389a84c6dec057fba6fc21241991e079006vboxsync hgcmObjDereference (pMsg);
27152389a84c6dec057fba6fc21241991e079006vboxsync
27152389a84c6dec057fba6fc21241991e079006vboxsync rc = hgcmMsgPost (hMsg, hgcmMsgCompletionCallback);
27152389a84c6dec057fba6fc21241991e079006vboxsync }
5558d00238c7e019ef8c0803358fae6edeba394evboxsync else
5558d00238c7e019ef8c0803358fae6edeba394evboxsync {
5558d00238c7e019ef8c0803358fae6edeba394evboxsync Log(("MAIN::HGCMService::Call: Message allocation failed: %Rrc\n", rc));
5558d00238c7e019ef8c0803358fae6edeba394evboxsync }
5558d00238c7e019ef8c0803358fae6edeba394evboxsync
5558d00238c7e019ef8c0803358fae6edeba394evboxsync LogFlowFunc(("rc = %Rrc\n", rc));
5558d00238c7e019ef8c0803358fae6edeba394evboxsync return rc;
5558d00238c7e019ef8c0803358fae6edeba394evboxsync}
27152389a84c6dec057fba6fc21241991e079006vboxsync
27152389a84c6dec057fba6fc21241991e079006vboxsync/* Perform a host call the service.
27152389a84c6dec057fba6fc21241991e079006vboxsync *
27152389a84c6dec057fba6fc21241991e079006vboxsync * @param u32Function The function number.
85e5ab5adbba74b522731762dd05ca88cb529140vboxsync * @param cParms Number of parameters.
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync * @param paParms Pointer to array of parameters.
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync * @return VBox rc.
27152389a84c6dec057fba6fc21241991e079006vboxsync */
27152389a84c6dec057fba6fc21241991e079006vboxsyncint HGCMService::HostCall (uint32_t u32Function, uint32_t cParms, VBOXHGCMSVCPARM *paParms)
27152389a84c6dec057fba6fc21241991e079006vboxsync{
27152389a84c6dec057fba6fc21241991e079006vboxsync LogFlowFunc(("%s u32Function = %d, cParms = %d, paParms = %p\n",
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync m_pszSvcName, u32Function, cParms, paParms));
27152389a84c6dec057fba6fc21241991e079006vboxsync
27152389a84c6dec057fba6fc21241991e079006vboxsync HGCMMSGHANDLE hMsg = 0;
27152389a84c6dec057fba6fc21241991e079006vboxsync int rc = hgcmMsgAlloc (m_thread, &hMsg, SVC_MSG_HOSTCALL, hgcmMessageAllocSvc);
27152389a84c6dec057fba6fc21241991e079006vboxsync
27152389a84c6dec057fba6fc21241991e079006vboxsync if (RT_SUCCESS(rc))
85e5ab5adbba74b522731762dd05ca88cb529140vboxsync {
27152389a84c6dec057fba6fc21241991e079006vboxsync HGCMMsgHostCallSvc *pMsg = (HGCMMsgHostCallSvc *)hgcmObjReference (hMsg, HGCMOBJ_MSG);
27152389a84c6dec057fba6fc21241991e079006vboxsync AssertRelease(pMsg);
27152389a84c6dec057fba6fc21241991e079006vboxsync
27152389a84c6dec057fba6fc21241991e079006vboxsync pMsg->u32Function = u32Function;
27152389a84c6dec057fba6fc21241991e079006vboxsync pMsg->cParms = cParms;
27152389a84c6dec057fba6fc21241991e079006vboxsync pMsg->paParms = paParms;
27152389a84c6dec057fba6fc21241991e079006vboxsync
27152389a84c6dec057fba6fc21241991e079006vboxsync hgcmObjDereference (pMsg);
85e5ab5adbba74b522731762dd05ca88cb529140vboxsync
27152389a84c6dec057fba6fc21241991e079006vboxsync rc = hgcmMsgSend (hMsg);
27152389a84c6dec057fba6fc21241991e079006vboxsync }
27152389a84c6dec057fba6fc21241991e079006vboxsync
27152389a84c6dec057fba6fc21241991e079006vboxsync LogFlowFunc(("rc = %Rrc\n", rc));
27152389a84c6dec057fba6fc21241991e079006vboxsync return rc;
27152389a84c6dec057fba6fc21241991e079006vboxsync}
27152389a84c6dec057fba6fc21241991e079006vboxsync
27152389a84c6dec057fba6fc21241991e079006vboxsync#ifdef VBOX_WITH_CRHGSMI
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsyncstatic DECLCALLBACK(void) hgcmMsgFastCallCompletionCallback (int32_t result, HGCMMsgCore *pMsgCore)
27152389a84c6dec057fba6fc21241991e079006vboxsync{
27152389a84c6dec057fba6fc21241991e079006vboxsync /* Call the VMMDev port interface to issue IRQ notification. */
27152389a84c6dec057fba6fc21241991e079006vboxsync LogFlow(("MAIN::hgcmMsgFastCallCompletionCallback: message %p\n", pMsgCore));
27152389a84c6dec057fba6fc21241991e079006vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync HGCMMsgHostFastCallAsyncSvc *pMsg = (HGCMMsgHostFastCallAsyncSvc *)pMsgCore;
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync if (pMsg->pfnCompletion)
27152389a84c6dec057fba6fc21241991e079006vboxsync {
27152389a84c6dec057fba6fc21241991e079006vboxsync pMsg->pfnCompletion (result, pMsg->u32Function, &pMsg->Param, pMsg->pvCompletion);
27152389a84c6dec057fba6fc21241991e079006vboxsync }
27152389a84c6dec057fba6fc21241991e079006vboxsync}
27152389a84c6dec057fba6fc21241991e079006vboxsync
27152389a84c6dec057fba6fc21241991e079006vboxsyncint HGCMService::HandleAcquired()
27152389a84c6dec057fba6fc21241991e079006vboxsync{
27152389a84c6dec057fba6fc21241991e079006vboxsync ++m_cHandleAcquires;
27152389a84c6dec057fba6fc21241991e079006vboxsync return VINF_SUCCESS;
27152389a84c6dec057fba6fc21241991e079006vboxsync}
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
27152389a84c6dec057fba6fc21241991e079006vboxsyncint HGCMService::HandleReleased()
27152389a84c6dec057fba6fc21241991e079006vboxsync{
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync Assert(m_cHandleAcquires);
27152389a84c6dec057fba6fc21241991e079006vboxsync if (m_cHandleAcquires)
27152389a84c6dec057fba6fc21241991e079006vboxsync {
27152389a84c6dec057fba6fc21241991e079006vboxsync --m_cHandleAcquires;
27152389a84c6dec057fba6fc21241991e079006vboxsync return VINF_SUCCESS;
27152389a84c6dec057fba6fc21241991e079006vboxsync }
27152389a84c6dec057fba6fc21241991e079006vboxsync return VERR_INVALID_STATE;
27152389a84c6dec057fba6fc21241991e079006vboxsync}
27152389a84c6dec057fba6fc21241991e079006vboxsync
27152389a84c6dec057fba6fc21241991e079006vboxsyncint HGCMService::HostFastCallAsync (uint32_t u32Function, VBOXHGCMSVCPARM *pParm, PHGCMHOSTFASTCALLCB pfnCompletion, void *pvCompletion)
27152389a84c6dec057fba6fc21241991e079006vboxsync{
27152389a84c6dec057fba6fc21241991e079006vboxsync LogFlowFunc(("%s u32Function = %d, pParm = %p\n",
27152389a84c6dec057fba6fc21241991e079006vboxsync m_pszSvcName, u32Function, pParm));
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync HGCMMSGHANDLE hMsg = 0;
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync int rc = hgcmMsgAlloc (m_thread, &hMsg, SVC_MSG_HOSTFASTCALLASYNC, hgcmMessageAllocSvc);
27152389a84c6dec057fba6fc21241991e079006vboxsync
27152389a84c6dec057fba6fc21241991e079006vboxsync if (RT_SUCCESS(rc))
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync {
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync HGCMMsgHostFastCallAsyncSvc *pMsg = (HGCMMsgHostFastCallAsyncSvc *)hgcmObjReference (hMsg, HGCMOBJ_MSG);
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync AssertRelease(pMsg);
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync pMsg->u32Function = u32Function;
6370aaf3748669b056c6ede9b64ff5f837a17820vboxsync pMsg->Param = *pParm;
6370aaf3748669b056c6ede9b64ff5f837a17820vboxsync pMsg->pfnCompletion = pfnCompletion;
6370aaf3748669b056c6ede9b64ff5f837a17820vboxsync pMsg->pvCompletion = pvCompletion;
6370aaf3748669b056c6ede9b64ff5f837a17820vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync hgcmObjDereference (pMsg);
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync rc = hgcmMsgPost(hMsg, hgcmMsgFastCallCompletionCallback);
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync }
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
e50527359fb17a5127ef6291e691c8f09d726157vboxsync LogFlowFunc(("rc = %Rrc\n", rc));
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync return rc;
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync}
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync#endif
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync/*
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync * Main HGCM thread that manages services.
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync */
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
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_LOAD (12) /* Load the service. */
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#ifdef VBOX_WITH_CRHGSMI
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync# define HGCM_MSG_SVCAQUIRE (30) /* Acquire a service handle (for fast host calls) */
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync# define HGCM_MSG_SVCRELEASE (31) /* Release a service */
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync#endif
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsyncclass HGCMMsgMainConnect: public HGCMMsgHeader
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync{
e50527359fb17a5127ef6291e691c8f09d726157vboxsync public:
e68a2ad82506ee1197ef0a520d7ffebca1e33a0cvboxsync /* Service name. */
4d6b317d67ba577744e53cdfa0c7472d4223db5avboxsync const char *pszServiceName;
4d6b317d67ba577744e53cdfa0c7472d4223db5avboxsync /* Where to store the client handle. */
02c33b191e5c82efdf0c0480ab7b28bab697feefvboxsync uint32_t *pu32ClientId;
4d6b317d67ba577744e53cdfa0c7472d4223db5avboxsync};
4d6b317d67ba577744e53cdfa0c7472d4223db5avboxsync
4d6b317d67ba577744e53cdfa0c7472d4223db5avboxsyncclass HGCMMsgMainDisconnect: public HGCMMsgHeader
e68a2ad82506ee1197ef0a520d7ffebca1e33a0cvboxsync{
4d6b317d67ba577744e53cdfa0c7472d4223db5avboxsync public:
4d6b317d67ba577744e53cdfa0c7472d4223db5avboxsync /* Handle of the client to be disconnected. */
02c33b191e5c82efdf0c0480ab7b28bab697feefvboxsync uint32_t u32ClientId;
e68a2ad82506ee1197ef0a520d7ffebca1e33a0cvboxsync};
e68a2ad82506ee1197ef0a520d7ffebca1e33a0cvboxsync
4d6b317d67ba577744e53cdfa0c7472d4223db5avboxsyncclass HGCMMsgMainLoad: public HGCMMsgCore
e68a2ad82506ee1197ef0a520d7ffebca1e33a0cvboxsync{
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync public:
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync /* Name of the library to be loaded. */
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync const char *pszServiceLibrary;
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync /* Name to be assigned to the service. */
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync const char *pszServiceName;
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync};
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsyncclass HGCMMsgMainHostCall: public HGCMMsgCore
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync{
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync public:
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync /* Which service to call. */
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync const char *pszServiceName;
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync /* Function number. */
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync uint32_t u32Function;
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync /* Number of the function parameters. */
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync uint32_t cParms;
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync /* Pointer to array of the function parameters. */
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync VBOXHGCMSVCPARM *paParms;
ad27e1d5e48ca41245120c331cc88b50464813cevboxsync};
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsyncclass HGCMMsgMainLoadSaveState: public HGCMMsgCore
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync{
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync public:
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync /* SSM context. */
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync PSSMHANDLE pSSM;
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync};
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsyncclass HGCMMsgMainReset: public HGCMMsgCore
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync{
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync};
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsyncclass HGCMMsgMainQuit: public HGCMMsgCore
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync{
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync};
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsyncclass HGCMMsgMainRegisterExtension: public HGCMMsgCore
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync{
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync public:
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync /* Returned handle to be used in HGCMMsgMainUnregisterExtension. */
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync HGCMSVCEXTHANDLE *pHandle;
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync /* Name of the service. */
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync const char *pszServiceName;
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync /* The extension entry point. */
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync PFNHGCMSVCEXT pfnExtension;
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync /* The extension pointer. */
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync void *pvExtension;
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync};
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsyncclass HGCMMsgMainUnregisterExtension: public HGCMMsgCore
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync{
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync public:
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync /* Handle of the registered extension. */
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync HGCMSVCEXTHANDLE handle;
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync};
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync#ifdef VBOX_WITH_CRHGSMI
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsyncclass HGCMMsgMainSvcAcquire: public HGCMMsgCore
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync{
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync public:
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync /* Which service to call. */
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync const char *pszServiceName;
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync /* Returned service. */
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync HGCMService *pService;
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync};
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsyncclass HGCMMsgMainSvcRelease: public HGCMMsgCore
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync{
11d3005e2935c925665896fa26fde09b3e656d70vboxsync public:
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync /* Svc . */
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync HGCMService *pService;
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync};
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync#endif
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsyncstatic HGCMMsgCore *hgcmMainMessageAlloc (uint32_t u32MsgId)
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync{
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync switch (u32MsgId)
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync {
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync case HGCM_MSG_CONNECT: return new HGCMMsgMainConnect ();
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync case HGCM_MSG_DISCONNECT: return new HGCMMsgMainDisconnect ();
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync case HGCM_MSG_LOAD: return new HGCMMsgMainLoad ();
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync case HGCM_MSG_HOSTCALL: return new HGCMMsgMainHostCall ();
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync case HGCM_MSG_LOADSTATE:
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync case HGCM_MSG_SAVESTATE: return new HGCMMsgMainLoadSaveState ();
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync case HGCM_MSG_RESET: return new HGCMMsgMainReset ();
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync case HGCM_MSG_QUIT: return new HGCMMsgMainQuit ();
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync case HGCM_MSG_REGEXT: return new HGCMMsgMainRegisterExtension ();
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync case HGCM_MSG_UNREGEXT: return new HGCMMsgMainUnregisterExtension ();
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync#ifdef VBOX_WITH_CRHGSMI
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync case HGCM_MSG_SVCAQUIRE: return new HGCMMsgMainSvcAcquire();
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync case HGCM_MSG_SVCRELEASE: return new HGCMMsgMainSvcRelease();
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync#endif
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync default:
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync AssertReleaseMsgFailed(("Msg id = %08X\n", u32MsgId));
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync }
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync return NULL;
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync}
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync/* The main HGCM thread handler. */
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsyncstatic DECLCALLBACK(void) hgcmThread (HGCMTHREADHANDLE ThreadHandle, void *pvUser)
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync{
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync LogFlowFunc(("ThreadHandle = %p, pvUser = %p\n",
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync ThreadHandle, pvUser));
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync NOREF(pvUser);
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync bool fQuit = false;
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync while (!fQuit)
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync {
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync HGCMMsgCore *pMsgCore;
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync int rc = hgcmMsgGet (ThreadHandle, &pMsgCore);
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync if (RT_FAILURE(rc))
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync {
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync /* The error means some serious unrecoverable problem in the hgcmMsg/hgcmThread layer. */
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync AssertMsgFailed (("%Rrc\n", rc));
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync break;
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync }
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync uint32_t u32MsgId = pMsgCore->MsgId ();
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync switch (u32MsgId)
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync {
0f7436d3bb787f4317851dd5b2b2ec1768618c2avboxsync case HGCM_MSG_CONNECT:
e94f86f2aec0daf4cf0628157df1ded65bcd5769vboxsync {
e94f86f2aec0daf4cf0628157df1ded65bcd5769vboxsync HGCMMsgMainConnect *pMsg = (HGCMMsgMainConnect *)pMsgCore;
e94f86f2aec0daf4cf0628157df1ded65bcd5769vboxsync
e94f86f2aec0daf4cf0628157df1ded65bcd5769vboxsync LogFlowFunc(("HGCM_MSG_CONNECT pszServiceName %s, pu32ClientId %p\n",
e94f86f2aec0daf4cf0628157df1ded65bcd5769vboxsync pMsg->pszServiceName, pMsg->pu32ClientId));
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync /* Resolve the service name to the pointer to service instance.
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync */
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync HGCMService *pService;
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync rc = HGCMService::ResolveService (&pService, pMsg->pszServiceName);
0f7436d3bb787f4317851dd5b2b2ec1768618c2avboxsync
0f7436d3bb787f4317851dd5b2b2ec1768618c2avboxsync if (RT_SUCCESS(rc))
e94f86f2aec0daf4cf0628157df1ded65bcd5769vboxsync {
e94f86f2aec0daf4cf0628157df1ded65bcd5769vboxsync /* Call the service instance method. */
e94f86f2aec0daf4cf0628157df1ded65bcd5769vboxsync rc = pService->CreateAndConnectClient (pMsg->pu32ClientId, 0);
0f7436d3bb787f4317851dd5b2b2ec1768618c2avboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync /* Release the service after resolve. */
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync pService->ReleaseService ();
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync }
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync } break;
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
e94f86f2aec0daf4cf0628157df1ded65bcd5769vboxsync case HGCM_MSG_DISCONNECT:
0f7436d3bb787f4317851dd5b2b2ec1768618c2avboxsync {
0f7436d3bb787f4317851dd5b2b2ec1768618c2avboxsync HGCMMsgMainDisconnect *pMsg = (HGCMMsgMainDisconnect *)pMsgCore;
0f7436d3bb787f4317851dd5b2b2ec1768618c2avboxsync
0f7436d3bb787f4317851dd5b2b2ec1768618c2avboxsync LogFlowFunc(("HGCM_MSG_DISCONNECT u32ClientId = %d\n",
0f7436d3bb787f4317851dd5b2b2ec1768618c2avboxsync pMsg->u32ClientId));
e94f86f2aec0daf4cf0628157df1ded65bcd5769vboxsync
0f7436d3bb787f4317851dd5b2b2ec1768618c2avboxsync HGCMClient *pClient = (HGCMClient *)hgcmObjReference (pMsg->u32ClientId, HGCMOBJ_CLIENT);
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync if (!pClient)
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync {
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync rc = VERR_HGCM_INVALID_CLIENT_ID;
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync break;
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync }
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync /* The service the client belongs to. */
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync HGCMService *pService = pClient->pService;
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync /* Call the service instance to disconnect the client. */
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync rc = pService->DisconnectClient (pMsg->u32ClientId, false);
bd88a03fe4f970611c171f081be318fcd74e85e8vboxsync
bd88a03fe4f970611c171f081be318fcd74e85e8vboxsync hgcmObjDereference (pClient);
bd88a03fe4f970611c171f081be318fcd74e85e8vboxsync } break;
bd88a03fe4f970611c171f081be318fcd74e85e8vboxsync
bd88a03fe4f970611c171f081be318fcd74e85e8vboxsync case HGCM_MSG_LOAD:
bd88a03fe4f970611c171f081be318fcd74e85e8vboxsync {
bd88a03fe4f970611c171f081be318fcd74e85e8vboxsync HGCMMsgMainLoad *pMsg = (HGCMMsgMainLoad *)pMsgCore;
bd88a03fe4f970611c171f081be318fcd74e85e8vboxsync
bd88a03fe4f970611c171f081be318fcd74e85e8vboxsync LogFlowFunc(("HGCM_MSG_LOAD pszServiceName = %s, pMsg->pszServiceLibrary = %s\n",
bd88a03fe4f970611c171f081be318fcd74e85e8vboxsync pMsg->pszServiceName, pMsg->pszServiceLibrary));
bd88a03fe4f970611c171f081be318fcd74e85e8vboxsync
bd88a03fe4f970611c171f081be318fcd74e85e8vboxsync rc = HGCMService::LoadService (pMsg->pszServiceLibrary, pMsg->pszServiceName);
bd88a03fe4f970611c171f081be318fcd74e85e8vboxsync } break;
bd88a03fe4f970611c171f081be318fcd74e85e8vboxsync
bd88a03fe4f970611c171f081be318fcd74e85e8vboxsync case HGCM_MSG_HOSTCALL:
bd88a03fe4f970611c171f081be318fcd74e85e8vboxsync {
bd88a03fe4f970611c171f081be318fcd74e85e8vboxsync HGCMMsgMainHostCall *pMsg = (HGCMMsgMainHostCall *)pMsgCore;
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
58461e707998a927c19da46b98748ee2b79f4190vboxsync LogFlowFunc(("HGCM_MSG_HOSTCALL pszServiceName %s, u32Function %d, cParms %d, paParms %p\n",
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync pMsg->pszServiceName, pMsg->u32Function, pMsg->cParms, pMsg->paParms));
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync /* Resolve the service name to the pointer to service instance. */
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync HGCMService *pService;
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync rc = HGCMService::ResolveService (&pService, pMsg->pszServiceName);
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync if (RT_SUCCESS(rc))
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync {
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync rc = pService->HostCall (pMsg->u32Function, pMsg->cParms, pMsg->paParms);
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync pService->ReleaseService ();
e6b70a63c722fdf132fdf96257aa00a1e0e37e3dvboxsync }
e6b70a63c722fdf132fdf96257aa00a1e0e37e3dvboxsync } break;
e6b70a63c722fdf132fdf96257aa00a1e0e37e3dvboxsync
e6b70a63c722fdf132fdf96257aa00a1e0e37e3dvboxsync#ifdef VBOX_WITH_CRHGSMI
e6b70a63c722fdf132fdf96257aa00a1e0e37e3dvboxsync case HGCM_MSG_SVCAQUIRE:
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync {
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync HGCMMsgMainSvcAcquire *pMsg = (HGCMMsgMainSvcAcquire *)pMsgCore;
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync LogFlowFunc(("HGCM_MSG_SVCAQUIRE pszServiceName %s\n", pMsg->pszServiceName));
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
e8d309b9da17d55dbaf8de632612470b4f16d926vboxsync /* Resolve the service name to the pointer to service instance. */
e8d309b9da17d55dbaf8de632612470b4f16d926vboxsync HGCMService *pService;
e8d309b9da17d55dbaf8de632612470b4f16d926vboxsync rc = HGCMService::ResolveService (&pService, pMsg->pszServiceName);
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync if (RT_SUCCESS(rc))
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync {
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync rc = pService->HandleAcquired ();
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync if (RT_SUCCESS(rc))
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync {
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync pMsg->pService = pService;
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync }
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync else
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync {
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync pService->ReleaseService ();
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync }
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync }
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync } break;
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync case HGCM_MSG_SVCRELEASE:
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync {
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync HGCMMsgMainSvcRelease *pMsg = (HGCMMsgMainSvcRelease *)pMsgCore;
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync LogFlowFunc(("HGCM_MSG_SVCARELEASE pService %p\n", pMsg->pService));
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync /* Resolve the service name to the pointer to service instance. */
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync rc = pMsg->pService->HandleReleased ();
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync if (RT_SUCCESS(rc))
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync {
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync pMsg->pService->ReleaseService ();
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync }
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync } break;
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync#endif
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync case HGCM_MSG_RESET:
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync {
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync LogFlowFunc(("HGCM_MSG_RESET\n"));
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync HGCMService::Reset ();
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync } break;
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync case HGCM_MSG_LOADSTATE:
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync {
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync HGCMMsgMainLoadSaveState *pMsg = (HGCMMsgMainLoadSaveState *)pMsgCore;
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync LogFlowFunc(("HGCM_MSG_LOADSTATE\n"));
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync rc = HGCMService::LoadState (pMsg->pSSM);
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync } break;
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync case HGCM_MSG_SAVESTATE:
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync {
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync HGCMMsgMainLoadSaveState *pMsg = (HGCMMsgMainLoadSaveState *)pMsgCore;
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync LogFlowFunc(("HGCM_MSG_SAVESTATE\n"));
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync rc = HGCMService::SaveState (pMsg->pSSM);
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync } break;
e068057c82b010bc7cc663e8f57ac3ef1890a33cvboxsync
85e5ab5adbba74b522731762dd05ca88cb529140vboxsync case HGCM_MSG_QUIT:
85e5ab5adbba74b522731762dd05ca88cb529140vboxsync {
85e5ab5adbba74b522731762dd05ca88cb529140vboxsync LogFlowFunc(("HGCM_MSG_QUIT\n"));
85e5ab5adbba74b522731762dd05ca88cb529140vboxsync
85e5ab5adbba74b522731762dd05ca88cb529140vboxsync HGCMService::UnloadAll ();
85e5ab5adbba74b522731762dd05ca88cb529140vboxsync
85e5ab5adbba74b522731762dd05ca88cb529140vboxsync fQuit = true;
85e5ab5adbba74b522731762dd05ca88cb529140vboxsync } break;
85e5ab5adbba74b522731762dd05ca88cb529140vboxsync
85e5ab5adbba74b522731762dd05ca88cb529140vboxsync case HGCM_MSG_REGEXT:
85e5ab5adbba74b522731762dd05ca88cb529140vboxsync {
85e5ab5adbba74b522731762dd05ca88cb529140vboxsync HGCMMsgMainRegisterExtension *pMsg = (HGCMMsgMainRegisterExtension *)pMsgCore;
85e5ab5adbba74b522731762dd05ca88cb529140vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync LogFlowFunc(("HGCM_MSG_REGEXT\n"));
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync /* Allocate the handle data. */
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync HGCMSVCEXTHANDLE handle = (HGCMSVCEXTHANDLE)RTMemAllocZ (sizeof (struct _HGCMSVCEXTHANDLEDATA)
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync + strlen (pMsg->pszServiceName)
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync + sizeof (char));
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync if (handle == NULL)
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync {
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync rc = VERR_NO_MEMORY;
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync }
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync else
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync {
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync handle->pszServiceName = (char *)((uint8_t *)handle + sizeof (struct _HGCMSVCEXTHANDLEDATA));
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync strcpy (handle->pszServiceName, pMsg->pszServiceName);
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync HGCMService *pService;
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync rc = HGCMService::ResolveService (&pService, handle->pszServiceName);
ce9015004a47e95eb75e047ba42f2d3200d2d222vboxsync
ce9015004a47e95eb75e047ba42f2d3200d2d222vboxsync if (RT_SUCCESS(rc))
ce9015004a47e95eb75e047ba42f2d3200d2d222vboxsync {
ce9015004a47e95eb75e047ba42f2d3200d2d222vboxsync pService->RegisterExtension (handle, pMsg->pfnExtension, pMsg->pvExtension);
64e889d83afc98d310a0c40fb458d23733b73b03vboxsync
64e889d83afc98d310a0c40fb458d23733b73b03vboxsync pService->ReleaseService ();
64e889d83afc98d310a0c40fb458d23733b73b03vboxsync }
64e889d83afc98d310a0c40fb458d23733b73b03vboxsync
64e889d83afc98d310a0c40fb458d23733b73b03vboxsync if (RT_FAILURE(rc))
64e889d83afc98d310a0c40fb458d23733b73b03vboxsync {
ce9015004a47e95eb75e047ba42f2d3200d2d222vboxsync RTMemFree (handle);
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync }
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync else
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync {
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync *pMsg->pHandle = handle;
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync }
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync }
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync } break;
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync case HGCM_MSG_UNREGEXT:
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync {
79baed6836ae36c5f15b182292387484dcf7a752vboxsync HGCMMsgMainUnregisterExtension *pMsg = (HGCMMsgMainUnregisterExtension *)pMsgCore;
79baed6836ae36c5f15b182292387484dcf7a752vboxsync
79baed6836ae36c5f15b182292387484dcf7a752vboxsync LogFlowFunc(("HGCM_MSG_UNREGEXT\n"));
79baed6836ae36c5f15b182292387484dcf7a752vboxsync
79baed6836ae36c5f15b182292387484dcf7a752vboxsync HGCMService *pService;
79baed6836ae36c5f15b182292387484dcf7a752vboxsync rc = HGCMService::ResolveService (&pService, pMsg->handle->pszServiceName);
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
ce9015004a47e95eb75e047ba42f2d3200d2d222vboxsync if (RT_SUCCESS(rc))
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync {
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync pService->UnregisterExtension (pMsg->handle);
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync pService->ReleaseService ();
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync }
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync RTMemFree (pMsg->handle);
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync } break;
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync default:
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync {
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync AssertMsgFailed(("hgcmThread: Unsupported message number %08X!!!\n", u32MsgId));
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync rc = VERR_NOT_SUPPORTED;
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync } break;
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync }
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync /* Complete the message processing. */
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync hgcmMsgComplete (pMsgCore, rc);
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync LogFlowFunc(("message processed %Rrc\n", rc));
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync }
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync}
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync/*
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync * The HGCM API.
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync */
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync/* The main hgcm thread. */
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsyncstatic HGCMTHREADHANDLE g_hgcmThread = 0;
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync/*
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync * Public HGCM functions.
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync *
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync * hgcmGuest* - called as a result of the guest HGCM requests.
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync * hgcmHost* - called by the host.
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync */
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync/* Load a HGCM service from the specified library.
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync * Assign the specified name to the service.
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync *
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync * @param pszServiceLibrary The library to be loaded.
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync * @param pszServiceName The name to be assigned to the service.
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync * @return VBox rc.
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync */
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsyncint HGCMHostLoad (const char *pszServiceLibrary,
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync const char *pszServiceName)
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync{
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync LogFlowFunc(("lib = %s, name = %s\n", pszServiceLibrary, pszServiceName));
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync if (!pszServiceLibrary || !pszServiceName)
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync {
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync return VERR_INVALID_PARAMETER;
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync }
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync /* Forward the request to the main hgcm thread. */
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync HGCMMSGHANDLE hMsg = 0;
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync int rc = hgcmMsgAlloc (g_hgcmThread, &hMsg, HGCM_MSG_LOAD, hgcmMainMessageAlloc);
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync if (RT_SUCCESS(rc))
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync {
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync /* Initialize the message. Since the message is synchronous, use the supplied pointers. */
79baed6836ae36c5f15b182292387484dcf7a752vboxsync HGCMMsgMainLoad *pMsg = (HGCMMsgMainLoad *)hgcmObjReference (hMsg, HGCMOBJ_MSG);
79baed6836ae36c5f15b182292387484dcf7a752vboxsync AssertRelease(pMsg);
79baed6836ae36c5f15b182292387484dcf7a752vboxsync
79baed6836ae36c5f15b182292387484dcf7a752vboxsync pMsg->pszServiceLibrary = pszServiceLibrary;
79baed6836ae36c5f15b182292387484dcf7a752vboxsync pMsg->pszServiceName = pszServiceName;
79baed6836ae36c5f15b182292387484dcf7a752vboxsync
79baed6836ae36c5f15b182292387484dcf7a752vboxsync hgcmObjDereference (pMsg);
79baed6836ae36c5f15b182292387484dcf7a752vboxsync
79baed6836ae36c5f15b182292387484dcf7a752vboxsync rc = hgcmMsgSend (hMsg);
79baed6836ae36c5f15b182292387484dcf7a752vboxsync }
79baed6836ae36c5f15b182292387484dcf7a752vboxsync
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync LogFlowFunc(("rc = %Rrc\n", rc));
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync return rc;
2ca380caf80f0dacc65f8c996077e827318f1c69vboxsync}
/* Register a HGCM service extension.
*
* @param pHandle Returned handle for the registered extension.
* @param pszServiceName The name of the service.
* @param pfnExtension The extension entry point (callback).
* @param pvExtension The extension pointer.
* @return VBox rc.
*/
int HGCMHostRegisterServiceExtension (HGCMSVCEXTHANDLE *pHandle,
const char *pszServiceName,
PFNHGCMSVCEXT pfnExtension,
void *pvExtension)
{
LogFlowFunc(("pHandle = %p, name = %s, pfn = %p, rv = %p\n", pHandle, pszServiceName, pfnExtension, pvExtension));
if (!pHandle || !pszServiceName || !pfnExtension)
{
return VERR_INVALID_PARAMETER;
}
/* Forward the request to the main hgcm thread. */
HGCMMSGHANDLE hMsg = 0;
int rc = hgcmMsgAlloc (g_hgcmThread, &hMsg, HGCM_MSG_REGEXT, hgcmMainMessageAlloc);
if (RT_SUCCESS(rc))
{
/* Initialize the message. Since the message is synchronous, use the supplied pointers. */
HGCMMsgMainRegisterExtension *pMsg = (HGCMMsgMainRegisterExtension *)hgcmObjReference (hMsg, HGCMOBJ_MSG);
AssertRelease(pMsg);
pMsg->pHandle = pHandle;
pMsg->pszServiceName = pszServiceName;
pMsg->pfnExtension = pfnExtension;
pMsg->pvExtension = pvExtension;
hgcmObjDereference (pMsg);
rc = hgcmMsgSend (hMsg);
}
LogFlowFunc(("*pHandle = %p, rc = %Rrc\n", *pHandle, rc));
return rc;
}
void HGCMHostUnregisterServiceExtension (HGCMSVCEXTHANDLE handle)
{
LogFlowFunc(("handle = %p\n", handle));
/* Forward the request to the main hgcm thread. */
HGCMMSGHANDLE hMsg = 0;
int rc = hgcmMsgAlloc (g_hgcmThread, &hMsg, HGCM_MSG_UNREGEXT, hgcmMainMessageAlloc);
if (RT_SUCCESS(rc))
{
/* Initialize the message. */
HGCMMsgMainUnregisterExtension *pMsg = (HGCMMsgMainUnregisterExtension *)hgcmObjReference (hMsg, HGCMOBJ_MSG);
AssertRelease(pMsg);
pMsg->handle = handle;
hgcmObjDereference (pMsg);
rc = hgcmMsgSend (hMsg);
}
LogFlowFunc(("rc = %Rrc\n", rc));
return;
}
/* Find a service and inform it about a client connection, create a client handle.
*
* @param pHGCMPort The port to be used for completion confirmation.
* @param pCmd The VBox HGCM context.
* @param pszServiceName The name of the service to be connected to.
* @param pu32ClientId Where the store the created client handle.
* @return VBox rc.
*/
int HGCMGuestConnect (PPDMIHGCMPORT pHGCMPort,
PVBOXHGCMCMD pCmd,
const char *pszServiceName,
uint32_t *pu32ClientId)
{
LogFlowFunc(("pHGCMPort = %p, pCmd = %p, name = %s, pu32ClientId = %p\n",
pHGCMPort, pCmd, pszServiceName, pu32ClientId));
if (pHGCMPort == NULL || pCmd == NULL || pszServiceName == NULL || pu32ClientId == NULL)
{
return VERR_INVALID_PARAMETER;
}
/* Forward the request to the main hgcm thread. */
HGCMMSGHANDLE hMsg = 0;
int rc = hgcmMsgAlloc (g_hgcmThread, &hMsg, HGCM_MSG_CONNECT, hgcmMainMessageAlloc);
if (RT_SUCCESS(rc))
{
/* Initialize the message. Since 'pszServiceName' and 'pu32ClientId'
* will not be deallocated by the caller until the message is completed,
* use the supplied pointers.
*/
HGCMMsgMainConnect *pMsg = (HGCMMsgMainConnect *)hgcmObjReference (hMsg, HGCMOBJ_MSG);
AssertRelease(pMsg);
pMsg->pHGCMPort = pHGCMPort;
pMsg->pCmd = pCmd;
pMsg->pszServiceName = pszServiceName;
pMsg->pu32ClientId = pu32ClientId;
hgcmObjDereference (pMsg);
rc = hgcmMsgPost (hMsg, hgcmMsgCompletionCallback);
}
LogFlowFunc(("rc = %Rrc\n", rc));
return rc;
}
/* Tell a service that the client is disconnecting, destroy the client handle.
*
* @param pHGCMPort The port to be used for completion confirmation.
* @param pCmd The VBox HGCM context.
* @param u32ClientId The client handle to be disconnected and deleted.
* @return VBox rc.
*/
int HGCMGuestDisconnect (PPDMIHGCMPORT pHGCMPort,
PVBOXHGCMCMD pCmd,
uint32_t u32ClientId)
{
LogFlowFunc(("pHGCMPort = %p, pCmd = %p, u32ClientId = %d\n",
pHGCMPort, pCmd, u32ClientId));
if (!pHGCMPort || !pCmd || !u32ClientId)
{
return VERR_INVALID_PARAMETER;
}
/* Forward the request to the main hgcm thread. */
HGCMMSGHANDLE hMsg = 0;
int rc = hgcmMsgAlloc (g_hgcmThread, &hMsg, HGCM_MSG_DISCONNECT, hgcmMainMessageAlloc);
if (RT_SUCCESS(rc))
{
/* Initialize the message. */
HGCMMsgMainDisconnect *pMsg = (HGCMMsgMainDisconnect *)hgcmObjReference (hMsg, HGCMOBJ_MSG);
AssertRelease(pMsg);
pMsg->pCmd = pCmd;
pMsg->pHGCMPort = pHGCMPort;
pMsg->u32ClientId = u32ClientId;
hgcmObjDereference (pMsg);
rc = hgcmMsgPost (hMsg, hgcmMsgCompletionCallback);
}
LogFlowFunc(("rc = %Rrc\n", rc));
return rc;
}
/* Helper to send either HGCM_MSG_SAVESTATE or HGCM_MSG_LOADSTATE messages to the main HGCM thread.
*
* @param pSSM The SSM handle.
* @param u32MsgId The message to be sent: HGCM_MSG_SAVESTATE or HGCM_MSG_LOADSTATE.
* @return VBox rc.
*/
static int hgcmHostLoadSaveState (PSSMHANDLE pSSM,
uint32_t u32MsgId)
{
LogFlowFunc(("pSSM = %p, u32MsgId = %d\n", pSSM, u32MsgId));
HGCMMSGHANDLE hMsg = 0;
int rc = hgcmMsgAlloc (g_hgcmThread, &hMsg, u32MsgId, hgcmMainMessageAlloc);
if (RT_SUCCESS(rc))
{
HGCMMsgMainLoadSaveState *pMsg = (HGCMMsgMainLoadSaveState *)hgcmObjReference (hMsg, HGCMOBJ_MSG);
AssertRelease(pMsg);
pMsg->pSSM = pSSM;
hgcmObjDereference (pMsg);
rc = hgcmMsgSend (hMsg);
}
LogFlowFunc(("rc = %Rrc\n", rc));
return rc;
}
/* Save the state of services.
*
* @param pSSM The SSM handle.
* @return VBox rc.
*/
int HGCMHostSaveState (PSSMHANDLE pSSM)
{
return hgcmHostLoadSaveState (pSSM, HGCM_MSG_SAVESTATE);
}
/* Load the state of services.
*
* @param pSSM The SSM handle.
* @return VBox rc.
*/
int HGCMHostLoadState (PSSMHANDLE pSSM)
{
return hgcmHostLoadSaveState (pSSM, HGCM_MSG_LOADSTATE);
}
/* The guest calls the service.
*
* @param pHGCMPort The port to be used for completion confirmation.
* @param pCmd The VBox HGCM context.
* @param u32ClientId The client handle to be disconnected and deleted.
* @param u32Function The function number.
* @param cParms Number of parameters.
* @param paParms Pointer to array of parameters.
* @return VBox rc.
*/
int HGCMGuestCall (PPDMIHGCMPORT pHGCMPort,
PVBOXHGCMCMD pCmd,
uint32_t u32ClientId,
uint32_t u32Function,
uint32_t cParms,
VBOXHGCMSVCPARM *paParms)
{
LogFlowFunc(("pHGCMPort = %p, pCmd = %p, u32ClientId = %d, u32Function = %d, cParms = %d, paParms = %p\n",
pHGCMPort, pCmd, u32ClientId, u32Function, cParms, paParms));
if (!pHGCMPort || !pCmd || u32ClientId == 0)
{
return VERR_INVALID_PARAMETER;
}
int rc = VERR_HGCM_INVALID_CLIENT_ID;
/* Resolve the client handle to the client instance pointer. */
HGCMClient *pClient = (HGCMClient *)hgcmObjReference (u32ClientId, HGCMOBJ_CLIENT);
if (pClient)
{
AssertRelease(pClient->pService);
/* Forward the message to the service thread. */
rc = pClient->pService->GuestCall (pHGCMPort, pCmd, u32ClientId, u32Function, cParms, paParms);
hgcmObjDereference (pClient);
}
LogFlowFunc(("rc = %Rrc\n", rc));
return rc;
}
/* The host calls the service.
*
* @param pszServiceName The service name to be called.
* @param u32Function The function number.
* @param cParms Number of parameters.
* @param paParms Pointer to array of parameters.
* @return VBox rc.
*/
int HGCMHostCall (const char *pszServiceName,
uint32_t u32Function,
uint32_t cParms,
VBOXHGCMSVCPARM *paParms)
{
LogFlowFunc(("name = %s, u32Function = %d, cParms = %d, paParms = %p\n",
pszServiceName, u32Function, cParms, paParms));
if (!pszServiceName)
{
return VERR_INVALID_PARAMETER;
}
HGCMMSGHANDLE hMsg = 0;
/* Host calls go to main HGCM thread that resolves the service name to the
* service instance pointer and then, using the service pointer, forwards
* the message to the service thread.
* So it is slow but host calls are intended mostly for configuration and
* other non-time-critical functions.
*/
int rc = hgcmMsgAlloc (g_hgcmThread, &hMsg, HGCM_MSG_HOSTCALL, hgcmMainMessageAlloc);
if (RT_SUCCESS(rc))
{
HGCMMsgMainHostCall *pMsg = (HGCMMsgMainHostCall *)hgcmObjReference (hMsg, HGCMOBJ_MSG);
AssertRelease(pMsg);
pMsg->pszServiceName = (char *)pszServiceName;
pMsg->u32Function = u32Function;
pMsg->cParms = cParms;
pMsg->paParms = paParms;
hgcmObjDereference (pMsg);
rc = hgcmMsgSend (hMsg);
}
LogFlowFunc(("rc = %Rrc\n", rc));
return rc;
}
#ifdef VBOX_WITH_CRHGSMI
int HGCMHostSvcHandleCreate (const char *pszServiceName, HGCMCVSHANDLE * phSvc)
{
LogFlowFunc(("name = %s\n", pszServiceName));
if (!pszServiceName)
{
return VERR_INVALID_PARAMETER;
}
if (!phSvc)
{
return VERR_INVALID_PARAMETER;
}
HGCMMSGHANDLE hMsg = 0;
/* Host calls go to main HGCM thread that resolves the service name to the
* service instance pointer and then, using the service pointer, forwards
* the message to the service thread.
* So it is slow but host calls are intended mostly for configuration and
* other non-time-critical functions.
*/
int rc = hgcmMsgAlloc (g_hgcmThread, &hMsg, HGCM_MSG_SVCAQUIRE, hgcmMainMessageAlloc);
if (RT_SUCCESS(rc))
{
HGCMMsgMainSvcAcquire *pMsg = (HGCMMsgMainSvcAcquire *)hgcmObjReference (hMsg, HGCMOBJ_MSG);
AssertRelease(pMsg);
pMsg->pszServiceName = (char *)pszServiceName;
pMsg->pService = NULL;
rc = hgcmMsgSend (hMsg);
if (RT_SUCCESS(rc))
{
/* for simplicity just use a svc ptr as handle for now */
*phSvc = (HGCMCVSHANDLE)pMsg->pService;
}
hgcmObjDereference (pMsg);
}
LogFlowFunc(("rc = %Rrc\n", rc));
return rc;
}
int HGCMHostSvcHandleDestroy (HGCMCVSHANDLE hSvc)
{
LogFlowFunc(("hSvc = %p\n", hSvc));
if (!hSvc)
{
return VERR_INVALID_PARAMETER;
}
HGCMMSGHANDLE hMsg = 0;
/* Host calls go to main HGCM thread that resolves the service name to the
* service instance pointer and then, using the service pointer, forwards
* the message to the service thread.
* So it is slow but host calls are intended mostly for configuration and
* other non-time-critical functions.
*/
int rc = hgcmMsgAlloc (g_hgcmThread, &hMsg, HGCM_MSG_SVCRELEASE, hgcmMainMessageAlloc);
if (RT_SUCCESS(rc))
{
HGCMMsgMainSvcRelease *pMsg = (HGCMMsgMainSvcRelease *)hgcmObjReference (hMsg, HGCMOBJ_MSG);
AssertRelease(pMsg);
pMsg->pService = (HGCMService *)hSvc;
hgcmObjDereference (pMsg);
rc = hgcmMsgSend (hMsg);
}
LogFlowFunc(("rc = %Rrc\n", rc));
return rc;
}
int HGCMHostFastCallAsync (HGCMCVSHANDLE hSvc, uint32_t function, VBOXHGCMSVCPARM *pParm, PHGCMHOSTFASTCALLCB pfnCompletion, void *pvCompletion)
{
LogFlowFunc(("hSvc = %p, u32Function = %d, pParm = %p\n",
hSvc, function, pParm));
if (!hSvc)
{
return VERR_INVALID_PARAMETER;
}
HGCMService *pService = (HGCMService *)hSvc;
int rc = pService->HostFastCallAsync (function, pParm, pfnCompletion, pvCompletion);
LogFlowFunc(("rc = %Rrc\n", rc));
return rc;
}
#endif
int HGCMHostReset (void)
{
LogFlowFunc(("\n"));
/* Disconnect all clients.
*/
HGCMMSGHANDLE hMsg = 0;
int rc = hgcmMsgAlloc (g_hgcmThread, &hMsg, HGCM_MSG_RESET, hgcmMainMessageAlloc);
if (RT_SUCCESS(rc))
{
rc = hgcmMsgSend (hMsg);
}
LogFlowFunc(("rc = %Rrc\n", rc));
return rc;
}
int HGCMHostInit (void)
{
LogFlowFunc(("\n"));
int rc = hgcmThreadInit ();
if (RT_SUCCESS(rc))
{
/*
* Start main HGCM thread.
*/
rc = hgcmThreadCreate (&g_hgcmThread, "MainHGCMthread", hgcmThread, NULL);
if (RT_FAILURE(rc))
{
LogRel(("Failed to start HGCM thread. HGCM services will be unavailable!!! rc = %Rrc\n", rc));
}
}
LogFlowFunc(("rc = %Rrc\n", rc));
return rc;
}
int HGCMHostShutdown (void)
{
LogFlowFunc(("\n"));
/*
* Do HGCMReset and then unload all services.
*/
int rc = HGCMHostReset ();
if (RT_SUCCESS(rc))
{
/* Send the quit message to the main hgcmThread. */
HGCMMSGHANDLE hMsg = 0;
rc = hgcmMsgAlloc (g_hgcmThread, &hMsg, HGCM_MSG_QUIT, hgcmMainMessageAlloc);
if (RT_SUCCESS(rc))
{
rc = hgcmMsgSend (hMsg);
if (RT_SUCCESS(rc))
{
/* Wait for the thread termination. */
hgcmThreadWait (g_hgcmThread);
g_hgcmThread = 0;
hgcmThreadUninit ();
}
}
}
LogFlowFunc(("rc = %Rrc\n", rc));
return rc;
}