VirtualBox

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

Last change on this file since 84848 was 84848, checked in by vboxsync, 5 years ago

Guest Control/VbglR3: Tried fixing bailing out from starting guest processes with too long environment blocks / arguments / command lines. ​​bugref:9320

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 78.9 KB
Line 
1/* $Id: VBoxGuestR3LibGuestCtrl.cpp 84848 2020-06-16 12:17:41Z vboxsync $ */
2/** @file
3 * VBoxGuestR3Lib - Ring-3 Support Library for VirtualBox guest additions, guest control.
4 */
5
6/*
7 * Copyright (C) 2010-2020 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.215389.xyz. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * The contents of this file may alternatively be used under the terms
18 * of the Common Development and Distribution License Version 1.0
19 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
20 * VirtualBox OSE distribution, in which case the provisions of the
21 * CDDL are applicable instead of those of the GPL.
22 *
23 * You may elect to license modified versions of this file under the
24 * terms and conditions of either the GPL or the CDDL or both.
25 */
26
27
28/*********************************************************************************************************************************
29* Header Files *
30*********************************************************************************************************************************/
31#include <iprt/string.h>
32#include <iprt/mem.h>
33#include <iprt/assert.h>
34#include <iprt/cpp/autores.h>
35#include <iprt/stdarg.h>
36#include <VBox/err.h>
37#include <VBox/log.h>
38#include <VBox/GuestHost/GuestControl.h>
39#include <VBox/HostServices/GuestControlSvc.h>
40
41#ifndef RT_OS_WINDOWS
42# include <signal.h>
43#endif
44
45#include "VBoxGuestR3LibInternal.h"
46
47using namespace guestControl;
48
49
50/*********************************************************************************************************************************
51* Global Variables *
52*********************************************************************************************************************************/
53/** Set if GUEST_MSG_PEEK_WAIT and friends are supported. */
54static int g_fVbglR3GuestCtrlHavePeekGetCancel = -1;
55
56
57/**
58 * Connects to the guest control service.
59 *
60 * @returns VBox status code
61 * @param pidClient Where to put The client ID on success. The client ID
62 * must be passed to all the other calls to the service.
63 */
64VBGLR3DECL(int) VbglR3GuestCtrlConnect(uint32_t *pidClient)
65{
66 return VbglR3HGCMConnect("VBoxGuestControlSvc", pidClient);
67}
68
69
70/**
71 * Disconnect from the guest control service.
72 *
73 * @returns VBox status code.
74 * @param idClient The client ID returned by VbglR3GuestCtrlConnect().
75 */
76VBGLR3DECL(int) VbglR3GuestCtrlDisconnect(uint32_t idClient)
77{
78 return VbglR3HGCMDisconnect(idClient);
79}
80
81
82/**
83 * Waits until a new host message arrives.
84 * This will block until a message becomes available.
85 *
86 * @returns VBox status code.
87 * @param idClient The client ID returned by VbglR3GuestCtrlConnect().
88 * @param pidMsg Where to store the message id.
89 * @param pcParameters Where to store the number of parameters which will
90 * be received in a second call to the host.
91 */
92static int vbglR3GuestCtrlMsgWaitFor(uint32_t idClient, uint32_t *pidMsg, uint32_t *pcParameters)
93{
94 AssertPtrReturn(pidMsg, VERR_INVALID_POINTER);
95 AssertPtrReturn(pcParameters, VERR_INVALID_POINTER);
96
97 HGCMMsgWaitFor Msg;
98 VBGL_HGCM_HDR_INIT(&Msg.hdr, idClient,
99 GUEST_MSG_WAIT, /* Tell the host we want our next message. */
100 2); /* Just peek for the next message! */
101 VbglHGCMParmUInt32Set(&Msg.msg, 0);
102 VbglHGCMParmUInt32Set(&Msg.num_parms, 0);
103
104 /*
105 * We should always get a VERR_TOO_MUCH_DATA response here, see
106 * guestControl::HostMessage::Peek() and its caller ClientState::SendReply().
107 * We accept success too here, in case someone decide to make the protocol
108 * slightly more sane.
109 *
110 * Note! A really sane protocol design would have a separate call for getting
111 * info about a pending message (returning VINF_SUCCESS), and a separate
112 * one for retriving the actual message parameters. Not this weird
113 * stuff, to put it rather bluntly.
114 *
115 * Note! As a result of this weird design, we are not able to correctly
116 * retrieve message if we're interrupted by a signal, like SIGCHLD.
117 * Because IPRT wants to use waitpid(), we're forced to have a handler
118 * installed for SIGCHLD, so when working with child processes there
119 * will be signals in the air and we will get VERR_INTERRUPTED returns.
120 * The way HGCM handles interrupted calls is to silently (?) drop them
121 * as they complete (see VMMDev), so the server knows little about it
122 * and just goes on to the next message inline.
123 *
124 * So, as a "temporary" mesasure, we block SIGCHLD here while waiting,
125 * because it will otherwise be impossible do simple stuff like 'mkdir'
126 * on a mac os x guest, and probably most other unix guests.
127 */
128#ifdef RT_OS_WINDOWS
129 int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
130#else
131 sigset_t SigSet;
132 sigemptyset(&SigSet);
133 sigaddset(&SigSet, SIGCHLD);
134 sigprocmask(SIG_BLOCK, &SigSet, NULL);
135 int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
136 sigprocmask(SIG_UNBLOCK, &SigSet, NULL);
137#endif
138 if ( rc == VERR_TOO_MUCH_DATA
139 || RT_SUCCESS(rc))
140 {
141 int rc2 = VbglHGCMParmUInt32Get(&Msg.msg, pidMsg);
142 if (RT_SUCCESS(rc2))
143 {
144 rc2 = VbglHGCMParmUInt32Get(&Msg.num_parms, pcParameters);
145 if (RT_SUCCESS(rc2))
146 {
147 /* Ok, so now we know what message type and how much parameters there are. */
148 return rc;
149 }
150 }
151 rc = rc2;
152 }
153 *pidMsg = UINT32_MAX - 1;
154 *pcParameters = UINT32_MAX - 2;
155 return rc;
156}
157
158
159/**
160 * Determins the value of g_fVbglR3GuestCtrlHavePeekGetCancel.
161 *
162 * @returns true if supported, false if not.
163 * @param idClient The client ID to use for the testing.
164 */
165DECL_NO_INLINE(static, bool) vbglR3GuestCtrlDetectPeekGetCancelSupport(uint32_t idClient)
166{
167 /*
168 * Seems we get VINF_SUCCESS back from the host if we try unsupported
169 * guest control messages, so we need to supply some random message
170 * parameters and check that they change.
171 */
172 uint32_t const idDummyMsg = UINT32_C(0x8350bdca);
173 uint32_t const cDummyParmeters = UINT32_C(0x7439604f);
174 uint32_t const cbDummyMask = UINT32_C(0xc0ffe000);
175 Assert(cDummyParmeters > VMMDEV_MAX_HGCM_PARMS);
176
177 int rc;
178 struct
179 {
180 VBGLIOCHGCMCALL Hdr;
181 HGCMFunctionParameter idMsg;
182 HGCMFunctionParameter cParams;
183 HGCMFunctionParameter acbParams[14];
184 } PeekCall;
185 Assert(RT_ELEMENTS(PeekCall.acbParams) + 2 < VMMDEV_MAX_HGCM_PARMS);
186
187 do
188 {
189 memset(&PeekCall, 0xf6, sizeof(PeekCall));
190 VBGL_HGCM_HDR_INIT(&PeekCall.Hdr, idClient, GUEST_MSG_PEEK_NOWAIT, 16);
191 VbglHGCMParmUInt32Set(&PeekCall.idMsg, idDummyMsg);
192 VbglHGCMParmUInt32Set(&PeekCall.cParams, cDummyParmeters);
193 for (uint32_t i = 0; i < RT_ELEMENTS(PeekCall.acbParams); i++)
194 VbglHGCMParmUInt32Set(&PeekCall.acbParams[i], i | cbDummyMask);
195
196 rc = VbglR3HGCMCall(&PeekCall.Hdr, sizeof(PeekCall));
197 } while (rc == VERR_INTERRUPTED);
198
199 LogRel2(("vbglR3GuestCtrlDetectPeekGetCancelSupport: rc=%Rrc %#x %#x %#x %#x %#x %#x %#x %#x %#x %#x %#x %#x %#x %#x %#x %#x\n",
200 rc, PeekCall.idMsg.u.value32, PeekCall.cParams.u.value32,
201 PeekCall.acbParams[ 0].u.value32, PeekCall.acbParams[ 1].u.value32,
202 PeekCall.acbParams[ 2].u.value32, PeekCall.acbParams[ 3].u.value32,
203 PeekCall.acbParams[ 4].u.value32, PeekCall.acbParams[ 5].u.value32,
204 PeekCall.acbParams[ 6].u.value32, PeekCall.acbParams[ 7].u.value32,
205 PeekCall.acbParams[ 8].u.value32, PeekCall.acbParams[ 9].u.value32,
206 PeekCall.acbParams[10].u.value32, PeekCall.acbParams[11].u.value32,
207 PeekCall.acbParams[12].u.value32, PeekCall.acbParams[13].u.value32));
208
209 /*
210 * VERR_TRY_AGAIN is likely and easy.
211 */
212 if ( rc == VERR_TRY_AGAIN
213 && PeekCall.idMsg.u.value32 == 0
214 && PeekCall.cParams.u.value32 == 0
215 && PeekCall.acbParams[0].u.value32 == 0
216 && PeekCall.acbParams[1].u.value32 == 0
217 && PeekCall.acbParams[2].u.value32 == 0
218 && PeekCall.acbParams[3].u.value32 == 0)
219 {
220 g_fVbglR3GuestCtrlHavePeekGetCancel = 1;
221 LogRel(("vbglR3GuestCtrlDetectPeekGetCancelSupport: Supported (#1)\n"));
222 return true;
223 }
224
225 /*
226 * VINF_SUCCESS is annoying but with 16 parameters we've got plenty to check.
227 */
228 if ( rc == VINF_SUCCESS
229 && PeekCall.idMsg.u.value32 != idDummyMsg
230 && PeekCall.idMsg.u.value32 != 0
231 && PeekCall.cParams.u.value32 <= VMMDEV_MAX_HGCM_PARMS)
232 {
233 for (uint32_t i = 0; i < RT_ELEMENTS(PeekCall.acbParams); i++)
234 if (PeekCall.acbParams[i].u.value32 != (i | cbDummyMask))
235 {
236 g_fVbglR3GuestCtrlHavePeekGetCancel = 0;
237 LogRel(("vbglR3GuestCtrlDetectPeekGetCancelSupport: Not supported (#1)\n"));
238 return false;
239 }
240 g_fVbglR3GuestCtrlHavePeekGetCancel = 1;
241 LogRel(("vbglR3GuestCtrlDetectPeekGetCancelSupport: Supported (#2)\n"));
242 return true;
243 }
244
245 /*
246 * Okay, pretty sure it's not supported then.
247 */
248 LogRel(("vbglR3GuestCtrlDetectPeekGetCancelSupport: Not supported (#3)\n"));
249 g_fVbglR3GuestCtrlHavePeekGetCancel = 0;
250 return false;
251}
252
253
254/**
255 * Reads g_fVbglR3GuestCtrlHavePeekGetCancel and resolved -1.
256 *
257 * @returns true if supported, false if not.
258 * @param idClient The client ID to use for the testing.
259 */
260DECLINLINE(bool) vbglR3GuestCtrlSupportsPeekGetCancel(uint32_t idClient)
261{
262 int fState = g_fVbglR3GuestCtrlHavePeekGetCancel;
263 if (RT_LIKELY(fState != -1))
264 return fState != 0;
265 return vbglR3GuestCtrlDetectPeekGetCancelSupport(idClient);
266}
267
268
269/**
270 * Figures which getter function to use to retrieve the message.
271 */
272DECLINLINE(uint32_t) vbglR3GuestCtrlGetMsgFunctionNo(uint32_t idClient)
273{
274 return vbglR3GuestCtrlSupportsPeekGetCancel(idClient) ? GUEST_MSG_GET : GUEST_MSG_WAIT;
275}
276
277
278/**
279 * Checks if the host supports the optimizes message and session functions.
280 *
281 * @returns true / false.
282 * @param idClient The client ID returned by VbglR3GuestCtrlConnect().
283 * We may need to use this for checking.
284 * @since 6.0
285 */
286VBGLR3DECL(bool) VbglR3GuestCtrlSupportsOptimizations(uint32_t idClient)
287{
288 return vbglR3GuestCtrlSupportsPeekGetCancel(idClient);
289}
290
291
292/**
293 * Make us the guest control master client.
294 *
295 * @returns VBox status code.
296 * @param idClient The client ID returned by VbglR3GuestCtrlConnect().
297 */
298VBGLR3DECL(int) VbglR3GuestCtrlMakeMeMaster(uint32_t idClient)
299{
300 int rc;
301 do
302 {
303 VBGLIOCHGCMCALL Hdr;
304 VBGL_HGCM_HDR_INIT(&Hdr, idClient, GUEST_MSG_MAKE_ME_MASTER, 0);
305 rc = VbglR3HGCMCall(&Hdr, sizeof(Hdr));
306 } while (rc == VERR_INTERRUPTED);
307 return rc;
308}
309
310
311/**
312 * Reports features to the host and retrieve host feature set.
313 *
314 * @returns VBox status code.
315 * @param idClient The client ID returned by VbglR3GuestCtrlConnect().
316 * @param fGuestFeatures Features to report, VBOX_GUESTCTRL_GF_XXX.
317 * @param pfHostFeatures Where to store the features VBOX_GUESTCTRL_HF_XXX.
318 */
319VBGLR3DECL(int) VbglR3GuestCtrlReportFeatures(uint32_t idClient, uint64_t fGuestFeatures, uint64_t *pfHostFeatures)
320{
321 int rc;
322 do
323 {
324 struct
325 {
326 VBGLIOCHGCMCALL Hdr;
327 HGCMFunctionParameter f64Features0;
328 HGCMFunctionParameter f64Features1;
329 } Msg;
330 VBGL_HGCM_HDR_INIT(&Msg.Hdr, idClient, GUEST_MSG_REPORT_FEATURES, 2);
331 VbglHGCMParmUInt64Set(&Msg.f64Features0, fGuestFeatures);
332 VbglHGCMParmUInt64Set(&Msg.f64Features1, VBOX_GUESTCTRL_GF_1_MUST_BE_ONE);
333
334 rc = VbglR3HGCMCall(&Msg.Hdr, sizeof(Msg));
335 if (RT_SUCCESS(rc))
336 {
337 Assert(Msg.f64Features0.type == VMMDevHGCMParmType_64bit);
338 Assert(Msg.f64Features1.type == VMMDevHGCMParmType_64bit);
339 if (Msg.f64Features1.u.value64 & VBOX_GUESTCTRL_GF_1_MUST_BE_ONE)
340 rc = VERR_NOT_SUPPORTED;
341 else if (pfHostFeatures)
342 *pfHostFeatures = Msg.f64Features0.u.value64;
343 break;
344 }
345 } while (rc == VERR_INTERRUPTED);
346 return rc;
347
348}
349
350
351/**
352 * Query the host features.
353 *
354 * @returns VBox status code.
355 * @param idClient The client ID returned by VbglR3GuestCtrlConnect().
356 * @param pfHostFeatures Where to store the host feature, VBOX_GUESTCTRL_HF_XXX.
357 */
358VBGLR3DECL(int) VbglR3GuestCtrlQueryFeatures(uint32_t idClient, uint64_t *pfHostFeatures)
359{
360 int rc;
361 do
362 {
363 struct
364 {
365 VBGLIOCHGCMCALL Hdr;
366 HGCMFunctionParameter f64Features0;
367 HGCMFunctionParameter f64Features1;
368 } Msg;
369 VBGL_HGCM_HDR_INIT(&Msg.Hdr, idClient, GUEST_MSG_QUERY_FEATURES, 2);
370 VbglHGCMParmUInt64Set(&Msg.f64Features0, 0);
371 VbglHGCMParmUInt64Set(&Msg.f64Features1, RT_BIT_64(63));
372
373 rc = VbglR3HGCMCall(&Msg.Hdr, sizeof(Msg));
374 if (RT_SUCCESS(rc))
375 {
376 Assert(Msg.f64Features0.type == VMMDevHGCMParmType_64bit);
377 Assert(Msg.f64Features1.type == VMMDevHGCMParmType_64bit);
378 if (Msg.f64Features1.u.value64 & RT_BIT_64(63))
379 rc = VERR_NOT_SUPPORTED;
380 else if (pfHostFeatures)
381 *pfHostFeatures = Msg.f64Features0.u.value64;
382 break;
383 }
384 } while (rc == VERR_INTERRUPTED);
385 return rc;
386
387}
388
389
390/**
391 * Peeks at the next host message, waiting for one to turn up.
392 *
393 * @returns VBox status code.
394 * @retval VERR_INTERRUPTED if interrupted. Does the necessary cleanup, so
395 * caller just have to repeat this call.
396 * @retval VERR_VM_RESTORED if the VM has been restored (idRestoreCheck).
397 *
398 * @param idClient The client ID returned by VbglR3GuestCtrlConnect().
399 * @param pidMsg Where to store the message id.
400 * @param pcParameters Where to store the number of parameters which will
401 * be received in a second call to the host.
402 * @param pidRestoreCheck Pointer to the VbglR3GetSessionId() variable to use
403 * for the VM restore check. Optional.
404 *
405 * @note Restore check is only performed optimally with a 6.0 host.
406 */
407VBGLR3DECL(int) VbglR3GuestCtrlMsgPeekWait(uint32_t idClient, uint32_t *pidMsg, uint32_t *pcParameters, uint64_t *pidRestoreCheck)
408{
409 AssertPtrReturn(pidMsg, VERR_INVALID_POINTER);
410 AssertPtrReturn(pcParameters, VERR_INVALID_POINTER);
411
412 int rc;
413 if (vbglR3GuestCtrlSupportsPeekGetCancel(idClient))
414 {
415 struct
416 {
417 VBGLIOCHGCMCALL Hdr;
418 HGCMFunctionParameter idMsg; /* Doubles as restore check on input. */
419 HGCMFunctionParameter cParameters;
420 } Msg;
421 VBGL_HGCM_HDR_INIT(&Msg.Hdr, idClient, GUEST_MSG_PEEK_WAIT, 2);
422 VbglHGCMParmUInt64Set(&Msg.idMsg, pidRestoreCheck ? *pidRestoreCheck : 0);
423 VbglHGCMParmUInt32Set(&Msg.cParameters, 0);
424 rc = VbglR3HGCMCall(&Msg.Hdr, sizeof(Msg));
425 LogRel2(("VbglR3GuestCtrlMsgPeekWait -> %Rrc\n", rc));
426 if (RT_SUCCESS(rc))
427 {
428 AssertMsgReturn( Msg.idMsg.type == VMMDevHGCMParmType_64bit
429 && Msg.cParameters.type == VMMDevHGCMParmType_32bit,
430 ("msg.type=%d num_parms.type=%d\n", Msg.idMsg.type, Msg.cParameters.type),
431 VERR_INTERNAL_ERROR_3);
432
433 *pidMsg = (uint32_t)Msg.idMsg.u.value64;
434 *pcParameters = Msg.cParameters.u.value32;
435 return rc;
436 }
437
438 /*
439 * If interrupted we must cancel the call so it doesn't prevent us from making another one.
440 */
441 if (rc == VERR_INTERRUPTED)
442 {
443 VBGL_HGCM_HDR_INIT(&Msg.Hdr, idClient, GUEST_MSG_CANCEL, 0);
444 int rc2 = VbglR3HGCMCall(&Msg.Hdr, sizeof(Msg.Hdr));
445 AssertRC(rc2);
446 }
447
448 /*
449 * If restored, update pidRestoreCheck.
450 */
451 if (rc == VERR_VM_RESTORED && pidRestoreCheck)
452 *pidRestoreCheck = Msg.idMsg.u.value64;
453
454 *pidMsg = UINT32_MAX - 1;
455 *pcParameters = UINT32_MAX - 2;
456 return rc;
457 }
458
459 /*
460 * Fallback if host < v6.0.
461 *
462 * Note! The restore check isn't perfect. Would require checking afterwards
463 * and stash the result if we were restored during the call. Too much
464 * hazzle for a downgrade scenario.
465 */
466 if (pidRestoreCheck)
467 {
468 uint64_t idRestoreCur = *pidRestoreCheck;
469 rc = VbglR3GetSessionId(&idRestoreCur);
470 if (RT_SUCCESS(rc) && idRestoreCur != *pidRestoreCheck)
471 {
472 *pidRestoreCheck = idRestoreCur;
473 return VERR_VM_RESTORED;
474 }
475 }
476
477 rc = vbglR3GuestCtrlMsgWaitFor(idClient, pidMsg, pcParameters);
478 if (rc == VERR_TOO_MUCH_DATA)
479 rc = VINF_SUCCESS;
480 return rc;
481}
482
483
484/**
485 * Asks the host guest control service to set a message filter to this
486 * client so that it only will receive certain messages in the future.
487 * The filter(s) are a bitmask for the context IDs, served from the host.
488 *
489 * @return IPRT status code.
490 * @param idClient The client ID returned by VbglR3GuestCtrlConnect().
491 * @param uValue The value to filter messages for.
492 * @param uMaskAdd Filter mask to add.
493 * @param uMaskRemove Filter mask to remove.
494 */
495VBGLR3DECL(int) VbglR3GuestCtrlMsgFilterSet(uint32_t idClient, uint32_t uValue, uint32_t uMaskAdd, uint32_t uMaskRemove)
496{
497 HGCMMsgFilterSet Msg;
498
499 /* Tell the host we want to set a filter. */
500 VBGL_HGCM_HDR_INIT(&Msg.hdr, idClient, GUEST_MSG_FILTER_SET, 4);
501 VbglHGCMParmUInt32Set(&Msg.value, uValue);
502 VbglHGCMParmUInt32Set(&Msg.mask_add, uMaskAdd);
503 VbglHGCMParmUInt32Set(&Msg.mask_remove, uMaskRemove);
504 VbglHGCMParmUInt32Set(&Msg.flags, 0 /* Flags, unused */);
505
506 return VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
507}
508
509
510/**
511 * Replies to a message from the host.
512 *
513 * @returns VBox status code.
514 * @param pCtx Guest control command context to use.
515 * @param rc Guest rc to reply.
516 */
517VBGLR3DECL(int) VbglR3GuestCtrlMsgReply(PVBGLR3GUESTCTRLCMDCTX pCtx,
518 int rc)
519{
520 return VbglR3GuestCtrlMsgReplyEx(pCtx, rc, 0 /* uType */,
521 NULL /* pvPayload */, 0 /* cbPayload */);
522}
523
524
525/**
526 * Replies to a message from the host, extended version.
527 *
528 * @returns VBox status code.
529 * @param pCtx Guest control command context to use.
530 * @param rc Guest rc to reply.
531 * @param uType Reply type; not used yet and must be 0.
532 * @param pvPayload Pointer to data payload to reply. Optional.
533 * @param cbPayload Size of data payload (in bytes) to reply.
534 */
535VBGLR3DECL(int) VbglR3GuestCtrlMsgReplyEx(PVBGLR3GUESTCTRLCMDCTX pCtx,
536 int rc, uint32_t uType,
537 void *pvPayload, uint32_t cbPayload)
538{
539 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
540 /* Everything else is optional. */
541
542 HGCMMsgReply Msg;
543 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, GUEST_MSG_REPLY, 4);
544 VbglHGCMParmUInt32Set(&Msg.context, pCtx->uContextID);
545 VbglHGCMParmUInt32Set(&Msg.type, uType);
546 VbglHGCMParmUInt32Set(&Msg.rc, (uint32_t)rc); /* int vs. uint32_t */
547 VbglHGCMParmPtrSet(&Msg.payload, pvPayload, cbPayload);
548
549 return VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
550}
551
552/**
553 * Tell the host to skip the current message replying VERR_NOT_SUPPORTED
554 *
555 * @return IPRT status code.
556 * @param idClient The client ID returned by VbglR3GuestCtrlConnect().
557 * @param rcSkip The status code to pass back to Main when skipping.
558 * @param idMsg The message ID to skip, pass UINT32_MAX to pass any.
559 */
560VBGLR3DECL(int) VbglR3GuestCtrlMsgSkip(uint32_t idClient, int rcSkip, uint32_t idMsg)
561{
562 if (vbglR3GuestCtrlSupportsPeekGetCancel(idClient))
563 {
564 struct
565 {
566 VBGLIOCHGCMCALL Hdr;
567 HGCMFunctionParameter rcSkip;
568 HGCMFunctionParameter idMsg;
569 } Msg;
570 VBGL_HGCM_HDR_INIT(&Msg.Hdr, idClient, GUEST_MSG_SKIP, 2);
571 VbglHGCMParmUInt32Set(&Msg.rcSkip, (uint32_t)rcSkip);
572 VbglHGCMParmUInt32Set(&Msg.idMsg, idMsg);
573 return VbglR3HGCMCall(&Msg.Hdr, sizeof(Msg));
574 }
575
576 /* This is generally better than nothing... */
577 return VbglR3GuestCtrlMsgSkipOld(idClient);
578}
579
580
581/**
582 * Tells the host service to skip the current message returned by
583 * VbglR3GuestCtrlMsgWaitFor().
584 *
585 * @return IPRT status code.
586 * @param idClient The client ID returned by VbglR3GuestCtrlConnect().
587 */
588VBGLR3DECL(int) VbglR3GuestCtrlMsgSkipOld(uint32_t idClient)
589{
590 HGCMMsgSkip Msg;
591
592 /* Tell the host we want to skip the current assigned message. */
593 VBGL_HGCM_HDR_INIT(&Msg.hdr, idClient, GUEST_MSG_SKIP_OLD, 1);
594 VbglHGCMParmUInt32Set(&Msg.flags, 0 /* Flags, unused */);
595 return VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
596}
597
598
599/**
600 * Asks the host to cancel (release) all pending waits which were deferred.
601 *
602 * @returns VBox status code.
603 * @param idClient The client ID returned by VbglR3GuestCtrlConnect().
604 */
605VBGLR3DECL(int) VbglR3GuestCtrlCancelPendingWaits(uint32_t idClient)
606{
607 HGCMMsgCancelPendingWaits Msg;
608 VBGL_HGCM_HDR_INIT(&Msg.hdr, idClient, GUEST_MSG_CANCEL, 0);
609 return VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
610}
611
612
613/**
614 * Prepares a session.
615 * @since 6.0
616 * @sa GUEST_SESSION_PREPARE
617 */
618VBGLR3DECL(int) VbglR3GuestCtrlSessionPrepare(uint32_t idClient, uint32_t idSession, void const *pvKey, uint32_t cbKey)
619{
620 int rc;
621 do
622 {
623 struct
624 {
625 VBGLIOCHGCMCALL Hdr;
626 HGCMFunctionParameter idSession;
627 HGCMFunctionParameter pKey;
628 } Msg;
629 VBGL_HGCM_HDR_INIT(&Msg.Hdr, idClient, GUEST_MSG_SESSION_PREPARE, 2);
630 VbglHGCMParmUInt32Set(&Msg.idSession, idSession);
631 VbglHGCMParmPtrSet(&Msg.pKey, (void *)pvKey, cbKey);
632 rc = VbglR3HGCMCall(&Msg.Hdr, sizeof(Msg));
633 } while (rc == VERR_INTERRUPTED);
634 return rc;
635}
636
637
638/**
639 * Accepts a session.
640 * @since 6.0
641 * @sa GUEST_SESSION_ACCEPT
642 */
643VBGLR3DECL(int) VbglR3GuestCtrlSessionAccept(uint32_t idClient, uint32_t idSession, void const *pvKey, uint32_t cbKey)
644{
645 int rc;
646 do
647 {
648 struct
649 {
650 VBGLIOCHGCMCALL Hdr;
651 HGCMFunctionParameter idSession;
652 HGCMFunctionParameter pKey;
653 } Msg;
654 VBGL_HGCM_HDR_INIT(&Msg.Hdr, idClient, GUEST_MSG_SESSION_ACCEPT, 2);
655 VbglHGCMParmUInt32Set(&Msg.idSession, idSession);
656 VbglHGCMParmPtrSet(&Msg.pKey, (void *)pvKey, cbKey);
657 rc = VbglR3HGCMCall(&Msg.Hdr, sizeof(Msg));
658 } while (rc == VERR_INTERRUPTED);
659 return rc;
660}
661
662
663/**
664 * Cancels a prepared session.
665 * @since 6.0
666 * @sa GUEST_SESSION_CANCEL_PREPARED
667 */
668VBGLR3DECL(int) VbglR3GuestCtrlSessionCancelPrepared(uint32_t idClient, uint32_t idSession)
669{
670 int rc;
671 do
672 {
673 struct
674 {
675 VBGLIOCHGCMCALL Hdr;
676 HGCMFunctionParameter idSession;
677 } Msg;
678 VBGL_HGCM_HDR_INIT(&Msg.Hdr, idClient, GUEST_MSG_SESSION_CANCEL_PREPARED, 1);
679 VbglHGCMParmUInt32Set(&Msg.idSession, idSession);
680 rc = VbglR3HGCMCall(&Msg.Hdr, sizeof(Msg));
681 } while (rc == VERR_INTERRUPTED);
682 return rc;
683}
684
685
686/**
687 * Invalidates the internal state because the (VM) session has been changed (i.e. restored).
688 *
689 * @returns VBox status code.
690 * @param idClient Client ID to use for invalidating state.
691 * @param idNewControlSession New control session ID. Currently unused.
692 */
693VBGLR3DECL(int) VbglR3GuestCtrlSessionHasChanged(uint32_t idClient, uint64_t idNewControlSession)
694{
695 RT_NOREF(idNewControlSession);
696
697 vbglR3GuestCtrlDetectPeekGetCancelSupport(idClient);
698
699 return VINF_SUCCESS;
700}
701
702
703/**
704 * Asks a specific guest session to close.
705 *
706 * @return IPRT status code.
707 * @param pCtx Guest control command context to use.
708 * @param fFlags Some kind of flag. Figure it out yourself.
709 */
710VBGLR3DECL(int) VbglR3GuestCtrlSessionClose(PVBGLR3GUESTCTRLCMDCTX pCtx, uint32_t fFlags)
711{
712 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
713 AssertReturn(pCtx->uNumParms == 2, VERR_INVALID_PARAMETER);
714
715 HGCMMsgSessionClose Msg;
716 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, GUEST_MSG_SESSION_CLOSE, pCtx->uNumParms);
717 VbglHGCMParmUInt32Set(&Msg.context, pCtx->uContextID);
718 VbglHGCMParmUInt32Set(&Msg.flags, fFlags);
719
720 return VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
721}
722
723
724/**
725 * Notifies a guest session.
726 *
727 * @returns VBox status code.
728 * @param pCtx Guest control command context to use.
729 * @param uType Notification type of type GUEST_SESSION_NOTIFYTYPE_XXX.
730 * @param iResult Result code (rc) to notify.
731 */
732VBGLR3DECL(int) VbglR3GuestCtrlSessionNotify(PVBGLR3GUESTCTRLCMDCTX pCtx, uint32_t uType, int32_t iResult)
733{
734 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
735
736 HGCMMsgSessionNotify Msg;
737 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, GUEST_MSG_SESSION_NOTIFY, 3);
738 VbglHGCMParmUInt32Set(&Msg.context, pCtx->uContextID);
739 VbglHGCMParmUInt32Set(&Msg.type, uType);
740 VbglHGCMParmUInt32Set(&Msg.result, (uint32_t)iResult);
741
742 return VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
743}
744
745/**
746 * Initializes a session startup info, extended version.
747 *
748 * @returns VBox status code.
749 * @param pStartupInfo Session startup info to initializes.
750 * @param cbUser Size (in bytes) to use for the user name buffer.
751 * @param cbPassword Size (in bytes) to use for the password buffer.
752 * @param cbDomain Size (in bytes) to use for the domain name buffer.
753 */
754VBGLR3DECL(int) VbglR3GuestCtrlSessionStartupInfoInitEx(PVBGLR3GUESTCTRLSESSIONSTARTUPINFO pStartupInfo,
755 size_t cbUser, size_t cbPassword, size_t cbDomain)
756{
757 AssertPtrReturn(pStartupInfo, VERR_INVALID_POINTER);
758
759 RT_BZERO(pStartupInfo, sizeof(VBGLR3GUESTCTRLSESSIONSTARTUPINFO));
760
761#define ALLOC_STR(a_Str, a_cb) \
762 if ((a_cb) > 0) \
763 { \
764 pStartupInfo->psz##a_Str = RTStrAlloc(a_cb); \
765 AssertPtrBreak(pStartupInfo->psz##a_Str); \
766 pStartupInfo->cb##a_Str = (uint32_t)a_cb; \
767 }
768
769 do
770 {
771 ALLOC_STR(User, cbUser);
772 ALLOC_STR(Password, cbPassword);
773 ALLOC_STR(Domain, cbDomain);
774
775 return VINF_SUCCESS;
776
777 } while (0);
778
779#undef ALLOC_STR
780
781 VbglR3GuestCtrlSessionStartupInfoDestroy(pStartupInfo);
782 return VERR_NO_MEMORY;
783}
784
785/**
786 * Initializes a session startup info.
787 *
788 * @returns VBox status code.
789 * @param pStartupInfo Session startup info to initializes.
790 */
791VBGLR3DECL(int) VbglR3GuestCtrlSessionStartupInfoInit(PVBGLR3GUESTCTRLSESSIONSTARTUPINFO pStartupInfo)
792{
793 return VbglR3GuestCtrlSessionStartupInfoInitEx(pStartupInfo,
794 GUESTPROCESS_DEFAULT_USER_LEN, GUESTPROCESS_DEFAULT_PASSWORD_LEN,
795 GUESTPROCESS_DEFAULT_DOMAIN_LEN);
796}
797
798/**
799 * Destroys a session startup info.
800 *
801 * @param pStartupInfo Session startup info to destroy.
802 */
803VBGLR3DECL(void) VbglR3GuestCtrlSessionStartupInfoDestroy(PVBGLR3GUESTCTRLSESSIONSTARTUPINFO pStartupInfo)
804{
805 if (!pStartupInfo)
806 return;
807
808 RTStrFree(pStartupInfo->pszUser);
809 RTStrFree(pStartupInfo->pszPassword);
810 RTStrFree(pStartupInfo->pszDomain);
811
812 RT_BZERO(pStartupInfo, sizeof(VBGLR3GUESTCTRLSESSIONSTARTUPINFO));
813}
814
815/**
816 * Free's a session startup info.
817 *
818 * @param pStartupInfo Session startup info to free.
819 * The pointer will not be valid anymore after return.
820 */
821VBGLR3DECL(void) VbglR3GuestCtrlSessionStartupInfoFree(PVBGLR3GUESTCTRLSESSIONSTARTUPINFO pStartupInfo)
822{
823 if (!pStartupInfo)
824 return;
825
826 VbglR3GuestCtrlSessionStartupInfoDestroy(pStartupInfo);
827
828 RTMemFree(pStartupInfo);
829 pStartupInfo = NULL;
830}
831
832/**
833 * Duplicates a session startup info.
834 *
835 * @returns Duplicated session startup info on success, or NULL on error.
836 * @param pStartupInfo Session startup info to duplicate.
837 */
838VBGLR3DECL(PVBGLR3GUESTCTRLSESSIONSTARTUPINFO) VbglR3GuestCtrlSessionStartupInfoDup(PVBGLR3GUESTCTRLSESSIONSTARTUPINFO pStartupInfo)
839{
840 AssertPtrReturn(pStartupInfo, NULL);
841
842 PVBGLR3GUESTCTRLSESSIONSTARTUPINFO pStartupInfoDup = (PVBGLR3GUESTCTRLSESSIONSTARTUPINFO)
843 RTMemDup(pStartupInfo, sizeof(VBGLR3GUESTCTRLSESSIONSTARTUPINFO));
844 if (pStartupInfoDup)
845 {
846 do
847 {
848 pStartupInfoDup->pszUser = NULL;
849 pStartupInfoDup->pszPassword = NULL;
850 pStartupInfoDup->pszDomain = NULL;
851
852#define DUP_STR(a_Str) \
853 if (pStartupInfo->cb##a_Str) \
854 { \
855 pStartupInfoDup->psz##a_Str = (char *)RTStrDup(pStartupInfo->psz##a_Str); \
856 AssertPtrBreak(pStartupInfoDup->psz##a_Str); \
857 pStartupInfoDup->cb##a_Str = (uint32_t)strlen(pStartupInfoDup->psz##a_Str) + 1 /* Include terminator */; \
858 }
859 DUP_STR(User);
860 DUP_STR(Password);
861 DUP_STR(Domain);
862
863#undef DUP_STR
864
865 return pStartupInfoDup;
866
867 } while (0); /* To use break macros above. */
868
869 VbglR3GuestCtrlSessionStartupInfoFree(pStartupInfoDup);
870 }
871
872 return NULL;
873}
874
875/**
876 * Retrieves a HOST_SESSION_CREATE message.
877 *
878 * @returns VBox status code.
879 * @param pCtx Guest control command context to use.
880 * @param ppStartupInfo Where to store the allocated session startup info.
881 * Needs to be free'd by VbglR3GuestCtrlSessionStartupInfoFree().
882 */
883VBGLR3DECL(int) VbglR3GuestCtrlSessionGetOpen(PVBGLR3GUESTCTRLCMDCTX pCtx, PVBGLR3GUESTCTRLSESSIONSTARTUPINFO *ppStartupInfo)
884{
885 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
886 AssertReturn(pCtx->uNumParms == 6, VERR_INVALID_PARAMETER);
887 AssertPtrReturn(ppStartupInfo, VERR_INVALID_POINTER);
888
889 PVBGLR3GUESTCTRLSESSIONSTARTUPINFO pStartupInfo
890 = (PVBGLR3GUESTCTRLSESSIONSTARTUPINFO)RTMemAlloc(sizeof(VBGLR3GUESTCTRLSESSIONSTARTUPINFO));
891 if (!pStartupInfo)
892 return VERR_NO_MEMORY;
893
894 int rc = VbglR3GuestCtrlSessionStartupInfoInit(pStartupInfo);
895 if (RT_FAILURE(rc))
896 {
897 VbglR3GuestCtrlSessionStartupInfoFree(pStartupInfo);
898 return rc;
899 }
900
901 do
902 {
903 HGCMMsgSessionOpen Msg;
904 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, vbglR3GuestCtrlGetMsgFunctionNo(pCtx->uClientID), pCtx->uNumParms);
905 VbglHGCMParmUInt32Set(&Msg.context, HOST_MSG_SESSION_CREATE);
906 VbglHGCMParmUInt32Set(&Msg.protocol, 0);
907 VbglHGCMParmPtrSet(&Msg.username, pStartupInfo->pszUser, pStartupInfo->cbUser);
908 VbglHGCMParmPtrSet(&Msg.password, pStartupInfo->pszPassword, pStartupInfo->cbPassword);
909 VbglHGCMParmPtrSet(&Msg.domain, pStartupInfo->pszDomain, pStartupInfo->cbDomain);
910 VbglHGCMParmUInt32Set(&Msg.flags, 0);
911
912 rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
913 if (RT_SUCCESS(rc))
914 {
915 Msg.context.GetUInt32(&pCtx->uContextID);
916 Msg.protocol.GetUInt32(&pStartupInfo->uProtocol);
917 Msg.flags.GetUInt32(&pStartupInfo->fFlags);
918
919 pStartupInfo->uSessionID = VBOX_GUESTCTRL_CONTEXTID_GET_SESSION(pCtx->uContextID);
920 }
921
922 } while (rc == VERR_INTERRUPTED && g_fVbglR3GuestCtrlHavePeekGetCancel);
923
924 if (RT_SUCCESS(rc))
925 {
926 *ppStartupInfo = pStartupInfo;
927 }
928 else
929 VbglR3GuestCtrlSessionStartupInfoFree(pStartupInfo);
930
931 LogFlowFuncLeaveRC(rc);
932 return rc;
933}
934
935
936/**
937 * Retrieves a HOST_SESSION_CLOSE message.
938 */
939VBGLR3DECL(int) VbglR3GuestCtrlSessionGetClose(PVBGLR3GUESTCTRLCMDCTX pCtx, uint32_t *pfFlags, uint32_t *pidSession)
940{
941 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
942 AssertReturn(pCtx->uNumParms == 2, VERR_INVALID_PARAMETER);
943
944 AssertPtrReturn(pfFlags, VERR_INVALID_POINTER);
945
946 int rc;
947 do
948 {
949 HGCMMsgSessionClose Msg;
950 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, vbglR3GuestCtrlGetMsgFunctionNo(pCtx->uClientID), pCtx->uNumParms);
951 VbglHGCMParmUInt32Set(&Msg.context, HOST_MSG_SESSION_CLOSE);
952 VbglHGCMParmUInt32Set(&Msg.flags, 0);
953
954 rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
955 if (RT_SUCCESS(rc))
956 {
957 Msg.context.GetUInt32(&pCtx->uContextID);
958 Msg.flags.GetUInt32(pfFlags);
959
960 if (pidSession)
961 *pidSession = VBOX_GUESTCTRL_CONTEXTID_GET_SESSION(pCtx->uContextID);
962 }
963 } while (rc == VERR_INTERRUPTED && g_fVbglR3GuestCtrlHavePeekGetCancel);
964 return rc;
965}
966
967
968/**
969 * Retrieves a HOST_PATH_RENAME message.
970 */
971VBGLR3DECL(int) VbglR3GuestCtrlPathGetRename(PVBGLR3GUESTCTRLCMDCTX pCtx,
972 char *pszSource, uint32_t cbSource,
973 char *pszDest, uint32_t cbDest,
974 uint32_t *pfFlags)
975{
976 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
977 AssertReturn(pCtx->uNumParms == 4, VERR_INVALID_PARAMETER);
978
979 AssertPtrReturn(pszSource, VERR_INVALID_POINTER);
980 AssertReturn(cbSource, VERR_INVALID_PARAMETER);
981 AssertPtrReturn(pszDest, VERR_INVALID_POINTER);
982 AssertReturn(cbDest, VERR_INVALID_PARAMETER);
983 AssertPtrReturn(pfFlags, VERR_INVALID_POINTER);
984
985 int rc;
986 do
987 {
988 HGCMMsgPathRename Msg;
989 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, vbglR3GuestCtrlGetMsgFunctionNo(pCtx->uClientID), pCtx->uNumParms);
990 VbglHGCMParmUInt32Set(&Msg.context, HOST_MSG_PATH_RENAME);
991 VbglHGCMParmPtrSet(&Msg.source, pszSource, cbSource);
992 VbglHGCMParmPtrSet(&Msg.dest, pszDest, cbDest);
993 VbglHGCMParmUInt32Set(&Msg.flags, 0);
994
995 rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
996 if (RT_SUCCESS(rc))
997 {
998 Msg.context.GetUInt32(&pCtx->uContextID);
999 Msg.flags.GetUInt32(pfFlags);
1000 }
1001
1002 } while (rc == VERR_INTERRUPTED && g_fVbglR3GuestCtrlHavePeekGetCancel);
1003 return rc;
1004}
1005
1006
1007/**
1008 * Retrieves a HOST_PATH_USER_DOCUMENTS message.
1009 */
1010VBGLR3DECL(int) VbglR3GuestCtrlPathGetUserDocuments(PVBGLR3GUESTCTRLCMDCTX pCtx)
1011{
1012 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1013 AssertReturn(pCtx->uNumParms == 1, VERR_INVALID_PARAMETER);
1014
1015 int rc;
1016 do
1017 {
1018 HGCMMsgPathUserDocuments Msg;
1019 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, vbglR3GuestCtrlGetMsgFunctionNo(pCtx->uClientID), pCtx->uNumParms);
1020 VbglHGCMParmUInt32Set(&Msg.context, HOST_MSG_PATH_USER_DOCUMENTS);
1021
1022 rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
1023 if (RT_SUCCESS(rc))
1024 Msg.context.GetUInt32(&pCtx->uContextID);
1025 } while (rc == VERR_INTERRUPTED && g_fVbglR3GuestCtrlHavePeekGetCancel);
1026 return rc;
1027}
1028
1029
1030/**
1031 * Retrieves a HOST_PATH_USER_HOME message.
1032 */
1033VBGLR3DECL(int) VbglR3GuestCtrlPathGetUserHome(PVBGLR3GUESTCTRLCMDCTX pCtx)
1034{
1035 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1036 AssertReturn(pCtx->uNumParms == 1, VERR_INVALID_PARAMETER);
1037
1038 int rc;
1039 do
1040 {
1041 HGCMMsgPathUserHome Msg;
1042 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, vbglR3GuestCtrlGetMsgFunctionNo(pCtx->uClientID), pCtx->uNumParms);
1043 VbglHGCMParmUInt32Set(&Msg.context, HOST_MSG_PATH_USER_HOME);
1044
1045 rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
1046 if (RT_SUCCESS(rc))
1047 Msg.context.GetUInt32(&pCtx->uContextID);
1048 } while (rc == VERR_INTERRUPTED && g_fVbglR3GuestCtrlHavePeekGetCancel);
1049 return rc;
1050}
1051
1052/**
1053 * Retrieves a HOST_MSG_SHUTDOWN message.
1054 *
1055 * @returns VBox status code.
1056 * @param pCtx Guest control command context to use.
1057 * @param pfAction Where to store the action flags on success.
1058 */
1059VBGLR3DECL(int) VbglR3GuestCtrlGetShutdown(PVBGLR3GUESTCTRLCMDCTX pCtx, uint32_t *pfAction)
1060{
1061 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1062 AssertReturn(pCtx->uNumParms == 2, VERR_INVALID_PARAMETER);
1063 AssertPtrReturn(pfAction, VERR_INVALID_POINTER);
1064
1065 int rc;
1066 do
1067 {
1068 HGCMMsgShutdown Msg;
1069 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, vbglR3GuestCtrlGetMsgFunctionNo(pCtx->uClientID), pCtx->uNumParms);
1070 VbglHGCMParmUInt32Set(&Msg.context, HOST_MSG_SHUTDOWN);
1071 VbglHGCMParmUInt32Set(&Msg.action, 0);
1072
1073 rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
1074 if (RT_SUCCESS(rc))
1075 {
1076 Msg.context.GetUInt32(&pCtx->uContextID);
1077 Msg.action.GetUInt32(pfAction);
1078 }
1079 } while (rc == VERR_INTERRUPTED && g_fVbglR3GuestCtrlHavePeekGetCancel);
1080 return rc;
1081}
1082
1083/**
1084 * Initializes a process startup info, extended version.
1085 *
1086 * @returns VBox status code.
1087 * @param pStartupInfo Process startup info to initializes.
1088 * @param cbCmd Size (in bytes) to use for the command buffer.
1089 * @param cbUser Size (in bytes) to use for the user name buffer.
1090 * @param cbPassword Size (in bytes) to use for the password buffer.
1091 * @param cbDomain Size (in bytes) to use for the domain buffer.
1092 * @param cbArgs Size (in bytes) to use for the arguments buffer.
1093 * @param cbEnv Size (in bytes) to use for the environment buffer.
1094 */
1095VBGLR3DECL(int) VbglR3GuestCtrlProcStartupInfoInitEx(PVBGLR3GUESTCTRLPROCSTARTUPINFO pStartupInfo,
1096 size_t cbCmd,
1097 size_t cbUser, size_t cbPassword, size_t cbDomain,
1098 size_t cbArgs, size_t cbEnv)
1099{
1100 AssertPtrReturn(pStartupInfo, VERR_INVALID_POINTER);
1101 AssertReturn(cbCmd, VERR_INVALID_PARAMETER);
1102 AssertReturn(cbUser, VERR_INVALID_PARAMETER);
1103 AssertReturn(cbPassword, VERR_INVALID_PARAMETER);
1104 AssertReturn(cbDomain, VERR_INVALID_PARAMETER);
1105 AssertReturn(cbArgs, VERR_INVALID_PARAMETER);
1106 AssertReturn(cbEnv, VERR_INVALID_PARAMETER);
1107
1108 RT_BZERO(pStartupInfo, sizeof(VBGLR3GUESTCTRLPROCSTARTUPINFO));
1109
1110#define ALLOC_STR(a_Str, a_cb) \
1111 if ((a_cb) > 0) \
1112 { \
1113 pStartupInfo->psz##a_Str = RTStrAlloc(a_cb); \
1114 AssertPtrBreak(pStartupInfo->psz##a_Str); \
1115 pStartupInfo->cb##a_Str = (uint32_t)a_cb; \
1116 }
1117
1118 do
1119 {
1120 ALLOC_STR(Cmd, cbCmd);
1121 ALLOC_STR(Args, cbArgs);
1122 ALLOC_STR(Env, cbEnv);
1123 ALLOC_STR(User, cbUser);
1124 ALLOC_STR(Password, cbPassword);
1125 ALLOC_STR(Domain, cbDomain);
1126
1127 return VINF_SUCCESS;
1128
1129 } while (0);
1130
1131#undef ALLOC_STR
1132
1133 VbglR3GuestCtrlProcStartupInfoDestroy(pStartupInfo);
1134 return VERR_NO_MEMORY;
1135}
1136
1137/**
1138 * Initializes a process startup info with default values.
1139 *
1140 * @param pStartupInfo Process startup info to initializes.
1141 */
1142VBGLR3DECL(int) VbglR3GuestCtrlProcStartupInfoInit(PVBGLR3GUESTCTRLPROCSTARTUPINFO pStartupInfo)
1143{
1144 return VbglR3GuestCtrlProcStartupInfoInitEx(pStartupInfo,
1145 GUESTPROCESS_DEFAULT_CMD_LEN,
1146 GUESTPROCESS_DEFAULT_USER_LEN /* Deprecated, now handled via session creation. */,
1147 GUESTPROCESS_DEFAULT_PASSWORD_LEN /* Ditto. */,
1148 GUESTPROCESS_DEFAULT_DOMAIN_LEN /* Ditto. */,
1149 GUESTPROCESS_DEFAULT_ARGS_LEN, GUESTPROCESS_DEFAULT_ENV_LEN);
1150}
1151
1152/**
1153 * Destroys a process startup info.
1154 *
1155 * @param pStartupInfo Process startup info to destroy.
1156 */
1157VBGLR3DECL(void) VbglR3GuestCtrlProcStartupInfoDestroy(PVBGLR3GUESTCTRLPROCSTARTUPINFO pStartupInfo)
1158{
1159 if (!pStartupInfo)
1160 return;
1161
1162 RTStrFree(pStartupInfo->pszCmd);
1163 RTStrFree(pStartupInfo->pszArgs);
1164 RTStrFree(pStartupInfo->pszEnv);
1165 RTStrFree(pStartupInfo->pszUser);
1166 RTStrFree(pStartupInfo->pszPassword);
1167 RTStrFree(pStartupInfo->pszDomain);
1168
1169 RT_BZERO(pStartupInfo, sizeof(VBGLR3GUESTCTRLPROCSTARTUPINFO));
1170}
1171
1172/**
1173 * Free's a process startup info.
1174 *
1175 * @param pStartupInfo Process startup info to free.
1176 * The pointer will not be valid anymore after return.
1177 */
1178VBGLR3DECL(void) VbglR3GuestCtrlProcStartupInfoFree(PVBGLR3GUESTCTRLPROCSTARTUPINFO pStartupInfo)
1179{
1180 if (!pStartupInfo)
1181 return;
1182
1183 VbglR3GuestCtrlProcStartupInfoDestroy(pStartupInfo);
1184
1185 RTMemFree(pStartupInfo);
1186 pStartupInfo = NULL;
1187}
1188
1189/**
1190 * Duplicates a process startup info.
1191 *
1192 * @returns Duplicated process startup info on success, or NULL on error.
1193 * @param pStartupInfo Process startup info to duplicate.
1194 */
1195VBGLR3DECL(PVBGLR3GUESTCTRLPROCSTARTUPINFO) VbglR3GuestCtrlProcStartupInfoDup(PVBGLR3GUESTCTRLPROCSTARTUPINFO pStartupInfo)
1196{
1197 AssertPtrReturn(pStartupInfo, NULL);
1198
1199 PVBGLR3GUESTCTRLPROCSTARTUPINFO pStartupInfoDup = (PVBGLR3GUESTCTRLPROCSTARTUPINFO)
1200 RTMemDup(pStartupInfo, sizeof(VBGLR3GUESTCTRLPROCSTARTUPINFO));
1201 if (pStartupInfoDup)
1202 {
1203 do
1204 {
1205 pStartupInfoDup->pszCmd = NULL;
1206 pStartupInfoDup->pszArgs = NULL;
1207 pStartupInfoDup->pszEnv = NULL;
1208 pStartupInfoDup->pszUser = NULL;
1209 pStartupInfoDup->pszPassword = NULL;
1210 pStartupInfoDup->pszDomain = NULL;
1211
1212#define DUP_STR(a_Str) \
1213 if (pStartupInfo->cb##a_Str) \
1214 { \
1215 pStartupInfoDup->psz##a_Str = (char *)RTStrDup(pStartupInfo->psz##a_Str); \
1216 AssertPtrBreak(pStartupInfoDup->psz##a_Str); \
1217 pStartupInfoDup->cb##a_Str = (uint32_t)strlen(pStartupInfoDup->psz##a_Str) + 1 /* Include terminator */; \
1218 }
1219
1220#define DUP_MEM(a_Str) \
1221 if (pStartupInfo->cb##a_Str) \
1222 { \
1223 pStartupInfoDup->psz##a_Str = (char *)RTMemDup(pStartupInfo->psz##a_Str, pStartupInfo->cb##a_Str); \
1224 AssertPtrBreak(pStartupInfoDup->psz##a_Str); \
1225 pStartupInfoDup->cb##a_Str = (uint32_t)pStartupInfo->cb##a_Str; \
1226 }
1227
1228 DUP_STR(Cmd);
1229 DUP_MEM(Args);
1230 DUP_MEM(Env);
1231 DUP_STR(User);
1232 DUP_STR(Password);
1233 DUP_STR(Domain);
1234
1235#undef DUP_STR
1236#undef DUP_MEM
1237
1238 return pStartupInfoDup;
1239
1240 } while (0); /* To use break macros above. */
1241
1242 VbglR3GuestCtrlProcStartupInfoFree(pStartupInfoDup);
1243 }
1244
1245 return NULL;
1246}
1247
1248/**
1249 * Retrieves a HOST_EXEC_CMD message.
1250 *
1251 * @returns VBox status code.
1252 * @param pCtx Guest control command context to use.
1253 * @param ppStartupInfo Where to store the allocated session startup info.
1254 * Needs to be free'd by VbglR3GuestCtrlProcStartupInfoFree().
1255 */
1256VBGLR3DECL(int) VbglR3GuestCtrlProcGetStart(PVBGLR3GUESTCTRLCMDCTX pCtx, PVBGLR3GUESTCTRLPROCSTARTUPINFO *ppStartupInfo)
1257{
1258 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1259 AssertPtrReturn(ppStartupInfo, VERR_INVALID_POINTER);
1260
1261 PVBGLR3GUESTCTRLPROCSTARTUPINFO pStartupInfo
1262 = (PVBGLR3GUESTCTRLPROCSTARTUPINFO)RTMemAlloc(sizeof(VBGLR3GUESTCTRLPROCSTARTUPINFO));
1263 if (!pStartupInfo)
1264 return VERR_NO_MEMORY;
1265
1266 int rc = VbglR3GuestCtrlProcStartupInfoInit(pStartupInfo);
1267 if (RT_FAILURE(rc))
1268 {
1269 VbglR3GuestCtrlProcStartupInfoFree(pStartupInfo);
1270 return rc;
1271 }
1272
1273 unsigned cRetries = 0;
1274 const unsigned cMaxRetries = 32; /* Should be enough for now. */
1275 const unsigned cGrowthFactor = 2; /* By how much the buffers will grow if they're too small yet. */
1276
1277 do
1278 {
1279 LogRel(("VbglR3GuestCtrlProcGetStart: Retrieving\n"));
1280
1281 HGCMMsgProcExec Msg;
1282 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, vbglR3GuestCtrlGetMsgFunctionNo(pCtx->uClientID), pCtx->uNumParms);
1283 VbglHGCMParmUInt32Set(&Msg.context, HOST_MSG_EXEC_CMD);
1284 VbglHGCMParmPtrSet(&Msg.cmd, pStartupInfo->pszCmd, pStartupInfo->cbCmd);
1285 VbglHGCMParmUInt32Set(&Msg.flags, 0);
1286 VbglHGCMParmUInt32Set(&Msg.num_args, 0);
1287 VbglHGCMParmPtrSet(&Msg.args, pStartupInfo->pszArgs, pStartupInfo->cbArgs);
1288 VbglHGCMParmUInt32Set(&Msg.num_env, 0);
1289 VbglHGCMParmUInt32Set(&Msg.cb_env, 0);
1290 VbglHGCMParmPtrSet(&Msg.env, pStartupInfo->pszEnv, pStartupInfo->cbEnv);
1291 if (pCtx->uProtocol < 2)
1292 {
1293 VbglHGCMParmPtrSet(&Msg.u.v1.username, pStartupInfo->pszUser, pStartupInfo->cbUser);
1294 VbglHGCMParmPtrSet(&Msg.u.v1.password, pStartupInfo->pszPassword, pStartupInfo->cbPassword);
1295 VbglHGCMParmUInt32Set(&Msg.u.v1.timeout, 0);
1296 }
1297 else
1298 {
1299 VbglHGCMParmUInt32Set(&Msg.u.v2.timeout, 0);
1300 VbglHGCMParmUInt32Set(&Msg.u.v2.priority, 0);
1301 VbglHGCMParmUInt32Set(&Msg.u.v2.num_affinity, 0);
1302 VbglHGCMParmPtrSet(&Msg.u.v2.affinity, pStartupInfo->uAffinity, sizeof(pStartupInfo->uAffinity));
1303 }
1304
1305 rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
1306 if (RT_FAILURE(rc))
1307 {
1308 LogRel(("VbglR3GuestCtrlProcGetStart: 1 - %Rrc (retry %u, cbCmd=%RU32, cbArgs=%RU32, cbEnv=%RU32)\n",
1309 rc, cRetries, pStartupInfo->cbCmd, pStartupInfo->cbArgs, pStartupInfo->cbEnv));
1310
1311 if ( rc == VERR_BUFFER_OVERFLOW
1312 && cRetries++ < cMaxRetries)
1313 {
1314#define GROW_STR(a_Str, a_cbMax) \
1315 pStartupInfo->psz##a_Str = (char *)RTMemRealloc(pStartupInfo->psz##a_Str, \
1316 RT_MIN(pStartupInfo->cb##a_Str * cGrowthFactor, a_cbMax)); \
1317 AssertPtrBreakStmt(pStartupInfo->psz##a_Str, VERR_NO_MEMORY); \
1318 pStartupInfo->cb##a_Str = RT_MIN(pStartupInfo->cb##a_Str * cGrowthFactor, a_cbMax);
1319
1320 /* We can't tell which parameter doesn't fit, so we have to resize all. */
1321 GROW_STR(Cmd , GUESTPROCESS_MAX_CMD_LEN);
1322 GROW_STR(Args, GUESTPROCESS_MAX_ARGS_LEN);
1323 GROW_STR(Env, GUESTPROCESS_MAX_ENV_LEN);
1324
1325#undef GROW_STR
1326 LogRel(("VbglR3GuestCtrlProcGetStart: 2 - %Rrc (retry %u, cbCmd=%RU32, cbArgs=%RU32, cbEnv=%RU32)\n",
1327 rc, cRetries, pStartupInfo->cbCmd, pStartupInfo->cbArgs, pStartupInfo->cbEnv));
1328 LogRel(("g_fVbglR3GuestCtrlHavePeekGetCancel=%d\n", g_fVbglR3GuestCtrlHavePeekGetCancel));
1329
1330 /* Only try another round if we can peek for the next bigger size; otherwise bail out on the bottom. */
1331 if (RT_BOOL(g_fVbglR3GuestCtrlHavePeekGetCancel))
1332 continue;
1333 }
1334 else
1335 break;
1336 }
1337 else
1338 {
1339 Msg.context.GetUInt32(&pCtx->uContextID);
1340 Msg.flags.GetUInt32(&pStartupInfo->fFlags);
1341 Msg.num_args.GetUInt32(&pStartupInfo->cArgs);
1342 Msg.num_env.GetUInt32(&pStartupInfo->cEnvVars);
1343 Msg.cb_env.GetUInt32(&pStartupInfo->cbEnv);
1344 if (pCtx->uProtocol < 2)
1345 Msg.u.v1.timeout.GetUInt32(&pStartupInfo->uTimeLimitMS);
1346 else
1347 {
1348 Msg.u.v2.timeout.GetUInt32(&pStartupInfo->uTimeLimitMS);
1349 Msg.u.v2.priority.GetUInt32(&pStartupInfo->uPriority);
1350 Msg.u.v2.num_affinity.GetUInt32(&pStartupInfo->cAffinity);
1351 }
1352 }
1353 } while (rc == VERR_INTERRUPTED && g_fVbglR3GuestCtrlHavePeekGetCancel);
1354
1355 if (RT_SUCCESS(rc))
1356 {
1357 *ppStartupInfo = pStartupInfo;
1358 }
1359 else
1360 VbglR3GuestCtrlProcStartupInfoFree(pStartupInfo);
1361
1362 LogRel(("VbglR3GuestCtrlProcGetStart: Returning %Rrc (retry %u, cbCmd=%RU32, cbArgs=%RU32, cbEnv=%RU32)\n",
1363 rc, cRetries, pStartupInfo->cbCmd, pStartupInfo->cbArgs, pStartupInfo->cbEnv));
1364
1365 LogFlowFuncLeaveRC(rc);
1366 return rc;
1367}
1368
1369/**
1370 * Allocates and gets host data, based on the message ID.
1371 *
1372 * This will block until data becomes available.
1373 *
1374 * @returns VBox status code.
1375 * @param pCtx Guest control command context to use.
1376 * @param puPID Where to return the guest PID to retrieve output from on success.
1377 * @param puHandle Where to return the guest process handle to retrieve output from on success.
1378 * @param pfFlags Where to return the output flags on success.
1379 */
1380VBGLR3DECL(int) VbglR3GuestCtrlProcGetOutput(PVBGLR3GUESTCTRLCMDCTX pCtx,
1381 uint32_t *puPID, uint32_t *puHandle, uint32_t *pfFlags)
1382{
1383 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1384 AssertReturn(pCtx->uNumParms == 4, VERR_INVALID_PARAMETER);
1385
1386 AssertPtrReturn(puPID, VERR_INVALID_POINTER);
1387 AssertPtrReturn(puHandle, VERR_INVALID_POINTER);
1388 AssertPtrReturn(pfFlags, VERR_INVALID_POINTER);
1389
1390 int rc;
1391 do
1392 {
1393 HGCMMsgProcOutput Msg;
1394 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, vbglR3GuestCtrlGetMsgFunctionNo(pCtx->uClientID), pCtx->uNumParms);
1395 VbglHGCMParmUInt32Set(&Msg.context, HOST_MSG_EXEC_GET_OUTPUT);
1396 VbglHGCMParmUInt32Set(&Msg.pid, 0);
1397 VbglHGCMParmUInt32Set(&Msg.handle, 0);
1398 VbglHGCMParmUInt32Set(&Msg.flags, 0);
1399
1400 rc = VbglR3HGCMCall(&Msg.hdr, RT_UOFFSETOF(HGCMMsgProcOutput, data));
1401 if (RT_SUCCESS(rc))
1402 {
1403 Msg.context.GetUInt32(&pCtx->uContextID);
1404 Msg.pid.GetUInt32(puPID);
1405 Msg.handle.GetUInt32(puHandle);
1406 Msg.flags.GetUInt32(pfFlags);
1407 }
1408 } while (rc == VERR_INTERRUPTED && g_fVbglR3GuestCtrlHavePeekGetCancel);
1409 return rc;
1410}
1411
1412
1413/**
1414 * Retrieves the input data from host which then gets sent to the started
1415 * process (HOST_EXEC_SET_INPUT).
1416 *
1417 * This will block until data becomes available.
1418 */
1419VBGLR3DECL(int) VbglR3GuestCtrlProcGetInput(PVBGLR3GUESTCTRLCMDCTX pCtx,
1420 uint32_t *puPID, uint32_t *pfFlags,
1421 void *pvData, uint32_t cbData,
1422 uint32_t *pcbSize)
1423{
1424 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1425 AssertReturn(pCtx->uNumParms == 5, VERR_INVALID_PARAMETER);
1426
1427 AssertPtrReturn(puPID, VERR_INVALID_POINTER);
1428 AssertPtrReturn(pfFlags, VERR_INVALID_POINTER);
1429 AssertPtrReturn(pvData, VERR_INVALID_POINTER);
1430 AssertPtrReturn(pcbSize, VERR_INVALID_POINTER);
1431
1432 int rc;
1433 do
1434 {
1435 HGCMMsgProcInput Msg;
1436 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, vbglR3GuestCtrlGetMsgFunctionNo(pCtx->uClientID), pCtx->uNumParms);
1437 VbglHGCMParmUInt32Set(&Msg.context, HOST_MSG_EXEC_SET_INPUT);
1438 VbglHGCMParmUInt32Set(&Msg.pid, 0);
1439 VbglHGCMParmUInt32Set(&Msg.flags, 0);
1440 VbglHGCMParmPtrSet(&Msg.data, pvData, cbData);
1441 VbglHGCMParmUInt32Set(&Msg.size, 0);
1442
1443 rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
1444 if (RT_SUCCESS(rc))
1445 {
1446 Msg.context.GetUInt32(&pCtx->uContextID);
1447 Msg.pid.GetUInt32(puPID);
1448 Msg.flags.GetUInt32(pfFlags);
1449 Msg.size.GetUInt32(pcbSize);
1450 }
1451 } while (rc == VERR_INTERRUPTED && g_fVbglR3GuestCtrlHavePeekGetCancel);
1452
1453 if ( rc != VERR_TOO_MUCH_DATA
1454 || g_fVbglR3GuestCtrlHavePeekGetCancel)
1455 return rc;
1456 return VERR_BUFFER_OVERFLOW;
1457}
1458
1459
1460/**
1461 * Retrieves a HOST_DIR_REMOVE message.
1462 */
1463VBGLR3DECL(int) VbglR3GuestCtrlDirGetRemove(PVBGLR3GUESTCTRLCMDCTX pCtx,
1464 char *pszPath, uint32_t cbPath,
1465 uint32_t *pfFlags)
1466{
1467 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1468 AssertReturn(pCtx->uNumParms == 3, VERR_INVALID_PARAMETER);
1469
1470 AssertPtrReturn(pszPath, VERR_INVALID_POINTER);
1471 AssertReturn(cbPath, VERR_INVALID_PARAMETER);
1472 AssertPtrReturn(pfFlags, VERR_INVALID_POINTER);
1473
1474 int rc;
1475 do
1476 {
1477 HGCMMsgDirRemove Msg;
1478 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, vbglR3GuestCtrlGetMsgFunctionNo(pCtx->uClientID), pCtx->uNumParms);
1479 VbglHGCMParmUInt32Set(&Msg.context, HOST_MSG_DIR_REMOVE);
1480 VbglHGCMParmPtrSet(&Msg.path, pszPath, cbPath);
1481 VbglHGCMParmUInt32Set(&Msg.flags, 0);
1482
1483 rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
1484 if (RT_SUCCESS(rc))
1485 {
1486 Msg.context.GetUInt32(&pCtx->uContextID);
1487 Msg.flags.GetUInt32(pfFlags);
1488 }
1489 } while (rc == VERR_INTERRUPTED && g_fVbglR3GuestCtrlHavePeekGetCancel);
1490 return rc;
1491}
1492
1493
1494/**
1495 * Retrieves a HOST_FILE_OPEN message.
1496 */
1497VBGLR3DECL(int) VbglR3GuestCtrlFileGetOpen(PVBGLR3GUESTCTRLCMDCTX pCtx,
1498 char *pszFileName, uint32_t cbFileName,
1499 char *pszAccess, uint32_t cbAccess,
1500 char *pszDisposition, uint32_t cbDisposition,
1501 char *pszSharing, uint32_t cbSharing,
1502 uint32_t *puCreationMode,
1503 uint64_t *poffAt)
1504{
1505 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1506 AssertReturn(pCtx->uNumParms == 7, VERR_INVALID_PARAMETER);
1507
1508 AssertPtrReturn(pszFileName, VERR_INVALID_POINTER);
1509 AssertReturn(cbFileName, VERR_INVALID_PARAMETER);
1510 AssertPtrReturn(pszAccess, VERR_INVALID_POINTER);
1511 AssertReturn(cbAccess, VERR_INVALID_PARAMETER);
1512 AssertPtrReturn(pszDisposition, VERR_INVALID_POINTER);
1513 AssertReturn(cbDisposition, VERR_INVALID_PARAMETER);
1514 AssertPtrReturn(pszSharing, VERR_INVALID_POINTER);
1515 AssertReturn(cbSharing, VERR_INVALID_PARAMETER);
1516 AssertPtrReturn(puCreationMode, VERR_INVALID_POINTER);
1517 AssertPtrReturn(poffAt, VERR_INVALID_POINTER);
1518
1519 int rc;
1520 do
1521 {
1522 HGCMMsgFileOpen Msg;
1523 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, vbglR3GuestCtrlGetMsgFunctionNo(pCtx->uClientID), pCtx->uNumParms);
1524 VbglHGCMParmUInt32Set(&Msg.context, HOST_MSG_FILE_OPEN);
1525 VbglHGCMParmPtrSet(&Msg.filename, pszFileName, cbFileName);
1526 VbglHGCMParmPtrSet(&Msg.openmode, pszAccess, cbAccess);
1527 VbglHGCMParmPtrSet(&Msg.disposition, pszDisposition, cbDisposition);
1528 VbglHGCMParmPtrSet(&Msg.sharing, pszSharing, cbSharing);
1529 VbglHGCMParmUInt32Set(&Msg.creationmode, 0);
1530 VbglHGCMParmUInt64Set(&Msg.offset, 0);
1531
1532 rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
1533 if (RT_SUCCESS(rc))
1534 {
1535 Msg.context.GetUInt32(&pCtx->uContextID);
1536 Msg.creationmode.GetUInt32(puCreationMode);
1537 Msg.offset.GetUInt64(poffAt);
1538 }
1539 } while (rc == VERR_INTERRUPTED && g_fVbglR3GuestCtrlHavePeekGetCancel);
1540 return rc;
1541}
1542
1543
1544/**
1545 * Retrieves a HOST_FILE_CLOSE message.
1546 */
1547VBGLR3DECL(int) VbglR3GuestCtrlFileGetClose(PVBGLR3GUESTCTRLCMDCTX pCtx, uint32_t *puHandle)
1548{
1549 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1550
1551 AssertReturn(pCtx->uNumParms == 2, VERR_INVALID_PARAMETER);
1552 AssertPtrReturn(puHandle, VERR_INVALID_POINTER);
1553
1554 int rc;
1555 do
1556 {
1557 HGCMMsgFileClose Msg;
1558 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, vbglR3GuestCtrlGetMsgFunctionNo(pCtx->uClientID), pCtx->uNumParms);
1559 VbglHGCMParmUInt32Set(&Msg.context, HOST_MSG_FILE_CLOSE);
1560 VbglHGCMParmUInt32Set(&Msg.handle, 0);
1561
1562 rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
1563 if (RT_SUCCESS(rc))
1564 {
1565 Msg.context.GetUInt32(&pCtx->uContextID);
1566 Msg.handle.GetUInt32(puHandle);
1567 }
1568 } while (rc == VERR_INTERRUPTED && g_fVbglR3GuestCtrlHavePeekGetCancel);
1569 return rc;
1570}
1571
1572
1573/**
1574 * Retrieves a HOST_FILE_READ message.
1575 */
1576VBGLR3DECL(int) VbglR3GuestCtrlFileGetRead(PVBGLR3GUESTCTRLCMDCTX pCtx, uint32_t *puHandle, uint32_t *puToRead)
1577{
1578 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1579
1580 AssertReturn(pCtx->uNumParms == 3, VERR_INVALID_PARAMETER);
1581 AssertPtrReturn(puHandle, VERR_INVALID_POINTER);
1582 AssertPtrReturn(puToRead, VERR_INVALID_POINTER);
1583
1584 int rc;
1585 do
1586 {
1587 HGCMMsgFileRead Msg;
1588 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, vbglR3GuestCtrlGetMsgFunctionNo(pCtx->uClientID), pCtx->uNumParms);
1589 VbglHGCMParmUInt32Set(&Msg.context, HOST_MSG_FILE_READ);
1590 VbglHGCMParmUInt32Set(&Msg.handle, 0);
1591 VbglHGCMParmUInt32Set(&Msg.size, 0);
1592
1593 rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
1594 if (RT_SUCCESS(rc))
1595 {
1596 Msg.context.GetUInt32(&pCtx->uContextID);
1597 Msg.handle.GetUInt32(puHandle);
1598 Msg.size.GetUInt32(puToRead);
1599 }
1600 } while (rc == VERR_INTERRUPTED && g_fVbglR3GuestCtrlHavePeekGetCancel);
1601 return rc;
1602}
1603
1604
1605/**
1606 * Retrieves a HOST_FILE_READ_AT message.
1607 */
1608VBGLR3DECL(int) VbglR3GuestCtrlFileGetReadAt(PVBGLR3GUESTCTRLCMDCTX pCtx,
1609 uint32_t *puHandle, uint32_t *puToRead, uint64_t *poffAt)
1610{
1611 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1612
1613 AssertReturn(pCtx->uNumParms == 4, VERR_INVALID_PARAMETER);
1614 AssertPtrReturn(puHandle, VERR_INVALID_POINTER);
1615 AssertPtrReturn(puToRead, VERR_INVALID_POINTER);
1616
1617 int rc;
1618 do
1619 {
1620 HGCMMsgFileReadAt Msg;
1621 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, vbglR3GuestCtrlGetMsgFunctionNo(pCtx->uClientID), pCtx->uNumParms);
1622 VbglHGCMParmUInt32Set(&Msg.context, HOST_MSG_FILE_READ_AT);
1623 VbglHGCMParmUInt32Set(&Msg.handle, 0);
1624 VbglHGCMParmUInt64Set(&Msg.offset, 0);
1625 VbglHGCMParmUInt32Set(&Msg.size, 0);
1626
1627 rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
1628 if (RT_SUCCESS(rc))
1629 {
1630 Msg.context.GetUInt32(&pCtx->uContextID);
1631 Msg.handle.GetUInt32(puHandle);
1632 Msg.offset.GetUInt64(poffAt);
1633 Msg.size.GetUInt32(puToRead);
1634 }
1635 } while (rc == VERR_INTERRUPTED && g_fVbglR3GuestCtrlHavePeekGetCancel);
1636 return rc;
1637}
1638
1639
1640/**
1641 * Retrieves a HOST_FILE_WRITE message.
1642 */
1643VBGLR3DECL(int) VbglR3GuestCtrlFileGetWrite(PVBGLR3GUESTCTRLCMDCTX pCtx, uint32_t *puHandle,
1644 void *pvData, uint32_t cbData, uint32_t *pcbSize)
1645{
1646 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1647
1648 AssertReturn(pCtx->uNumParms == 4, VERR_INVALID_PARAMETER);
1649 AssertPtrReturn(puHandle, VERR_INVALID_POINTER);
1650 AssertPtrReturn(pvData, VERR_INVALID_POINTER);
1651 AssertReturn(cbData, VERR_INVALID_PARAMETER);
1652 AssertPtrReturn(pcbSize, VERR_INVALID_POINTER);
1653
1654 int rc;
1655 do
1656 {
1657 HGCMMsgFileWrite Msg;
1658 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, vbglR3GuestCtrlGetMsgFunctionNo(pCtx->uClientID), pCtx->uNumParms);
1659 VbglHGCMParmUInt32Set(&Msg.context, HOST_MSG_FILE_WRITE);
1660 VbglHGCMParmUInt32Set(&Msg.handle, 0);
1661 VbglHGCMParmPtrSet(&Msg.data, pvData, cbData);
1662 VbglHGCMParmUInt32Set(&Msg.size, 0);
1663
1664 rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
1665 if (RT_SUCCESS(rc))
1666 {
1667 Msg.context.GetUInt32(&pCtx->uContextID);
1668 Msg.handle.GetUInt32(puHandle);
1669 Msg.size.GetUInt32(pcbSize);
1670 }
1671 } while (rc == VERR_INTERRUPTED && g_fVbglR3GuestCtrlHavePeekGetCancel);
1672
1673 if ( rc != VERR_TOO_MUCH_DATA
1674 || g_fVbglR3GuestCtrlHavePeekGetCancel)
1675 return rc;
1676 return VERR_BUFFER_OVERFLOW;
1677}
1678
1679
1680/**
1681 * Retrieves a HOST_FILE_WRITE_AT message.
1682 */
1683VBGLR3DECL(int) VbglR3GuestCtrlFileGetWriteAt(PVBGLR3GUESTCTRLCMDCTX pCtx, uint32_t *puHandle,
1684 void *pvData, uint32_t cbData, uint32_t *pcbSize, uint64_t *poffAt)
1685{
1686 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1687
1688 AssertReturn(pCtx->uNumParms == 5, VERR_INVALID_PARAMETER);
1689 AssertPtrReturn(puHandle, VERR_INVALID_POINTER);
1690 AssertPtrReturn(pvData, VERR_INVALID_POINTER);
1691 AssertReturn(cbData, VERR_INVALID_PARAMETER);
1692 AssertPtrReturn(pcbSize, VERR_INVALID_POINTER);
1693
1694 int rc;
1695 do
1696 {
1697 HGCMMsgFileWriteAt Msg;
1698 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, vbglR3GuestCtrlGetMsgFunctionNo(pCtx->uClientID), pCtx->uNumParms);
1699 VbglHGCMParmUInt32Set(&Msg.context, HOST_MSG_FILE_WRITE_AT);
1700 VbglHGCMParmUInt32Set(&Msg.handle, 0);
1701 VbglHGCMParmPtrSet(&Msg.data, pvData, cbData);
1702 VbglHGCMParmUInt32Set(&Msg.size, 0);
1703 VbglHGCMParmUInt64Set(&Msg.offset, 0);
1704
1705 rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
1706 if (RT_SUCCESS(rc))
1707 {
1708 Msg.context.GetUInt32(&pCtx->uContextID);
1709 Msg.handle.GetUInt32(puHandle);
1710 Msg.size.GetUInt32(pcbSize);
1711 Msg.offset.GetUInt64(poffAt);
1712 }
1713 } while (rc == VERR_INTERRUPTED && g_fVbglR3GuestCtrlHavePeekGetCancel);
1714
1715 if ( rc != VERR_TOO_MUCH_DATA
1716 || g_fVbglR3GuestCtrlHavePeekGetCancel)
1717 return rc;
1718 return VERR_BUFFER_OVERFLOW;
1719}
1720
1721
1722/**
1723 * Retrieves a HOST_FILE_SEEK message.
1724 */
1725VBGLR3DECL(int) VbglR3GuestCtrlFileGetSeek(PVBGLR3GUESTCTRLCMDCTX pCtx,
1726 uint32_t *puHandle, uint32_t *puSeekMethod, uint64_t *poffAt)
1727{
1728 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1729
1730 AssertReturn(pCtx->uNumParms == 4, VERR_INVALID_PARAMETER);
1731 AssertPtrReturn(puHandle, VERR_INVALID_POINTER);
1732 AssertPtrReturn(puSeekMethod, VERR_INVALID_POINTER);
1733 AssertPtrReturn(poffAt, VERR_INVALID_POINTER);
1734
1735 int rc;
1736 do
1737 {
1738 HGCMMsgFileSeek Msg;
1739 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, vbglR3GuestCtrlGetMsgFunctionNo(pCtx->uClientID), pCtx->uNumParms);
1740 VbglHGCMParmUInt32Set(&Msg.context, HOST_MSG_FILE_SEEK);
1741 VbglHGCMParmUInt32Set(&Msg.handle, 0);
1742 VbglHGCMParmUInt32Set(&Msg.method, 0);
1743 VbglHGCMParmUInt64Set(&Msg.offset, 0);
1744
1745 rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
1746 if (RT_SUCCESS(rc))
1747 {
1748 Msg.context.GetUInt32(&pCtx->uContextID);
1749 Msg.handle.GetUInt32(puHandle);
1750 Msg.method.GetUInt32(puSeekMethod);
1751 Msg.offset.GetUInt64(poffAt);
1752 }
1753 } while (rc == VERR_INTERRUPTED && g_fVbglR3GuestCtrlHavePeekGetCancel);
1754 return rc;
1755}
1756
1757
1758/**
1759 * Retrieves a HOST_FILE_TELL message.
1760 */
1761VBGLR3DECL(int) VbglR3GuestCtrlFileGetTell(PVBGLR3GUESTCTRLCMDCTX pCtx, uint32_t *puHandle)
1762{
1763 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1764
1765 AssertReturn(pCtx->uNumParms == 2, VERR_INVALID_PARAMETER);
1766 AssertPtrReturn(puHandle, VERR_INVALID_POINTER);
1767
1768 int rc;
1769 do
1770 {
1771 HGCMMsgFileTell Msg;
1772 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, vbglR3GuestCtrlGetMsgFunctionNo(pCtx->uClientID), pCtx->uNumParms);
1773 VbglHGCMParmUInt32Set(&Msg.context, HOST_MSG_FILE_TELL);
1774 VbglHGCMParmUInt32Set(&Msg.handle, 0);
1775
1776 rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
1777 if (RT_SUCCESS(rc))
1778 {
1779 Msg.context.GetUInt32(&pCtx->uContextID);
1780 Msg.handle.GetUInt32(puHandle);
1781 }
1782 } while (rc == VERR_INTERRUPTED && g_fVbglR3GuestCtrlHavePeekGetCancel);
1783 return rc;
1784}
1785
1786
1787/**
1788 * Retrieves a HOST_FILE_SET_SIZE message.
1789 */
1790VBGLR3DECL(int) VbglR3GuestCtrlFileGetSetSize(PVBGLR3GUESTCTRLCMDCTX pCtx, uint32_t *puHandle, uint64_t *pcbNew)
1791{
1792 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1793
1794 AssertReturn(pCtx->uNumParms == 3, VERR_INVALID_PARAMETER);
1795 AssertPtrReturn(puHandle, VERR_INVALID_POINTER);
1796 AssertPtrReturn(pcbNew, VERR_INVALID_POINTER);
1797
1798 int rc;
1799 do
1800 {
1801 HGCMMsgFileSetSize Msg;
1802 VBGL_HGCM_HDR_INIT(&Msg.Hdr, pCtx->uClientID, vbglR3GuestCtrlGetMsgFunctionNo(pCtx->uClientID), pCtx->uNumParms);
1803 VbglHGCMParmUInt32Set(&Msg.id32Context, HOST_MSG_FILE_SET_SIZE);
1804 VbglHGCMParmUInt32Set(&Msg.id32Handle, 0);
1805 VbglHGCMParmUInt64Set(&Msg.cb64NewSize, 0);
1806
1807 rc = VbglR3HGCMCall(&Msg.Hdr, sizeof(Msg));
1808 if (RT_SUCCESS(rc))
1809 {
1810 Msg.id32Context.GetUInt32(&pCtx->uContextID);
1811 Msg.id32Handle.GetUInt32(puHandle);
1812 Msg.cb64NewSize.GetUInt64(pcbNew);
1813 }
1814 } while (rc == VERR_INTERRUPTED && g_fVbglR3GuestCtrlHavePeekGetCancel);
1815 return rc;
1816}
1817
1818
1819/**
1820 * Retrieves a HOST_EXEC_TERMINATE message.
1821 */
1822VBGLR3DECL(int) VbglR3GuestCtrlProcGetTerminate(PVBGLR3GUESTCTRLCMDCTX pCtx, uint32_t *puPID)
1823{
1824 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1825
1826 AssertReturn(pCtx->uNumParms == 2, VERR_INVALID_PARAMETER);
1827 AssertPtrReturn(puPID, VERR_INVALID_POINTER);
1828
1829 int rc;
1830 do
1831 {
1832 HGCMMsgProcTerminate Msg;
1833 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, vbglR3GuestCtrlGetMsgFunctionNo(pCtx->uClientID), pCtx->uNumParms);
1834 VbglHGCMParmUInt32Set(&Msg.context, HOST_MSG_EXEC_TERMINATE);
1835 VbglHGCMParmUInt32Set(&Msg.pid, 0);
1836
1837 rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
1838 if (RT_SUCCESS(rc))
1839 {
1840 Msg.context.GetUInt32(&pCtx->uContextID);
1841 Msg.pid.GetUInt32(puPID);
1842 }
1843 } while (rc == VERR_INTERRUPTED && g_fVbglR3GuestCtrlHavePeekGetCancel);
1844 return rc;
1845}
1846
1847
1848/**
1849 * Retrieves a HOST_EXEC_WAIT_FOR message.
1850 */
1851VBGLR3DECL(int) VbglR3GuestCtrlProcGetWaitFor(PVBGLR3GUESTCTRLCMDCTX pCtx,
1852 uint32_t *puPID, uint32_t *puWaitFlags, uint32_t *puTimeoutMS)
1853{
1854 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1855
1856 AssertReturn(pCtx->uNumParms == 5, VERR_INVALID_PARAMETER);
1857 AssertPtrReturn(puPID, VERR_INVALID_POINTER);
1858
1859 int rc;
1860 do
1861 {
1862 HGCMMsgProcWaitFor Msg;
1863 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, vbglR3GuestCtrlGetMsgFunctionNo(pCtx->uClientID), pCtx->uNumParms);
1864 VbglHGCMParmUInt32Set(&Msg.context, HOST_MSG_EXEC_WAIT_FOR);
1865 VbglHGCMParmUInt32Set(&Msg.pid, 0);
1866 VbglHGCMParmUInt32Set(&Msg.flags, 0);
1867 VbglHGCMParmUInt32Set(&Msg.timeout, 0);
1868
1869 rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
1870 if (RT_SUCCESS(rc))
1871 {
1872 Msg.context.GetUInt32(&pCtx->uContextID);
1873 Msg.pid.GetUInt32(puPID);
1874 Msg.flags.GetUInt32(puWaitFlags);
1875 Msg.timeout.GetUInt32(puTimeoutMS);
1876 }
1877 } while (rc == VERR_INTERRUPTED && g_fVbglR3GuestCtrlHavePeekGetCancel);
1878 return rc;
1879}
1880
1881
1882/**
1883 * Replies to a HOST_MSG_FILE_OPEN message.
1884 *
1885 * @returns VBox status code.
1886 * @param pCtx Guest control command context to use.
1887 * @param uRc Guest rc of operation (note: IPRT-style signed int).
1888 * @param uFileHandle File handle of opened file on success.
1889 */
1890VBGLR3DECL(int) VbglR3GuestCtrlFileCbOpen(PVBGLR3GUESTCTRLCMDCTX pCtx,
1891 uint32_t uRc, uint32_t uFileHandle)
1892{
1893 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1894
1895 HGCMReplyFileNotify Msg;
1896 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, GUEST_MSG_FILE_NOTIFY, 4);
1897 VbglHGCMParmUInt32Set(&Msg.context, pCtx->uContextID);
1898 VbglHGCMParmUInt32Set(&Msg.type, GUEST_FILE_NOTIFYTYPE_OPEN);
1899 VbglHGCMParmUInt32Set(&Msg.rc, uRc);
1900 VbglHGCMParmUInt32Set(&Msg.u.open.handle, uFileHandle);
1901
1902 return VbglR3HGCMCall(&Msg.hdr, RT_UOFFSET_AFTER(HGCMReplyFileNotify, u.open));
1903}
1904
1905
1906/**
1907 * Replies to a HOST_MSG_FILE_CLOSE message.
1908 *
1909 * @returns VBox status code.
1910 * @param pCtx Guest control command context to use.
1911 * @param uRc Guest rc of operation (note: IPRT-style signed int).
1912 */
1913VBGLR3DECL(int) VbglR3GuestCtrlFileCbClose(PVBGLR3GUESTCTRLCMDCTX pCtx,
1914 uint32_t uRc)
1915{
1916 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1917
1918 HGCMReplyFileNotify Msg;
1919 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, GUEST_MSG_FILE_NOTIFY, 3);
1920 VbglHGCMParmUInt32Set(&Msg.context, pCtx->uContextID);
1921 VbglHGCMParmUInt32Set(&Msg.type, GUEST_FILE_NOTIFYTYPE_CLOSE);
1922 VbglHGCMParmUInt32Set(&Msg.rc, uRc);
1923
1924 return VbglR3HGCMCall(&Msg.hdr, RT_UOFFSETOF(HGCMReplyFileNotify, u));
1925}
1926
1927
1928/**
1929 * Sends an unexpected file handling error to the host.
1930 *
1931 * @returns VBox status code.
1932 * @param pCtx Guest control command context to use.
1933 * @param uRc Guest rc of operation (note: IPRT-style signed int).
1934 */
1935VBGLR3DECL(int) VbglR3GuestCtrlFileCbError(PVBGLR3GUESTCTRLCMDCTX pCtx, uint32_t uRc)
1936{
1937 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1938
1939 HGCMReplyFileNotify Msg;
1940 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, GUEST_MSG_FILE_NOTIFY, 3);
1941 VbglHGCMParmUInt32Set(&Msg.context, pCtx->uContextID);
1942 VbglHGCMParmUInt32Set(&Msg.type, GUEST_FILE_NOTIFYTYPE_ERROR);
1943 VbglHGCMParmUInt32Set(&Msg.rc, uRc);
1944
1945 return VbglR3HGCMCall(&Msg.hdr, RT_UOFFSETOF(HGCMReplyFileNotify, u));
1946}
1947
1948
1949/**
1950 * Replies to a HOST_MSG_FILE_READ message.
1951 *
1952 * @returns VBox status code.
1953 * @param pCtx Guest control command context to use.
1954 * @param uRc Guest rc of operation (note: IPRT-style signed int).
1955 * @param pvData Pointer to read file data from guest on success.
1956 * @param cbData Size (in bytes) of read file data from guest on success.
1957 */
1958VBGLR3DECL(int) VbglR3GuestCtrlFileCbRead(PVBGLR3GUESTCTRLCMDCTX pCtx,
1959 uint32_t uRc,
1960 void *pvData, uint32_t cbData)
1961{
1962 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1963
1964 HGCMReplyFileNotify Msg;
1965 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, GUEST_MSG_FILE_NOTIFY, 4);
1966 VbglHGCMParmUInt32Set(&Msg.context, pCtx->uContextID);
1967 VbglHGCMParmUInt32Set(&Msg.type, GUEST_FILE_NOTIFYTYPE_READ);
1968 VbglHGCMParmUInt32Set(&Msg.rc, uRc);
1969 VbglHGCMParmPtrSet(&Msg.u.read.data, pvData, cbData);
1970
1971 return VbglR3HGCMCall(&Msg.hdr, RT_UOFFSET_AFTER(HGCMReplyFileNotify, u.read));
1972}
1973
1974
1975/**
1976 * Replies to a HOST_MSG_FILE_READ_AT message.
1977 *
1978 * @returns VBox status code.
1979 * @param pCtx Guest control command context to use.
1980 * @param uRc Guest rc of operation (note: IPRT-style signed int).
1981 * @param pvData Pointer to read file data from guest on success.
1982 * @param cbData Size (in bytes) of read file data from guest on success.
1983 * @param offNew New offset (in bytes) the guest file pointer points at on success.
1984 */
1985VBGLR3DECL(int) VbglR3GuestCtrlFileCbReadOffset(PVBGLR3GUESTCTRLCMDCTX pCtx, uint32_t uRc,
1986 void *pvData, uint32_t cbData, int64_t offNew)
1987{
1988 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1989
1990 HGCMReplyFileNotify Msg;
1991 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, GUEST_MSG_FILE_NOTIFY, 5);
1992 VbglHGCMParmUInt32Set(&Msg.context, pCtx->uContextID);
1993 VbglHGCMParmUInt32Set(&Msg.type, GUEST_FILE_NOTIFYTYPE_READ_OFFSET);
1994 VbglHGCMParmUInt32Set(&Msg.rc, uRc);
1995 VbglHGCMParmPtrSet(&Msg.u.ReadOffset.pvData, pvData, cbData);
1996 VbglHGCMParmUInt64Set(&Msg.u.ReadOffset.off64New, (uint64_t)offNew);
1997
1998 return VbglR3HGCMCall(&Msg.hdr, RT_UOFFSET_AFTER(HGCMReplyFileNotify, u.ReadOffset));
1999}
2000
2001
2002/**
2003 * Replies to a HOST_MSG_FILE_WRITE message.
2004 *
2005 * @returns VBox status code.
2006 * @param pCtx Guest control command context to use.
2007 * @param uRc Guest rc of operation (note: IPRT-style signed int).
2008 * @param cbWritten Size (in bytes) of file data successfully written to guest file. Can be partial.
2009 */
2010VBGLR3DECL(int) VbglR3GuestCtrlFileCbWrite(PVBGLR3GUESTCTRLCMDCTX pCtx, uint32_t uRc, uint32_t cbWritten)
2011{
2012 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
2013
2014 HGCMReplyFileNotify Msg;
2015 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, GUEST_MSG_FILE_NOTIFY, 4);
2016 VbglHGCMParmUInt32Set(&Msg.context, pCtx->uContextID);
2017 VbglHGCMParmUInt32Set(&Msg.type, GUEST_FILE_NOTIFYTYPE_WRITE);
2018 VbglHGCMParmUInt32Set(&Msg.rc, uRc);
2019 VbglHGCMParmUInt32Set(&Msg.u.write.written, cbWritten);
2020
2021 return VbglR3HGCMCall(&Msg.hdr, RT_UOFFSET_AFTER(HGCMReplyFileNotify, u.write));
2022}
2023
2024
2025/**
2026 * Replies to a HOST_MSG_FILE_WRITE_AT message.
2027 *
2028 * @returns VBox status code.
2029 * @param pCtx Guest control command context to use.
2030 * @param uRc Guest rc of operation (note: IPRT-style signed int).
2031 * @param cbWritten Size (in bytes) of file data successfully written to guest file. Can be partial.
2032 * @param offNew New offset (in bytes) the guest file pointer points at on success.
2033 */
2034VBGLR3DECL(int) VbglR3GuestCtrlFileCbWriteOffset(PVBGLR3GUESTCTRLCMDCTX pCtx, uint32_t uRc, uint32_t cbWritten, int64_t offNew)
2035{
2036 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
2037
2038 HGCMReplyFileNotify Msg;
2039 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, GUEST_MSG_FILE_NOTIFY, 5);
2040 VbglHGCMParmUInt32Set(&Msg.context, pCtx->uContextID);
2041 VbglHGCMParmUInt32Set(&Msg.type, GUEST_FILE_NOTIFYTYPE_WRITE_OFFSET);
2042 VbglHGCMParmUInt32Set(&Msg.rc, uRc);
2043 VbglHGCMParmUInt32Set(&Msg.u.WriteOffset.cb32Written, cbWritten);
2044 VbglHGCMParmUInt64Set(&Msg.u.WriteOffset.off64New, (uint64_t)offNew);
2045
2046 return VbglR3HGCMCall(&Msg.hdr, RT_UOFFSET_AFTER(HGCMReplyFileNotify, u.WriteOffset));
2047}
2048
2049
2050/**
2051 * Replies to a HOST_MSG_FILE_SEEK message.
2052 *
2053 * @returns VBox status code.
2054 * @param pCtx Guest control command context to use.
2055 * @param uRc Guest rc of operation (note: IPRT-style signed int).
2056 * @param offCurrent New offset (in bytes) the guest file pointer points at on success.
2057 */
2058VBGLR3DECL(int) VbglR3GuestCtrlFileCbSeek(PVBGLR3GUESTCTRLCMDCTX pCtx, uint32_t uRc, uint64_t offCurrent)
2059{
2060 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
2061
2062 HGCMReplyFileNotify Msg;
2063 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, GUEST_MSG_FILE_NOTIFY, 4);
2064 VbglHGCMParmUInt32Set(&Msg.context, pCtx->uContextID);
2065 VbglHGCMParmUInt32Set(&Msg.type, GUEST_FILE_NOTIFYTYPE_SEEK);
2066 VbglHGCMParmUInt32Set(&Msg.rc, uRc);
2067 VbglHGCMParmUInt64Set(&Msg.u.seek.offset, offCurrent);
2068
2069 return VbglR3HGCMCall(&Msg.hdr, RT_UOFFSET_AFTER(HGCMReplyFileNotify, u.seek));
2070}
2071
2072
2073/**
2074 * Replies to a HOST_MSG_FILE_TELL message.
2075 *
2076 * @returns VBox status code.
2077 * @param pCtx Guest control command context to use.
2078 * @param uRc Guest rc of operation (note: IPRT-style signed int).
2079 * @param offCurrent Current offset (in bytes) the guest file pointer points at on success.
2080 */
2081VBGLR3DECL(int) VbglR3GuestCtrlFileCbTell(PVBGLR3GUESTCTRLCMDCTX pCtx, uint32_t uRc, uint64_t offCurrent)
2082{
2083 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
2084
2085 HGCMReplyFileNotify Msg;
2086 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, GUEST_MSG_FILE_NOTIFY, 4);
2087 VbglHGCMParmUInt32Set(&Msg.context, pCtx->uContextID);
2088 VbglHGCMParmUInt32Set(&Msg.type, GUEST_FILE_NOTIFYTYPE_TELL);
2089 VbglHGCMParmUInt32Set(&Msg.rc, uRc);
2090 VbglHGCMParmUInt64Set(&Msg.u.tell.offset, offCurrent);
2091
2092 return VbglR3HGCMCall(&Msg.hdr, RT_UOFFSET_AFTER(HGCMReplyFileNotify, u.tell));
2093}
2094
2095
2096/**
2097 * Replies to a HOST_MSG_FILE_SET_SIZE message.
2098 *
2099 * @returns VBox status code.
2100 * @param pCtx Guest control command context to use.
2101 * @param uRc Guest rc of operation (note: IPRT-style signed int).
2102 * @param cbNew New file size (in bytes) of the guest file on success.
2103 */
2104VBGLR3DECL(int) VbglR3GuestCtrlFileCbSetSize(PVBGLR3GUESTCTRLCMDCTX pCtx, uint32_t uRc, uint64_t cbNew)
2105{
2106 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
2107
2108 HGCMReplyFileNotify Msg;
2109 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, GUEST_MSG_FILE_NOTIFY, 4);
2110 VbglHGCMParmUInt32Set(&Msg.context, pCtx->uContextID);
2111 VbglHGCMParmUInt32Set(&Msg.type, GUEST_FILE_NOTIFYTYPE_SET_SIZE);
2112 VbglHGCMParmUInt32Set(&Msg.rc, uRc);
2113 VbglHGCMParmUInt64Set(&Msg.u.SetSize.cb64Size, cbNew);
2114
2115 return VbglR3HGCMCall(&Msg.hdr, RT_UOFFSET_AFTER(HGCMReplyFileNotify, u.SetSize));
2116}
2117
2118
2119/**
2120 * Callback for reporting a guest process status (along with some other stuff) to the host.
2121 *
2122 * @returns VBox status code.
2123 * @param pCtx Guest control command context to use.
2124 * @param uPID Guest process PID to report status for.
2125 * @param uStatus Status to report. Of type PROC_STS_XXX.
2126 * @param fFlags Additional status flags, depending on the reported status. See RTPROCSTATUS.
2127 * @param pvData Pointer to additional status data. Optional.
2128 * @param cbData Size (in bytes) of additional status data.
2129 */
2130VBGLR3DECL(int) VbglR3GuestCtrlProcCbStatus(PVBGLR3GUESTCTRLCMDCTX pCtx,
2131 uint32_t uPID, uint32_t uStatus, uint32_t fFlags,
2132 void *pvData, uint32_t cbData)
2133{
2134 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
2135
2136 HGCMMsgProcStatus Msg;
2137 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, GUEST_MSG_EXEC_STATUS, 5);
2138 VbglHGCMParmUInt32Set(&Msg.context, pCtx->uContextID);
2139 VbglHGCMParmUInt32Set(&Msg.pid, uPID);
2140 VbglHGCMParmUInt32Set(&Msg.status, uStatus);
2141 VbglHGCMParmUInt32Set(&Msg.flags, fFlags);
2142 VbglHGCMParmPtrSet(&Msg.data, pvData, cbData);
2143
2144 return VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
2145}
2146
2147
2148/**
2149 * Sends output (from stdout/stderr) from a running process.
2150 *
2151 * @returns VBox status code.
2152 * @param pCtx Guest control command context to use.
2153 * @param uPID Guest process PID to report status for.
2154 * @param uHandle Guest process handle the output belong to.
2155 * @param fFlags Additional output flags.
2156 * @param pvData Pointer to actual output data.
2157 * @param cbData Size (in bytes) of output data.
2158 */
2159VBGLR3DECL(int) VbglR3GuestCtrlProcCbOutput(PVBGLR3GUESTCTRLCMDCTX pCtx,
2160 uint32_t uPID,uint32_t uHandle, uint32_t fFlags,
2161 void *pvData, uint32_t cbData)
2162{
2163 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
2164
2165 HGCMMsgProcOutput Msg;
2166 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, GUEST_MSG_EXEC_OUTPUT, 5);
2167 VbglHGCMParmUInt32Set(&Msg.context, pCtx->uContextID);
2168 VbglHGCMParmUInt32Set(&Msg.pid, uPID);
2169 VbglHGCMParmUInt32Set(&Msg.handle, uHandle);
2170 VbglHGCMParmUInt32Set(&Msg.flags, fFlags);
2171 VbglHGCMParmPtrSet(&Msg.data, pvData, cbData);
2172
2173 return VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
2174}
2175
2176
2177/**
2178 * Callback for reporting back the input status of a guest process to the host.
2179 *
2180 * @returns VBox status code.
2181 * @param pCtx Guest control command context to use.
2182 * @param uPID Guest process PID to report status for.
2183 * @param uStatus Status to report. Of type INPUT_STS_XXX.
2184 * @param fFlags Additional input flags.
2185 * @param cbWritten Size (in bytes) of input data handled.
2186 */
2187VBGLR3DECL(int) VbglR3GuestCtrlProcCbStatusInput(PVBGLR3GUESTCTRLCMDCTX pCtx,
2188 uint32_t uPID, uint32_t uStatus,
2189 uint32_t fFlags, uint32_t cbWritten)
2190{
2191 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
2192
2193 HGCMMsgProcStatusInput Msg;
2194 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, GUEST_MSG_EXEC_INPUT_STATUS, 5);
2195 VbglHGCMParmUInt32Set(&Msg.context, pCtx->uContextID);
2196 VbglHGCMParmUInt32Set(&Msg.pid, uPID);
2197 VbglHGCMParmUInt32Set(&Msg.status, uStatus);
2198 VbglHGCMParmUInt32Set(&Msg.flags, fFlags);
2199 VbglHGCMParmUInt32Set(&Msg.written, cbWritten);
2200
2201 return VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
2202}
2203
Note: See TracBrowser for help on using the repository browser.

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