VirtualBox

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

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

Guest properties: initial commit of new interface

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 12.3 KB
Line 
1/* $Id: VBoxGuestR3LibGuestProp.cpp 10797 2008-07-22 08:12:42Z 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, char *pszName, char *pszValue, 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, pszName, strlen(pszName) + 1);
106 VbglHGCMParmPtrSet(&Msg.value, pszValue, strlen(pszValue) + 1);
107 VbglHGCMParmPtrSet(&Msg.flags, 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, 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 * @param u32ClientId The client id returned by VbglR3InvsSvcConnect().
134 * @param pszName The property to save to. Utf8
135 * @param pszValue The value to store. Utf8. If this is NULL then
136 * the property will be removed.
137 * @note if the property already exists and pszValue is not NULL then the
138 * property's flags field will be left unchanged
139 */
140VBGLR3DECL(int) VbglR3GuestPropWriteValue(uint32_t u32ClientId, char *pszName, char *pszValue)
141{
142 int rc;
143
144 if (pszValue != NULL)
145 {
146 SetPropertyValue Msg;
147
148 Msg.hdr.result = (uint32_t)VERR_WRONG_ORDER; /** @todo drop the cast when the result type has been fixed! */
149 Msg.hdr.u32ClientID = u32ClientId;
150 Msg.hdr.u32Function = SET_PROP_VALUE;
151 Msg.hdr.cParms = 2;
152 VbglHGCMParmPtrSet(&Msg.name, pszName, strlen(pszName) + 1);
153 VbglHGCMParmPtrSet(&Msg.value, pszValue, strlen(pszValue) + 1);
154 rc = vbglR3DoIOCtl(VBOXGUEST_IOCTL_HGCM_CALL(sizeof(Msg)), &Msg, sizeof(Msg));
155 if (RT_SUCCESS(rc))
156 rc = Msg.hdr.result;
157 }
158 else
159 {
160 DelProperty Msg;
161
162 Msg.hdr.result = (uint32_t)VERR_WRONG_ORDER; /** @todo drop the cast when the result type has been fixed! */
163 Msg.hdr.u32ClientID = u32ClientId;
164 Msg.hdr.u32Function = DEL_PROP;
165 Msg.hdr.cParms = 1;
166 VbglHGCMParmPtrSet(&Msg.name, pszName, strlen(pszName) + 1);
167 rc = vbglR3DoIOCtl(VBOXGUEST_IOCTL_HGCM_CALL(sizeof(Msg)), &Msg, sizeof(Msg));
168 if (RT_SUCCESS(rc))
169 rc = Msg.hdr.result;
170 }
171 return rc;
172}
173
174
175/**
176 * Retrieve a property.
177 *
178 * @returns VBox status code.
179 * @retval VINF_SUCCESS on success, pszValue, pu64Timestamp and pszFlags
180 * containing valid data.
181 * @retval VERR_BUFFER_OVERFLOW if the scratch buffer @a pcBuf is not large
182 * enough. In this case the size needed will be placed in
183 * @a pcbBufActual if it is not NULL.
184 * @retval VERR_NOT_FOUND if the key wasn't found.
185 *
186 * @param u32ClientId The client id returned by VbglR3ClipboardConnect().
187 * @param pszName The value to read. Utf8
188 * @param pcBuf A scratch buffer to store the data retrieved into.
189 * The returned data is only valid for it's lifetime.
190 * @param cbBuf The size of @a pcBuf
191 * @param pszValue Where to store the pointer to the value retrieved.
192 * @param pu64Timestamp Where to store the timestamp. Optional.
193 * @param pszFlags Where to store the pointer to the flags. Optional.
194 * @param pcbBufActual If @a pcBuf is not large enough, the size needed.
195 * Optional.
196 */
197VBGLR3DECL(int) VbglR3GuestPropRead(uint32_t u32ClientId, const char *pszName,
198 void *pvBuf, uint32_t cbBuf,
199 char **ppszValue, uint64_t *pu64Timestamp,
200 char **ppszFlags,
201 uint32_t *pcbBufActual)
202{
203 GetProperty Msg;
204
205 Msg.hdr.result = (uint32_t)VERR_WRONG_ORDER; /** @todo drop the cast when the result type has been fixed! */
206 Msg.hdr.u32ClientID = u32ClientId;
207 Msg.hdr.u32Function = GET_PROP;
208 Msg.hdr.cParms = 4;
209 VbglHGCMParmPtrSet(&Msg.name, const_cast<char *>(pszName),
210 strlen(pszName) + 1);
211 VbglHGCMParmPtrSet(&Msg.buffer, pvBuf, cbBuf);
212 VbglHGCMParmUInt64Set(&Msg.timestamp, 0);
213 VbglHGCMParmUInt32Set(&Msg.size, 0);
214
215 int rc = vbglR3DoIOCtl(VBOXGUEST_IOCTL_HGCM_CALL(sizeof(Msg)), &Msg, sizeof(Msg));
216 if (RT_SUCCESS(rc))
217 rc = Msg.hdr.result;
218 if ((VERR_BUFFER_OVERFLOW == rc) && (pcbBufActual != NULL))
219 {
220 int rc2 = VbglHGCMParmUInt32Get(&Msg.size, pcbBufActual);
221 if (!RT_SUCCESS(rc2))
222 rc = rc2;
223 }
224 if (RT_SUCCESS(rc) && (pu64Timestamp != NULL))
225 rc = VbglHGCMParmUInt64Get(&Msg.timestamp, pu64Timestamp);
226 if (RT_SUCCESS(rc))
227 *ppszValue = reinterpret_cast<char *>(pvBuf);
228 if (RT_SUCCESS(rc) && (ppszFlags != NULL))
229 {
230 bool found = false;
231 size_t i = 0;
232 char *pcBuf = reinterpret_cast<char *>(pvBuf);
233 for (; i < cbBuf && !found; ++i)
234 if (0 == pcBuf[i])
235 found = true;
236 if (!found)
237 /* To my mind this is an internal error, but whatever */
238 rc = VERR_TOO_MUCH_DATA;
239 else
240 *ppszFlags = pcBuf + i;
241 }
242 return rc;
243}
244
245
246/**
247 * Retrieve a property value, allocating space for it.
248 *
249 * @returns VBox status code.
250 * @retval VINF_SUCCESS on success, pszValue containing valid data.
251 * @retval VERR_NOT_FOUND if the key wasn't found.
252 *
253 * @param u32ClientId The client id returned by VbglR3ClipboardConnect().
254 * @param pszName The value to read. Utf8
255 * @param ppszValue Where to store the pointer to the value returned.
256 */
257VBGLR3DECL(int) VbglR3GuestPropReadValueAlloc(uint32_t u32ClientId,
258 const char *pszName,
259 char **ppszValue)
260{
261 int rc = VINF_SUCCESS;
262 uint32_t cchBuf = 1024;
263 void *pvBuf = RTMemAlloc(cchBuf);
264 char *pszValue = NULL;
265 if (NULL == pvBuf)
266 rc = VERR_NO_MEMORY;
267 if (RT_SUCCESS(rc))
268 {
269 rc = VbglR3GuestPropRead(u32ClientId, pszName, pvBuf, cchBuf,
270 &pszValue, NULL, NULL, &cchBuf);
271 if (VERR_BUFFER_OVERFLOW == rc)
272 {
273 /** @todo how should we handle the race condition here? */
274 pvBuf = RTMemRealloc(pvBuf, cchBuf);
275 if (pvBuf != NULL)
276 rc = VbglR3GuestPropRead(u32ClientId, pszName, pvBuf, cchBuf,
277 &pszValue, NULL, NULL, NULL);
278 else
279 rc = VERR_NO_MEMORY;
280 if (VERR_BUFFER_OVERFLOW == rc)
281 /* VERR_BUFFER_OVERFLOW has a different meaning here as a
282 * return code */
283 rc = VERR_TOO_MUCH_DATA;
284 }
285 }
286 if (RT_SUCCESS(rc))
287 *ppszValue = pszValue;
288 return rc;
289}
290
291/**
292 * Free the memory used by VbglR3GuestPropReadValueAlloc for returning a
293 * value.
294 *
295 * @param pszValue the memory to be freed. NULL pointers will be ignored.
296 */
297VBGLR3DECL(void) VbglR3GuestPropReadValueFree(char *pszValue)
298{
299 RTMemFree(pszValue);
300}
301
302
303/**
304 * Retrieve a property value, using a user-provided buffer to store it.
305 *
306 * @returns VBox status code.
307 * @retval VINF_SUCCESS on success, pszValue containing valid data.
308 * @retval VERR_BUFFER_OVERFLOW and the size needed in pcchValueActual if the
309 * buffer provided was too small
310 * @retval VERR_NOT_FOUND if the key wasn't found.
311 *
312 * @note There is a race here between obtaining the size of the buffer
313 * needed to hold the value and the value being updated.
314 *
315 * @param u32ClientId The client id returned by VbglR3ClipboardConnect().
316 * @param pszName The value to read. Utf8
317 * @param pszValue Where to store the value retrieved.
318 * @param cchValue The size of the buffer pointed to by @a pszValue
319 * @param pcchValueActual Where to store the size of the buffer needed if
320 * the buffer supplied is too small. Optional.
321 */
322VBGLR3DECL(int) VbglR3GuestPropReadValue(uint32_t u32ClientId, const char *pszName,
323 char *pszValue, uint32_t cchValue,
324 uint32_t *pcchValueActual)
325{
326 char *pcBuf = NULL;
327 int rc = VbglR3GuestPropReadValueAlloc(u32ClientId, pszName, &pcBuf);
328 if (RT_SUCCESS(rc))
329 {
330 uint32_t cchValueActual = strlen(pcBuf) + 1;
331 if (cchValueActual > cchValue)
332 {
333 if (pcchValueActual != NULL)
334 *pcchValueActual = cchValueActual;
335 rc = VERR_BUFFER_OVERFLOW;
336 }
337 if (RT_SUCCESS(rc))
338 strcpy(pszValue, pcBuf);
339 }
340 VbglR3GuestPropReadValueFree(pcBuf);
341 return rc;
342}
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