VirtualBox

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

Last change on this file since 63687 was 62476, checked in by vboxsync, 8 years ago

(C) 2016

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