553 lines
20 KiB
C
553 lines
20 KiB
C
/** @file
|
|
* Guest property service - Common header for host service and guest clients.
|
|
*/
|
|
|
|
/*
|
|
* Copyright (C) 2006-2023 Oracle and/or its affiliates.
|
|
*
|
|
* This file is part of VirtualBox base platform packages, as
|
|
* available from https://www.virtualbox.org.
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License
|
|
* as published by the Free Software Foundation, in version 3 of the
|
|
* License.
|
|
*
|
|
* This program is distributed in the hope that it will be useful, but
|
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, see <https://www.gnu.org/licenses>.
|
|
*
|
|
* The contents of this file may alternatively be used under the terms
|
|
* of the Common Development and Distribution License Version 1.0
|
|
* (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
|
|
* in the VirtualBox distribution, in which case the provisions of the
|
|
* CDDL are applicable instead of those of the GPL.
|
|
*
|
|
* You may elect to license modified versions of this file under the
|
|
* terms and conditions of either the GPL or the CDDL or both.
|
|
*
|
|
* SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
|
|
*/
|
|
|
|
#ifndef VBOX_INCLUDED_HostServices_GuestPropertySvc_h
|
|
#define VBOX_INCLUDED_HostServices_GuestPropertySvc_h
|
|
#ifndef RT_WITHOUT_PRAGMA_ONCE
|
|
# pragma once
|
|
#endif
|
|
|
|
#include <VBox/VMMDevCoreTypes.h>
|
|
#include <VBox/VBoxGuestCoreTypes.h>
|
|
#include <VBox/log.h>
|
|
#include <iprt/err.h>
|
|
#include <iprt/assertcompile.h>
|
|
#include <iprt/string.h>
|
|
|
|
|
|
/** Maximum size for property names (including the terminator). */
|
|
#define GUEST_PROP_MAX_NAME_LEN 64
|
|
/** Maximum size for property values (including the terminator). */
|
|
#define GUEST_PROP_MAX_VALUE_LEN 1024
|
|
/** Maximum number of properties per guest. */
|
|
#define GUEST_PROP_MAX_PROPS 256
|
|
/** Maximum size for enumeration patterns (including the terminators). */
|
|
#define GUEST_PROP_MAX_PATTERN_LEN 1024
|
|
/** Maximum number of changes we remember for guest notifications. */
|
|
#define GUEST_PROP_MAX_GUEST_NOTIFICATIONS 256
|
|
/** Maximum number of current pending waits per client. */
|
|
#define GUEST_PROP_MAX_GUEST_CONCURRENT_WAITS 16
|
|
|
|
|
|
/** @name GUEST_PROP_F_XXX - The guest property flag values which are currently accepted.
|
|
* @{
|
|
*/
|
|
#define GUEST_PROP_F_NILFLAG UINT32_C(0)
|
|
/** Transient until VM gets shut down. */
|
|
#define GUEST_PROP_F_TRANSIENT RT_BIT_32(1)
|
|
#define GUEST_PROP_F_RDONLYGUEST RT_BIT_32(2)
|
|
#define GUEST_PROP_F_RDONLYHOST RT_BIT_32(3)
|
|
/** Transient until VM gets a reset / restarts.
|
|
* Implies TRANSIENT. */
|
|
#define GUEST_PROP_F_TRANSRESET RT_BIT_32(4)
|
|
#define GUEST_PROP_F_READONLY (GUEST_PROP_F_RDONLYGUEST | GUEST_PROP_F_RDONLYHOST)
|
|
#define GUEST_PROP_F_ALLFLAGS (GUEST_PROP_F_TRANSIENT | GUEST_PROP_F_READONLY | GUEST_PROP_F_TRANSRESET)
|
|
/** @} */
|
|
|
|
/**
|
|
* Check that a string fits our criteria for a property name.
|
|
*
|
|
* @returns IPRT status code
|
|
* @param pszName The string to check, must be valid Utf8
|
|
* @param cbName The number of bytes @a pszName points to, including the
|
|
* terminating character.
|
|
*/
|
|
DECLINLINE(int) GuestPropValidateName(const char *pszName, size_t cbName)
|
|
{
|
|
/* Property name is expected to be at least 1 charecter long plus terminating character. */
|
|
AssertReturn(cbName >= 2, VERR_INVALID_PARAMETER);
|
|
AssertReturn(cbName <= GUEST_PROP_MAX_NAME_LEN, VERR_INVALID_PARAMETER);
|
|
|
|
AssertPtrReturn(pszName, VERR_INVALID_POINTER);
|
|
|
|
AssertReturn(memchr(pszName, '*', cbName) == NULL, VERR_INVALID_PARAMETER);
|
|
AssertReturn(memchr(pszName, '?', cbName) == NULL, VERR_INVALID_PARAMETER);
|
|
AssertReturn(memchr(pszName, '|', cbName) == NULL, VERR_INVALID_PARAMETER);
|
|
|
|
return VINF_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
* Check a string fits our criteria for the value of a guest property.
|
|
*
|
|
* @returns IPRT status code
|
|
* @retval VINF_SUCCESS if guest property value corresponds to all criteria.
|
|
* @retval VERR_TOO_MUCH_DATA if guest property value size exceeds limits.
|
|
* @retval VERR_INVALID_PARAMETER if guest property does not correspond to all other criteria.
|
|
* @param pszValue The string to check, must be valid utf-8.
|
|
* @param cbValue The size of of @a pszValue in bytes, including the
|
|
* terminator.
|
|
* @thread HGCM
|
|
*/
|
|
DECLINLINE(int) GuestPropValidateValue(const char *pszValue, size_t cbValue)
|
|
{
|
|
AssertPtrReturn(pszValue, VERR_INVALID_POINTER);
|
|
|
|
/* Zero-length values are possible, however buffer should contain terminating character at least. */
|
|
AssertReturn(cbValue > 0, VERR_INVALID_PARAMETER);
|
|
AssertReturn(cbValue <= GUEST_PROP_MAX_VALUE_LEN, VERR_TOO_MUCH_DATA);
|
|
|
|
return VINF_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
* Get the name of a flag as a string.
|
|
* @returns the name, or NULL if fFlag is invalid.
|
|
* @param fFlag The flag, GUEST_PROP_F_XXX.
|
|
* @param pcchName Where to return the name length.
|
|
*/
|
|
DECLINLINE(const char *) GuestPropFlagNameAndLen(uint32_t fFlag, size_t *pcchName)
|
|
{
|
|
switch (fFlag)
|
|
{
|
|
case GUEST_PROP_F_TRANSIENT:
|
|
*pcchName = sizeof("TRANSIENT") - 1;
|
|
return "TRANSIENT";
|
|
case GUEST_PROP_F_RDONLYGUEST:
|
|
*pcchName = sizeof("RDONLYGUEST") - 1;
|
|
return "RDONLYGUEST";
|
|
case GUEST_PROP_F_RDONLYHOST:
|
|
*pcchName = sizeof("RDONLYHOST") - 1;
|
|
return "RDONLYHOST";
|
|
case GUEST_PROP_F_READONLY:
|
|
*pcchName = sizeof("READONLY") - 1;
|
|
return "READONLY";
|
|
case GUEST_PROP_F_TRANSRESET:
|
|
*pcchName = sizeof("TRANSRESET") - 1;
|
|
return "TRANSRESET";
|
|
default:
|
|
*pcchName = 0;
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Maximum length for the property flags field. We only ever return one of
|
|
* RDONLYGUEST, RDONLYHOST and RDONLY
|
|
*/
|
|
#define GUEST_PROP_MAX_FLAGS_LEN sizeof("TRANSIENT, RDONLYGUEST, TRANSRESET")
|
|
|
|
/**
|
|
* Parse a guest properties flags string for flag names and make sure that
|
|
* there is no junk text in the string.
|
|
*
|
|
* @returns IPRT status code
|
|
* @retval VERR_INVALID_PARAMETER if the flag string is not valid
|
|
* @param pcszFlags the flag string to parse
|
|
* @param pfFlags where to store the parse result. May not be NULL.
|
|
* @note This function is also inline because it must be accessible from
|
|
* several modules and it does not seem reasonable to put it into
|
|
* its own library.
|
|
*/
|
|
DECLINLINE(int) GuestPropValidateFlags(const char *pcszFlags, uint32_t *pfFlags)
|
|
{
|
|
static const uint32_t s_aFlagList[] =
|
|
{
|
|
GUEST_PROP_F_TRANSIENT, GUEST_PROP_F_READONLY, GUEST_PROP_F_RDONLYGUEST, GUEST_PROP_F_RDONLYHOST, GUEST_PROP_F_TRANSRESET
|
|
};
|
|
const char *pcszNext = pcszFlags;
|
|
int rc = VINF_SUCCESS;
|
|
uint32_t fFlags = 0;
|
|
AssertLogRelReturn(RT_VALID_PTR(pfFlags), VERR_INVALID_POINTER);
|
|
|
|
if (pcszFlags)
|
|
{
|
|
while (*pcszNext == ' ')
|
|
++pcszNext;
|
|
while ((*pcszNext != '\0') && RT_SUCCESS(rc))
|
|
{
|
|
unsigned i;
|
|
rc = VERR_PARSE_ERROR;
|
|
for (i = 0; i < RT_ELEMENTS(s_aFlagList); ++i)
|
|
{
|
|
size_t cchFlagName;
|
|
const char *pszFlagName = GuestPropFlagNameAndLen(s_aFlagList[i], &cchFlagName);
|
|
if (RTStrNICmpAscii(pcszNext, pszFlagName, cchFlagName) == 0)
|
|
{
|
|
char ch;
|
|
fFlags |= s_aFlagList[i];
|
|
pcszNext += cchFlagName;
|
|
while ((ch = *pcszNext) == ' ')
|
|
++pcszNext;
|
|
rc = VINF_SUCCESS;
|
|
if (ch == ',')
|
|
{
|
|
++pcszNext;
|
|
while (*pcszNext == ' ')
|
|
++pcszNext;
|
|
}
|
|
else if (ch != '\0')
|
|
rc = VERR_PARSE_ERROR;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (RT_SUCCESS(rc))
|
|
*pfFlags = fFlags;
|
|
return rc;
|
|
}
|
|
|
|
|
|
/**
|
|
* Write out flags to a string.
|
|
* @returns IPRT status code
|
|
* @param fFlags the flags to write out
|
|
* @param pszFlags where to write the flags string. This must point to
|
|
* a buffer of size (at least) GUEST_PROP_MAX_FLAGS_LEN.
|
|
*/
|
|
DECLINLINE(int) GuestPropWriteFlags(uint32_t fFlags, char *pszFlags)
|
|
{
|
|
/* Putting READONLY before the other RDONLY flags keeps the result short. */
|
|
static const uint32_t s_aFlagList[] =
|
|
{
|
|
GUEST_PROP_F_TRANSIENT, GUEST_PROP_F_READONLY, GUEST_PROP_F_RDONLYGUEST, GUEST_PROP_F_RDONLYHOST, GUEST_PROP_F_TRANSRESET
|
|
};
|
|
int rc = VINF_SUCCESS;
|
|
|
|
AssertLogRelReturn(RT_VALID_PTR(pszFlags), VERR_INVALID_POINTER);
|
|
if ((fFlags & ~GUEST_PROP_F_ALLFLAGS) == GUEST_PROP_F_NILFLAG)
|
|
{
|
|
char *pszNext;
|
|
unsigned i;
|
|
|
|
/* TRANSRESET implies TRANSIENT. For compatability with old clients we
|
|
always set TRANSIENT when TRANSRESET appears. */
|
|
if (fFlags & GUEST_PROP_F_TRANSRESET)
|
|
fFlags |= GUEST_PROP_F_TRANSIENT;
|
|
|
|
pszNext = pszFlags;
|
|
for (i = 0; i < RT_ELEMENTS(s_aFlagList); ++i)
|
|
{
|
|
if (s_aFlagList[i] == (fFlags & s_aFlagList[i]))
|
|
{
|
|
size_t cchFlagName;
|
|
const char *pszFlagName = GuestPropFlagNameAndLen(s_aFlagList[i], &cchFlagName);
|
|
memcpy(pszNext, pszFlagName, cchFlagName);
|
|
pszNext += cchFlagName;
|
|
fFlags &= ~s_aFlagList[i];
|
|
if (fFlags != GUEST_PROP_F_NILFLAG)
|
|
{
|
|
*pszNext++ = ',';
|
|
*pszNext++ = ' ';
|
|
}
|
|
}
|
|
}
|
|
*pszNext = '\0';
|
|
|
|
Assert((uintptr_t)(pszNext - pszFlags) < GUEST_PROP_MAX_FLAGS_LEN);
|
|
Assert(fFlags == GUEST_PROP_F_NILFLAG); /* bad s_aFlagList */
|
|
}
|
|
else
|
|
rc = VERR_INVALID_PARAMETER;
|
|
return rc;
|
|
}
|
|
|
|
|
|
/** @name The service functions which are callable by host.
|
|
* @{
|
|
*/
|
|
/** Set properties in a block.
|
|
* The parameters are pointers to NULL-terminated arrays containing the
|
|
* parameters. These are, in order, name, value, timestamp, flags. Strings are
|
|
* stored as pointers to mutable utf8 data. All parameters must be supplied. */
|
|
#define GUEST_PROP_FN_HOST_SET_PROPS 1
|
|
/** Get the value attached to a guest property.
|
|
* The parameter format matches that of GET_PROP. */
|
|
#define GUEST_PROP_FN_HOST_GET_PROP 2
|
|
/** Set the value attached to a guest property.
|
|
* The parameter format matches that of SET_PROP. */
|
|
#define GUEST_PROP_FN_HOST_SET_PROP 3
|
|
/** Set the value attached to a guest property.
|
|
* The parameter format matches that of SET_PROP_VALUE. */
|
|
#define GUEST_PROP_FN_HOST_SET_PROP_VALUE 4
|
|
/** Remove a guest property.
|
|
* The parameter format matches that of DEL_PROP. */
|
|
#define GUEST_PROP_FN_HOST_DEL_PROP 5
|
|
/** Enumerate guest properties.
|
|
* The parameter format matches that of ENUM_PROPS. */
|
|
#define GUEST_PROP_FN_HOST_ENUM_PROPS 6
|
|
/** Set global flags for the service.
|
|
* Currently RDONLYGUEST is supported. Takes one 32-bit unsigned integer
|
|
* parameter for the flags. */
|
|
#define GUEST_PROP_FN_HOST_SET_GLOBAL_FLAGS 7
|
|
/** @} */
|
|
|
|
|
|
/** @name The service functions which are called by guest.
|
|
*
|
|
* @note The numbers may not change!
|
|
* @{
|
|
*/
|
|
/** Get a guest property */
|
|
#define GUEST_PROP_FN_GET_PROP 1
|
|
/** Set a guest property */
|
|
#define GUEST_PROP_FN_SET_PROP 2
|
|
/** Set just the value of a guest property */
|
|
#define GUEST_PROP_FN_SET_PROP_VALUE 3
|
|
/** Delete a guest property */
|
|
#define GUEST_PROP_FN_DEL_PROP 4
|
|
/** Enumerate guest properties */
|
|
#define GUEST_PROP_FN_ENUM_PROPS 5
|
|
/** Poll for guest notifications */
|
|
#define GUEST_PROP_FN_GET_NOTIFICATION 6
|
|
/** @} */
|
|
|
|
|
|
/**
|
|
* Data structure to pass to the service extension callback.
|
|
* We use this to notify the host of changes to properties.
|
|
*/
|
|
typedef struct GUESTPROPHOSTCALLBACKDATA
|
|
{
|
|
/** Magic number to identify the structure (GUESTPROPHOSTCALLBACKDATA_MAGIC). */
|
|
uint32_t u32Magic;
|
|
/** The name of the property that was changed */
|
|
const char *pcszName;
|
|
/** The new property value, or NULL if the property was deleted */
|
|
const char *pcszValue;
|
|
/** The timestamp of the modification */
|
|
uint64_t u64Timestamp;
|
|
/** The flags field of the modified property */
|
|
const char *pcszFlags;
|
|
} GUESTPROPHOSTCALLBACKDATA;
|
|
/** Poitner to a data structure to pass to the service extension callback. */
|
|
typedef GUESTPROPHOSTCALLBACKDATA *PGUESTPROPHOSTCALLBACKDATA;
|
|
|
|
/** Magic number for sanity checking the HOSTCALLBACKDATA structure */
|
|
#define GUESTPROPHOSTCALLBACKDATA_MAGIC UINT32_C(0x69c87a78)
|
|
|
|
/**
|
|
* HGCM parameter structures. Packing is explicitly defined as this is a wire format.
|
|
*/
|
|
/** The guest is requesting the value of a property */
|
|
typedef struct GuestPropMsgGetProperty
|
|
{
|
|
VBGLIOCHGCMCALL hdr;
|
|
|
|
/**
|
|
* The property name (IN pointer)
|
|
* This must fit to a number of criteria, namely
|
|
* - Only Utf8 strings are allowed
|
|
* - Less than or equal to MAX_NAME_LEN bytes in length
|
|
* - Zero terminated
|
|
*/
|
|
HGCMFunctionParameter name;
|
|
|
|
/**
|
|
* The returned string data will be placed here. (OUT pointer)
|
|
* This call returns two null-terminated strings which will be placed one
|
|
* after another: value and flags.
|
|
*/
|
|
HGCMFunctionParameter buffer;
|
|
|
|
/**
|
|
* The property timestamp. (OUT uint64_t)
|
|
*/
|
|
HGCMFunctionParameter timestamp;
|
|
|
|
/**
|
|
* If the buffer provided was large enough this will contain the size of
|
|
* the returned data. Otherwise it will contain the size of the buffer
|
|
* needed to hold the data and VERR_BUFFER_OVERFLOW will be returned.
|
|
* (OUT uint32_t)
|
|
*/
|
|
HGCMFunctionParameter size;
|
|
} GuestPropMsgGetProperty;
|
|
AssertCompileSize(GuestPropMsgGetProperty, 40 + 4 * (ARCH_BITS == 64 ? 16 : 12));
|
|
|
|
/** The guest is requesting to change a property */
|
|
typedef struct GuestPropMsgSetProperty
|
|
{
|
|
VBGLIOCHGCMCALL hdr;
|
|
|
|
/**
|
|
* The property name. (IN pointer)
|
|
* This must fit to a number of criteria, namely
|
|
* - Only Utf8 strings are allowed
|
|
* - Less than or equal to MAX_NAME_LEN bytes in length
|
|
* - Zero terminated
|
|
*/
|
|
HGCMFunctionParameter name;
|
|
|
|
/**
|
|
* The value of the property (IN pointer)
|
|
* Criteria as for the name parameter, but with length less than or equal to
|
|
* MAX_VALUE_LEN.
|
|
*/
|
|
HGCMFunctionParameter value;
|
|
|
|
/**
|
|
* The property flags (IN pointer)
|
|
* This is a comma-separated list of the format flag=value
|
|
* The length must be less than or equal to GUEST_PROP_MAX_FLAGS_LEN and only
|
|
* known flag names and values will be accepted.
|
|
*/
|
|
HGCMFunctionParameter flags;
|
|
} GuestPropMsgSetProperty;
|
|
AssertCompileSize(GuestPropMsgSetProperty, 40 + 3 * (ARCH_BITS == 64 ? 16 : 12));
|
|
|
|
/** The guest is requesting to change the value of a property */
|
|
typedef struct GuestPropMsgSetPropertyValue
|
|
{
|
|
VBGLIOCHGCMCALL hdr;
|
|
|
|
/**
|
|
* The property name. (IN pointer)
|
|
* This must fit to a number of criteria, namely
|
|
* - Only Utf8 strings are allowed
|
|
* - Less than or equal to MAX_NAME_LEN bytes in length
|
|
* - Zero terminated
|
|
*/
|
|
HGCMFunctionParameter name;
|
|
|
|
/**
|
|
* The value of the property (IN pointer)
|
|
* Criteria as for the name parameter, but with length less than or equal to
|
|
* MAX_VALUE_LEN.
|
|
*/
|
|
HGCMFunctionParameter value;
|
|
} GuestPropMsgSetPropertyValue;
|
|
AssertCompileSize(GuestPropMsgSetPropertyValue, 40 + 2 * (ARCH_BITS == 64 ? 16 : 12));
|
|
|
|
/** The guest is requesting to remove a property */
|
|
typedef struct GuestPropMsgDelProperty
|
|
{
|
|
VBGLIOCHGCMCALL hdr;
|
|
|
|
/**
|
|
* The property name. This must fit to a number of criteria, namely
|
|
* - Only Utf8 strings are allowed
|
|
* - Less than or equal to MAX_NAME_LEN bytes in length
|
|
* - Zero terminated
|
|
*/
|
|
HGCMFunctionParameter name;
|
|
} GuestPropMsgDelProperty;
|
|
AssertCompileSize(GuestPropMsgDelProperty, 40 + 1 * (ARCH_BITS == 64 ? 16 : 12));
|
|
|
|
/** The guest is requesting to enumerate properties */
|
|
typedef struct GuestPropMsgEnumProperties
|
|
{
|
|
VBGLIOCHGCMCALL hdr;
|
|
|
|
/**
|
|
* Array of patterns to match the properties against, separated by '|'
|
|
* characters. For backwards compatibility, '\\0' is also accepted
|
|
* as a separater.
|
|
* (IN pointer)
|
|
* If only a single, empty pattern is given then match all.
|
|
*/
|
|
HGCMFunctionParameter patterns;
|
|
/**
|
|
* On success, null-separated array of strings in which the properties are
|
|
* returned. (OUT pointer)
|
|
* The number of strings in the array is always a multiple of four,
|
|
* and in sequences of name, value, timestamp (hexadecimal string) and the
|
|
* flags as a comma-separated list in the format "name=value". The list
|
|
* is terminated by an empty string after a "flags" entry (or at the
|
|
* start).
|
|
*/
|
|
HGCMFunctionParameter strings;
|
|
/**
|
|
* On success, the size of the returned data. If the buffer provided is
|
|
* too small, the size of buffer needed. (OUT uint32_t)
|
|
*/
|
|
HGCMFunctionParameter size;
|
|
} GuestPropMsgEnumProperties;
|
|
AssertCompileSize(GuestPropMsgEnumProperties, 40 + 3 * (ARCH_BITS == 64 ? 16 : 12));
|
|
|
|
/**
|
|
* The guest is polling for notifications on changes to properties, specifying
|
|
* a set of patterns to match the names of changed properties against and
|
|
* optionally the timestamp of the last notification seen.
|
|
* On success, VINF_SUCCESS will be returned and the buffer will contain
|
|
* details of a property notification. If no new notification is available
|
|
* which matches one of the specified patterns, the call will block until one
|
|
* is.
|
|
* If the last notification could not be found by timestamp, VWRN_NOT_FOUND
|
|
* will be returned and the oldest available notification will be returned.
|
|
* If a zero timestamp is specified, the call will always wait for a new
|
|
* notification to arrive.
|
|
* If the buffer supplied was not large enough to hold the notification,
|
|
* VERR_BUFFER_OVERFLOW will be returned and the size parameter will contain
|
|
* the size of the buffer needed.
|
|
*
|
|
* The protocol for a guest to obtain notifications is to call
|
|
* GET_NOTIFICATION in a loop. On the first call, the ingoing timestamp
|
|
* parameter should be set to zero. On subsequent calls, it should be set to
|
|
* the outgoing timestamp from the previous call.
|
|
*/
|
|
typedef struct GuestPropMsgGetNotification
|
|
{
|
|
VBGLIOCHGCMCALL hdr;
|
|
|
|
/**
|
|
* A list of patterns to match the guest event name against, separated by
|
|
* vertical bars (|) (IN pointer)
|
|
* An empty string means match all.
|
|
*/
|
|
HGCMFunctionParameter patterns;
|
|
/**
|
|
* The timestamp of the last change seen (IN uint64_t)
|
|
* This may be zero, in which case the oldest available change will be
|
|
* sent. If the service does not remember an event matching the
|
|
* timestamp, then VWRN_NOT_FOUND will be returned, and the guest should
|
|
* assume that it has missed a certain number of notifications.
|
|
*
|
|
* The timestamp of the change being notified of (OUT uint64_t)
|
|
* Undefined on failure.
|
|
*/
|
|
HGCMFunctionParameter timestamp;
|
|
|
|
/**
|
|
* The returned data, if any, will be placed here. (OUT pointer)
|
|
* This call returns three null-terminated strings which will be placed
|
|
* one after another: name, value and flags. For a delete notification,
|
|
* value and flags will be empty strings. Undefined on failure.
|
|
*/
|
|
HGCMFunctionParameter buffer;
|
|
|
|
/**
|
|
* On success, the size of the returned data. (OUT uint32_t)
|
|
* On buffer overflow, the size of the buffer needed to hold the data.
|
|
* Undefined on failure.
|
|
*/
|
|
HGCMFunctionParameter size;
|
|
} GuestPropMsgGetNotification;
|
|
AssertCompileSize(GuestPropMsgGetNotification, 40 + 4 * (ARCH_BITS == 64 ? 16 : 12));
|
|
|
|
|
|
#endif /* !VBOX_INCLUDED_HostServices_GuestPropertySvc_h */
|
|
|