VirtualBox

source: vbox/trunk/src/VBox/Additions/common/VBoxGuestLib/VBoxGuestR3LibGuestProp.cpp@ 10980

Last change on this file since 10980 was 10980, checked in by vboxsync, 16 years ago

Runtime, HostServices/GuestProperties, Additions/common: autores update

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 24.9 KB
Line 
1/* $Id: VBoxGuestR3LibGuestProp.cpp 10980 2008-07-30 13:13:20Z vboxsync $ */
2/** @file
3 * VBoxGuestR3Lib - Ring-3 Support Library for VirtualBox guest additions,
4 * guest properties.
5 */
6
7/*
8 * Copyright (C) 2007 Sun Microsystems, Inc.
9 *
10 * This file is part of VirtualBox Open Source Edition (OSE), as
11 * available from http://www.virtualbox.org. This file is free software;
12 * you can redistribute it and/or modify it under the terms of the GNU
13 * General Public License (GPL) as published by the Free Software
14 * Foundation, in version 2 as it comes in the "COPYING" file of the
15 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
16 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
17 *
18 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
19 * Clara, CA 95054 USA or visit http://www.sun.com if you need
20 * additional information or have any questions.
21 */
22
23
24/*******************************************************************************
25* Header Files *
26*******************************************************************************/
27#include <iprt/string.h>
28#include <iprt/mem.h>
29#include <iprt/assert.h>
30#include <iprt/autores.h>
31#include <iprt/stdarg.h>
32#include <VBox/log.h>
33#include <VBox/HostServices/GuestPropertySvc.h>
34
35#include "VBGLR3Internal.h"
36
37
38/*******************************************************************************
39* Structures and Typedefs *
40*******************************************************************************/
41/**
42 * Structure containing information needed to enumerate through guest
43 * properties.
44 */
45struct VBGLR3GUESTPROPENUM
46{
47 /** @todo add a magic and validate the handle. */
48 /** The buffer containing the raw enumeration data */
49 char *pchBuf;
50 /** The size of the buffer */
51 uint32_t cchBuf;
52 /** Index into the buffer pointing to the next entry to enumerate */
53 uint32_t iBuf;
54};
55
56using namespace guestProp;
57
58/**
59 * Connects to the guest property service.
60 *
61 * @returns VBox status code
62 * @param pu32ClientId Where to put the client id on success. The client id
63 * must be passed to all the other calls to the service.
64 */
65VBGLR3DECL(int) VbglR3GuestPropConnect(uint32_t *pu32ClientId)
66{
67 VBoxGuestHGCMConnectInfo Info;
68 Info.result = (uint32_t)VERR_WRONG_ORDER; /** @todo drop the cast when the result type has been fixed! */
69 Info.Loc.type = VMMDevHGCMLoc_LocalHost_Existing;
70 memset(&Info.Loc.u, 0, sizeof(Info.Loc.u));
71 strcpy(Info.Loc.u.host.achName, "VBoxGuestPropSvc");
72 Info.u32ClientID = UINT32_MAX; /* try make valgrid shut up. */
73
74 int rc = vbglR3DoIOCtl(VBOXGUEST_IOCTL_HGCM_CONNECT, &Info, sizeof(Info));
75 if (RT_SUCCESS(rc))
76 {
77 rc = Info.result;
78 if (RT_SUCCESS(rc))
79 *pu32ClientId = Info.u32ClientID;
80 }
81 return rc;
82}
83
84
85/**
86 * Disconnect from the guest property service.
87 *
88 * @returns VBox status code.
89 * @param u32ClientId The client id returned by VbglR3InfoSvcConnect().
90 */
91VBGLR3DECL(int) VbglR3GuestPropDisconnect(uint32_t u32ClientId)
92{
93 VBoxGuestHGCMDisconnectInfo Info;
94 Info.result = (uint32_t)VERR_WRONG_ORDER; /** @todo drop the cast when the result type has been fixed! */
95 Info.u32ClientID = u32ClientId;
96
97 int rc = vbglR3DoIOCtl(VBOXGUEST_IOCTL_HGCM_DISCONNECT, &Info, sizeof(Info));
98 if (RT_SUCCESS(rc))
99 rc = Info.result;
100 return rc;
101}
102
103
104/**
105 * Write a property value.
106 *
107 * @returns VBox status code.
108 * @param u32ClientId The client id returned by VbglR3InvsSvcConnect().
109 * @param pszName The property to save to. Utf8
110 * @param pszValue The value to store. Utf8. If this is NULL then
111 * the property will be removed.
112 * @param pszFlags The flags for the property
113 */
114VBGLR3DECL(int) VbglR3GuestPropWrite(uint32_t u32ClientId, const char *pszName, const char *pszValue, const char *pszFlags)
115{
116 int rc;
117
118 if (pszValue != NULL)
119 {
120 SetProperty Msg;
121
122 Msg.hdr.result = (uint32_t)VERR_WRONG_ORDER; /** @todo drop the cast when the result type has been fixed! */
123 Msg.hdr.u32ClientID = u32ClientId;
124 Msg.hdr.u32Function = SET_PROP_VALUE;
125 Msg.hdr.cParms = 2;
126 VbglHGCMParmPtrSet(&Msg.name, const_cast<char *>(pszName), strlen(pszName) + 1);
127 VbglHGCMParmPtrSet(&Msg.value, const_cast<char *>(pszValue), strlen(pszValue) + 1);
128 VbglHGCMParmPtrSet(&Msg.flags, const_cast<char *>(pszFlags), strlen(pszFlags) + 1);
129 rc = vbglR3DoIOCtl(VBOXGUEST_IOCTL_HGCM_CALL(sizeof(Msg)), &Msg, sizeof(Msg));
130 if (RT_SUCCESS(rc))
131 rc = Msg.hdr.result;
132 }
133 else
134 {
135 DelProperty Msg;
136
137 Msg.hdr.result = (uint32_t)VERR_WRONG_ORDER; /** @todo drop the cast when the result type has been fixed! */
138 Msg.hdr.u32ClientID = u32ClientId;
139 Msg.hdr.u32Function = DEL_PROP;
140 Msg.hdr.cParms = 1;
141 VbglHGCMParmPtrSet(&Msg.name, const_cast<char *>(pszName), strlen(pszName) + 1);
142 rc = vbglR3DoIOCtl(VBOXGUEST_IOCTL_HGCM_CALL(sizeof(Msg)), &Msg, sizeof(Msg));
143 if (RT_SUCCESS(rc))
144 rc = Msg.hdr.result;
145 }
146 return rc;
147}
148
149
150/**
151 * Write a property value.
152 *
153 * @returns VBox status code.
154 *
155 * @param u32ClientId The client id returned by VbglR3InvsSvcConnect().
156 * @param pszName The property to save to. Must be valid UTF-8.
157 * @param pszValue The value to store. Must be valid UTF-8.
158 * If this is NULL then the property will be removed.
159 *
160 * @note if the property already exists and pszValue is not NULL then the
161 * property's flags field will be left unchanged
162 */
163VBGLR3DECL(int) VbglR3GuestPropWriteValue(uint32_t u32ClientId, const char *pszName, const char *pszValue)
164{
165 int rc;
166
167 if (pszValue != NULL)
168 {
169 SetPropertyValue Msg;
170
171 Msg.hdr.result = (uint32_t)VERR_WRONG_ORDER; /** @todo drop the cast when the result type has been fixed! */
172 Msg.hdr.u32ClientID = u32ClientId;
173 Msg.hdr.u32Function = SET_PROP_VALUE;
174 Msg.hdr.cParms = 2;
175 VbglHGCMParmPtrSet(&Msg.name, const_cast<char *>(pszName), strlen(pszName) + 1);
176 VbglHGCMParmPtrSet(&Msg.value, const_cast<char *>(pszValue), strlen(pszValue) + 1);
177 rc = vbglR3DoIOCtl(VBOXGUEST_IOCTL_HGCM_CALL(sizeof(Msg)), &Msg, sizeof(Msg));
178 if (RT_SUCCESS(rc))
179 rc = Msg.hdr.result;
180 }
181 else
182 {
183 DelProperty Msg;
184
185 Msg.hdr.result = (uint32_t)VERR_WRONG_ORDER; /** @todo drop the cast when the result type has been fixed! */
186 Msg.hdr.u32ClientID = u32ClientId;
187 Msg.hdr.u32Function = DEL_PROP;
188 Msg.hdr.cParms = 1;
189 VbglHGCMParmPtrSet(&Msg.name, const_cast<char *>(pszName), strlen(pszName) + 1);
190 rc = vbglR3DoIOCtl(VBOXGUEST_IOCTL_HGCM_CALL(sizeof(Msg)), &Msg, sizeof(Msg));
191 if (RT_SUCCESS(rc))
192 rc = Msg.hdr.result;
193 }
194 return rc;
195}
196
197
198/**
199 * Write a property value where the value is formatted in RTStrPrintfV fashion.
200 *
201 * @returns The same as VbglR3GuestPropWriteValue with the addition of VERR_NO_STR_MEMORY.
202 *
203 * @param u32ClientId The client ID returned by VbglR3InvsSvcConnect().
204 * @param pszName The property to save to. Must be valid UTF-8.
205 * @param pszValueFormat The value format. This must be valid UTF-8 when fully formatted.
206 * @param va The format arguments.
207 */
208VBGLR3DECL(int) VbglR3GuestPropWriteValueV(uint32_t u32ClientId, const char *pszName, const char *pszValueFormat, va_list va)
209{
210 /*
211 * Format the value and pass it on to the setter.
212 */
213 int rc = VERR_NO_STR_MEMORY;
214 char *pszValue;
215 if (RTStrAPrintfV(&pszValue, pszValueFormat, va) < 0)
216 {
217 rc = VbglR3GuestPropWriteValue(u32ClientId, pszName, pszValue);
218 RTStrFree(pszValue);
219 }
220 return rc;
221}
222
223
224/**
225 * Write a property value where the value is formatted in RTStrPrintf fashion.
226 *
227 * @returns The same as VbglR3GuestPropWriteValue with the addition of VERR_NO_STR_MEMORY.
228 *
229 * @param u32ClientId The client ID returned by VbglR3InvsSvcConnect().
230 * @param pszName The property to save to. Must be valid UTF-8.
231 * @param pszValueFormat The value format. This must be valid UTF-8 when fully formatted.
232 * @param ... The format arguments.
233 */
234VBGLR3DECL(int) VbglR3GuestPropWriteValueF(uint32_t u32ClientId, const char *pszName, const char *pszValueFormat, ...)
235{
236 va_list va;
237 va_start(va, pszValueFormat);
238 int rc = VbglR3GuestPropWriteValueV(u32ClientId, pszName, pszValueFormat, va);
239 va_end(va);
240 return rc;
241}
242
243
244/**
245 * Retrieve a property.
246 *
247 * @returns VBox status code.
248 * @retval VINF_SUCCESS on success, pszValue, pu64Timestamp and pszFlags
249 * containing valid data.
250 * @retval VERR_BUFFER_OVERFLOW if the scratch buffer @a pcBuf is not large
251 * enough. In this case the size needed will be placed in
252 * @a pcbBufActual if it is not NULL.
253 * @retval VERR_NOT_FOUND if the key wasn't found.
254 *
255 * @param u32ClientId The client id returned by VbglR3ClipboardConnect().
256 * @param pszName The value to read. Utf8
257 * @param pvBuf A scratch buffer to store the data retrieved into.
258 * The returned data is only valid for it's lifetime.
259 * @a ppszValue will point to the start of this buffer.
260 * @param cbBuf The size of @a pcBuf
261 * @param pszValue Where to store the pointer to the value retrieved.
262 * Optional.
263 * @param pu64Timestamp Where to store the timestamp. Optional.
264 * @param pszFlags Where to store the pointer to the flags. Optional.
265 * @param pcbBufActual If @a pcBuf is not large enough, the size needed.
266 * Optional.
267 */
268VBGLR3DECL(int) VbglR3GuestPropRead(uint32_t u32ClientId, const char *pszName,
269 void *pvBuf, uint32_t cbBuf,
270 char **ppszValue, uint64_t *pu64Timestamp,
271 char **ppszFlags,
272 uint32_t *pcbBufActual)
273{
274 GetProperty Msg;
275
276 Msg.hdr.result = (uint32_t)VERR_WRONG_ORDER; /** @todo drop the cast when the result type has been fixed! */
277 Msg.hdr.u32ClientID = u32ClientId;
278 Msg.hdr.u32Function = GET_PROP;
279 Msg.hdr.cParms = 4;
280 VbglHGCMParmPtrSet(&Msg.name, const_cast<char *>(pszName),
281 strlen(pszName) + 1);
282 VbglHGCMParmPtrSet(&Msg.buffer, pvBuf, cbBuf);
283 VbglHGCMParmUInt64Set(&Msg.timestamp, 0);
284 VbglHGCMParmUInt32Set(&Msg.size, 0);
285
286 int rc = vbglR3DoIOCtl(VBOXGUEST_IOCTL_HGCM_CALL(sizeof(Msg)), &Msg, sizeof(Msg));
287 if (RT_SUCCESS(rc))
288 rc = Msg.hdr.result;
289 if ((VERR_BUFFER_OVERFLOW == rc) && (pcbBufActual != NULL))
290 {
291 int rc2 = VbglHGCMParmUInt32Get(&Msg.size, pcbBufActual);
292 if (!RT_SUCCESS(rc2))
293 rc = rc2;
294 }
295 if (RT_SUCCESS(rc) && (pu64Timestamp != NULL))
296 rc = VbglHGCMParmUInt64Get(&Msg.timestamp, pu64Timestamp);
297 if (RT_SUCCESS(rc) && (ppszValue != NULL))
298 *ppszValue = reinterpret_cast<char *>(pvBuf);
299 if (RT_SUCCESS(rc) && (ppszFlags != NULL))
300 {
301 char *pszEos = reinterpret_cast<char *>(memchr(pvBuf, '\0', cbBuf));
302 if (pszEos)
303 *ppszFlags = pszEos + 1;
304 else
305 rc = VERR_TOO_MUCH_DATA;
306 }
307 return rc;
308}
309
310
311/**
312 * Retrieve a property value, allocating space for it.
313 *
314 * @returns VBox status code.
315 * @retval VINF_SUCCESS on success, *ppszValue containing valid data.
316 * @retval VERR_NOT_FOUND if the key wasn't found.
317 * @retval VERR_TOO_MUCH_DATA if we were unable to determine the right size
318 * to allocate for the buffer. This can happen as the result of a
319 * race between our allocating space and the host changing the
320 * property value.
321 *
322 * @param u32ClientId The client id returned by VbglR3ClipboardConnect().
323 * @param pszName The value to read. Must be valid UTF-8.
324 * @param ppszValue Where to store the pointer to the value returned.
325 * This is always set to NULL or to the result, even
326 * on failure.
327 */
328VBGLR3DECL(int) VbglR3GuestPropReadValueAlloc(uint32_t u32ClientId,
329 const char *pszName,
330 char **ppszValue)
331{
332 /*
333 * Quick input validation.
334 */
335 AssertPtr(ppszValue);
336 *ppszValue = NULL;
337 AssertPtrReturn(pszName, VERR_INVALID_PARAMETER);
338
339 /*
340 * There is a race here between our reading the property size and the
341 * host changing the value before we read it. Try up to ten times and
342 * report the problem if that fails.
343 */
344 char *pszValue = NULL;
345 void *pvBuf = NULL;
346 uint32_t cchBuf = MAX_VALUE_LEN;
347 int rc = VERR_BUFFER_OVERFLOW;
348 for (unsigned i = 0; i < 10 && rc == VERR_BUFFER_OVERFLOW; ++i)
349 {
350 /* We leave a bit of space here in case the maximum value is raised. */
351 cchBuf += 1024;
352 void *pvTmpBuf = RTMemRealloc(pvBuf, cchBuf);
353 if (pvTmpBuf)
354 {
355 pvBuf = pvTmpBuf;
356 rc = VbglR3GuestPropRead(u32ClientId, pszName, pvBuf, cchBuf,
357 &pszValue, NULL, NULL, &cchBuf);
358 }
359 else
360 rc = VERR_NO_MEMORY;
361 }
362 if (RT_SUCCESS(rc))
363 {
364 Assert(pszValue == (char *)pvBuf);
365 *ppszValue = pszValue;
366 }
367 else
368 {
369 RTMemFree(pvBuf);
370 if (rc == VERR_BUFFER_OVERFLOW)
371 /* VERR_BUFFER_OVERFLOW has a different meaning here as a
372 * return code, but we need to report the race. */
373 rc = VERR_TOO_MUCH_DATA;
374 }
375
376 return rc;
377}
378
379
380/**
381 * Free the memory used by VbglR3GuestPropReadValueAlloc for returning a
382 * value.
383 *
384 * @param pszValue the memory to be freed. NULL pointers will be ignored.
385 */
386VBGLR3DECL(void) VbglR3GuestPropReadValueFree(char *pszValue)
387{
388 RTMemFree(pszValue);
389}
390
391
392/**
393 * Retrieve a property value, using a user-provided buffer to store it.
394 *
395 * @returns VBox status code.
396 * @retval VINF_SUCCESS on success, pszValue containing valid data.
397 * @retval VERR_BUFFER_OVERFLOW and the size needed in pcchValueActual if the
398 * buffer provided was too small
399 * @retval VERR_NOT_FOUND if the key wasn't found.
400 *
401 * @note There is a race here between obtaining the size of the buffer
402 * needed to hold the value and the value being updated.
403 *
404 * @param u32ClientId The client id returned by VbglR3ClipboardConnect().
405 * @param pszName The value to read. Utf8
406 * @param pszValue Where to store the value retrieved.
407 * @param cchValue The size of the buffer pointed to by @a pszValue
408 * @param pcchValueActual Where to store the size of the buffer needed if
409 * the buffer supplied is too small. Optional.
410 */
411VBGLR3DECL(int) VbglR3GuestPropReadValue(uint32_t u32ClientId, const char *pszName,
412 char *pszValue, uint32_t cchValue,
413 uint32_t *pcchValueActual)
414{
415 char *pcBuf = NULL;
416 int rc = VbglR3GuestPropReadValueAlloc(u32ClientId, pszName, &pcBuf);
417 if (RT_SUCCESS(rc))
418 {
419 uint32_t cchValueActual = strlen(pcBuf) + 1;
420 if (cchValueActual > cchValue)
421 {
422 if (pcchValueActual != NULL)
423 *pcchValueActual = cchValueActual;
424 rc = VERR_BUFFER_OVERFLOW;
425 }
426 if (RT_SUCCESS(rc))
427 strcpy(pszValue, pcBuf);
428 }
429 VbglR3GuestPropReadValueFree(pcBuf);
430 return rc;
431}
432
433
434/**
435 * Raw API for enumerating guest properties which match a given pattern.
436 *
437 * @returns VBox status code.
438 * @retval VINF_SUCCESS on success and pcBuf points to a packed array
439 * of the form <name>, <value>, <timestamp string>, <flags>,
440 * terminated by four empty strings. pcbBufActual will contain the
441 * total size of the array.
442 * @retval VERR_BUFFER_OVERFLOW if the buffer provided was too small. In
443 * this case pcbBufActual will contain the size of the buffer needed.
444 * @returns IPRT error code in other cases, and pchBufActual is undefined.
445 *
446 * @param u32ClientId The client ID returned by VbglR3GuestPropConnect
447 * @param paszPatterns A packed array of zero terminated strings, terminated
448 * by an empty string.
449 * @param pcBuf The buffer to store the results to.
450 * @param cbBuf The size of the buffer
451 * @param pcbBufActual Where to store the size of the returned data on
452 * success or the buffer size needed if @a pcBuf is too
453 * small.
454 */
455VBGLR3DECL(int) VbglR3GuestPropEnumRaw(uint32_t u32ClientId,
456 const char *pszzPatterns,
457 char *pcBuf,
458 uint32_t cbBuf,
459 uint32_t *pcbBufActual)
460{
461 EnumProperties Msg;
462
463 Msg.hdr.result = (uint32_t)VERR_WRONG_ORDER; /** @todo drop the cast when the result type has been fixed! */
464 Msg.hdr.u32ClientID = u32ClientId;
465 Msg.hdr.u32Function = ENUM_PROPS;
466 Msg.hdr.cParms = 3;
467 /* Get the length of the patterns array... */
468 uint32_t cchPatterns = 0;
469 for (uint32_t cchCurrent = strlen(pszzPatterns); cchCurrent != 0;
470 cchCurrent = strlen(pszzPatterns + cchPatterns))
471 cchPatterns += cchCurrent + 1;
472 /* ...including the terminator. */
473 ++cchPatterns;
474 VbglHGCMParmPtrSet(&Msg.patterns, const_cast<char *>(pszzPatterns),
475 cchPatterns);
476 VbglHGCMParmPtrSet(&Msg.strings, pcBuf, cbBuf);
477 VbglHGCMParmUInt32Set(&Msg.size, 0);
478
479 int rc = vbglR3DoIOCtl(VBOXGUEST_IOCTL_HGCM_CALL(sizeof(Msg)), &Msg, sizeof(Msg));
480 if (RT_SUCCESS(rc))
481 rc = Msg.hdr.result;
482 if ( pcbBufActual
483 && ( RT_SUCCESS(rc)
484 || rc == VERR_BUFFER_OVERFLOW))
485 {
486 int rc2 = VbglHGCMParmUInt32Get(&Msg.size, pcbBufActual);
487 if (!RT_SUCCESS(rc2))
488 rc = rc2;
489 }
490 return rc;
491}
492
493
494/**
495 * Start enumerating guest properties which match a given pattern.
496 * This function creates a handle which can be used to continue enumerating.
497 *
498 * @returns VBox status code.
499 * @retval VINF_SUCCESS on success, *ppHandle points to a handle for continuing
500 * the enumeration and *ppszName, *ppszValue, *pu64Timestamp and
501 * *ppszFlags are set.
502 * @retval VERR_NOT_FOUND if no matching properties were found. In this case
503 * the return parameters are not initialised.
504 * @retval VERR_TOO_MUCH_DATA if it was not possible to determine the amount
505 * of local space needed to store all the enumeration data. This is
506 * due to a race between allocating space and the host adding new
507 * data, so retrying may help here. Other parameters are left
508 * uninitialised
509 *
510 * @param papszPatterns The patterns against which the properties are
511 * matched. Pass NULL if everything should be matched.
512 * @param cPatterns The number of patterns in @a papszPatterns. 0 means
513 * match everything.
514 * @param ppHandle where the handle for continued enumeration is stored
515 * on success. This must be freed with
516 * VbglR3GuestPropEnumFree when it is no longer needed.
517 * @param ppszName Where to store the first property name on success.
518 * Should not be freed.
519 * @param ppszValue Where to store the first property value on success.
520 * Should not be freed.
521 * @param ppszValue Where to store the first timestamp value on success.
522 * @param ppszFlags Where to store the first flags value on success.
523 * Should not be freed.
524 */
525VBGLR3DECL(int) VbglR3GuestPropEnum(uint32_t u32ClientId,
526 char **papszPatterns,
527 int cPatterns,
528 PVBGLR3GUESTPROPENUM *ppHandle,
529 char **ppszName,
530 char **ppszValue,
531 uint64_t *pu64Timestamp,
532 char **ppszFlags)
533{
534 int rc = VINF_SUCCESS;
535 RTMemAutoPtr<VBGLR3GUESTPROPENUM, VbglR3GuestPropEnumFree> Handle;
536 Handle = RTMemAllocZ(sizeof(VBGLR3GUESTPROPENUM));
537 if (!Handle)
538 rc = VERR_NO_MEMORY;
539
540 /* Get the length of the pattern string, including the final terminator. */
541 uint32_t cchPatterns = 1;
542 for (int i = 0; i < cPatterns; ++i)
543 cchPatterns += strlen(papszPatterns[i]) + 1;
544 /* Pack the pattern array */
545 RTMemAutoPtr<char> Patterns;
546 Patterns = reinterpret_cast<char *>(RTMemAlloc(cchPatterns));
547 size_t iOffs = 0;
548 for (int i = 0; i < cPatterns; ++i)
549 {
550 size_t cb = strlen(papszPatterns[i]) + 1;
551 memcpy(&Patterns[iOffs], papszPatterns[i], cb);
552 iOffs += cb;
553 }
554 Patterns[iOffs] = '\0';
555
556 /* Randomly chosen initial size for the buffer to hold the enumeration
557 * information. */
558 uint32_t cchBuf = 4096;
559 RTMemAutoPtr<char> Buf;
560 /* In reading the guest property data we are racing against the host
561 * adding more of it, so loop a few times and retry on overflow. */
562 bool finish = false;
563 if (RT_SUCCESS(rc))
564 for (int i = 0; (i < 10) && !finish; ++i)
565 {
566 if (!Buf.realloc(cchBuf))
567 rc = VERR_NO_MEMORY;
568 if (RT_SUCCESS(rc) || (VERR_BUFFER_OVERFLOW == rc))
569 rc = VbglR3GuestPropEnumRaw(u32ClientId, Patterns.get(),
570 Buf.get(), cchBuf, &cchBuf);
571 if (rc != VERR_BUFFER_OVERFLOW)
572 finish = true;
573 else
574 cchBuf += 4096; /* Just to increase our chances */
575 }
576 if (VERR_BUFFER_OVERFLOW == rc)
577 rc = VERR_TOO_MUCH_DATA;
578 if (RT_SUCCESS(rc))
579 {
580 /* Transfer ownership of the buffer to the handle structure. */
581 Handle->pchBuf = Buf.release();
582 Handle->cchBuf = cchBuf;
583 }
584 if (RT_SUCCESS(rc))
585 rc = VbglR3GuestPropEnumNext(Handle.get(), ppszName, ppszValue,
586 pu64Timestamp, ppszFlags);
587 if (RT_SUCCESS(rc) && (NULL == ppszName))
588 /* No matching properties found */
589 rc = VERR_NOT_FOUND;
590 /* And transfer ownership of the handle to the caller. */
591 if (RT_SUCCESS(rc))
592 *ppHandle = Handle.release();
593 return rc;
594}
595
596
597/**
598 * Get the next guest property. See @a VbglR3GuestPropEnum.
599 *
600 * @returns VBox status code.
601 *
602 * @param pHandle Handle obtained from @a VbglR3GuestPropEnum.
603 * @param ppszName Where to store the next property name. This will be
604 * set to NULL if there are no more properties to
605 * enumerate. This pointer should not be freed.
606 * @param ppszValue Where to store the next property value. This will be
607 * set to NULL if there are no more properties to
608 * enumerate. This pointer should not be freed.
609 * @param pu64Timestamp Where to store the next property timestamp. This
610 * will be set to zero if there are no more properties
611 * to enumerate.
612 * @param ppszFlags Where to store the next property flags. This will be
613 * set to NULL if there are no more properties to
614 * enumerate. This pointer should not be freed.
615 */
616VBGLR3DECL(int) VbglR3GuestPropEnumNext(PVBGLR3GUESTPROPENUM pHandle,
617 char **ppszName,
618 char **ppszValue,
619 uint64_t *pu64Timestamp,
620 char **ppszFlags)
621{
622 uint32_t iBuf = pHandle->iBuf;
623 char *pszName = pHandle->pchBuf + iBuf;
624 /** @todo replace these with safe memchr's and return an error if needed. */
625 iBuf += strlen(pszName) + 1;
626 char *pszValue = pHandle->pchBuf + iBuf;
627 iBuf += strlen(pszValue) + 1;
628 char *pszTimestamp = pHandle->pchBuf + iBuf;
629 iBuf += strlen(pszTimestamp) + 1;
630 uint64_t u64Timestamp = RTStrToUInt64(pszTimestamp);
631 char *pszFlags = pHandle->pchBuf + iBuf;
632 iBuf += strlen(pszFlags) + 1;
633 /* Otherwise we just stay at the end of the list. */
634 if ((iBuf != pHandle->iBuf + 4) && (iBuf < pHandle->cchBuf) /* sanity */)
635 pHandle->iBuf = iBuf;
636 *ppszName = *pszName != 0 ? pszName : NULL;
637 *ppszValue = pszValue != 0 ? pszValue : NULL;
638 *pu64Timestamp = u64Timestamp;
639 *ppszFlags = pszFlags != 0 ? pszFlags : NULL;
640 return VINF_SUCCESS;
641}
642
643
644/**
645 * Free an enumeration handle returned by @a VbglR3GuestPropEnum.
646 * @param pHandle the handle to free
647 */
648VBGLR3DECL(void) VbglR3GuestPropEnumFree(PVBGLR3GUESTPROPENUM pHandle)
649{
650 RTMemFree(pHandle->pchBuf);
651 RTMemFree(pHandle);
652}
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