VirtualBox

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

Last change on this file since 98804 was 98804, checked in by vboxsync, 21 months ago

Guest Control: Fixed the Additions burns. bugref:9783

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 102.3 KB
Line 
1/* $Id: VBoxGuestR3LibGuestCtrl.cpp 98804 2023-03-01 09:42:40Z 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.virtualbox.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * The contents of this file may alternatively be used under the terms
26 * of the Common Development and Distribution License Version 1.0
27 * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
28 * in the VirtualBox distribution, in which case the provisions of the
29 * CDDL are applicable instead of those of the GPL.
30 *
31 * You may elect to license modified versions of this file under the
32 * terms and conditions of either the GPL or the CDDL or both.
33 *
34 * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
35 */
36
37
38/*********************************************************************************************************************************
39* Header Files *
40*********************************************************************************************************************************/
41#include <iprt/string.h>
42#include <iprt/mem.h>
43#include <iprt/assert.h>
44#include <iprt/cpp/autores.h>
45#include <iprt/stdarg.h>
46#include <VBox/err.h>
47#include <VBox/log.h>
48#include <VBox/GuestHost/GuestControl.h>
49#include <VBox/HostServices/GuestControlSvc.h>
50
51#ifndef RT_OS_WINDOWS
52# include <signal.h>
53# ifdef RT_OS_DARWIN
54# include <pthread.h>
55# define sigprocmask pthread_sigmask /* On xnu sigprocmask works on the process, not the calling thread as elsewhere. */
56# endif
57#endif
58
59#include "VBoxGuestR3LibInternal.h"
60
61using namespace guestControl;
62
63
64/*********************************************************************************************************************************
65* Global Variables *
66*********************************************************************************************************************************/
67/** Set if GUEST_MSG_PEEK_WAIT and friends are supported. */
68static int g_fVbglR3GuestCtrlHavePeekGetCancel = -1;
69
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 */
993VBGLR3DECL(int) VbglR3GuestCtrlDirGetOpen(PVBGLR3GUESTCTRLCMDCTX pCtx, char *pszPath, uint32_t cbPath, uint32_t *pfFlags,
994 GSTCTLDIRFILTER *penmFilter)
995{
996 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
997 AssertReturn(pCtx->uNumParms == 4, VERR_INVALID_PARAMETER);
998
999 AssertPtrReturn(pszPath, VERR_INVALID_POINTER);
1000 AssertReturn(cbPath, VERR_INVALID_PARAMETER);
1001 AssertPtrReturn(pfFlags, VERR_INVALID_POINTER);
1002 AssertPtrReturn(penmFilter, VERR_INVALID_POINTER);
1003
1004 int rc;
1005 do
1006 {
1007 HGCMMsgDirOpen Msg;
1008 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, vbglR3GuestCtrlGetMsgFunctionNo(pCtx->uClientID), pCtx->uNumParms);
1009 VbglHGCMParmUInt32Set(&Msg.context, HOST_MSG_DIR_OPEN);
1010 VbglHGCMParmPtrSet(&Msg.path, pszPath, cbPath);
1011 VbglHGCMParmUInt32Set(&Msg.filter, 0);
1012 VbglHGCMParmUInt32Set(&Msg.flags, 0);
1013
1014 rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
1015 if (RT_SUCCESS(rc))
1016 {
1017 Msg.context.GetUInt32(&pCtx->uContextID);
1018 Msg.filter.GetUInt32((uint32_t *)penmFilter);
1019 Msg.flags.GetUInt32(pfFlags);
1020 }
1021 } while (rc == VERR_INTERRUPTED && g_fVbglR3GuestCtrlHavePeekGetCancel);
1022 return rc;
1023}
1024
1025
1026/**
1027 * Retrieves a HOST_MSG_DIR_CLOSE message.
1028 *
1029 * @returns VBox status code.
1030 * @param pCtx Guest control command context to use.
1031 * @param puHandle Where to return the handle of the guest directory to close.
1032 */
1033VBGLR3DECL(int) VbglR3GuestCtrlDirGetClose(PVBGLR3GUESTCTRLCMDCTX pCtx, uint32_t *puHandle)
1034{
1035 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1036 AssertReturn(pCtx->uNumParms == 2, VERR_INVALID_PARAMETER);
1037
1038 AssertPtrReturn(puHandle, VERR_INVALID_POINTER);
1039
1040 int rc;
1041 do
1042 {
1043 HGCMMsgDirClose Msg;
1044 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, vbglR3GuestCtrlGetMsgFunctionNo(pCtx->uClientID), pCtx->uNumParms);
1045 VbglHGCMParmUInt32Set(&Msg.context, HOST_MSG_DIR_CLOSE);
1046 VbglHGCMParmUInt32Set(&Msg.handle, 0);
1047
1048 rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
1049 if (RT_SUCCESS(rc))
1050 {
1051 Msg.context.GetUInt32(&pCtx->uContextID);
1052 Msg.handle.GetUInt32(puHandle);
1053 }
1054 } while (rc == VERR_INTERRUPTED && g_fVbglR3GuestCtrlHavePeekGetCancel);
1055 return rc;
1056}
1057
1058
1059/**
1060 * Retrieves a HOST_MSG_DIR_READ message.
1061 *
1062 * @returns VBox status code.
1063 * @param pCtx Guest control command context to use.
1064 * @param puHandle Where to return the directory handle to rewind.
1065 * @param pcbDirEntry Where to return the directory entry size.
1066 * @param penmAddAttrib Where to return the additional attributes enumeration.
1067 * @param pfFlags Where to return the directory reading flags..
1068 */
1069VBGLR3DECL(int) VbglR3GuestCtrlDirGetRead(PVBGLR3GUESTCTRLCMDCTX pCtx, uint32_t *puHandle, uint32_t *pcbDirEntry,
1070 uint32_t *penmAddAttrib, uint32_t *pfFlags)
1071{
1072 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1073 AssertReturn(pCtx->uNumParms == 5, VERR_INVALID_PARAMETER);
1074
1075 AssertPtrReturn(puHandle, VERR_INVALID_POINTER);
1076 AssertPtrReturn(pcbDirEntry, VERR_INVALID_POINTER);
1077 AssertPtrReturn(penmAddAttrib, VERR_INVALID_POINTER);
1078 AssertPtrReturn(pfFlags, VERR_INVALID_POINTER);
1079
1080 int rc;
1081 do
1082 {
1083 HGCMMsgDirRead Msg;
1084 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, vbglR3GuestCtrlGetMsgFunctionNo(pCtx->uClientID), pCtx->uNumParms);
1085 VbglHGCMParmUInt32Set(&Msg.context, HOST_MSG_DIR_READ);
1086 VbglHGCMParmUInt32Set(&Msg.handle, 0);
1087 VbglHGCMParmUInt32Set(&Msg.max_entry_size, 0);
1088 VbglHGCMParmUInt32Set(&Msg.add_attributes, 0);
1089 VbglHGCMParmUInt32Set(&Msg.flags, 0);
1090
1091 rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
1092 if (RT_SUCCESS(rc))
1093 {
1094 Msg.context.GetUInt32(&pCtx->uContextID);
1095 Msg.handle.GetUInt32(puHandle);
1096 Msg.max_entry_size.GetUInt32(pcbDirEntry);
1097 Msg.add_attributes.GetUInt32(penmAddAttrib);
1098 Msg.flags.GetUInt32(pfFlags);
1099 }
1100 } while (rc == VERR_INTERRUPTED && g_fVbglR3GuestCtrlHavePeekGetCancel);
1101 return rc;
1102}
1103
1104
1105/**
1106 * Retrieves a HOST_MSG_DIR_REWIND message.
1107 *
1108 * @returns VBox status code.
1109 * @param pCtx Guest control command context to use.
1110 * @param puHandle Where to return the directory handle to rewind.
1111 */
1112VBGLR3DECL(int) VbglR3GuestCtrlDirGetRewind(PVBGLR3GUESTCTRLCMDCTX pCtx, uint32_t *puHandle)
1113{
1114 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1115 AssertReturn(pCtx->uNumParms == 2, VERR_INVALID_PARAMETER);
1116
1117 AssertPtrReturn(puHandle, VERR_INVALID_POINTER);
1118
1119 int rc;
1120 do
1121 {
1122 HGCMMsgDirRewind Msg;
1123 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, vbglR3GuestCtrlGetMsgFunctionNo(pCtx->uClientID), pCtx->uNumParms);
1124 VbglHGCMParmUInt32Set(&Msg.context, HOST_MSG_DIR_REWIND);
1125 VbglHGCMParmUInt64Set(&Msg.handle, 0);
1126
1127 rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
1128 if (RT_SUCCESS(rc))
1129 {
1130 Msg.context.GetUInt32(&pCtx->uContextID);
1131 Msg.handle.GetUInt32(puHandle);
1132 }
1133 } while (rc == VERR_INTERRUPTED && g_fVbglR3GuestCtrlHavePeekGetCancel);
1134 return rc;
1135}
1136#endif /* VBOX_WITH_GSTCTL_TOOLBOX_AS_CMDS */
1137
1138
1139/**
1140 * Retrieves a HOST_PATH_RENAME message.
1141 */
1142VBGLR3DECL(int) VbglR3GuestCtrlPathGetRename(PVBGLR3GUESTCTRLCMDCTX pCtx,
1143 char *pszSource, uint32_t cbSource,
1144 char *pszDest, uint32_t cbDest,
1145 uint32_t *pfFlags)
1146{
1147 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1148 AssertReturn(pCtx->uNumParms == 4, VERR_INVALID_PARAMETER);
1149
1150 AssertPtrReturn(pszSource, VERR_INVALID_POINTER);
1151 AssertReturn(cbSource, VERR_INVALID_PARAMETER);
1152 AssertPtrReturn(pszDest, VERR_INVALID_POINTER);
1153 AssertReturn(cbDest, VERR_INVALID_PARAMETER);
1154 AssertPtrReturn(pfFlags, VERR_INVALID_POINTER);
1155
1156 int rc;
1157 do
1158 {
1159 HGCMMsgPathRename Msg;
1160 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, vbglR3GuestCtrlGetMsgFunctionNo(pCtx->uClientID), pCtx->uNumParms);
1161 VbglHGCMParmUInt32Set(&Msg.context, HOST_MSG_PATH_RENAME);
1162 VbglHGCMParmPtrSet(&Msg.source, pszSource, cbSource);
1163 VbglHGCMParmPtrSet(&Msg.dest, pszDest, cbDest);
1164 VbglHGCMParmUInt32Set(&Msg.flags, 0);
1165
1166 rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
1167 if (RT_SUCCESS(rc))
1168 {
1169 Msg.context.GetUInt32(&pCtx->uContextID);
1170 Msg.flags.GetUInt32(pfFlags);
1171 }
1172
1173 } while (rc == VERR_INTERRUPTED && g_fVbglR3GuestCtrlHavePeekGetCancel);
1174 return rc;
1175}
1176
1177
1178/**
1179 * Retrieves a HOST_PATH_USER_DOCUMENTS message.
1180 */
1181VBGLR3DECL(int) VbglR3GuestCtrlPathGetUserDocuments(PVBGLR3GUESTCTRLCMDCTX pCtx)
1182{
1183 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1184 AssertReturn(pCtx->uNumParms == 1, VERR_INVALID_PARAMETER);
1185
1186 int rc;
1187 do
1188 {
1189 HGCMMsgPathUserDocuments Msg;
1190 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, vbglR3GuestCtrlGetMsgFunctionNo(pCtx->uClientID), pCtx->uNumParms);
1191 VbglHGCMParmUInt32Set(&Msg.context, HOST_MSG_PATH_USER_DOCUMENTS);
1192
1193 rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
1194 if (RT_SUCCESS(rc))
1195 Msg.context.GetUInt32(&pCtx->uContextID);
1196 } while (rc == VERR_INTERRUPTED && g_fVbglR3GuestCtrlHavePeekGetCancel);
1197 return rc;
1198}
1199
1200
1201/**
1202 * Retrieves a HOST_PATH_USER_HOME message.
1203 */
1204VBGLR3DECL(int) VbglR3GuestCtrlPathGetUserHome(PVBGLR3GUESTCTRLCMDCTX pCtx)
1205{
1206 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1207 AssertReturn(pCtx->uNumParms == 1, VERR_INVALID_PARAMETER);
1208
1209 int rc;
1210 do
1211 {
1212 HGCMMsgPathUserHome Msg;
1213 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, vbglR3GuestCtrlGetMsgFunctionNo(pCtx->uClientID), pCtx->uNumParms);
1214 VbglHGCMParmUInt32Set(&Msg.context, HOST_MSG_PATH_USER_HOME);
1215
1216 rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
1217 if (RT_SUCCESS(rc))
1218 Msg.context.GetUInt32(&pCtx->uContextID);
1219 } while (rc == VERR_INTERRUPTED && g_fVbglR3GuestCtrlHavePeekGetCancel);
1220 return rc;
1221}
1222
1223
1224#ifdef VBOX_WITH_GSTCTL_TOOLBOX_AS_CMDS
1225/**
1226 * Retrieves a HOST_MSG_FS_QUERY_INFO message.
1227 *
1228 * @returns VBox status code.
1229 * @param pCtx Guest control command context to use.
1230 * @param pszPath Where to return the path of the file system object to query.
1231 * @param cbPath Size (in bytes) of \a pszPath.
1232 * @param penmAddAttrib Where to return the additional attributes enumeration.
1233 * @param pfFlags Where to return the flags for .
1234 */
1235VBGLR3DECL(int) VbglR3GuestCtrlFsGetQueryInfo(PVBGLR3GUESTCTRLCMDCTX pCtx,
1236 char *pszPath, uint32_t cbPath, GSTCTLFSOBJATTRADD *penmAddAttrib, uint32_t *pfFlags)
1237{
1238 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1239 AssertReturn(pCtx->uNumParms == 4, VERR_INVALID_PARAMETER);
1240
1241 AssertPtrReturn(pszPath, VERR_INVALID_POINTER);
1242 AssertReturn(cbPath, VERR_INVALID_PARAMETER);
1243 AssertPtrReturn(penmAddAttrib, VERR_INVALID_POINTER);
1244 AssertPtrReturn(pfFlags, VERR_INVALID_POINTER);
1245
1246 int rc;
1247 do
1248 {
1249 HGCMMsgFsQueryInfo Msg;
1250 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, vbglR3GuestCtrlGetMsgFunctionNo(pCtx->uClientID), pCtx->uNumParms);
1251 VbglHGCMParmUInt32Set(&Msg.context, HOST_MSG_FS_QUERY_INFO);
1252 VbglHGCMParmPtrSet(&Msg.path, pszPath, cbPath);
1253 VbglHGCMParmUInt32Set(&Msg.add_attributes, 0);
1254 VbglHGCMParmUInt32Set(&Msg.flags, 0);
1255
1256 rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
1257 if (RT_SUCCESS(rc))
1258 {
1259 Msg.context.GetUInt32(&pCtx->uContextID);
1260 Msg.add_attributes.GetUInt32((uint32_t *)penmAddAttrib);
1261 Msg.flags.GetUInt32(pfFlags);
1262 }
1263
1264 } while (rc == VERR_INTERRUPTED && g_fVbglR3GuestCtrlHavePeekGetCancel);
1265 return rc;
1266}
1267
1268
1269/**
1270 * Retrieves a HOST_MSG_FS_CREATE_TEMP message.
1271 *
1272 * @returns VBox status code.
1273 * @param pCtx Guest control command context to use.
1274 * @param pszTemplate Where to return the template name.
1275 * @param cbTemplate Size (in bytes) of \a pszTemplate.
1276 * @param pszPath Where to return the temporary directory path.
1277 * @param cbTemplate Size (in bytes) of \a pszPath.
1278 * @param pfFlags Where to return the creation flags.
1279 * @param pfMode Where to return the creation mode.
1280 */
1281VBGLR3DECL(int) VbglR3GuestCtrlFsGetCreateTemp(PVBGLR3GUESTCTRLCMDCTX pCtx,
1282 char *pszTemplate, uint32_t cbTemplate, char *pszPath, uint32_t cbPath,
1283 uint32_t *pfFlags, uint32_t *pfMode)
1284{
1285 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1286 AssertReturn(pCtx->uNumParms == 5, VERR_INVALID_PARAMETER);
1287
1288 AssertPtrReturn(pszTemplate, VERR_INVALID_POINTER);
1289 AssertReturn(cbTemplate, VERR_INVALID_PARAMETER);
1290 AssertPtrReturn(pszPath, VERR_INVALID_POINTER);
1291 AssertReturn(cbPath, VERR_INVALID_PARAMETER);
1292 AssertPtrReturn(pfFlags, VERR_INVALID_POINTER);
1293 AssertPtrReturn(pfMode, VERR_INVALID_POINTER);
1294
1295 int rc;
1296 do
1297 {
1298 HGCMMsgFsCreateTemp Msg;
1299 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, vbglR3GuestCtrlGetMsgFunctionNo(pCtx->uClientID), pCtx->uNumParms);
1300 VbglHGCMParmUInt32Set(&Msg.context, HOST_MSG_FS_CREATE_TEMP);
1301 VbglHGCMParmPtrSet(&Msg.template_name, pszTemplate, cbTemplate);
1302 VbglHGCMParmPtrSet(&Msg.tmpdir, pszPath, cbPath);
1303 VbglHGCMParmUInt32Set(&Msg.flags, 0);
1304 VbglHGCMParmUInt32Set(&Msg.mode, 0);
1305
1306 rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
1307 if (RT_SUCCESS(rc))
1308 {
1309 Msg.context.GetUInt32(&pCtx->uContextID);
1310 Msg.flags.GetUInt32(pfFlags);
1311 Msg.mode.GetUInt32(pfMode);
1312 }
1313
1314 } while (rc == VERR_INTERRUPTED && g_fVbglR3GuestCtrlHavePeekGetCancel);
1315 return rc;
1316}
1317#endif /* VBOX_WITH_GSTCTL_TOOLBOX_AS_CMDS */
1318
1319
1320/**
1321 * Retrieves a HOST_MSG_SHUTDOWN message.
1322 *
1323 * @returns VBox status code.
1324 * @param pCtx Guest control command context to use.
1325 * @param pfAction Where to store the action flags on success.
1326 */
1327VBGLR3DECL(int) VbglR3GuestCtrlGetShutdown(PVBGLR3GUESTCTRLCMDCTX pCtx, uint32_t *pfAction)
1328{
1329 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1330 AssertReturn(pCtx->uNumParms == 2, VERR_INVALID_PARAMETER);
1331 AssertPtrReturn(pfAction, VERR_INVALID_POINTER);
1332
1333 int rc;
1334 do
1335 {
1336 HGCMMsgShutdown Msg;
1337 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, vbglR3GuestCtrlGetMsgFunctionNo(pCtx->uClientID), pCtx->uNumParms);
1338 VbglHGCMParmUInt32Set(&Msg.context, HOST_MSG_SHUTDOWN);
1339 VbglHGCMParmUInt32Set(&Msg.action, 0);
1340
1341 rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
1342 if (RT_SUCCESS(rc))
1343 {
1344 Msg.context.GetUInt32(&pCtx->uContextID);
1345 Msg.action.GetUInt32(pfAction);
1346 }
1347 } while (rc == VERR_INTERRUPTED && g_fVbglR3GuestCtrlHavePeekGetCancel);
1348 return rc;
1349}
1350
1351/**
1352 * Initializes a process startup info, extended version.
1353 *
1354 * @returns VBox status code.
1355 * @param pStartupInfo Process startup info to initializes.
1356 * @param cbCmd Size (in bytes) to use for the command buffer.
1357 * @param cbUser Size (in bytes) to use for the user name buffer.
1358 * @param cbPassword Size (in bytes) to use for the password buffer.
1359 * @param cbDomain Size (in bytes) to use for the domain buffer.
1360 * @param cbArgs Size (in bytes) to use for the arguments buffer.
1361 * @param cbEnv Size (in bytes) to use for the environment buffer.
1362 */
1363VBGLR3DECL(int) VbglR3GuestCtrlProcStartupInfoInitEx(PVBGLR3GUESTCTRLPROCSTARTUPINFO pStartupInfo,
1364 size_t cbCmd,
1365 size_t cbUser, size_t cbPassword, size_t cbDomain,
1366 size_t cbArgs, size_t cbEnv)
1367{
1368 AssertPtrReturn(pStartupInfo, VERR_INVALID_POINTER);
1369 AssertReturn(cbCmd, VERR_INVALID_PARAMETER);
1370 AssertReturn(cbUser, VERR_INVALID_PARAMETER);
1371 AssertReturn(cbPassword, VERR_INVALID_PARAMETER);
1372 AssertReturn(cbDomain, VERR_INVALID_PARAMETER);
1373 AssertReturn(cbArgs, VERR_INVALID_PARAMETER);
1374 AssertReturn(cbEnv, VERR_INVALID_PARAMETER);
1375
1376 RT_BZERO(pStartupInfo, sizeof(VBGLR3GUESTCTRLPROCSTARTUPINFO));
1377
1378#define ALLOC_STR(a_Str, a_cb) \
1379 if ((a_cb) > 0) \
1380 { \
1381 pStartupInfo->psz##a_Str = RTStrAlloc(a_cb); \
1382 AssertPtrBreak(pStartupInfo->psz##a_Str); \
1383 pStartupInfo->cb##a_Str = (uint32_t)a_cb; \
1384 }
1385
1386 do
1387 {
1388 ALLOC_STR(Cmd, cbCmd);
1389 ALLOC_STR(Args, cbArgs);
1390 ALLOC_STR(Env, cbEnv);
1391 ALLOC_STR(User, cbUser);
1392 ALLOC_STR(Password, cbPassword);
1393 ALLOC_STR(Domain, cbDomain);
1394
1395 return VINF_SUCCESS;
1396
1397 } while (0);
1398
1399#undef ALLOC_STR
1400
1401 VbglR3GuestCtrlProcStartupInfoDestroy(pStartupInfo);
1402 return VERR_NO_MEMORY;
1403}
1404
1405/**
1406 * Initializes a process startup info with default values.
1407 *
1408 * @param pStartupInfo Process startup info to initializes.
1409 */
1410VBGLR3DECL(int) VbglR3GuestCtrlProcStartupInfoInit(PVBGLR3GUESTCTRLPROCSTARTUPINFO pStartupInfo)
1411{
1412 return VbglR3GuestCtrlProcStartupInfoInitEx(pStartupInfo,
1413 GUEST_PROC_DEF_CMD_LEN,
1414 GUEST_PROC_DEF_USER_LEN /* Deprecated, now handled via session creation. */,
1415 GUEST_PROC_DEF_PASSWORD_LEN /* Ditto. */,
1416 GUEST_PROC_DEF_DOMAIN_LEN /* Ditto. */,
1417 GUEST_PROC_DEF_ARGS_LEN, GUEST_PROC_DEF_ENV_LEN);
1418}
1419
1420/**
1421 * Destroys a process startup info.
1422 *
1423 * @param pStartupInfo Process startup info to destroy.
1424 */
1425VBGLR3DECL(void) VbglR3GuestCtrlProcStartupInfoDestroy(PVBGLR3GUESTCTRLPROCSTARTUPINFO pStartupInfo)
1426{
1427 if (!pStartupInfo)
1428 return;
1429
1430 RTStrFree(pStartupInfo->pszCmd);
1431 RTStrFree(pStartupInfo->pszArgs);
1432 RTStrFree(pStartupInfo->pszEnv);
1433 RTStrFree(pStartupInfo->pszUser);
1434 RTStrFree(pStartupInfo->pszPassword);
1435 RTStrFree(pStartupInfo->pszDomain);
1436
1437 RT_BZERO(pStartupInfo, sizeof(VBGLR3GUESTCTRLPROCSTARTUPINFO));
1438}
1439
1440/**
1441 * Free's a process startup info.
1442 *
1443 * @param pStartupInfo Process startup info to free.
1444 * The pointer will not be valid anymore after return.
1445 */
1446VBGLR3DECL(void) VbglR3GuestCtrlProcStartupInfoFree(PVBGLR3GUESTCTRLPROCSTARTUPINFO pStartupInfo)
1447{
1448 if (!pStartupInfo)
1449 return;
1450
1451 VbglR3GuestCtrlProcStartupInfoDestroy(pStartupInfo);
1452
1453 RTMemFree(pStartupInfo);
1454 pStartupInfo = NULL;
1455}
1456
1457/**
1458 * Duplicates a process startup info.
1459 *
1460 * @returns Duplicated process startup info on success, or NULL on error.
1461 * @param pStartupInfo Process startup info to duplicate.
1462 */
1463VBGLR3DECL(PVBGLR3GUESTCTRLPROCSTARTUPINFO) VbglR3GuestCtrlProcStartupInfoDup(PVBGLR3GUESTCTRLPROCSTARTUPINFO pStartupInfo)
1464{
1465 AssertPtrReturn(pStartupInfo, NULL);
1466
1467 PVBGLR3GUESTCTRLPROCSTARTUPINFO pStartupInfoDup = (PVBGLR3GUESTCTRLPROCSTARTUPINFO)
1468 RTMemDup(pStartupInfo, sizeof(VBGLR3GUESTCTRLPROCSTARTUPINFO));
1469 if (pStartupInfoDup)
1470 {
1471 do
1472 {
1473 pStartupInfoDup->pszCmd = NULL;
1474 pStartupInfoDup->pszArgs = NULL;
1475 pStartupInfoDup->pszEnv = NULL;
1476 pStartupInfoDup->pszUser = NULL;
1477 pStartupInfoDup->pszPassword = NULL;
1478 pStartupInfoDup->pszDomain = NULL;
1479
1480#define DUP_STR(a_Str) \
1481 if (pStartupInfo->cb##a_Str) \
1482 { \
1483 pStartupInfoDup->psz##a_Str = (char *)RTStrDup(pStartupInfo->psz##a_Str); \
1484 AssertPtrBreak(pStartupInfoDup->psz##a_Str); \
1485 pStartupInfoDup->cb##a_Str = (uint32_t)strlen(pStartupInfoDup->psz##a_Str) + 1 /* Include terminator */; \
1486 }
1487
1488#define DUP_MEM(a_Str) \
1489 if (pStartupInfo->cb##a_Str) \
1490 { \
1491 pStartupInfoDup->psz##a_Str = (char *)RTMemDup(pStartupInfo->psz##a_Str, pStartupInfo->cb##a_Str); \
1492 AssertPtrBreak(pStartupInfoDup->psz##a_Str); \
1493 pStartupInfoDup->cb##a_Str = (uint32_t)pStartupInfo->cb##a_Str; \
1494 }
1495
1496 DUP_STR(Cmd);
1497 DUP_MEM(Args);
1498 DUP_MEM(Env);
1499 DUP_STR(User);
1500 DUP_STR(Password);
1501 DUP_STR(Domain);
1502
1503#undef DUP_STR
1504#undef DUP_MEM
1505
1506 return pStartupInfoDup;
1507
1508 } while (0); /* To use break macros above. */
1509
1510 VbglR3GuestCtrlProcStartupInfoFree(pStartupInfoDup);
1511 }
1512
1513 return NULL;
1514}
1515
1516/**
1517 * Retrieves a HOST_EXEC_CMD message.
1518 *
1519 * @returns VBox status code.
1520 * @param pCtx Guest control command context to use.
1521 * @param ppStartupInfo Where to store the allocated session startup info.
1522 * Needs to be free'd by VbglR3GuestCtrlProcStartupInfoFree().
1523 */
1524VBGLR3DECL(int) VbglR3GuestCtrlProcGetStart(PVBGLR3GUESTCTRLCMDCTX pCtx, PVBGLR3GUESTCTRLPROCSTARTUPINFO *ppStartupInfo)
1525{
1526 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1527 AssertPtrReturn(ppStartupInfo, VERR_INVALID_POINTER);
1528
1529 PVBGLR3GUESTCTRLPROCSTARTUPINFO pStartupInfo
1530 = (PVBGLR3GUESTCTRLPROCSTARTUPINFO)RTMemAlloc(sizeof(VBGLR3GUESTCTRLPROCSTARTUPINFO));
1531 if (!pStartupInfo)
1532 return VERR_NO_MEMORY;
1533
1534 int rc = VbglR3GuestCtrlProcStartupInfoInit(pStartupInfo);
1535 if (RT_FAILURE(rc))
1536 {
1537 VbglR3GuestCtrlProcStartupInfoFree(pStartupInfo);
1538 return rc;
1539 }
1540
1541 unsigned cRetries = 0;
1542 const unsigned cMaxRetries = 32; /* Should be enough for now. */
1543 const unsigned cGrowthFactor = 2; /* By how much the buffers will grow if they're too small yet. */
1544
1545 do
1546 {
1547 LogRel(("VbglR3GuestCtrlProcGetStart: Retrieving\n"));
1548
1549 HGCMMsgProcExec Msg;
1550 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, vbglR3GuestCtrlGetMsgFunctionNo(pCtx->uClientID), pCtx->uNumParms);
1551 VbglHGCMParmUInt32Set(&Msg.context, HOST_MSG_EXEC_CMD);
1552 VbglHGCMParmPtrSet(&Msg.cmd, pStartupInfo->pszCmd, pStartupInfo->cbCmd);
1553 VbglHGCMParmUInt32Set(&Msg.flags, 0);
1554 VbglHGCMParmUInt32Set(&Msg.num_args, 0);
1555 VbglHGCMParmPtrSet(&Msg.args, pStartupInfo->pszArgs, pStartupInfo->cbArgs);
1556 VbglHGCMParmUInt32Set(&Msg.num_env, 0);
1557 VbglHGCMParmUInt32Set(&Msg.cb_env, 0);
1558 VbglHGCMParmPtrSet(&Msg.env, pStartupInfo->pszEnv, pStartupInfo->cbEnv);
1559 if (pCtx->uProtocol < 2)
1560 {
1561 VbglHGCMParmPtrSet(&Msg.u.v1.username, pStartupInfo->pszUser, pStartupInfo->cbUser);
1562 VbglHGCMParmPtrSet(&Msg.u.v1.password, pStartupInfo->pszPassword, pStartupInfo->cbPassword);
1563 VbglHGCMParmUInt32Set(&Msg.u.v1.timeout, 0);
1564 }
1565 else
1566 {
1567 VbglHGCMParmUInt32Set(&Msg.u.v2.timeout, 0);
1568 VbglHGCMParmUInt32Set(&Msg.u.v2.priority, 0);
1569 VbglHGCMParmUInt32Set(&Msg.u.v2.num_affinity, 0);
1570 VbglHGCMParmPtrSet(&Msg.u.v2.affinity, pStartupInfo->uAffinity, sizeof(pStartupInfo->uAffinity));
1571 }
1572
1573 rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
1574 if (RT_FAILURE(rc))
1575 {
1576 LogRel(("VbglR3GuestCtrlProcGetStart: 1 - %Rrc (retry %u, cbCmd=%RU32, cbArgs=%RU32, cbEnv=%RU32)\n",
1577 rc, cRetries, pStartupInfo->cbCmd, pStartupInfo->cbArgs, pStartupInfo->cbEnv));
1578
1579 if ( rc == VERR_BUFFER_OVERFLOW
1580 && cRetries++ < cMaxRetries)
1581 {
1582#define GROW_STR(a_Str, a_cbMax) \
1583 pStartupInfo->psz##a_Str = (char *)RTMemRealloc(pStartupInfo->psz##a_Str, \
1584 RT_MIN(pStartupInfo->cb##a_Str * cGrowthFactor, a_cbMax)); \
1585 AssertPtrBreakStmt(pStartupInfo->psz##a_Str, VERR_NO_MEMORY); \
1586 pStartupInfo->cb##a_Str = RT_MIN(pStartupInfo->cb##a_Str * cGrowthFactor, a_cbMax);
1587
1588 /* We can't tell which parameter doesn't fit, so we have to resize all. */
1589 GROW_STR(Cmd , GUEST_PROC_MAX_CMD_LEN);
1590 GROW_STR(Args, GUEST_PROC_MAX_ARGS_LEN);
1591 GROW_STR(Env, GUEST_PROC_MAX_ENV_LEN);
1592
1593#undef GROW_STR
1594 LogRel(("VbglR3GuestCtrlProcGetStart: 2 - %Rrc (retry %u, cbCmd=%RU32, cbArgs=%RU32, cbEnv=%RU32)\n",
1595 rc, cRetries, pStartupInfo->cbCmd, pStartupInfo->cbArgs, pStartupInfo->cbEnv));
1596 LogRel(("g_fVbglR3GuestCtrlHavePeekGetCancel=%RTbool\n", RT_BOOL(g_fVbglR3GuestCtrlHavePeekGetCancel)));
1597 }
1598 else
1599 break;
1600 }
1601 else
1602 {
1603 Msg.context.GetUInt32(&pCtx->uContextID);
1604 Msg.flags.GetUInt32(&pStartupInfo->fFlags);
1605 Msg.num_args.GetUInt32(&pStartupInfo->cArgs);
1606 Msg.num_env.GetUInt32(&pStartupInfo->cEnvVars);
1607 Msg.cb_env.GetUInt32(&pStartupInfo->cbEnv);
1608 if (pCtx->uProtocol < 2)
1609 Msg.u.v1.timeout.GetUInt32(&pStartupInfo->uTimeLimitMS);
1610 else
1611 {
1612 Msg.u.v2.timeout.GetUInt32(&pStartupInfo->uTimeLimitMS);
1613 Msg.u.v2.priority.GetUInt32(&pStartupInfo->uPriority);
1614 Msg.u.v2.num_affinity.GetUInt32(&pStartupInfo->cAffinity);
1615 }
1616 }
1617 } while (( rc == VERR_INTERRUPTED
1618 || rc == VERR_BUFFER_OVERFLOW) && g_fVbglR3GuestCtrlHavePeekGetCancel);
1619
1620 if (RT_SUCCESS(rc))
1621 {
1622 *ppStartupInfo = pStartupInfo;
1623 }
1624 else
1625 VbglR3GuestCtrlProcStartupInfoFree(pStartupInfo);
1626
1627 LogRel(("VbglR3GuestCtrlProcGetStart: Returning %Rrc (retry %u, cbCmd=%RU32, cbArgs=%RU32, cbEnv=%RU32)\n",
1628 rc, cRetries, pStartupInfo->cbCmd, pStartupInfo->cbArgs, pStartupInfo->cbEnv));
1629
1630 LogFlowFuncLeaveRC(rc);
1631 return rc;
1632}
1633
1634/**
1635 * Allocates and gets host data, based on the message ID.
1636 *
1637 * This will block until data becomes available.
1638 *
1639 * @returns VBox status code.
1640 * @param pCtx Guest control command context to use.
1641 * @param puPID Where to return the guest PID to retrieve output from on success.
1642 * @param puHandle Where to return the guest process handle to retrieve output from on success.
1643 * @param pfFlags Where to return the output flags on success.
1644 */
1645VBGLR3DECL(int) VbglR3GuestCtrlProcGetOutput(PVBGLR3GUESTCTRLCMDCTX pCtx,
1646 uint32_t *puPID, uint32_t *puHandle, uint32_t *pfFlags)
1647{
1648 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1649 AssertReturn(pCtx->uNumParms == 4, VERR_INVALID_PARAMETER);
1650
1651 AssertPtrReturn(puPID, VERR_INVALID_POINTER);
1652 AssertPtrReturn(puHandle, VERR_INVALID_POINTER);
1653 AssertPtrReturn(pfFlags, VERR_INVALID_POINTER);
1654
1655 int rc;
1656 do
1657 {
1658 HGCMMsgProcOutput Msg;
1659 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, vbglR3GuestCtrlGetMsgFunctionNo(pCtx->uClientID), pCtx->uNumParms);
1660 VbglHGCMParmUInt32Set(&Msg.context, HOST_MSG_EXEC_GET_OUTPUT);
1661 VbglHGCMParmUInt32Set(&Msg.pid, 0);
1662 VbglHGCMParmUInt32Set(&Msg.handle, 0);
1663 VbglHGCMParmUInt32Set(&Msg.flags, 0);
1664
1665 rc = VbglR3HGCMCall(&Msg.hdr, RT_UOFFSETOF(HGCMMsgProcOutput, data));
1666 if (RT_SUCCESS(rc))
1667 {
1668 Msg.context.GetUInt32(&pCtx->uContextID);
1669 Msg.pid.GetUInt32(puPID);
1670 Msg.handle.GetUInt32(puHandle);
1671 Msg.flags.GetUInt32(pfFlags);
1672 }
1673 } while (rc == VERR_INTERRUPTED && g_fVbglR3GuestCtrlHavePeekGetCancel);
1674 return rc;
1675}
1676
1677
1678/**
1679 * Retrieves the input data from host which then gets sent to the started
1680 * process (HOST_EXEC_SET_INPUT).
1681 *
1682 * This will block until data becomes available.
1683 */
1684VBGLR3DECL(int) VbglR3GuestCtrlProcGetInput(PVBGLR3GUESTCTRLCMDCTX pCtx,
1685 uint32_t *puPID, uint32_t *pfFlags,
1686 void *pvData, uint32_t cbData,
1687 uint32_t *pcbSize)
1688{
1689 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1690 AssertReturn(pCtx->uNumParms == 5, VERR_INVALID_PARAMETER);
1691
1692 AssertPtrReturn(puPID, VERR_INVALID_POINTER);
1693 AssertPtrReturn(pfFlags, VERR_INVALID_POINTER);
1694 AssertPtrReturn(pvData, VERR_INVALID_POINTER);
1695 AssertPtrReturn(pcbSize, VERR_INVALID_POINTER);
1696
1697 int rc;
1698 do
1699 {
1700 HGCMMsgProcInput Msg;
1701 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, vbglR3GuestCtrlGetMsgFunctionNo(pCtx->uClientID), pCtx->uNumParms);
1702 VbglHGCMParmUInt32Set(&Msg.context, HOST_MSG_EXEC_SET_INPUT);
1703 VbglHGCMParmUInt32Set(&Msg.pid, 0);
1704 VbglHGCMParmUInt32Set(&Msg.flags, 0);
1705 VbglHGCMParmPtrSet(&Msg.data, pvData, cbData);
1706 VbglHGCMParmUInt32Set(&Msg.size, 0);
1707
1708 rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
1709 if (RT_SUCCESS(rc))
1710 {
1711 Msg.context.GetUInt32(&pCtx->uContextID);
1712 Msg.pid.GetUInt32(puPID);
1713 Msg.flags.GetUInt32(pfFlags);
1714 Msg.size.GetUInt32(pcbSize);
1715 }
1716 } while (rc == VERR_INTERRUPTED && g_fVbglR3GuestCtrlHavePeekGetCancel);
1717
1718 if ( rc != VERR_TOO_MUCH_DATA
1719 || g_fVbglR3GuestCtrlHavePeekGetCancel)
1720 return rc;
1721 return VERR_BUFFER_OVERFLOW;
1722}
1723
1724
1725#ifdef VBOX_WITH_GSTCTL_TOOLBOX_AS_CMDS
1726/**
1727 * Retrieves a HOST_MSG_DIR_CREATE message.
1728 *
1729 * @returns VBox status code.
1730 * @param pCtx Guest control command context to use.
1731 * @param pszPath Where to return the path.
1732 * @param cbPath Size (in bytes) of \a pszPath.
1733 * @param pfMode Where to return the creation mode.
1734 * @param pfFlags Where to return the creation flags (GSTCTL_CREATEDIRECTORY_F_XXX).
1735 */
1736VBGLR3DECL(int) VbglR3GuestCtrlDirGetCreate(PVBGLR3GUESTCTRLCMDCTX pCtx, char *pszPath, uint32_t cbPath, uint32_t *pfMode, uint32_t *pfFlags)
1737{
1738 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1739 AssertReturn(pCtx->uNumParms == 4, VERR_INVALID_PARAMETER);
1740
1741 AssertPtrReturn(pszPath, VERR_INVALID_POINTER);
1742 AssertReturn(cbPath, VERR_INVALID_PARAMETER);
1743 AssertPtrReturn(pfFlags, VERR_INVALID_POINTER);
1744 AssertPtrReturn(pfMode, VERR_INVALID_POINTER);
1745
1746 int rc;
1747 do
1748 {
1749 HGCMMsgDirCreate Msg;
1750 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, vbglR3GuestCtrlGetMsgFunctionNo(pCtx->uClientID), pCtx->uNumParms);
1751 VbglHGCMParmUInt32Set(&Msg.context, HOST_MSG_DIR_CREATE);
1752 VbglHGCMParmPtrSet(&Msg.path, pszPath, cbPath);
1753 VbglHGCMParmUInt32Set(&Msg.mode, 0);
1754 VbglHGCMParmUInt32Set(&Msg.flags, 0);
1755
1756 rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
1757 if (RT_SUCCESS(rc))
1758 {
1759 Msg.context.GetUInt32(&pCtx->uContextID);
1760 Msg.flags.GetUInt32(pfFlags);
1761 Msg.mode.GetUInt32(pfMode);
1762 }
1763
1764 } while (rc == VERR_INTERRUPTED && g_fVbglR3GuestCtrlHavePeekGetCancel);
1765 return rc;
1766}
1767#endif /* VBOX_WITH_GSTCTL_TOOLBOX_AS_CMDS */
1768
1769
1770/**
1771 * Retrieves a HOST_DIR_REMOVE message.
1772 */
1773VBGLR3DECL(int) VbglR3GuestCtrlDirGetRemove(PVBGLR3GUESTCTRLCMDCTX pCtx,
1774 char *pszPath, uint32_t cbPath,
1775 uint32_t *pfFlags)
1776{
1777 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1778 AssertReturn(pCtx->uNumParms == 3, VERR_INVALID_PARAMETER);
1779
1780 AssertPtrReturn(pszPath, VERR_INVALID_POINTER);
1781 AssertReturn(cbPath, VERR_INVALID_PARAMETER);
1782 AssertPtrReturn(pfFlags, VERR_INVALID_POINTER);
1783
1784 int rc;
1785 do
1786 {
1787 HGCMMsgDirRemove Msg;
1788 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, vbglR3GuestCtrlGetMsgFunctionNo(pCtx->uClientID), pCtx->uNumParms);
1789 VbglHGCMParmUInt32Set(&Msg.context, HOST_MSG_DIR_REMOVE);
1790 VbglHGCMParmPtrSet(&Msg.path, pszPath, cbPath);
1791 VbglHGCMParmUInt32Set(&Msg.flags, 0);
1792
1793 rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
1794 if (RT_SUCCESS(rc))
1795 {
1796 Msg.context.GetUInt32(&pCtx->uContextID);
1797 Msg.flags.GetUInt32(pfFlags);
1798 }
1799 } while (rc == VERR_INTERRUPTED && g_fVbglR3GuestCtrlHavePeekGetCancel);
1800 return rc;
1801}
1802
1803
1804/**
1805 * Retrieves a HOST_FILE_OPEN message.
1806 */
1807VBGLR3DECL(int) VbglR3GuestCtrlFileGetOpen(PVBGLR3GUESTCTRLCMDCTX pCtx,
1808 char *pszFileName, uint32_t cbFileName,
1809 char *pszAccess, uint32_t cbAccess,
1810 char *pszDisposition, uint32_t cbDisposition,
1811 char *pszSharing, uint32_t cbSharing,
1812 uint32_t *puCreationMode,
1813 uint64_t *poffAt)
1814{
1815 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1816 AssertReturn(pCtx->uNumParms == 7, VERR_INVALID_PARAMETER);
1817
1818 AssertPtrReturn(pszFileName, VERR_INVALID_POINTER);
1819 AssertReturn(cbFileName, VERR_INVALID_PARAMETER);
1820 AssertPtrReturn(pszAccess, VERR_INVALID_POINTER);
1821 AssertReturn(cbAccess, VERR_INVALID_PARAMETER);
1822 AssertPtrReturn(pszDisposition, VERR_INVALID_POINTER);
1823 AssertReturn(cbDisposition, VERR_INVALID_PARAMETER);
1824 AssertPtrReturn(pszSharing, VERR_INVALID_POINTER);
1825 AssertReturn(cbSharing, VERR_INVALID_PARAMETER);
1826 AssertPtrReturn(puCreationMode, VERR_INVALID_POINTER);
1827 AssertPtrReturn(poffAt, VERR_INVALID_POINTER);
1828
1829 int rc;
1830 do
1831 {
1832 HGCMMsgFileOpen Msg;
1833 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, vbglR3GuestCtrlGetMsgFunctionNo(pCtx->uClientID), pCtx->uNumParms);
1834 VbglHGCMParmUInt32Set(&Msg.context, HOST_MSG_FILE_OPEN);
1835 VbglHGCMParmPtrSet(&Msg.filename, pszFileName, cbFileName);
1836 VbglHGCMParmPtrSet(&Msg.openmode, pszAccess, cbAccess);
1837 VbglHGCMParmPtrSet(&Msg.disposition, pszDisposition, cbDisposition);
1838 VbglHGCMParmPtrSet(&Msg.sharing, pszSharing, cbSharing);
1839 VbglHGCMParmUInt32Set(&Msg.creationmode, 0);
1840 VbglHGCMParmUInt64Set(&Msg.offset, 0);
1841
1842 rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
1843 if (RT_SUCCESS(rc))
1844 {
1845 Msg.context.GetUInt32(&pCtx->uContextID);
1846 Msg.creationmode.GetUInt32(puCreationMode);
1847 Msg.offset.GetUInt64(poffAt);
1848 }
1849 } while (rc == VERR_INTERRUPTED && g_fVbglR3GuestCtrlHavePeekGetCancel);
1850 return rc;
1851}
1852
1853
1854/**
1855 * Retrieves a HOST_FILE_CLOSE message.
1856 */
1857VBGLR3DECL(int) VbglR3GuestCtrlFileGetClose(PVBGLR3GUESTCTRLCMDCTX pCtx, uint32_t *puHandle)
1858{
1859 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1860
1861 AssertReturn(pCtx->uNumParms == 2, VERR_INVALID_PARAMETER);
1862 AssertPtrReturn(puHandle, VERR_INVALID_POINTER);
1863
1864 int rc;
1865 do
1866 {
1867 HGCMMsgFileClose Msg;
1868 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, vbglR3GuestCtrlGetMsgFunctionNo(pCtx->uClientID), pCtx->uNumParms);
1869 VbglHGCMParmUInt32Set(&Msg.context, HOST_MSG_FILE_CLOSE);
1870 VbglHGCMParmUInt32Set(&Msg.handle, 0);
1871
1872 rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
1873 if (RT_SUCCESS(rc))
1874 {
1875 Msg.context.GetUInt32(&pCtx->uContextID);
1876 Msg.handle.GetUInt32(puHandle);
1877 }
1878 } while (rc == VERR_INTERRUPTED && g_fVbglR3GuestCtrlHavePeekGetCancel);
1879 return rc;
1880}
1881
1882
1883/**
1884 * Retrieves a HOST_FILE_READ message.
1885 */
1886VBGLR3DECL(int) VbglR3GuestCtrlFileGetRead(PVBGLR3GUESTCTRLCMDCTX pCtx, uint32_t *puHandle, uint32_t *puToRead)
1887{
1888 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1889
1890 AssertReturn(pCtx->uNumParms == 3, VERR_INVALID_PARAMETER);
1891 AssertPtrReturn(puHandle, VERR_INVALID_POINTER);
1892 AssertPtrReturn(puToRead, VERR_INVALID_POINTER);
1893
1894 int rc;
1895 do
1896 {
1897 HGCMMsgFileRead Msg;
1898 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, vbglR3GuestCtrlGetMsgFunctionNo(pCtx->uClientID), pCtx->uNumParms);
1899 VbglHGCMParmUInt32Set(&Msg.context, HOST_MSG_FILE_READ);
1900 VbglHGCMParmUInt32Set(&Msg.handle, 0);
1901 VbglHGCMParmUInt32Set(&Msg.size, 0);
1902
1903 rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
1904 if (RT_SUCCESS(rc))
1905 {
1906 Msg.context.GetUInt32(&pCtx->uContextID);
1907 Msg.handle.GetUInt32(puHandle);
1908 Msg.size.GetUInt32(puToRead);
1909 }
1910 } while (rc == VERR_INTERRUPTED && g_fVbglR3GuestCtrlHavePeekGetCancel);
1911 return rc;
1912}
1913
1914
1915/**
1916 * Retrieves a HOST_FILE_READ_AT message.
1917 */
1918VBGLR3DECL(int) VbglR3GuestCtrlFileGetReadAt(PVBGLR3GUESTCTRLCMDCTX pCtx,
1919 uint32_t *puHandle, uint32_t *puToRead, uint64_t *poffAt)
1920{
1921 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1922
1923 AssertReturn(pCtx->uNumParms == 4, VERR_INVALID_PARAMETER);
1924 AssertPtrReturn(puHandle, VERR_INVALID_POINTER);
1925 AssertPtrReturn(puToRead, VERR_INVALID_POINTER);
1926
1927 int rc;
1928 do
1929 {
1930 HGCMMsgFileReadAt Msg;
1931 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, vbglR3GuestCtrlGetMsgFunctionNo(pCtx->uClientID), pCtx->uNumParms);
1932 VbglHGCMParmUInt32Set(&Msg.context, HOST_MSG_FILE_READ_AT);
1933 VbglHGCMParmUInt32Set(&Msg.handle, 0);
1934 VbglHGCMParmUInt64Set(&Msg.offset, 0);
1935 VbglHGCMParmUInt32Set(&Msg.size, 0);
1936
1937 rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
1938 if (RT_SUCCESS(rc))
1939 {
1940 Msg.context.GetUInt32(&pCtx->uContextID);
1941 Msg.handle.GetUInt32(puHandle);
1942 Msg.offset.GetUInt64(poffAt);
1943 Msg.size.GetUInt32(puToRead);
1944 }
1945 } while (rc == VERR_INTERRUPTED && g_fVbglR3GuestCtrlHavePeekGetCancel);
1946 return rc;
1947}
1948
1949
1950/**
1951 * Retrieves a HOST_FILE_WRITE message.
1952 */
1953VBGLR3DECL(int) VbglR3GuestCtrlFileGetWrite(PVBGLR3GUESTCTRLCMDCTX pCtx, uint32_t *puHandle,
1954 void *pvData, uint32_t cbData, uint32_t *pcbSize)
1955{
1956 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1957
1958 AssertReturn(pCtx->uNumParms == 4, VERR_INVALID_PARAMETER);
1959 AssertPtrReturn(puHandle, VERR_INVALID_POINTER);
1960 AssertPtrReturn(pvData, VERR_INVALID_POINTER);
1961 AssertReturn(cbData, VERR_INVALID_PARAMETER);
1962 AssertPtrReturn(pcbSize, VERR_INVALID_POINTER);
1963
1964 int rc;
1965 do
1966 {
1967 HGCMMsgFileWrite Msg;
1968 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, vbglR3GuestCtrlGetMsgFunctionNo(pCtx->uClientID), pCtx->uNumParms);
1969 VbglHGCMParmUInt32Set(&Msg.context, HOST_MSG_FILE_WRITE);
1970 VbglHGCMParmUInt32Set(&Msg.handle, 0);
1971 VbglHGCMParmPtrSet(&Msg.data, pvData, cbData);
1972 VbglHGCMParmUInt32Set(&Msg.size, 0);
1973
1974 rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
1975 if (RT_SUCCESS(rc))
1976 {
1977 Msg.context.GetUInt32(&pCtx->uContextID);
1978 Msg.handle.GetUInt32(puHandle);
1979 Msg.size.GetUInt32(pcbSize);
1980 }
1981 } while (rc == VERR_INTERRUPTED && g_fVbglR3GuestCtrlHavePeekGetCancel);
1982
1983 if ( rc != VERR_TOO_MUCH_DATA
1984 || g_fVbglR3GuestCtrlHavePeekGetCancel)
1985 return rc;
1986 return VERR_BUFFER_OVERFLOW;
1987}
1988
1989
1990/**
1991 * Retrieves a HOST_FILE_WRITE_AT message.
1992 */
1993VBGLR3DECL(int) VbglR3GuestCtrlFileGetWriteAt(PVBGLR3GUESTCTRLCMDCTX pCtx, uint32_t *puHandle,
1994 void *pvData, uint32_t cbData, uint32_t *pcbSize, uint64_t *poffAt)
1995{
1996 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1997
1998 AssertReturn(pCtx->uNumParms == 5, VERR_INVALID_PARAMETER);
1999 AssertPtrReturn(puHandle, VERR_INVALID_POINTER);
2000 AssertPtrReturn(pvData, VERR_INVALID_POINTER);
2001 AssertReturn(cbData, VERR_INVALID_PARAMETER);
2002 AssertPtrReturn(pcbSize, VERR_INVALID_POINTER);
2003
2004 int rc;
2005 do
2006 {
2007 HGCMMsgFileWriteAt Msg;
2008 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, vbglR3GuestCtrlGetMsgFunctionNo(pCtx->uClientID), pCtx->uNumParms);
2009 VbglHGCMParmUInt32Set(&Msg.context, HOST_MSG_FILE_WRITE_AT);
2010 VbglHGCMParmUInt32Set(&Msg.handle, 0);
2011 VbglHGCMParmPtrSet(&Msg.data, pvData, cbData);
2012 VbglHGCMParmUInt32Set(&Msg.size, 0);
2013 VbglHGCMParmUInt64Set(&Msg.offset, 0);
2014
2015 rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
2016 if (RT_SUCCESS(rc))
2017 {
2018 Msg.context.GetUInt32(&pCtx->uContextID);
2019 Msg.handle.GetUInt32(puHandle);
2020 Msg.size.GetUInt32(pcbSize);
2021 Msg.offset.GetUInt64(poffAt);
2022 }
2023 } while (rc == VERR_INTERRUPTED && g_fVbglR3GuestCtrlHavePeekGetCancel);
2024
2025 if ( rc != VERR_TOO_MUCH_DATA
2026 || g_fVbglR3GuestCtrlHavePeekGetCancel)
2027 return rc;
2028 return VERR_BUFFER_OVERFLOW;
2029}
2030
2031
2032/**
2033 * Retrieves a HOST_FILE_SEEK message.
2034 */
2035VBGLR3DECL(int) VbglR3GuestCtrlFileGetSeek(PVBGLR3GUESTCTRLCMDCTX pCtx,
2036 uint32_t *puHandle, uint32_t *puSeekMethod, uint64_t *poffAt)
2037{
2038 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
2039
2040 AssertReturn(pCtx->uNumParms == 4, VERR_INVALID_PARAMETER);
2041 AssertPtrReturn(puHandle, VERR_INVALID_POINTER);
2042 AssertPtrReturn(puSeekMethod, VERR_INVALID_POINTER);
2043 AssertPtrReturn(poffAt, VERR_INVALID_POINTER);
2044
2045 int rc;
2046 do
2047 {
2048 HGCMMsgFileSeek Msg;
2049 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, vbglR3GuestCtrlGetMsgFunctionNo(pCtx->uClientID), pCtx->uNumParms);
2050 VbglHGCMParmUInt32Set(&Msg.context, HOST_MSG_FILE_SEEK);
2051 VbglHGCMParmUInt32Set(&Msg.handle, 0);
2052 VbglHGCMParmUInt32Set(&Msg.method, 0);
2053 VbglHGCMParmUInt64Set(&Msg.offset, 0);
2054
2055 rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
2056 if (RT_SUCCESS(rc))
2057 {
2058 Msg.context.GetUInt32(&pCtx->uContextID);
2059 Msg.handle.GetUInt32(puHandle);
2060 Msg.method.GetUInt32(puSeekMethod);
2061 Msg.offset.GetUInt64(poffAt);
2062 }
2063 } while (rc == VERR_INTERRUPTED && g_fVbglR3GuestCtrlHavePeekGetCancel);
2064 return rc;
2065}
2066
2067
2068/**
2069 * Retrieves a HOST_FILE_TELL message.
2070 */
2071VBGLR3DECL(int) VbglR3GuestCtrlFileGetTell(PVBGLR3GUESTCTRLCMDCTX pCtx, uint32_t *puHandle)
2072{
2073 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
2074
2075 AssertReturn(pCtx->uNumParms == 2, VERR_INVALID_PARAMETER);
2076 AssertPtrReturn(puHandle, VERR_INVALID_POINTER);
2077
2078 int rc;
2079 do
2080 {
2081 HGCMMsgFileTell Msg;
2082 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, vbglR3GuestCtrlGetMsgFunctionNo(pCtx->uClientID), pCtx->uNumParms);
2083 VbglHGCMParmUInt32Set(&Msg.context, HOST_MSG_FILE_TELL);
2084 VbglHGCMParmUInt32Set(&Msg.handle, 0);
2085
2086 rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
2087 if (RT_SUCCESS(rc))
2088 {
2089 Msg.context.GetUInt32(&pCtx->uContextID);
2090 Msg.handle.GetUInt32(puHandle);
2091 }
2092 } while (rc == VERR_INTERRUPTED && g_fVbglR3GuestCtrlHavePeekGetCancel);
2093 return rc;
2094}
2095
2096
2097/**
2098 * Retrieves a HOST_FILE_SET_SIZE message.
2099 */
2100VBGLR3DECL(int) VbglR3GuestCtrlFileGetSetSize(PVBGLR3GUESTCTRLCMDCTX pCtx, uint32_t *puHandle, uint64_t *pcbNew)
2101{
2102 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
2103
2104 AssertReturn(pCtx->uNumParms == 3, VERR_INVALID_PARAMETER);
2105 AssertPtrReturn(puHandle, VERR_INVALID_POINTER);
2106 AssertPtrReturn(pcbNew, VERR_INVALID_POINTER);
2107
2108 int rc;
2109 do
2110 {
2111 HGCMMsgFileSetSize Msg;
2112 VBGL_HGCM_HDR_INIT(&Msg.Hdr, pCtx->uClientID, vbglR3GuestCtrlGetMsgFunctionNo(pCtx->uClientID), pCtx->uNumParms);
2113 VbglHGCMParmUInt32Set(&Msg.id32Context, HOST_MSG_FILE_SET_SIZE);
2114 VbglHGCMParmUInt32Set(&Msg.id32Handle, 0);
2115 VbglHGCMParmUInt64Set(&Msg.cb64NewSize, 0);
2116
2117 rc = VbglR3HGCMCall(&Msg.Hdr, sizeof(Msg));
2118 if (RT_SUCCESS(rc))
2119 {
2120 Msg.id32Context.GetUInt32(&pCtx->uContextID);
2121 Msg.id32Handle.GetUInt32(puHandle);
2122 Msg.cb64NewSize.GetUInt64(pcbNew);
2123 }
2124 } while (rc == VERR_INTERRUPTED && g_fVbglR3GuestCtrlHavePeekGetCancel);
2125 return rc;
2126}
2127
2128
2129#ifdef VBOX_WITH_GSTCTL_TOOLBOX_AS_CMDS
2130VBGLR3DECL(int) VbglR3GuestCtrlFileGetRemove(PVBGLR3GUESTCTRLCMDCTX pCtx, char *pszFileName, uint32_t cbFileName)
2131{
2132 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
2133
2134 AssertReturn(pCtx->uNumParms == 2, VERR_INVALID_PARAMETER);
2135 AssertPtrReturn(pszFileName, VERR_INVALID_POINTER);
2136 AssertReturn(cbFileName, VERR_INVALID_PARAMETER);
2137
2138 int rc;
2139 do
2140 {
2141 HGCMMsgFileRemove Msg;
2142 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, vbglR3GuestCtrlGetMsgFunctionNo(pCtx->uClientID), pCtx->uNumParms);
2143 VbglHGCMParmUInt32Set(&Msg.context, HOST_MSG_FILE_REMOVE);
2144 VbglHGCMParmPtrSet(&Msg.filename, pszFileName, cbFileName);
2145
2146 rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
2147 if (RT_SUCCESS(rc))
2148 {
2149 Msg.context.GetUInt32(&pCtx->uContextID);
2150 }
2151 } while (rc == VERR_INTERRUPTED && g_fVbglR3GuestCtrlHavePeekGetCancel);
2152 return rc;
2153}
2154#endif /* VBOX_WITH_GSTCTL_TOOLBOX_AS_CMDS */
2155
2156
2157/**
2158 * Retrieves a HOST_EXEC_TERMINATE message.
2159 */
2160VBGLR3DECL(int) VbglR3GuestCtrlProcGetTerminate(PVBGLR3GUESTCTRLCMDCTX pCtx, uint32_t *puPID)
2161{
2162 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
2163
2164 AssertReturn(pCtx->uNumParms == 2, VERR_INVALID_PARAMETER);
2165 AssertPtrReturn(puPID, VERR_INVALID_POINTER);
2166
2167 int rc;
2168 do
2169 {
2170 HGCMMsgProcTerminate Msg;
2171 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, vbglR3GuestCtrlGetMsgFunctionNo(pCtx->uClientID), pCtx->uNumParms);
2172 VbglHGCMParmUInt32Set(&Msg.context, HOST_MSG_EXEC_TERMINATE);
2173 VbglHGCMParmUInt32Set(&Msg.pid, 0);
2174
2175 rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
2176 if (RT_SUCCESS(rc))
2177 {
2178 Msg.context.GetUInt32(&pCtx->uContextID);
2179 Msg.pid.GetUInt32(puPID);
2180 }
2181 } while (rc == VERR_INTERRUPTED && g_fVbglR3GuestCtrlHavePeekGetCancel);
2182 return rc;
2183}
2184
2185
2186/**
2187 * Retrieves a HOST_EXEC_WAIT_FOR message.
2188 */
2189VBGLR3DECL(int) VbglR3GuestCtrlProcGetWaitFor(PVBGLR3GUESTCTRLCMDCTX pCtx,
2190 uint32_t *puPID, uint32_t *puWaitFlags, uint32_t *puTimeoutMS)
2191{
2192 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
2193
2194 AssertReturn(pCtx->uNumParms == 5, VERR_INVALID_PARAMETER);
2195 AssertPtrReturn(puPID, VERR_INVALID_POINTER);
2196
2197 int rc;
2198 do
2199 {
2200 HGCMMsgProcWaitFor Msg;
2201 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, vbglR3GuestCtrlGetMsgFunctionNo(pCtx->uClientID), pCtx->uNumParms);
2202 VbglHGCMParmUInt32Set(&Msg.context, HOST_MSG_EXEC_WAIT_FOR);
2203 VbglHGCMParmUInt32Set(&Msg.pid, 0);
2204 VbglHGCMParmUInt32Set(&Msg.flags, 0);
2205 VbglHGCMParmUInt32Set(&Msg.timeout, 0);
2206
2207 rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
2208 if (RT_SUCCESS(rc))
2209 {
2210 Msg.context.GetUInt32(&pCtx->uContextID);
2211 Msg.pid.GetUInt32(puPID);
2212 Msg.flags.GetUInt32(puWaitFlags);
2213 Msg.timeout.GetUInt32(puTimeoutMS);
2214 }
2215 } while (rc == VERR_INTERRUPTED && g_fVbglR3GuestCtrlHavePeekGetCancel);
2216 return rc;
2217}
2218
2219
2220/*********************************************************************************************************************************
2221 * Directory callbacks *
2222 ********************************************************************************************************************************/
2223
2224#ifdef VBOX_WITH_GSTCTL_TOOLBOX_AS_CMDS
2225/**
2226 * Replies to a HOST_MSG_DIR_OPEN message.
2227 *
2228 * @returns VBox status code.
2229 * @param pCtx Guest control command context to use.
2230 * @param uRc Guest rc of operation (note: IPRT-style signed int).
2231 * @param uDirHandle Directory handle of opened directory.
2232 */
2233VBGLR3DECL(int) VbglR3GuestCtrlDirCbOpen(PVBGLR3GUESTCTRLCMDCTX pCtx, uint32_t uRc, uint32_t uDirHandle)
2234{
2235 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
2236
2237 HGCMReplyDirNotify Msg;
2238 VBGL_HGCM_HDR_INIT(&Msg.reply_hdr.hdr, pCtx->uClientID, GUEST_MSG_DIR_NOTIFY, GSTCTL_HGCM_REPLY_HDR_PARMS + 1);
2239 VbglHGCMParmUInt32Set(&Msg.reply_hdr.context, pCtx->uContextID);
2240 VbglHGCMParmUInt32Set(&Msg.reply_hdr.type, GUEST_DIR_NOTIFYTYPE_OPEN);
2241 VbglHGCMParmUInt32Set(&Msg.reply_hdr.rc, uRc);
2242
2243 VbglHGCMParmUInt32Set(&Msg.u.open.handle, uDirHandle);
2244
2245 return VbglR3HGCMCall(&Msg.reply_hdr.hdr, RT_UOFFSET_AFTER(HGCMReplyDirNotify, u.open));
2246}
2247
2248
2249/**
2250 * Replies to a HOST_MSG_DIR_CLOSE message.
2251 *
2252 * @returns VBox status code.
2253 * @param pCtx Guest control command context to use.
2254 * @param uRc Guest rc of operation (note: IPRT-style signed int).
2255 */
2256VBGLR3DECL(int) VbglR3GuestCtrlDirCbClose(PVBGLR3GUESTCTRLCMDCTX pCtx, uint32_t uRc)
2257{
2258 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
2259
2260 HGCMReplyDirNotify Msg;
2261 VBGL_HGCM_HDR_INIT(&Msg.reply_hdr.hdr, pCtx->uClientID, GUEST_MSG_DIR_NOTIFY, GSTCTL_HGCM_REPLY_HDR_PARMS);
2262 VbglHGCMParmUInt32Set(&Msg.reply_hdr.context, pCtx->uContextID);
2263 VbglHGCMParmUInt32Set(&Msg.reply_hdr.type, GUEST_DIR_NOTIFYTYPE_CLOSE);
2264 VbglHGCMParmUInt32Set(&Msg.reply_hdr.rc, uRc);
2265
2266 return VbglR3HGCMCall(&Msg.reply_hdr.hdr, RT_UOFFSET_AFTER(HGCMReplyDirNotify, reply_hdr));
2267}
2268
2269
2270/**
2271 * Replies to a HOST_MSG_DIR_READ message, extended version.
2272 *
2273 * @returns VBox status code.
2274 * @param pCtx Guest control command context to use.
2275 * @param uRc Guest rc of operation (note: IPRT-style signed int).
2276 * @param pEntry Directory entry to send.
2277 * @param cbSize Size (in bytes) of \a pDirEntry to send.
2278 * This might be needed as the size can be bigger than GSTCTLDIRENTRYEX.
2279 * See RTDirReadEx() for more information.
2280 * @param pszUser Associated user ID (owner, uid) as a string.
2281 * @param pszGroups Associated user groups as a string.
2282 * Multiple groups are delimited by "\r\n", whereas the first group always is the primary group.
2283 * @param pvACL ACL block to send.
2284 * @param cbACL Size (in bytes) of ACL block to send.
2285 */
2286VBGLR3DECL(int) VbglR3GuestCtrlDirCbReadEx(PVBGLR3GUESTCTRLCMDCTX pCtx, uint32_t uRc, PGSTCTLDIRENTRYEX pEntry, uint32_t cbSize,
2287 char *pszUser, char *pszGroups, void *pvACL, size_t cbACL)
2288{
2289 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
2290 AssertPtrReturn(pszUser, VERR_INVALID_POINTER);
2291 AssertPtrReturn(pszGroups, VERR_INVALID_POINTER);
2292 AssertPtrReturn(pvACL, VERR_INVALID_POINTER);
2293 AssertReturn(cbACL, VERR_INVALID_PARAMETER);
2294
2295 HGCMReplyDirNotify Msg;
2296 VBGL_HGCM_HDR_INIT(&Msg.reply_hdr.hdr, pCtx->uClientID, GUEST_MSG_DIR_NOTIFY, GSTCTL_HGCM_REPLY_HDR_PARMS + 4);
2297 VbglHGCMParmUInt32Set(&Msg.reply_hdr.context, pCtx->uContextID);
2298 VbglHGCMParmUInt32Set(&Msg.reply_hdr.type, GUEST_DIR_NOTIFYTYPE_READ);
2299 VbglHGCMParmUInt32Set(&Msg.reply_hdr.rc, uRc);
2300
2301 VbglHGCMParmPtrSet (&Msg.u.read.entry, pEntry, cbSize);
2302 VbglHGCMParmPtrSetString(&Msg.u.read.user, pszUser);
2303 VbglHGCMParmPtrSetString(&Msg.u.read.groups, pszGroups);
2304 VbglHGCMParmPtrSet (&Msg.u.read.acl, pvACL, (uint32_t)cbACL);
2305
2306 return VbglR3HGCMCall(&Msg.reply_hdr.hdr, RT_UOFFSET_AFTER(HGCMReplyDirNotify, u.read));
2307}
2308
2309
2310/**
2311 * Replies to a HOST_MSG_DIR_READ message.
2312 *
2313 * @returns VBox status code.
2314 * @param pCtx Guest control command context to use.
2315 * @param uRc Guest rc of operation (note: IPRT-style signed int).
2316 * @param pEntry Directory entry to send.
2317 * @param cbSize Size (in bytes) of \a pDirEntry to send.
2318 * This might be needed as the size can be bigger than GSTCTLDIRENTRYEX.
2319 * See RTDirReadEx() for more information.
2320 */
2321VBGLR3DECL(int) VbglR3GuestCtrlDirCbRead(PVBGLR3GUESTCTRLCMDCTX pCtx, uint32_t uRc, PGSTCTLDIRENTRYEX pEntry, uint32_t cbSize)
2322{
2323 char szIgnored[1] = { 0 };
2324 return VbglR3GuestCtrlDirCbReadEx(pCtx, uRc, pEntry, cbSize, szIgnored /* pszUser */, szIgnored /* pszGroups */,
2325 szIgnored /* pvACL */, sizeof(szIgnored) /* cbACL */);
2326}
2327
2328
2329/**
2330 * Replies to a HOST_MSG_DIR_REWIND message.
2331 *
2332 * @returns VBox status code.
2333 * @param pCtx Guest control command context to use.
2334 * @param uRc Guest rc of operation (note: IPRT-style signed int).
2335 */
2336VBGLR3DECL(int) VbglR3GuestCtrlDirCbRewind(PVBGLR3GUESTCTRLCMDCTX pCtx, uint32_t uRc)
2337{
2338 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
2339
2340 HGCMReplyDirNotify Msg;
2341 VBGL_HGCM_HDR_INIT(&Msg.reply_hdr.hdr, pCtx->uClientID, GUEST_MSG_DIR_NOTIFY, GSTCTL_HGCM_REPLY_HDR_PARMS);
2342 VbglHGCMParmUInt32Set(&Msg.reply_hdr.context, pCtx->uContextID);
2343 VbglHGCMParmUInt32Set(&Msg.reply_hdr.type, GUEST_DIR_NOTIFYTYPE_REWIND);
2344 VbglHGCMParmUInt32Set(&Msg.reply_hdr.rc, uRc);
2345
2346 return VbglR3HGCMCall(&Msg.reply_hdr.hdr, RT_UOFFSET_AFTER(HGCMReplyDirNotify, u));
2347}
2348#endif /* VBOX_WITH_GSTCTL_TOOLBOX_AS_CMDS */
2349
2350
2351/*********************************************************************************************************************************
2352 * File callbacks *
2353 ********************************************************************************************************************************/
2354
2355/**
2356 * Replies to a HOST_MSG_FILE_OPEN message.
2357 *
2358 * @returns VBox status code.
2359 * @param pCtx Guest control command context to use.
2360 * @param uRc Guest rc of operation (note: IPRT-style signed int).
2361 * @param uFileHandle File handle of opened file on success.
2362 */
2363VBGLR3DECL(int) VbglR3GuestCtrlFileCbOpen(PVBGLR3GUESTCTRLCMDCTX pCtx,
2364 uint32_t uRc, uint32_t uFileHandle)
2365{
2366 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
2367
2368 HGCMReplyFileNotify Msg;
2369 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, GUEST_MSG_FILE_NOTIFY, 4);
2370 VbglHGCMParmUInt32Set(&Msg.context, pCtx->uContextID);
2371 VbglHGCMParmUInt32Set(&Msg.type, GUEST_FILE_NOTIFYTYPE_OPEN);
2372 VbglHGCMParmUInt32Set(&Msg.rc, uRc);
2373 VbglHGCMParmUInt32Set(&Msg.u.open.handle, uFileHandle);
2374
2375 return VbglR3HGCMCall(&Msg.hdr, RT_UOFFSET_AFTER(HGCMReplyFileNotify, u.open));
2376}
2377
2378
2379/**
2380 * Replies to a HOST_MSG_FILE_CLOSE message.
2381 *
2382 * @returns VBox status code.
2383 * @param pCtx Guest control command context to use.
2384 * @param uRc Guest rc of operation (note: IPRT-style signed int).
2385 */
2386VBGLR3DECL(int) VbglR3GuestCtrlFileCbClose(PVBGLR3GUESTCTRLCMDCTX pCtx,
2387 uint32_t uRc)
2388{
2389 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
2390
2391 HGCMReplyFileNotify Msg;
2392 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, GUEST_MSG_FILE_NOTIFY, 3);
2393 VbglHGCMParmUInt32Set(&Msg.context, pCtx->uContextID);
2394 VbglHGCMParmUInt32Set(&Msg.type, GUEST_FILE_NOTIFYTYPE_CLOSE);
2395 VbglHGCMParmUInt32Set(&Msg.rc, uRc);
2396
2397 return VbglR3HGCMCall(&Msg.hdr, RT_UOFFSETOF(HGCMReplyFileNotify, u));
2398}
2399
2400
2401/**
2402 * Sends an unexpected file handling error to the host.
2403 *
2404 * @returns VBox status code.
2405 * @param pCtx Guest control command context to use.
2406 * @param uRc Guest rc of operation (note: IPRT-style signed int).
2407 */
2408VBGLR3DECL(int) VbglR3GuestCtrlFileCbError(PVBGLR3GUESTCTRLCMDCTX pCtx, uint32_t uRc)
2409{
2410 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
2411
2412 HGCMReplyFileNotify Msg;
2413 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, GUEST_MSG_FILE_NOTIFY, 3);
2414 VbglHGCMParmUInt32Set(&Msg.context, pCtx->uContextID);
2415 VbglHGCMParmUInt32Set(&Msg.type, GUEST_FILE_NOTIFYTYPE_ERROR);
2416 VbglHGCMParmUInt32Set(&Msg.rc, uRc);
2417
2418 return VbglR3HGCMCall(&Msg.hdr, RT_UOFFSETOF(HGCMReplyFileNotify, u));
2419}
2420
2421
2422/**
2423 * Replies to a HOST_MSG_FILE_READ message.
2424 *
2425 * @returns VBox status code.
2426 * @param pCtx Guest control command context to use.
2427 * @param uRc Guest rc of operation (note: IPRT-style signed int).
2428 * @param pvData Pointer to read file data from guest on success.
2429 * @param cbData Size (in bytes) of read file data from guest on success.
2430 */
2431VBGLR3DECL(int) VbglR3GuestCtrlFileCbRead(PVBGLR3GUESTCTRLCMDCTX pCtx,
2432 uint32_t uRc,
2433 void *pvData, uint32_t cbData)
2434{
2435 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
2436
2437 HGCMReplyFileNotify Msg;
2438 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, GUEST_MSG_FILE_NOTIFY, 4);
2439 VbglHGCMParmUInt32Set(&Msg.context, pCtx->uContextID);
2440 VbglHGCMParmUInt32Set(&Msg.type, GUEST_FILE_NOTIFYTYPE_READ);
2441 VbglHGCMParmUInt32Set(&Msg.rc, uRc);
2442 VbglHGCMParmPtrSet(&Msg.u.read.data, pvData, cbData);
2443
2444 return VbglR3HGCMCall(&Msg.hdr, RT_UOFFSET_AFTER(HGCMReplyFileNotify, u.read));
2445}
2446
2447
2448/**
2449 * Replies to a HOST_MSG_FILE_READ_AT message.
2450 *
2451 * @returns VBox status code.
2452 * @param pCtx Guest control command context to use.
2453 * @param uRc Guest rc of operation (note: IPRT-style signed int).
2454 * @param pvData Pointer to read file data from guest on success.
2455 * @param cbData Size (in bytes) of read file data from guest on success.
2456 * @param offNew New offset (in bytes) the guest file pointer points at on success.
2457 */
2458VBGLR3DECL(int) VbglR3GuestCtrlFileCbReadOffset(PVBGLR3GUESTCTRLCMDCTX pCtx, uint32_t uRc,
2459 void *pvData, uint32_t cbData, int64_t offNew)
2460{
2461 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
2462
2463 HGCMReplyFileNotify Msg;
2464 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, GUEST_MSG_FILE_NOTIFY, 5);
2465 VbglHGCMParmUInt32Set(&Msg.context, pCtx->uContextID);
2466 VbglHGCMParmUInt32Set(&Msg.type, GUEST_FILE_NOTIFYTYPE_READ_OFFSET);
2467 VbglHGCMParmUInt32Set(&Msg.rc, uRc);
2468 VbglHGCMParmPtrSet(&Msg.u.ReadOffset.pvData, pvData, cbData);
2469 VbglHGCMParmUInt64Set(&Msg.u.ReadOffset.off64New, (uint64_t)offNew);
2470
2471 return VbglR3HGCMCall(&Msg.hdr, RT_UOFFSET_AFTER(HGCMReplyFileNotify, u.ReadOffset));
2472}
2473
2474
2475/**
2476 * Replies to a HOST_MSG_FILE_WRITE message.
2477 *
2478 * @returns VBox status code.
2479 * @param pCtx Guest control command context to use.
2480 * @param uRc Guest rc of operation (note: IPRT-style signed int).
2481 * @param cbWritten Size (in bytes) of file data successfully written to guest file. Can be partial.
2482 */
2483VBGLR3DECL(int) VbglR3GuestCtrlFileCbWrite(PVBGLR3GUESTCTRLCMDCTX pCtx, uint32_t uRc, uint32_t cbWritten)
2484{
2485 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
2486
2487 HGCMReplyFileNotify Msg;
2488 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, GUEST_MSG_FILE_NOTIFY, 4);
2489 VbglHGCMParmUInt32Set(&Msg.context, pCtx->uContextID);
2490 VbglHGCMParmUInt32Set(&Msg.type, GUEST_FILE_NOTIFYTYPE_WRITE);
2491 VbglHGCMParmUInt32Set(&Msg.rc, uRc);
2492 VbglHGCMParmUInt32Set(&Msg.u.write.written, cbWritten);
2493
2494 return VbglR3HGCMCall(&Msg.hdr, RT_UOFFSET_AFTER(HGCMReplyFileNotify, u.write));
2495}
2496
2497
2498/**
2499 * Replies to a HOST_MSG_FILE_WRITE_AT message.
2500 *
2501 * @returns VBox status code.
2502 * @param pCtx Guest control command context to use.
2503 * @param uRc Guest rc of operation (note: IPRT-style signed int).
2504 * @param cbWritten Size (in bytes) of file data successfully written to guest file. Can be partial.
2505 * @param offNew New offset (in bytes) the guest file pointer points at on success.
2506 */
2507VBGLR3DECL(int) VbglR3GuestCtrlFileCbWriteOffset(PVBGLR3GUESTCTRLCMDCTX pCtx, uint32_t uRc, uint32_t cbWritten, int64_t offNew)
2508{
2509 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
2510
2511 HGCMReplyFileNotify Msg;
2512 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, GUEST_MSG_FILE_NOTIFY, 5);
2513 VbglHGCMParmUInt32Set(&Msg.context, pCtx->uContextID);
2514 VbglHGCMParmUInt32Set(&Msg.type, GUEST_FILE_NOTIFYTYPE_WRITE_OFFSET);
2515 VbglHGCMParmUInt32Set(&Msg.rc, uRc);
2516 VbglHGCMParmUInt32Set(&Msg.u.WriteOffset.cb32Written, cbWritten);
2517 VbglHGCMParmUInt64Set(&Msg.u.WriteOffset.off64New, (uint64_t)offNew);
2518
2519 return VbglR3HGCMCall(&Msg.hdr, RT_UOFFSET_AFTER(HGCMReplyFileNotify, u.WriteOffset));
2520}
2521
2522
2523/**
2524 * Replies to a HOST_MSG_FILE_SEEK message.
2525 *
2526 * @returns VBox status code.
2527 * @param pCtx Guest control command context to use.
2528 * @param uRc Guest rc of operation (note: IPRT-style signed int).
2529 * @param offCurrent New offset (in bytes) the guest file pointer points at on success.
2530 */
2531VBGLR3DECL(int) VbglR3GuestCtrlFileCbSeek(PVBGLR3GUESTCTRLCMDCTX pCtx, uint32_t uRc, uint64_t offCurrent)
2532{
2533 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
2534
2535 HGCMReplyFileNotify Msg;
2536 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, GUEST_MSG_FILE_NOTIFY, 4);
2537 VbglHGCMParmUInt32Set(&Msg.context, pCtx->uContextID);
2538 VbglHGCMParmUInt32Set(&Msg.type, GUEST_FILE_NOTIFYTYPE_SEEK);
2539 VbglHGCMParmUInt32Set(&Msg.rc, uRc);
2540 VbglHGCMParmUInt64Set(&Msg.u.seek.offset, offCurrent);
2541
2542 return VbglR3HGCMCall(&Msg.hdr, RT_UOFFSET_AFTER(HGCMReplyFileNotify, u.seek));
2543}
2544
2545
2546/**
2547 * Replies to a HOST_MSG_FILE_TELL message.
2548 *
2549 * @returns VBox status code.
2550 * @param pCtx Guest control command context to use.
2551 * @param uRc Guest rc of operation (note: IPRT-style signed int).
2552 * @param offCurrent Current offset (in bytes) the guest file pointer points at on success.
2553 */
2554VBGLR3DECL(int) VbglR3GuestCtrlFileCbTell(PVBGLR3GUESTCTRLCMDCTX pCtx, uint32_t uRc, uint64_t offCurrent)
2555{
2556 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
2557
2558 HGCMReplyFileNotify Msg;
2559 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, GUEST_MSG_FILE_NOTIFY, 4);
2560 VbglHGCMParmUInt32Set(&Msg.context, pCtx->uContextID);
2561 VbglHGCMParmUInt32Set(&Msg.type, GUEST_FILE_NOTIFYTYPE_TELL);
2562 VbglHGCMParmUInt32Set(&Msg.rc, uRc);
2563 VbglHGCMParmUInt64Set(&Msg.u.tell.offset, offCurrent);
2564
2565 return VbglR3HGCMCall(&Msg.hdr, RT_UOFFSET_AFTER(HGCMReplyFileNotify, u.tell));
2566}
2567
2568
2569/**
2570 * Replies to a HOST_MSG_FILE_SET_SIZE message.
2571 *
2572 * @returns VBox status code.
2573 * @param pCtx Guest control command context to use.
2574 * @param uRc Guest rc of operation (note: IPRT-style signed int).
2575 * @param cbNew New file size (in bytes) of the guest file on success.
2576 */
2577VBGLR3DECL(int) VbglR3GuestCtrlFileCbSetSize(PVBGLR3GUESTCTRLCMDCTX pCtx, uint32_t uRc, uint64_t cbNew)
2578{
2579 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
2580
2581 HGCMReplyFileNotify Msg;
2582 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, GUEST_MSG_FILE_NOTIFY, 4);
2583 VbglHGCMParmUInt32Set(&Msg.context, pCtx->uContextID);
2584 VbglHGCMParmUInt32Set(&Msg.type, GUEST_FILE_NOTIFYTYPE_SET_SIZE);
2585 VbglHGCMParmUInt32Set(&Msg.rc, uRc);
2586 VbglHGCMParmUInt64Set(&Msg.u.SetSize.cb64Size, cbNew);
2587
2588 return VbglR3HGCMCall(&Msg.hdr, RT_UOFFSET_AFTER(HGCMReplyFileNotify, u.SetSize));
2589}
2590
2591
2592/*********************************************************************************************************************************
2593 * File system callbacks *
2594 ********************************************************************************************************************************/
2595
2596#ifdef VBOX_WITH_GSTCTL_TOOLBOX_AS_CMDS
2597/**
2598 * Replies to a HOST_MSG_FS_QUERY_INFO message, extended version.
2599 *
2600 * @returns VBox status code.
2601 * @param pCtx Guest control command context to use.
2602 * @param uRc Guest rc of operation (note: IPRT-style signed int).
2603 * @param pFsObjInfo Guest file system object information to send.
2604 * @param pszUser Associated user ID (owner, uid) as a string.
2605 * @param pszGroups Associated user groups as a string.
2606 * Multiple groups are delimited by "\r\n", whereas the first group always is the primary group.
2607 * @param pvACL ACL block to send.
2608 * @param cbACL Size (in bytes) of ACL block to send.
2609 */
2610VBGLR3DECL(int) VbglR3GuestCtrlFsCbQueryInfoEx(PVBGLR3GUESTCTRLCMDCTX pCtx, uint32_t uRc, PGSTCTLFSOBJINFO pFsObjInfo,
2611 char *pszUser, char *pszGroups, void *pvACL, uint32_t cbACL)
2612{
2613 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
2614 AssertPtrReturn(pFsObjInfo, VERR_INVALID_POINTER);
2615 AssertPtrReturn(pszUser, VERR_INVALID_POINTER);
2616 AssertPtrReturn(pszGroups, VERR_INVALID_POINTER);
2617 AssertPtrReturn(pvACL, VERR_INVALID_POINTER);
2618 AssertReturn(cbACL, VERR_INVALID_PARAMETER);
2619
2620 HGCMReplyFsNotify Msg;
2621 VBGL_HGCM_HDR_INIT(&Msg.reply_hdr.hdr, pCtx->uClientID, GUEST_MSG_FS_NOTIFY, 7);
2622 VbglHGCMParmUInt32Set(&Msg.reply_hdr.context, pCtx->uContextID);
2623 VbglHGCMParmUInt32Set(&Msg.reply_hdr.type, GUEST_FS_NOTIFYTYPE_QUERY_INFO);
2624 VbglHGCMParmUInt32Set(&Msg.reply_hdr.rc, uRc);
2625 VbglHGCMParmPtrSet (&Msg.u.queryinfo.obj_info, pFsObjInfo, sizeof(GSTCTLFSOBJINFO));
2626 VbglHGCMParmPtrSetString(&Msg.u.queryinfo.user, pszUser);
2627 VbglHGCMParmPtrSetString(&Msg.u.queryinfo.groups, pszGroups);
2628 VbglHGCMParmPtrSet (&Msg.u.queryinfo.acl, pvACL, cbACL);
2629
2630 return VbglR3HGCMCall(&Msg.reply_hdr.hdr, RT_UOFFSET_AFTER(HGCMReplyFsNotify, u.queryinfo));
2631}
2632
2633
2634/**
2635 * Replies to a HOST_MSG_FS_QUERY_INFO message.
2636 *
2637 * @returns VBox status code.
2638 * @param pCtx Guest control command context to use.
2639 * @param uRc Guest rc of operation (note: IPRT-style signed int).
2640 * @param pFsObjInfo Guest file system object information to send.
2641 */
2642VBGLR3DECL(int) VbglR3GuestCtrlFsCbQueryInfo(PVBGLR3GUESTCTRLCMDCTX pCtx, uint32_t uRc, PGSTCTLFSOBJINFO pFsObjInfo)
2643{
2644 char szIgnored[1];
2645 return VbglR3GuestCtrlFsCbQueryInfoEx(pCtx, uRc, pFsObjInfo, szIgnored /* pszUser */, szIgnored /* pszGroups */,
2646 szIgnored /* pvACL */, sizeof(szIgnored) /* cbACL */);
2647}
2648
2649
2650/**
2651 * Replies to a HOST_MSG_FS_CREATE_TEMP message.
2652 *
2653 * @returns VBox status code.
2654 * @param pCtx Guest control command context to use.
2655 * @param uRc Guest rc of operation (note: IPRT-style signed int).
2656 * @param pszPath Path of created temporary file / directory, if \a uRc marks a success.
2657 * Specify an empty path on failure -- NULL is not allowed!
2658 */
2659VBGLR3DECL(int) VbglR3GuestCtrlFsCbCreateTemp(PVBGLR3GUESTCTRLCMDCTX pCtx, uint32_t uRc, const char *pszPath)
2660{
2661 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
2662 AssertPtrReturn(pszPath, VERR_INVALID_POINTER);
2663
2664 HGCMReplyFsNotify Msg;
2665 VBGL_HGCM_HDR_INIT(&Msg.reply_hdr.hdr, pCtx->uClientID, GUEST_MSG_FS_NOTIFY, 4);
2666 VbglHGCMParmUInt32Set(&Msg.reply_hdr.context, pCtx->uContextID);
2667 VbglHGCMParmUInt32Set(&Msg.reply_hdr.type, GUEST_FS_NOTIFYTYPE_CREATE_TEMP);
2668 VbglHGCMParmUInt32Set(&Msg.reply_hdr.rc, uRc);
2669 VbglHGCMParmPtrSetString(&Msg.u.createtemp.path, pszPath);
2670
2671 return VbglR3HGCMCall(&Msg.reply_hdr.hdr, RT_UOFFSET_AFTER(HGCMReplyFsNotify, u.createtemp));
2672}
2673#endif /* VBOX_WITH_GSTCTL_TOOLBOX_AS_CMDS */
2674
2675
2676/*********************************************************************************************************************************
2677 * Process callbacks *
2678 ********************************************************************************************************************************/
2679
2680/**
2681 * Callback for reporting a guest process status (along with some other stuff) to the host.
2682 *
2683 * @returns VBox status code.
2684 * @param pCtx Guest control command context to use.
2685 * @param uPID Guest process PID to report status for.
2686 * @param uStatus Status to report. Of type PROC_STS_XXX.
2687 * @param fFlags Additional status flags, depending on the reported status. See RTPROCSTATUS.
2688 * @param pvData Pointer to additional status data. Optional.
2689 * @param cbData Size (in bytes) of additional status data.
2690 */
2691VBGLR3DECL(int) VbglR3GuestCtrlProcCbStatus(PVBGLR3GUESTCTRLCMDCTX pCtx,
2692 uint32_t uPID, uint32_t uStatus, uint32_t fFlags,
2693 void *pvData, uint32_t cbData)
2694{
2695 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
2696
2697 HGCMMsgProcStatus Msg;
2698 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, GUEST_MSG_EXEC_STATUS, 5);
2699 VbglHGCMParmUInt32Set(&Msg.context, pCtx->uContextID);
2700 VbglHGCMParmUInt32Set(&Msg.pid, uPID);
2701 VbglHGCMParmUInt32Set(&Msg.status, uStatus);
2702 VbglHGCMParmUInt32Set(&Msg.flags, fFlags);
2703 VbglHGCMParmPtrSet(&Msg.data, pvData, cbData);
2704
2705 return VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
2706}
2707
2708
2709/**
2710 * Sends output (from stdout/stderr) from a running process.
2711 *
2712 * @returns VBox status code.
2713 * @param pCtx Guest control command context to use.
2714 * @param uPID Guest process PID to report status for.
2715 * @param uHandle Guest process handle the output belong to.
2716 * @param fFlags Additional output flags.
2717 * @param pvData Pointer to actual output data.
2718 * @param cbData Size (in bytes) of output data.
2719 */
2720VBGLR3DECL(int) VbglR3GuestCtrlProcCbOutput(PVBGLR3GUESTCTRLCMDCTX pCtx,
2721 uint32_t uPID,uint32_t uHandle, uint32_t fFlags,
2722 void *pvData, uint32_t cbData)
2723{
2724 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
2725
2726 HGCMMsgProcOutput Msg;
2727 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, GUEST_MSG_EXEC_OUTPUT, 5);
2728 VbglHGCMParmUInt32Set(&Msg.context, pCtx->uContextID);
2729 VbglHGCMParmUInt32Set(&Msg.pid, uPID);
2730 VbglHGCMParmUInt32Set(&Msg.handle, uHandle);
2731 VbglHGCMParmUInt32Set(&Msg.flags, fFlags);
2732 VbglHGCMParmPtrSet(&Msg.data, pvData, cbData);
2733
2734 return VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
2735}
2736
2737
2738/**
2739 * Callback for reporting back the input status of a guest process to the host.
2740 *
2741 * @returns VBox status code.
2742 * @param pCtx Guest control command context to use.
2743 * @param uPID Guest process PID to report status for.
2744 * @param uStatus Status to report. Of type INPUT_STS_XXX.
2745 * @param fFlags Additional input flags.
2746 * @param cbWritten Size (in bytes) of input data handled.
2747 */
2748VBGLR3DECL(int) VbglR3GuestCtrlProcCbStatusInput(PVBGLR3GUESTCTRLCMDCTX pCtx,
2749 uint32_t uPID, uint32_t uStatus,
2750 uint32_t fFlags, uint32_t cbWritten)
2751{
2752 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
2753
2754 HGCMMsgProcStatusInput Msg;
2755 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, GUEST_MSG_EXEC_INPUT_STATUS, 5);
2756 VbglHGCMParmUInt32Set(&Msg.context, pCtx->uContextID);
2757 VbglHGCMParmUInt32Set(&Msg.pid, uPID);
2758 VbglHGCMParmUInt32Set(&Msg.status, uStatus);
2759 VbglHGCMParmUInt32Set(&Msg.flags, fFlags);
2760 VbglHGCMParmUInt32Set(&Msg.written, cbWritten);
2761
2762 return VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
2763}
2764
Note: See TracBrowser for help on using the repository browser.

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