VirtualBox

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

Last change on this file since 102881 was 102881, checked in by vboxsync, 17 months ago

Guest Control/VbglR3: Also init the flags in VbglR3GuestCtrlGetMountPoints(). bugref:10415

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