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

