VirtualBox

source: vbox/trunk/include/VBox/HostServices/GuestPropertySvc.h@ 25306

Last change on this file since 25306 was 25306, checked in by vboxsync, 15 years ago

HostServices/GuestProperties: add global "RDONLYGUEST" flag and clean up the test case

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 16.0 KB
Line 
1/** @file
2 * Guest property service:
3 * Common header for host service and guest clients.
4 */
5
6/*
7 * Copyright (C) 2006-2007 Sun Microsystems, Inc.
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * The contents of this file may alternatively be used under the terms
18 * of the Common Development and Distribution License Version 1.0
19 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
20 * VirtualBox OSE distribution, in which case the provisions of the
21 * CDDL are applicable instead of those of the GPL.
22 *
23 * You may elect to license modified versions of this file under the
24 * terms and conditions of either the GPL or the CDDL or both.
25 *
26 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
27 * Clara, CA 95054 USA or visit http://www.sun.com if you need
28 * additional information or have any questions.
29 */
30
31#ifndef ___VBox_HostService_GuestPropertyService_h
32#define ___VBox_HostService_GuestPropertyService_h
33
34#include <VBox/types.h>
35#include <VBox/VMMDev.h>
36#include <VBox/VBoxGuest2.h>
37#include <VBox/hgcmsvc.h>
38#include <VBox/log.h>
39#include <iprt/assert.h>
40#include <iprt/string.h>
41
42/** Everything defined in this file lives in this namespace. */
43namespace guestProp {
44
45/******************************************************************************
46* Typedefs, constants and inlines *
47******************************************************************************/
48
49/** Maximum length for property names */
50enum { MAX_NAME_LEN = 64 };
51/** Maximum length for property values */
52enum { MAX_VALUE_LEN = 128 };
53/** Maximum number of properties per guest */
54enum { MAX_PROPS = 256 };
55/** Maximum size for enumeration patterns */
56enum { MAX_PATTERN_LEN = 1024 };
57/** Maximum number of changes we remember for guest notifications */
58enum { MAX_GUEST_NOTIFICATIONS = 256 };
59
60/**
61 * The guest property flag values which are currently accepted.
62 */
63enum ePropFlags
64{
65 NILFLAG = 0,
66 TRANSIENT = RT_BIT(1),
67 RDONLYGUEST = RT_BIT(2),
68 RDONLYHOST = RT_BIT(3),
69 READONLY = RDONLYGUEST | RDONLYHOST,
70 ALLFLAGS = TRANSIENT | READONLY
71};
72
73/**
74 * Get the name of a flag as a string.
75 * @returns the name, or NULL if fFlag is invalid.
76 * @param fFlag the flag. Must be a value from the ePropFlags enumeration
77 * list.
78 */
79DECLINLINE(const char *) flagName(uint32_t fFlag)
80{
81 switch(fFlag)
82 {
83 case TRANSIENT:
84 return "TRANSIENT";
85 case RDONLYGUEST:
86 return "RDONLYGUEST";
87 case RDONLYHOST:
88 return "RDONLYHOST";
89 case READONLY:
90 return "READONLY";
91 default:
92 return NULL;
93 }
94}
95
96/**
97 * Get the length of a flag name as returned by flagName.
98 * @returns the length, or 0 if fFlag is invalid.
99 * @param fFlag the flag. Must be a value from the ePropFlags enumeration
100 * list.
101 */
102DECLINLINE(size_t) flagNameLen(uint32_t fFlag)
103{
104 const char *pcszName = flagName(fFlag);
105 return RT_LIKELY(pcszName != NULL) ? strlen(pcszName) : 0;
106}
107
108/**
109 * Maximum length for the property flags field. We only ever return one of
110 * RDONLYGUEST, RDONLYHOST and RDONLY
111 */
112enum { MAX_FLAGS_LEN = sizeof("TRANSIENT, RDONLYGUEST") };
113
114/**
115 * Parse a guest properties flags string for flag names and make sure that
116 * there is no junk text in the string.
117 * @returns IPRT status code
118 * @returns VERR_INVALID_PARAM if the flag string is not valid
119 * @param pcszFlags the flag string to parse
120 * @param pfFlags where to store the parse result. May not be NULL.
121 * @note This function is also inline because it must be accessible from
122 * several modules and it does not seem reasonable to put it into
123 * its own library.
124 */
125DECLINLINE(int) validateFlags(const char *pcszFlags, uint32_t *pfFlags)
126{
127 static const uint32_t s_aFlagList[] =
128 {
129 TRANSIENT, READONLY, RDONLYGUEST, RDONLYHOST
130 };
131 const char *pcszNext = pcszFlags;
132 int rc = VINF_SUCCESS;
133 uint32_t fFlags = 0;
134 AssertLogRelReturn(VALID_PTR(pfFlags), VERR_INVALID_POINTER);
135
136 if (pcszFlags)
137 {
138 while (' ' == *pcszNext)
139 ++pcszNext;
140 while ((*pcszNext != '\0') && RT_SUCCESS(rc))
141 {
142 unsigned i = 0;
143 for (; i < RT_ELEMENTS(s_aFlagList); ++i)
144 if (RTStrNICmp(pcszNext, flagName(s_aFlagList[i]),
145 flagNameLen(s_aFlagList[i])) == 0)
146 break;
147 if (RT_ELEMENTS(s_aFlagList) == i)
148 rc = VERR_PARSE_ERROR;
149 else
150 {
151 fFlags |= s_aFlagList[i];
152 pcszNext += flagNameLen(s_aFlagList[i]);
153 while (' ' == *pcszNext)
154 ++pcszNext;
155 if (',' == *pcszNext)
156 ++pcszNext;
157 else if (*pcszNext != '\0')
158 rc = VERR_PARSE_ERROR;
159 while (' ' == *pcszNext)
160 ++pcszNext;
161 }
162 }
163 }
164 if (RT_SUCCESS(rc))
165 *pfFlags = fFlags;
166 return rc;
167}
168
169/**
170 * Write out flags to a string.
171 * @returns IPRT status code
172 * @param fFlags the flags to write out
173 * @param pszFlags where to write the flags string. This must point to
174 * a buffer of size (at least) MAX_FLAGS_LEN.
175 */
176DECLINLINE(int) writeFlags(uint32_t fFlags, char *pszFlags)
177{
178 static const uint32_t s_aFlagList[] =
179 {
180 TRANSIENT, READONLY, RDONLYGUEST, RDONLYHOST
181 };
182 char *pszNext = pszFlags;
183 int rc = VINF_SUCCESS;
184 AssertLogRelReturn(VALID_PTR(pszFlags), VERR_INVALID_POINTER);
185 if ((fFlags & ~ALLFLAGS) != NILFLAG)
186 rc = VERR_INVALID_PARAMETER;
187 if (RT_SUCCESS(rc))
188 {
189 unsigned i = 0;
190 for (; i < RT_ELEMENTS(s_aFlagList); ++i)
191 {
192 if (s_aFlagList[i] == (fFlags & s_aFlagList[i]))
193 {
194 strcpy(pszNext, flagName(s_aFlagList[i]));
195 pszNext += flagNameLen(s_aFlagList[i]);
196 fFlags &= ~s_aFlagList[i];
197 if (fFlags != NILFLAG)
198 {
199 strcpy(pszNext, ", ");
200 pszNext += 2;
201 }
202 }
203 }
204 *pszNext = '\0';
205 if (fFlags != NILFLAG)
206 rc = VERR_INVALID_PARAMETER; /* But pszFlags will still be set right. */
207 }
208 return rc;
209}
210
211/**
212 * The service functions which are callable by host.
213 */
214enum eHostFn
215{
216 /**
217 * Set properties in a block. The parameters are pointers to
218 * NULL-terminated arrays containing the paramters. These are, in order,
219 * name, value, timestamp, flags. Strings are stored as pointers to
220 * mutable utf8 data. All parameters must be supplied.
221 */
222 SET_PROPS_HOST = 1,
223 /**
224 * Get the value attached to a guest property
225 * The parameter format matches that of GET_PROP.
226 */
227 GET_PROP_HOST = 2,
228 /**
229 * Set the value attached to a guest property
230 * The parameter format matches that of SET_PROP.
231 */
232 SET_PROP_HOST = 3,
233 /**
234 * Set the value attached to a guest property
235 * The parameter format matches that of SET_PROP_VALUE.
236 */
237 SET_PROP_VALUE_HOST = 4,
238 /**
239 * Remove a guest property.
240 * The parameter format matches that of DEL_PROP.
241 */
242 DEL_PROP_HOST = 5,
243 /**
244 * Enumerate guest properties.
245 * The parameter format matches that of ENUM_PROPS.
246 */
247 ENUM_PROPS_HOST = 6,
248
249 /**
250 * Set global flags for the service. Currently RDONLYGUEST is supported.
251 * Takes one 32-bit unsigned integer parameter for the flags.
252 */
253 SET_GLOBAL_FLAGS_HOST = 7,
254
255 /**
256 * Flush notifications.
257 * Takes one 32-bit unsigned integer parameter that gives the number of
258 * milliseconds to wait for the worker thread to get the work done.
259 */
260 FLUSH_NOTIFICATIONS_HOST
261};
262
263/**
264 * The service functions which are called by guest. The numbers may not change,
265 * so we hardcode them.
266 */
267enum eGuestFn
268{
269 /** Get a guest property */
270 GET_PROP = 1,
271 /** Set a guest property */
272 SET_PROP = 2,
273 /** Set just the value of a guest property */
274 SET_PROP_VALUE = 3,
275 /** Delete a guest property */
276 DEL_PROP = 4,
277 /** Enumerate guest properties */
278 ENUM_PROPS = 5,
279 /** Poll for guest notifications */
280 GET_NOTIFICATION = 6
281};
282
283/**
284 * Data structure to pass to the service extension callback. We use this to
285 * notify the host of changes to properties.
286 */
287typedef struct _HOSTCALLBACKDATA
288{
289 /** Magic number to identify the structure */
290 uint32_t u32Magic;
291 /** The name of the property that was changed */
292 const char *pcszName;
293 /** The new property value, or NULL if the property was deleted */
294 const char *pcszValue;
295 /** The timestamp of the modification */
296 uint64_t u64Timestamp;
297 /** The flags field of the modified property */
298 const char *pcszFlags;
299} HOSTCALLBACKDATA, *PHOSTCALLBACKDATA;
300
301enum
302{
303 /** Magic number for sanity checking the HOSTCALLBACKDATA structure */
304 HOSTCALLBACKMAGIC = 0x69c87a78
305};
306
307/**
308 * HGCM parameter structures. Packing is explicitly defined as this is a wire format.
309 */
310#pragma pack (1)
311/** The guest is requesting the value of a property */
312typedef struct _GetProperty
313{
314 VBoxGuestHGCMCallInfo hdr;
315
316 /**
317 * The property name (IN pointer)
318 * This must fit to a number of criteria, namely
319 * - Only Utf8 strings are allowed
320 * - Less than or equal to MAX_NAME_LEN bytes in length
321 * - Zero terminated
322 */
323 HGCMFunctionParameter name;
324
325 /**
326 * The returned string data will be placed here. (OUT pointer)
327 * This call returns two null-terminated strings which will be placed one
328 * after another: value and flags.
329 */
330 HGCMFunctionParameter buffer;
331
332 /**
333 * The property timestamp. (OUT uint64_t)
334 */
335 HGCMFunctionParameter timestamp;
336
337 /**
338 * If the buffer provided was large enough this will contain the size of
339 * the returned data. Otherwise it will contain the size of the buffer
340 * needed to hold the data and VERR_BUFFER_OVERFLOW will be returned.
341 * (OUT uint32_t)
342 */
343 HGCMFunctionParameter size;
344} GetProperty;
345
346/** The guest is requesting to change a property */
347typedef struct _SetProperty
348{
349 VBoxGuestHGCMCallInfo hdr;
350
351 /**
352 * The property name. (IN pointer)
353 * This must fit to a number of criteria, namely
354 * - Only Utf8 strings are allowed
355 * - Less than or equal to MAX_NAME_LEN bytes in length
356 * - Zero terminated
357 */
358 HGCMFunctionParameter name;
359
360 /**
361 * The value of the property (IN pointer)
362 * Criteria as for the name parameter, but with length less than or equal to
363 * MAX_VALUE_LEN.
364 */
365 HGCMFunctionParameter value;
366
367 /**
368 * The property flags (IN pointer)
369 * This is a comma-separated list of the format flag=value
370 * The length must be less than or equal to MAX_FLAGS_LEN and only
371 * known flag names and values will be accepted.
372 */
373 HGCMFunctionParameter flags;
374} SetProperty;
375
376/** The guest is requesting to change the value of a property */
377typedef struct _SetPropertyValue
378{
379 VBoxGuestHGCMCallInfo hdr;
380
381 /**
382 * The property name. (IN pointer)
383 * This must fit to a number of criteria, namely
384 * - Only Utf8 strings are allowed
385 * - Less than or equal to MAX_NAME_LEN bytes in length
386 * - Zero terminated
387 */
388 HGCMFunctionParameter name;
389
390 /**
391 * The value of the property (IN pointer)
392 * Criteria as for the name parameter, but with length less than or equal to
393 * MAX_VALUE_LEN.
394 */
395 HGCMFunctionParameter value;
396} SetPropertyValue;
397
398/** The guest is requesting to remove a property */
399typedef struct _DelProperty
400{
401 VBoxGuestHGCMCallInfo hdr;
402
403 /**
404 * The property name. This must fit to a number of criteria, namely
405 * - Only Utf8 strings are allowed
406 * - Less than or equal to MAX_NAME_LEN bytes in length
407 * - Zero terminated
408 */
409 HGCMFunctionParameter name;
410} DelProperty;
411
412/** The guest is requesting to enumerate properties */
413typedef struct _EnumProperties
414{
415 VBoxGuestHGCMCallInfo hdr;
416
417 /**
418 * Array of patterns to match the properties against, separated by '|'
419 * characters. For backwards compatibility, '\0' is also accepted
420 * as a separater.
421 * (IN pointer)
422 * If only a single, empty pattern is given then match all.
423 */
424 HGCMFunctionParameter patterns;
425 /**
426 * On success, null-separated array of strings in which the properties are
427 * returned. (OUT pointer)
428 * The number of strings in the array is always a multiple of four,
429 * and in sequences of name, value, timestamp (hexadecimal string) and the
430 * flags as a comma-separated list in the format "name=value". The list
431 * is terminated by an empty string after a "flags" entry (or at the
432 * start).
433 */
434 HGCMFunctionParameter strings;
435 /**
436 * On success, the size of the returned data. If the buffer provided is
437 * too small, the size of buffer needed. (OUT uint32_t)
438 */
439 HGCMFunctionParameter size;
440} EnumProperties;
441
442/**
443 * The guest is polling for notifications on changes to properties, specifying
444 * a set of patterns to match the names of changed properties against and
445 * optionally the timestamp of the last notification seen.
446 * On success, VINF_SUCCESS will be returned and the buffer will contain
447 * details of a property notification. If no new notification is available
448 * which matches one of the specified patterns, the call will block until one
449 * is.
450 * If the last notification could not be found by timestamp, VWRN_NOT_FOUND
451 * will be returned and the oldest available notification will be returned.
452 * If a zero timestamp is specified, the call will always wait for a new
453 * notification to arrive.
454 * If the buffer supplied was not large enough to hold the notification,
455 * VERR_BUFFER_OVERFLOW will be returned and the size parameter will contain
456 * the size of the buffer needed.
457 *
458 * The protocol for a guest to obtain notifications is to call
459 * GET_NOTIFICATION in a loop. On the first call, the ingoing timestamp
460 * parameter should be set to zero. On subsequent calls, it should be set to
461 * the outgoing timestamp from the previous call.
462 */
463typedef struct _GetNotification
464{
465 VBoxGuestHGCMCallInfoTimed hdr;
466
467 /**
468 * A list of patterns to match the guest event name against, separated by
469 * vertical bars (|) (IN pointer)
470 * An empty string means match all.
471 */
472 HGCMFunctionParameter patterns;
473 /**
474 * The timestamp of the last change seen (IN uint64_t)
475 * This may be zero, in which case the oldest available change will be
476 * sent. If the service does not remember an event matching the
477 * timestamp, then VWRN_NOT_FOUND will be returned, and the guest should
478 * assume that it has missed a certain number of notifications.
479 *
480 * The timestamp of the change being notified of (OUT uint64_t)
481 * Undefined on failure.
482 */
483 HGCMFunctionParameter timestamp;
484
485 /**
486 * The returned data, if any, will be placed here. (OUT pointer)
487 * This call returns three null-terminated strings which will be placed
488 * one after another: name, value and flags. For a delete notification,
489 * value and flags will be empty strings. Undefined on failure.
490 */
491 HGCMFunctionParameter buffer;
492
493 /**
494 * On success, the size of the returned data. (OUT uint32_t)
495 * On buffer overflow, the size of the buffer needed to hold the data.
496 * Undefined on failure.
497 */
498 HGCMFunctionParameter size;
499} GetNotification;
500#pragma pack ()
501
502} /* namespace guestProp */
503
504#endif /* ___VBox_HostService_GuestPropertySvc_h defined */
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette