VBoxGuestR3LibGuestProp.cpp revision ada022f71e6728d4f2b15e643d35aa94992656c7
/* $Id$ */
/** @file
* VBoxGuestR3Lib - Ring-3 Support Library for VirtualBox guest additions,
* guest properties.
*/
/*
* Copyright (C) 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;
* 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.
*
* 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.
*/
/*******************************************************************************
* Header Files *
*******************************************************************************/
#include "VBGLR3Internal.h"
/*******************************************************************************
* Structures and Typedefs *
*******************************************************************************/
/**
* Structure containing information needed to enumerate through guest
* properties.
*/
struct VBGLR3GUESTPROPENUM
{
/** @todo add a magic and validate the handle. */
/** The buffer containing the raw enumeration data */
char *pchBuf;
/** The size of the buffer */
/** Index into the buffer pointing to the next entry to enumerate */
};
using namespace guestProp;
/**
* Connects to the guest property service.
*
* @returns VBox status code
* @param pu32ClientId Where to put the client id on success. The client id
* must be passed to all the other calls to the service.
*/
{
Info.result = (uint32_t)VERR_WRONG_ORDER; /** @todo drop the cast when the result type has been fixed! */
if (RT_SUCCESS(rc))
{
if (RT_SUCCESS(rc))
}
return rc;
}
/**
* Disconnect from the guest property service.
*
* @returns VBox status code.
* @param u32ClientId The client id returned by VbglR3InfoSvcConnect().
*/
{
Info.result = (uint32_t)VERR_WRONG_ORDER; /** @todo drop the cast when the result type has been fixed! */
if (RT_SUCCESS(rc))
return rc;
}
/**
* Write a property value.
*
* @returns VBox status code.
* @param u32ClientId The client id returned by VbglR3InvsSvcConnect().
* @param pszName The property to save to. Utf8
* @param pszValue The value to store. Utf8. If this is NULL then
* the property will be removed.
* @param pszFlags The flags for the property
*/
VBGLR3DECL(int) VbglR3GuestPropWrite(uint32_t u32ClientId, const char *pszName, const char *pszValue, const char *pszFlags)
{
int rc;
{
Msg.hdr.result = (uint32_t)VERR_WRONG_ORDER; /** @todo drop the cast when the result type has been fixed! */
if (RT_SUCCESS(rc))
}
else
{
Msg.hdr.result = (uint32_t)VERR_WRONG_ORDER; /** @todo drop the cast when the result type has been fixed! */
if (RT_SUCCESS(rc))
}
return rc;
}
/**
* Write a property value.
*
* @returns VBox status code.
*
* @param u32ClientId The client id returned by VbglR3InvsSvcConnect().
* @param pszName The property to save to. Must be valid UTF-8.
* @param pszValue The value to store. Must be valid UTF-8.
* If this is NULL then the property will be removed.
*
* @note if the property already exists and pszValue is not NULL then the
* property's flags field will be left unchanged
*/
VBGLR3DECL(int) VbglR3GuestPropWriteValue(uint32_t u32ClientId, const char *pszName, const char *pszValue)
{
int rc;
{
Msg.hdr.result = (uint32_t)VERR_WRONG_ORDER; /** @todo drop the cast when the result type has been fixed! */
if (RT_SUCCESS(rc))
}
else
{
Msg.hdr.result = (uint32_t)VERR_WRONG_ORDER; /** @todo drop the cast when the result type has been fixed! */
if (RT_SUCCESS(rc))
}
return rc;
}
/**
* Write a property value where the value is formatted in RTStrPrintfV fashion.
*
* @returns The same as VbglR3GuestPropWriteValue with the addition of VERR_NO_STR_MEMORY.
*
* @param u32ClientId The client ID returned by VbglR3InvsSvcConnect().
* @param pszName The property to save to. Must be valid UTF-8.
* @param pszValueFormat The value format. This must be valid UTF-8 when fully formatted.
* @param va The format arguments.
*/
VBGLR3DECL(int) VbglR3GuestPropWriteValueV(uint32_t u32ClientId, const char *pszName, const char *pszValueFormat, va_list va)
{
/*
* Format the value and pass it on to the setter.
*/
int rc = VERR_NO_STR_MEMORY;
char *pszValue;
{
}
return rc;
}
/**
* Write a property value where the value is formatted in RTStrPrintf fashion.
*
* @returns The same as VbglR3GuestPropWriteValue with the addition of VERR_NO_STR_MEMORY.
*
* @param u32ClientId The client ID returned by VbglR3InvsSvcConnect().
* @param pszName The property to save to. Must be valid UTF-8.
* @param pszValueFormat The value format. This must be valid UTF-8 when fully formatted.
* @param ... The format arguments.
*/
VBGLR3DECL(int) VbglR3GuestPropWriteValueF(uint32_t u32ClientId, const char *pszName, const char *pszValueFormat, ...)
{
return rc;
}
/**
* Retrieve a property.
*
* @returns VBox status code.
* @retval VINF_SUCCESS on success, pszValue, pu64Timestamp and pszFlags
* containing valid data.
* @retval VERR_BUFFER_OVERFLOW if the scratch buffer @a pcBuf is not large
* enough. In this case the size needed will be placed in
* @a pcbBufActual if it is not NULL.
* @retval VERR_NOT_FOUND if the key wasn't found.
*
* @param u32ClientId The client id returned by VbglR3ClipboardConnect().
* @param pszName The value to read. Utf8
* @param pvBuf A scratch buffer to store the data retrieved into.
* The returned data is only valid for it's lifetime.
* @a ppszValue will point to the start of this buffer.
* @param cbBuf The size of @a pcBuf
* @param pszValue Where to store the pointer to the value retrieved.
* Optional.
* @param pu64Timestamp Where to store the timestamp. Optional.
* @param pszFlags Where to store the pointer to the flags. Optional.
* @param pcbBufActual If @a pcBuf is not large enough, the size needed.
* Optional.
*/
char **ppszFlags,
{
Msg.hdr.result = (uint32_t)VERR_WRONG_ORDER; /** @todo drop the cast when the result type has been fixed! */
if (RT_SUCCESS(rc))
{
if (!RT_SUCCESS(rc2))
}
{
if (pszEos)
else
}
return rc;
}
/**
* Retrieve a property value, allocating space for it.
*
* @returns VBox status code.
* @retval VINF_SUCCESS on success, *ppszValue containing valid data.
* @retval VERR_NOT_FOUND if the key wasn't found.
* @retval VERR_TOO_MUCH_DATA if we were unable to determine the right size
* to allocate for the buffer. This can happen as the result of a
* race between our allocating space and the host changing the
* property value.
*
* @param u32ClientId The client id returned by VbglR3ClipboardConnect().
* @param pszName The value to read. Must be valid UTF-8.
* @param ppszValue Where to store the pointer to the value returned.
* This is always set to NULL or to the result, even
* on failure.
*/
const char *pszName,
char **ppszValue)
{
/*
* Quick input validation.
*/
/*
* There is a race here between our reading the property size and the
* host changing the value before we read it. Try up to ten times and
* report the problem if that fails.
*/
int rc = VERR_BUFFER_OVERFLOW;
{
/* We leave a bit of space here in case the maximum value is raised. */
cchBuf += 1024;
if (pvTmpBuf)
{
}
else
rc = VERR_NO_MEMORY;
}
if (RT_SUCCESS(rc))
{
}
else
{
if (rc == VERR_BUFFER_OVERFLOW)
/* VERR_BUFFER_OVERFLOW has a different meaning here as a
* return code, but we need to report the race. */
}
return rc;
}
/**
* Free the memory used by VbglR3GuestPropReadValueAlloc for returning a
* value.
*
* @param pszValue the memory to be freed. NULL pointers will be ignored.
*/
{
}
/**
* Retrieve a property value, using a user-provided buffer to store it.
*
* @returns VBox status code.
* @retval VINF_SUCCESS on success, pszValue containing valid data.
* @retval VERR_BUFFER_OVERFLOW and the size needed in pcchValueActual if the
* buffer provided was too small
* @retval VERR_NOT_FOUND if the key wasn't found.
*
* @note There is a race here between obtaining the size of the buffer
* needed to hold the value and the value being updated.
*
* @param u32ClientId The client id returned by VbglR3ClipboardConnect().
* @param pszName The value to read. Utf8
* @param pszValue Where to store the value retrieved.
* @param cchValue The size of the buffer pointed to by @a pszValue
* @param pcchValueActual Where to store the size of the buffer needed if
* the buffer supplied is too small. Optional.
*/
{
if (RT_SUCCESS(rc))
{
if (cchValueActual > cchValue)
{
if (pcchValueActual != NULL)
}
if (RT_SUCCESS(rc))
}
return rc;
}
/**
* Raw API for enumerating guest properties which match a given pattern.
*
* @returns VBox status code.
* @retval VINF_SUCCESS on success and pcBuf points to a packed array
* of the form <name>, <value>, <timestamp string>, <flags>,
* terminated by four empty strings. pcbBufActual will contain the
* total size of the array.
* @retval VERR_BUFFER_OVERFLOW if the buffer provided was too small. In
* this case pcbBufActual will contain the size of the buffer needed.
* @returns IPRT error code in other cases, and pchBufActual is undefined.
*
* @param u32ClientId The client ID returned by VbglR3GuestPropConnect
* @param paszPatterns A packed array of zero terminated strings, terminated
* by an empty string.
* @param pcBuf The buffer to store the results to.
* @param cbBuf The size of the buffer
* @param pcbBufActual Where to store the size of the returned data on
* success or the buffer size needed if @a pcBuf is too
* small.
*/
const char *pszzPatterns,
char *pcBuf,
{
Msg.hdr.result = (uint32_t)VERR_WRONG_ORDER; /** @todo drop the cast when the result type has been fixed! */
/* Get the length of the patterns array... */
uint32_t cchPatterns = 0;
/* ...including the terminator. */
++cchPatterns;
if (RT_SUCCESS(rc))
if ( pcbBufActual
&& ( RT_SUCCESS(rc)
|| rc == VERR_BUFFER_OVERFLOW))
{
if (!RT_SUCCESS(rc2))
}
return rc;
}
/**
* Start enumerating guest properties which match a given pattern.
* This function creates a handle which can be used to continue enumerating.
*
* @returns VBox status code.
* @retval VINF_SUCCESS on success, *ppHandle points to a handle for continuing
* the enumeration and *ppszName, *ppszValue, *pu64Timestamp and
* *ppszFlags are set.
* @retval VERR_NOT_FOUND if no matching properties were found. In this case
* the return parameters are not initialised.
* @retval VERR_TOO_MUCH_DATA if it was not possible to determine the amount
* of local space needed to store all the enumeration data. This is
* due to a race between allocating space and the host adding new
* data, so retrying may help here. Other parameters are left
* uninitialised
*
* @param u32ClientId The client id returned by VbglR3InfoSvcConnect().
* @param papszPatterns The patterns against which the properties are
* matched. Pass NULL if everything should be matched.
* @param cPatterns The number of patterns in @a papszPatterns. 0 means
* match everything.
* @param ppHandle where the handle for continued enumeration is stored
* on success. This must be freed with
* VbglR3GuestPropEnumFree when it is no longer needed.
* @param ppszName Where to store the first property name on success.
* Should not be freed.
* @param ppszValue Where to store the first property value on success.
* Should not be freed.
* @param ppszValue Where to store the first timestamp value on success.
* @param ppszFlags Where to store the first flags value on success.
* Should not be freed.
*/
char const * const *papszPatterns,
char const **ppszName,
char const **ppszValue,
char const **ppszFlags)
{
int rc = VINF_SUCCESS;
if (!Handle)
rc = VERR_NO_MEMORY;
/* Get the length of the pattern string, including the final terminator. */
for (unsigned i = 0; i < cPatterns; ++i)
/* Pack the pattern array */
{
}
/* Randomly chosen initial size for the buffer to hold the enumeration
* information. */
/* In reading the guest property data we are racing against the host
* adding more of it, so loop a few times and retry on overflow. */
bool finish = false;
if (RT_SUCCESS(rc))
for (int i = 0; (i < 10) && !finish; ++i)
{
rc = VERR_NO_MEMORY;
if (rc != VERR_BUFFER_OVERFLOW)
finish = true;
else
}
if (VERR_BUFFER_OVERFLOW == rc)
if (RT_SUCCESS(rc))
{
/* Transfer ownership of the buffer to the handle structure. */
}
if (RT_SUCCESS(rc))
/* No matching properties found */
rc = VERR_NOT_FOUND;
/* And transfer ownership of the handle to the caller. */
if (RT_SUCCESS(rc))
return rc;
}
/**
* Get the next guest property. See @a VbglR3GuestPropEnum.
*
* @returns VBox status code.
*
* @param pHandle Handle obtained from @a VbglR3GuestPropEnum.
* @param ppszName Where to store the next property name. This will be
* set to NULL if there are no more properties to
* enumerate. This pointer should not be freed.
* @param ppszValue Where to store the next property value. This will be
* set to NULL if there are no more properties to
* enumerate. This pointer should not be freed.
* @param pu64Timestamp Where to store the next property timestamp. This
* will be set to zero if there are no more properties
* to enumerate.
* @param ppszFlags Where to store the next property flags. This will be
* set to NULL if there are no more properties to
* enumerate. This pointer should not be freed.
*/
char const **ppszName,
char const **ppszValue,
char const **ppszFlags)
{
/** @todo replace these with safe memchr's and return an error if needed. A
* PLEASE add a comment about the layout because this is rather
* unreadable. */
/* Otherwise we just stay at the end of the list. */
return VINF_SUCCESS;
}
/**
* Free an enumeration handle returned by @a VbglR3GuestPropEnum.
* @param pHandle the handle to free
*/
{
}
/**
* Deletes a set of keys.
*
* The set is specified in the same way as for VbglR3GuestPropEnum.
*
* @returns VBox status code. Stops on first failure.
* See also VbglR3GuestPropEnum.
*
* @param u32ClientId The client id returned by VbglR3InfoSvcConnect().
* @param papszPatterns The patterns against which the properties are
* matched. Pass NULL if everything should be matched.
* @param cPatterns The number of patterns in @a papszPatterns. 0 means
* match everything.
*/
const char * const *papszPatterns,
{
(char **)papszPatterns, /** @todo fix this cast. */
&pHandle,
&pszName,
&pszValue,
&pszFlags);
{
if (!RT_SUCCESS(rc))
break;
&pszName,
&pszValue,
&pszFlags);
}
return rc;
}