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