VirtualBox

source: vbox/trunk/src/VBox/Additions/common/VBoxGuest/lib/VBoxGuestR3LibSharedFolders.cpp@ 98103

Last change on this file since 98103 was 98103, checked in by vboxsync, 2 years ago

Copyright year updates by scm.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 14.8 KB
Line 
1/* $Id: VBoxGuestR3LibSharedFolders.cpp 98103 2023-01-17 14:15:46Z vboxsync $ */
2/** @file
3 * VBoxGuestR3Lib - Ring-3 Support Library for VirtualBox guest additions, shared folders.
4 */
5
6/*
7 * Copyright (C) 2010-2023 Oracle and/or its affiliates.
8 *
9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.virtualbox.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * The contents of this file may alternatively be used under the terms
26 * of the Common Development and Distribution License Version 1.0
27 * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
28 * in the VirtualBox distribution, in which case the provisions of the
29 * CDDL are applicable instead of those of the GPL.
30 *
31 * You may elect to license modified versions of this file under the
32 * terms and conditions of either the GPL or the CDDL or both.
33 *
34 * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
35 */
36
37
38/*********************************************************************************************************************************
39* Header Files *
40*********************************************************************************************************************************/
41#include <iprt/string.h>
42#include <iprt/mem.h>
43#include <iprt/assert.h>
44#include <iprt/cpp/autores.h>
45#include <iprt/stdarg.h>
46#include <VBox/log.h>
47#include <VBox/shflsvc.h> /** @todo File should be moved to VBox/HostServices/SharedFolderSvc.h */
48
49#include "VBoxGuestR3LibInternal.h"
50
51
52/**
53 * Connects to the shared folder service.
54 *
55 * @returns VBox status code
56 * @param pidClient Where to put the client id on success. The client id
57 * must be passed to all the other calls to the service.
58 */
59VBGLR3DECL(int) VbglR3SharedFolderConnect(HGCMCLIENTID *pidClient)
60{
61 return VbglR3HGCMConnect("VBoxSharedFolders", pidClient);
62}
63
64
65/**
66 * Disconnect from the shared folder service.
67 *
68 * @returns VBox status code.
69 * @param idClient The client id returned by VbglR3InfoSvcConnect().
70 */
71VBGLR3DECL(int) VbglR3SharedFolderDisconnect(HGCMCLIENTID idClient)
72{
73 return VbglR3HGCMDisconnect(idClient);
74}
75
76
77/**
78 * Checks whether a shared folder share exists or not.
79 *
80 * @returns True if shared folder exists, false if not.
81 * @param idClient The client id returned by VbglR3InfoSvcConnect().
82 * @param pszShareName Shared folder name to check.
83 */
84VBGLR3DECL(bool) VbglR3SharedFolderExists(HGCMCLIENTID idClient, const char *pszShareName)
85{
86 AssertPtr(pszShareName);
87
88 uint32_t cMappings;
89 VBGLR3SHAREDFOLDERMAPPING *paMappings;
90
91 /** @todo Use some caching here? */
92 bool fFound = false;
93 int rc = VbglR3SharedFolderGetMappings(idClient, true /* Only process auto-mounted folders */, &paMappings, &cMappings);
94 if (RT_SUCCESS(rc))
95 {
96 for (uint32_t i = 0; i < cMappings && !fFound; i++)
97 {
98 char *pszName = NULL;
99 rc = VbglR3SharedFolderGetName(idClient, paMappings[i].u32Root, &pszName);
100 if ( RT_SUCCESS(rc)
101 && *pszName)
102 {
103 if (RTStrICmp(pszName, pszShareName) == 0)
104 fFound = true;
105 RTStrFree(pszName);
106 }
107 }
108 VbglR3SharedFolderFreeMappings(paMappings);
109 }
110 return fFound;
111}
112
113
114/**
115 * Get the list of available shared folders.
116 *
117 * @returns VBox status code.
118 * @param idClient The client id returned by VbglR3SharedFolderConnect().
119 * @param fAutoMountOnly Flag whether only auto-mounted shared folders
120 * should be reported.
121 * @param ppaMappings Allocated array which will retrieve the mapping info. Needs
122 * to be freed with VbglR3SharedFolderFreeMappings() later.
123 * @param pcMappings The number of mappings returned in @a ppaMappings.
124 */
125VBGLR3DECL(int) VbglR3SharedFolderGetMappings(HGCMCLIENTID idClient, bool fAutoMountOnly,
126 PVBGLR3SHAREDFOLDERMAPPING *ppaMappings, uint32_t *pcMappings)
127{
128 AssertPtrReturn(pcMappings, VERR_INVALID_PARAMETER);
129 AssertPtrReturn(ppaMappings, VERR_INVALID_PARAMETER);
130
131 *pcMappings = 0;
132 *ppaMappings = NULL;
133
134 VBoxSFQueryMappings Msg;
135 VBGL_HGCM_HDR_INIT(&Msg.callInfo, idClient, SHFL_FN_QUERY_MAPPINGS, 3);
136
137 /* Set the mapping flags. */
138 uint32_t u32Flags = 0; /** @todo SHFL_MF_UTF8 is not implemented yet. */
139 if (fAutoMountOnly) /* We only want the mappings which get auto-mounted. */
140 u32Flags |= SHFL_MF_AUTOMOUNT;
141 VbglHGCMParmUInt32Set(&Msg.flags, u32Flags);
142
143 /*
144 * Prepare and get the actual mappings from the host service.
145 */
146 int rc = VINF_SUCCESS;
147 uint32_t cMappings = 8; /* Should be a good default value. */
148 uint32_t cbSize = cMappings * sizeof(VBGLR3SHAREDFOLDERMAPPING);
149 VBGLR3SHAREDFOLDERMAPPING *ppaMappingsTemp = (PVBGLR3SHAREDFOLDERMAPPING)RTMemAllocZ(cbSize);
150 if (!ppaMappingsTemp)
151 return VERR_NO_MEMORY;
152
153 do
154 {
155 VbglHGCMParmUInt32Set(&Msg.numberOfMappings, cMappings);
156 VbglHGCMParmPtrSet(&Msg.mappings, ppaMappingsTemp, cbSize);
157
158 rc = VbglR3HGCMCall(&Msg.callInfo, sizeof(Msg));
159 if (RT_SUCCESS(rc))
160 {
161 VbglHGCMParmUInt32Get(&Msg.numberOfMappings, pcMappings);
162
163 /* Do we have more mappings than we have allocated space for? */
164 if (rc == VINF_BUFFER_OVERFLOW)
165 {
166 cMappings = *pcMappings;
167 cbSize = cMappings * sizeof(VBGLR3SHAREDFOLDERMAPPING);
168 void *pvNew = RTMemRealloc(ppaMappingsTemp, cbSize);
169 AssertPtrBreakStmt(pvNew, rc = VERR_NO_MEMORY);
170 ppaMappingsTemp = (PVBGLR3SHAREDFOLDERMAPPING)pvNew;
171 }
172 }
173 } while (rc == VINF_BUFFER_OVERFLOW); /** @todo r=bird: This won't happen because the weird host code never returns it. */
174
175 if ( RT_FAILURE(rc)
176 || !*pcMappings)
177 {
178 RTMemFree(ppaMappingsTemp);
179 ppaMappingsTemp = NULL;
180 }
181
182 /* In this case, just return success with 0 mappings */
183 if ( rc == VERR_INVALID_PARAMETER
184 && fAutoMountOnly)
185 rc = VINF_SUCCESS;
186
187 *ppaMappings = ppaMappingsTemp;
188
189 return rc;
190}
191
192
193/**
194 * Frees the shared folder mappings allocated by
195 * VbglR3SharedFolderGetMappings() before.
196 *
197 * @param paMappings What
198 */
199VBGLR3DECL(void) VbglR3SharedFolderFreeMappings(PVBGLR3SHAREDFOLDERMAPPING paMappings)
200{
201 if (paMappings)
202 RTMemFree(paMappings);
203}
204
205
206/**
207 * Get the real name of a shared folder.
208 *
209 * @returns VBox status code.
210 * @param idClient The client id returned by VbglR3InvsSvcConnect().
211 * @param u32Root Root ID of shared folder to get the name for.
212 * @param ppszName Where to return the name string. This shall be
213 * freed by calling RTStrFree.
214 */
215VBGLR3DECL(int) VbglR3SharedFolderGetName(HGCMCLIENTID idClient, uint32_t u32Root, char **ppszName)
216{
217 AssertPtr(ppszName);
218
219 VBoxSFQueryMapName Msg;
220 VBGL_HGCM_HDR_INIT(&Msg.callInfo, idClient, SHFL_FN_QUERY_MAP_NAME, 2);
221
222 int rc;
223 uint32_t cbString = SHFLSTRING_HEADER_SIZE + SHFL_MAX_LEN * sizeof(RTUTF16);
224 PSHFLSTRING pString = (PSHFLSTRING)RTMemAlloc(cbString);
225 if (pString)
226 {
227 if (!ShflStringInitBuffer(pString, cbString))
228 {
229 RTMemFree(pString);
230 return VERR_INVALID_PARAMETER;
231 }
232
233 VbglHGCMParmUInt32Set(&Msg.root, u32Root);
234 VbglHGCMParmPtrSet(&Msg.name, pString, cbString);
235
236 rc = VbglR3HGCMCall(&Msg.callInfo, sizeof(Msg));
237 if (RT_SUCCESS(rc))
238 {
239 *ppszName = NULL;
240 rc = RTUtf16ToUtf8(&pString->String.ucs2[0], ppszName);
241 }
242 RTMemFree(pString);
243 }
244 else
245 rc = VERR_NO_MEMORY;
246 return rc;
247}
248
249
250/**
251 * Queries information about a shared folder.
252 *
253 * @returns VBox status code.
254 *
255 * @param idClient The client ID.
256 * @param idRoot The root ID of the folder to query information for.
257 * @param fQueryFlags SHFL_MIQF_XXX.
258 * @param ppszName Where to return the pointer to the name.
259 * Free using RTStrFree. Optional.
260 * @param ppszMountPoint Where to return the pointer to the auto mount point.
261 * Free using RTStrFree. Optional.
262 * @param pfFlags Where to return the flags (SHFL_MIF_XXX). Optional.
263 * @param puRootIdVersion where to return the root ID version. Optional.
264 * This helps detecting root-id reuse.
265 *
266 * @remarks ASSUMES UTF-16 connection to host.
267 */
268VBGLR3DECL(int) VbglR3SharedFolderQueryFolderInfo(HGCMCLIENTID idClient, uint32_t idRoot, uint64_t fQueryFlags,
269 char **ppszName, char **ppszMountPoint,
270 uint64_t *pfFlags, uint32_t *puRootIdVersion)
271{
272 AssertReturn(!(fQueryFlags & ~(SHFL_MIQF_DRIVE_LETTER | SHFL_MIQF_PATH)), VERR_INVALID_FLAGS);
273
274 /*
275 * Allocate string buffers first.
276 */
277 int rc;
278 PSHFLSTRING pNameBuf = (PSHFLSTRING)RTMemAlloc(SHFLSTRING_HEADER_SIZE + (SHFL_MAX_LEN + 1) * sizeof(RTUTF16));
279 PSHFLSTRING pMountPoint = (PSHFLSTRING)RTMemAlloc(SHFLSTRING_HEADER_SIZE + (260 + 1) * sizeof(RTUTF16));
280 if (pNameBuf && pMountPoint)
281 {
282 ShflStringInitBuffer(pNameBuf, SHFLSTRING_HEADER_SIZE + (SHFL_MAX_LEN + 1) * sizeof(RTUTF16));
283 ShflStringInitBuffer(pMountPoint, SHFLSTRING_HEADER_SIZE + (260 + 1) * sizeof(RTUTF16));
284
285 /*
286 * Make the call.
287 */
288 VBoxSFQueryMapInfo Msg;
289 VBGL_HGCM_HDR_INIT(&Msg.callInfo, idClient, SHFL_FN_QUERY_MAP_INFO, 5);
290 VbglHGCMParmUInt32Set(&Msg.root, idRoot);
291 VbglHGCMParmPtrSet(&Msg.name, pNameBuf, SHFLSTRING_HEADER_SIZE + pNameBuf->u16Size);
292 VbglHGCMParmPtrSet(&Msg.mountPoint, pMountPoint, SHFLSTRING_HEADER_SIZE + pMountPoint->u16Size);
293 VbglHGCMParmUInt64Set(&Msg.flags, fQueryFlags);
294 VbglHGCMParmUInt32Set(&Msg.rootIdVersion, 0);
295
296 rc = VbglR3HGCMCall(&Msg.callInfo, sizeof(Msg));
297 if (RT_SUCCESS(rc))
298 {
299 /*
300 * Copy out the results.
301 */
302 if (puRootIdVersion)
303 *puRootIdVersion = Msg.rootIdVersion.u.value64;
304
305 if (pfFlags)
306 *pfFlags = Msg.flags.u.value64;
307
308 if (ppszName)
309 {
310 *ppszName = NULL;
311 rc = RTUtf16ToUtf8Ex(pNameBuf->String.utf16, pNameBuf->u16Length / sizeof(RTUTF16), ppszName, 0, NULL);
312 }
313
314 if (ppszMountPoint && RT_SUCCESS(rc))
315 {
316 *ppszMountPoint = NULL;
317 rc = RTUtf16ToUtf8Ex(pMountPoint->String.utf16, pMountPoint->u16Length / sizeof(RTUTF16), ppszMountPoint, 0, NULL);
318 if (RT_FAILURE(rc) && ppszName)
319 {
320 RTStrFree(*ppszName);
321 *ppszName = NULL;
322 }
323 }
324 }
325 }
326 else
327 rc = VERR_NO_MEMORY;
328 RTMemFree(pMountPoint);
329 RTMemFree(pNameBuf);
330 return rc;
331}
332
333
334/**
335 * Waits for changes to the mappings (add, remove, restore).
336 *
337 * @returns VBox status code.
338 * @retval VINF_SUCCESS on change
339 * @retval VINF_TRY_AGAIN on restore.
340 * @retval VERR_OUT_OF_RESOURCES if there are too many guys waiting.
341 *
342 * @param idClient The client ID.
343 * @param uPrevVersion The mappings config version number returned the last
344 * time around. Use UINT32_MAX for the first call.
345 * @param puCurVersion Where to return the current mappings config version.
346 */
347VBGLR3DECL(int) VbglR3SharedFolderWaitForMappingsChanges(HGCMCLIENTID idClient, uint32_t uPrevVersion, uint32_t *puCurVersion)
348{
349 VBoxSFWaitForMappingsChanges Msg;
350 VBGL_HGCM_HDR_INIT(&Msg.callInfo, idClient, SHFL_FN_WAIT_FOR_MAPPINGS_CHANGES, 1);
351 VbglHGCMParmUInt32Set(&Msg.version, uPrevVersion);
352
353 int rc = VbglR3HGCMCall(&Msg.callInfo, sizeof(Msg));
354
355 *puCurVersion = Msg.version.u.value32;
356 return rc;
357}
358
359
360/**
361 * Cancels all threads currently waiting for changes for this client.
362 *
363 * @returns VBox status code.
364 * @param idClient The client ID.
365 */
366VBGLR3DECL(int) VbglR3SharedFolderCancelMappingsChangesWaits(HGCMCLIENTID idClient)
367{
368 VBGLIOCHGCMCALL CallInfo;
369 VBGL_HGCM_HDR_INIT(&CallInfo, idClient, SHFL_FN_CANCEL_MAPPINGS_CHANGES_WAITS, 0);
370
371 return VbglR3HGCMCall(&CallInfo, sizeof(CallInfo));
372}
373
374
375/**
376 * Retrieves the prefix for a shared folder mount point. If no prefix
377 * is set in the guest properties "sf_" is returned.
378 *
379 * @returns VBox status code.
380 * @param ppszPrefix Where to return the prefix string. This shall be
381 * freed by calling RTStrFree.
382 */
383VBGLR3DECL(int) VbglR3SharedFolderGetMountPrefix(char **ppszPrefix)
384{
385 AssertPtrReturn(ppszPrefix, VERR_INVALID_POINTER);
386 int rc;
387#ifdef VBOX_WITH_GUEST_PROPS
388 HGCMCLIENTID idClientGuestProp;
389 rc = VbglR3GuestPropConnect(&idClientGuestProp);
390 if (RT_SUCCESS(rc))
391 {
392 rc = VbglR3GuestPropReadValueAlloc(idClientGuestProp, "/VirtualBox/GuestAdd/SharedFolders/MountPrefix", ppszPrefix);
393 if (rc == VERR_NOT_FOUND) /* No prefix set? Then set the default. */
394 {
395#endif
396/** @todo r=bird: Inconsistent! VbglR3SharedFolderGetMountDir does not return a default. */
397 rc = RTStrDupEx(ppszPrefix, "sf_");
398#ifdef VBOX_WITH_GUEST_PROPS
399 }
400 VbglR3GuestPropDisconnect(idClientGuestProp);
401 }
402#endif
403 return rc;
404}
405
406
407/**
408 * Retrieves the mount root directory for auto-mounted shared
409 * folders. mount point. If no string is set (VERR_NOT_FOUND)
410 * it's up on the caller (guest) to decide where to mount.
411 *
412 * @returns VBox status code.
413 * @param ppszDir Where to return the directory
414 * string. This shall be freed by
415 * calling RTStrFree.
416 */
417VBGLR3DECL(int) VbglR3SharedFolderGetMountDir(char **ppszDir)
418{
419 AssertPtrReturn(ppszDir, VERR_INVALID_POINTER);
420 int rc = VERR_NOT_FOUND;
421#ifdef VBOX_WITH_GUEST_PROPS
422 HGCMCLIENTID idClientGuestProp;
423 rc = VbglR3GuestPropConnect(&idClientGuestProp);
424 if (RT_SUCCESS(rc))
425 {
426 rc = VbglR3GuestPropReadValueAlloc(idClientGuestProp, "/VirtualBox/GuestAdd/SharedFolders/MountDir", ppszDir);
427 VbglR3GuestPropDisconnect(idClientGuestProp);
428 }
429#endif
430 return rc;
431}
432
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