service.cpp revision a199a85faf02c288525d2559de1f4a92289ab18b
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync/** @file
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync *
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync * Guest Property Service:
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync * Host service entry points.
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync */
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync/*
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync * Copyright (C) 2008 Sun Microsystems, Inc.
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync *
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync * available from http://www.virtualbox.org. This file is free software;
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync * you can redistribute it and/or modify it under the terms of the GNU
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync * General Public License (GPL) as published by the Free Software
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync *
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync * Clara, CA 95054 USA or visit http://www.sun.com if you need
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync * additional information or have any questions.
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync */
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync/**
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync * This HGCM service allows the guest to set and query values in a property
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync * store on the host. The service proxies the guest requests to the service
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync * owner on the host using a request callback provided by the owner, and is
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync * notified of changes to properties made by the host. It forwards these
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync * notifications to clients in the guest which have expressed interest and
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync * are waiting for notification.
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync *
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync * The service currently consists of two threads. One of these is the main
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync * HGCM service thread which deals with requests from the guest and from the
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync * host. The second thread sends the host asynchronous notifications of
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync * changes made by the guest and deals with notification timeouts.
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync *
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync * Guest requests to wait for notification are added to a list of open
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync * notification requests and completed when a corresponding guest property
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync * is changed or when the request times out.
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync */
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync#define LOG_GROUP LOG_GROUP_HGCM
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync/*******************************************************************************
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync* Header Files *
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync*******************************************************************************/
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync#include <VBox/HostServices/GuestPropertySvc.h>
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync#include <memory> /* for auto_ptr */
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync#include <iprt/err.h>
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync#include <iprt/assert.h>
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync#include <iprt/string.h>
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync#include <iprt/mem.h>
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync#include <iprt/autores.h>
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync#include <iprt/time.h>
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync#include <iprt/cpputils.h>
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync#include <iprt/req.h>
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync#include <iprt/thread.h>
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync#include <VBox/log.h>
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync#include <VBox/cfgm.h>
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync/*******************************************************************************
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync* Internal functions *
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync*******************************************************************************/
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync/** Extract a pointer value from an HGCM parameter structure */
6728a36898fd2be125a28e84d2115d19aa4923edvboxsyncstatic int VBoxHGCMParmPtrGet (VBOXHGCMSVCPARM *pParm, void **ppv, uint32_t *pcb)
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync{
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync if (pParm->type == VBOX_HGCM_SVC_PARM_PTR)
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync {
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync *ppv = pParm->u.pointer.addr;
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync *pcb = pParm->u.pointer.size;
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync return VINF_SUCCESS;
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync }
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync return VERR_INVALID_PARAMETER;
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync}
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync/** Set a uint32_t value to an HGCM parameter structure */
6728a36898fd2be125a28e84d2115d19aa4923edvboxsyncstatic void VBoxHGCMParmUInt32Set (VBOXHGCMSVCPARM *pParm, uint32_t u32)
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync{
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync pParm->type = VBOX_HGCM_SVC_PARM_32BIT;
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync pParm->u.uint32 = u32;
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync}
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync/** Set a uint64_t value to an HGCM parameter structure */
6728a36898fd2be125a28e84d2115d19aa4923edvboxsyncstatic void VBoxHGCMParmUInt64Set (VBOXHGCMSVCPARM *pParm, uint64_t u64)
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync{
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync pParm->type = VBOX_HGCM_SVC_PARM_64BIT;
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync pParm->u.uint64 = u64;
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync}
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync
6728a36898fd2be125a28e84d2115d19aa4923edvboxsyncnamespace guestProp {
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync/**
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync * Class containing the shared information service functionality.
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync */
6728a36898fd2be125a28e84d2115d19aa4923edvboxsyncclass Service : public stdx::non_copyable
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync{
6728a36898fd2be125a28e84d2115d19aa4923edvboxsyncprivate:
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync /** Type definition for use in callback functions */
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync typedef Service SELF;
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync /** HGCM helper functions. */
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync PVBOXHGCMSVCHELPERS mpHelpers;
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync /** Pointer to our configuration values node. */
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync PCFGMNODE mpValueNode;
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync /** Pointer to our configuration timestamps node. */
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync PCFGMNODE mpTimestampNode;
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync /** Pointer to our configuration flags node. */
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync PCFGMNODE mpFlagsNode;
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync /** @todo we should have classes for thread and request handler thread */
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync /** Queue of outstanding property change notifications */
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync RTREQQUEUE *mReqQueue;
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync /** Thread for processing the request queue */
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync RTTHREAD mReqThread;
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync /** Tell the thread that it should exit */
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync bool mfExitThread;
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync /** Callback function supplied by the host for notification of updates
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync * to properties */
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync PFNHGCMSVCEXT mpfnHostCallback;
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync /** User data pointer to be supplied to the host callback function */
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync void *mpvHostData;
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync
6728a36898fd2be125a28e84d2115d19aa4923edvboxsyncpublic:
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync explicit Service(PVBOXHGCMSVCHELPERS pHelpers)
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync : mpHelpers(pHelpers), mpValueNode(NULL), mpTimestampNode(NULL),
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync mpFlagsNode(NULL), mfExitThread(false), mpfnHostCallback(NULL),
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync mpvHostData(NULL)
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync {
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync int rc = RTReqCreateQueue(&mReqQueue);
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync rc = RTThreadCreate(&mReqThread, reqThreadFn, this, 0, RTTHREADTYPE_MSG_PUMP,
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync RTTHREADFLAGS_WAITABLE, "GuestPropReq");
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync if (RT_FAILURE(rc))
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync throw rc;
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync }
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync /**
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync * @copydoc VBOXHGCMSVCHELPERS::pfnUnload
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync * Simply deletes the service object
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync */
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync static DECLCALLBACK(int) svcUnload (void *pvService)
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync {
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync AssertLogRelReturn(VALID_PTR(pvService), VERR_INVALID_PARAMETER);
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync SELF *pSelf = reinterpret_cast<SELF *>(pvService);
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync int rc = pSelf->uninit();
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync AssertRC(rc);
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync if (RT_SUCCESS(rc))
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync delete pSelf;
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync return rc;
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync }
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync /**
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync * @copydoc VBOXHGCMSVCHELPERS::pfnConnect
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync * Stub implementation of pfnConnect and pfnDisconnect.
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync */
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync static DECLCALLBACK(int) svcConnectDisconnect (void * /* pvService */,
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync uint32_t /* u32ClientID */,
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync void * /* pvClient */)
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync {
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync return VINF_SUCCESS;
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync }
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync /**
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync * @copydoc VBOXHGCMSVCHELPERS::pfnCall
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync * Wraps to the call member function
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync */
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync static DECLCALLBACK(void) svcCall (void * pvService,
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync VBOXHGCMCALLHANDLE callHandle,
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync uint32_t u32ClientID,
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync void *pvClient,
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync uint32_t u32Function,
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync uint32_t cParms,
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync VBOXHGCMSVCPARM paParms[])
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync {
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync AssertLogRelReturnVoid(VALID_PTR(pvService));
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync SELF *pSelf = reinterpret_cast<SELF *>(pvService);
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync pSelf->call(callHandle, u32ClientID, pvClient, u32Function, cParms, paParms);
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync }
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync /**
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync * @copydoc VBOXHGCMSVCHELPERS::pfnHostCall
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync * Wraps to the hostCall member function
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync */
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync static DECLCALLBACK(int) svcHostCall (void *pvService,
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync uint32_t u32Function,
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync uint32_t cParms,
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync VBOXHGCMSVCPARM paParms[])
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync {
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync AssertLogRelReturn(VALID_PTR(pvService), VERR_INVALID_PARAMETER);
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync SELF *pSelf = reinterpret_cast<SELF *>(pvService);
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync return pSelf->hostCall(u32Function, cParms, paParms);
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync }
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync /**
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync * @copydoc VBOXHGCMSVCHELPERS::pfnRegisterExtension
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync * Installs a host callback for notifications of property changes.
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync */
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync static DECLCALLBACK(int) svcRegisterExtension (void *pvService,
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync PFNHGCMSVCEXT pfnExtension,
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync void *pvExtension)
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync {
0c94df02222ed175411e5363dd39658f2fb1df41vboxsync AssertLogRelReturn(VALID_PTR(pvService), VERR_INVALID_PARAMETER);
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync SELF *pSelf = reinterpret_cast<SELF *>(pvService);
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync pSelf->mpfnHostCallback = pfnExtension;
0c94df02222ed175411e5363dd39658f2fb1df41vboxsync pSelf->mpvHostData = pvExtension;
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync return VINF_SUCCESS;
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync }
6728a36898fd2be125a28e84d2115d19aa4923edvboxsyncprivate:
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync static DECLCALLBACK(int) reqThreadFn(RTTHREAD ThreadSelf, void *pvUser);
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync int validateName(const char *pszName, uint32_t cbName);
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync int validateValue(char *pszValue, uint32_t cbValue);
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync int getPropValue(uint32_t cParms, VBOXHGCMSVCPARM paParms[]);
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync int getProperty(uint32_t cParms, VBOXHGCMSVCPARM paParms[]);
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync int setProperty(uint32_t cParms, VBOXHGCMSVCPARM paParms[], bool isGuest);
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync int delProperty(uint32_t cParms, VBOXHGCMSVCPARM paParms[], bool isGuest);
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync int enumProps(uint32_t cParms, VBOXHGCMSVCPARM paParms[]);
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync void notifyHost(const char *pszProperty);
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync static DECLCALLBACK(int) reqNotify(PFNHGCMSVCEXT pfnCallback,
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync void *pvData, char *pszName,
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync char *pszValue, uint32_t u32TimeHigh,
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync uint32_t u32TimeLow, char *pszFlags);
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync /**
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync * Empty request function for terminating the request thread.
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync * @returns VINF_EOF to cause the request processing function to return
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync * @todo return something more appropriate
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync */
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync static DECLCALLBACK(int) reqVoid() { return VINF_EOF; }
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync void call (VBOXHGCMCALLHANDLE callHandle, uint32_t u32ClientID,
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync void *pvClient, uint32_t eFunction, uint32_t cParms,
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync VBOXHGCMSVCPARM paParms[]);
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync int hostCall (uint32_t eFunction, uint32_t cParms, VBOXHGCMSVCPARM paParms[]);
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync int uninit ();
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync};
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync/**
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync * Thread function for processing the request queue
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync * @copydoc FNRTTHREAD
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync */
6728a36898fd2be125a28e84d2115d19aa4923edvboxsyncDECLCALLBACK(int) Service::reqThreadFn(RTTHREAD ThreadSelf, void *pvUser)
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync{
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync SELF *pSelf = reinterpret_cast<SELF *>(pvUser);
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync while (!pSelf->mfExitThread)
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync RTReqProcess(pSelf->mReqQueue, RT_INDEFINITE_WAIT);
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync return VINF_SUCCESS;
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync}
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync/**
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync * Checking that the name passed by the guest fits our criteria for a
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync * property name.
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync *
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync * @returns IPRT status code
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync * @param pszName the name passed by the guest
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync * @param cbName the number of bytes pszName points to, including the
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync * terminating '\0'
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync * @thread HGCM
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync */
0c94df02222ed175411e5363dd39658f2fb1df41vboxsyncint Service::validateName(const char *pszName, uint32_t cbName)
0c94df02222ed175411e5363dd39658f2fb1df41vboxsync{
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync LogFlowFunc(("cbName=%d\n", cbName));
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync /*
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync * Validate the name, checking that it's proper UTF-8 and has
0c94df02222ed175411e5363dd39658f2fb1df41vboxsync * a string terminator.
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync */
0c94df02222ed175411e5363dd39658f2fb1df41vboxsync int rc = RTStrValidateEncodingEx(pszName, RT_MIN(cbName, (uint32_t) MAX_NAME_LEN),
0c94df02222ed175411e5363dd39658f2fb1df41vboxsync RTSTR_VALIDATE_ENCODING_ZERO_TERMINATED);
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync if (RT_SUCCESS(rc) && (cbName < 2))
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync rc = VERR_INVALID_PARAMETER;
0c94df02222ed175411e5363dd39658f2fb1df41vboxsync
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync LogFlowFunc(("returning %Rrc\n", rc));
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync return rc;
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync}
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync/**
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync * Check that the data passed by the guest fits our criteria for the value of
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync * a guest property.
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync *
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync * @returns IPRT status code
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync * @param pszValue the value to store in the property
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync * @param cbValue the number of bytes in the buffer pszValue points to
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync * @thread HGCM
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync */
6728a36898fd2be125a28e84d2115d19aa4923edvboxsyncint Service::validateValue(char *pszValue, uint32_t cbValue)
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync{
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync LogFlowFunc(("cbValue=%d\n", cbValue));
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync /*
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync * Validate the value, checking that it's proper UTF-8 and has
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync * a string terminator. Don't pass a 0 length request to the
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync * validator since it won't find any '\0' then.
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync */
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync int rc = VINF_SUCCESS;
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync if (cbValue)
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync rc = RTStrValidateEncodingEx(pszValue, RT_MIN(cbValue, (uint32_t) MAX_VALUE_LEN),
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync RTSTR_VALIDATE_ENCODING_ZERO_TERMINATED);
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync if (RT_SUCCESS(rc))
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync LogFlow((" pszValue=%s\n", cbValue > 0 ? pszValue : NULL));
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync LogFlowFunc(("returning %Rrc\n", rc));
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync return rc;
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync}
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync/**
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync * Retrieve a value from the property registry by name, checking the validity
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync * of the arguments passed. If the guest has not allocated enough buffer
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync * space for the value then we return VERR_OVERFLOW and set the size of the
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync * buffer needed in the "size" HGCM parameter. If the name was not found at
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync * all, we return VERR_NOT_FOUND.
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync *
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync * @returns iprt status value
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync * @param cParms the number of HGCM parameters supplied
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync * @param paParms the array of HGCM parameters
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync * @thread HGCM
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync */
6728a36898fd2be125a28e84d2115d19aa4923edvboxsyncint Service::getPropValue(uint32_t cParms, VBOXHGCMSVCPARM paParms[])
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync{
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync int rc = VINF_SUCCESS;
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync char *pszName, *pszValue;
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync uint32_t cbName, cbValue;
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync size_t cbValueActual;
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync LogFlowThisFunc(("\n"));
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync AssertReturn(VALID_PTR(mpValueNode), VERR_WRONG_ORDER); /* a.k.a. VERR_NOT_INITIALIZED */
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync if ( (cParms != 3) /* Hardcoded value as the next lines depend on it. */
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync || (paParms[0].type != VBOX_HGCM_SVC_PARM_PTR) /* name */
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync || (paParms[1].type != VBOX_HGCM_SVC_PARM_PTR) /* value */
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync )
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync rc = VERR_INVALID_PARAMETER;
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync if (RT_SUCCESS(rc))
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync rc = VBoxHGCMParmPtrGet(&paParms[0], (void **) &pszName, &cbName);
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync if (RT_SUCCESS(rc))
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync rc = VBoxHGCMParmPtrGet(&paParms[1], (void **) &pszValue, &cbValue);
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync if (RT_SUCCESS(rc))
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync rc = validateName(pszName, cbName);
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync if (RT_SUCCESS(rc))
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync rc = CFGMR3QuerySize(mpValueNode, pszName, &cbValueActual);
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync if (RT_SUCCESS(rc))
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync VBoxHGCMParmUInt32Set(&paParms[2], cbValueActual);
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync if (RT_SUCCESS(rc) && (cbValueActual > cbValue))
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync rc = VERR_BUFFER_OVERFLOW;
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync if (RT_SUCCESS(rc))
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync rc = CFGMR3QueryString(mpValueNode, pszName, pszValue, cbValue);
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync if (RT_SUCCESS(rc))
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync Log2(("Queried string %s, rc=%Rrc, value=%.*s\n", pszName, rc, cbValue, pszValue));
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync else if (VERR_CFGM_VALUE_NOT_FOUND == rc)
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync rc = VERR_NOT_FOUND;
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync LogFlowThisFunc(("rc = %Rrc\n", rc));
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync return rc;
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync}
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync/**
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync * Retrieve a value from the property registry by name, checking the validity
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync * of the arguments passed. If the guest has not allocated enough buffer
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync * space for the value then we return VERR_OVERFLOW and set the size of the
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync * buffer needed in the "size" HGCM parameter. If the name was not found at
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync * all, we return VERR_NOT_FOUND.
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync *
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync * @returns iprt status value
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync * @param cParms the number of HGCM parameters supplied
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync * @param paParms the array of HGCM parameters
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync * @thread HGCM
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync */
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsyncint Service::getProperty(uint32_t cParms, VBOXHGCMSVCPARM paParms[])
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync{
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync int rc = VINF_SUCCESS;
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync char *pszName, *pchBuf;
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync uint32_t cchName, cchBuf;
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync size_t cchValue, cchFlags, cchBufActual;
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync char szFlags[MAX_FLAGS_LEN];
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync uint32_t fFlags;
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync /*
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync * Get and validate the parameters
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync */
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync LogFlowThisFunc(("\n"));
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync AssertReturn(VALID_PTR(mpValueNode), VERR_WRONG_ORDER); /* a.k.a. VERR_NOT_INITIALIZED */
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync if ( (cParms != 4) /* Hardcoded value as the next lines depend on it. */
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync || (paParms[0].type != VBOX_HGCM_SVC_PARM_PTR) /* name */
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync || (paParms[1].type != VBOX_HGCM_SVC_PARM_PTR) /* buffer */
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync )
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync rc = VERR_INVALID_PARAMETER;
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync if (RT_SUCCESS(rc))
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync rc = VBoxHGCMParmPtrGet(&paParms[0], (void **) &pszName, &cchName);
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync if (RT_SUCCESS(rc))
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync rc = VBoxHGCMParmPtrGet(&paParms[1], (void **) &pchBuf, &cchBuf);
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync if (RT_SUCCESS(rc))
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync rc = validateName(pszName, cchName);
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync /*
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync * Read and set the values we will return
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync */
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync /* Get the value size */
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync if (RT_SUCCESS(rc))
ac153c99053f1edf42b00bf3a13475923bc4fcf1vboxsync rc = CFGMR3QuerySize(mpValueNode, pszName, &cchValue);
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync /* Get the flags and their size */
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync if (RT_SUCCESS(rc))
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync CFGMR3QueryU32(mpFlagsNode, pszName, (uint32_t *)&fFlags);
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync if (RT_SUCCESS(rc))
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync rc = writeFlags(fFlags, szFlags);
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync if (RT_SUCCESS(rc))
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync cchFlags = strlen(szFlags);
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync /* Check that the buffer is big enough */
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync if (RT_SUCCESS(rc))
ac153c99053f1edf42b00bf3a13475923bc4fcf1vboxsync {
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync cchBufActual = cchValue + cchFlags;
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync VBoxHGCMParmUInt32Set(&paParms[3], cchBufActual);
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync }
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync if (RT_SUCCESS(rc) && (cchBufActual > cchBuf))
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync rc = VERR_BUFFER_OVERFLOW;
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync /* Write the value */
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync if (RT_SUCCESS(rc))
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync rc = CFGMR3QueryString(mpValueNode, pszName, pchBuf, cchBuf);
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync /* Write the flags */
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync if (RT_SUCCESS(rc))
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync strcpy(pchBuf + cchValue, szFlags);
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync /* Timestamp */
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync uint64_t u64Timestamp = 0;
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync if (RT_SUCCESS(rc))
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync CFGMR3QueryU64(mpTimestampNode, pszName, &u64Timestamp);
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync VBoxHGCMParmUInt64Set(&paParms[2], u64Timestamp);
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync /*
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync * Done! Do exit logging and return.
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync */
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync if (RT_SUCCESS(rc))
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync Log2(("Queried string %S, value=%.*S, timestamp=%lld, flags=%.*S\n",
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync pszName, cchValue, pchBuf, u64Timestamp, cchFlags,
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync pchBuf + cchValue));
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync else if (VERR_CFGM_VALUE_NOT_FOUND == rc)
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync rc = VERR_NOT_FOUND;
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync LogFlowThisFunc(("rc = %Rrc\n", rc));
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync return rc;
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync}
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync/**
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync * Set a value in the property registry by name, checking the validity
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync * of the arguments passed.
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync *
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync * @returns iprt status value
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync * @param cParms the number of HGCM parameters supplied
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync * @param paParms the array of HGCM parameters
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync * @thread HGCM
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync */
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsyncint Service::setProperty(uint32_t cParms, VBOXHGCMSVCPARM paParms[], bool isGuest)
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync{
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync int rc = VINF_SUCCESS;
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync char *pszName, *pszValue;
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync uint32_t cchName, cchValue;
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync uint32_t fFlags = NILFLAG;
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync LogFlowThisFunc(("\n"));
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync AssertReturn(VALID_PTR(mpValueNode), VERR_WRONG_ORDER); /* a.k.a. VERR_NOT_INITIALIZED */
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync /*
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync * First of all, make sure that we won't exceed the maximum number of properties.
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync */
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync {
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync unsigned cChildren = 0;
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync for (PCFGMNODE pChild = CFGMR3GetFirstChild(mpValueNode); pChild != 0; pChild = CFGMR3GetNextChild(pChild))
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync ++cChildren;
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync if (cChildren >= MAX_PROPS)
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync rc = VERR_TOO_MUCH_DATA;
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync }
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync /*
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync * General parameter correctness checking.
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync */
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync if ( RT_SUCCESS(rc)
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync && ( (cParms < 2) || (cParms > 4) /* Hardcoded value as the next lines depend on it. */
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync || (paParms[0].type != VBOX_HGCM_SVC_PARM_PTR) /* name */
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync || (paParms[1].type != VBOX_HGCM_SVC_PARM_PTR) /* value */
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync || ((3 == cParms) && (paParms[2].type != VBOX_HGCM_SVC_PARM_PTR)) /* flags */
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync )
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync )
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync rc = VERR_INVALID_PARAMETER;
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync /*
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync * Check the values passed in the parameters for correctness.
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync */
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync if (RT_SUCCESS(rc))
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync rc = VBoxHGCMParmPtrGet(&paParms[0], (void **) &pszName, &cchName);
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync if (RT_SUCCESS(rc))
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync rc = VBoxHGCMParmPtrGet(&paParms[1], (void **) &pszValue, &cchValue);
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync if (RT_SUCCESS(rc))
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync rc = validateName(pszName, cchName);
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync if (RT_SUCCESS(rc))
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync rc = validateValue(pszValue, cchValue);
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync /*
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync * If the property already exists, check its flags to see if we are allowed
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync * to change it.
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync */
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync if (RT_SUCCESS(rc))
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync {
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync CFGMR3QueryU32(mpFlagsNode, pszName, &fFlags); /* Failure is no problem here. */
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync if ( (isGuest && (fFlags & RDONLYGUEST))
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync || (!isGuest && (fFlags & RDONLYHOST))
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync )
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync rc = VERR_PERMISSION_DENIED;
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync }
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync /*
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync * Check whether the user supplied flags (if any) are valid.
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync */
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync if (RT_SUCCESS(rc) && (3 == cParms))
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync {
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync char *pszFlags;
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync uint32_t cchFlags;
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync rc = VBoxHGCMParmPtrGet(&paParms[2], (void **) &pszFlags, &cchFlags);
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync if (RT_SUCCESS(rc))
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync rc = validateFlags(pszFlags, &fFlags);
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync }
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync /*
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync * Set the actual value
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync */
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync if (RT_SUCCESS(rc))
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync {
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync RTTIMESPEC time;
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync CFGMR3RemoveValue(mpValueNode, pszName);
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync CFGMR3RemoveValue(mpTimestampNode, pszName);
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync CFGMR3RemoveValue(mpFlagsNode, pszName);
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync rc = CFGMR3InsertString(mpValueNode, pszName, pszValue);
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync if (RT_SUCCESS(rc))
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync rc = CFGMR3InsertInteger(mpTimestampNode, pszName,
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync RTTimeSpecGetNano(RTTimeNow(&time)));
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync if (RT_SUCCESS(rc))
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync rc = CFGMR3InsertInteger(mpFlagsNode, pszName, fFlags);
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync /* If anything goes wrong, make sure that we leave a clean state
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync * behind. */
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync if (RT_FAILURE(rc))
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync {
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync CFGMR3RemoveValue(mpValueNode, pszName);
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync CFGMR3RemoveValue(mpTimestampNode, pszName);
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync CFGMR3RemoveValue(mpFlagsNode, pszName);
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync }
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync }
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync /*
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync * Send a notification to the host and return.
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync */
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync if (RT_SUCCESS(rc))
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync {
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync if (isGuest)
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync notifyHost(pszName);
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync Log2(("Set string %s, rc=%Rrc, value=%s\n", pszName, rc, pszValue));
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync }
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync LogFlowThisFunc(("rc = %Rrc\n", rc));
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync return rc;
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync}
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync
ac153c99053f1edf42b00bf3a13475923bc4fcf1vboxsync
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync/**
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync * Remove a value in the property registry by name, checking the validity
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync * of the arguments passed.
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync *
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync * @returns iprt status value
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync * @param cParms the number of HGCM parameters supplied
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync * @param paParms the array of HGCM parameters
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync * @thread HGCM
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync */
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsyncint Service::delProperty(uint32_t cParms, VBOXHGCMSVCPARM paParms[], bool isGuest)
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync{
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync int rc = VINF_SUCCESS;
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync char *pszName;
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync uint32_t cbName;
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync LogFlowThisFunc(("\n"));
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync AssertReturn(VALID_PTR(mpValueNode), VERR_WRONG_ORDER); /* a.k.a. VERR_NOT_INITIALIZED */
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync /*
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync * Check the user-supplied parameters.
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync */
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync if ( (cParms != 1) /* Hardcoded value as the next lines depend on it. */
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync || (paParms[0].type != VBOX_HGCM_SVC_PARM_PTR) /* name */
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync )
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync rc = VERR_INVALID_PARAMETER;
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync if (RT_SUCCESS(rc))
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync rc = VBoxHGCMParmPtrGet(&paParms[0], (void **) &pszName, &cbName);
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync if (RT_SUCCESS(rc))
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync rc = validateName(pszName, cbName);
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync /*
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync * If the property already exists, check its flags to see if we are allowed
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync * to change it.
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync */
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync if (RT_SUCCESS(rc))
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync {
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync uint32_t fFlags = NILFLAG;
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync CFGMR3QueryU32(mpFlagsNode, pszName, &fFlags); /* Failure is no problem here. */
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync if ( (isGuest && (fFlags & RDONLYGUEST))
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync || (!isGuest && (fFlags & RDONLYHOST))
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync )
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync rc = VERR_PERMISSION_DENIED;
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync }
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync /*
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync * And delete the property if all is well.
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync */
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync if (RT_SUCCESS(rc))
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync {
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync CFGMR3RemoveValue(mpValueNode, pszName);
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync if (isGuest)
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync notifyHost(pszName);
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync }
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync LogFlowThisFunc(("rc = %Rrc\n", rc));
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync return rc;
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync}
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync/**
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync * Enumerate guest properties by mask, checking the validity
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync * of the arguments passed.
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync *
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync * @returns iprt status value
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync * @param cParms the number of HGCM parameters supplied
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync * @param paParms the array of HGCM parameters
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync * @thread HGCM
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync */
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsyncint Service::enumProps(uint32_t cParms, VBOXHGCMSVCPARM paParms[])
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync{
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync /* We reallocate the temporary buffer in which we build up our array in
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync * increments of size BLOCK: */
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync enum
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync {
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync /* Calculate the increment, not yet rounded down */
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync BLOCKINCRFULL = (MAX_NAME_LEN + MAX_VALUE_LEN + MAX_FLAGS_LEN + 2048),
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync /* And this is the increment after rounding */
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync BLOCKINCR = BLOCKINCRFULL - BLOCKINCRFULL % 1024
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync };
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync int rc = VINF_SUCCESS;
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync/*
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync * Get the HGCM function arguments.
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync */
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync char *paszPatterns = NULL, *pchBuf = NULL;
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync uint32_t cchPatterns = 0, cchBuf = 0;
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync LogFlowThisFunc(("\n"));
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync AssertReturn(VALID_PTR(mpValueNode), VERR_WRONG_ORDER); /* a.k.a. VERR_NOT_INITIALIZED */
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync if ( (cParms != 3) /* Hardcoded value as the next lines depend on it. */
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync || (paParms[0].type != VBOX_HGCM_SVC_PARM_PTR) /* patterns */
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync || (paParms[1].type != VBOX_HGCM_SVC_PARM_PTR) /* return buffer */
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync )
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync rc = VERR_INVALID_PARAMETER;
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync if (RT_SUCCESS(rc))
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync rc = VBoxHGCMParmPtrGet(&paParms[0], (void **) &paszPatterns, &cchPatterns);
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync if (RT_SUCCESS(rc) && cchPatterns > MAX_PATTERN_LEN)
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync rc = VERR_TOO_MUCH_DATA;
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync if (RT_SUCCESS(rc))
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync rc = VBoxHGCMParmPtrGet(&paParms[1], (void **) &pchBuf, &cchBuf);
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync/*
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync * First repack the patterns into the format expected by RTStrSimplePatternMatch()
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync */
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync bool matchAll = false;
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync char pszPatterns[MAX_PATTERN_LEN];
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync if ( (NULL == paszPatterns)
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync || (cchPatterns < 2) /* An empty pattern string means match all */
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync )
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync matchAll = true;
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync else
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync {
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync for (unsigned i = 0; i < cchPatterns - 1; ++i)
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync if (paszPatterns[i] != '\0')
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync pszPatterns[i] = paszPatterns[i];
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync else
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync pszPatterns[i] = '|';
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync pszPatterns[cchPatterns - 1] = '\0';
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync }
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync/*
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync * Next enumerate all values in the current node into a temporary buffer.
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync */
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync RTMemAutoPtr<char> TmpBuf;
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync uint32_t cchTmpBuf = 0, iTmpBuf = 0;
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync PCFGMLEAF pLeaf = CFGMR3GetFirstValue(mpValueNode);
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync while ((pLeaf != NULL) && RT_SUCCESS(rc))
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync {
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync /* Reallocate the buffer if it has got too tight */
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync if (iTmpBuf + BLOCKINCR > cchTmpBuf)
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync {
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync cchTmpBuf += BLOCKINCR * 2;
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync if (!TmpBuf.realloc(cchTmpBuf))
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync rc = VERR_NO_MEMORY;
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync }
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync /* Fetch the name into the buffer and if it matches one of the
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync * patterns, add its value and an empty timestamp and flags. If it
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync * doesn't match, we simply overwrite it in the buffer. */
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync if (RT_SUCCESS(rc))
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync rc = CFGMR3GetValueName(pLeaf, &TmpBuf[iTmpBuf], cchTmpBuf - iTmpBuf);
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync /* Only increment the buffer offest if the name matches, otherwise we
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync * overwrite it next iteration. */
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync if ( RT_SUCCESS(rc)
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync && ( matchAll
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync || RTStrSimplePatternMultiMatch(pszPatterns, RTSTR_MAX,
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync &TmpBuf[iTmpBuf], RTSTR_MAX,
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync NULL)
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync )
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync )
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync {
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync const char *pszName = &TmpBuf[iTmpBuf];
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync /* Get value */
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync iTmpBuf += strlen(&TmpBuf[iTmpBuf]) + 1;
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync rc = CFGMR3QueryString(mpValueNode, pszName, &TmpBuf[iTmpBuf],
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync cchTmpBuf - iTmpBuf);
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync if (RT_SUCCESS(rc))
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync {
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync /* Get timestamp */
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync iTmpBuf += strlen(&TmpBuf[iTmpBuf]) + 1;
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync uint64_t u64Timestamp = 0;
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync CFGMR3QueryU64(mpTimestampNode, pszName, &u64Timestamp);
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync iTmpBuf += RTStrFormatNumber(&TmpBuf[iTmpBuf], u64Timestamp,
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync 10, 0, 0, 0) + 1;
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync /* Get flags */
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync uint32_t fFlags = NILFLAG;
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync CFGMR3QueryU32(mpFlagsNode, pszName, &fFlags);
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync TmpBuf[iTmpBuf] = '\0'; /* Bad (== in)sanity, will be fixed. */
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync writeFlags(fFlags, &TmpBuf[iTmpBuf]);
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync iTmpBuf += strlen(&TmpBuf[iTmpBuf]) + 1;
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync }
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync }
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync if (RT_SUCCESS(rc))
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync pLeaf = CFGMR3GetNextValue(pLeaf);
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync }
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync if (RT_SUCCESS(rc))
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync {
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync /* The terminator. We *do* have space left for this. */
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync TmpBuf[iTmpBuf] = '\0';
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync TmpBuf[iTmpBuf + 1] = '\0';
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync TmpBuf[iTmpBuf + 2] = '\0';
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync TmpBuf[iTmpBuf + 3] = '\0';
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync iTmpBuf += 4;
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync VBoxHGCMParmUInt32Set(&paParms[2], iTmpBuf);
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync /* Copy the memory if it fits into the guest buffer */
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync if (iTmpBuf <= cchBuf)
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync memcpy(pchBuf, TmpBuf.get(), iTmpBuf);
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync else
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync rc = VERR_BUFFER_OVERFLOW;
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync }
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync return rc;
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync}
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync/**
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync * Notify the service owner that a property has been added/deleted/changed
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync * @param pszProperty the name of the property which has changed
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync * @note this call allocates memory which the reqNotify request is expected to
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync * free again, using RTStrFree().
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync *
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync * @thread HGCM service
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync */
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsyncvoid Service::notifyHost(const char *pszProperty)
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync{
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync char szValue[MAX_VALUE_LEN];
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync uint64_t u64Timestamp = 0;
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync uint32_t fFlags = NILFLAG;
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync char szFlags[MAX_FLAGS_LEN];
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync char *pszName = NULL, *pszValue = NULL, *pszFlags = NULL;
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync AssertPtr(mpValueNode);
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync if (NULL == mpfnHostCallback)
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync return; /* Nothing to do. */
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync int rc = CFGMR3QueryString(mpValueNode, pszProperty, szValue,
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync sizeof(szValue));
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync /*
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync * First case: if the property exists then send the host its current value
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync */
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync if (rc != VERR_CFGM_VALUE_NOT_FOUND)
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync {
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync if (RT_SUCCESS(rc))
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync rc = CFGMR3QueryU64(mpTimestampNode, pszProperty, &u64Timestamp);
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync if (RT_SUCCESS(rc))
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync rc = CFGMR3QueryU32(mpFlagsNode, pszProperty, &fFlags);
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync if (RT_SUCCESS(rc))
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync rc = writeFlags(fFlags, szFlags);
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync if (RT_SUCCESS(rc))
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync rc = RTStrDupEx(&pszName, pszProperty);
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync if (RT_SUCCESS(rc))
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync rc = RTStrDupEx(&pszValue, szValue);
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync if (RT_SUCCESS(rc))
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync rc = RTStrDupEx(&pszFlags, szFlags);
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync if (RT_SUCCESS(rc))
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync rc = RTReqCallEx(mReqQueue, NULL, 0, RTREQFLAGS_NO_WAIT,
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync (PFNRT)Service::reqNotify, 7, mpfnHostCallback,
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync mpvHostData, pszName, pszValue,
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync (uint32_t) RT_HIDWORD(u64Timestamp),
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync (uint32_t) RT_LODWORD(u64Timestamp), pszFlags);
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync if (RT_FAILURE(rc)) /* clean up */
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync {
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync RTStrFree(pszName);
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync RTStrFree(pszValue);
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync RTStrFree(pszFlags);
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync }
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync }
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync else
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync /*
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync * Second case: if the property does not exist then send the host an empty
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync * value
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync */
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync {
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync rc = RTStrDupEx(&pszName, pszProperty);
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync if (RT_SUCCESS(rc))
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync rc = RTReqCallEx(mReqQueue, NULL, 0, RTREQFLAGS_NO_WAIT,
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync (PFNRT)Service::reqNotify, 7, mpfnHostCallback,
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync mpvHostData, pszName, NULL, 0, 0, NULL);
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync }
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync if (RT_FAILURE(rc)) /* clean up if we failed somewhere */
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync {
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync RTStrFree(pszName);
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync RTStrFree(pszValue);
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync RTStrFree(pszFlags);
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync }
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync}
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync/**
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync * Notify the service owner that a property has been added/deleted/changed.
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync * asynchronous part.
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync * @param pszProperty the name of the property which has changed
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync * @note this call allocates memory which the reqNotify request is expected to
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync * free again, using RTStrFree().
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync *
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync * @thread request thread
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync */
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsyncint Service::reqNotify(PFNHGCMSVCEXT pfnCallback, void *pvData,
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync char *pszName, char *pszValue, uint32_t u32TimeHigh,
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync uint32_t u32TimeLow, char *pszFlags)
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync{
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync HOSTCALLBACKDATA HostCallbackData;
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync HostCallbackData.u32Magic = HOSTCALLBACKMAGIC;
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync HostCallbackData.pcszName = pszName;
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync HostCallbackData.pcszValue = pszValue;
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync HostCallbackData.u64Timestamp = RT_MAKE_U64(u32TimeLow, u32TimeHigh);
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync HostCallbackData.pcszFlags = pszFlags;
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync AssertRC(pfnCallback(pvData, 0, reinterpret_cast<void *>(&HostCallbackData),
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync sizeof(HostCallbackData)));
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync RTStrFree(pszName);
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync RTStrFree(pszValue);
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync RTStrFree(pszFlags);
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync return VINF_SUCCESS;
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync}
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync/**
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync * Handle an HGCM service call.
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync * @copydoc VBOXHGCMSVCFNTABLE::pfnCall
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync * @note All functions which do not involve an unreasonable delay will be
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync * handled synchronously. If needed, we will add a request handler
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync * thread in future for those which do.
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync *
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync * @thread HGCM
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync */
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsyncvoid Service::call (VBOXHGCMCALLHANDLE callHandle, uint32_t u32ClientID,
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync void * /* pvClient */, uint32_t eFunction, uint32_t cParms,
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync VBOXHGCMSVCPARM paParms[])
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync{
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync int rc = VINF_SUCCESS;
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync bool fCallSync = true;
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync LogFlowFunc(("u32ClientID = %d, fn = %d, cParms = %d, pparms = %d\n",
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync u32ClientID, eFunction, cParms, paParms));
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync switch (eFunction)
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync {
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync /* The guest wishes to read a property */
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync case GET_PROP:
0c94df02222ed175411e5363dd39658f2fb1df41vboxsync LogFlowFunc(("GET_PROP\n"));
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync rc = getProperty(cParms, paParms);
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync break;
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync /* The guest wishes to set a property */
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync case SET_PROP:
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync LogFlowFunc(("SET_PROP\n"));
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync rc = setProperty(cParms, paParms, true);
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync break;
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync /* The guest wishes to set a property value */
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync case SET_PROP_VALUE:
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync LogFlowFunc(("SET_PROP_VALUE\n"));
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync rc = setProperty(cParms, paParms, true);
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync break;
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync /* The guest wishes to remove a configuration value */
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync case DEL_PROP:
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync LogFlowFunc(("DEL_PROP\n"));
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync rc = delProperty(cParms, paParms, true);
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync break;
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync /* The guest wishes to enumerate all properties */
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync case ENUM_PROPS:
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync LogFlowFunc(("ENUM_PROPS\n"));
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync rc = enumProps(cParms, paParms);
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync break;
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync default:
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync rc = VERR_NOT_IMPLEMENTED;
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync }
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync if (fCallSync)
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync {
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync LogFlowFunc(("rc = %Rrc\n", rc));
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync mpHelpers->pfnCallComplete (callHandle, rc);
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync }
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync}
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync/**
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync * Service call handler for the host.
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync * @copydoc VBOXHGCMSVCFNTABLE::pfnHostCall
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync * @thread hgcm
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync */
6728a36898fd2be125a28e84d2115d19aa4923edvboxsyncint Service::hostCall (uint32_t eFunction, uint32_t cParms, VBOXHGCMSVCPARM paParms[])
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync{
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync int rc = VINF_SUCCESS;
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync LogFlowFunc(("fn = %d, cParms = %d, pparms = %d\n",
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync eFunction, cParms, paParms));
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync switch (eFunction)
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync {
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync /* Set the root CFGM node used. This should be called when instantiating
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync * the service. */
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync /* This whole case is due to go away, so I will not clean it up. */
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync case SET_CFGM_NODE:
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync {
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync LogFlowFunc(("SET_CFGM_NODE\n"));
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync if ( (cParms != 3)
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync || (paParms[0].type != VBOX_HGCM_SVC_PARM_PTR) /* pValue */
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync || (paParms[1].type != VBOX_HGCM_SVC_PARM_PTR) /* pTimestamp */
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync || (paParms[2].type != VBOX_HGCM_SVC_PARM_PTR) /* pFlags */
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync )
0c94df02222ed175411e5363dd39658f2fb1df41vboxsync rc = VERR_INVALID_PARAMETER;
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync else
0c94df02222ed175411e5363dd39658f2fb1df41vboxsync {
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync PCFGMNODE pValue = NULL, pTimestamp = NULL, pFlags = NULL;
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync uint32_t cbDummy;
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync rc = VBoxHGCMParmPtrGet (&paParms[0], (void **) &pValue, &cbDummy);
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync if (RT_SUCCESS(rc))
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync rc = VBoxHGCMParmPtrGet (&paParms[1], (void **) &pTimestamp, &cbDummy);
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync if (RT_SUCCESS(rc))
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync rc = VBoxHGCMParmPtrGet (&paParms[2], (void **) &pFlags, &cbDummy);
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync if (RT_SUCCESS(rc))
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync {
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync mpValueNode = pValue;
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync mpTimestampNode = pTimestamp;
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync mpFlagsNode = pFlags;
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync }
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync }
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync } break;
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync /* The host wishes to read a configuration value */
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync case GET_PROP_HOST:
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync LogFlowFunc(("GET_PROP_HOST\n"));
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync rc = getProperty(cParms, paParms);
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync break;
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync /* The host wishes to set a configuration value */
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync case SET_PROP_HOST:
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync LogFlowFunc(("SET_PROP_HOST\n"));
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync rc = setProperty(cParms, paParms, false);
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync break;
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync /* The host wishes to set a configuration value */
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync case SET_PROP_VALUE_HOST:
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync LogFlowFunc(("SET_PROP_VALUE_HOST\n"));
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync rc = setProperty(cParms, paParms, false);
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync break;
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync /* The host wishes to remove a configuration value */
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync case DEL_PROP_HOST:
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync LogFlowFunc(("DEL_PROP_HOST\n"));
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync rc = delProperty(cParms, paParms, false);
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync break;
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync /* The host wishes to enumerate all properties */
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync case ENUM_PROPS_HOST:
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync LogFlowFunc(("ENUM_PROPS\n"));
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync rc = enumProps(cParms, paParms);
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync break;
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync default:
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync rc = VERR_NOT_SUPPORTED;
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync break;
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync }
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync LogFlowFunc(("rc = %Vrc\n", rc));
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync return rc;
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync}
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsyncint Service::uninit()
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync{
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync int rc;
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync unsigned count = 0;
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync mfExitThread = true;
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync rc = RTReqCallEx(mReqQueue, NULL, 0, RTREQFLAGS_NO_WAIT, (PFNRT)reqVoid, 0);
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync if (RT_SUCCESS(rc))
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync do
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync {
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync rc = RTThreadWait(mReqThread, 1000, NULL);
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync ++count;
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync Assert(RT_SUCCESS(rc) || ((VERR_TIMEOUT == rc) && (count != 5)));
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync } while ((VERR_TIMEOUT == rc) && (count < 300));
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync if (RT_SUCCESS(rc))
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync RTReqDestroyQueue(mReqQueue);
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync return rc;
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync}
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync} /* namespace guestProp */
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsyncusing guestProp::Service;
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync/**
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync * @copydoc VBOXHGCMSVCLOAD
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync */
6728a36898fd2be125a28e84d2115d19aa4923edvboxsyncextern "C" DECLCALLBACK(DECLEXPORT(int)) VBoxHGCMSvcLoad (VBOXHGCMSVCFNTABLE *ptable)
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync{
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync int rc = VINF_SUCCESS;
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync LogFlowFunc(("ptable = %p\n", ptable));
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync if (!VALID_PTR(ptable))
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync {
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync rc = VERR_INVALID_PARAMETER;
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync }
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync else
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync {
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync LogFlowFunc(("ptable->cbSize = %d, ptable->u32Version = 0x%08X\n", ptable->cbSize, ptable->u32Version));
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync if ( ptable->cbSize != sizeof (VBOXHGCMSVCFNTABLE)
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync || ptable->u32Version != VBOX_HGCM_SVC_VERSION)
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync {
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync rc = VERR_VERSION_MISMATCH;
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync }
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync else
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync {
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync std::auto_ptr<Service> apService;
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync /* No exceptions may propogate outside. */
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync try {
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync apService = std::auto_ptr<Service>(new Service(ptable->pHelpers));
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync } catch (int rcThrown) {
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync rc = rcThrown;
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync } catch (...) {
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync rc = VERR_UNRESOLVED_ERROR;
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync }
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync if (RT_SUCCESS(rc))
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync {
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync /* We do not maintain connections, so no client data is needed. */
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync ptable->cbClient = 0;
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync
0e52499a0d557fe66f1bea625fe78d8d15e6238bvboxsync ptable->pfnUnload = Service::svcUnload;
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync ptable->pfnConnect = Service::svcConnectDisconnect;
6728a36898fd2be125a28e84d2115d19aa4923edvboxsync ptable->pfnDisconnect = Service::svcConnectDisconnect;
ac153c99053f1edf42b00bf3a13475923bc4fcf1vboxsync ptable->pfnCall = Service::svcCall;
ac153c99053f1edf42b00bf3a13475923bc4fcf1vboxsync ptable->pfnHostCall = Service::svcHostCall;
ac153c99053f1edf42b00bf3a13475923bc4fcf1vboxsync ptable->pfnSaveState = NULL; /* The service is stateless by definition, so the */
ac153c99053f1edf42b00bf3a13475923bc4fcf1vboxsync ptable->pfnLoadState = NULL; /* normal construction done before restoring suffices */
ac153c99053f1edf42b00bf3a13475923bc4fcf1vboxsync ptable->pfnRegisterExtension = Service::svcRegisterExtension;
ac153c99053f1edf42b00bf3a13475923bc4fcf1vboxsync
ac153c99053f1edf42b00bf3a13475923bc4fcf1vboxsync /* Service specific initialization. */
ac153c99053f1edf42b00bf3a13475923bc4fcf1vboxsync ptable->pvService = apService.release();
ac153c99053f1edf42b00bf3a13475923bc4fcf1vboxsync }
ac153c99053f1edf42b00bf3a13475923bc4fcf1vboxsync }
ac153c99053f1edf42b00bf3a13475923bc4fcf1vboxsync }
ac153c99053f1edf42b00bf3a13475923bc4fcf1vboxsync
ac153c99053f1edf42b00bf3a13475923bc4fcf1vboxsync LogFlowFunc(("returning %Rrc\n", rc));
ac153c99053f1edf42b00bf3a13475923bc4fcf1vboxsync return rc;
ac153c99053f1edf42b00bf3a13475923bc4fcf1vboxsync}
ac153c99053f1edf42b00bf3a13475923bc4fcf1vboxsync