VirtualBox

source: vbox/trunk/src/VBox/Additions/common/VBoxGuest/lib/VBoxGuestR3LibGuestCtrl.cpp

Last change on this file was 108896, checked in by vboxsync, 4 weeks ago

src/VBox/Additions/common/VBoxGuest/lib/VBoxGuestR3LibGuestCtrl.cpp: eliminate useless assignment

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 111.8 KB
Line 
1/* $Id: VBoxGuestR3LibGuestCtrl.cpp 108896 2025-04-08 15:53:09Z vboxsync $ */
2/** @file
3 * VBoxGuestR3Lib - Ring-3 Support Library for VirtualBox guest additions, guest control.
4 */
5
6/*
7 * Copyright (C) 2010-2024 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/err.h>
47#include <VBox/log.h>
48#include <VBox/GuestHost/GuestControl.h>
49#include <VBox/HostServices/GuestControlSvc.h>
50
51#ifndef RT_OS_WINDOWS
52# include <signal.h>
53# ifdef RT_OS_DARWIN
54# include <pthread.h>
55# define sigprocmask pthread_sigmask /* On xnu sigprocmask works on the process, not the calling thread as elsewhere. */
56# endif
57#endif
58
59#include "VBoxGuestR3LibInternal.h"
60
61using namespace guestControl;
62
63
64/*********************************************************************************************************************************
65* Global Variables *
66*********************************************************************************************************************************/
67/** Set if GUEST_MSG_PEEK_WAIT and friends are supported. */
68static int g_fVbglR3GuestCtrlHavePeekGetCancel = -1;
69/** Represents the currently cached host features 0.
70 * Set to 0 if not available / not cached yet. */
71static uint64_t g_fVbglR3GuestCtrlHostFeatures0 = 0;
72
73
74/*********************************************************************************************************************************
75* Prototypes *
76*********************************************************************************************************************************/
77static int vbglR3GuestCtrlQueryFeatures(uint32_t idClient, uint64_t *pfHostFeatures0, uint64_t *pfHostFeatures1);
78
79
80/**
81 * Invalidates the internal state of the Guest Control API.
82 *
83 * @returns VBox status code.
84 * @param idClient The client ID returned by VbglR3GuestCtrlConnect().
85 */
86static int vbglR3GuestCtrlInvalidate(uint32_t idClient)
87{
88 uint64_t fVbglR3GuestCtrlHostFeatures0 = 0;
89 int const rc2 = vbglR3GuestCtrlQueryFeatures(idClient,
90 &fVbglR3GuestCtrlHostFeatures0, NULL /* pfHostFeatures1, unused */);
91 if (RT_SUCCESS(rc2))
92 {
93 /* Check if the host's feature set has changed. This might happen on a VM restore. */
94 if ( g_fVbglR3GuestCtrlHostFeatures0
95 && g_fVbglR3GuestCtrlHostFeatures0 != fVbglR3GuestCtrlHostFeatures0)
96 LogRelFunc(("Host feature set has changed (%#x -> %#x)\n",
97 g_fVbglR3GuestCtrlHostFeatures0, fVbglR3GuestCtrlHostFeatures0));
98
99 g_fVbglR3GuestCtrlHostFeatures0 = fVbglR3GuestCtrlHostFeatures0;
100 }
101 else
102 LogRelFunc(("Querying host features not supported, rc=%Rrc\n", rc2));
103 /* Note: Very old hosts don't know about querying host features, so this isn't fatal for the caller. */
104
105 return VINF_SUCCESS;
106}
107
108
109/**
110 * Connects to the guest control service.
111 *
112 * @returns VBox status code
113 * @param pidClient Where to put The client ID on success. The client ID
114 * must be passed to all the other calls to the service.
115 */
116VBGLR3DECL(int) VbglR3GuestCtrlConnect(uint32_t *pidClient)
117{
118 AssertPtrReturn(pidClient, VERR_INVALID_POINTER);
119
120 int rc = VbglR3HGCMConnect("VBoxGuestControlSvc", pidClient);
121 if (RT_SUCCESS(rc))
122 rc = vbglR3GuestCtrlInvalidate(*pidClient);
123
124 return rc;
125}
126
127
128/**
129 * Disconnect from the guest control service.
130 *
131 * @returns VBox status code.
132 * @param idClient The client ID returned by VbglR3GuestCtrlConnect().
133 */
134VBGLR3DECL(int) VbglR3GuestCtrlDisconnect(uint32_t idClient)
135{
136 return VbglR3HGCMDisconnect(idClient);
137}
138
139
140/**
141 * Waits until a new host message arrives.
142 * This will block until a message becomes available.
143 *
144 * @returns VBox status code.
145 * @param idClient The client ID returned by VbglR3GuestCtrlConnect().
146 * @param pidMsg Where to store the message id.
147 * @param pcParameters Where to store the number of parameters which will
148 * be received in a second call to the host.
149 */
150static int vbglR3GuestCtrlMsgWaitFor(uint32_t idClient, uint32_t *pidMsg, uint32_t *pcParameters)
151{
152 AssertPtrReturn(pidMsg, VERR_INVALID_POINTER);
153 AssertPtrReturn(pcParameters, VERR_INVALID_POINTER);
154
155 HGCMMsgWaitFor Msg;
156 VBGL_HGCM_HDR_INIT(&Msg.hdr, idClient,
157 GUEST_MSG_WAIT, /* Tell the host we want our next message. */
158 2); /* Just peek for the next message! */
159 VbglHGCMParmUInt32Set(&Msg.msg, 0);
160 VbglHGCMParmUInt32Set(&Msg.num_parms, 0);
161
162 /*
163 * We should always get a VERR_TOO_MUCH_DATA response here, see
164 * guestControl::HostMessage::Peek() and its caller ClientState::SendReply().
165 * We accept success too here, in case someone decide to make the protocol
166 * slightly more sane.
167 *
168 * Note! A really sane protocol design would have a separate call for getting
169 * info about a pending message (returning VINF_SUCCESS), and a separate
170 * one for retriving the actual message parameters. Not this weird
171 * stuff, to put it rather bluntly.
172 *
173 * Note! As a result of this weird design, we are not able to correctly
174 * retrieve message if we're interrupted by a signal, like SIGCHLD.
175 * Because IPRT wants to use waitpid(), we're forced to have a handler
176 * installed for SIGCHLD, so when working with child processes there
177 * will be signals in the air and we will get VERR_INTERRUPTED returns.
178 * The way HGCM handles interrupted calls is to silently (?) drop them
179 * as they complete (see VMMDev), so the server knows little about it
180 * and just goes on to the next message inline.
181 *
182 * So, as a "temporary" mesasure, we block SIGCHLD here while waiting,
183 * because it will otherwise be impossible do simple stuff like 'mkdir'
184 * on a mac os x guest, and probably most other unix guests.
185 */
186#ifdef RT_OS_WINDOWS
187 int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
188#else
189 sigset_t SigSet;
190 sigemptyset(&SigSet);
191 sigaddset(&SigSet, SIGCHLD);
192 sigprocmask(SIG_BLOCK, &SigSet, NULL);
193 int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
194 sigprocmask(SIG_UNBLOCK, &SigSet, NULL);
195#endif
196 if ( rc == VERR_TOO_MUCH_DATA
197 || RT_SUCCESS(rc))
198 {
199 int rc2 = VbglHGCMParmUInt32Get(&Msg.msg, pidMsg);
200 if (RT_SUCCESS(rc2))
201 {
202 rc2 = VbglHGCMParmUInt32Get(&Msg.num_parms, pcParameters);
203 if (RT_SUCCESS(rc2))
204 {
205 /* Ok, so now we know what message type and how much parameters there are. */
206 return rc;
207 }
208 }
209 rc = rc2;
210 }
211 *pidMsg = UINT32_MAX - 1;
212 *pcParameters = UINT32_MAX - 2;
213 return rc;
214}
215
216
217/**
218 * Determins the value of g_fVbglR3GuestCtrlHavePeekGetCancel.
219 *
220 * @returns true if supported, false if not.
221 * @param idClient The client ID to use for the testing.
222 */
223DECL_NO_INLINE(static, bool) vbglR3GuestCtrlDetectPeekGetCancelSupport(uint32_t idClient)
224{
225 /*
226 * Seems we get VINF_SUCCESS back from the host if we try unsupported
227 * guest control messages, so we need to supply some random message
228 * parameters and check that they change.
229 */
230 uint32_t const idDummyMsg = UINT32_C(0x8350bdca);
231 uint32_t const cDummyParmeters = UINT32_C(0x7439604f);
232 uint32_t const cbDummyMask = UINT32_C(0xc0ffe000);
233 Assert(cDummyParmeters > VMMDEV_MAX_HGCM_PARMS);
234
235 int rc;
236 struct
237 {
238 VBGLIOCHGCMCALL Hdr;
239 HGCMFunctionParameter idMsg;
240 HGCMFunctionParameter cParams;
241 HGCMFunctionParameter acbParams[14];
242 } PeekCall;
243 Assert(RT_ELEMENTS(PeekCall.acbParams) + 2 < VMMDEV_MAX_HGCM_PARMS);
244
245 do
246 {
247 memset(&PeekCall, 0xf6, sizeof(PeekCall));
248 VBGL_HGCM_HDR_INIT(&PeekCall.Hdr, idClient, GUEST_MSG_PEEK_NOWAIT, 16);
249 VbglHGCMParmUInt32Set(&PeekCall.idMsg, idDummyMsg);
250 VbglHGCMParmUInt32Set(&PeekCall.cParams, cDummyParmeters);
251 for (uint32_t i = 0; i < RT_ELEMENTS(PeekCall.acbParams); i++)
252 VbglHGCMParmUInt32Set(&PeekCall.acbParams[i], i | cbDummyMask);
253
254 rc = VbglR3HGCMCall(&PeekCall.Hdr, sizeof(PeekCall));
255 } while (rc == VERR_INTERRUPTED);
256
257 LogRel2(("vbglR3GuestCtrlDetectPeekGetCancelSupport: rc=%Rrc %#x %#x %#x %#x %#x %#x %#x %#x %#x %#x %#x %#x %#x %#x %#x %#x\n",
258 rc, PeekCall.idMsg.u.value32, PeekCall.cParams.u.value32,
259 PeekCall.acbParams[ 0].u.value32, PeekCall.acbParams[ 1].u.value32,
260 PeekCall.acbParams[ 2].u.value32, PeekCall.acbParams[ 3].u.value32,
261 PeekCall.acbParams[ 4].u.value32, PeekCall.acbParams[ 5].u.value32,
262 PeekCall.acbParams[ 6].u.value32, PeekCall.acbParams[ 7].u.value32,
263 PeekCall.acbParams[ 8].u.value32, PeekCall.acbParams[ 9].u.value32,
264 PeekCall.acbParams[10].u.value32, PeekCall.acbParams[11].u.value32,
265 PeekCall.acbParams[12].u.value32, PeekCall.acbParams[13].u.value32));
266
267 /*
268 * VERR_TRY_AGAIN is likely and easy.
269 */
270 if ( rc == VERR_TRY_AGAIN
271 && PeekCall.idMsg.u.value32 == 0
272 && PeekCall.cParams.u.value32 == 0
273 && PeekCall.acbParams[0].u.value32 == 0
274 && PeekCall.acbParams[1].u.value32 == 0
275 && PeekCall.acbParams[2].u.value32 == 0
276 && PeekCall.acbParams[3].u.value32 == 0)
277 {
278 g_fVbglR3GuestCtrlHavePeekGetCancel = 1;
279 LogRel(("vbglR3GuestCtrlDetectPeekGetCancelSupport: Supported (#1)\n"));
280 return true;
281 }
282
283 /*
284 * VINF_SUCCESS is annoying but with 16 parameters we've got plenty to check.
285 */
286 if ( rc == VINF_SUCCESS
287 && PeekCall.idMsg.u.value32 != idDummyMsg
288 && PeekCall.idMsg.u.value32 != 0
289 && PeekCall.cParams.u.value32 <= VMMDEV_MAX_HGCM_PARMS)
290 {
291 for (uint32_t i = 0; i < RT_ELEMENTS(PeekCall.acbParams); i++)
292 if (PeekCall.acbParams[i].u.value32 != (i | cbDummyMask))
293 {
294 g_fVbglR3GuestCtrlHavePeekGetCancel = 0;
295 LogRel(("vbglR3GuestCtrlDetectPeekGetCancelSupport: Not supported (#1)\n"));
296 return false;
297 }
298 g_fVbglR3GuestCtrlHavePeekGetCancel = 1;
299 LogRel(("vbglR3GuestCtrlDetectPeekGetCancelSupport: Supported (#2)\n"));
300 return true;
301 }
302
303 /*
304 * Okay, pretty sure it's not supported then.
305 */
306 LogRel(("vbglR3GuestCtrlDetectPeekGetCancelSupport: Not supported (#3)\n"));
307 g_fVbglR3GuestCtrlHavePeekGetCancel = 0;
308 return false;
309}
310
311
312/**
313 * Reads g_fVbglR3GuestCtrlHavePeekGetCancel and resolved -1.
314 *
315 * @returns true if supported, false if not.
316 * @param idClient The client ID to use for the testing.
317 */
318DECLINLINE(bool) vbglR3GuestCtrlSupportsPeekGetCancel(uint32_t idClient)
319{
320 int fState = g_fVbglR3GuestCtrlHavePeekGetCancel;
321 if (RT_LIKELY(fState != -1))
322 return fState != 0;
323 return vbglR3GuestCtrlDetectPeekGetCancelSupport(idClient);
324}
325
326
327/**
328 * Figures which getter function to use to retrieve the message.
329 */
330DECLINLINE(uint32_t) vbglR3GuestCtrlGetMsgFunctionNo(uint32_t idClient)
331{
332 return vbglR3GuestCtrlSupportsPeekGetCancel(idClient) ? GUEST_MSG_GET : GUEST_MSG_WAIT;
333}
334
335
336/**
337 * Checks if the host supports the optimizes message and session functions.
338 *
339 * @returns true / false.
340 * @param idClient The client ID returned by VbglR3GuestCtrlConnect().
341 * We may need to use this for checking.
342 * @since 6.0
343 */
344VBGLR3DECL(bool) VbglR3GuestCtrlSupportsOptimizations(uint32_t idClient)
345{
346 return vbglR3GuestCtrlSupportsPeekGetCancel(idClient);
347}
348
349
350/**
351 * Make us the guest control master client.
352 *
353 * @returns VBox status code.
354 * @param idClient The client ID returned by VbglR3GuestCtrlConnect().
355 */
356VBGLR3DECL(int) VbglR3GuestCtrlMakeMeMaster(uint32_t idClient)
357{
358 int rc;
359 do
360 {
361 VBGLIOCHGCMCALL Hdr;
362 VBGL_HGCM_HDR_INIT(&Hdr, idClient, GUEST_MSG_MAKE_ME_MASTER, 0);
363 rc = VbglR3HGCMCall(&Hdr, sizeof(Hdr));
364 } while (rc == VERR_INTERRUPTED);
365 return rc;
366}
367
368
369/**
370 * Reports features to the host and retrieve host features set.
371 *
372 * @returns VBox status code.
373 * @param idClient The client ID returned by VbglR3GuestCtrlConnect().
374 * @param fGuestFeatures Features to report, VBOX_GUESTCTRL_GF_XXX.
375 * @param pfHostFeatures Where to store the features VBOX_GUESTCTRL_HF_XXX.
376 */
377VBGLR3DECL(int) VbglR3GuestCtrlReportFeatures(uint32_t idClient, uint64_t fGuestFeatures, uint64_t *pfHostFeatures)
378{
379 int rc;
380 do
381 {
382 struct
383 {
384 VBGLIOCHGCMCALL Hdr;
385 HGCMFunctionParameter f64Features0;
386 HGCMFunctionParameter f64Features1;
387 } Msg;
388 VBGL_HGCM_HDR_INIT(&Msg.Hdr, idClient, GUEST_MSG_REPORT_FEATURES, 2);
389 VbglHGCMParmUInt64Set(&Msg.f64Features0, fGuestFeatures);
390 VbglHGCMParmUInt64Set(&Msg.f64Features1, VBOX_GUESTCTRL_GF_1_MUST_BE_ONE);
391
392 rc = VbglR3HGCMCall(&Msg.Hdr, sizeof(Msg));
393 if (RT_SUCCESS(rc))
394 {
395 Assert(Msg.f64Features0.type == VMMDevHGCMParmType_64bit);
396 Assert(Msg.f64Features1.type == VMMDevHGCMParmType_64bit);
397 if (Msg.f64Features1.u.value64 & VBOX_GUESTCTRL_GF_1_MUST_BE_ONE)
398 rc = VERR_NOT_SUPPORTED;
399 else if (pfHostFeatures)
400 *pfHostFeatures = Msg.f64Features0.u.value64;
401 break;
402 }
403 } while (rc == VERR_INTERRUPTED);
404 return rc;
405
406}
407
408
409/**
410 * Queries the host features, internal version.
411 *
412 * @returns VBox status code.
413 * @param idClient The client ID returned by VbglR3GuestCtrlConnect().
414 * @param pfHostFeatures0 Where to store the host features, VBOX_GUESTCTRL_HF_0_XXX.
415 * Optional and can be NULL.
416 * @param pfHostFeatures1 Where to store the host features, VBOX_GUESTCTRL_HF_1_XXX.
417 * Currently unused. Optional and can be NULL.
418 */
419static int vbglR3GuestCtrlQueryFeatures(uint32_t idClient, uint64_t *pfHostFeatures0, uint64_t *pfHostFeatures1)
420{
421 int rc;
422 do
423 {
424 struct
425 {
426 VBGLIOCHGCMCALL Hdr;
427 HGCMFunctionParameter f64Features0;
428 HGCMFunctionParameter f64Features1;
429 } Msg;
430 VBGL_HGCM_HDR_INIT(&Msg.Hdr, idClient, GUEST_MSG_QUERY_FEATURES, 2);
431 VbglHGCMParmUInt64Set(&Msg.f64Features0, 0);
432 VbglHGCMParmUInt64Set(&Msg.f64Features1, RT_BIT_64(63));
433
434 rc = VbglR3HGCMCall(&Msg.Hdr, sizeof(Msg));
435 if (RT_SUCCESS(rc))
436 {
437 Assert(Msg.f64Features0.type == VMMDevHGCMParmType_64bit);
438 Assert(Msg.f64Features1.type == VMMDevHGCMParmType_64bit);
439 if (Msg.f64Features1.u.value64 & RT_BIT_64(63))
440 rc = VERR_NOT_SUPPORTED;
441 else
442 {
443 if (pfHostFeatures0)
444 *pfHostFeatures0 = Msg.f64Features0.u.value64;
445 if (pfHostFeatures1)
446 *pfHostFeatures1 = Msg.f64Features1.u.value64;
447 }
448 break;
449 }
450 } while (rc == VERR_INTERRUPTED);
451 return rc;
452}
453
454
455/**
456 * Queries the host features.
457 *
458 * @returns VBox status code.
459 * @param idClient The client ID returned by VbglR3GuestCtrlConnect().
460 * @param pfHostFeatures Where to store the host features, VBOX_GUESTCTRL_HF_0_XXX. Optional and can be NULL.
461 */
462VBGLR3DECL(int) VbglR3GuestCtrlQueryFeatures(uint32_t idClient, uint64_t *pfHostFeatures)
463{
464 return vbglR3GuestCtrlQueryFeatures(idClient, pfHostFeatures, NULL /* pfHostFeatures1, unused */);
465}
466
467
468/**
469 * Peeks at the next host message, waiting for one to turn up.
470 *
471 * @returns VBox status code.
472 * @retval VERR_INTERRUPTED if interrupted. Does the necessary cleanup, so
473 * caller just have to repeat this call.
474 * @retval VERR_VM_RESTORED if the VM has been restored (idRestoreCheck).
475 *
476 * @param idClient The client ID returned by VbglR3GuestCtrlConnect().
477 * @param pidMsg Where to store the message id.
478 * @param pcParameters Where to store the number of parameters which will
479 * be received in a second call to the host.
480 * @param pidRestoreCheck Pointer to the VbglR3GetSessionId() variable to use
481 * for the VM restore check. Optional.
482 *
483 * @note Restore check is only performed optimally with a 6.0 host.
484 */
485VBGLR3DECL(int) VbglR3GuestCtrlMsgPeekWait(uint32_t idClient, uint32_t *pidMsg, uint32_t *pcParameters, uint64_t *pidRestoreCheck)
486{
487 AssertPtrReturn(pidMsg, VERR_INVALID_POINTER);
488 AssertPtrReturn(pcParameters, VERR_INVALID_POINTER);
489
490 int rc;
491 if (vbglR3GuestCtrlSupportsPeekGetCancel(idClient))
492 {
493 struct
494 {
495 VBGLIOCHGCMCALL Hdr;
496 HGCMFunctionParameter idMsg; /* Doubles as restore check on input. */
497 HGCMFunctionParameter cParameters;
498 } Msg;
499 VBGL_HGCM_HDR_INIT(&Msg.Hdr, idClient, GUEST_MSG_PEEK_WAIT, 2);
500 VbglHGCMParmUInt64Set(&Msg.idMsg, pidRestoreCheck ? *pidRestoreCheck : 0);
501 VbglHGCMParmUInt32Set(&Msg.cParameters, 0);
502 rc = VbglR3HGCMCall(&Msg.Hdr, sizeof(Msg));
503 LogRel2(("VbglR3GuestCtrlMsgPeekWait -> %Rrc\n", rc));
504 if (RT_SUCCESS(rc))
505 {
506 AssertMsgReturn( Msg.idMsg.type == VMMDevHGCMParmType_64bit
507 && Msg.cParameters.type == VMMDevHGCMParmType_32bit,
508 ("msg.type=%d num_parms.type=%d\n", Msg.idMsg.type, Msg.cParameters.type),
509 VERR_INTERNAL_ERROR_3);
510
511 *pidMsg = (uint32_t)Msg.idMsg.u.value64;
512 *pcParameters = Msg.cParameters.u.value32;
513 return rc;
514 }
515
516 /*
517 * If interrupted we must cancel the call so it doesn't prevent us from making another one.
518 */
519 if (rc == VERR_INTERRUPTED)
520 {
521 VBGL_HGCM_HDR_INIT(&Msg.Hdr, idClient, GUEST_MSG_CANCEL, 0);
522 int rc2 = VbglR3HGCMCall(&Msg.Hdr, sizeof(Msg.Hdr));
523 AssertRC(rc2);
524 }
525
526 /*
527 * If restored, update pidRestoreCheck.
528 */
529 if (rc == VERR_VM_RESTORED && pidRestoreCheck)
530 *pidRestoreCheck = Msg.idMsg.u.value64;
531
532 *pidMsg = UINT32_MAX - 1;
533 *pcParameters = UINT32_MAX - 2;
534 return rc;
535 }
536
537 /*
538 * Fallback if host < v6.0.
539 *
540 * Note! The restore check isn't perfect. Would require checking afterwards
541 * and stash the result if we were restored during the call. Too much
542 * hazzle for a downgrade scenario.
543 */
544 if (pidRestoreCheck)
545 {
546 uint64_t idRestoreCur = *pidRestoreCheck;
547 rc = VbglR3GetSessionId(&idRestoreCur);
548 if (RT_SUCCESS(rc) && idRestoreCur != *pidRestoreCheck)
549 {
550 *pidRestoreCheck = idRestoreCur;
551 return VERR_VM_RESTORED;
552 }
553 }
554
555 rc = vbglR3GuestCtrlMsgWaitFor(idClient, pidMsg, pcParameters);
556 if (rc == VERR_TOO_MUCH_DATA)
557 rc = VINF_SUCCESS;
558 return rc;
559}
560
561
562/**
563 * Asks the host guest control service to set a message filter to this
564 * client so that it only will receive certain messages in the future.
565 * The filter(s) are a bitmask for the context IDs, served from the host.
566 *
567 * @return IPRT status code.
568 * @param idClient The client ID returned by VbglR3GuestCtrlConnect().
569 * @param uValue The value to filter messages for.
570 * @param uMaskAdd Filter mask to add.
571 * @param uMaskRemove Filter mask to remove.
572 */
573VBGLR3DECL(int) VbglR3GuestCtrlMsgFilterSet(uint32_t idClient, uint32_t uValue, uint32_t uMaskAdd, uint32_t uMaskRemove)
574{
575 HGCMMsgFilterSet Msg;
576
577 /* Tell the host we want to set a filter. */
578 VBGL_HGCM_HDR_INIT(&Msg.hdr, idClient, GUEST_MSG_FILTER_SET, 4);
579 VbglHGCMParmUInt32Set(&Msg.value, uValue);
580 VbglHGCMParmUInt32Set(&Msg.mask_add, uMaskAdd);
581 VbglHGCMParmUInt32Set(&Msg.mask_remove, uMaskRemove);
582 VbglHGCMParmUInt32Set(&Msg.flags, 0 /* Flags, unused */);
583
584 return VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
585}
586
587
588/**
589 * Replies to a message from the host.
590 *
591 * @returns VBox status code.
592 * @param pCtx Guest control command context to use.
593 * @param rc Guest rc to reply.
594 */
595VBGLR3DECL(int) VbglR3GuestCtrlMsgReply(PVBGLR3GUESTCTRLCMDCTX pCtx,
596 int rc)
597{
598 return VbglR3GuestCtrlMsgReplyEx(pCtx, rc, 0 /* uType */,
599 NULL /* pvPayload */, 0 /* cbPayload */);
600}
601
602
603/**
604 * Replies to a message from the host, extended version.
605 *
606 * @returns VBox status code.
607 * @param pCtx Guest control command context to use.
608 * @param rc Guest rc to reply.
609 * @param uType Reply type; not used yet and must be 0.
610 * @param pvPayload Pointer to data payload to reply. Optional.
611 * @param cbPayload Size of data payload (in bytes) to reply.
612 */
613VBGLR3DECL(int) VbglR3GuestCtrlMsgReplyEx(PVBGLR3GUESTCTRLCMDCTX pCtx,
614 int rc, uint32_t uType,
615 void *pvPayload, uint32_t cbPayload)
616{
617 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
618 /* Everything else is optional. */
619
620 HGCMMsgReply Msg;
621 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, GUEST_MSG_REPLY, 4);
622 VbglHGCMParmUInt32Set(&Msg.context, pCtx->uContextID);
623 VbglHGCMParmUInt32Set(&Msg.type, uType);
624 VbglHGCMParmUInt32Set(&Msg.rc, (uint32_t)rc); /* int vs. uint32_t */
625 VbglHGCMParmPtrSet(&Msg.payload, pvPayload, cbPayload);
626
627 return VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
628}
629
630/**
631 * Tell the host to skip the current message replying VERR_NOT_SUPPORTED
632 *
633 * @return IPRT status code.
634 * @param idClient The client ID returned by VbglR3GuestCtrlConnect().
635 * @param rcSkip The status code to pass back to Main when skipping.
636 * @param idMsg The message ID to skip, pass UINT32_MAX to pass any.
637 */
638VBGLR3DECL(int) VbglR3GuestCtrlMsgSkip(uint32_t idClient, int rcSkip, uint32_t idMsg)
639{
640 if (vbglR3GuestCtrlSupportsPeekGetCancel(idClient))
641 {
642 struct
643 {
644 VBGLIOCHGCMCALL Hdr;
645 HGCMFunctionParameter rcSkip;
646 HGCMFunctionParameter idMsg;
647 } Msg;
648 VBGL_HGCM_HDR_INIT(&Msg.Hdr, idClient, GUEST_MSG_SKIP, 2);
649 VbglHGCMParmUInt32Set(&Msg.rcSkip, (uint32_t)rcSkip);
650 VbglHGCMParmUInt32Set(&Msg.idMsg, idMsg);
651 return VbglR3HGCMCall(&Msg.Hdr, sizeof(Msg));
652 }
653
654 /* This is generally better than nothing... */
655 return VbglR3GuestCtrlMsgSkipOld(idClient);
656}
657
658
659/**
660 * Tells the host service to skip the current message returned by
661 * VbglR3GuestCtrlMsgWaitFor().
662 *
663 * @return IPRT status code.
664 * @param idClient The client ID returned by VbglR3GuestCtrlConnect().
665 */
666VBGLR3DECL(int) VbglR3GuestCtrlMsgSkipOld(uint32_t idClient)
667{
668 HGCMMsgSkip Msg;
669
670 /* Tell the host we want to skip the current assigned message. */
671 VBGL_HGCM_HDR_INIT(&Msg.hdr, idClient, GUEST_MSG_SKIP_OLD, 1);
672 VbglHGCMParmUInt32Set(&Msg.flags, 0 /* Flags, unused */);
673 return VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
674}
675
676
677/**
678 * Asks the host to cancel (release) all pending waits which were deferred.
679 *
680 * @returns VBox status code.
681 * @param idClient The client ID returned by VbglR3GuestCtrlConnect().
682 */
683VBGLR3DECL(int) VbglR3GuestCtrlCancelPendingWaits(uint32_t idClient)
684{
685 HGCMMsgCancelPendingWaits Msg;
686 VBGL_HGCM_HDR_INIT(&Msg.hdr, idClient, GUEST_MSG_CANCEL, 0);
687 return VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
688}
689
690
691/**
692 * Prepares a session.
693 * @since 6.0
694 * @sa GUEST_SESSION_PREPARE
695 */
696VBGLR3DECL(int) VbglR3GuestCtrlSessionPrepare(uint32_t idClient, uint32_t idSession, void const *pvKey, uint32_t cbKey)
697{
698 int rc;
699 do
700 {
701 struct
702 {
703 VBGLIOCHGCMCALL Hdr;
704 HGCMFunctionParameter idSession;
705 HGCMFunctionParameter pKey;
706 } Msg;
707 VBGL_HGCM_HDR_INIT(&Msg.Hdr, idClient, GUEST_MSG_SESSION_PREPARE, 2);
708 VbglHGCMParmUInt32Set(&Msg.idSession, idSession);
709 VbglHGCMParmPtrSet(&Msg.pKey, (void *)pvKey, cbKey);
710 rc = VbglR3HGCMCall(&Msg.Hdr, sizeof(Msg));
711 } while (rc == VERR_INTERRUPTED);
712 return rc;
713}
714
715
716/**
717 * Accepts a session.
718 * @since 6.0
719 * @sa GUEST_SESSION_ACCEPT
720 */
721VBGLR3DECL(int) VbglR3GuestCtrlSessionAccept(uint32_t idClient, uint32_t idSession, void const *pvKey, uint32_t cbKey)
722{
723 int rc;
724 do
725 {
726 struct
727 {
728 VBGLIOCHGCMCALL Hdr;
729 HGCMFunctionParameter idSession;
730 HGCMFunctionParameter pKey;
731 } Msg;
732 VBGL_HGCM_HDR_INIT(&Msg.Hdr, idClient, GUEST_MSG_SESSION_ACCEPT, 2);
733 VbglHGCMParmUInt32Set(&Msg.idSession, idSession);
734 VbglHGCMParmPtrSet(&Msg.pKey, (void *)pvKey, cbKey);
735 rc = VbglR3HGCMCall(&Msg.Hdr, sizeof(Msg));
736 } while (rc == VERR_INTERRUPTED);
737 return rc;
738}
739
740
741/**
742 * Cancels a prepared session.
743 * @since 6.0
744 * @sa GUEST_SESSION_CANCEL_PREPARED
745 */
746VBGLR3DECL(int) VbglR3GuestCtrlSessionCancelPrepared(uint32_t idClient, uint32_t idSession)
747{
748 int rc;
749 do
750 {
751 struct
752 {
753 VBGLIOCHGCMCALL Hdr;
754 HGCMFunctionParameter idSession;
755 } Msg;
756 VBGL_HGCM_HDR_INIT(&Msg.Hdr, idClient, GUEST_MSG_SESSION_CANCEL_PREPARED, 1);
757 VbglHGCMParmUInt32Set(&Msg.idSession, idSession);
758 rc = VbglR3HGCMCall(&Msg.Hdr, sizeof(Msg));
759 } while (rc == VERR_INTERRUPTED);
760 return rc;
761}
762
763
764/**
765 * Invalidates the internal state because the (VM) session has been changed (i.e. restored).
766 *
767 * @returns VBox status code.
768 * @param idClient Client ID to use for invalidating state.
769 * @param idNewControlSession New control session ID. Currently unused.
770 */
771VBGLR3DECL(int) VbglR3GuestCtrlSessionHasChanged(uint32_t idClient, uint64_t idNewControlSession)
772{
773 RT_NOREF(idNewControlSession);
774
775 vbglR3GuestCtrlDetectPeekGetCancelSupport(idClient);
776
777 return VINF_SUCCESS;
778}
779
780
781/**
782 * Asks a specific guest session to close.
783 *
784 * @return IPRT status code.
785 * @param pCtx Guest control command context to use.
786 * @param fFlags Some kind of flag. Figure it out yourself.
787 */
788VBGLR3DECL(int) VbglR3GuestCtrlSessionClose(PVBGLR3GUESTCTRLCMDCTX pCtx, uint32_t fFlags)
789{
790 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
791 AssertReturn(pCtx->uNumParms == 2, VERR_INVALID_PARAMETER);
792
793 HGCMMsgSessionClose Msg;
794 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, GUEST_MSG_SESSION_CLOSE, pCtx->uNumParms);
795 VbglHGCMParmUInt32Set(&Msg.context, pCtx->uContextID);
796 VbglHGCMParmUInt32Set(&Msg.flags, fFlags);
797
798 return VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
799}
800
801
802/**
803 * Notifies a guest session.
804 *
805 * @returns VBox status code.
806 * @param pCtx Guest control command context to use.
807 * @param uType Notification type of type GUEST_SESSION_NOTIFYTYPE_XXX.
808 * @param iResult Result code (rc) to notify.
809 */
810VBGLR3DECL(int) VbglR3GuestCtrlSessionNotify(PVBGLR3GUESTCTRLCMDCTX pCtx, uint32_t uType, int32_t iResult)
811{
812 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
813
814 HGCMMsgSessionNotify Msg;
815 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, GUEST_MSG_SESSION_NOTIFY, 3);
816 VbglHGCMParmUInt32Set(&Msg.context, pCtx->uContextID);
817 VbglHGCMParmUInt32Set(&Msg.type, uType);
818 VbglHGCMParmUInt32Set(&Msg.result, (uint32_t)iResult);
819
820 return VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
821}
822
823/**
824 * Initializes a session startup info, extended version.
825 *
826 * @returns VBox status code.
827 * @param pStartupInfo Session startup info to initializes.
828 * @param cbUser Size (in bytes) to use for the user name buffer.
829 * @param cbPassword Size (in bytes) to use for the password buffer.
830 * @param cbDomain Size (in bytes) to use for the domain name buffer.
831 */
832VBGLR3DECL(int) VbglR3GuestCtrlSessionStartupInfoInitEx(PVBGLR3GUESTCTRLSESSIONSTARTUPINFO pStartupInfo,
833 size_t cbUser, size_t cbPassword, size_t cbDomain)
834{
835 AssertPtrReturn(pStartupInfo, VERR_INVALID_POINTER);
836
837 RT_BZERO(pStartupInfo, sizeof(VBGLR3GUESTCTRLSESSIONSTARTUPINFO));
838
839#define ALLOC_STR(a_Str, a_cb) \
840 if ((a_cb) > 0) \
841 { \
842 pStartupInfo->psz##a_Str = RTStrAlloc(a_cb); \
843 AssertPtrBreak(pStartupInfo->psz##a_Str); \
844 pStartupInfo->cb##a_Str = (uint32_t)a_cb; \
845 }
846
847 do
848 {
849 ALLOC_STR(User, cbUser);
850 ALLOC_STR(Password, cbPassword);
851 ALLOC_STR(Domain, cbDomain);
852
853 return VINF_SUCCESS;
854
855 } while (0);
856
857#undef ALLOC_STR
858
859 VbglR3GuestCtrlSessionStartupInfoDestroy(pStartupInfo);
860 return VERR_NO_MEMORY;
861}
862
863/**
864 * Initializes a session startup info.
865 *
866 * @returns VBox status code.
867 * @param pStartupInfo Session startup info to initializes.
868 */
869VBGLR3DECL(int) VbglR3GuestCtrlSessionStartupInfoInit(PVBGLR3GUESTCTRLSESSIONSTARTUPINFO pStartupInfo)
870{
871 return VbglR3GuestCtrlSessionStartupInfoInitEx(pStartupInfo,
872 GUEST_PROC_DEF_USER_LEN, GUEST_PROC_DEF_PASSWORD_LEN,
873 GUEST_PROC_DEF_DOMAIN_LEN);
874}
875
876/**
877 * Destroys a session startup info.
878 *
879 * @param pStartupInfo Session startup info to destroy.
880 */
881VBGLR3DECL(void) VbglR3GuestCtrlSessionStartupInfoDestroy(PVBGLR3GUESTCTRLSESSIONSTARTUPINFO pStartupInfo)
882{
883 if (!pStartupInfo)
884 return;
885
886 RTStrFree(pStartupInfo->pszUser);
887 RTStrFree(pStartupInfo->pszPassword);
888 RTStrFree(pStartupInfo->pszDomain);
889
890 RT_BZERO(pStartupInfo, sizeof(VBGLR3GUESTCTRLSESSIONSTARTUPINFO));
891}
892
893/**
894 * Free's a session startup info.
895 *
896 * @param pStartupInfo Session startup info to free.
897 * The pointer will not be valid anymore after return.
898 */
899VBGLR3DECL(void) VbglR3GuestCtrlSessionStartupInfoFree(PVBGLR3GUESTCTRLSESSIONSTARTUPINFO pStartupInfo)
900{
901 if (!pStartupInfo)
902 return;
903
904 VbglR3GuestCtrlSessionStartupInfoDestroy(pStartupInfo);
905
906 RTMemFree(pStartupInfo);
907}
908
909/**
910 * Duplicates a session startup info.
911 *
912 * @returns Duplicated session startup info on success, or NULL on error.
913 * @param pStartupInfo Session startup info to duplicate.
914 */
915VBGLR3DECL(PVBGLR3GUESTCTRLSESSIONSTARTUPINFO) VbglR3GuestCtrlSessionStartupInfoDup(PVBGLR3GUESTCTRLSESSIONSTARTUPINFO pStartupInfo)
916{
917 AssertPtrReturn(pStartupInfo, NULL);
918
919 PVBGLR3GUESTCTRLSESSIONSTARTUPINFO pStartupInfoDup = (PVBGLR3GUESTCTRLSESSIONSTARTUPINFO)
920 RTMemDup(pStartupInfo, sizeof(VBGLR3GUESTCTRLSESSIONSTARTUPINFO));
921 if (pStartupInfoDup)
922 {
923 do
924 {
925 pStartupInfoDup->pszUser = NULL;
926 pStartupInfoDup->pszPassword = NULL;
927 pStartupInfoDup->pszDomain = NULL;
928
929#define DUP_STR(a_Str) \
930 if (pStartupInfo->cb##a_Str) \
931 { \
932 pStartupInfoDup->psz##a_Str = (char *)RTStrDup(pStartupInfo->psz##a_Str); \
933 AssertPtrBreak(pStartupInfoDup->psz##a_Str); \
934 pStartupInfoDup->cb##a_Str = (uint32_t)strlen(pStartupInfoDup->psz##a_Str) + 1 /* Include terminator */; \
935 }
936 DUP_STR(User);
937 DUP_STR(Password);
938 DUP_STR(Domain);
939
940#undef DUP_STR
941
942 return pStartupInfoDup;
943
944 } while (0); /* To use break macros above. */
945
946 VbglR3GuestCtrlSessionStartupInfoFree(pStartupInfoDup);
947 }
948
949 return NULL;
950}
951
952/**
953 * Retrieves a HOST_SESSION_CREATE message.
954 *
955 * @returns VBox status code.
956 * @param pCtx Guest control command context to use.
957 * @param ppStartupInfo Where to store the allocated session startup info.
958 * Needs to be free'd by VbglR3GuestCtrlSessionStartupInfoFree().
959 */
960VBGLR3DECL(int) VbglR3GuestCtrlSessionGetOpen(PVBGLR3GUESTCTRLCMDCTX pCtx, PVBGLR3GUESTCTRLSESSIONSTARTUPINFO *ppStartupInfo)
961{
962 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
963 AssertReturn(pCtx->uNumParms == 6, VERR_INVALID_PARAMETER);
964 AssertPtrReturn(ppStartupInfo, VERR_INVALID_POINTER);
965
966 PVBGLR3GUESTCTRLSESSIONSTARTUPINFO pStartupInfo
967 = (PVBGLR3GUESTCTRLSESSIONSTARTUPINFO)RTMemAlloc(sizeof(VBGLR3GUESTCTRLSESSIONSTARTUPINFO));
968 if (!pStartupInfo)
969 return VERR_NO_MEMORY;
970
971 int rc = VbglR3GuestCtrlSessionStartupInfoInit(pStartupInfo);
972 if (RT_FAILURE(rc))
973 {
974 VbglR3GuestCtrlSessionStartupInfoFree(pStartupInfo);
975 return rc;
976 }
977
978 do
979 {
980 HGCMMsgSessionOpen Msg;
981 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, vbglR3GuestCtrlGetMsgFunctionNo(pCtx->uClientID), pCtx->uNumParms);
982 VbglHGCMParmUInt32Set(&Msg.context, HOST_MSG_SESSION_CREATE);
983 VbglHGCMParmUInt32Set(&Msg.protocol, 0);
984 VbglHGCMParmPtrSet(&Msg.username, pStartupInfo->pszUser, pStartupInfo->cbUser);
985 VbglHGCMParmPtrSet(&Msg.password, pStartupInfo->pszPassword, pStartupInfo->cbPassword);
986 VbglHGCMParmPtrSet(&Msg.domain, pStartupInfo->pszDomain, pStartupInfo->cbDomain);
987 VbglHGCMParmUInt32Set(&Msg.flags, 0);
988
989 rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
990 if (RT_SUCCESS(rc))
991 {
992 Msg.context.GetUInt32(&pCtx->uContextID);
993 Msg.protocol.GetUInt32(&pStartupInfo->uProtocol);
994 Msg.flags.GetUInt32(&pStartupInfo->fFlags);
995
996 pStartupInfo->uSessionID = VBOX_GUESTCTRL_CONTEXTID_GET_SESSION(pCtx->uContextID);
997 }
998
999 } while (rc == VERR_INTERRUPTED && g_fVbglR3GuestCtrlHavePeekGetCancel);
1000
1001 if (RT_SUCCESS(rc))
1002 {
1003 *ppStartupInfo = pStartupInfo;
1004 }
1005 else
1006 VbglR3GuestCtrlSessionStartupInfoFree(pStartupInfo);
1007
1008 LogFlowFuncLeaveRC(rc);
1009 return rc;
1010}
1011
1012
1013/**
1014 * Retrieves a HOST_SESSION_CLOSE message.
1015 */
1016VBGLR3DECL(int) VbglR3GuestCtrlSessionGetClose(PVBGLR3GUESTCTRLCMDCTX pCtx, uint32_t *pfFlags, uint32_t *pidSession)
1017{
1018 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1019 AssertReturn(pCtx->uNumParms == 2, VERR_INVALID_PARAMETER);
1020
1021 AssertPtrReturn(pfFlags, VERR_INVALID_POINTER);
1022
1023 int rc;
1024 do
1025 {
1026 HGCMMsgSessionClose Msg;
1027 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, vbglR3GuestCtrlGetMsgFunctionNo(pCtx->uClientID), pCtx->uNumParms);
1028 VbglHGCMParmUInt32Set(&Msg.context, HOST_MSG_SESSION_CLOSE);
1029 VbglHGCMParmUInt32Set(&Msg.flags, 0);
1030
1031 rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
1032 if (RT_SUCCESS(rc))
1033 {
1034 Msg.context.GetUInt32(&pCtx->uContextID);
1035 Msg.flags.GetUInt32(pfFlags);
1036
1037 if (pidSession)
1038 *pidSession = VBOX_GUESTCTRL_CONTEXTID_GET_SESSION(pCtx->uContextID);
1039 }
1040 } while (rc == VERR_INTERRUPTED && g_fVbglR3GuestCtrlHavePeekGetCancel);
1041 return rc;
1042}
1043
1044
1045#ifdef VBOX_WITH_GSTCTL_TOOLBOX_AS_CMDS
1046/**
1047 * Retrieves a HOST_MSG_DIR_OPEN message.
1048 *
1049 * @returns VBox status code.
1050 * @param pCtx Guest control command context to use.
1051 * @param pszPath Where to return the directory path to open.
1052 * @param cbPath Size (in bytes) of \a pszPath.
1053 * @param pfFlags Where to return the directory listing flags.
1054 * @param enmFilter Where to return the directory filter type.
1055 * @param penmAttrAdd Where to return the additional attributes enumeration to use for reading directory entries later.
1056 * @param pfReadFlags Where to return the flags for reading directory entries later.
1057 */
1058VBGLR3DECL(int) VbglR3GuestCtrlDirGetOpen(PVBGLR3GUESTCTRLCMDCTX pCtx, char *pszPath, uint32_t cbPath, uint32_t *pfFlags,
1059 GSTCTLDIRFILTER *penmFilter, GSTCTLFSOBJATTRADD *penmReadAttrAdd, uint32_t *pfReadFlags)
1060{
1061 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1062 AssertReturn(pCtx->uNumParms == 6, VERR_INVALID_PARAMETER);
1063
1064 AssertPtrReturn(pszPath, VERR_INVALID_POINTER);
1065 AssertReturn(cbPath, VERR_INVALID_PARAMETER);
1066 AssertPtrReturn(pfFlags, VERR_INVALID_POINTER);
1067 AssertPtrReturn(penmFilter, VERR_INVALID_POINTER);
1068 AssertPtrReturn(penmReadAttrAdd, VERR_INVALID_POINTER);
1069 AssertPtrReturn(pfReadFlags, VERR_INVALID_POINTER);
1070
1071 int rc;
1072 do
1073 {
1074 HGCMMsgDirOpen Msg;
1075 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, vbglR3GuestCtrlGetMsgFunctionNo(pCtx->uClientID), pCtx->uNumParms);
1076 VbglHGCMParmUInt32Set(&Msg.context, HOST_MSG_DIR_OPEN);
1077 VbglHGCMParmPtrSet(&Msg.path, pszPath, cbPath);
1078 VbglHGCMParmUInt32Set(&Msg.filter, 0);
1079 VbglHGCMParmUInt32Set(&Msg.flags, 0);
1080 VbglHGCMParmUInt32Set(&Msg.read_attr_add, 0);
1081 VbglHGCMParmUInt32Set(&Msg.read_flags, 0);
1082
1083 rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
1084 if (RT_SUCCESS(rc))
1085 {
1086 Msg.context.GetUInt32(&pCtx->uContextID);
1087 Msg.filter.GetUInt32((uint32_t *)penmFilter);
1088 Msg.flags.GetUInt32(pfFlags);
1089 Msg.read_attr_add.GetUInt32((uint32_t *)penmReadAttrAdd);
1090 Msg.read_flags.GetUInt32(pfReadFlags);
1091 }
1092 } while (rc == VERR_INTERRUPTED && g_fVbglR3GuestCtrlHavePeekGetCancel);
1093 return rc;
1094}
1095
1096
1097/**
1098 * Retrieves a HOST_MSG_DIR_CLOSE message.
1099 *
1100 * @returns VBox status code.
1101 * @param pCtx Guest control command context to use.
1102 * @param puHandle Where to return the handle of the guest directory to close.
1103 */
1104VBGLR3DECL(int) VbglR3GuestCtrlDirGetClose(PVBGLR3GUESTCTRLCMDCTX pCtx, uint32_t *puHandle)
1105{
1106 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1107 AssertReturn(pCtx->uNumParms == 2, VERR_INVALID_PARAMETER);
1108
1109 AssertPtrReturn(puHandle, VERR_INVALID_POINTER);
1110
1111 int rc;
1112 do
1113 {
1114 HGCMMsgDirClose Msg;
1115 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, vbglR3GuestCtrlGetMsgFunctionNo(pCtx->uClientID), pCtx->uNumParms);
1116 VbglHGCMParmUInt32Set(&Msg.context, HOST_MSG_DIR_CLOSE);
1117 VbglHGCMParmUInt32Set(&Msg.handle, 0);
1118
1119 rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
1120 if (RT_SUCCESS(rc))
1121 {
1122 Msg.context.GetUInt32(&pCtx->uContextID);
1123 Msg.handle.GetUInt32(puHandle);
1124 }
1125 } while (rc == VERR_INTERRUPTED && g_fVbglR3GuestCtrlHavePeekGetCancel);
1126 return rc;
1127}
1128
1129
1130/**
1131 * Retrieves a HOST_MSG_DIR_READ message.
1132 *
1133 * @returns VBox status code.
1134 * @param pCtx Guest control command context to use.
1135 * @param puHandle Where to return the directory handle to rewind.
1136 */
1137VBGLR3DECL(int) VbglR3GuestCtrlDirGetRead(PVBGLR3GUESTCTRLCMDCTX pCtx, uint32_t *puHandle)
1138{
1139 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1140 AssertReturn(pCtx->uNumParms == 2, VERR_INVALID_PARAMETER);
1141
1142 AssertPtrReturn(puHandle, VERR_INVALID_POINTER);
1143
1144 int rc;
1145 do
1146 {
1147 HGCMMsgDirRead Msg;
1148 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, vbglR3GuestCtrlGetMsgFunctionNo(pCtx->uClientID), pCtx->uNumParms);
1149 VbglHGCMParmUInt32Set(&Msg.context, HOST_MSG_DIR_READ);
1150 VbglHGCMParmUInt32Set(&Msg.handle, 0);
1151
1152 rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
1153 if (RT_SUCCESS(rc))
1154 {
1155 Msg.context.GetUInt32(&pCtx->uContextID);
1156 Msg.handle.GetUInt32(puHandle);
1157 }
1158 } while (rc == VERR_INTERRUPTED && g_fVbglR3GuestCtrlHavePeekGetCancel);
1159 return rc;
1160}
1161
1162
1163/**
1164 * Retrieves a HOST_MSG_DIR_REWIND message.
1165 *
1166 * @returns VBox status code.
1167 * @param pCtx Guest control command context to use.
1168 * @param puHandle Where to return the directory handle to rewind.
1169 */
1170VBGLR3DECL(int) VbglR3GuestCtrlDirGetRewind(PVBGLR3GUESTCTRLCMDCTX pCtx, uint32_t *puHandle)
1171{
1172 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1173 AssertReturn(pCtx->uNumParms == 2, VERR_INVALID_PARAMETER);
1174
1175 AssertPtrReturn(puHandle, VERR_INVALID_POINTER);
1176
1177 int rc;
1178 do
1179 {
1180 HGCMMsgDirRewind Msg;
1181 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, vbglR3GuestCtrlGetMsgFunctionNo(pCtx->uClientID), pCtx->uNumParms);
1182 VbglHGCMParmUInt32Set(&Msg.context, HOST_MSG_DIR_REWIND);
1183 VbglHGCMParmUInt32Set(&Msg.handle, 0);
1184
1185 rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
1186 if (RT_SUCCESS(rc))
1187 {
1188 Msg.context.GetUInt32(&pCtx->uContextID);
1189 Msg.handle.GetUInt32(puHandle);
1190 }
1191 } while (rc == VERR_INTERRUPTED && g_fVbglR3GuestCtrlHavePeekGetCancel);
1192 return rc;
1193}
1194
1195
1196/**
1197 * Retrieves a HOST_MSG_DIR_LIST message.
1198 *
1199 * @returns VBox status code.
1200 * @param pCtx Guest control command context to use.
1201 * @param puHandle Where to return the directory handle to rewind.
1202 * @param pcEntries Where to return the number of directory entries to read.
1203 * @param pfFlags Where to return the directory listing flags.
1204 */
1205VBGLR3DECL(int) VbglR3GuestCtrlDirGetList(PVBGLR3GUESTCTRLCMDCTX pCtx, uint32_t *puHandle, uint32_t *pcEntries, uint32_t *pfFlags)
1206{
1207 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1208 AssertReturn(pCtx->uNumParms == 4, VERR_INVALID_PARAMETER);
1209
1210 AssertPtrReturn(puHandle, VERR_INVALID_POINTER);
1211 AssertPtrReturn(pcEntries, VERR_INVALID_POINTER);
1212 AssertPtrReturn(pfFlags, VERR_INVALID_POINTER);
1213
1214 int rc;
1215 do
1216 {
1217 HGCMMsgDirList Msg;
1218 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, vbglR3GuestCtrlGetMsgFunctionNo(pCtx->uClientID), pCtx->uNumParms);
1219 VbglHGCMParmUInt32Set(&Msg.context, HOST_MSG_DIR_LIST);
1220 VbglHGCMParmUInt32Set(&Msg.handle, 0);
1221 VbglHGCMParmUInt32Set(&Msg.num_entries, 0);
1222 VbglHGCMParmUInt32Set(&Msg.flags, 0);
1223
1224 rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
1225 if (RT_SUCCESS(rc))
1226 {
1227 Msg.context.GetUInt32(&pCtx->uContextID);
1228 Msg.handle.GetUInt32(puHandle);
1229 Msg.num_entries.GetUInt32(pcEntries);
1230 Msg.flags.GetUInt32(pfFlags);
1231 }
1232 } while (rc == VERR_INTERRUPTED && g_fVbglR3GuestCtrlHavePeekGetCancel);
1233 return rc;
1234}
1235#endif /* VBOX_WITH_GSTCTL_TOOLBOX_AS_CMDS */
1236
1237
1238/**
1239 * Retrieves a HOST_PATH_RENAME message.
1240 *
1241 * @returns VBox status code.
1242 * @param pCtx Guest control command context to use.
1243 * @param pszSource Where to return the source path.
1244 * @param cbSource Size (in bytes) of \a pszSource.
1245 * @param pszDest Where to return the destination path.
1246 * @param cbDest Size (in bytes) of \a pszDest.
1247 * @param pfFlags Where to return the rename flags.
1248 */
1249VBGLR3DECL(int) VbglR3GuestCtrlPathGetRename(PVBGLR3GUESTCTRLCMDCTX pCtx,
1250 char *pszSource, uint32_t cbSource,
1251 char *pszDest, uint32_t cbDest,
1252 uint32_t *pfFlags)
1253{
1254 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1255 AssertReturn(pCtx->uNumParms == 4, VERR_INVALID_PARAMETER);
1256
1257 AssertPtrReturn(pszSource, VERR_INVALID_POINTER);
1258 AssertReturn(cbSource, VERR_INVALID_PARAMETER);
1259 AssertPtrReturn(pszDest, VERR_INVALID_POINTER);
1260 AssertReturn(cbDest, VERR_INVALID_PARAMETER);
1261 AssertPtrReturn(pfFlags, VERR_INVALID_POINTER);
1262
1263 int rc;
1264 do
1265 {
1266 HGCMMsgPathRename Msg;
1267 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, vbglR3GuestCtrlGetMsgFunctionNo(pCtx->uClientID), pCtx->uNumParms);
1268 VbglHGCMParmUInt32Set(&Msg.context, HOST_MSG_PATH_RENAME);
1269 VbglHGCMParmPtrSet(&Msg.source, pszSource, cbSource);
1270 VbglHGCMParmPtrSet(&Msg.dest, pszDest, cbDest);
1271 VbglHGCMParmUInt32Set(&Msg.flags, 0);
1272
1273 rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
1274 if (RT_SUCCESS(rc))
1275 {
1276 Msg.context.GetUInt32(&pCtx->uContextID);
1277 Msg.flags.GetUInt32(pfFlags);
1278 }
1279
1280 } while (rc == VERR_INTERRUPTED && g_fVbglR3GuestCtrlHavePeekGetCancel);
1281 return rc;
1282}
1283
1284
1285/**
1286 * Retrieves a HOST_PATH_USER_DOCUMENTS message.
1287 *
1288 * @param pCtx Guest control command context to use.
1289 */
1290VBGLR3DECL(int) VbglR3GuestCtrlPathGetUserDocuments(PVBGLR3GUESTCTRLCMDCTX pCtx)
1291{
1292 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1293 AssertReturn(pCtx->uNumParms == 1, VERR_INVALID_PARAMETER);
1294
1295 int rc;
1296 do
1297 {
1298 HGCMMsgPathUserDocuments Msg;
1299 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, vbglR3GuestCtrlGetMsgFunctionNo(pCtx->uClientID), pCtx->uNumParms);
1300 VbglHGCMParmUInt32Set(&Msg.context, HOST_MSG_PATH_USER_DOCUMENTS);
1301
1302 rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
1303 if (RT_SUCCESS(rc))
1304 Msg.context.GetUInt32(&pCtx->uContextID);
1305 } while (rc == VERR_INTERRUPTED && g_fVbglR3GuestCtrlHavePeekGetCancel);
1306 return rc;
1307}
1308
1309
1310/**
1311 * Retrieves a HOST_PATH_USER_HOME message.
1312 *
1313 * @param pCtx Guest control command context to use.
1314 */
1315VBGLR3DECL(int) VbglR3GuestCtrlPathGetUserHome(PVBGLR3GUESTCTRLCMDCTX pCtx)
1316{
1317 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1318 AssertReturn(pCtx->uNumParms == 1, VERR_INVALID_PARAMETER);
1319
1320 int rc;
1321 do
1322 {
1323 HGCMMsgPathUserHome Msg;
1324 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, vbglR3GuestCtrlGetMsgFunctionNo(pCtx->uClientID), pCtx->uNumParms);
1325 VbglHGCMParmUInt32Set(&Msg.context, HOST_MSG_PATH_USER_HOME);
1326
1327 rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
1328 if (RT_SUCCESS(rc))
1329 Msg.context.GetUInt32(&pCtx->uContextID);
1330 } while (rc == VERR_INTERRUPTED && g_fVbglR3GuestCtrlHavePeekGetCancel);
1331 return rc;
1332}
1333
1334
1335/**
1336 * Retrieves a HOST_MSG_MOUNT_POINTS message.
1337 *
1338 * @param pCtx Guest control command context to use.
1339 * @param pfFlags Where to return the get mount point flags on success.
1340 */
1341VBGLR3DECL(int) VbglR3GuestCtrlGetMountPoints(PVBGLR3GUESTCTRLCMDCTX pCtx, uint32_t *pfFlags)
1342{
1343 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1344 AssertReturn(pCtx->uNumParms == 2, VERR_INVALID_PARAMETER);
1345 AssertPtrReturn(pfFlags, VERR_INVALID_POINTER);
1346
1347 int rc;
1348 do
1349 {
1350 HGCMMsgMountPoints Msg;
1351 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, vbglR3GuestCtrlGetMsgFunctionNo(pCtx->uClientID), pCtx->uNumParms);
1352 VbglHGCMParmUInt32Set(&Msg.context, HOST_MSG_MOUNT_POINTS);
1353 VbglHGCMParmUInt32Set(&Msg.flags, 0);
1354
1355 rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
1356 if (RT_SUCCESS(rc))
1357 {
1358 Msg.context.GetUInt32(&pCtx->uContextID);
1359 Msg.flags.GetUInt32(pfFlags);
1360 }
1361 } while (rc == VERR_INTERRUPTED && g_fVbglR3GuestCtrlHavePeekGetCancel);
1362 return rc;
1363}
1364
1365
1366#ifdef VBOX_WITH_GSTCTL_TOOLBOX_AS_CMDS
1367/**
1368 * Retrieves a HOST_MSG_FS_QUERY_INFO message.
1369 *
1370 * @returns VBox status code.
1371 * @param pCtx Guest control command context to use.
1372 * @param pszPath Where to return the path of the file system object to query.
1373 * @param cbPath Size (in bytes) of \a pszPath.
1374 */
1375VBGLR3DECL(int) VbglR3GuestCtrlFsGetQueryInfo(PVBGLR3GUESTCTRLCMDCTX pCtx, char *pszPath, uint32_t cbPath)
1376{
1377 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1378
1379 AssertPtrReturn(pszPath, VERR_INVALID_POINTER);
1380 AssertReturn(cbPath, VERR_INVALID_PARAMETER);
1381
1382 int rc;
1383 do
1384 {
1385 HGCMMsgFsQueryInfo Msg;
1386 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, vbglR3GuestCtrlGetMsgFunctionNo(pCtx->uClientID), pCtx->uNumParms);
1387 VbglHGCMParmUInt32Set(&Msg.context, HOST_MSG_FS_QUERY_INFO);
1388 VbglHGCMParmPtrSet(&Msg.path, pszPath, cbPath);
1389
1390 rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
1391 if (RT_SUCCESS(rc))
1392 Msg.context.GetUInt32(&pCtx->uContextID);
1393
1394 } while (rc == VERR_INTERRUPTED && g_fVbglR3GuestCtrlHavePeekGetCancel);
1395 return rc;
1396}
1397
1398/**
1399 * Retrieves a HOST_MSG_FS_OBJ_QUERY_INFO message.
1400 *
1401 * @returns VBox status code.
1402 * @param pCtx Guest control command context to use.
1403 * @param pszPath Where to return the path of the file system object to query.
1404 * @param cbPath Size (in bytes) of \a pszPath.
1405 * @param penmAddAttrib Where to return the additional attributes enumeration.
1406 * @param pfFlags Where to return the flags for .
1407 */
1408VBGLR3DECL(int) VbglR3GuestCtrlFsObjGetQueryInfo(PVBGLR3GUESTCTRLCMDCTX pCtx,
1409 char *pszPath, uint32_t cbPath, GSTCTLFSOBJATTRADD *penmAddAttrib,
1410 uint32_t *pfFlags)
1411{
1412 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1413 AssertReturn(pCtx->uNumParms == 4, VERR_INVALID_PARAMETER);
1414
1415 AssertPtrReturn(pszPath, VERR_INVALID_POINTER);
1416 AssertReturn(cbPath, VERR_INVALID_PARAMETER);
1417 AssertPtrReturn(penmAddAttrib, VERR_INVALID_POINTER);
1418 AssertPtrReturn(pfFlags, VERR_INVALID_POINTER);
1419
1420 int rc;
1421 do
1422 {
1423 HGCMMsgFsObjQueryInfo Msg;
1424 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, vbglR3GuestCtrlGetMsgFunctionNo(pCtx->uClientID), pCtx->uNumParms);
1425 VbglHGCMParmUInt32Set(&Msg.context, HOST_MSG_FS_OBJ_QUERY_INFO);
1426 VbglHGCMParmPtrSet(&Msg.path, pszPath, cbPath);
1427 VbglHGCMParmUInt32Set(&Msg.add_attributes, 0);
1428 VbglHGCMParmUInt32Set(&Msg.flags, 0);
1429
1430 rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
1431 if (RT_SUCCESS(rc))
1432 {
1433 Msg.context.GetUInt32(&pCtx->uContextID);
1434 Msg.add_attributes.GetUInt32((uint32_t *)penmAddAttrib);
1435 Msg.flags.GetUInt32(pfFlags);
1436 }
1437
1438 } while (rc == VERR_INTERRUPTED && g_fVbglR3GuestCtrlHavePeekGetCancel);
1439 return rc;
1440}
1441
1442
1443/**
1444 * Retrieves a HOST_MSG_FS_CREATE_TEMP message.
1445 *
1446 * @returns VBox status code.
1447 * @param pCtx Guest control command context to use.
1448 * @param pszTemplate Where to return the template name.
1449 * @param cbTemplate Size (in bytes) of \a pszTemplate.
1450 * @param pszPath Where to return the temporary directory path.
1451 * @param cbTemplate Size (in bytes) of \a pszPath.
1452 * @param pfFlags Where to return the creation flags.
1453 * @param pfMode Where to return the creation mode.
1454 */
1455VBGLR3DECL(int) VbglR3GuestCtrlFsGetCreateTemp(PVBGLR3GUESTCTRLCMDCTX pCtx,
1456 char *pszTemplate, uint32_t cbTemplate, char *pszPath, uint32_t cbPath,
1457 uint32_t *pfFlags, uint32_t *pfMode)
1458{
1459 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1460 AssertReturn(pCtx->uNumParms == 5, VERR_INVALID_PARAMETER);
1461
1462 AssertPtrReturn(pszTemplate, VERR_INVALID_POINTER);
1463 AssertReturn(cbTemplate, VERR_INVALID_PARAMETER);
1464 AssertPtrReturn(pszPath, VERR_INVALID_POINTER);
1465 AssertReturn(cbPath, VERR_INVALID_PARAMETER);
1466 AssertPtrReturn(pfFlags, VERR_INVALID_POINTER);
1467 AssertPtrReturn(pfMode, VERR_INVALID_POINTER);
1468
1469 int rc;
1470 do
1471 {
1472 HGCMMsgFsCreateTemp Msg;
1473 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, vbglR3GuestCtrlGetMsgFunctionNo(pCtx->uClientID), pCtx->uNumParms);
1474 VbglHGCMParmUInt32Set(&Msg.context, HOST_MSG_FS_CREATE_TEMP);
1475 VbglHGCMParmPtrSet(&Msg.template_name, pszTemplate, cbTemplate);
1476 VbglHGCMParmPtrSet(&Msg.tmpdir, pszPath, cbPath);
1477 VbglHGCMParmUInt32Set(&Msg.flags, 0);
1478 VbglHGCMParmUInt32Set(&Msg.mode, 0);
1479
1480 rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
1481 if (RT_SUCCESS(rc))
1482 {
1483 Msg.context.GetUInt32(&pCtx->uContextID);
1484 Msg.flags.GetUInt32(pfFlags);
1485 Msg.mode.GetUInt32(pfMode);
1486 }
1487
1488 } while (rc == VERR_INTERRUPTED && g_fVbglR3GuestCtrlHavePeekGetCancel);
1489 return rc;
1490}
1491#endif /* VBOX_WITH_GSTCTL_TOOLBOX_AS_CMDS */
1492
1493
1494/**
1495 * Retrieves a HOST_MSG_SHUTDOWN message.
1496 *
1497 * @returns VBox status code.
1498 * @param pCtx Guest control command context to use.
1499 * @param pfAction Where to store the action flags on success.
1500 */
1501VBGLR3DECL(int) VbglR3GuestCtrlGetShutdown(PVBGLR3GUESTCTRLCMDCTX pCtx, uint32_t *pfAction)
1502{
1503 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1504 AssertReturn(pCtx->uNumParms == 2, VERR_INVALID_PARAMETER);
1505 AssertPtrReturn(pfAction, VERR_INVALID_POINTER);
1506
1507 int rc;
1508 do
1509 {
1510 HGCMMsgShutdown Msg;
1511 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, vbglR3GuestCtrlGetMsgFunctionNo(pCtx->uClientID), pCtx->uNumParms);
1512 VbglHGCMParmUInt32Set(&Msg.context, HOST_MSG_SHUTDOWN);
1513 VbglHGCMParmUInt32Set(&Msg.action, 0);
1514
1515 rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
1516 if (RT_SUCCESS(rc))
1517 {
1518 Msg.context.GetUInt32(&pCtx->uContextID);
1519 Msg.action.GetUInt32(pfAction);
1520 }
1521 } while (rc == VERR_INTERRUPTED && g_fVbglR3GuestCtrlHavePeekGetCancel);
1522 return rc;
1523}
1524
1525/**
1526 * Initializes a process startup info, extended version.
1527 *
1528 * @returns VBox status code.
1529 * @param pStartupInfo Process startup info to initializes.
1530 * @param cbCmd Size (in bytes) to use for the command buffer.
1531 * @param cbArgs Size (in bytes) to use for the arguments buffer.
1532 * @param cbEnv Size (in bytes) to use for the environment buffer.
1533 * @param cbCwd Size (in bytes) to use for the current working directory.
1534 * @param cbUser Size (in bytes) to use for the user name buffer.
1535 * @param cbPassword Size (in bytes) to use for the password buffer.
1536 * @param cbDomain Size (in bytes) to use for the domain buffer.
1537 */
1538VBGLR3DECL(int) VbglR3GuestCtrlProcStartupInfoInitEx(PVBGLR3GUESTCTRLPROCSTARTUPINFO pStartupInfo,
1539 size_t cbCmd, size_t cbArgs, size_t cbEnv,
1540 size_t cbCwd,
1541 size_t cbUser, size_t cbPassword, size_t cbDomain)
1542{
1543 AssertPtrReturn(pStartupInfo, VERR_INVALID_POINTER);
1544 AssertReturn(cbCmd, VERR_INVALID_PARAMETER);
1545 AssertReturn(cbArgs, VERR_INVALID_PARAMETER);
1546 AssertReturn(cbEnv, VERR_INVALID_PARAMETER);
1547 AssertReturn(cbCwd, VERR_INVALID_PARAMETER);
1548 AssertReturn(cbUser, VERR_INVALID_PARAMETER);
1549 AssertReturn(cbPassword, VERR_INVALID_PARAMETER);
1550 AssertReturn(cbDomain, VERR_INVALID_PARAMETER);
1551
1552 RT_BZERO(pStartupInfo, sizeof(VBGLR3GUESTCTRLPROCSTARTUPINFO));
1553
1554#define ALLOC_STR(a_Str, a_cb) \
1555 if ((a_cb) > 0) \
1556 { \
1557 pStartupInfo->psz##a_Str = RTStrAlloc(a_cb); \
1558 AssertPtrBreak(pStartupInfo->psz##a_Str); \
1559 pStartupInfo->cb##a_Str = (uint32_t)a_cb; \
1560 }
1561
1562 do
1563 {
1564 ALLOC_STR(Cmd, cbCmd);
1565 ALLOC_STR(Args, cbArgs);
1566 ALLOC_STR(Env, cbEnv);
1567 ALLOC_STR(Cwd, cbCwd);
1568 ALLOC_STR(User, cbUser);
1569 ALLOC_STR(Password, cbPassword);
1570 ALLOC_STR(Domain, cbDomain);
1571
1572 return VINF_SUCCESS;
1573
1574 } while (0);
1575
1576#undef ALLOC_STR
1577
1578 VbglR3GuestCtrlProcStartupInfoDestroy(pStartupInfo);
1579 return VERR_NO_MEMORY;
1580}
1581
1582/**
1583 * Initializes a process startup info with default values.
1584 *
1585 * @param pStartupInfo Process startup info to initialize.
1586 */
1587VBGLR3DECL(int) VbglR3GuestCtrlProcStartupInfoInit(PVBGLR3GUESTCTRLPROCSTARTUPINFO pStartupInfo)
1588{
1589 return VbglR3GuestCtrlProcStartupInfoInitEx(pStartupInfo,
1590 GUEST_PROC_DEF_CMD_LEN, GUEST_PROC_DEF_ARGS_LEN, GUEST_PROC_DEF_ENV_LEN,
1591 GUEST_PROC_DEF_CWD_LEN,
1592 GUEST_PROC_DEF_USER_LEN /* Deprecated, now handled via session creation. */,
1593 GUEST_PROC_DEF_PASSWORD_LEN /* Ditto. */,
1594 GUEST_PROC_DEF_DOMAIN_LEN /* Ditto. */);
1595}
1596
1597/**
1598 * Destroys a process startup info.
1599 *
1600 * @param pStartupInfo Process startup info to destroy.
1601 */
1602VBGLR3DECL(void) VbglR3GuestCtrlProcStartupInfoDestroy(PVBGLR3GUESTCTRLPROCSTARTUPINFO pStartupInfo)
1603{
1604 if (!pStartupInfo)
1605 return;
1606
1607 RTStrFree(pStartupInfo->pszCmd);
1608 RTStrFree(pStartupInfo->pszArgs);
1609 RTStrFree(pStartupInfo->pszEnv);
1610 RTStrFree(pStartupInfo->pszCwd);
1611 RTStrFree(pStartupInfo->pszUser);
1612 RTStrFree(pStartupInfo->pszPassword);
1613 RTStrFree(pStartupInfo->pszDomain);
1614
1615 RT_BZERO(pStartupInfo, sizeof(VBGLR3GUESTCTRLPROCSTARTUPINFO));
1616}
1617
1618/**
1619 * Free's a process startup info.
1620 *
1621 * @param pStartupInfo Process startup info to free.
1622 * The pointer will not be valid anymore after return.
1623 */
1624VBGLR3DECL(void) VbglR3GuestCtrlProcStartupInfoFree(PVBGLR3GUESTCTRLPROCSTARTUPINFO pStartupInfo)
1625{
1626 if (!pStartupInfo)
1627 return;
1628
1629 VbglR3GuestCtrlProcStartupInfoDestroy(pStartupInfo);
1630
1631 RTMemFree(pStartupInfo);
1632 pStartupInfo = NULL;
1633}
1634
1635/**
1636 * Duplicates a process startup info.
1637 *
1638 * @returns Duplicated process startup info on success, or NULL on error.
1639 * @param pStartupInfo Process startup info to duplicate.
1640 */
1641VBGLR3DECL(PVBGLR3GUESTCTRLPROCSTARTUPINFO) VbglR3GuestCtrlProcStartupInfoDup(PVBGLR3GUESTCTRLPROCSTARTUPINFO pStartupInfo)
1642{
1643 AssertPtrReturn(pStartupInfo, NULL);
1644
1645 PVBGLR3GUESTCTRLPROCSTARTUPINFO pStartupInfoDup = (PVBGLR3GUESTCTRLPROCSTARTUPINFO)
1646 RTMemDup(pStartupInfo, sizeof(VBGLR3GUESTCTRLPROCSTARTUPINFO));
1647 if (pStartupInfoDup)
1648 {
1649 do
1650 {
1651 pStartupInfoDup->pszCmd = NULL;
1652 pStartupInfoDup->pszArgs = NULL;
1653 pStartupInfoDup->pszEnv = NULL;
1654 pStartupInfoDup->pszCwd = NULL;
1655 pStartupInfoDup->pszUser = NULL;
1656 pStartupInfoDup->pszPassword = NULL;
1657 pStartupInfoDup->pszDomain = NULL;
1658
1659#define DUP_STR(a_Str) \
1660 if (pStartupInfo->cb##a_Str) \
1661 { \
1662 pStartupInfoDup->psz##a_Str = (char *)RTStrDup(pStartupInfo->psz##a_Str); \
1663 AssertPtrBreak(pStartupInfoDup->psz##a_Str); \
1664 pStartupInfoDup->cb##a_Str = (uint32_t)strlen(pStartupInfoDup->psz##a_Str) + 1 /* Include terminator */; \
1665 }
1666
1667#define DUP_MEM(a_Str) \
1668 if (pStartupInfo->cb##a_Str) \
1669 { \
1670 pStartupInfoDup->psz##a_Str = (char *)RTMemDup(pStartupInfo->psz##a_Str, pStartupInfo->cb##a_Str); \
1671 AssertPtrBreak(pStartupInfoDup->psz##a_Str); \
1672 pStartupInfoDup->cb##a_Str = (uint32_t)pStartupInfo->cb##a_Str; \
1673 }
1674
1675 DUP_STR(Cmd);
1676 DUP_MEM(Args);
1677 DUP_MEM(Env);
1678 DUP_MEM(Cwd);
1679 DUP_STR(User);
1680 DUP_STR(Password);
1681 DUP_STR(Domain);
1682
1683#undef DUP_STR
1684#undef DUP_MEM
1685
1686 return pStartupInfoDup;
1687
1688 } while (0); /* To use break macros above. */
1689
1690 VbglR3GuestCtrlProcStartupInfoFree(pStartupInfoDup);
1691 }
1692
1693 return NULL;
1694}
1695
1696/**
1697 * Retrieves a HOST_EXEC_CMD message.
1698 *
1699 * @returns VBox status code.
1700 * @param pCtx Guest control command context to use.
1701 * @param ppStartupInfo Where to store the allocated session startup info.
1702 * Needs to be free'd by VbglR3GuestCtrlProcStartupInfoFree().
1703 */
1704VBGLR3DECL(int) VbglR3GuestCtrlProcGetStart(PVBGLR3GUESTCTRLCMDCTX pCtx, PVBGLR3GUESTCTRLPROCSTARTUPINFO *ppStartupInfo)
1705{
1706 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1707 AssertPtrReturn(ppStartupInfo, VERR_INVALID_POINTER);
1708
1709 PVBGLR3GUESTCTRLPROCSTARTUPINFO pStartupInfo
1710 = (PVBGLR3GUESTCTRLPROCSTARTUPINFO)RTMemAlloc(sizeof(VBGLR3GUESTCTRLPROCSTARTUPINFO));
1711 if (!pStartupInfo)
1712 return VERR_NO_MEMORY;
1713
1714 int rc = VbglR3GuestCtrlProcStartupInfoInit(pStartupInfo);
1715 if (RT_FAILURE(rc))
1716 {
1717 VbglR3GuestCtrlProcStartupInfoFree(pStartupInfo);
1718 return rc;
1719 }
1720
1721 unsigned cRetries = 0;
1722 const unsigned cMaxRetries = 32; /* Should be enough for now. */
1723 const unsigned cGrowthFactor = 2; /* By how much the buffers will grow if they're too small yet. */
1724
1725 do
1726 {
1727 LogRel(("VbglR3GuestCtrlProcGetStart: Retrieving\n"));
1728
1729 HGCMMsgProcExec Msg;
1730 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, vbglR3GuestCtrlGetMsgFunctionNo(pCtx->uClientID), pCtx->uNumParms);
1731 VbglHGCMParmUInt32Set(&Msg.context, HOST_MSG_EXEC_CMD);
1732 VbglHGCMParmPtrSet(&Msg.cmd, pStartupInfo->pszCmd, pStartupInfo->cbCmd);
1733 VbglHGCMParmUInt32Set(&Msg.flags, 0);
1734 VbglHGCMParmUInt32Set(&Msg.num_args, 0);
1735 VbglHGCMParmPtrSet(&Msg.args, pStartupInfo->pszArgs, pStartupInfo->cbArgs);
1736 VbglHGCMParmUInt32Set(&Msg.num_env, 0);
1737 VbglHGCMParmUInt32Set(&Msg.cb_env, 0);
1738 VbglHGCMParmPtrSet(&Msg.env, pStartupInfo->pszEnv, pStartupInfo->cbEnv);
1739 if (pCtx->uProtocol < 2) /* Protocol v1, deprecated. */
1740 {
1741 VbglHGCMParmPtrSet(&Msg.u.v1.username, pStartupInfo->pszUser, pStartupInfo->cbUser);
1742 VbglHGCMParmPtrSet(&Msg.u.v1.password, pStartupInfo->pszPassword, pStartupInfo->cbPassword);
1743 VbglHGCMParmUInt32Set(&Msg.u.v1.timeout, 0);
1744 }
1745 else /* Protocol v2. */
1746 {
1747 VbglHGCMParmUInt32Set(&Msg.u.v2.timeout, 0);
1748 VbglHGCMParmUInt32Set(&Msg.u.v2.priority, 0);
1749 VbglHGCMParmUInt32Set(&Msg.u.v2.num_affinity, 0);
1750 VbglHGCMParmPtrSet(&Msg.u.v2.affinity, pStartupInfo->uAffinity, sizeof(pStartupInfo->uAffinity));
1751 }
1752
1753 /* CWD support was added in VBox 7.1. Otherwise just skip setting it. */
1754 if (g_fVbglR3GuestCtrlHostFeatures0 & VBOX_GUESTCTRL_HF_0_PROCESS_CWD)
1755 VbglHGCMParmPtrSet(&Msg.cwd, pStartupInfo->pszCwd, pStartupInfo->cbCwd);
1756
1757 /*
1758 * We need to calculate the data size ourselves here and not rely on sizeof(),
1759 * as sizeof(Msg) might be different to what the host expects.
1760 *
1761 * This first was needed when excluding the CWD support for hosts running VBox < 7.1.
1762 */
1763 rc = VbglR3HGCMCall(&Msg.hdr, sizeof(VBGLIOCHGCMCALL) + pCtx->uNumParms * sizeof(HGCMFunctionParameter));
1764 if (RT_FAILURE(rc))
1765 {
1766 LogRel(("VbglR3GuestCtrlProcGetStart: 1 - %Rrc (retry %u, cbCmd=%RU32, cbCwd=%RU32, cbArgs=%RU32, cbEnv=%RU32)\n",
1767 rc, cRetries, pStartupInfo->cbCmd, pStartupInfo->cbCwd, pStartupInfo->cbArgs, pStartupInfo->cbEnv));
1768
1769 if ( rc == VERR_BUFFER_OVERFLOW
1770 && cRetries++ < cMaxRetries)
1771 {
1772#define GROW_STR(a_Str, a_cbMax) \
1773 pStartupInfo->psz##a_Str = (char *)RTMemRealloc(pStartupInfo->psz##a_Str, \
1774 RT_MIN(pStartupInfo->cb##a_Str * cGrowthFactor, a_cbMax)); \
1775 AssertPtrBreakStmt(pStartupInfo->psz##a_Str, rc = VERR_NO_MEMORY); \
1776 pStartupInfo->cb##a_Str = RT_MIN(pStartupInfo->cb##a_Str * cGrowthFactor, a_cbMax);
1777
1778 /* We can't tell which parameter doesn't fit, so we have to resize all. */
1779 GROW_STR(Cmd , GUEST_PROC_MAX_CMD_LEN);
1780 GROW_STR(Args, GUEST_PROC_MAX_ARGS_LEN);
1781 GROW_STR(Env, GUEST_PROC_MAX_ENV_LEN);
1782 GROW_STR(Cwd, GUEST_PROC_MAX_CWD_LEN);
1783#undef GROW_STR
1784 LogRel(("VbglR3GuestCtrlProcGetStart: 2 - %Rrc (retry %u, cbCmd=%RU32, cbCwd=%RU32, cbArgs=%RU32, cbEnv=%RU32)\n",
1785 rc, cRetries, pStartupInfo->cbCmd, pStartupInfo->cbCwd, pStartupInfo->cbArgs, pStartupInfo->cbEnv));
1786 LogRel(("g_fVbglR3GuestCtrlHavePeekGetCancel=%RTbool\n", RT_BOOL(g_fVbglR3GuestCtrlHavePeekGetCancel)));
1787 }
1788 else
1789 break;
1790 }
1791 else
1792 {
1793 Msg.context.GetUInt32(&pCtx->uContextID);
1794 Msg.flags.GetUInt32(&pStartupInfo->fFlags);
1795 Msg.num_args.GetUInt32(&pStartupInfo->cArgs);
1796 Msg.num_env.GetUInt32(&pStartupInfo->cEnvVars);
1797 Msg.cb_env.GetUInt32(&pStartupInfo->cbEnv);
1798 if (pCtx->uProtocol < 2)
1799 Msg.u.v1.timeout.GetUInt32(&pStartupInfo->uTimeLimitMS);
1800 else
1801 {
1802 Msg.u.v2.timeout.GetUInt32(&pStartupInfo->uTimeLimitMS);
1803 Msg.u.v2.priority.GetUInt32(&pStartupInfo->uPriority);
1804 Msg.u.v2.num_affinity.GetUInt32(&pStartupInfo->cAffinity);
1805 }
1806 }
1807 } while (( rc == VERR_INTERRUPTED
1808 || rc == VERR_BUFFER_OVERFLOW) && g_fVbglR3GuestCtrlHavePeekGetCancel);
1809
1810 LogRel(("VbglR3GuestCtrlProcGetStart: Returning %Rrc (retry %u, cbCmd=%RU32, cbArgs=%RU32, cbEnv=%RU32)\n",
1811 rc, cRetries, pStartupInfo->cbCmd, pStartupInfo->cbArgs, pStartupInfo->cbEnv));
1812
1813 if (RT_SUCCESS(rc))
1814 {
1815 *ppStartupInfo = pStartupInfo;
1816 }
1817 else
1818 VbglR3GuestCtrlProcStartupInfoFree(pStartupInfo);
1819
1820 LogFlowFuncLeaveRC(rc);
1821 return rc;
1822}
1823
1824/**
1825 * Allocates and gets host data, based on the message ID.
1826 *
1827 * This will block until data becomes available.
1828 *
1829 * @returns VBox status code.
1830 * @param pCtx Guest control command context to use.
1831 * @param puPID Where to return the guest PID to retrieve output from on success.
1832 * @param puHandle Where to return the guest process handle to retrieve output from on success.
1833 * @param pfFlags Where to return the output flags on success.
1834 */
1835VBGLR3DECL(int) VbglR3GuestCtrlProcGetOutput(PVBGLR3GUESTCTRLCMDCTX pCtx,
1836 uint32_t *puPID, uint32_t *puHandle, uint32_t *pfFlags)
1837{
1838 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1839 AssertReturn(pCtx->uNumParms == 4, VERR_INVALID_PARAMETER);
1840
1841 AssertPtrReturn(puPID, VERR_INVALID_POINTER);
1842 AssertPtrReturn(puHandle, VERR_INVALID_POINTER);
1843 AssertPtrReturn(pfFlags, VERR_INVALID_POINTER);
1844
1845 int rc;
1846 do
1847 {
1848 HGCMMsgProcOutput Msg;
1849 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, vbglR3GuestCtrlGetMsgFunctionNo(pCtx->uClientID), pCtx->uNumParms);
1850 VbglHGCMParmUInt32Set(&Msg.context, HOST_MSG_EXEC_GET_OUTPUT);
1851 VbglHGCMParmUInt32Set(&Msg.pid, 0);
1852 VbglHGCMParmUInt32Set(&Msg.handle, 0);
1853 VbglHGCMParmUInt32Set(&Msg.flags, 0);
1854
1855 rc = VbglR3HGCMCall(&Msg.hdr, RT_UOFFSETOF(HGCMMsgProcOutput, data));
1856 if (RT_SUCCESS(rc))
1857 {
1858 Msg.context.GetUInt32(&pCtx->uContextID);
1859 Msg.pid.GetUInt32(puPID);
1860 Msg.handle.GetUInt32(puHandle);
1861 Msg.flags.GetUInt32(pfFlags);
1862 }
1863 } while (rc == VERR_INTERRUPTED && g_fVbglR3GuestCtrlHavePeekGetCancel);
1864 return rc;
1865}
1866
1867
1868/**
1869 * Retrieves the input data from host which then gets sent to the started
1870 * process (HOST_EXEC_SET_INPUT).
1871 *
1872 * This will block until data becomes available.
1873 */
1874VBGLR3DECL(int) VbglR3GuestCtrlProcGetInput(PVBGLR3GUESTCTRLCMDCTX pCtx,
1875 uint32_t *puPID, uint32_t *pfFlags,
1876 void *pvData, uint32_t cbData,
1877 uint32_t *pcbSize)
1878{
1879 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1880 AssertReturn(pCtx->uNumParms == 5, VERR_INVALID_PARAMETER);
1881
1882 AssertPtrReturn(puPID, VERR_INVALID_POINTER);
1883 AssertPtrReturn(pfFlags, VERR_INVALID_POINTER);
1884 AssertPtrReturn(pvData, VERR_INVALID_POINTER);
1885 AssertPtrReturn(pcbSize, VERR_INVALID_POINTER);
1886
1887 int rc;
1888 do
1889 {
1890 HGCMMsgProcInput Msg;
1891 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, vbglR3GuestCtrlGetMsgFunctionNo(pCtx->uClientID), pCtx->uNumParms);
1892 VbglHGCMParmUInt32Set(&Msg.context, HOST_MSG_EXEC_SET_INPUT);
1893 VbglHGCMParmUInt32Set(&Msg.pid, 0);
1894 VbglHGCMParmUInt32Set(&Msg.flags, 0);
1895 VbglHGCMParmPtrSet(&Msg.data, pvData, cbData);
1896 VbglHGCMParmUInt32Set(&Msg.size, 0);
1897
1898 rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
1899 if (RT_SUCCESS(rc))
1900 {
1901 Msg.context.GetUInt32(&pCtx->uContextID);
1902 Msg.pid.GetUInt32(puPID);
1903 Msg.flags.GetUInt32(pfFlags);
1904 Msg.size.GetUInt32(pcbSize);
1905 }
1906 } while (rc == VERR_INTERRUPTED && g_fVbglR3GuestCtrlHavePeekGetCancel);
1907
1908 if ( rc != VERR_TOO_MUCH_DATA
1909 || g_fVbglR3GuestCtrlHavePeekGetCancel)
1910 return rc;
1911 return VERR_BUFFER_OVERFLOW;
1912}
1913
1914
1915#ifdef VBOX_WITH_GSTCTL_TOOLBOX_AS_CMDS
1916/**
1917 * Retrieves a HOST_MSG_DIR_CREATE message.
1918 *
1919 * @returns VBox status code.
1920 * @param pCtx Guest control command context to use.
1921 * @param pszPath Where to return the path.
1922 * @param cbPath Size (in bytes) of \a pszPath.
1923 * @param pfMode Where to return the creation mode.
1924 * @param pfFlags Where to return the creation flags (GSTCTL_CREATEDIRECTORY_F_XXX).
1925 */
1926VBGLR3DECL(int) VbglR3GuestCtrlDirGetCreate(PVBGLR3GUESTCTRLCMDCTX pCtx, char *pszPath, uint32_t cbPath, uint32_t *pfMode, uint32_t *pfFlags)
1927{
1928 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1929 AssertReturn(pCtx->uNumParms == 4, VERR_INVALID_PARAMETER);
1930
1931 AssertPtrReturn(pszPath, VERR_INVALID_POINTER);
1932 AssertReturn(cbPath, VERR_INVALID_PARAMETER);
1933 AssertPtrReturn(pfFlags, VERR_INVALID_POINTER);
1934 AssertPtrReturn(pfMode, VERR_INVALID_POINTER);
1935
1936 int rc;
1937 do
1938 {
1939 HGCMMsgDirCreate Msg;
1940 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, vbglR3GuestCtrlGetMsgFunctionNo(pCtx->uClientID), pCtx->uNumParms);
1941 VbglHGCMParmUInt32Set(&Msg.context, HOST_MSG_DIR_CREATE);
1942 VbglHGCMParmPtrSet(&Msg.path, pszPath, cbPath);
1943 VbglHGCMParmUInt32Set(&Msg.mode, 0);
1944 VbglHGCMParmUInt32Set(&Msg.flags, 0);
1945
1946 rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
1947 if (RT_SUCCESS(rc))
1948 {
1949 Msg.context.GetUInt32(&pCtx->uContextID);
1950 Msg.flags.GetUInt32(pfFlags);
1951 Msg.mode.GetUInt32(pfMode);
1952 }
1953
1954 } while (rc == VERR_INTERRUPTED && g_fVbglR3GuestCtrlHavePeekGetCancel);
1955 return rc;
1956}
1957#endif /* VBOX_WITH_GSTCTL_TOOLBOX_AS_CMDS */
1958
1959
1960/**
1961 * Retrieves a HOST_DIR_REMOVE message.
1962 */
1963VBGLR3DECL(int) VbglR3GuestCtrlDirGetRemove(PVBGLR3GUESTCTRLCMDCTX pCtx,
1964 char *pszPath, uint32_t cbPath,
1965 uint32_t *pfFlags)
1966{
1967 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1968 AssertReturn(pCtx->uNumParms == 3, VERR_INVALID_PARAMETER);
1969
1970 AssertPtrReturn(pszPath, VERR_INVALID_POINTER);
1971 AssertReturn(cbPath, VERR_INVALID_PARAMETER);
1972 AssertPtrReturn(pfFlags, VERR_INVALID_POINTER);
1973
1974 int rc;
1975 do
1976 {
1977 HGCMMsgDirRemove Msg;
1978 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, vbglR3GuestCtrlGetMsgFunctionNo(pCtx->uClientID), pCtx->uNumParms);
1979 VbglHGCMParmUInt32Set(&Msg.context, HOST_MSG_DIR_REMOVE);
1980 VbglHGCMParmPtrSet(&Msg.path, pszPath, cbPath);
1981 VbglHGCMParmUInt32Set(&Msg.flags, 0);
1982
1983 rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
1984 if (RT_SUCCESS(rc))
1985 {
1986 Msg.context.GetUInt32(&pCtx->uContextID);
1987 Msg.flags.GetUInt32(pfFlags);
1988 }
1989 } while (rc == VERR_INTERRUPTED && g_fVbglR3GuestCtrlHavePeekGetCancel);
1990 return rc;
1991}
1992
1993
1994/**
1995 * Retrieves a HOST_FILE_OPEN message.
1996 */
1997VBGLR3DECL(int) VbglR3GuestCtrlFileGetOpen(PVBGLR3GUESTCTRLCMDCTX pCtx,
1998 char *pszFileName, uint32_t cbFileName,
1999 char *pszAccess, uint32_t cbAccess,
2000 char *pszDisposition, uint32_t cbDisposition,
2001 char *pszSharing, uint32_t cbSharing,
2002 uint32_t *puCreationMode,
2003 uint64_t *poffAt)
2004{
2005 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
2006 AssertReturn(pCtx->uNumParms == 7, VERR_INVALID_PARAMETER);
2007
2008 AssertPtrReturn(pszFileName, VERR_INVALID_POINTER);
2009 AssertReturn(cbFileName, VERR_INVALID_PARAMETER);
2010 AssertPtrReturn(pszAccess, VERR_INVALID_POINTER);
2011 AssertReturn(cbAccess, VERR_INVALID_PARAMETER);
2012 AssertPtrReturn(pszDisposition, VERR_INVALID_POINTER);
2013 AssertReturn(cbDisposition, VERR_INVALID_PARAMETER);
2014 AssertPtrReturn(pszSharing, VERR_INVALID_POINTER);
2015 AssertReturn(cbSharing, VERR_INVALID_PARAMETER);
2016 AssertPtrReturn(puCreationMode, VERR_INVALID_POINTER);
2017 AssertPtrReturn(poffAt, VERR_INVALID_POINTER);
2018
2019 int rc;
2020 do
2021 {
2022 HGCMMsgFileOpen Msg;
2023 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, vbglR3GuestCtrlGetMsgFunctionNo(pCtx->uClientID), pCtx->uNumParms);
2024 VbglHGCMParmUInt32Set(&Msg.context, HOST_MSG_FILE_OPEN);
2025 VbglHGCMParmPtrSet(&Msg.filename, pszFileName, cbFileName);
2026 VbglHGCMParmPtrSet(&Msg.openmode, pszAccess, cbAccess);
2027 VbglHGCMParmPtrSet(&Msg.disposition, pszDisposition, cbDisposition);
2028 VbglHGCMParmPtrSet(&Msg.sharing, pszSharing, cbSharing);
2029 VbglHGCMParmUInt32Set(&Msg.creationmode, 0);
2030 VbglHGCMParmUInt64Set(&Msg.offset, 0);
2031
2032 rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
2033 if (RT_SUCCESS(rc))
2034 {
2035 Msg.context.GetUInt32(&pCtx->uContextID);
2036 Msg.creationmode.GetUInt32(puCreationMode);
2037 Msg.offset.GetUInt64(poffAt);
2038 }
2039 } while (rc == VERR_INTERRUPTED && g_fVbglR3GuestCtrlHavePeekGetCancel);
2040 return rc;
2041}
2042
2043
2044/**
2045 * Retrieves a HOST_FILE_CLOSE message.
2046 */
2047VBGLR3DECL(int) VbglR3GuestCtrlFileGetClose(PVBGLR3GUESTCTRLCMDCTX pCtx, uint32_t *puHandle)
2048{
2049 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
2050
2051 AssertReturn(pCtx->uNumParms == 2, VERR_INVALID_PARAMETER);
2052 AssertPtrReturn(puHandle, VERR_INVALID_POINTER);
2053
2054 int rc;
2055 do
2056 {
2057 HGCMMsgFileClose Msg;
2058 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, vbglR3GuestCtrlGetMsgFunctionNo(pCtx->uClientID), pCtx->uNumParms);
2059 VbglHGCMParmUInt32Set(&Msg.context, HOST_MSG_FILE_CLOSE);
2060 VbglHGCMParmUInt32Set(&Msg.handle, 0);
2061
2062 rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
2063 if (RT_SUCCESS(rc))
2064 {
2065 Msg.context.GetUInt32(&pCtx->uContextID);
2066 Msg.handle.GetUInt32(puHandle);
2067 }
2068 } while (rc == VERR_INTERRUPTED && g_fVbglR3GuestCtrlHavePeekGetCancel);
2069 return rc;
2070}
2071
2072
2073/**
2074 * Retrieves a HOST_FILE_READ message.
2075 */
2076VBGLR3DECL(int) VbglR3GuestCtrlFileGetRead(PVBGLR3GUESTCTRLCMDCTX pCtx, uint32_t *puHandle, uint32_t *puToRead)
2077{
2078 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
2079
2080 AssertReturn(pCtx->uNumParms == 3, VERR_INVALID_PARAMETER);
2081 AssertPtrReturn(puHandle, VERR_INVALID_POINTER);
2082 AssertPtrReturn(puToRead, VERR_INVALID_POINTER);
2083
2084 int rc;
2085 do
2086 {
2087 HGCMMsgFileRead Msg;
2088 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, vbglR3GuestCtrlGetMsgFunctionNo(pCtx->uClientID), pCtx->uNumParms);
2089 VbglHGCMParmUInt32Set(&Msg.context, HOST_MSG_FILE_READ);
2090 VbglHGCMParmUInt32Set(&Msg.handle, 0);
2091 VbglHGCMParmUInt32Set(&Msg.size, 0);
2092
2093 rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
2094 if (RT_SUCCESS(rc))
2095 {
2096 Msg.context.GetUInt32(&pCtx->uContextID);
2097 Msg.handle.GetUInt32(puHandle);
2098 Msg.size.GetUInt32(puToRead);
2099 }
2100 } while (rc == VERR_INTERRUPTED && g_fVbglR3GuestCtrlHavePeekGetCancel);
2101 return rc;
2102}
2103
2104
2105/**
2106 * Retrieves a HOST_FILE_READ_AT message.
2107 */
2108VBGLR3DECL(int) VbglR3GuestCtrlFileGetReadAt(PVBGLR3GUESTCTRLCMDCTX pCtx,
2109 uint32_t *puHandle, uint32_t *puToRead, uint64_t *poffAt)
2110{
2111 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
2112
2113 AssertReturn(pCtx->uNumParms == 4, VERR_INVALID_PARAMETER);
2114 AssertPtrReturn(puHandle, VERR_INVALID_POINTER);
2115 AssertPtrReturn(puToRead, VERR_INVALID_POINTER);
2116
2117 int rc;
2118 do
2119 {
2120 HGCMMsgFileReadAt Msg;
2121 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, vbglR3GuestCtrlGetMsgFunctionNo(pCtx->uClientID), pCtx->uNumParms);
2122 VbglHGCMParmUInt32Set(&Msg.context, HOST_MSG_FILE_READ_AT);
2123 VbglHGCMParmUInt32Set(&Msg.handle, 0);
2124 VbglHGCMParmUInt64Set(&Msg.offset, 0);
2125 VbglHGCMParmUInt32Set(&Msg.size, 0);
2126
2127 rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
2128 if (RT_SUCCESS(rc))
2129 {
2130 Msg.context.GetUInt32(&pCtx->uContextID);
2131 Msg.handle.GetUInt32(puHandle);
2132 Msg.offset.GetUInt64(poffAt);
2133 Msg.size.GetUInt32(puToRead);
2134 }
2135 } while (rc == VERR_INTERRUPTED && g_fVbglR3GuestCtrlHavePeekGetCancel);
2136 return rc;
2137}
2138
2139
2140/**
2141 * Retrieves a HOST_FILE_WRITE message.
2142 */
2143VBGLR3DECL(int) VbglR3GuestCtrlFileGetWrite(PVBGLR3GUESTCTRLCMDCTX pCtx, uint32_t *puHandle,
2144 void *pvData, uint32_t cbData, uint32_t *pcbSize)
2145{
2146 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
2147
2148 AssertReturn(pCtx->uNumParms == 4, VERR_INVALID_PARAMETER);
2149 AssertPtrReturn(puHandle, VERR_INVALID_POINTER);
2150 AssertPtrReturn(pvData, VERR_INVALID_POINTER);
2151 AssertReturn(cbData, VERR_INVALID_PARAMETER);
2152 AssertPtrReturn(pcbSize, VERR_INVALID_POINTER);
2153
2154 int rc;
2155 do
2156 {
2157 HGCMMsgFileWrite Msg;
2158 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, vbglR3GuestCtrlGetMsgFunctionNo(pCtx->uClientID), pCtx->uNumParms);
2159 VbglHGCMParmUInt32Set(&Msg.context, HOST_MSG_FILE_WRITE);
2160 VbglHGCMParmUInt32Set(&Msg.handle, 0);
2161 VbglHGCMParmPtrSet(&Msg.data, pvData, cbData);
2162 VbglHGCMParmUInt32Set(&Msg.size, 0);
2163
2164 rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
2165 if (RT_SUCCESS(rc))
2166 {
2167 Msg.context.GetUInt32(&pCtx->uContextID);
2168 Msg.handle.GetUInt32(puHandle);
2169 Msg.size.GetUInt32(pcbSize);
2170 }
2171 } while (rc == VERR_INTERRUPTED && g_fVbglR3GuestCtrlHavePeekGetCancel);
2172
2173 if ( rc != VERR_TOO_MUCH_DATA
2174 || g_fVbglR3GuestCtrlHavePeekGetCancel)
2175 return rc;
2176 return VERR_BUFFER_OVERFLOW;
2177}
2178
2179
2180/**
2181 * Retrieves a HOST_FILE_WRITE_AT message.
2182 */
2183VBGLR3DECL(int) VbglR3GuestCtrlFileGetWriteAt(PVBGLR3GUESTCTRLCMDCTX pCtx, uint32_t *puHandle,
2184 void *pvData, uint32_t cbData, uint32_t *pcbSize, uint64_t *poffAt)
2185{
2186 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
2187
2188 AssertReturn(pCtx->uNumParms == 5, VERR_INVALID_PARAMETER);
2189 AssertPtrReturn(puHandle, VERR_INVALID_POINTER);
2190 AssertPtrReturn(pvData, VERR_INVALID_POINTER);
2191 AssertReturn(cbData, VERR_INVALID_PARAMETER);
2192 AssertPtrReturn(pcbSize, VERR_INVALID_POINTER);
2193
2194 int rc;
2195 do
2196 {
2197 HGCMMsgFileWriteAt Msg;
2198 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, vbglR3GuestCtrlGetMsgFunctionNo(pCtx->uClientID), pCtx->uNumParms);
2199 VbglHGCMParmUInt32Set(&Msg.context, HOST_MSG_FILE_WRITE_AT);
2200 VbglHGCMParmUInt32Set(&Msg.handle, 0);
2201 VbglHGCMParmPtrSet(&Msg.data, pvData, cbData);
2202 VbglHGCMParmUInt32Set(&Msg.size, 0);
2203 VbglHGCMParmUInt64Set(&Msg.offset, 0);
2204
2205 rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
2206 if (RT_SUCCESS(rc))
2207 {
2208 Msg.context.GetUInt32(&pCtx->uContextID);
2209 Msg.handle.GetUInt32(puHandle);
2210 Msg.size.GetUInt32(pcbSize);
2211 Msg.offset.GetUInt64(poffAt);
2212 }
2213 } while (rc == VERR_INTERRUPTED && g_fVbglR3GuestCtrlHavePeekGetCancel);
2214
2215 if ( rc != VERR_TOO_MUCH_DATA
2216 || g_fVbglR3GuestCtrlHavePeekGetCancel)
2217 return rc;
2218 return VERR_BUFFER_OVERFLOW;
2219}
2220
2221
2222/**
2223 * Retrieves a HOST_FILE_SEEK message.
2224 */
2225VBGLR3DECL(int) VbglR3GuestCtrlFileGetSeek(PVBGLR3GUESTCTRLCMDCTX pCtx,
2226 uint32_t *puHandle, uint32_t *puSeekMethod, uint64_t *poffAt)
2227{
2228 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
2229
2230 AssertReturn(pCtx->uNumParms == 4, VERR_INVALID_PARAMETER);
2231 AssertPtrReturn(puHandle, VERR_INVALID_POINTER);
2232 AssertPtrReturn(puSeekMethod, VERR_INVALID_POINTER);
2233 AssertPtrReturn(poffAt, VERR_INVALID_POINTER);
2234
2235 int rc;
2236 do
2237 {
2238 HGCMMsgFileSeek Msg;
2239 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, vbglR3GuestCtrlGetMsgFunctionNo(pCtx->uClientID), pCtx->uNumParms);
2240 VbglHGCMParmUInt32Set(&Msg.context, HOST_MSG_FILE_SEEK);
2241 VbglHGCMParmUInt32Set(&Msg.handle, 0);
2242 VbglHGCMParmUInt32Set(&Msg.method, 0);
2243 VbglHGCMParmUInt64Set(&Msg.offset, 0);
2244
2245 rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
2246 if (RT_SUCCESS(rc))
2247 {
2248 Msg.context.GetUInt32(&pCtx->uContextID);
2249 Msg.handle.GetUInt32(puHandle);
2250 Msg.method.GetUInt32(puSeekMethod);
2251 Msg.offset.GetUInt64(poffAt);
2252 }
2253 } while (rc == VERR_INTERRUPTED && g_fVbglR3GuestCtrlHavePeekGetCancel);
2254 return rc;
2255}
2256
2257
2258/**
2259 * Retrieves a HOST_FILE_TELL message.
2260 */
2261VBGLR3DECL(int) VbglR3GuestCtrlFileGetTell(PVBGLR3GUESTCTRLCMDCTX pCtx, uint32_t *puHandle)
2262{
2263 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
2264
2265 AssertReturn(pCtx->uNumParms == 2, VERR_INVALID_PARAMETER);
2266 AssertPtrReturn(puHandle, VERR_INVALID_POINTER);
2267
2268 int rc;
2269 do
2270 {
2271 HGCMMsgFileTell Msg;
2272 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, vbglR3GuestCtrlGetMsgFunctionNo(pCtx->uClientID), pCtx->uNumParms);
2273 VbglHGCMParmUInt32Set(&Msg.context, HOST_MSG_FILE_TELL);
2274 VbglHGCMParmUInt32Set(&Msg.handle, 0);
2275
2276 rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
2277 if (RT_SUCCESS(rc))
2278 {
2279 Msg.context.GetUInt32(&pCtx->uContextID);
2280 Msg.handle.GetUInt32(puHandle);
2281 }
2282 } while (rc == VERR_INTERRUPTED && g_fVbglR3GuestCtrlHavePeekGetCancel);
2283 return rc;
2284}
2285
2286
2287/**
2288 * Retrieves a HOST_FILE_SET_SIZE message.
2289 */
2290VBGLR3DECL(int) VbglR3GuestCtrlFileGetSetSize(PVBGLR3GUESTCTRLCMDCTX pCtx, uint32_t *puHandle, uint64_t *pcbNew)
2291{
2292 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
2293
2294 AssertReturn(pCtx->uNumParms == 3, VERR_INVALID_PARAMETER);
2295 AssertPtrReturn(puHandle, VERR_INVALID_POINTER);
2296 AssertPtrReturn(pcbNew, VERR_INVALID_POINTER);
2297
2298 int rc;
2299 do
2300 {
2301 HGCMMsgFileSetSize Msg;
2302 VBGL_HGCM_HDR_INIT(&Msg.Hdr, pCtx->uClientID, vbglR3GuestCtrlGetMsgFunctionNo(pCtx->uClientID), pCtx->uNumParms);
2303 VbglHGCMParmUInt32Set(&Msg.id32Context, HOST_MSG_FILE_SET_SIZE);
2304 VbglHGCMParmUInt32Set(&Msg.id32Handle, 0);
2305 VbglHGCMParmUInt64Set(&Msg.cb64NewSize, 0);
2306
2307 rc = VbglR3HGCMCall(&Msg.Hdr, sizeof(Msg));
2308 if (RT_SUCCESS(rc))
2309 {
2310 Msg.id32Context.GetUInt32(&pCtx->uContextID);
2311 Msg.id32Handle.GetUInt32(puHandle);
2312 Msg.cb64NewSize.GetUInt64(pcbNew);
2313 }
2314 } while (rc == VERR_INTERRUPTED && g_fVbglR3GuestCtrlHavePeekGetCancel);
2315 return rc;
2316}
2317
2318
2319#ifdef VBOX_WITH_GSTCTL_TOOLBOX_AS_CMDS
2320VBGLR3DECL(int) VbglR3GuestCtrlFileGetRemove(PVBGLR3GUESTCTRLCMDCTX pCtx, char *pszFileName, uint32_t cbFileName)
2321{
2322 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
2323
2324 AssertReturn(pCtx->uNumParms == 2, VERR_INVALID_PARAMETER);
2325 AssertPtrReturn(pszFileName, VERR_INVALID_POINTER);
2326 AssertReturn(cbFileName, VERR_INVALID_PARAMETER);
2327
2328 int rc;
2329 do
2330 {
2331 HGCMMsgFileRemove Msg;
2332 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, vbglR3GuestCtrlGetMsgFunctionNo(pCtx->uClientID), pCtx->uNumParms);
2333 VbglHGCMParmUInt32Set(&Msg.context, HOST_MSG_FILE_REMOVE);
2334 VbglHGCMParmPtrSet(&Msg.filename, pszFileName, cbFileName);
2335
2336 rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
2337 if (RT_SUCCESS(rc))
2338 {
2339 Msg.context.GetUInt32(&pCtx->uContextID);
2340 }
2341 } while (rc == VERR_INTERRUPTED && g_fVbglR3GuestCtrlHavePeekGetCancel);
2342 return rc;
2343}
2344#endif /* VBOX_WITH_GSTCTL_TOOLBOX_AS_CMDS */
2345
2346
2347/**
2348 * Retrieves a HOST_EXEC_TERMINATE message.
2349 */
2350VBGLR3DECL(int) VbglR3GuestCtrlProcGetTerminate(PVBGLR3GUESTCTRLCMDCTX pCtx, uint32_t *puPID)
2351{
2352 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
2353
2354 AssertReturn(pCtx->uNumParms == 2, VERR_INVALID_PARAMETER);
2355 AssertPtrReturn(puPID, VERR_INVALID_POINTER);
2356
2357 int rc;
2358 do
2359 {
2360 HGCMMsgProcTerminate Msg;
2361 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, vbglR3GuestCtrlGetMsgFunctionNo(pCtx->uClientID), pCtx->uNumParms);
2362 VbglHGCMParmUInt32Set(&Msg.context, HOST_MSG_EXEC_TERMINATE);
2363 VbglHGCMParmUInt32Set(&Msg.pid, 0);
2364
2365 rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
2366 if (RT_SUCCESS(rc))
2367 {
2368 Msg.context.GetUInt32(&pCtx->uContextID);
2369 Msg.pid.GetUInt32(puPID);
2370 }
2371 } while (rc == VERR_INTERRUPTED && g_fVbglR3GuestCtrlHavePeekGetCancel);
2372 return rc;
2373}
2374
2375
2376/**
2377 * Retrieves a HOST_EXEC_WAIT_FOR message.
2378 */
2379VBGLR3DECL(int) VbglR3GuestCtrlProcGetWaitFor(PVBGLR3GUESTCTRLCMDCTX pCtx,
2380 uint32_t *puPID, uint32_t *puWaitFlags, uint32_t *puTimeoutMS)
2381{
2382 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
2383
2384 AssertReturn(pCtx->uNumParms == 4, VERR_INVALID_PARAMETER);
2385 AssertPtrReturn(puPID, VERR_INVALID_POINTER);
2386
2387 int rc;
2388 do
2389 {
2390 HGCMMsgProcWaitFor Msg;
2391 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, vbglR3GuestCtrlGetMsgFunctionNo(pCtx->uClientID), pCtx->uNumParms);
2392 VbglHGCMParmUInt32Set(&Msg.context, HOST_MSG_EXEC_WAIT_FOR);
2393 VbglHGCMParmUInt32Set(&Msg.pid, 0);
2394 VbglHGCMParmUInt32Set(&Msg.flags, 0);
2395 VbglHGCMParmUInt32Set(&Msg.timeout, 0);
2396
2397 rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
2398 if (RT_SUCCESS(rc))
2399 {
2400 Msg.context.GetUInt32(&pCtx->uContextID);
2401 Msg.pid.GetUInt32(puPID);
2402 Msg.flags.GetUInt32(puWaitFlags);
2403 Msg.timeout.GetUInt32(puTimeoutMS);
2404 }
2405 } while (rc == VERR_INTERRUPTED && g_fVbglR3GuestCtrlHavePeekGetCancel);
2406 return rc;
2407}
2408
2409
2410/*********************************************************************************************************************************
2411 * Directory callbacks *
2412 ********************************************************************************************************************************/
2413
2414#ifdef VBOX_WITH_GSTCTL_TOOLBOX_AS_CMDS
2415/**
2416 * Replies to a HOST_MSG_DIR_OPEN message.
2417 *
2418 * @returns VBox status code.
2419 * @param pCtx Guest control command context to use.
2420 * @param rc Guest rc of operation (note: IPRT-style signed int).
2421 * @param uDirHandle Directory handle of opened directory.
2422 */
2423VBGLR3DECL(int) VbglR3GuestCtrlDirCbOpen(PVBGLR3GUESTCTRLCMDCTX pCtx, int rc, uint32_t uDirHandle)
2424{
2425 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
2426
2427 HGCMReplyDirNotify Msg;
2428 VBGL_HGCM_HDR_INIT(&Msg.reply_hdr.hdr, pCtx->uClientID, GUEST_MSG_DIR_NOTIFY, GSTCTL_HGCM_REPLY_HDR_PARMS + 1);
2429 VbglHGCMParmUInt32Set(&Msg.reply_hdr.context, pCtx->uContextID);
2430 VbglHGCMParmUInt32Set(&Msg.reply_hdr.type, GUEST_DIR_NOTIFYTYPE_OPEN);
2431 VbglHGCMParmUInt32Set(&Msg.reply_hdr.rc, (uint32_t)rc);
2432
2433 VbglHGCMParmUInt32Set(&Msg.u.open.handle, uDirHandle);
2434
2435 return VbglR3HGCMCall(&Msg.reply_hdr.hdr, RT_UOFFSET_AFTER(HGCMReplyDirNotify, u.open));
2436}
2437
2438
2439/**
2440 * Replies to a HOST_MSG_DIR_CLOSE message.
2441 *
2442 * @returns VBox status code.
2443 * @param pCtx Guest control command context to use.
2444 * @param rc Guest rc of operation (note: IPRT-style signed int).
2445 */
2446VBGLR3DECL(int) VbglR3GuestCtrlDirCbClose(PVBGLR3GUESTCTRLCMDCTX pCtx, int rc)
2447{
2448 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
2449
2450 HGCMReplyDirNotify Msg;
2451 VBGL_HGCM_HDR_INIT(&Msg.reply_hdr.hdr, pCtx->uClientID, GUEST_MSG_DIR_NOTIFY, GSTCTL_HGCM_REPLY_HDR_PARMS);
2452 VbglHGCMParmUInt32Set(&Msg.reply_hdr.context, pCtx->uContextID);
2453 VbglHGCMParmUInt32Set(&Msg.reply_hdr.type, GUEST_DIR_NOTIFYTYPE_CLOSE);
2454 VbglHGCMParmUInt32Set(&Msg.reply_hdr.rc, (uint32_t)rc);
2455
2456 return VbglR3HGCMCall(&Msg.reply_hdr.hdr, RT_UOFFSET_AFTER(HGCMReplyDirNotify, reply_hdr));
2457}
2458
2459
2460/**
2461 * Replies to a HOST_MSG_DIR_READ message, extended version.
2462 *
2463 * @returns VBox status code.
2464 * @param pCtx Guest control command context to use.
2465 * @param rc Guest rc of operation (note: IPRT-style signed int).
2466 * @param pEntry Directory entry to send.
2467 * @param cbSize Size (in bytes) of the OFFSET(GSTCTLDIRENTRYEX, szName[pEntry->cbName + 1]).
2468 * See RTDirReadEx() for more information.
2469 * @param pszUser Associated user ID (owner, uid) as a string.
2470 * @param pszGroups Associated user groups as a string.
2471 * Multiple groups are delimited by GSTCTL_DIRENTRY_GROUPS_DELIMITER_STR,
2472 * whereas the first group always is the primary group.
2473 */
2474VBGLR3DECL(int) VbglR3GuestCtrlDirCbReadEx(PVBGLR3GUESTCTRLCMDCTX pCtx, int rc, PGSTCTLDIRENTRYEX pEntry, uint32_t cbSize,
2475 const char *pszUser, const char *pszGroups)
2476{
2477 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
2478
2479 HGCMReplyDirNotify Msg;
2480 VBGL_HGCM_HDR_INIT(&Msg.reply_hdr.hdr, pCtx->uClientID, GUEST_MSG_DIR_NOTIFY, GSTCTL_HGCM_REPLY_HDR_PARMS + 3);
2481 VbglHGCMParmUInt32Set(&Msg.reply_hdr.context, pCtx->uContextID);
2482 VbglHGCMParmUInt32Set(&Msg.reply_hdr.type, GUEST_DIR_NOTIFYTYPE_READ);
2483 VbglHGCMParmUInt32Set(&Msg.reply_hdr.rc, (uint32_t)rc);
2484
2485 VbglHGCMParmPtrSet (&Msg.u.read.entry, pEntry, cbSize);
2486 VbglHGCMParmPtrSetString(&Msg.u.read.user, pszUser);
2487 VbglHGCMParmPtrSetString(&Msg.u.read.groups, pszGroups);
2488
2489 return VbglR3HGCMCall(&Msg.reply_hdr.hdr, RT_UOFFSET_AFTER(HGCMReplyDirNotify, u.read));
2490}
2491
2492
2493/**
2494 * Replies to a HOST_MSG_DIR_READ message.
2495 *
2496 * @returns VBox status code.
2497 * @param pCtx Guest control command context to use.
2498 * @param rc Guest rc of operation (note: IPRT-style signed int).
2499 * @param pEntry Directory entry to send.
2500 * @param cbSize Size (in bytes) of the OFFSET(GSTCTLDIRENTRYEX, szName[pEntry->cbName + 1]).
2501 * See RTDirReadEx() for more information.
2502 */
2503VBGLR3DECL(int) VbglR3GuestCtrlDirCbRead(PVBGLR3GUESTCTRLCMDCTX pCtx, int rc, PGSTCTLDIRENTRYEX pEntry, uint32_t cbSize)
2504{
2505 char szIgnored[1] = { 0 };
2506 return VbglR3GuestCtrlDirCbReadEx(pCtx, rc, pEntry, cbSize, szIgnored /* pszUser */, szIgnored /* pszGroups */);
2507}
2508
2509
2510/**
2511 * Replies to a HOST_MSG_DIR_REWIND message.
2512 *
2513 * @returns VBox status code.
2514 * @param pCtx Guest control command context to use.
2515 * @param rc Guest rc of operation (note: IPRT-style signed int).
2516 */
2517VBGLR3DECL(int) VbglR3GuestCtrlDirCbRewind(PVBGLR3GUESTCTRLCMDCTX pCtx, int rc)
2518{
2519 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
2520
2521 HGCMReplyDirNotify Msg;
2522 VBGL_HGCM_HDR_INIT(&Msg.reply_hdr.hdr, pCtx->uClientID, GUEST_MSG_DIR_NOTIFY, GSTCTL_HGCM_REPLY_HDR_PARMS);
2523 VbglHGCMParmUInt32Set(&Msg.reply_hdr.context, pCtx->uContextID);
2524 VbglHGCMParmUInt32Set(&Msg.reply_hdr.type, GUEST_DIR_NOTIFYTYPE_REWIND);
2525 VbglHGCMParmUInt32Set(&Msg.reply_hdr.rc, (uint32_t)rc);
2526
2527 return VbglR3HGCMCall(&Msg.reply_hdr.hdr, RT_UOFFSET_AFTER(HGCMReplyDirNotify, u));
2528}
2529
2530
2531/**
2532 * Replies to a HOST_MSG_DIR_LIST message.
2533 *
2534 * @returns VBox status code.
2535 * @param pCtx Guest control command context to use.
2536 * @param rc Guest rc of operation (note: IPRT-style signed int).
2537 * @param cEntries Number of directory entries to send.
2538 * @param pvBuf Buffer of directory entries to send.
2539 * @param cbBuf Size (in bytes) of \a pvBuf.
2540 */
2541VBGLR3DECL(int) VbglR3GuestCtrlDirCbList(PVBGLR3GUESTCTRLCMDCTX pCtx, int rc,
2542 uint32_t cEntries, void *pvBuf, uint32_t cbBuf)
2543{
2544 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
2545
2546 HGCMReplyDirNotify Msg;
2547 VBGL_HGCM_HDR_INIT(&Msg.reply_hdr.hdr, pCtx->uClientID, GUEST_MSG_DIR_NOTIFY, GSTCTL_HGCM_REPLY_HDR_PARMS + 2);
2548 VbglHGCMParmUInt32Set(&Msg.reply_hdr.context, pCtx->uContextID);
2549 VbglHGCMParmUInt32Set(&Msg.reply_hdr.type, GUEST_DIR_NOTIFYTYPE_LIST);
2550 VbglHGCMParmUInt32Set(&Msg.reply_hdr.rc, (uint32_t)rc);
2551
2552 VbglHGCMParmUInt32Set(&Msg.u.list.num_entries, cEntries);
2553 VbglHGCMParmPtrSet(&Msg.u.list.buffer, pvBuf, cbBuf);
2554
2555 return VbglR3HGCMCall(&Msg.reply_hdr.hdr, RT_UOFFSET_AFTER(HGCMReplyDirNotify, u.list));
2556}
2557#endif /* VBOX_WITH_GSTCTL_TOOLBOX_AS_CMDS */
2558
2559
2560/*********************************************************************************************************************************
2561 * File callbacks *
2562 ********************************************************************************************************************************/
2563
2564/**
2565 * Replies to a HOST_MSG_FILE_OPEN message.
2566 *
2567 * @returns VBox status code.
2568 * @param pCtx Guest control command context to use.
2569 * @param rc Guest rc of operation (note: IPRT-style signed int).
2570 * @param uFileHandle File handle of opened file on success.
2571 */
2572VBGLR3DECL(int) VbglR3GuestCtrlFileCbOpen(PVBGLR3GUESTCTRLCMDCTX pCtx,
2573 int rc, uint32_t uFileHandle)
2574{
2575 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
2576
2577 HGCMReplyFileNotify Msg;
2578 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, GUEST_MSG_FILE_NOTIFY, 4);
2579 VbglHGCMParmUInt32Set(&Msg.context, pCtx->uContextID);
2580 VbglHGCMParmUInt32Set(&Msg.type, GUEST_FILE_NOTIFYTYPE_OPEN);
2581 VbglHGCMParmUInt32Set(&Msg.rc, (uint32_t)rc);
2582 VbglHGCMParmUInt32Set(&Msg.u.open.handle, uFileHandle);
2583
2584 return VbglR3HGCMCall(&Msg.hdr, RT_UOFFSET_AFTER(HGCMReplyFileNotify, u.open));
2585}
2586
2587
2588/**
2589 * Replies to a HOST_MSG_FILE_CLOSE message.
2590 *
2591 * @returns VBox status code.
2592 * @param pCtx Guest control command context to use.
2593 * @param rc Guest rc of operation (note: IPRT-style signed int).
2594 */
2595VBGLR3DECL(int) VbglR3GuestCtrlFileCbClose(PVBGLR3GUESTCTRLCMDCTX pCtx, int rc)
2596{
2597 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
2598
2599 HGCMReplyFileNotify Msg;
2600 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, GUEST_MSG_FILE_NOTIFY, 3);
2601 VbglHGCMParmUInt32Set(&Msg.context, pCtx->uContextID);
2602 VbglHGCMParmUInt32Set(&Msg.type, GUEST_FILE_NOTIFYTYPE_CLOSE);
2603 VbglHGCMParmUInt32Set(&Msg.rc, (uint32_t)rc);
2604
2605 return VbglR3HGCMCall(&Msg.hdr, RT_UOFFSETOF(HGCMReplyFileNotify, u));
2606}
2607
2608
2609/**
2610 * Sends an unexpected file handling error to the host.
2611 *
2612 * @returns VBox status code.
2613 * @param pCtx Guest control command context to use.
2614 * @param rc Guest rc of operation (note: IPRT-style signed int).
2615 */
2616VBGLR3DECL(int) VbglR3GuestCtrlFileCbError(PVBGLR3GUESTCTRLCMDCTX pCtx, int rc)
2617{
2618 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
2619
2620 HGCMReplyFileNotify Msg;
2621 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, GUEST_MSG_FILE_NOTIFY, 3);
2622 VbglHGCMParmUInt32Set(&Msg.context, pCtx->uContextID);
2623 VbglHGCMParmUInt32Set(&Msg.type, GUEST_FILE_NOTIFYTYPE_ERROR);
2624 VbglHGCMParmUInt32Set(&Msg.rc, (uint32_t)rc);
2625
2626 return VbglR3HGCMCall(&Msg.hdr, RT_UOFFSETOF(HGCMReplyFileNotify, u));
2627}
2628
2629
2630/**
2631 * Replies to a HOST_MSG_FILE_READ message.
2632 *
2633 * @returns VBox status code.
2634 * @param pCtx Guest control command context to use.
2635 * @param rc Guest rc of operation (note: IPRT-style signed int).
2636 * @param pvData Pointer to read file data from guest on success.
2637 * @param cbData Size (in bytes) of read file data from guest on success.
2638 */
2639VBGLR3DECL(int) VbglR3GuestCtrlFileCbRead(PVBGLR3GUESTCTRLCMDCTX pCtx,
2640 int rc,
2641 void *pvData, uint32_t cbData)
2642{
2643 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
2644
2645 HGCMReplyFileNotify Msg;
2646 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, GUEST_MSG_FILE_NOTIFY, 4);
2647 VbglHGCMParmUInt32Set(&Msg.context, pCtx->uContextID);
2648 VbglHGCMParmUInt32Set(&Msg.type, GUEST_FILE_NOTIFYTYPE_READ);
2649 VbglHGCMParmUInt32Set(&Msg.rc, (uint32_t)rc);
2650 VbglHGCMParmPtrSet(&Msg.u.read.data, pvData, cbData);
2651
2652 return VbglR3HGCMCall(&Msg.hdr, RT_UOFFSET_AFTER(HGCMReplyFileNotify, u.read));
2653}
2654
2655
2656/**
2657 * Replies to a HOST_MSG_FILE_READ_AT message.
2658 *
2659 * @returns VBox status code.
2660 * @param pCtx Guest control command context to use.
2661 * @param rc Guest rc of operation (note: IPRT-style signed int).
2662 * @param pvData Pointer to read file data from guest on success.
2663 * @param cbData Size (in bytes) of read file data from guest on success.
2664 * @param offNew New offset (in bytes) the guest file pointer points at on success.
2665 */
2666VBGLR3DECL(int) VbglR3GuestCtrlFileCbReadOffset(PVBGLR3GUESTCTRLCMDCTX pCtx, int rc,
2667 void *pvData, uint32_t cbData, int64_t offNew)
2668{
2669 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
2670
2671 HGCMReplyFileNotify Msg;
2672 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, GUEST_MSG_FILE_NOTIFY, 5);
2673 VbglHGCMParmUInt32Set(&Msg.context, pCtx->uContextID);
2674 VbglHGCMParmUInt32Set(&Msg.type, GUEST_FILE_NOTIFYTYPE_READ_OFFSET);
2675 VbglHGCMParmUInt32Set(&Msg.rc, (uint32_t)rc);
2676 VbglHGCMParmPtrSet(&Msg.u.ReadOffset.pvData, pvData, cbData);
2677 VbglHGCMParmUInt64Set(&Msg.u.ReadOffset.off64New, (uint64_t)offNew);
2678
2679 return VbglR3HGCMCall(&Msg.hdr, RT_UOFFSET_AFTER(HGCMReplyFileNotify, u.ReadOffset));
2680}
2681
2682
2683/**
2684 * Replies to a HOST_MSG_FILE_WRITE message.
2685 *
2686 * @returns VBox status code.
2687 * @param pCtx Guest control command context to use.
2688 * @param rc Guest rc of operation (note: IPRT-style signed int).
2689 * @param cbWritten Size (in bytes) of file data successfully written to guest file. Can be partial.
2690 */
2691VBGLR3DECL(int) VbglR3GuestCtrlFileCbWrite(PVBGLR3GUESTCTRLCMDCTX pCtx, int rc, uint32_t cbWritten)
2692{
2693 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
2694
2695 HGCMReplyFileNotify Msg;
2696 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, GUEST_MSG_FILE_NOTIFY, 4);
2697 VbglHGCMParmUInt32Set(&Msg.context, pCtx->uContextID);
2698 VbglHGCMParmUInt32Set(&Msg.type, GUEST_FILE_NOTIFYTYPE_WRITE);
2699 VbglHGCMParmUInt32Set(&Msg.rc, (uint32_t)rc);
2700 VbglHGCMParmUInt32Set(&Msg.u.write.written, cbWritten);
2701
2702 return VbglR3HGCMCall(&Msg.hdr, RT_UOFFSET_AFTER(HGCMReplyFileNotify, u.write));
2703}
2704
2705
2706/**
2707 * Replies to a HOST_MSG_FILE_WRITE_AT message.
2708 *
2709 * @returns VBox status code.
2710 * @param pCtx Guest control command context to use.
2711 * @param rc Guest rc of operation (note: IPRT-style signed int).
2712 * @param cbWritten Size (in bytes) of file data successfully written to guest file. Can be partial.
2713 * @param offNew New offset (in bytes) the guest file pointer points at on success.
2714 */
2715VBGLR3DECL(int) VbglR3GuestCtrlFileCbWriteOffset(PVBGLR3GUESTCTRLCMDCTX pCtx, int rc, uint32_t cbWritten, int64_t offNew)
2716{
2717 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
2718
2719 HGCMReplyFileNotify Msg;
2720 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, GUEST_MSG_FILE_NOTIFY, 5);
2721 VbglHGCMParmUInt32Set(&Msg.context, pCtx->uContextID);
2722 VbglHGCMParmUInt32Set(&Msg.type, GUEST_FILE_NOTIFYTYPE_WRITE_OFFSET);
2723 VbglHGCMParmUInt32Set(&Msg.rc, (uint32_t)rc);
2724 VbglHGCMParmUInt32Set(&Msg.u.WriteOffset.cb32Written, cbWritten);
2725 VbglHGCMParmUInt64Set(&Msg.u.WriteOffset.off64New, (uint64_t)offNew);
2726
2727 return VbglR3HGCMCall(&Msg.hdr, RT_UOFFSET_AFTER(HGCMReplyFileNotify, u.WriteOffset));
2728}
2729
2730
2731/**
2732 * Replies to a HOST_MSG_FILE_SEEK message.
2733 *
2734 * @returns VBox status code.
2735 * @param pCtx Guest control command context to use.
2736 * @param rc Guest rc of operation (note: IPRT-style signed int).
2737 * @param offCurrent New offset (in bytes) the guest file pointer points at on success.
2738 */
2739VBGLR3DECL(int) VbglR3GuestCtrlFileCbSeek(PVBGLR3GUESTCTRLCMDCTX pCtx, int rc, uint64_t offCurrent)
2740{
2741 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
2742
2743 HGCMReplyFileNotify Msg;
2744 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, GUEST_MSG_FILE_NOTIFY, 4);
2745 VbglHGCMParmUInt32Set(&Msg.context, pCtx->uContextID);
2746 VbglHGCMParmUInt32Set(&Msg.type, GUEST_FILE_NOTIFYTYPE_SEEK);
2747 VbglHGCMParmUInt32Set(&Msg.rc, (uint32_t)rc);
2748 VbglHGCMParmUInt64Set(&Msg.u.seek.offset, offCurrent);
2749
2750 return VbglR3HGCMCall(&Msg.hdr, RT_UOFFSET_AFTER(HGCMReplyFileNotify, u.seek));
2751}
2752
2753
2754/**
2755 * Replies to a HOST_MSG_FILE_TELL message.
2756 *
2757 * @returns VBox status code.
2758 * @param pCtx Guest control command context to use.
2759 * @param rc Guest rc of operation (note: IPRT-style signed int).
2760 * @param offCurrent Current offset (in bytes) the guest file pointer points at on success.
2761 */
2762VBGLR3DECL(int) VbglR3GuestCtrlFileCbTell(PVBGLR3GUESTCTRLCMDCTX pCtx, int rc, uint64_t offCurrent)
2763{
2764 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
2765
2766 HGCMReplyFileNotify Msg;
2767 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, GUEST_MSG_FILE_NOTIFY, 4);
2768 VbglHGCMParmUInt32Set(&Msg.context, pCtx->uContextID);
2769 VbglHGCMParmUInt32Set(&Msg.type, GUEST_FILE_NOTIFYTYPE_TELL);
2770 VbglHGCMParmUInt32Set(&Msg.rc, (uint32_t)rc);
2771 VbglHGCMParmUInt64Set(&Msg.u.tell.offset, offCurrent);
2772
2773 return VbglR3HGCMCall(&Msg.hdr, RT_UOFFSET_AFTER(HGCMReplyFileNotify, u.tell));
2774}
2775
2776
2777/**
2778 * Replies to a HOST_MSG_FILE_SET_SIZE message.
2779 *
2780 * @returns VBox status code.
2781 * @param pCtx Guest control command context to use.
2782 * @param rc Guest rc of operation (note: IPRT-style signed int).
2783 * @param cbNew New file size (in bytes) of the guest file on success.
2784 */
2785VBGLR3DECL(int) VbglR3GuestCtrlFileCbSetSize(PVBGLR3GUESTCTRLCMDCTX pCtx, int rc, uint64_t cbNew)
2786{
2787 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
2788
2789 HGCMReplyFileNotify Msg;
2790 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, GUEST_MSG_FILE_NOTIFY, 4);
2791 VbglHGCMParmUInt32Set(&Msg.context, pCtx->uContextID);
2792 VbglHGCMParmUInt32Set(&Msg.type, GUEST_FILE_NOTIFYTYPE_SET_SIZE);
2793 VbglHGCMParmUInt32Set(&Msg.rc, (uint32_t)rc);
2794 VbglHGCMParmUInt64Set(&Msg.u.SetSize.cb64Size, cbNew);
2795
2796 return VbglR3HGCMCall(&Msg.hdr, RT_UOFFSET_AFTER(HGCMReplyFileNotify, u.SetSize));
2797}
2798
2799
2800/*********************************************************************************************************************************
2801 * File system callbacks *
2802 ********************************************************************************************************************************/
2803
2804#ifdef VBOX_WITH_GSTCTL_TOOLBOX_AS_CMDS
2805/**
2806 * Replies to a HOST_MSG_FS_OBJ_QUERY_INFO message, extended version.
2807 *
2808 * @returns VBox status code.
2809 * @param pCtx Guest control command context to use.
2810 * @param rc Guest rc of operation (note: IPRT-style signed int).
2811 * @param pFsObjInfo Guest file system object information to send.
2812 * @param pszUser Associated user ID (owner, uid) as a string.
2813 * @param pszGroups Associated user groups as a string.
2814 * Multiple groups are delimited by GSTCTL_DIRENTRY_GROUPS_DELIMITER_STR,
2815 * whereas the first group always is the primary group.
2816 */
2817VBGLR3DECL(int) VbglR3GuestCtrlFsObjCbQueryInfoEx(PVBGLR3GUESTCTRLCMDCTX pCtx, int rc, PGSTCTLFSOBJINFO pFsObjInfo,
2818 const char *pszUser, const char *pszGroups)
2819{
2820 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
2821 AssertPtrReturn(pFsObjInfo, VERR_INVALID_POINTER);
2822 AssertPtrReturn(pszUser, VERR_INVALID_POINTER);
2823 AssertPtrReturn(pszGroups, VERR_INVALID_POINTER);
2824
2825 HGCMReplyFsNotify Msg;
2826 VBGL_HGCM_HDR_INIT(&Msg.reply_hdr.hdr, pCtx->uClientID, GUEST_MSG_FS_NOTIFY, GSTCTL_HGCM_REPLY_HDR_PARMS + 3);
2827 VbglHGCMParmUInt32Set(&Msg.reply_hdr.context, pCtx->uContextID);
2828 VbglHGCMParmUInt32Set(&Msg.reply_hdr.type, GUEST_FS_NOTIFYTYPE_QUERY_OBJ_INFO);
2829 VbglHGCMParmUInt32Set(&Msg.reply_hdr.rc, (uint32_t)rc);
2830
2831 VbglHGCMParmPtrSet (&Msg.u.queryobjinfo.obj_info, pFsObjInfo, sizeof(GSTCTLFSOBJINFO));
2832 VbglHGCMParmPtrSetString(&Msg.u.queryobjinfo.user, pszUser);
2833 VbglHGCMParmPtrSetString(&Msg.u.queryobjinfo.groups, pszGroups);
2834
2835 return VbglR3HGCMCall(&Msg.reply_hdr.hdr, RT_UOFFSET_AFTER(HGCMReplyFsNotify, u.queryobjinfo));
2836}
2837
2838
2839/**
2840 * Replies to a HOST_MSG_FS_OBJ_QUERY_INFO message.
2841 *
2842 * @returns VBox status code.
2843 * @param pCtx Guest control command context to use.
2844 * @param rc Guest rc of operation (note: IPRT-style signed int).
2845 * @param pFsObjInfo Guest file system object information to send.
2846 */
2847VBGLR3DECL(int) VbglR3GuestCtrlFsObjCbQueryInfo(PVBGLR3GUESTCTRLCMDCTX pCtx, int rc, PGSTCTLFSOBJINFO pFsObjInfo)
2848{
2849 char szIgnored[1] = { 0 };
2850 return VbglR3GuestCtrlFsObjCbQueryInfoEx(pCtx, rc, pFsObjInfo, szIgnored /* pszUser */, szIgnored /* pszGroups */);
2851}
2852
2853
2854/**
2855 * Replies to a HOST_MSG_FS_CREATE_TEMP message.
2856 *
2857 * @returns VBox status code.
2858 * @param pCtx Guest control command context to use.
2859 * @param rc Guest rc of operation (note: IPRT-style signed int).
2860 * @param pszPath Path of created temporary file / directory, if \a rc marks a success.
2861 * Specify an empty path on failure -- NULL is not allowed!
2862 */
2863VBGLR3DECL(int) VbglR3GuestCtrlFsCbCreateTemp(PVBGLR3GUESTCTRLCMDCTX pCtx, int rc, const char *pszPath)
2864{
2865 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
2866 AssertPtrReturn(pszPath, VERR_INVALID_POINTER);
2867
2868 HGCMReplyFsNotify Msg;
2869 VBGL_HGCM_HDR_INIT(&Msg.reply_hdr.hdr, pCtx->uClientID, GUEST_MSG_FS_NOTIFY, GSTCTL_HGCM_REPLY_HDR_PARMS + 1);
2870 VbglHGCMParmUInt32Set(&Msg.reply_hdr.context, pCtx->uContextID);
2871 VbglHGCMParmUInt32Set(&Msg.reply_hdr.type, GUEST_FS_NOTIFYTYPE_CREATE_TEMP);
2872 VbglHGCMParmUInt32Set(&Msg.reply_hdr.rc, (uint32_t)rc);
2873
2874 VbglHGCMParmPtrSetString(&Msg.u.createtemp.path, pszPath);
2875
2876 return VbglR3HGCMCall(&Msg.reply_hdr.hdr, RT_UOFFSET_AFTER(HGCMReplyFsNotify, u.createtemp));
2877}
2878
2879/**
2880 * Replies to a HOST_MSG_FS_QUERY_INFO message.
2881 *
2882 * @returns VBox status code.
2883 * @param pCtx Guest control command context to use.
2884 * @param rc Guest rc of operation (note: IPRT-style signed int).
2885 * @param pFsInfo File system information to return.
2886 * @param cbFsInfo Size (in bytes) of \a pFsInfo.
2887 */
2888VBGLR3DECL(int) VbglR3GuestCtrlFsCbQueryInfo(PVBGLR3GUESTCTRLCMDCTX pCtx, int rc, PGSTCTLFSINFO pFsInfo, uint32_t cbFsInfo)
2889{
2890 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
2891 AssertPtrReturn(pFsInfo, VERR_INVALID_POINTER);
2892 AssertReturn(cbFsInfo, VERR_INVALID_PARAMETER);
2893
2894 HGCMReplyFsNotify Msg;
2895 VBGL_HGCM_HDR_INIT(&Msg.reply_hdr.hdr, pCtx->uClientID, GUEST_MSG_FS_NOTIFY, GSTCTL_HGCM_REPLY_HDR_PARMS + 1);
2896 VbglHGCMParmUInt32Set(&Msg.reply_hdr.context, pCtx->uContextID);
2897 VbglHGCMParmUInt32Set(&Msg.reply_hdr.type, GUEST_FS_NOTIFYTYPE_QUERY_INFO);
2898 VbglHGCMParmUInt32Set(&Msg.reply_hdr.rc, (uint32_t)rc);
2899
2900 VbglHGCMParmPtrSet(&Msg.u.queryinfo.fs_info, pFsInfo, cbFsInfo);
2901
2902 return VbglR3HGCMCall(&Msg.reply_hdr.hdr, RT_UOFFSET_AFTER(HGCMReplyFsNotify, u.queryinfo));
2903}
2904#endif /* VBOX_WITH_GSTCTL_TOOLBOX_AS_CMDS */
2905
2906
2907/*********************************************************************************************************************************
2908 * Process callbacks *
2909 ********************************************************************************************************************************/
2910
2911/**
2912 * Callback for reporting a guest process status (along with some other stuff) to the host.
2913 *
2914 * @returns VBox status code.
2915 * @param pCtx Guest control command context to use.
2916 * @param uPID Guest process PID to report status for.
2917 * @param uStatus Status to report. Of type PROC_STS_XXX.
2918 * @param fFlags Additional status flags, depending on the reported status. See RTPROCSTATUS.
2919 * @param pvData Pointer to additional status data. Optional.
2920 * @param cbData Size (in bytes) of additional status data.
2921 */
2922VBGLR3DECL(int) VbglR3GuestCtrlProcCbStatus(PVBGLR3GUESTCTRLCMDCTX pCtx,
2923 uint32_t uPID, uint32_t uStatus, uint32_t fFlags,
2924 void *pvData, uint32_t cbData)
2925{
2926 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
2927
2928 HGCMMsgProcStatus Msg;
2929 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, GUEST_MSG_EXEC_STATUS, 5);
2930 VbglHGCMParmUInt32Set(&Msg.context, pCtx->uContextID);
2931 VbglHGCMParmUInt32Set(&Msg.pid, uPID);
2932 VbglHGCMParmUInt32Set(&Msg.status, uStatus);
2933 VbglHGCMParmUInt32Set(&Msg.flags, fFlags);
2934 VbglHGCMParmPtrSet(&Msg.data, pvData, cbData);
2935
2936 return VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
2937}
2938
2939
2940/**
2941 * Sends output (from stdout/stderr) from a running process.
2942 *
2943 * @returns VBox status code.
2944 * @param pCtx Guest control command context to use.
2945 * @param uPID Guest process PID to report status for.
2946 * @param uHandle Guest process handle the output belong to.
2947 * @param fFlags Additional output flags.
2948 * @param pvData Pointer to actual output data.
2949 * @param cbData Size (in bytes) of output data.
2950 */
2951VBGLR3DECL(int) VbglR3GuestCtrlProcCbOutput(PVBGLR3GUESTCTRLCMDCTX pCtx,
2952 uint32_t uPID,uint32_t uHandle, uint32_t fFlags,
2953 void *pvData, uint32_t cbData)
2954{
2955 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
2956
2957 HGCMMsgProcOutput Msg;
2958 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, GUEST_MSG_EXEC_OUTPUT, 5);
2959 VbglHGCMParmUInt32Set(&Msg.context, pCtx->uContextID);
2960 VbglHGCMParmUInt32Set(&Msg.pid, uPID);
2961 VbglHGCMParmUInt32Set(&Msg.handle, uHandle);
2962 VbglHGCMParmUInt32Set(&Msg.flags, fFlags);
2963 VbglHGCMParmPtrSet(&Msg.data, pvData, cbData);
2964
2965 return VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
2966}
2967
2968
2969/**
2970 * Callback for reporting back the input status of a guest process to the host.
2971 *
2972 * @returns VBox status code.
2973 * @param pCtx Guest control command context to use.
2974 * @param uPID Guest process PID to report status for.
2975 * @param uStatus Status to report. Of type INPUT_STS_XXX.
2976 * @param fFlags Additional input flags.
2977 * @param cbWritten Size (in bytes) of input data handled.
2978 */
2979VBGLR3DECL(int) VbglR3GuestCtrlProcCbStatusInput(PVBGLR3GUESTCTRLCMDCTX pCtx,
2980 uint32_t uPID, uint32_t uStatus,
2981 uint32_t fFlags, uint32_t cbWritten)
2982{
2983 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
2984
2985 HGCMMsgProcStatusInput Msg;
2986 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, GUEST_MSG_EXEC_INPUT_STATUS, 5);
2987 VbglHGCMParmUInt32Set(&Msg.context, pCtx->uContextID);
2988 VbglHGCMParmUInt32Set(&Msg.pid, uPID);
2989 VbglHGCMParmUInt32Set(&Msg.status, uStatus);
2990 VbglHGCMParmUInt32Set(&Msg.flags, fFlags);
2991 VbglHGCMParmUInt32Set(&Msg.written, cbWritten);
2992
2993 return VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
2994}
2995
Note: See TracBrowser for help on using the repository browser.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette