VirtualBox

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

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

doc

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 14.7 KB
Line 
1/* $Id: VBoxGuestR3LibGuestProp.cpp 10862 2008-07-24 17:16:04Z 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 <VBox/log.h>
31#include <VBox/HostServices/GuestPropertySvc.h>
32
33#include "VBGLR3Internal.h"
34
35using namespace guestProp;
36
37/**
38 * Connects to the guest property service.
39 *
40 * @returns VBox status code
41 * @param pu32ClientId Where to put the client id on success. The client id
42 * must be passed to all the other calls to the service.
43 */
44VBGLR3DECL(int) VbglR3GuestPropConnect(uint32_t *pu32ClientId)
45{
46 VBoxGuestHGCMConnectInfo Info;
47 Info.result = (uint32_t)VERR_WRONG_ORDER; /** @todo drop the cast when the result type has been fixed! */
48 Info.Loc.type = VMMDevHGCMLoc_LocalHost_Existing;
49 memset(&Info.Loc.u, 0, sizeof(Info.Loc.u));
50 strcpy(Info.Loc.u.host.achName, "VBoxGuestPropSvc");
51 Info.u32ClientID = UINT32_MAX; /* try make valgrid shut up. */
52
53 int rc = vbglR3DoIOCtl(VBOXGUEST_IOCTL_HGCM_CONNECT, &Info, sizeof(Info));
54 if (RT_SUCCESS(rc))
55 {
56 rc = Info.result;
57 if (RT_SUCCESS(rc))
58 *pu32ClientId = Info.u32ClientID;
59 }
60 return rc;
61}
62
63
64/**
65 * Disconnect from the guest property service.
66 *
67 * @returns VBox status code.
68 * @param u32ClientId The client id returned by VbglR3InfoSvcConnect().
69 */
70VBGLR3DECL(int) VbglR3GuestPropDisconnect(uint32_t u32ClientId)
71{
72 VBoxGuestHGCMDisconnectInfo Info;
73 Info.result = (uint32_t)VERR_WRONG_ORDER; /** @todo drop the cast when the result type has been fixed! */
74 Info.u32ClientID = u32ClientId;
75
76 int rc = vbglR3DoIOCtl(VBOXGUEST_IOCTL_HGCM_DISCONNECT, &Info, sizeof(Info));
77 if (RT_SUCCESS(rc))
78 rc = Info.result;
79 return rc;
80}
81
82
83/**
84 * Write a property value.
85 *
86 * @returns VBox status code.
87 * @param u32ClientId The client id returned by VbglR3InvsSvcConnect().
88 * @param pszName The property to save to. Utf8
89 * @param pszValue The value to store. Utf8. If this is NULL then
90 * the property will be removed.
91 * @param pszFlags The flags for the property
92 */
93VBGLR3DECL(int) VbglR3GuestPropWrite(uint32_t u32ClientId, const char *pszName, const char *pszValue, const char *pszFlags)
94{
95 int rc;
96
97 if (pszValue != NULL)
98 {
99 SetProperty Msg;
100
101 Msg.hdr.result = (uint32_t)VERR_WRONG_ORDER; /** @todo drop the cast when the result type has been fixed! */
102 Msg.hdr.u32ClientID = u32ClientId;
103 Msg.hdr.u32Function = SET_PROP_VALUE;
104 Msg.hdr.cParms = 2;
105 VbglHGCMParmPtrSet(&Msg.name, const_cast<char *>(pszName), strlen(pszName) + 1);
106 VbglHGCMParmPtrSet(&Msg.value, const_cast<char *>(pszValue), strlen(pszValue) + 1);
107 VbglHGCMParmPtrSet(&Msg.flags, const_cast<char *>(pszFlags), strlen(pszFlags) + 1);
108 rc = vbglR3DoIOCtl(VBOXGUEST_IOCTL_HGCM_CALL(sizeof(Msg)), &Msg, sizeof(Msg));
109 if (RT_SUCCESS(rc))
110 rc = Msg.hdr.result;
111 }
112 else
113 {
114 DelProperty Msg;
115
116 Msg.hdr.result = (uint32_t)VERR_WRONG_ORDER; /** @todo drop the cast when the result type has been fixed! */
117 Msg.hdr.u32ClientID = u32ClientId;
118 Msg.hdr.u32Function = DEL_PROP;
119 Msg.hdr.cParms = 1;
120 VbglHGCMParmPtrSet(&Msg.name, const_cast<char *>(pszName), strlen(pszName) + 1);
121 rc = vbglR3DoIOCtl(VBOXGUEST_IOCTL_HGCM_CALL(sizeof(Msg)), &Msg, sizeof(Msg));
122 if (RT_SUCCESS(rc))
123 rc = Msg.hdr.result;
124 }
125 return rc;
126}
127
128
129/**
130 * Write a property value.
131 *
132 * @returns VBox status code.
133 *
134 * @param u32ClientId The client id returned by VbglR3InvsSvcConnect().
135 * @param pszName The property to save to. Must be valid UTF-8.
136 * @param pszValue The value to store. Must be valid UTF-8.
137 * If this is NULL then the property will be removed.
138 *
139 * @note if the property already exists and pszValue is not NULL then the
140 * property's flags field will be left unchanged
141 */
142VBGLR3DECL(int) VbglR3GuestPropWriteValue(uint32_t u32ClientId, const char *pszName, const char *pszValue)
143{
144 int rc;
145
146 if (pszValue != NULL)
147 {
148 SetPropertyValue Msg;
149
150 Msg.hdr.result = (uint32_t)VERR_WRONG_ORDER; /** @todo drop the cast when the result type has been fixed! */
151 Msg.hdr.u32ClientID = u32ClientId;
152 Msg.hdr.u32Function = SET_PROP_VALUE;
153 Msg.hdr.cParms = 2;
154 VbglHGCMParmPtrSet(&Msg.name, const_cast<char *>(pszName), strlen(pszName) + 1);
155 VbglHGCMParmPtrSet(&Msg.value, const_cast<char *>(pszValue), strlen(pszValue) + 1);
156 rc = vbglR3DoIOCtl(VBOXGUEST_IOCTL_HGCM_CALL(sizeof(Msg)), &Msg, sizeof(Msg));
157 if (RT_SUCCESS(rc))
158 rc = Msg.hdr.result;
159 }
160 else
161 {
162 DelProperty Msg;
163
164 Msg.hdr.result = (uint32_t)VERR_WRONG_ORDER; /** @todo drop the cast when the result type has been fixed! */
165 Msg.hdr.u32ClientID = u32ClientId;
166 Msg.hdr.u32Function = DEL_PROP;
167 Msg.hdr.cParms = 1;
168 VbglHGCMParmPtrSet(&Msg.name, const_cast<char *>(pszName), strlen(pszName) + 1);
169 rc = vbglR3DoIOCtl(VBOXGUEST_IOCTL_HGCM_CALL(sizeof(Msg)), &Msg, sizeof(Msg));
170 if (RT_SUCCESS(rc))
171 rc = Msg.hdr.result;
172 }
173 return rc;
174}
175
176
177/**
178 * Write a property value where the value is formatted in RTStrPrintfV fashion.
179 *
180 * @returns The same as VbglR3GuestPropWriteValue with the addition of VERR_NO_STR_MEMORY.
181 *
182 * @param u32ClientId The client ID returned by VbglR3InvsSvcConnect().
183 * @param pszName The property to save to. Must be valid UTF-8.
184 * @param pszValueFormat The value format. This must be valid UTF-8 when fully formatted.
185 * @param va The format arguments.
186 */
187VBGLR3DECL(int) VbglR3GuestPropWriteValueV(uint32_t u32ClientId, const char *pszName, const char *pszValueFormat, va_list va)
188{
189 /*
190 * Format the value and pass it on to the setter.
191 */
192 int rc = VERR_NO_STR_MEMORY;
193 char *pszValue;
194 if (RTStrAPrintfV(&pszValue, pszValueFormat, va) < 0)
195 {
196 rc = VbglR3GuestPropWriteValue(u32ClientId, pszName, pszValue);
197 RTStrFree(pszValue);
198 }
199 return rc;
200}
201
202
203/**
204 * Write a property value where the value is formatted in RTStrPrintf fashion.
205 *
206 * @returns The same as VbglR3GuestPropWriteValue with the addition of VERR_NO_STR_MEMORY.
207 *
208 * @param u32ClientId The client ID returned by VbglR3InvsSvcConnect().
209 * @param pszName The property to save to. Must be valid UTF-8.
210 * @param pszValueFormat The value format. This must be valid UTF-8 when fully formatted.
211 * @param ... The format arguments.
212 */
213VBGLR3DECL(int) VbglR3GuestPropWriteValueF(uint32_t u32ClientId, const char *pszName, const char *pszValueFormat, ...)
214{
215 va_list va;
216 va_start(va, pszValueFormat);
217 int rc = VbglR3GuestPropWriteValueV(u32ClientId, pszName, pszValueFormat, va);
218 va_end(va);
219 return rc;
220}
221
222
223/**
224 * Retrieve a property.
225 *
226 * @returns VBox status code.
227 * @retval VINF_SUCCESS on success, pszValue, pu64Timestamp and pszFlags
228 * containing valid data.
229 * @retval VERR_BUFFER_OVERFLOW if the scratch buffer @a pcBuf is not large
230 * enough. In this case the size needed will be placed in
231 * @a pcbBufActual if it is not NULL.
232 * @retval VERR_NOT_FOUND if the key wasn't found.
233 *
234 * @param u32ClientId The client id returned by VbglR3ClipboardConnect().
235 * @param pszName The value to read. Utf8
236 * @param pcBuf A scratch buffer to store the data retrieved into.
237 * The returned data is only valid for it's lifetime.
238 * @param cbBuf The size of @a pcBuf
239 * @param pszValue Where to store the pointer to the value retrieved.
240 * @param pu64Timestamp Where to store the timestamp. Optional.
241 * @param pszFlags Where to store the pointer to the flags. Optional.
242 * @param pcbBufActual If @a pcBuf is not large enough, the size needed.
243 * Optional.
244 */
245VBGLR3DECL(int) VbglR3GuestPropRead(uint32_t u32ClientId, const char *pszName,
246 void *pvBuf, uint32_t cbBuf,
247 char **ppszValue, uint64_t *pu64Timestamp,
248 char **ppszFlags,
249 uint32_t *pcbBufActual)
250{
251 GetProperty Msg;
252
253 Msg.hdr.result = (uint32_t)VERR_WRONG_ORDER; /** @todo drop the cast when the result type has been fixed! */
254 Msg.hdr.u32ClientID = u32ClientId;
255 Msg.hdr.u32Function = GET_PROP;
256 Msg.hdr.cParms = 4;
257 VbglHGCMParmPtrSet(&Msg.name, const_cast<char *>(pszName),
258 strlen(pszName) + 1);
259 VbglHGCMParmPtrSet(&Msg.buffer, pvBuf, cbBuf);
260 VbglHGCMParmUInt64Set(&Msg.timestamp, 0);
261 VbglHGCMParmUInt32Set(&Msg.size, 0);
262
263 int rc = vbglR3DoIOCtl(VBOXGUEST_IOCTL_HGCM_CALL(sizeof(Msg)), &Msg, sizeof(Msg));
264 if (RT_SUCCESS(rc))
265 rc = Msg.hdr.result;
266 if ((VERR_BUFFER_OVERFLOW == rc) && (pcbBufActual != NULL))
267 {
268 int rc2 = VbglHGCMParmUInt32Get(&Msg.size, pcbBufActual);
269 if (!RT_SUCCESS(rc2))
270 rc = rc2;
271 }
272 if (RT_SUCCESS(rc) && (pu64Timestamp != NULL))
273 rc = VbglHGCMParmUInt64Get(&Msg.timestamp, pu64Timestamp);
274 if (RT_SUCCESS(rc))
275 *ppszValue = reinterpret_cast<char *>(pvBuf);
276 if (RT_SUCCESS(rc) && (ppszFlags != NULL))
277 {
278 char *pszEos = reinterpret_cast<char *>(memchr(pvBuf, '\0', cbBuf));
279 if (pszEos)
280 *ppszFlags = pszEos + 1;
281 else
282 rc = VERR_TOO_MUCH_DATA;
283 }
284 return rc;
285}
286
287
288/**
289 * Retrieve a property value, allocating space for it.
290 *
291 * @returns VBox status code.
292 * @retval VINF_SUCCESS on success, *ppszValue containing valid data.
293 * @retval VERR_NOT_FOUND if the key wasn't found.
294 * @retval VERR_TOO_MUCH_DATA if we were unable to determine the right size
295 * to allocate for the buffer. This can happen as the result of a
296 * race between our allocating space and the host changing the
297 * property value.
298 *
299 * @param u32ClientId The client id returned by VbglR3ClipboardConnect().
300 * @param pszName The value to read. Must be valid UTF-8.
301 * @param ppszValue Where to store the pointer to the value returned.
302 * This is always set to NULL or to the result, even
303 * on failure.
304 */
305VBGLR3DECL(int) VbglR3GuestPropReadValueAlloc(uint32_t u32ClientId,
306 const char *pszName,
307 char **ppszValue)
308{
309 /*
310 * Quick input validation.
311 */
312 AssertPtr(ppszValue);
313 *ppszValue = NULL;
314 AssertPtrReturn(pszName, VERR_INVALID_PARAMETER);
315
316 /*
317 * There is a race here between our reading the property size and the
318 * host changing the value before we read it. Try up to ten times and
319 * report the problem if that fails.
320 */
321 char *pszValue = NULL;
322 void *pvBuf = NULL;
323 uint32_t cchBuf = MAX_VALUE_LEN;
324 int rc = VERR_BUFFER_OVERFLOW;
325 for (unsigned i = 0; i < 10 && rc == VERR_BUFFER_OVERFLOW; ++i)
326 {
327 /* We leave a bit of space here in case the maximum value is raised. */
328 cchBuf += 1024;
329 void *pvTmpBuf = RTMemRealloc(pvBuf, cchBuf);
330 if (pvTmpBuf)
331 {
332 pvBuf = pvTmpBuf;
333 rc = VbglR3GuestPropRead(u32ClientId, pszName, pvBuf, cchBuf,
334 &pszValue, NULL, NULL, &cchBuf);
335 }
336 else
337 rc = VERR_NO_MEMORY;
338 }
339 if (RT_SUCCESS(rc))
340 {
341 Assert(pszValue == (char *)pvBuf);
342 *ppszValue = pszValue;
343 }
344 else
345 {
346 RTMemFree(pvBuf);
347 if (rc == VERR_BUFFER_OVERFLOW)
348 /* VERR_BUFFER_OVERFLOW has a different meaning here as a
349 * return code, but we need to report the race. */
350 rc = VERR_TOO_MUCH_DATA;
351 }
352
353 return rc;
354}
355
356/**
357 * Free the memory used by VbglR3GuestPropReadValueAlloc for returning a
358 * value.
359 *
360 * @param pszValue the memory to be freed. NULL pointers will be ignored.
361 */
362VBGLR3DECL(void) VbglR3GuestPropReadValueFree(char *pszValue)
363{
364 RTMemFree(pszValue);
365}
366
367
368/**
369 * Retrieve a property value, using a user-provided buffer to store it.
370 *
371 * @returns VBox status code.
372 * @retval VINF_SUCCESS on success, pszValue containing valid data.
373 * @retval VERR_BUFFER_OVERFLOW and the size needed in pcchValueActual if the
374 * buffer provided was too small
375 * @retval VERR_NOT_FOUND if the key wasn't found.
376 *
377 * @note There is a race here between obtaining the size of the buffer
378 * needed to hold the value and the value being updated.
379 *
380 * @param u32ClientId The client id returned by VbglR3ClipboardConnect().
381 * @param pszName The value to read. Utf8
382 * @param pszValue Where to store the value retrieved.
383 * @param cchValue The size of the buffer pointed to by @a pszValue
384 * @param pcchValueActual Where to store the size of the buffer needed if
385 * the buffer supplied is too small. Optional.
386 */
387VBGLR3DECL(int) VbglR3GuestPropReadValue(uint32_t u32ClientId, const char *pszName,
388 char *pszValue, uint32_t cchValue,
389 uint32_t *pcchValueActual)
390{
391 char *pcBuf = NULL;
392 int rc = VbglR3GuestPropReadValueAlloc(u32ClientId, pszName, &pcBuf);
393 if (RT_SUCCESS(rc))
394 {
395 uint32_t cchValueActual = strlen(pcBuf) + 1;
396 if (cchValueActual > cchValue)
397 {
398 if (pcchValueActual != NULL)
399 *pcchValueActual = cchValueActual;
400 rc = VERR_BUFFER_OVERFLOW;
401 }
402 if (RT_SUCCESS(rc))
403 strcpy(pszValue, pcBuf);
404 }
405 VbglR3GuestPropReadValueFree(pcBuf);
406 return rc;
407}
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