VirtualBox

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

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

Guest Control: Implemented guest side support for gracefully rebooting / shutting down the guest. Untested. bugref:9320

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 71.5 KB
Line 
1/* $Id: VBoxGuestR3LibGuestCtrl.cpp 84548 2020-05-26 17:43:31Z 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.virtualbox.org. 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
510VBGLR3DECL(int) VbglR3GuestCtrlMsgReply(PVBGLR3GUESTCTRLCMDCTX pCtx,
511 int rc)
512{
513 return VbglR3GuestCtrlMsgReplyEx(pCtx, rc, 0 /* uType */,
514 NULL /* pvPayload */, 0 /* cbPayload */);
515}
516
517
518VBGLR3DECL(int) VbglR3GuestCtrlMsgReplyEx(PVBGLR3GUESTCTRLCMDCTX pCtx,
519 int rc, uint32_t uType,
520 void *pvPayload, uint32_t cbPayload)
521{
522 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
523 /* Everything else is optional. */
524
525 HGCMMsgReply Msg;
526 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, GUEST_MSG_REPLY, 4);
527 VbglHGCMParmUInt32Set(&Msg.context, pCtx->uContextID);
528 VbglHGCMParmUInt32Set(&Msg.type, uType);
529 VbglHGCMParmUInt32Set(&Msg.rc, (uint32_t)rc); /* int vs. uint32_t */
530 VbglHGCMParmPtrSet(&Msg.payload, pvPayload, cbPayload);
531
532 return VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
533}
534
535/**
536 * Tell the host to skip the current message replying VERR_NOT_SUPPORTED
537 *
538 * @return IPRT status code.
539 * @param idClient The client ID returned by VbglR3GuestCtrlConnect().
540 * @param rcSkip The status code to pass back to Main when skipping.
541 * @param idMsg The message ID to skip, pass UINT32_MAX to pass any.
542 */
543VBGLR3DECL(int) VbglR3GuestCtrlMsgSkip(uint32_t idClient, int rcSkip, uint32_t idMsg)
544{
545 if (vbglR3GuestCtrlSupportsPeekGetCancel(idClient))
546 {
547 struct
548 {
549 VBGLIOCHGCMCALL Hdr;
550 HGCMFunctionParameter rcSkip;
551 HGCMFunctionParameter idMsg;
552 } Msg;
553 VBGL_HGCM_HDR_INIT(&Msg.Hdr, idClient, GUEST_MSG_SKIP, 2);
554 VbglHGCMParmUInt32Set(&Msg.rcSkip, (uint32_t)rcSkip);
555 VbglHGCMParmUInt32Set(&Msg.idMsg, idMsg);
556 return VbglR3HGCMCall(&Msg.Hdr, sizeof(Msg));
557 }
558
559 /* This is generally better than nothing... */
560 return VbglR3GuestCtrlMsgSkipOld(idClient);
561}
562
563
564/**
565 * Tells the host service to skip the current message returned by
566 * VbglR3GuestCtrlMsgWaitFor().
567 *
568 * @return IPRT status code.
569 * @param idClient The client ID returned by VbglR3GuestCtrlConnect().
570 */
571VBGLR3DECL(int) VbglR3GuestCtrlMsgSkipOld(uint32_t idClient)
572{
573 HGCMMsgSkip Msg;
574
575 /* Tell the host we want to skip the current assigned message. */
576 VBGL_HGCM_HDR_INIT(&Msg.hdr, idClient, GUEST_MSG_SKIP_OLD, 1);
577 VbglHGCMParmUInt32Set(&Msg.flags, 0 /* Flags, unused */);
578 return VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
579}
580
581
582/**
583 * Asks the host to cancel (release) all pending waits which were deferred.
584 *
585 * @returns VBox status code.
586 * @param idClient The client ID returned by VbglR3GuestCtrlConnect().
587 */
588VBGLR3DECL(int) VbglR3GuestCtrlCancelPendingWaits(uint32_t idClient)
589{
590 HGCMMsgCancelPendingWaits Msg;
591 VBGL_HGCM_HDR_INIT(&Msg.hdr, idClient, GUEST_MSG_CANCEL, 0);
592 return VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
593}
594
595
596/**
597 * Prepares a session.
598 * @since 6.0
599 * @sa GUEST_SESSION_PREPARE
600 */
601VBGLR3DECL(int) VbglR3GuestCtrlSessionPrepare(uint32_t idClient, uint32_t idSession, void const *pvKey, uint32_t cbKey)
602{
603 int rc;
604 do
605 {
606 struct
607 {
608 VBGLIOCHGCMCALL Hdr;
609 HGCMFunctionParameter idSession;
610 HGCMFunctionParameter pKey;
611 } Msg;
612 VBGL_HGCM_HDR_INIT(&Msg.Hdr, idClient, GUEST_MSG_SESSION_PREPARE, 2);
613 VbglHGCMParmUInt32Set(&Msg.idSession, idSession);
614 VbglHGCMParmPtrSet(&Msg.pKey, (void *)pvKey, cbKey);
615 rc = VbglR3HGCMCall(&Msg.Hdr, sizeof(Msg));
616 } while (rc == VERR_INTERRUPTED);
617 return rc;
618}
619
620
621/**
622 * Accepts a session.
623 * @since 6.0
624 * @sa GUEST_SESSION_ACCEPT
625 */
626VBGLR3DECL(int) VbglR3GuestCtrlSessionAccept(uint32_t idClient, uint32_t idSession, void const *pvKey, uint32_t cbKey)
627{
628 int rc;
629 do
630 {
631 struct
632 {
633 VBGLIOCHGCMCALL Hdr;
634 HGCMFunctionParameter idSession;
635 HGCMFunctionParameter pKey;
636 } Msg;
637 VBGL_HGCM_HDR_INIT(&Msg.Hdr, idClient, GUEST_MSG_SESSION_ACCEPT, 2);
638 VbglHGCMParmUInt32Set(&Msg.idSession, idSession);
639 VbglHGCMParmPtrSet(&Msg.pKey, (void *)pvKey, cbKey);
640 rc = VbglR3HGCMCall(&Msg.Hdr, sizeof(Msg));
641 } while (rc == VERR_INTERRUPTED);
642 return rc;
643}
644
645
646/**
647 * Cancels a prepared session.
648 * @since 6.0
649 * @sa GUEST_SESSION_CANCEL_PREPARED
650 */
651VBGLR3DECL(int) VbglR3GuestCtrlSessionCancelPrepared(uint32_t idClient, uint32_t idSession)
652{
653 int rc;
654 do
655 {
656 struct
657 {
658 VBGLIOCHGCMCALL Hdr;
659 HGCMFunctionParameter idSession;
660 } Msg;
661 VBGL_HGCM_HDR_INIT(&Msg.Hdr, idClient, GUEST_MSG_SESSION_CANCEL_PREPARED, 1);
662 VbglHGCMParmUInt32Set(&Msg.idSession, idSession);
663 rc = VbglR3HGCMCall(&Msg.Hdr, sizeof(Msg));
664 } while (rc == VERR_INTERRUPTED);
665 return rc;
666}
667
668
669/**
670 * Invalidates the internal state because the (VM) session has been changed (i.e. restored).
671 *
672 * @returns VBox status code.
673 * @param idClient Client ID to use for invalidating state.
674 * @param idNewControlSession New control session ID. Currently unused.
675 */
676VBGLR3DECL(int) VbglR3GuestCtrlSessionHasChanged(uint32_t idClient, uint64_t idNewControlSession)
677{
678 RT_NOREF(idNewControlSession);
679
680 vbglR3GuestCtrlDetectPeekGetCancelSupport(idClient);
681
682 return VINF_SUCCESS;
683}
684
685
686/**
687 * Asks a specific guest session to close.
688 *
689 * @return IPRT status code.
690 * @param pCtx Host context.
691 * @param fFlags Some kind of flag. Figure it out yourself.
692 ** @todo Docs!
693 */
694VBGLR3DECL(int) VbglR3GuestCtrlSessionClose(PVBGLR3GUESTCTRLCMDCTX pCtx, uint32_t fFlags)
695{
696 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
697 AssertReturn(pCtx->uNumParms == 2, VERR_INVALID_PARAMETER);
698
699 HGCMMsgSessionClose Msg;
700 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, GUEST_MSG_SESSION_CLOSE, pCtx->uNumParms);
701 VbglHGCMParmUInt32Set(&Msg.context, pCtx->uContextID);
702 VbglHGCMParmUInt32Set(&Msg.flags, fFlags);
703
704 return VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
705}
706
707
708VBGLR3DECL(int) VbglR3GuestCtrlSessionNotify(PVBGLR3GUESTCTRLCMDCTX pCtx, uint32_t uType, int32_t iResult)
709{
710 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
711
712 HGCMMsgSessionNotify Msg;
713 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, GUEST_MSG_SESSION_NOTIFY, 3);
714 VbglHGCMParmUInt32Set(&Msg.context, pCtx->uContextID);
715 VbglHGCMParmUInt32Set(&Msg.type, uType);
716 VbglHGCMParmUInt32Set(&Msg.result, (uint32_t)iResult);
717
718 return VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
719}
720
721/**
722 * Initializes a session startup info, extended version.
723 *
724 * @returns VBox status code.
725 * @param pStartupInfo Session startup info to initializes.
726 * @param cbUser Size (in bytes) to use for the user name buffer.
727 * @param cbPassword Size (in bytes) to use for the password buffer.
728 * @param cbDomain Size (in bytes) to use for the domain name buffer.
729 */
730VBGLR3DECL(int) VbglR3GuestCtrlSessionStartupInfoInitEx(PVBGLR3GUESTCTRLSESSIONSTARTUPINFO pStartupInfo,
731 size_t cbUser, size_t cbPassword, size_t cbDomain)
732{
733 AssertPtrReturn(pStartupInfo, VERR_INVALID_POINTER);
734
735 RT_BZERO(pStartupInfo, sizeof(VBGLR3GUESTCTRLSESSIONSTARTUPINFO));
736
737#define ALLOC_STR(a_Str, a_cb) \
738 if ((a_cb) > 0) \
739 { \
740 pStartupInfo->psz##a_Str = RTStrAlloc(a_cb); \
741 AssertPtrBreak(pStartupInfo->psz##a_Str); \
742 pStartupInfo->cb##a_Str = (uint32_t)a_cb; \
743 }
744
745 do
746 {
747 ALLOC_STR(User, cbUser);
748 ALLOC_STR(Password, cbPassword);
749 ALLOC_STR(Domain, cbDomain);
750
751 return VINF_SUCCESS;
752
753 } while (0);
754
755#undef ALLOC_STR
756
757 VbglR3GuestCtrlSessionStartupInfoDestroy(pStartupInfo);
758 return VERR_NO_MEMORY;
759}
760
761/**
762 * Initializes a session startup info.
763 *
764 * @returns VBox status code.
765 * @param pStartupInfo Session startup info to initializes.
766 */
767VBGLR3DECL(int) VbglR3GuestCtrlSessionStartupInfoInit(PVBGLR3GUESTCTRLSESSIONSTARTUPINFO pStartupInfo)
768{
769 return VbglR3GuestCtrlSessionStartupInfoInitEx(pStartupInfo,
770 GUESTPROCESS_MAX_USER_LEN, GUESTPROCESS_MAX_PASSWORD_LEN,
771 GUESTPROCESS_MAX_DOMAIN_LEN);
772}
773
774/**
775 * Destroys a session startup info.
776 *
777 * @param pStartupInfo Session startup info to destroy.
778 */
779VBGLR3DECL(void) VbglR3GuestCtrlSessionStartupInfoDestroy(PVBGLR3GUESTCTRLSESSIONSTARTUPINFO pStartupInfo)
780{
781 if (!pStartupInfo)
782 return;
783
784 RTStrFree(pStartupInfo->pszUser);
785 RTStrFree(pStartupInfo->pszPassword);
786 RTStrFree(pStartupInfo->pszDomain);
787
788 RT_BZERO(pStartupInfo, sizeof(VBGLR3GUESTCTRLSESSIONSTARTUPINFO));
789}
790
791/**
792 * Free's a session startup info.
793 *
794 * @param pStartupInfo Session startup info to free.
795 * The pointer will not be valid anymore after return.
796 */
797VBGLR3DECL(void) VbglR3GuestCtrlSessionStartupInfoFree(PVBGLR3GUESTCTRLSESSIONSTARTUPINFO pStartupInfo)
798{
799 if (!pStartupInfo)
800 return;
801
802 VbglR3GuestCtrlSessionStartupInfoDestroy(pStartupInfo);
803
804 RTMemFree(pStartupInfo);
805 pStartupInfo = NULL;
806}
807
808/**
809 * Duplicates a session startup info.
810 *
811 * @returns Duplicated session startup info on success, or NULL on error.
812 * @param pStartupInfo Session startup info to duplicate.
813 */
814VBGLR3DECL(PVBGLR3GUESTCTRLSESSIONSTARTUPINFO) VbglR3GuestCtrlSessionStartupInfoDup(PVBGLR3GUESTCTRLSESSIONSTARTUPINFO pStartupInfo)
815{
816 AssertPtrReturn(pStartupInfo, NULL);
817
818 PVBGLR3GUESTCTRLSESSIONSTARTUPINFO pStartupInfoDup = (PVBGLR3GUESTCTRLSESSIONSTARTUPINFO)
819 RTMemDup(pStartupInfo, sizeof(VBGLR3GUESTCTRLSESSIONSTARTUPINFO));
820 if (pStartupInfoDup)
821 {
822 do
823 {
824 pStartupInfoDup->pszUser = NULL;
825 pStartupInfoDup->pszPassword = NULL;
826 pStartupInfoDup->pszDomain = NULL;
827
828#define DUP_STR(a_Str) \
829 if (pStartupInfo->cb##a_Str) \
830 { \
831 pStartupInfoDup->psz##a_Str = (char *)RTStrDup(pStartupInfo->psz##a_Str); \
832 AssertPtrBreak(pStartupInfoDup->psz##a_Str); \
833 pStartupInfoDup->cb##a_Str = (uint32_t)strlen(pStartupInfoDup->psz##a_Str) + 1 /* Include terminator */; \
834 }
835 DUP_STR(User);
836 DUP_STR(Password);
837 DUP_STR(Domain);
838
839#undef DUP_STR
840
841 return pStartupInfoDup;
842
843 } while (0); /* To use break macros above. */
844
845 VbglR3GuestCtrlSessionStartupInfoFree(pStartupInfoDup);
846 }
847
848 return NULL;
849}
850
851/**
852 * Retrieves a HOST_SESSION_CREATE message.
853 *
854 * @returns VBox status code.
855 * @param pCtx Guest control command context to use.
856 * @param ppStartupInfo Where to store the allocated session startup info.
857 * Needs to be free'd by VbglR3GuestCtrlSessionStartupInfoFree().
858 */
859VBGLR3DECL(int) VbglR3GuestCtrlSessionGetOpen(PVBGLR3GUESTCTRLCMDCTX pCtx, PVBGLR3GUESTCTRLSESSIONSTARTUPINFO *ppStartupInfo)
860{
861 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
862 AssertReturn(pCtx->uNumParms == 6, VERR_INVALID_PARAMETER);
863 AssertPtrReturn(ppStartupInfo, VERR_INVALID_POINTER);
864
865 PVBGLR3GUESTCTRLSESSIONSTARTUPINFO pStartupInfo
866 = (PVBGLR3GUESTCTRLSESSIONSTARTUPINFO)RTMemAlloc(sizeof(VBGLR3GUESTCTRLSESSIONSTARTUPINFO));
867 if (!pStartupInfo)
868 return VERR_NO_MEMORY;
869
870 int rc = VbglR3GuestCtrlSessionStartupInfoInit(pStartupInfo);
871 if (RT_FAILURE(rc))
872 {
873 VbglR3GuestCtrlSessionStartupInfoFree(pStartupInfo);
874 return rc;
875 }
876
877 do
878 {
879 HGCMMsgSessionOpen Msg;
880 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, vbglR3GuestCtrlGetMsgFunctionNo(pCtx->uClientID), pCtx->uNumParms);
881 VbglHGCMParmUInt32Set(&Msg.context, HOST_MSG_SESSION_CREATE);
882 VbglHGCMParmUInt32Set(&Msg.protocol, 0);
883 VbglHGCMParmPtrSet(&Msg.username, pStartupInfo->pszUser, pStartupInfo->cbUser);
884 VbglHGCMParmPtrSet(&Msg.password, pStartupInfo->pszPassword, pStartupInfo->cbPassword);
885 VbglHGCMParmPtrSet(&Msg.domain, pStartupInfo->pszDomain, pStartupInfo->cbDomain);
886 VbglHGCMParmUInt32Set(&Msg.flags, 0);
887
888 rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
889 if (RT_SUCCESS(rc))
890 {
891 Msg.context.GetUInt32(&pCtx->uContextID);
892 Msg.protocol.GetUInt32(&pStartupInfo->uProtocol);
893 Msg.flags.GetUInt32(&pStartupInfo->fFlags);
894
895 pStartupInfo->uSessionID = VBOX_GUESTCTRL_CONTEXTID_GET_SESSION(pCtx->uContextID);
896 }
897
898 } while (rc == VERR_INTERRUPTED && g_fVbglR3GuestCtrlHavePeekGetCancel);
899
900 if (RT_SUCCESS(rc))
901 {
902 *ppStartupInfo = pStartupInfo;
903 }
904 else
905 VbglR3GuestCtrlSessionStartupInfoFree(pStartupInfo);
906
907 LogFlowFuncLeaveRC(rc);
908 return rc;
909}
910
911
912/**
913 * Retrieves a HOST_SESSION_CLOSE message.
914 */
915VBGLR3DECL(int) VbglR3GuestCtrlSessionGetClose(PVBGLR3GUESTCTRLCMDCTX pCtx, uint32_t *pfFlags, uint32_t *pidSession)
916{
917 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
918 AssertReturn(pCtx->uNumParms == 2, VERR_INVALID_PARAMETER);
919
920 AssertPtrReturn(pfFlags, VERR_INVALID_POINTER);
921
922 int rc;
923 do
924 {
925 HGCMMsgSessionClose Msg;
926 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, vbglR3GuestCtrlGetMsgFunctionNo(pCtx->uClientID), pCtx->uNumParms);
927 VbglHGCMParmUInt32Set(&Msg.context, HOST_MSG_SESSION_CLOSE);
928 VbglHGCMParmUInt32Set(&Msg.flags, 0);
929
930 rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
931 if (RT_SUCCESS(rc))
932 {
933 Msg.context.GetUInt32(&pCtx->uContextID);
934 Msg.flags.GetUInt32(pfFlags);
935
936 if (pidSession)
937 *pidSession = VBOX_GUESTCTRL_CONTEXTID_GET_SESSION(pCtx->uContextID);
938 }
939 } while (rc == VERR_INTERRUPTED && g_fVbglR3GuestCtrlHavePeekGetCancel);
940 return rc;
941}
942
943
944/**
945 * Retrieves a HOST_PATH_RENAME message.
946 */
947VBGLR3DECL(int) VbglR3GuestCtrlPathGetRename(PVBGLR3GUESTCTRLCMDCTX pCtx,
948 char *pszSource, uint32_t cbSource,
949 char *pszDest, uint32_t cbDest,
950 uint32_t *pfFlags)
951{
952 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
953 AssertReturn(pCtx->uNumParms == 4, VERR_INVALID_PARAMETER);
954
955 AssertPtrReturn(pszSource, VERR_INVALID_POINTER);
956 AssertReturn(cbSource, VERR_INVALID_PARAMETER);
957 AssertPtrReturn(pszDest, VERR_INVALID_POINTER);
958 AssertReturn(cbDest, VERR_INVALID_PARAMETER);
959 AssertPtrReturn(pfFlags, VERR_INVALID_POINTER);
960
961 int rc;
962 do
963 {
964 HGCMMsgPathRename Msg;
965 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, vbglR3GuestCtrlGetMsgFunctionNo(pCtx->uClientID), pCtx->uNumParms);
966 VbglHGCMParmUInt32Set(&Msg.context, HOST_MSG_PATH_RENAME);
967 VbglHGCMParmPtrSet(&Msg.source, pszSource, cbSource);
968 VbglHGCMParmPtrSet(&Msg.dest, pszDest, cbDest);
969 VbglHGCMParmUInt32Set(&Msg.flags, 0);
970
971 rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
972 if (RT_SUCCESS(rc))
973 {
974 Msg.context.GetUInt32(&pCtx->uContextID);
975 Msg.flags.GetUInt32(pfFlags);
976 }
977
978 } while (rc == VERR_INTERRUPTED && g_fVbglR3GuestCtrlHavePeekGetCancel);
979 return rc;
980}
981
982
983/**
984 * Retrieves a HOST_PATH_USER_DOCUMENTS message.
985 */
986VBGLR3DECL(int) VbglR3GuestCtrlPathGetUserDocuments(PVBGLR3GUESTCTRLCMDCTX pCtx)
987{
988 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
989 AssertReturn(pCtx->uNumParms == 1, VERR_INVALID_PARAMETER);
990
991 int rc;
992 do
993 {
994 HGCMMsgPathUserDocuments Msg;
995 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, vbglR3GuestCtrlGetMsgFunctionNo(pCtx->uClientID), pCtx->uNumParms);
996 VbglHGCMParmUInt32Set(&Msg.context, HOST_MSG_PATH_USER_DOCUMENTS);
997
998 rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
999 if (RT_SUCCESS(rc))
1000 Msg.context.GetUInt32(&pCtx->uContextID);
1001 } while (rc == VERR_INTERRUPTED && g_fVbglR3GuestCtrlHavePeekGetCancel);
1002 return rc;
1003}
1004
1005
1006/**
1007 * Retrieves a HOST_PATH_USER_HOME message.
1008 */
1009VBGLR3DECL(int) VbglR3GuestCtrlPathGetUserHome(PVBGLR3GUESTCTRLCMDCTX pCtx)
1010{
1011 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1012 AssertReturn(pCtx->uNumParms == 1, VERR_INVALID_PARAMETER);
1013
1014 int rc;
1015 do
1016 {
1017 HGCMMsgPathUserHome Msg;
1018 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, vbglR3GuestCtrlGetMsgFunctionNo(pCtx->uClientID), pCtx->uNumParms);
1019 VbglHGCMParmUInt32Set(&Msg.context, HOST_MSG_PATH_USER_HOME);
1020
1021 rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
1022 if (RT_SUCCESS(rc))
1023 Msg.context.GetUInt32(&pCtx->uContextID);
1024 } while (rc == VERR_INTERRUPTED && g_fVbglR3GuestCtrlHavePeekGetCancel);
1025 return rc;
1026}
1027
1028/**
1029 * Retrieves a HOST_MSG_SHUTDOWN message.
1030 *
1031 * @returns VBox status code.
1032 * @param pCtx Guest control command context to use.
1033 * @param pfAction Where to store the action flags on success.
1034 */
1035VBGLR3DECL(int) VbglR3GuestCtrlGetShutdown(PVBGLR3GUESTCTRLCMDCTX pCtx, uint32_t *pfAction)
1036{
1037 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1038 AssertReturn(pCtx->uNumParms == 1, VERR_INVALID_PARAMETER);
1039
1040 int rc;
1041 do
1042 {
1043 HGCMMsgShutdown Msg;
1044 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, vbglR3GuestCtrlGetMsgFunctionNo(pCtx->uClientID), pCtx->uNumParms);
1045 VbglHGCMParmUInt32Set(&Msg.context, HOST_MSG_SHUTDOWN);
1046
1047 rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
1048 if (RT_SUCCESS(rc))
1049 {
1050 Msg.context.GetUInt32(&pCtx->uContextID);
1051 Msg.action.GetUInt32(pfAction);
1052 }
1053 } while (rc == VERR_INTERRUPTED && g_fVbglR3GuestCtrlHavePeekGetCancel);
1054 return rc;
1055}
1056
1057/**
1058 * Initializes a process startup info, extended version.
1059 *
1060 * @returns VBox status code.
1061 * @param pStartupInfo Process startup info to initializes.
1062 * @param cbCmd Size (in bytes) to use for the command buffer.
1063 * @param cbUser Size (in bytes) to use for the user name buffer.
1064 * @param cbPassword Size (in bytes) to use for the password buffer.
1065 * @param cbDomain Size (in bytes) to use for the domain buffer.
1066 * @param cbArgs Size (in bytes) to use for the arguments buffer.
1067 * @param cbEnv Size (in bytes) to use for the environment buffer.
1068 */
1069VBGLR3DECL(int) VbglR3GuestCtrlProcStartupInfoInitEx(PVBGLR3GUESTCTRLPROCSTARTUPINFO pStartupInfo,
1070 size_t cbCmd,
1071 size_t cbUser, size_t cbPassword, size_t cbDomain,
1072 size_t cbArgs, size_t cbEnv)
1073{
1074 AssertPtrReturn(pStartupInfo, VERR_INVALID_POINTER);
1075 AssertReturn(cbCmd, VERR_INVALID_PARAMETER);
1076 AssertReturn(cbUser, VERR_INVALID_PARAMETER);
1077 AssertReturn(cbPassword, VERR_INVALID_PARAMETER);
1078 AssertReturn(cbDomain, VERR_INVALID_PARAMETER);
1079 AssertReturn(cbArgs, VERR_INVALID_PARAMETER);
1080 AssertReturn(cbEnv, VERR_INVALID_PARAMETER);
1081
1082 RT_BZERO(pStartupInfo, sizeof(VBGLR3GUESTCTRLPROCSTARTUPINFO));
1083
1084#define ALLOC_STR(a_Str, a_cb) \
1085 if ((a_cb) > 0) \
1086 { \
1087 pStartupInfo->psz##a_Str = RTStrAlloc(a_cb); \
1088 AssertPtrBreak(pStartupInfo->psz##a_Str); \
1089 pStartupInfo->cb##a_Str = (uint32_t)a_cb; \
1090 }
1091
1092 do
1093 {
1094 ALLOC_STR(Cmd, cbCmd);
1095 ALLOC_STR(Args, cbArgs);
1096 ALLOC_STR(Env, cbEnv);
1097 ALLOC_STR(User, cbUser);
1098 ALLOC_STR(Password, cbPassword);
1099 ALLOC_STR(Domain, cbDomain);
1100
1101 return VINF_SUCCESS;
1102
1103 } while (0);
1104
1105#undef ALLOC_STR
1106
1107 VbglR3GuestCtrlProcStartupInfoDestroy(pStartupInfo);
1108 return VERR_NO_MEMORY;
1109}
1110
1111/**
1112 * Initializes a process startup info with default values.
1113 *
1114 * @param pStartupInfo Process startup info to initializes.
1115 */
1116VBGLR3DECL(int) VbglR3GuestCtrlProcStartupInfoInit(PVBGLR3GUESTCTRLPROCSTARTUPINFO pStartupInfo)
1117{
1118 return VbglR3GuestCtrlProcStartupInfoInitEx(pStartupInfo,
1119 GUESTPROCESS_MAX_CMD_LEN,
1120 GUESTPROCESS_MAX_USER_LEN, GUESTPROCESS_MAX_PASSWORD_LEN,
1121 GUESTPROCESS_MAX_DOMAIN_LEN,
1122 GUESTPROCESS_MAX_ARGS_LEN, GUESTPROCESS_MAX_ENV_LEN);
1123}
1124
1125/**
1126 * Destroys a process startup info.
1127 *
1128 * @param pStartupInfo Process startup info to destroy.
1129 */
1130VBGLR3DECL(void) VbglR3GuestCtrlProcStartupInfoDestroy(PVBGLR3GUESTCTRLPROCSTARTUPINFO pStartupInfo)
1131{
1132 if (!pStartupInfo)
1133 return;
1134
1135 RTStrFree(pStartupInfo->pszCmd);
1136 RTStrFree(pStartupInfo->pszArgs);
1137 RTStrFree(pStartupInfo->pszEnv);
1138 RTStrFree(pStartupInfo->pszUser);
1139 RTStrFree(pStartupInfo->pszPassword);
1140 RTStrFree(pStartupInfo->pszDomain);
1141
1142 RT_BZERO(pStartupInfo, sizeof(VBGLR3GUESTCTRLPROCSTARTUPINFO));
1143}
1144
1145/**
1146 * Free's a process startup info.
1147 *
1148 * @param pStartupInfo Process startup info to free.
1149 * The pointer will not be valid anymore after return.
1150 */
1151VBGLR3DECL(void) VbglR3GuestCtrlProcStartupInfoFree(PVBGLR3GUESTCTRLPROCSTARTUPINFO pStartupInfo)
1152{
1153 if (!pStartupInfo)
1154 return;
1155
1156 VbglR3GuestCtrlProcStartupInfoDestroy(pStartupInfo);
1157
1158 RTMemFree(pStartupInfo);
1159 pStartupInfo = NULL;
1160}
1161
1162/**
1163 * Duplicates a process startup info.
1164 *
1165 * @returns Duplicated process startup info on success, or NULL on error.
1166 * @param pStartupInfo Process startup info to duplicate.
1167 */
1168VBGLR3DECL(PVBGLR3GUESTCTRLPROCSTARTUPINFO) VbglR3GuestCtrlProcStartupInfoDup(PVBGLR3GUESTCTRLPROCSTARTUPINFO pStartupInfo)
1169{
1170 AssertPtrReturn(pStartupInfo, NULL);
1171
1172 PVBGLR3GUESTCTRLPROCSTARTUPINFO pStartupInfoDup = (PVBGLR3GUESTCTRLPROCSTARTUPINFO)
1173 RTMemDup(pStartupInfo, sizeof(VBGLR3GUESTCTRLPROCSTARTUPINFO));
1174 if (pStartupInfoDup)
1175 {
1176 do
1177 {
1178 pStartupInfoDup->pszCmd = NULL;
1179 pStartupInfoDup->pszArgs = NULL;
1180 pStartupInfoDup->pszEnv = NULL;
1181 pStartupInfoDup->pszUser = NULL;
1182 pStartupInfoDup->pszPassword = NULL;
1183 pStartupInfoDup->pszDomain = NULL;
1184
1185#define DUP_STR(a_Str) \
1186 if (pStartupInfo->cb##a_Str) \
1187 { \
1188 pStartupInfoDup->psz##a_Str = (char *)RTStrDup(pStartupInfo->psz##a_Str); \
1189 AssertPtrBreak(pStartupInfoDup->psz##a_Str); \
1190 pStartupInfoDup->cb##a_Str = (uint32_t)strlen(pStartupInfoDup->psz##a_Str) + 1 /* Include terminator */; \
1191 }
1192
1193#define DUP_MEM(a_Str) \
1194 if (pStartupInfo->cb##a_Str) \
1195 { \
1196 pStartupInfoDup->psz##a_Str = (char *)RTMemDup(pStartupInfo->psz##a_Str, pStartupInfo->cb##a_Str); \
1197 AssertPtrBreak(pStartupInfoDup->psz##a_Str); \
1198 pStartupInfoDup->cb##a_Str = (uint32_t)pStartupInfo->cb##a_Str; \
1199 }
1200
1201 DUP_STR(Cmd);
1202 DUP_MEM(Args);
1203 DUP_MEM(Env);
1204 DUP_STR(User);
1205 DUP_STR(Password);
1206 DUP_STR(Domain);
1207
1208#undef DUP_STR
1209#undef DUP_MEM
1210
1211 return pStartupInfoDup;
1212
1213 } while (0); /* To use break macros above. */
1214
1215 VbglR3GuestCtrlProcStartupInfoFree(pStartupInfoDup);
1216 }
1217
1218 return NULL;
1219}
1220
1221/**
1222 * Retrieves a HOST_EXEC_CMD message.
1223 *
1224 * @returns VBox status code.
1225 * @param pCtx Guest control command context to use.
1226 * @param ppStartupInfo Where to store the allocated session startup info.
1227 * Needs to be free'd by VbglR3GuestCtrlProcStartupInfoFree().
1228 */
1229VBGLR3DECL(int) VbglR3GuestCtrlProcGetStart(PVBGLR3GUESTCTRLCMDCTX pCtx, PVBGLR3GUESTCTRLPROCSTARTUPINFO *ppStartupInfo)
1230{
1231 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1232 AssertPtrReturn(ppStartupInfo, VERR_INVALID_POINTER);
1233
1234 PVBGLR3GUESTCTRLPROCSTARTUPINFO pStartupInfo
1235 = (PVBGLR3GUESTCTRLPROCSTARTUPINFO)RTMemAlloc(sizeof(VBGLR3GUESTCTRLPROCSTARTUPINFO));
1236 if (!pStartupInfo)
1237 return VERR_NO_MEMORY;
1238
1239 int rc = VbglR3GuestCtrlProcStartupInfoInit(pStartupInfo);
1240 if (RT_FAILURE(rc))
1241 {
1242 VbglR3GuestCtrlProcStartupInfoFree(pStartupInfo);
1243 return rc;
1244 }
1245
1246 unsigned cRetries = 0;
1247 unsigned cGrowthFactor = 2;
1248
1249 do
1250 {
1251 HGCMMsgProcExec Msg;
1252 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, vbglR3GuestCtrlGetMsgFunctionNo(pCtx->uClientID), pCtx->uNumParms);
1253 VbglHGCMParmUInt32Set(&Msg.context, HOST_MSG_EXEC_CMD);
1254 VbglHGCMParmPtrSet(&Msg.cmd, pStartupInfo->pszCmd, pStartupInfo->cbCmd);
1255 VbglHGCMParmUInt32Set(&Msg.flags, 0);
1256 VbglHGCMParmUInt32Set(&Msg.num_args, 0);
1257 VbglHGCMParmPtrSet(&Msg.args, pStartupInfo->pszArgs, pStartupInfo->cbArgs);
1258 VbglHGCMParmUInt32Set(&Msg.num_env, 0);
1259 VbglHGCMParmUInt32Set(&Msg.cb_env, 0);
1260 VbglHGCMParmPtrSet(&Msg.env, pStartupInfo->pszEnv, pStartupInfo->cbEnv);
1261 if (pCtx->uProtocol < 2)
1262 {
1263 VbglHGCMParmPtrSet(&Msg.u.v1.username, pStartupInfo->pszUser, pStartupInfo->cbUser);
1264 VbglHGCMParmPtrSet(&Msg.u.v1.password, pStartupInfo->pszPassword, pStartupInfo->cbPassword);
1265 VbglHGCMParmUInt32Set(&Msg.u.v1.timeout, 0);
1266 }
1267 else
1268 {
1269 VbglHGCMParmUInt32Set(&Msg.u.v2.timeout, 0);
1270 VbglHGCMParmUInt32Set(&Msg.u.v2.priority, 0);
1271 VbglHGCMParmUInt32Set(&Msg.u.v2.num_affinity, 0);
1272 VbglHGCMParmPtrSet(&Msg.u.v2.affinity, pStartupInfo->uAffinity, sizeof(pStartupInfo->uAffinity));
1273 }
1274
1275 rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
1276 if (RT_FAILURE(rc))
1277 {
1278 if ( rc == VERR_BUFFER_OVERFLOW
1279 && cRetries++ < 4)
1280 {
1281#define GROW_STR(a_Str, a_cbMax) \
1282 pStartupInfo->psz##a_Str = (char *)RTMemRealloc(pStartupInfo->psz##a_Str, \
1283 RT_MAX(pStartupInfo->cb##a_Str * cGrowthFactor, a_cbMax)); \
1284 AssertPtrBreakStmt(pStartupInfo->psz##a_Str, VERR_NO_MEMORY); \
1285 pStartupInfo->cb##a_Str = RT_MAX(pStartupInfo->cb##a_Str * cGrowthFactor, a_cbMax);
1286
1287 GROW_STR(Cmd , GUESTPROCESS_MAX_CMD_LEN);
1288 GROW_STR(Args, GUESTPROCESS_MAX_ARGS_LEN);
1289 GROW_STR(Env, GUESTPROCESS_MAX_ENV_LEN);
1290
1291#undef GROW_STR
1292 cGrowthFactor *= cGrowthFactor;
1293 }
1294 else
1295 break;
1296 }
1297 else
1298 {
1299 Msg.context.GetUInt32(&pCtx->uContextID);
1300 Msg.flags.GetUInt32(&pStartupInfo->fFlags);
1301 Msg.num_args.GetUInt32(&pStartupInfo->cArgs);
1302 Msg.num_env.GetUInt32(&pStartupInfo->cEnvVars);
1303 Msg.cb_env.GetUInt32(&pStartupInfo->cbEnv);
1304 if (pCtx->uProtocol < 2)
1305 Msg.u.v1.timeout.GetUInt32(&pStartupInfo->uTimeLimitMS);
1306 else
1307 {
1308 Msg.u.v2.timeout.GetUInt32(&pStartupInfo->uTimeLimitMS);
1309 Msg.u.v2.priority.GetUInt32(&pStartupInfo->uPriority);
1310 Msg.u.v2.num_affinity.GetUInt32(&pStartupInfo->cAffinity);
1311 }
1312 }
1313 } while (rc == VERR_INTERRUPTED && g_fVbglR3GuestCtrlHavePeekGetCancel);
1314
1315 if (RT_SUCCESS(rc))
1316 {
1317 *ppStartupInfo = pStartupInfo;
1318 }
1319 else
1320 VbglR3GuestCtrlProcStartupInfoFree(pStartupInfo);
1321
1322 LogFlowFuncLeaveRC(rc);
1323 return rc;
1324}
1325
1326/**
1327 * Allocates and gets host data, based on the message id.
1328 *
1329 * This will block until data becomes available.
1330 *
1331 * @returns VBox status code.
1332 ** @todo Docs!
1333 */
1334VBGLR3DECL(int) VbglR3GuestCtrlProcGetOutput(PVBGLR3GUESTCTRLCMDCTX pCtx,
1335 uint32_t *puPID, uint32_t *puHandle, uint32_t *pfFlags)
1336{
1337 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1338 AssertReturn(pCtx->uNumParms == 4, VERR_INVALID_PARAMETER);
1339
1340 AssertPtrReturn(puPID, VERR_INVALID_POINTER);
1341 AssertPtrReturn(puHandle, VERR_INVALID_POINTER);
1342 AssertPtrReturn(pfFlags, VERR_INVALID_POINTER);
1343
1344 int rc;
1345 do
1346 {
1347 HGCMMsgProcOutput Msg;
1348 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, vbglR3GuestCtrlGetMsgFunctionNo(pCtx->uClientID), pCtx->uNumParms);
1349 VbglHGCMParmUInt32Set(&Msg.context, HOST_MSG_EXEC_GET_OUTPUT);
1350 VbglHGCMParmUInt32Set(&Msg.pid, 0);
1351 VbglHGCMParmUInt32Set(&Msg.handle, 0);
1352 VbglHGCMParmUInt32Set(&Msg.flags, 0);
1353
1354 rc = VbglR3HGCMCall(&Msg.hdr, RT_UOFFSETOF(HGCMMsgProcOutput, data));
1355 if (RT_SUCCESS(rc))
1356 {
1357 Msg.context.GetUInt32(&pCtx->uContextID);
1358 Msg.pid.GetUInt32(puPID);
1359 Msg.handle.GetUInt32(puHandle);
1360 Msg.flags.GetUInt32(pfFlags);
1361 }
1362 } while (rc == VERR_INTERRUPTED && g_fVbglR3GuestCtrlHavePeekGetCancel);
1363 return rc;
1364}
1365
1366
1367/**
1368 * Retrieves the input data from host which then gets sent to the started
1369 * process (HOST_EXEC_SET_INPUT).
1370 *
1371 * This will block until data becomes available.
1372 */
1373VBGLR3DECL(int) VbglR3GuestCtrlProcGetInput(PVBGLR3GUESTCTRLCMDCTX pCtx,
1374 uint32_t *puPID, uint32_t *pfFlags,
1375 void *pvData, uint32_t cbData,
1376 uint32_t *pcbSize)
1377{
1378 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1379 AssertReturn(pCtx->uNumParms == 5, VERR_INVALID_PARAMETER);
1380
1381 AssertPtrReturn(puPID, VERR_INVALID_POINTER);
1382 AssertPtrReturn(pfFlags, VERR_INVALID_POINTER);
1383 AssertPtrReturn(pvData, VERR_INVALID_POINTER);
1384 AssertPtrReturn(pcbSize, VERR_INVALID_POINTER);
1385
1386 int rc;
1387 do
1388 {
1389 HGCMMsgProcInput Msg;
1390 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, vbglR3GuestCtrlGetMsgFunctionNo(pCtx->uClientID), pCtx->uNumParms);
1391 VbglHGCMParmUInt32Set(&Msg.context, HOST_MSG_EXEC_SET_INPUT);
1392 VbglHGCMParmUInt32Set(&Msg.pid, 0);
1393 VbglHGCMParmUInt32Set(&Msg.flags, 0);
1394 VbglHGCMParmPtrSet(&Msg.data, pvData, cbData);
1395 VbglHGCMParmUInt32Set(&Msg.size, 0);
1396
1397 rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
1398 if (RT_SUCCESS(rc))
1399 {
1400 Msg.context.GetUInt32(&pCtx->uContextID);
1401 Msg.pid.GetUInt32(puPID);
1402 Msg.flags.GetUInt32(pfFlags);
1403 Msg.size.GetUInt32(pcbSize);
1404 }
1405 } while (rc == VERR_INTERRUPTED && g_fVbglR3GuestCtrlHavePeekGetCancel);
1406
1407 if ( rc != VERR_TOO_MUCH_DATA
1408 || g_fVbglR3GuestCtrlHavePeekGetCancel)
1409 return rc;
1410 return VERR_BUFFER_OVERFLOW;
1411}
1412
1413
1414/**
1415 * Retrieves a HOST_DIR_REMOVE message.
1416 */
1417VBGLR3DECL(int) VbglR3GuestCtrlDirGetRemove(PVBGLR3GUESTCTRLCMDCTX pCtx,
1418 char *pszPath, uint32_t cbPath,
1419 uint32_t *pfFlags)
1420{
1421 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1422 AssertReturn(pCtx->uNumParms == 3, VERR_INVALID_PARAMETER);
1423
1424 AssertPtrReturn(pszPath, VERR_INVALID_POINTER);
1425 AssertReturn(cbPath, VERR_INVALID_PARAMETER);
1426 AssertPtrReturn(pfFlags, VERR_INVALID_POINTER);
1427
1428 int rc;
1429 do
1430 {
1431 HGCMMsgDirRemove Msg;
1432 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, vbglR3GuestCtrlGetMsgFunctionNo(pCtx->uClientID), pCtx->uNumParms);
1433 VbglHGCMParmUInt32Set(&Msg.context, HOST_MSG_DIR_REMOVE);
1434 VbglHGCMParmPtrSet(&Msg.path, pszPath, cbPath);
1435 VbglHGCMParmUInt32Set(&Msg.flags, 0);
1436
1437 rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
1438 if (RT_SUCCESS(rc))
1439 {
1440 Msg.context.GetUInt32(&pCtx->uContextID);
1441 Msg.flags.GetUInt32(pfFlags);
1442 }
1443 } while (rc == VERR_INTERRUPTED && g_fVbglR3GuestCtrlHavePeekGetCancel);
1444 return rc;
1445}
1446
1447
1448/**
1449 * Retrieves a HOST_FILE_OPEN message.
1450 */
1451VBGLR3DECL(int) VbglR3GuestCtrlFileGetOpen(PVBGLR3GUESTCTRLCMDCTX pCtx,
1452 char *pszFileName, uint32_t cbFileName,
1453 char *pszAccess, uint32_t cbAccess,
1454 char *pszDisposition, uint32_t cbDisposition,
1455 char *pszSharing, uint32_t cbSharing,
1456 uint32_t *puCreationMode,
1457 uint64_t *poffAt)
1458{
1459 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1460 AssertReturn(pCtx->uNumParms == 7, VERR_INVALID_PARAMETER);
1461
1462 AssertPtrReturn(pszFileName, VERR_INVALID_POINTER);
1463 AssertReturn(cbFileName, VERR_INVALID_PARAMETER);
1464 AssertPtrReturn(pszAccess, VERR_INVALID_POINTER);
1465 AssertReturn(cbAccess, VERR_INVALID_PARAMETER);
1466 AssertPtrReturn(pszDisposition, VERR_INVALID_POINTER);
1467 AssertReturn(cbDisposition, VERR_INVALID_PARAMETER);
1468 AssertPtrReturn(pszSharing, VERR_INVALID_POINTER);
1469 AssertReturn(cbSharing, VERR_INVALID_PARAMETER);
1470 AssertPtrReturn(puCreationMode, VERR_INVALID_POINTER);
1471 AssertPtrReturn(poffAt, VERR_INVALID_POINTER);
1472
1473 int rc;
1474 do
1475 {
1476 HGCMMsgFileOpen Msg;
1477 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, vbglR3GuestCtrlGetMsgFunctionNo(pCtx->uClientID), pCtx->uNumParms);
1478 VbglHGCMParmUInt32Set(&Msg.context, HOST_MSG_FILE_OPEN);
1479 VbglHGCMParmPtrSet(&Msg.filename, pszFileName, cbFileName);
1480 VbglHGCMParmPtrSet(&Msg.openmode, pszAccess, cbAccess);
1481 VbglHGCMParmPtrSet(&Msg.disposition, pszDisposition, cbDisposition);
1482 VbglHGCMParmPtrSet(&Msg.sharing, pszSharing, cbSharing);
1483 VbglHGCMParmUInt32Set(&Msg.creationmode, 0);
1484 VbglHGCMParmUInt64Set(&Msg.offset, 0);
1485
1486 rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
1487 if (RT_SUCCESS(rc))
1488 {
1489 Msg.context.GetUInt32(&pCtx->uContextID);
1490 Msg.creationmode.GetUInt32(puCreationMode);
1491 Msg.offset.GetUInt64(poffAt);
1492 }
1493 } while (rc == VERR_INTERRUPTED && g_fVbglR3GuestCtrlHavePeekGetCancel);
1494 return rc;
1495}
1496
1497
1498/**
1499 * Retrieves a HOST_FILE_CLOSE message.
1500 */
1501VBGLR3DECL(int) VbglR3GuestCtrlFileGetClose(PVBGLR3GUESTCTRLCMDCTX pCtx, uint32_t *puHandle)
1502{
1503 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1504
1505 AssertReturn(pCtx->uNumParms == 2, VERR_INVALID_PARAMETER);
1506 AssertPtrReturn(puHandle, VERR_INVALID_POINTER);
1507
1508 int rc;
1509 do
1510 {
1511 HGCMMsgFileClose Msg;
1512 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, vbglR3GuestCtrlGetMsgFunctionNo(pCtx->uClientID), pCtx->uNumParms);
1513 VbglHGCMParmUInt32Set(&Msg.context, HOST_MSG_FILE_CLOSE);
1514 VbglHGCMParmUInt32Set(&Msg.handle, 0);
1515
1516 rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
1517 if (RT_SUCCESS(rc))
1518 {
1519 Msg.context.GetUInt32(&pCtx->uContextID);
1520 Msg.handle.GetUInt32(puHandle);
1521 }
1522 } while (rc == VERR_INTERRUPTED && g_fVbglR3GuestCtrlHavePeekGetCancel);
1523 return rc;
1524}
1525
1526
1527/**
1528 * Retrieves a HOST_FILE_READ message.
1529 */
1530VBGLR3DECL(int) VbglR3GuestCtrlFileGetRead(PVBGLR3GUESTCTRLCMDCTX pCtx, uint32_t *puHandle, uint32_t *puToRead)
1531{
1532 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1533
1534 AssertReturn(pCtx->uNumParms == 3, VERR_INVALID_PARAMETER);
1535 AssertPtrReturn(puHandle, VERR_INVALID_POINTER);
1536 AssertPtrReturn(puToRead, VERR_INVALID_POINTER);
1537
1538 int rc;
1539 do
1540 {
1541 HGCMMsgFileRead Msg;
1542 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, vbglR3GuestCtrlGetMsgFunctionNo(pCtx->uClientID), pCtx->uNumParms);
1543 VbglHGCMParmUInt32Set(&Msg.context, HOST_MSG_FILE_READ);
1544 VbglHGCMParmUInt32Set(&Msg.handle, 0);
1545 VbglHGCMParmUInt32Set(&Msg.size, 0);
1546
1547 rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
1548 if (RT_SUCCESS(rc))
1549 {
1550 Msg.context.GetUInt32(&pCtx->uContextID);
1551 Msg.handle.GetUInt32(puHandle);
1552 Msg.size.GetUInt32(puToRead);
1553 }
1554 } while (rc == VERR_INTERRUPTED && g_fVbglR3GuestCtrlHavePeekGetCancel);
1555 return rc;
1556}
1557
1558
1559/**
1560 * Retrieves a HOST_FILE_READ_AT message.
1561 */
1562VBGLR3DECL(int) VbglR3GuestCtrlFileGetReadAt(PVBGLR3GUESTCTRLCMDCTX pCtx,
1563 uint32_t *puHandle, uint32_t *puToRead, uint64_t *poffAt)
1564{
1565 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1566
1567 AssertReturn(pCtx->uNumParms == 4, VERR_INVALID_PARAMETER);
1568 AssertPtrReturn(puHandle, VERR_INVALID_POINTER);
1569 AssertPtrReturn(puToRead, VERR_INVALID_POINTER);
1570
1571 int rc;
1572 do
1573 {
1574 HGCMMsgFileReadAt Msg;
1575 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, vbglR3GuestCtrlGetMsgFunctionNo(pCtx->uClientID), pCtx->uNumParms);
1576 VbglHGCMParmUInt32Set(&Msg.context, HOST_MSG_FILE_READ_AT);
1577 VbglHGCMParmUInt32Set(&Msg.handle, 0);
1578 VbglHGCMParmUInt64Set(&Msg.offset, 0);
1579 VbglHGCMParmUInt32Set(&Msg.size, 0);
1580
1581 rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
1582 if (RT_SUCCESS(rc))
1583 {
1584 Msg.context.GetUInt32(&pCtx->uContextID);
1585 Msg.handle.GetUInt32(puHandle);
1586 Msg.offset.GetUInt64(poffAt);
1587 Msg.size.GetUInt32(puToRead);
1588 }
1589 } while (rc == VERR_INTERRUPTED && g_fVbglR3GuestCtrlHavePeekGetCancel);
1590 return rc;
1591}
1592
1593
1594/**
1595 * Retrieves a HOST_FILE_WRITE message.
1596 */
1597VBGLR3DECL(int) VbglR3GuestCtrlFileGetWrite(PVBGLR3GUESTCTRLCMDCTX pCtx, uint32_t *puHandle,
1598 void *pvData, uint32_t cbData, uint32_t *pcbSize)
1599{
1600 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1601
1602 AssertReturn(pCtx->uNumParms == 4, VERR_INVALID_PARAMETER);
1603 AssertPtrReturn(puHandle, VERR_INVALID_POINTER);
1604 AssertPtrReturn(pvData, VERR_INVALID_POINTER);
1605 AssertReturn(cbData, VERR_INVALID_PARAMETER);
1606 AssertPtrReturn(pcbSize, VERR_INVALID_POINTER);
1607
1608 int rc;
1609 do
1610 {
1611 HGCMMsgFileWrite Msg;
1612 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, vbglR3GuestCtrlGetMsgFunctionNo(pCtx->uClientID), pCtx->uNumParms);
1613 VbglHGCMParmUInt32Set(&Msg.context, HOST_MSG_FILE_WRITE);
1614 VbglHGCMParmUInt32Set(&Msg.handle, 0);
1615 VbglHGCMParmPtrSet(&Msg.data, pvData, cbData);
1616 VbglHGCMParmUInt32Set(&Msg.size, 0);
1617
1618 rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
1619 if (RT_SUCCESS(rc))
1620 {
1621 Msg.context.GetUInt32(&pCtx->uContextID);
1622 Msg.handle.GetUInt32(puHandle);
1623 Msg.size.GetUInt32(pcbSize);
1624 }
1625 } while (rc == VERR_INTERRUPTED && g_fVbglR3GuestCtrlHavePeekGetCancel);
1626
1627 if ( rc != VERR_TOO_MUCH_DATA
1628 || g_fVbglR3GuestCtrlHavePeekGetCancel)
1629 return rc;
1630 return VERR_BUFFER_OVERFLOW;
1631}
1632
1633
1634/**
1635 * Retrieves a HOST_FILE_WRITE_AT message.
1636 */
1637VBGLR3DECL(int) VbglR3GuestCtrlFileGetWriteAt(PVBGLR3GUESTCTRLCMDCTX pCtx, uint32_t *puHandle,
1638 void *pvData, uint32_t cbData, uint32_t *pcbSize, uint64_t *poffAt)
1639{
1640 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1641
1642 AssertReturn(pCtx->uNumParms == 5, VERR_INVALID_PARAMETER);
1643 AssertPtrReturn(puHandle, VERR_INVALID_POINTER);
1644 AssertPtrReturn(pvData, VERR_INVALID_POINTER);
1645 AssertReturn(cbData, VERR_INVALID_PARAMETER);
1646 AssertPtrReturn(pcbSize, VERR_INVALID_POINTER);
1647
1648 int rc;
1649 do
1650 {
1651 HGCMMsgFileWriteAt Msg;
1652 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, vbglR3GuestCtrlGetMsgFunctionNo(pCtx->uClientID), pCtx->uNumParms);
1653 VbglHGCMParmUInt32Set(&Msg.context, HOST_MSG_FILE_WRITE_AT);
1654 VbglHGCMParmUInt32Set(&Msg.handle, 0);
1655 VbglHGCMParmPtrSet(&Msg.data, pvData, cbData);
1656 VbglHGCMParmUInt32Set(&Msg.size, 0);
1657 VbglHGCMParmUInt64Set(&Msg.offset, 0);
1658
1659 rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
1660 if (RT_SUCCESS(rc))
1661 {
1662 Msg.context.GetUInt32(&pCtx->uContextID);
1663 Msg.handle.GetUInt32(puHandle);
1664 Msg.size.GetUInt32(pcbSize);
1665 Msg.offset.GetUInt64(poffAt);
1666 }
1667 } while (rc == VERR_INTERRUPTED && g_fVbglR3GuestCtrlHavePeekGetCancel);
1668
1669 if ( rc != VERR_TOO_MUCH_DATA
1670 || g_fVbglR3GuestCtrlHavePeekGetCancel)
1671 return rc;
1672 return VERR_BUFFER_OVERFLOW;
1673}
1674
1675
1676/**
1677 * Retrieves a HOST_FILE_SEEK message.
1678 */
1679VBGLR3DECL(int) VbglR3GuestCtrlFileGetSeek(PVBGLR3GUESTCTRLCMDCTX pCtx,
1680 uint32_t *puHandle, uint32_t *puSeekMethod, uint64_t *poffAt)
1681{
1682 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1683
1684 AssertReturn(pCtx->uNumParms == 4, VERR_INVALID_PARAMETER);
1685 AssertPtrReturn(puHandle, VERR_INVALID_POINTER);
1686 AssertPtrReturn(puSeekMethod, VERR_INVALID_POINTER);
1687 AssertPtrReturn(poffAt, VERR_INVALID_POINTER);
1688
1689 int rc;
1690 do
1691 {
1692 HGCMMsgFileSeek Msg;
1693 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, vbglR3GuestCtrlGetMsgFunctionNo(pCtx->uClientID), pCtx->uNumParms);
1694 VbglHGCMParmUInt32Set(&Msg.context, HOST_MSG_FILE_SEEK);
1695 VbglHGCMParmUInt32Set(&Msg.handle, 0);
1696 VbglHGCMParmUInt32Set(&Msg.method, 0);
1697 VbglHGCMParmUInt64Set(&Msg.offset, 0);
1698
1699 rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
1700 if (RT_SUCCESS(rc))
1701 {
1702 Msg.context.GetUInt32(&pCtx->uContextID);
1703 Msg.handle.GetUInt32(puHandle);
1704 Msg.method.GetUInt32(puSeekMethod);
1705 Msg.offset.GetUInt64(poffAt);
1706 }
1707 } while (rc == VERR_INTERRUPTED && g_fVbglR3GuestCtrlHavePeekGetCancel);
1708 return rc;
1709}
1710
1711
1712/**
1713 * Retrieves a HOST_FILE_TELL message.
1714 */
1715VBGLR3DECL(int) VbglR3GuestCtrlFileGetTell(PVBGLR3GUESTCTRLCMDCTX pCtx, uint32_t *puHandle)
1716{
1717 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1718
1719 AssertReturn(pCtx->uNumParms == 2, VERR_INVALID_PARAMETER);
1720 AssertPtrReturn(puHandle, VERR_INVALID_POINTER);
1721
1722 int rc;
1723 do
1724 {
1725 HGCMMsgFileTell Msg;
1726 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, vbglR3GuestCtrlGetMsgFunctionNo(pCtx->uClientID), pCtx->uNumParms);
1727 VbglHGCMParmUInt32Set(&Msg.context, HOST_MSG_FILE_TELL);
1728 VbglHGCMParmUInt32Set(&Msg.handle, 0);
1729
1730 rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
1731 if (RT_SUCCESS(rc))
1732 {
1733 Msg.context.GetUInt32(&pCtx->uContextID);
1734 Msg.handle.GetUInt32(puHandle);
1735 }
1736 } while (rc == VERR_INTERRUPTED && g_fVbglR3GuestCtrlHavePeekGetCancel);
1737 return rc;
1738}
1739
1740
1741/**
1742 * Retrieves a HOST_FILE_SET_SIZE message.
1743 */
1744VBGLR3DECL(int) VbglR3GuestCtrlFileGetSetSize(PVBGLR3GUESTCTRLCMDCTX pCtx, uint32_t *puHandle, uint64_t *pcbNew)
1745{
1746 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1747
1748 AssertReturn(pCtx->uNumParms == 3, VERR_INVALID_PARAMETER);
1749 AssertPtrReturn(puHandle, VERR_INVALID_POINTER);
1750 AssertPtrReturn(pcbNew, VERR_INVALID_POINTER);
1751
1752 int rc;
1753 do
1754 {
1755 HGCMMsgFileSetSize Msg;
1756 VBGL_HGCM_HDR_INIT(&Msg.Hdr, pCtx->uClientID, vbglR3GuestCtrlGetMsgFunctionNo(pCtx->uClientID), pCtx->uNumParms);
1757 VbglHGCMParmUInt32Set(&Msg.id32Context, HOST_MSG_FILE_SET_SIZE);
1758 VbglHGCMParmUInt32Set(&Msg.id32Handle, 0);
1759 VbglHGCMParmUInt64Set(&Msg.cb64NewSize, 0);
1760
1761 rc = VbglR3HGCMCall(&Msg.Hdr, sizeof(Msg));
1762 if (RT_SUCCESS(rc))
1763 {
1764 Msg.id32Context.GetUInt32(&pCtx->uContextID);
1765 Msg.id32Handle.GetUInt32(puHandle);
1766 Msg.cb64NewSize.GetUInt64(pcbNew);
1767 }
1768 } while (rc == VERR_INTERRUPTED && g_fVbglR3GuestCtrlHavePeekGetCancel);
1769 return rc;
1770}
1771
1772
1773/**
1774 * Retrieves a HOST_EXEC_TERMINATE message.
1775 */
1776VBGLR3DECL(int) VbglR3GuestCtrlProcGetTerminate(PVBGLR3GUESTCTRLCMDCTX pCtx, uint32_t *puPID)
1777{
1778 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1779
1780 AssertReturn(pCtx->uNumParms == 2, VERR_INVALID_PARAMETER);
1781 AssertPtrReturn(puPID, VERR_INVALID_POINTER);
1782
1783 int rc;
1784 do
1785 {
1786 HGCMMsgProcTerminate Msg;
1787 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, vbglR3GuestCtrlGetMsgFunctionNo(pCtx->uClientID), pCtx->uNumParms);
1788 VbglHGCMParmUInt32Set(&Msg.context, HOST_MSG_EXEC_TERMINATE);
1789 VbglHGCMParmUInt32Set(&Msg.pid, 0);
1790
1791 rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
1792 if (RT_SUCCESS(rc))
1793 {
1794 Msg.context.GetUInt32(&pCtx->uContextID);
1795 Msg.pid.GetUInt32(puPID);
1796 }
1797 } while (rc == VERR_INTERRUPTED && g_fVbglR3GuestCtrlHavePeekGetCancel);
1798 return rc;
1799}
1800
1801
1802/**
1803 * Retrieves a HOST_EXEC_WAIT_FOR message.
1804 */
1805VBGLR3DECL(int) VbglR3GuestCtrlProcGetWaitFor(PVBGLR3GUESTCTRLCMDCTX pCtx,
1806 uint32_t *puPID, uint32_t *puWaitFlags, uint32_t *puTimeoutMS)
1807{
1808 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1809
1810 AssertReturn(pCtx->uNumParms == 5, VERR_INVALID_PARAMETER);
1811 AssertPtrReturn(puPID, VERR_INVALID_POINTER);
1812
1813 int rc;
1814 do
1815 {
1816 HGCMMsgProcWaitFor Msg;
1817 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, vbglR3GuestCtrlGetMsgFunctionNo(pCtx->uClientID), pCtx->uNumParms);
1818 VbglHGCMParmUInt32Set(&Msg.context, HOST_MSG_EXEC_WAIT_FOR);
1819 VbglHGCMParmUInt32Set(&Msg.pid, 0);
1820 VbglHGCMParmUInt32Set(&Msg.flags, 0);
1821 VbglHGCMParmUInt32Set(&Msg.timeout, 0);
1822
1823 rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
1824 if (RT_SUCCESS(rc))
1825 {
1826 Msg.context.GetUInt32(&pCtx->uContextID);
1827 Msg.pid.GetUInt32(puPID);
1828 Msg.flags.GetUInt32(puWaitFlags);
1829 Msg.timeout.GetUInt32(puTimeoutMS);
1830 }
1831 } while (rc == VERR_INTERRUPTED && g_fVbglR3GuestCtrlHavePeekGetCancel);
1832 return rc;
1833}
1834
1835
1836VBGLR3DECL(int) VbglR3GuestCtrlFileCbOpen(PVBGLR3GUESTCTRLCMDCTX pCtx,
1837 uint32_t uRc, uint32_t uFileHandle)
1838{
1839 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1840
1841 HGCMReplyFileNotify Msg;
1842 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, GUEST_MSG_FILE_NOTIFY, 4);
1843 VbglHGCMParmUInt32Set(&Msg.context, pCtx->uContextID);
1844 VbglHGCMParmUInt32Set(&Msg.type, GUEST_FILE_NOTIFYTYPE_OPEN);
1845 VbglHGCMParmUInt32Set(&Msg.rc, uRc);
1846 VbglHGCMParmUInt32Set(&Msg.u.open.handle, uFileHandle);
1847
1848 return VbglR3HGCMCall(&Msg.hdr, RT_UOFFSET_AFTER(HGCMReplyFileNotify, u.open));
1849}
1850
1851
1852VBGLR3DECL(int) VbglR3GuestCtrlFileCbClose(PVBGLR3GUESTCTRLCMDCTX pCtx,
1853 uint32_t uRc)
1854{
1855 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1856
1857 HGCMReplyFileNotify Msg;
1858 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, GUEST_MSG_FILE_NOTIFY, 3);
1859 VbglHGCMParmUInt32Set(&Msg.context, pCtx->uContextID);
1860 VbglHGCMParmUInt32Set(&Msg.type, GUEST_FILE_NOTIFYTYPE_CLOSE);
1861 VbglHGCMParmUInt32Set(&Msg.rc, uRc);
1862
1863 return VbglR3HGCMCall(&Msg.hdr, RT_UOFFSETOF(HGCMReplyFileNotify, u));
1864}
1865
1866
1867VBGLR3DECL(int) VbglR3GuestCtrlFileCbError(PVBGLR3GUESTCTRLCMDCTX pCtx, uint32_t uRc)
1868{
1869 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1870
1871 HGCMReplyFileNotify Msg;
1872 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, GUEST_MSG_FILE_NOTIFY, 3);
1873 VbglHGCMParmUInt32Set(&Msg.context, pCtx->uContextID);
1874 VbglHGCMParmUInt32Set(&Msg.type, GUEST_FILE_NOTIFYTYPE_ERROR);
1875 VbglHGCMParmUInt32Set(&Msg.rc, uRc);
1876
1877 return VbglR3HGCMCall(&Msg.hdr, RT_UOFFSETOF(HGCMReplyFileNotify, u));
1878}
1879
1880
1881VBGLR3DECL(int) VbglR3GuestCtrlFileCbRead(PVBGLR3GUESTCTRLCMDCTX pCtx,
1882 uint32_t uRc,
1883 void *pvData, uint32_t cbData)
1884{
1885 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1886
1887 HGCMReplyFileNotify Msg;
1888 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, GUEST_MSG_FILE_NOTIFY, 4);
1889 VbglHGCMParmUInt32Set(&Msg.context, pCtx->uContextID);
1890 VbglHGCMParmUInt32Set(&Msg.type, GUEST_FILE_NOTIFYTYPE_READ);
1891 VbglHGCMParmUInt32Set(&Msg.rc, uRc);
1892 VbglHGCMParmPtrSet(&Msg.u.read.data, pvData, cbData);
1893
1894 return VbglR3HGCMCall(&Msg.hdr, RT_UOFFSET_AFTER(HGCMReplyFileNotify, u.read));
1895}
1896
1897
1898VBGLR3DECL(int) VbglR3GuestCtrlFileCbReadOffset(PVBGLR3GUESTCTRLCMDCTX pCtx, uint32_t uRc,
1899 void *pvData, uint32_t cbData, int64_t offNew)
1900{
1901 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1902
1903 HGCMReplyFileNotify Msg;
1904 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, GUEST_MSG_FILE_NOTIFY, 5);
1905 VbglHGCMParmUInt32Set(&Msg.context, pCtx->uContextID);
1906 VbglHGCMParmUInt32Set(&Msg.type, GUEST_FILE_NOTIFYTYPE_READ_OFFSET);
1907 VbglHGCMParmUInt32Set(&Msg.rc, uRc);
1908 VbglHGCMParmPtrSet(&Msg.u.ReadOffset.pvData, pvData, cbData);
1909 VbglHGCMParmUInt64Set(&Msg.u.ReadOffset.off64New, (uint64_t)offNew);
1910
1911 return VbglR3HGCMCall(&Msg.hdr, RT_UOFFSET_AFTER(HGCMReplyFileNotify, u.ReadOffset));
1912}
1913
1914
1915VBGLR3DECL(int) VbglR3GuestCtrlFileCbWrite(PVBGLR3GUESTCTRLCMDCTX pCtx, uint32_t uRc, uint32_t cbWritten)
1916{
1917 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1918
1919 HGCMReplyFileNotify Msg;
1920 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, GUEST_MSG_FILE_NOTIFY, 4);
1921 VbglHGCMParmUInt32Set(&Msg.context, pCtx->uContextID);
1922 VbglHGCMParmUInt32Set(&Msg.type, GUEST_FILE_NOTIFYTYPE_WRITE);
1923 VbglHGCMParmUInt32Set(&Msg.rc, uRc);
1924 VbglHGCMParmUInt32Set(&Msg.u.write.written, cbWritten);
1925
1926 return VbglR3HGCMCall(&Msg.hdr, RT_UOFFSET_AFTER(HGCMReplyFileNotify, u.write));
1927}
1928
1929
1930VBGLR3DECL(int) VbglR3GuestCtrlFileCbWriteOffset(PVBGLR3GUESTCTRLCMDCTX pCtx, uint32_t uRc, uint32_t cbWritten, int64_t offNew)
1931{
1932 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1933
1934 HGCMReplyFileNotify Msg;
1935 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, GUEST_MSG_FILE_NOTIFY, 5);
1936 VbglHGCMParmUInt32Set(&Msg.context, pCtx->uContextID);
1937 VbglHGCMParmUInt32Set(&Msg.type, GUEST_FILE_NOTIFYTYPE_WRITE_OFFSET);
1938 VbglHGCMParmUInt32Set(&Msg.rc, uRc);
1939 VbglHGCMParmUInt32Set(&Msg.u.WriteOffset.cb32Written, cbWritten);
1940 VbglHGCMParmUInt64Set(&Msg.u.WriteOffset.off64New, (uint64_t)offNew);
1941
1942 return VbglR3HGCMCall(&Msg.hdr, RT_UOFFSET_AFTER(HGCMReplyFileNotify, u.WriteOffset));
1943}
1944
1945
1946VBGLR3DECL(int) VbglR3GuestCtrlFileCbSeek(PVBGLR3GUESTCTRLCMDCTX pCtx, uint32_t uRc, uint64_t offCurrent)
1947{
1948 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1949
1950 HGCMReplyFileNotify Msg;
1951 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, GUEST_MSG_FILE_NOTIFY, 4);
1952 VbglHGCMParmUInt32Set(&Msg.context, pCtx->uContextID);
1953 VbglHGCMParmUInt32Set(&Msg.type, GUEST_FILE_NOTIFYTYPE_SEEK);
1954 VbglHGCMParmUInt32Set(&Msg.rc, uRc);
1955 VbglHGCMParmUInt64Set(&Msg.u.seek.offset, offCurrent);
1956
1957 return VbglR3HGCMCall(&Msg.hdr, RT_UOFFSET_AFTER(HGCMReplyFileNotify, u.seek));
1958}
1959
1960
1961VBGLR3DECL(int) VbglR3GuestCtrlFileCbTell(PVBGLR3GUESTCTRLCMDCTX pCtx, uint32_t uRc, uint64_t offCurrent)
1962{
1963 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1964
1965 HGCMReplyFileNotify Msg;
1966 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, GUEST_MSG_FILE_NOTIFY, 4);
1967 VbglHGCMParmUInt32Set(&Msg.context, pCtx->uContextID);
1968 VbglHGCMParmUInt32Set(&Msg.type, GUEST_FILE_NOTIFYTYPE_TELL);
1969 VbglHGCMParmUInt32Set(&Msg.rc, uRc);
1970 VbglHGCMParmUInt64Set(&Msg.u.tell.offset, offCurrent);
1971
1972 return VbglR3HGCMCall(&Msg.hdr, RT_UOFFSET_AFTER(HGCMReplyFileNotify, u.tell));
1973}
1974
1975
1976VBGLR3DECL(int) VbglR3GuestCtrlFileCbSetSize(PVBGLR3GUESTCTRLCMDCTX pCtx, uint32_t uRc, uint64_t cbNew)
1977{
1978 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1979
1980 HGCMReplyFileNotify Msg;
1981 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, GUEST_MSG_FILE_NOTIFY, 4);
1982 VbglHGCMParmUInt32Set(&Msg.context, pCtx->uContextID);
1983 VbglHGCMParmUInt32Set(&Msg.type, GUEST_FILE_NOTIFYTYPE_SET_SIZE);
1984 VbglHGCMParmUInt32Set(&Msg.rc, uRc);
1985 VbglHGCMParmUInt64Set(&Msg.u.SetSize.cb64Size, cbNew);
1986
1987 return VbglR3HGCMCall(&Msg.hdr, RT_UOFFSET_AFTER(HGCMReplyFileNotify, u.SetSize));
1988}
1989
1990
1991/**
1992 * Callback for reporting a guest process status (along with some other stuff) to the host.
1993 *
1994 * @returns VBox status code.
1995 ** @todo Docs!
1996 */
1997VBGLR3DECL(int) VbglR3GuestCtrlProcCbStatus(PVBGLR3GUESTCTRLCMDCTX pCtx,
1998 uint32_t uPID, uint32_t uStatus, uint32_t fFlags,
1999 void *pvData, uint32_t cbData)
2000{
2001 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
2002
2003 HGCMMsgProcStatus Msg;
2004 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, GUEST_MSG_EXEC_STATUS, 5);
2005 VbglHGCMParmUInt32Set(&Msg.context, pCtx->uContextID);
2006 VbglHGCMParmUInt32Set(&Msg.pid, uPID);
2007 VbglHGCMParmUInt32Set(&Msg.status, uStatus);
2008 VbglHGCMParmUInt32Set(&Msg.flags, fFlags);
2009 VbglHGCMParmPtrSet(&Msg.data, pvData, cbData);
2010
2011 return VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
2012}
2013
2014
2015/**
2016 * Sends output (from stdout/stderr) from a running process.
2017 *
2018 * @returns VBox status code.
2019 ** @todo Docs!
2020 */
2021VBGLR3DECL(int) VbglR3GuestCtrlProcCbOutput(PVBGLR3GUESTCTRLCMDCTX pCtx,
2022 uint32_t uPID,uint32_t uHandle, uint32_t fFlags,
2023 void *pvData, uint32_t cbData)
2024{
2025 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
2026
2027 HGCMMsgProcOutput Msg;
2028 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, GUEST_MSG_EXEC_OUTPUT, 5);
2029 VbglHGCMParmUInt32Set(&Msg.context, pCtx->uContextID);
2030 VbglHGCMParmUInt32Set(&Msg.pid, uPID);
2031 VbglHGCMParmUInt32Set(&Msg.handle, uHandle);
2032 VbglHGCMParmUInt32Set(&Msg.flags, fFlags);
2033 VbglHGCMParmPtrSet(&Msg.data, pvData, cbData);
2034
2035 return VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
2036}
2037
2038
2039/**
2040 * Callback for reporting back the input status of a guest process to the host.
2041 *
2042 * @returns VBox status code.
2043 ** @todo Docs!
2044 */
2045VBGLR3DECL(int) VbglR3GuestCtrlProcCbStatusInput(PVBGLR3GUESTCTRLCMDCTX pCtx,
2046 uint32_t uPID, uint32_t uStatus,
2047 uint32_t fFlags, uint32_t cbWritten)
2048{
2049 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
2050
2051 HGCMMsgProcStatusInput Msg;
2052 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, GUEST_MSG_EXEC_INPUT_STATUS, 5);
2053 VbglHGCMParmUInt32Set(&Msg.context, pCtx->uContextID);
2054 VbglHGCMParmUInt32Set(&Msg.pid, uPID);
2055 VbglHGCMParmUInt32Set(&Msg.status, uStatus);
2056 VbglHGCMParmUInt32Set(&Msg.flags, fFlags);
2057 VbglHGCMParmUInt32Set(&Msg.written, cbWritten);
2058
2059 return VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
2060}
2061
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