GuestPropertySvc.h

/** @file * Guest property service: * Common header for host service and guest clients. *//* * Copyright (C) 2006-2007 Sun Microsystems, Inc. * * This file is part of VirtualBox Open Source Edition (OSE), as * available from http://www.virtualbox.org. This file is free software; * you can redistribute it and/or modify it under the terms of the GNU * General Public License (GPL) as published by the Free Software * Foundation, in version 2 as it comes in the "COPYING" file of the * VirtualBox OSE distribution. VirtualBox OSE is distributed in the * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. * * The contents of this file may alternatively be used under the terms * of the Common Development and Distribution License Version 1.0 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the * VirtualBox OSE 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. * * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa * Clara, CA 95054 USA or visit http://www.sun.com if you need * additional information or have any questions. */#ifndef ___VBox_HostService_GuestPropertyService_h#define ___VBox_HostService_GuestPropertyService_h#include <VBox/types.h>#include <VBox/VBoxGuest.h>#include <VBox/hgcmsvc.h>#include <VBox/log.h>#include <iprt/assert.h>#include <iprt/string.h>/** Everything defined in this file lives in this namespace. */00042namespace guestProp {
/******************************************************************************* Typedefs, constants and inlines *******************************************************************************//** Maximum length for property names */enum { MAX_NAME_LEN = 64 };/** Maximum length for property values */enum { MAX_VALUE_LEN = 128 };/** Maximum number of properties per guest */enum { MAX_PROPS = 256 };/** Maximum size for enumeration patterns */enum { MAX_PATTERN_LEN = 1024 };/** Maximum number of changes we remember for guest notifications */enum { MAX_GUEST_NOTIFICATIONS = 256 };
/** * The guest property flag values which are currently accepted. */00062enumePropFlags
{
NILFLAG = 0,
TRANSIENT = RT_BIT(1),
RDONLYGUEST = RT_BIT(2),
RDONLYHOST = RT_BIT(3),
READONLY = RDONLYGUEST | RDONLYHOST,
ALLFLAGS = TRANSIENT | READONLY
};
/** * Get the name of a flag as a string. * @returns the name, or NULL if fFlag is invalid. * @param fFlag the flag. Must be a value from the ePropFlags enumeration * list. */00078DECLINLINE(constchar *) flagName(uint32_t fFlag)
{
switch(fFlag)
{
case TRANSIENT:
return"TRANSIENT";
case RDONLYGUEST:
return"RDONLYGUEST";
case RDONLYHOST:
return"RDONLYHOST";
case READONLY:
return"READONLY";
default:
returnNULL;
}
}
/** * Get the length of a flag name as returned by flagName. * @returns the length, or 0 if fFlag is invalid. * @param fFlag the flag. Must be a value from the ePropFlags enumeration * list. */00101DECLINLINE(size_t) flagNameLen(uint32_t fFlag)
{
constchar *pcszName = flagName(fFlag);
returnRT_LIKELY(pcszName != NULL) ? strlen(pcszName) : 0;
}
/** * Maximum length for the property flags field. We only ever return one of * RDONLYGUEST, RDONLYHOST and RDONLY */enum { MAX_FLAGS_LEN = sizeof("TRANSIENT, RDONLYGUEST") };
/** * 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 * @returns VERR_INVALID_PARAM 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) validateFlags(const char *pcszFlags, uint32_t *pfFlags)
{
conststatic uint32_t sFlagList[] =
{
TRANSIENT, READONLY, RDONLYGUEST, RDONLYHOST
};
constchar *pcszNext = pcszFlags;
int rc = VINF_SUCCESS;
uint32_t fFlags = 0;
AssertLogRelReturn(VALID_PTR(pfFlags), VERR_INVALID_POINTER);
AssertLogRelReturn(VALID_PTR(pcszFlags), VERR_INVALID_POINTER);
while (' ' == *pcszNext)
++pcszNext;
while ((*pcszNext != '\0') && RT_SUCCESS(rc))
{
unsigned i = 0;
for (; i < RT_ELEMENTS(sFlagList); ++i)
if (RTStrNICmp(pcszNext, flagName(sFlagList[i]),
flagNameLen(sFlagList[i])
) == 0
)
break;
if (RT_ELEMENTS(sFlagList) == i)
rc = VERR_PARSE_ERROR;
else
{
fFlags |= sFlagList[i];
pcszNext += flagNameLen(sFlagList[i]);
while (' ' == *pcszNext)
++pcszNext;
if (',' == *pcszNext)
++pcszNext;
elseif (*pcszNext != '\0')
rc = VERR_PARSE_ERROR;
while (' ' == *pcszNext)
++pcszNext;
}
}
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) MAX_FLAGS_LEN. */DECLINLINE(int) writeFlags(uint32_t fFlags, char *pszFlags)
{
conststatic uint32_t sFlagList[] =
{
TRANSIENT, READONLY, RDONLYGUEST, RDONLYHOST
};
char *pszNext = pszFlags;
int rc = VINF_SUCCESS;
AssertLogRelReturn(VALID_PTR(pszFlags), VERR_INVALID_POINTER);
if ((fFlags & ~ALLFLAGS) != NILFLAG)
rc = VERR_INVALID_PARAMETER;
if (RT_SUCCESS(rc))
{
unsigned i = 0;
for (; i < RT_ELEMENTS(sFlagList); ++i)
{
if (sFlagList[i] == (fFlags & sFlagList[i]))
{
strcpy(pszNext, flagName(sFlagList[i]));
pszNext += flagNameLen(sFlagList[i]);
fFlags &= ~sFlagList[i];
if (fFlags != NILFLAG)
{
strcpy(pszNext, ", ");
pszNext += 2;
}
}
}
*pszNext = '\0';
if (fFlags != NILFLAG)
rc = VERR_INVALID_PARAMETER; /* But pszFlags will still be set right. */
}
return rc;
}
/** * The service functions which are callable by host. */enum eHostFn
{ /** * Set properties in a block. The parameters are pointers to * NULL-terminated arrays containing the paramters. These are, in order, * name, value, timestamp, flags. Strings are stored as pointers to * mutable utf8 data. All parameters must be supplied. */
SET_PROPS_HOST = 1, /** * Get the value attached to a guest property * The parameter format matches that of GET_PROP. */
GET_PROP_HOST = 2, /** * Set the value attached to a guest property * The parameter format matches that of SET_PROP. */
SET_PROP_HOST = 3, /** * Set the value attached to a guest property * The parameter format matches that of SET_PROP_VALUE. */
SET_PROP_VALUE_HOST = 4, /** * Remove a guest property. * The parameter format matches that of DEL_PROP. */
DEL_PROP_HOST = 5, /** * Enumerate guest properties. * The parameter format matches that of ENUM_PROPS. */
ENUM_PROPS_HOST = 6
};
/** * The service functions which are called by guest. The numbers may not change, * so we hardcode them. */00252enumeGuestFn
{ /** Get a guest property */00255GET_PROP = 1, /** Set a guest property */00257SET_PROP = 2, /** Set just the value of a guest property */00259SET_PROP_VALUE = 3, /** Delete a guest property */00261DEL_PROP = 4, /** Enumerate guest properties */00263ENUM_PROPS = 5, /** Poll for guest notifications */00265GET_NOTIFICATION = 6
};
/** * Data structure to pass to the service extension callback. We use this to * notify the host of changes to properties. */00272typedefstruct _HOSTCALLBACKDATA
{ /** Magic number to identify the structure */00275 uint32_t u32Magic; /** The name of the property that was changed */00277constchar *pcszName; /** The new property value, or NULL if the property was deleted */00279constchar *pcszValue; /** The timestamp of the modification */00281 uint64_t u64Timestamp; /** The flags field of the modified property */00283constchar *pcszFlags;
} HOSTCALLBACKDATA, *PHOSTCALLBACKDATA;
enum
{ /** Magic number for sanity checking the HOSTCALLBACKDATA structure */00289HOSTCALLBACKMAGIC = 0x69c87a78
};
/** * HGCM parameter structures. Packing is explicitly defined as this is a wire format. */#pragma pack (1)/** The guest is requesting the value of a property */00297typedefstruct _GetProperty
{
VBoxGuestHGCMCallInfo 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 */00308 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. */00315 HGCMFunctionParameter buffer;
/** * The property timestamp. (OUT uint64_t) */00320 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) */00328 HGCMFunctionParameter size;
} GetProperty;
/** The guest is requesting to change a property */00332typedefstruct _SetProperty
{
VBoxGuestHGCMCallInfo 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 */00343 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. */00350 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 MAX_FLAGS_LEN and only * known flag names and values will be accepted. */00358 HGCMFunctionParameter flags;
} SetProperty;
/** The guest is requesting to change the value of a property */00362typedefstruct _SetPropertyValue
{
VBoxGuestHGCMCallInfo 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 */00373 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. */00380 HGCMFunctionParameter value;
} SetPropertyValue;
/** The guest is requesting to remove a property */00384typedefstruct _DelProperty
{
VBoxGuestHGCMCallInfo 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 */00394 HGCMFunctionParameter name;
} DelProperty;
/** The guest is requesting to enumerate properties */00398typedefstruct _EnumProperties
{
VBoxGuestHGCMCallInfo 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. */00409 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). */00419 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) */00424 HGCMFunctionParameter size;
} EnumProperties;
/** * 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. */00448typedefstruct _GetNotification
{
VBoxGuestHGCMCallInfoTimed hdr;
/** * A list of patterns to match the guest event name against, separated by * vertical bars (|) (IN pointer) * An empty string means match all. */00457 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. */00468 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. */00476 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. */00483 HGCMFunctionParameter size;
} GetNotification;
#pragma pack ()
} /* namespace guestProp */#endif /* ___VBox_HostService_GuestPropertySvc_h defined */