VirtualBox

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

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

Guest Control: Fixed assertions in VbglR3GuestCtrlGetShutdown(). bugref:9320

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 71.9 KB
Line 
1/* $Id: VBoxGuestR3LibGuestCtrl.cpp 84812 2020-06-12 09:44:32Z 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_DEFAULT_USER_LEN, GUESTPROCESS_DEFAULT_PASSWORD_LEN,
771 GUESTPROCESS_DEFAULT_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 == 2, VERR_INVALID_PARAMETER);
1039 AssertPtrReturn(pfAction, VERR_INVALID_POINTER);
1040
1041 int rc;
1042 do
1043 {
1044 HGCMMsgShutdown Msg;
1045 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, vbglR3GuestCtrlGetMsgFunctionNo(pCtx->uClientID), pCtx->uNumParms);
1046 VbglHGCMParmUInt32Set(&Msg.context, HOST_MSG_SHUTDOWN);
1047 VbglHGCMParmUInt32Set(&Msg.action, 0);
1048
1049 rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
1050 if (RT_SUCCESS(rc))
1051 {
1052 Msg.context.GetUInt32(&pCtx->uContextID);
1053 Msg.action.GetUInt32(pfAction);
1054 }
1055 } while (rc == VERR_INTERRUPTED && g_fVbglR3GuestCtrlHavePeekGetCancel);
1056 return rc;
1057}
1058
1059/**
1060 * Initializes a process startup info, extended version.
1061 *
1062 * @returns VBox status code.
1063 * @param pStartupInfo Process startup info to initializes.
1064 * @param cbCmd Size (in bytes) to use for the command buffer.
1065 * @param cbUser Size (in bytes) to use for the user name buffer.
1066 * @param cbPassword Size (in bytes) to use for the password buffer.
1067 * @param cbDomain Size (in bytes) to use for the domain buffer.
1068 * @param cbArgs Size (in bytes) to use for the arguments buffer.
1069 * @param cbEnv Size (in bytes) to use for the environment buffer.
1070 */
1071VBGLR3DECL(int) VbglR3GuestCtrlProcStartupInfoInitEx(PVBGLR3GUESTCTRLPROCSTARTUPINFO pStartupInfo,
1072 size_t cbCmd,
1073 size_t cbUser, size_t cbPassword, size_t cbDomain,
1074 size_t cbArgs, size_t cbEnv)
1075{
1076 AssertPtrReturn(pStartupInfo, VERR_INVALID_POINTER);
1077 AssertReturn(cbCmd, VERR_INVALID_PARAMETER);
1078 AssertReturn(cbUser, VERR_INVALID_PARAMETER);
1079 AssertReturn(cbPassword, VERR_INVALID_PARAMETER);
1080 AssertReturn(cbDomain, VERR_INVALID_PARAMETER);
1081 AssertReturn(cbArgs, VERR_INVALID_PARAMETER);
1082 AssertReturn(cbEnv, VERR_INVALID_PARAMETER);
1083
1084 RT_BZERO(pStartupInfo, sizeof(VBGLR3GUESTCTRLPROCSTARTUPINFO));
1085
1086#define ALLOC_STR(a_Str, a_cb) \
1087 if ((a_cb) > 0) \
1088 { \
1089 pStartupInfo->psz##a_Str = RTStrAlloc(a_cb); \
1090 AssertPtrBreak(pStartupInfo->psz##a_Str); \
1091 pStartupInfo->cb##a_Str = (uint32_t)a_cb; \
1092 }
1093
1094 do
1095 {
1096 ALLOC_STR(Cmd, cbCmd);
1097 ALLOC_STR(Args, cbArgs);
1098 ALLOC_STR(Env, cbEnv);
1099 ALLOC_STR(User, cbUser);
1100 ALLOC_STR(Password, cbPassword);
1101 ALLOC_STR(Domain, cbDomain);
1102
1103 return VINF_SUCCESS;
1104
1105 } while (0);
1106
1107#undef ALLOC_STR
1108
1109 VbglR3GuestCtrlProcStartupInfoDestroy(pStartupInfo);
1110 return VERR_NO_MEMORY;
1111}
1112
1113/**
1114 * Initializes a process startup info with default values.
1115 *
1116 * @param pStartupInfo Process startup info to initializes.
1117 */
1118VBGLR3DECL(int) VbglR3GuestCtrlProcStartupInfoInit(PVBGLR3GUESTCTRLPROCSTARTUPINFO pStartupInfo)
1119{
1120 return VbglR3GuestCtrlProcStartupInfoInitEx(pStartupInfo,
1121 GUESTPROCESS_DEFAULT_CMD_LEN,
1122 GUESTPROCESS_DEFAULT_USER_LEN /* Deprecated, now handled via session creation. */,
1123 GUESTPROCESS_DEFAULT_PASSWORD_LEN /* Ditto. */,
1124 GUESTPROCESS_DEFAULT_DOMAIN_LEN /* Ditto. */,
1125 GUESTPROCESS_DEFAULT_ARGS_LEN, GUESTPROCESS_DEFAULT_ENV_LEN);
1126}
1127
1128/**
1129 * Destroys a process startup info.
1130 *
1131 * @param pStartupInfo Process startup info to destroy.
1132 */
1133VBGLR3DECL(void) VbglR3GuestCtrlProcStartupInfoDestroy(PVBGLR3GUESTCTRLPROCSTARTUPINFO pStartupInfo)
1134{
1135 if (!pStartupInfo)
1136 return;
1137
1138 RTStrFree(pStartupInfo->pszCmd);
1139 RTStrFree(pStartupInfo->pszArgs);
1140 RTStrFree(pStartupInfo->pszEnv);
1141 RTStrFree(pStartupInfo->pszUser);
1142 RTStrFree(pStartupInfo->pszPassword);
1143 RTStrFree(pStartupInfo->pszDomain);
1144
1145 RT_BZERO(pStartupInfo, sizeof(VBGLR3GUESTCTRLPROCSTARTUPINFO));
1146}
1147
1148/**
1149 * Free's a process startup info.
1150 *
1151 * @param pStartupInfo Process startup info to free.
1152 * The pointer will not be valid anymore after return.
1153 */
1154VBGLR3DECL(void) VbglR3GuestCtrlProcStartupInfoFree(PVBGLR3GUESTCTRLPROCSTARTUPINFO pStartupInfo)
1155{
1156 if (!pStartupInfo)
1157 return;
1158
1159 VbglR3GuestCtrlProcStartupInfoDestroy(pStartupInfo);
1160
1161 RTMemFree(pStartupInfo);
1162 pStartupInfo = NULL;
1163}
1164
1165/**
1166 * Duplicates a process startup info.
1167 *
1168 * @returns Duplicated process startup info on success, or NULL on error.
1169 * @param pStartupInfo Process startup info to duplicate.
1170 */
1171VBGLR3DECL(PVBGLR3GUESTCTRLPROCSTARTUPINFO) VbglR3GuestCtrlProcStartupInfoDup(PVBGLR3GUESTCTRLPROCSTARTUPINFO pStartupInfo)
1172{
1173 AssertPtrReturn(pStartupInfo, NULL);
1174
1175 PVBGLR3GUESTCTRLPROCSTARTUPINFO pStartupInfoDup = (PVBGLR3GUESTCTRLPROCSTARTUPINFO)
1176 RTMemDup(pStartupInfo, sizeof(VBGLR3GUESTCTRLPROCSTARTUPINFO));
1177 if (pStartupInfoDup)
1178 {
1179 do
1180 {
1181 pStartupInfoDup->pszCmd = NULL;
1182 pStartupInfoDup->pszArgs = NULL;
1183 pStartupInfoDup->pszEnv = NULL;
1184 pStartupInfoDup->pszUser = NULL;
1185 pStartupInfoDup->pszPassword = NULL;
1186 pStartupInfoDup->pszDomain = NULL;
1187
1188#define DUP_STR(a_Str) \
1189 if (pStartupInfo->cb##a_Str) \
1190 { \
1191 pStartupInfoDup->psz##a_Str = (char *)RTStrDup(pStartupInfo->psz##a_Str); \
1192 AssertPtrBreak(pStartupInfoDup->psz##a_Str); \
1193 pStartupInfoDup->cb##a_Str = (uint32_t)strlen(pStartupInfoDup->psz##a_Str) + 1 /* Include terminator */; \
1194 }
1195
1196#define DUP_MEM(a_Str) \
1197 if (pStartupInfo->cb##a_Str) \
1198 { \
1199 pStartupInfoDup->psz##a_Str = (char *)RTMemDup(pStartupInfo->psz##a_Str, pStartupInfo->cb##a_Str); \
1200 AssertPtrBreak(pStartupInfoDup->psz##a_Str); \
1201 pStartupInfoDup->cb##a_Str = (uint32_t)pStartupInfo->cb##a_Str; \
1202 }
1203
1204 DUP_STR(Cmd);
1205 DUP_MEM(Args);
1206 DUP_MEM(Env);
1207 DUP_STR(User);
1208 DUP_STR(Password);
1209 DUP_STR(Domain);
1210
1211#undef DUP_STR
1212#undef DUP_MEM
1213
1214 return pStartupInfoDup;
1215
1216 } while (0); /* To use break macros above. */
1217
1218 VbglR3GuestCtrlProcStartupInfoFree(pStartupInfoDup);
1219 }
1220
1221 return NULL;
1222}
1223
1224/**
1225 * Retrieves a HOST_EXEC_CMD message.
1226 *
1227 * @returns VBox status code.
1228 * @param pCtx Guest control command context to use.
1229 * @param ppStartupInfo Where to store the allocated session startup info.
1230 * Needs to be free'd by VbglR3GuestCtrlProcStartupInfoFree().
1231 */
1232VBGLR3DECL(int) VbglR3GuestCtrlProcGetStart(PVBGLR3GUESTCTRLCMDCTX pCtx, PVBGLR3GUESTCTRLPROCSTARTUPINFO *ppStartupInfo)
1233{
1234 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1235 AssertPtrReturn(ppStartupInfo, VERR_INVALID_POINTER);
1236
1237 PVBGLR3GUESTCTRLPROCSTARTUPINFO pStartupInfo
1238 = (PVBGLR3GUESTCTRLPROCSTARTUPINFO)RTMemAlloc(sizeof(VBGLR3GUESTCTRLPROCSTARTUPINFO));
1239 if (!pStartupInfo)
1240 return VERR_NO_MEMORY;
1241
1242 int rc = VbglR3GuestCtrlProcStartupInfoInit(pStartupInfo);
1243 if (RT_FAILURE(rc))
1244 {
1245 VbglR3GuestCtrlProcStartupInfoFree(pStartupInfo);
1246 return rc;
1247 }
1248
1249 unsigned cRetries = 0;
1250 const unsigned cMaxRetries = 32; /* Should be enough for now. */
1251 const unsigned cGrowthFactor = 2; /* By how much the buffers will grow if they're too small yet. */
1252
1253 do
1254 {
1255 HGCMMsgProcExec Msg;
1256 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, vbglR3GuestCtrlGetMsgFunctionNo(pCtx->uClientID), pCtx->uNumParms);
1257 VbglHGCMParmUInt32Set(&Msg.context, HOST_MSG_EXEC_CMD);
1258 VbglHGCMParmPtrSet(&Msg.cmd, pStartupInfo->pszCmd, pStartupInfo->cbCmd);
1259 VbglHGCMParmUInt32Set(&Msg.flags, 0);
1260 VbglHGCMParmUInt32Set(&Msg.num_args, 0);
1261 VbglHGCMParmPtrSet(&Msg.args, pStartupInfo->pszArgs, pStartupInfo->cbArgs);
1262 VbglHGCMParmUInt32Set(&Msg.num_env, 0);
1263 VbglHGCMParmUInt32Set(&Msg.cb_env, 0);
1264 VbglHGCMParmPtrSet(&Msg.env, pStartupInfo->pszEnv, pStartupInfo->cbEnv);
1265 if (pCtx->uProtocol < 2)
1266 {
1267 VbglHGCMParmPtrSet(&Msg.u.v1.username, pStartupInfo->pszUser, pStartupInfo->cbUser);
1268 VbglHGCMParmPtrSet(&Msg.u.v1.password, pStartupInfo->pszPassword, pStartupInfo->cbPassword);
1269 VbglHGCMParmUInt32Set(&Msg.u.v1.timeout, 0);
1270 }
1271 else
1272 {
1273 VbglHGCMParmUInt32Set(&Msg.u.v2.timeout, 0);
1274 VbglHGCMParmUInt32Set(&Msg.u.v2.priority, 0);
1275 VbglHGCMParmUInt32Set(&Msg.u.v2.num_affinity, 0);
1276 VbglHGCMParmPtrSet(&Msg.u.v2.affinity, pStartupInfo->uAffinity, sizeof(pStartupInfo->uAffinity));
1277 }
1278
1279 rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
1280 if (RT_FAILURE(rc))
1281 {
1282 if ( rc == VERR_BUFFER_OVERFLOW
1283 && cRetries++ < cMaxRetries)
1284 {
1285#define GROW_STR(a_Str, a_cbMax) \
1286 pStartupInfo->psz##a_Str = (char *)RTMemRealloc(pStartupInfo->psz##a_Str, \
1287 RT_MAX(pStartupInfo->cb##a_Str * cGrowthFactor, a_cbMax)); \
1288 AssertPtrBreakStmt(pStartupInfo->psz##a_Str, VERR_NO_MEMORY); \
1289 pStartupInfo->cb##a_Str = RT_MAX(pStartupInfo->cb##a_Str * cGrowthFactor, a_cbMax);
1290
1291 GROW_STR(Cmd , GUESTPROCESS_MAX_CMD_LEN);
1292 GROW_STR(Args, GUESTPROCESS_MAX_ARGS_LEN);
1293 GROW_STR(Env, GUESTPROCESS_MAX_ENV_LEN);
1294
1295#undef GROW_STR
1296 }
1297 else
1298 break;
1299 }
1300 else
1301 {
1302 Msg.context.GetUInt32(&pCtx->uContextID);
1303 Msg.flags.GetUInt32(&pStartupInfo->fFlags);
1304 Msg.num_args.GetUInt32(&pStartupInfo->cArgs);
1305 Msg.num_env.GetUInt32(&pStartupInfo->cEnvVars);
1306 Msg.cb_env.GetUInt32(&pStartupInfo->cbEnv);
1307 if (pCtx->uProtocol < 2)
1308 Msg.u.v1.timeout.GetUInt32(&pStartupInfo->uTimeLimitMS);
1309 else
1310 {
1311 Msg.u.v2.timeout.GetUInt32(&pStartupInfo->uTimeLimitMS);
1312 Msg.u.v2.priority.GetUInt32(&pStartupInfo->uPriority);
1313 Msg.u.v2.num_affinity.GetUInt32(&pStartupInfo->cAffinity);
1314 }
1315 }
1316 } while (rc == VERR_INTERRUPTED && g_fVbglR3GuestCtrlHavePeekGetCancel);
1317
1318 if (RT_SUCCESS(rc))
1319 {
1320 *ppStartupInfo = pStartupInfo;
1321 }
1322 else
1323 VbglR3GuestCtrlProcStartupInfoFree(pStartupInfo);
1324
1325 LogFlowFuncLeaveRC(rc);
1326 return rc;
1327}
1328
1329/**
1330 * Allocates and gets host data, based on the message id.
1331 *
1332 * This will block until data becomes available.
1333 *
1334 * @returns VBox status code.
1335 ** @todo Docs!
1336 */
1337VBGLR3DECL(int) VbglR3GuestCtrlProcGetOutput(PVBGLR3GUESTCTRLCMDCTX pCtx,
1338 uint32_t *puPID, uint32_t *puHandle, uint32_t *pfFlags)
1339{
1340 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1341 AssertReturn(pCtx->uNumParms == 4, VERR_INVALID_PARAMETER);
1342
1343 AssertPtrReturn(puPID, VERR_INVALID_POINTER);
1344 AssertPtrReturn(puHandle, VERR_INVALID_POINTER);
1345 AssertPtrReturn(pfFlags, VERR_INVALID_POINTER);
1346
1347 int rc;
1348 do
1349 {
1350 HGCMMsgProcOutput Msg;
1351 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, vbglR3GuestCtrlGetMsgFunctionNo(pCtx->uClientID), pCtx->uNumParms);
1352 VbglHGCMParmUInt32Set(&Msg.context, HOST_MSG_EXEC_GET_OUTPUT);
1353 VbglHGCMParmUInt32Set(&Msg.pid, 0);
1354 VbglHGCMParmUInt32Set(&Msg.handle, 0);
1355 VbglHGCMParmUInt32Set(&Msg.flags, 0);
1356
1357 rc = VbglR3HGCMCall(&Msg.hdr, RT_UOFFSETOF(HGCMMsgProcOutput, data));
1358 if (RT_SUCCESS(rc))
1359 {
1360 Msg.context.GetUInt32(&pCtx->uContextID);
1361 Msg.pid.GetUInt32(puPID);
1362 Msg.handle.GetUInt32(puHandle);
1363 Msg.flags.GetUInt32(pfFlags);
1364 }
1365 } while (rc == VERR_INTERRUPTED && g_fVbglR3GuestCtrlHavePeekGetCancel);
1366 return rc;
1367}
1368
1369
1370/**
1371 * Retrieves the input data from host which then gets sent to the started
1372 * process (HOST_EXEC_SET_INPUT).
1373 *
1374 * This will block until data becomes available.
1375 */
1376VBGLR3DECL(int) VbglR3GuestCtrlProcGetInput(PVBGLR3GUESTCTRLCMDCTX pCtx,
1377 uint32_t *puPID, uint32_t *pfFlags,
1378 void *pvData, uint32_t cbData,
1379 uint32_t *pcbSize)
1380{
1381 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1382 AssertReturn(pCtx->uNumParms == 5, VERR_INVALID_PARAMETER);
1383
1384 AssertPtrReturn(puPID, VERR_INVALID_POINTER);
1385 AssertPtrReturn(pfFlags, VERR_INVALID_POINTER);
1386 AssertPtrReturn(pvData, VERR_INVALID_POINTER);
1387 AssertPtrReturn(pcbSize, VERR_INVALID_POINTER);
1388
1389 int rc;
1390 do
1391 {
1392 HGCMMsgProcInput Msg;
1393 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, vbglR3GuestCtrlGetMsgFunctionNo(pCtx->uClientID), pCtx->uNumParms);
1394 VbglHGCMParmUInt32Set(&Msg.context, HOST_MSG_EXEC_SET_INPUT);
1395 VbglHGCMParmUInt32Set(&Msg.pid, 0);
1396 VbglHGCMParmUInt32Set(&Msg.flags, 0);
1397 VbglHGCMParmPtrSet(&Msg.data, pvData, cbData);
1398 VbglHGCMParmUInt32Set(&Msg.size, 0);
1399
1400 rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
1401 if (RT_SUCCESS(rc))
1402 {
1403 Msg.context.GetUInt32(&pCtx->uContextID);
1404 Msg.pid.GetUInt32(puPID);
1405 Msg.flags.GetUInt32(pfFlags);
1406 Msg.size.GetUInt32(pcbSize);
1407 }
1408 } while (rc == VERR_INTERRUPTED && g_fVbglR3GuestCtrlHavePeekGetCancel);
1409
1410 if ( rc != VERR_TOO_MUCH_DATA
1411 || g_fVbglR3GuestCtrlHavePeekGetCancel)
1412 return rc;
1413 return VERR_BUFFER_OVERFLOW;
1414}
1415
1416
1417/**
1418 * Retrieves a HOST_DIR_REMOVE message.
1419 */
1420VBGLR3DECL(int) VbglR3GuestCtrlDirGetRemove(PVBGLR3GUESTCTRLCMDCTX pCtx,
1421 char *pszPath, uint32_t cbPath,
1422 uint32_t *pfFlags)
1423{
1424 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1425 AssertReturn(pCtx->uNumParms == 3, VERR_INVALID_PARAMETER);
1426
1427 AssertPtrReturn(pszPath, VERR_INVALID_POINTER);
1428 AssertReturn(cbPath, VERR_INVALID_PARAMETER);
1429 AssertPtrReturn(pfFlags, VERR_INVALID_POINTER);
1430
1431 int rc;
1432 do
1433 {
1434 HGCMMsgDirRemove Msg;
1435 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, vbglR3GuestCtrlGetMsgFunctionNo(pCtx->uClientID), pCtx->uNumParms);
1436 VbglHGCMParmUInt32Set(&Msg.context, HOST_MSG_DIR_REMOVE);
1437 VbglHGCMParmPtrSet(&Msg.path, pszPath, cbPath);
1438 VbglHGCMParmUInt32Set(&Msg.flags, 0);
1439
1440 rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
1441 if (RT_SUCCESS(rc))
1442 {
1443 Msg.context.GetUInt32(&pCtx->uContextID);
1444 Msg.flags.GetUInt32(pfFlags);
1445 }
1446 } while (rc == VERR_INTERRUPTED && g_fVbglR3GuestCtrlHavePeekGetCancel);
1447 return rc;
1448}
1449
1450
1451/**
1452 * Retrieves a HOST_FILE_OPEN message.
1453 */
1454VBGLR3DECL(int) VbglR3GuestCtrlFileGetOpen(PVBGLR3GUESTCTRLCMDCTX pCtx,
1455 char *pszFileName, uint32_t cbFileName,
1456 char *pszAccess, uint32_t cbAccess,
1457 char *pszDisposition, uint32_t cbDisposition,
1458 char *pszSharing, uint32_t cbSharing,
1459 uint32_t *puCreationMode,
1460 uint64_t *poffAt)
1461{
1462 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1463 AssertReturn(pCtx->uNumParms == 7, VERR_INVALID_PARAMETER);
1464
1465 AssertPtrReturn(pszFileName, VERR_INVALID_POINTER);
1466 AssertReturn(cbFileName, VERR_INVALID_PARAMETER);
1467 AssertPtrReturn(pszAccess, VERR_INVALID_POINTER);
1468 AssertReturn(cbAccess, VERR_INVALID_PARAMETER);
1469 AssertPtrReturn(pszDisposition, VERR_INVALID_POINTER);
1470 AssertReturn(cbDisposition, VERR_INVALID_PARAMETER);
1471 AssertPtrReturn(pszSharing, VERR_INVALID_POINTER);
1472 AssertReturn(cbSharing, VERR_INVALID_PARAMETER);
1473 AssertPtrReturn(puCreationMode, VERR_INVALID_POINTER);
1474 AssertPtrReturn(poffAt, VERR_INVALID_POINTER);
1475
1476 int rc;
1477 do
1478 {
1479 HGCMMsgFileOpen Msg;
1480 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, vbglR3GuestCtrlGetMsgFunctionNo(pCtx->uClientID), pCtx->uNumParms);
1481 VbglHGCMParmUInt32Set(&Msg.context, HOST_MSG_FILE_OPEN);
1482 VbglHGCMParmPtrSet(&Msg.filename, pszFileName, cbFileName);
1483 VbglHGCMParmPtrSet(&Msg.openmode, pszAccess, cbAccess);
1484 VbglHGCMParmPtrSet(&Msg.disposition, pszDisposition, cbDisposition);
1485 VbglHGCMParmPtrSet(&Msg.sharing, pszSharing, cbSharing);
1486 VbglHGCMParmUInt32Set(&Msg.creationmode, 0);
1487 VbglHGCMParmUInt64Set(&Msg.offset, 0);
1488
1489 rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
1490 if (RT_SUCCESS(rc))
1491 {
1492 Msg.context.GetUInt32(&pCtx->uContextID);
1493 Msg.creationmode.GetUInt32(puCreationMode);
1494 Msg.offset.GetUInt64(poffAt);
1495 }
1496 } while (rc == VERR_INTERRUPTED && g_fVbglR3GuestCtrlHavePeekGetCancel);
1497 return rc;
1498}
1499
1500
1501/**
1502 * Retrieves a HOST_FILE_CLOSE message.
1503 */
1504VBGLR3DECL(int) VbglR3GuestCtrlFileGetClose(PVBGLR3GUESTCTRLCMDCTX pCtx, uint32_t *puHandle)
1505{
1506 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1507
1508 AssertReturn(pCtx->uNumParms == 2, VERR_INVALID_PARAMETER);
1509 AssertPtrReturn(puHandle, VERR_INVALID_POINTER);
1510
1511 int rc;
1512 do
1513 {
1514 HGCMMsgFileClose Msg;
1515 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, vbglR3GuestCtrlGetMsgFunctionNo(pCtx->uClientID), pCtx->uNumParms);
1516 VbglHGCMParmUInt32Set(&Msg.context, HOST_MSG_FILE_CLOSE);
1517 VbglHGCMParmUInt32Set(&Msg.handle, 0);
1518
1519 rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
1520 if (RT_SUCCESS(rc))
1521 {
1522 Msg.context.GetUInt32(&pCtx->uContextID);
1523 Msg.handle.GetUInt32(puHandle);
1524 }
1525 } while (rc == VERR_INTERRUPTED && g_fVbglR3GuestCtrlHavePeekGetCancel);
1526 return rc;
1527}
1528
1529
1530/**
1531 * Retrieves a HOST_FILE_READ message.
1532 */
1533VBGLR3DECL(int) VbglR3GuestCtrlFileGetRead(PVBGLR3GUESTCTRLCMDCTX pCtx, uint32_t *puHandle, uint32_t *puToRead)
1534{
1535 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1536
1537 AssertReturn(pCtx->uNumParms == 3, VERR_INVALID_PARAMETER);
1538 AssertPtrReturn(puHandle, VERR_INVALID_POINTER);
1539 AssertPtrReturn(puToRead, VERR_INVALID_POINTER);
1540
1541 int rc;
1542 do
1543 {
1544 HGCMMsgFileRead Msg;
1545 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, vbglR3GuestCtrlGetMsgFunctionNo(pCtx->uClientID), pCtx->uNumParms);
1546 VbglHGCMParmUInt32Set(&Msg.context, HOST_MSG_FILE_READ);
1547 VbglHGCMParmUInt32Set(&Msg.handle, 0);
1548 VbglHGCMParmUInt32Set(&Msg.size, 0);
1549
1550 rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
1551 if (RT_SUCCESS(rc))
1552 {
1553 Msg.context.GetUInt32(&pCtx->uContextID);
1554 Msg.handle.GetUInt32(puHandle);
1555 Msg.size.GetUInt32(puToRead);
1556 }
1557 } while (rc == VERR_INTERRUPTED && g_fVbglR3GuestCtrlHavePeekGetCancel);
1558 return rc;
1559}
1560
1561
1562/**
1563 * Retrieves a HOST_FILE_READ_AT message.
1564 */
1565VBGLR3DECL(int) VbglR3GuestCtrlFileGetReadAt(PVBGLR3GUESTCTRLCMDCTX pCtx,
1566 uint32_t *puHandle, uint32_t *puToRead, uint64_t *poffAt)
1567{
1568 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1569
1570 AssertReturn(pCtx->uNumParms == 4, VERR_INVALID_PARAMETER);
1571 AssertPtrReturn(puHandle, VERR_INVALID_POINTER);
1572 AssertPtrReturn(puToRead, VERR_INVALID_POINTER);
1573
1574 int rc;
1575 do
1576 {
1577 HGCMMsgFileReadAt Msg;
1578 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, vbglR3GuestCtrlGetMsgFunctionNo(pCtx->uClientID), pCtx->uNumParms);
1579 VbglHGCMParmUInt32Set(&Msg.context, HOST_MSG_FILE_READ_AT);
1580 VbglHGCMParmUInt32Set(&Msg.handle, 0);
1581 VbglHGCMParmUInt64Set(&Msg.offset, 0);
1582 VbglHGCMParmUInt32Set(&Msg.size, 0);
1583
1584 rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
1585 if (RT_SUCCESS(rc))
1586 {
1587 Msg.context.GetUInt32(&pCtx->uContextID);
1588 Msg.handle.GetUInt32(puHandle);
1589 Msg.offset.GetUInt64(poffAt);
1590 Msg.size.GetUInt32(puToRead);
1591 }
1592 } while (rc == VERR_INTERRUPTED && g_fVbglR3GuestCtrlHavePeekGetCancel);
1593 return rc;
1594}
1595
1596
1597/**
1598 * Retrieves a HOST_FILE_WRITE message.
1599 */
1600VBGLR3DECL(int) VbglR3GuestCtrlFileGetWrite(PVBGLR3GUESTCTRLCMDCTX pCtx, uint32_t *puHandle,
1601 void *pvData, uint32_t cbData, uint32_t *pcbSize)
1602{
1603 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1604
1605 AssertReturn(pCtx->uNumParms == 4, VERR_INVALID_PARAMETER);
1606 AssertPtrReturn(puHandle, VERR_INVALID_POINTER);
1607 AssertPtrReturn(pvData, VERR_INVALID_POINTER);
1608 AssertReturn(cbData, VERR_INVALID_PARAMETER);
1609 AssertPtrReturn(pcbSize, VERR_INVALID_POINTER);
1610
1611 int rc;
1612 do
1613 {
1614 HGCMMsgFileWrite Msg;
1615 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, vbglR3GuestCtrlGetMsgFunctionNo(pCtx->uClientID), pCtx->uNumParms);
1616 VbglHGCMParmUInt32Set(&Msg.context, HOST_MSG_FILE_WRITE);
1617 VbglHGCMParmUInt32Set(&Msg.handle, 0);
1618 VbglHGCMParmPtrSet(&Msg.data, pvData, cbData);
1619 VbglHGCMParmUInt32Set(&Msg.size, 0);
1620
1621 rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
1622 if (RT_SUCCESS(rc))
1623 {
1624 Msg.context.GetUInt32(&pCtx->uContextID);
1625 Msg.handle.GetUInt32(puHandle);
1626 Msg.size.GetUInt32(pcbSize);
1627 }
1628 } while (rc == VERR_INTERRUPTED && g_fVbglR3GuestCtrlHavePeekGetCancel);
1629
1630 if ( rc != VERR_TOO_MUCH_DATA
1631 || g_fVbglR3GuestCtrlHavePeekGetCancel)
1632 return rc;
1633 return VERR_BUFFER_OVERFLOW;
1634}
1635
1636
1637/**
1638 * Retrieves a HOST_FILE_WRITE_AT message.
1639 */
1640VBGLR3DECL(int) VbglR3GuestCtrlFileGetWriteAt(PVBGLR3GUESTCTRLCMDCTX pCtx, uint32_t *puHandle,
1641 void *pvData, uint32_t cbData, uint32_t *pcbSize, uint64_t *poffAt)
1642{
1643 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1644
1645 AssertReturn(pCtx->uNumParms == 5, VERR_INVALID_PARAMETER);
1646 AssertPtrReturn(puHandle, VERR_INVALID_POINTER);
1647 AssertPtrReturn(pvData, VERR_INVALID_POINTER);
1648 AssertReturn(cbData, VERR_INVALID_PARAMETER);
1649 AssertPtrReturn(pcbSize, VERR_INVALID_POINTER);
1650
1651 int rc;
1652 do
1653 {
1654 HGCMMsgFileWriteAt Msg;
1655 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, vbglR3GuestCtrlGetMsgFunctionNo(pCtx->uClientID), pCtx->uNumParms);
1656 VbglHGCMParmUInt32Set(&Msg.context, HOST_MSG_FILE_WRITE_AT);
1657 VbglHGCMParmUInt32Set(&Msg.handle, 0);
1658 VbglHGCMParmPtrSet(&Msg.data, pvData, cbData);
1659 VbglHGCMParmUInt32Set(&Msg.size, 0);
1660 VbglHGCMParmUInt64Set(&Msg.offset, 0);
1661
1662 rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
1663 if (RT_SUCCESS(rc))
1664 {
1665 Msg.context.GetUInt32(&pCtx->uContextID);
1666 Msg.handle.GetUInt32(puHandle);
1667 Msg.size.GetUInt32(pcbSize);
1668 Msg.offset.GetUInt64(poffAt);
1669 }
1670 } while (rc == VERR_INTERRUPTED && g_fVbglR3GuestCtrlHavePeekGetCancel);
1671
1672 if ( rc != VERR_TOO_MUCH_DATA
1673 || g_fVbglR3GuestCtrlHavePeekGetCancel)
1674 return rc;
1675 return VERR_BUFFER_OVERFLOW;
1676}
1677
1678
1679/**
1680 * Retrieves a HOST_FILE_SEEK message.
1681 */
1682VBGLR3DECL(int) VbglR3GuestCtrlFileGetSeek(PVBGLR3GUESTCTRLCMDCTX pCtx,
1683 uint32_t *puHandle, uint32_t *puSeekMethod, uint64_t *poffAt)
1684{
1685 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1686
1687 AssertReturn(pCtx->uNumParms == 4, VERR_INVALID_PARAMETER);
1688 AssertPtrReturn(puHandle, VERR_INVALID_POINTER);
1689 AssertPtrReturn(puSeekMethod, VERR_INVALID_POINTER);
1690 AssertPtrReturn(poffAt, VERR_INVALID_POINTER);
1691
1692 int rc;
1693 do
1694 {
1695 HGCMMsgFileSeek Msg;
1696 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, vbglR3GuestCtrlGetMsgFunctionNo(pCtx->uClientID), pCtx->uNumParms);
1697 VbglHGCMParmUInt32Set(&Msg.context, HOST_MSG_FILE_SEEK);
1698 VbglHGCMParmUInt32Set(&Msg.handle, 0);
1699 VbglHGCMParmUInt32Set(&Msg.method, 0);
1700 VbglHGCMParmUInt64Set(&Msg.offset, 0);
1701
1702 rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
1703 if (RT_SUCCESS(rc))
1704 {
1705 Msg.context.GetUInt32(&pCtx->uContextID);
1706 Msg.handle.GetUInt32(puHandle);
1707 Msg.method.GetUInt32(puSeekMethod);
1708 Msg.offset.GetUInt64(poffAt);
1709 }
1710 } while (rc == VERR_INTERRUPTED && g_fVbglR3GuestCtrlHavePeekGetCancel);
1711 return rc;
1712}
1713
1714
1715/**
1716 * Retrieves a HOST_FILE_TELL message.
1717 */
1718VBGLR3DECL(int) VbglR3GuestCtrlFileGetTell(PVBGLR3GUESTCTRLCMDCTX pCtx, uint32_t *puHandle)
1719{
1720 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1721
1722 AssertReturn(pCtx->uNumParms == 2, VERR_INVALID_PARAMETER);
1723 AssertPtrReturn(puHandle, VERR_INVALID_POINTER);
1724
1725 int rc;
1726 do
1727 {
1728 HGCMMsgFileTell Msg;
1729 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, vbglR3GuestCtrlGetMsgFunctionNo(pCtx->uClientID), pCtx->uNumParms);
1730 VbglHGCMParmUInt32Set(&Msg.context, HOST_MSG_FILE_TELL);
1731 VbglHGCMParmUInt32Set(&Msg.handle, 0);
1732
1733 rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
1734 if (RT_SUCCESS(rc))
1735 {
1736 Msg.context.GetUInt32(&pCtx->uContextID);
1737 Msg.handle.GetUInt32(puHandle);
1738 }
1739 } while (rc == VERR_INTERRUPTED && g_fVbglR3GuestCtrlHavePeekGetCancel);
1740 return rc;
1741}
1742
1743
1744/**
1745 * Retrieves a HOST_FILE_SET_SIZE message.
1746 */
1747VBGLR3DECL(int) VbglR3GuestCtrlFileGetSetSize(PVBGLR3GUESTCTRLCMDCTX pCtx, uint32_t *puHandle, uint64_t *pcbNew)
1748{
1749 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1750
1751 AssertReturn(pCtx->uNumParms == 3, VERR_INVALID_PARAMETER);
1752 AssertPtrReturn(puHandle, VERR_INVALID_POINTER);
1753 AssertPtrReturn(pcbNew, VERR_INVALID_POINTER);
1754
1755 int rc;
1756 do
1757 {
1758 HGCMMsgFileSetSize Msg;
1759 VBGL_HGCM_HDR_INIT(&Msg.Hdr, pCtx->uClientID, vbglR3GuestCtrlGetMsgFunctionNo(pCtx->uClientID), pCtx->uNumParms);
1760 VbglHGCMParmUInt32Set(&Msg.id32Context, HOST_MSG_FILE_SET_SIZE);
1761 VbglHGCMParmUInt32Set(&Msg.id32Handle, 0);
1762 VbglHGCMParmUInt64Set(&Msg.cb64NewSize, 0);
1763
1764 rc = VbglR3HGCMCall(&Msg.Hdr, sizeof(Msg));
1765 if (RT_SUCCESS(rc))
1766 {
1767 Msg.id32Context.GetUInt32(&pCtx->uContextID);
1768 Msg.id32Handle.GetUInt32(puHandle);
1769 Msg.cb64NewSize.GetUInt64(pcbNew);
1770 }
1771 } while (rc == VERR_INTERRUPTED && g_fVbglR3GuestCtrlHavePeekGetCancel);
1772 return rc;
1773}
1774
1775
1776/**
1777 * Retrieves a HOST_EXEC_TERMINATE message.
1778 */
1779VBGLR3DECL(int) VbglR3GuestCtrlProcGetTerminate(PVBGLR3GUESTCTRLCMDCTX pCtx, uint32_t *puPID)
1780{
1781 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1782
1783 AssertReturn(pCtx->uNumParms == 2, VERR_INVALID_PARAMETER);
1784 AssertPtrReturn(puPID, VERR_INVALID_POINTER);
1785
1786 int rc;
1787 do
1788 {
1789 HGCMMsgProcTerminate Msg;
1790 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, vbglR3GuestCtrlGetMsgFunctionNo(pCtx->uClientID), pCtx->uNumParms);
1791 VbglHGCMParmUInt32Set(&Msg.context, HOST_MSG_EXEC_TERMINATE);
1792 VbglHGCMParmUInt32Set(&Msg.pid, 0);
1793
1794 rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
1795 if (RT_SUCCESS(rc))
1796 {
1797 Msg.context.GetUInt32(&pCtx->uContextID);
1798 Msg.pid.GetUInt32(puPID);
1799 }
1800 } while (rc == VERR_INTERRUPTED && g_fVbglR3GuestCtrlHavePeekGetCancel);
1801 return rc;
1802}
1803
1804
1805/**
1806 * Retrieves a HOST_EXEC_WAIT_FOR message.
1807 */
1808VBGLR3DECL(int) VbglR3GuestCtrlProcGetWaitFor(PVBGLR3GUESTCTRLCMDCTX pCtx,
1809 uint32_t *puPID, uint32_t *puWaitFlags, uint32_t *puTimeoutMS)
1810{
1811 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1812
1813 AssertReturn(pCtx->uNumParms == 5, VERR_INVALID_PARAMETER);
1814 AssertPtrReturn(puPID, VERR_INVALID_POINTER);
1815
1816 int rc;
1817 do
1818 {
1819 HGCMMsgProcWaitFor Msg;
1820 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, vbglR3GuestCtrlGetMsgFunctionNo(pCtx->uClientID), pCtx->uNumParms);
1821 VbglHGCMParmUInt32Set(&Msg.context, HOST_MSG_EXEC_WAIT_FOR);
1822 VbglHGCMParmUInt32Set(&Msg.pid, 0);
1823 VbglHGCMParmUInt32Set(&Msg.flags, 0);
1824 VbglHGCMParmUInt32Set(&Msg.timeout, 0);
1825
1826 rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
1827 if (RT_SUCCESS(rc))
1828 {
1829 Msg.context.GetUInt32(&pCtx->uContextID);
1830 Msg.pid.GetUInt32(puPID);
1831 Msg.flags.GetUInt32(puWaitFlags);
1832 Msg.timeout.GetUInt32(puTimeoutMS);
1833 }
1834 } while (rc == VERR_INTERRUPTED && g_fVbglR3GuestCtrlHavePeekGetCancel);
1835 return rc;
1836}
1837
1838
1839VBGLR3DECL(int) VbglR3GuestCtrlFileCbOpen(PVBGLR3GUESTCTRLCMDCTX pCtx,
1840 uint32_t uRc, uint32_t uFileHandle)
1841{
1842 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1843
1844 HGCMReplyFileNotify Msg;
1845 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, GUEST_MSG_FILE_NOTIFY, 4);
1846 VbglHGCMParmUInt32Set(&Msg.context, pCtx->uContextID);
1847 VbglHGCMParmUInt32Set(&Msg.type, GUEST_FILE_NOTIFYTYPE_OPEN);
1848 VbglHGCMParmUInt32Set(&Msg.rc, uRc);
1849 VbglHGCMParmUInt32Set(&Msg.u.open.handle, uFileHandle);
1850
1851 return VbglR3HGCMCall(&Msg.hdr, RT_UOFFSET_AFTER(HGCMReplyFileNotify, u.open));
1852}
1853
1854
1855VBGLR3DECL(int) VbglR3GuestCtrlFileCbClose(PVBGLR3GUESTCTRLCMDCTX pCtx,
1856 uint32_t uRc)
1857{
1858 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1859
1860 HGCMReplyFileNotify Msg;
1861 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, GUEST_MSG_FILE_NOTIFY, 3);
1862 VbglHGCMParmUInt32Set(&Msg.context, pCtx->uContextID);
1863 VbglHGCMParmUInt32Set(&Msg.type, GUEST_FILE_NOTIFYTYPE_CLOSE);
1864 VbglHGCMParmUInt32Set(&Msg.rc, uRc);
1865
1866 return VbglR3HGCMCall(&Msg.hdr, RT_UOFFSETOF(HGCMReplyFileNotify, u));
1867}
1868
1869
1870VBGLR3DECL(int) VbglR3GuestCtrlFileCbError(PVBGLR3GUESTCTRLCMDCTX pCtx, uint32_t uRc)
1871{
1872 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1873
1874 HGCMReplyFileNotify Msg;
1875 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, GUEST_MSG_FILE_NOTIFY, 3);
1876 VbglHGCMParmUInt32Set(&Msg.context, pCtx->uContextID);
1877 VbglHGCMParmUInt32Set(&Msg.type, GUEST_FILE_NOTIFYTYPE_ERROR);
1878 VbglHGCMParmUInt32Set(&Msg.rc, uRc);
1879
1880 return VbglR3HGCMCall(&Msg.hdr, RT_UOFFSETOF(HGCMReplyFileNotify, u));
1881}
1882
1883
1884VBGLR3DECL(int) VbglR3GuestCtrlFileCbRead(PVBGLR3GUESTCTRLCMDCTX pCtx,
1885 uint32_t uRc,
1886 void *pvData, uint32_t cbData)
1887{
1888 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1889
1890 HGCMReplyFileNotify Msg;
1891 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, GUEST_MSG_FILE_NOTIFY, 4);
1892 VbglHGCMParmUInt32Set(&Msg.context, pCtx->uContextID);
1893 VbglHGCMParmUInt32Set(&Msg.type, GUEST_FILE_NOTIFYTYPE_READ);
1894 VbglHGCMParmUInt32Set(&Msg.rc, uRc);
1895 VbglHGCMParmPtrSet(&Msg.u.read.data, pvData, cbData);
1896
1897 return VbglR3HGCMCall(&Msg.hdr, RT_UOFFSET_AFTER(HGCMReplyFileNotify, u.read));
1898}
1899
1900
1901VBGLR3DECL(int) VbglR3GuestCtrlFileCbReadOffset(PVBGLR3GUESTCTRLCMDCTX pCtx, uint32_t uRc,
1902 void *pvData, uint32_t cbData, int64_t offNew)
1903{
1904 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1905
1906 HGCMReplyFileNotify Msg;
1907 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, GUEST_MSG_FILE_NOTIFY, 5);
1908 VbglHGCMParmUInt32Set(&Msg.context, pCtx->uContextID);
1909 VbglHGCMParmUInt32Set(&Msg.type, GUEST_FILE_NOTIFYTYPE_READ_OFFSET);
1910 VbglHGCMParmUInt32Set(&Msg.rc, uRc);
1911 VbglHGCMParmPtrSet(&Msg.u.ReadOffset.pvData, pvData, cbData);
1912 VbglHGCMParmUInt64Set(&Msg.u.ReadOffset.off64New, (uint64_t)offNew);
1913
1914 return VbglR3HGCMCall(&Msg.hdr, RT_UOFFSET_AFTER(HGCMReplyFileNotify, u.ReadOffset));
1915}
1916
1917
1918VBGLR3DECL(int) VbglR3GuestCtrlFileCbWrite(PVBGLR3GUESTCTRLCMDCTX pCtx, uint32_t uRc, uint32_t cbWritten)
1919{
1920 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1921
1922 HGCMReplyFileNotify Msg;
1923 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, GUEST_MSG_FILE_NOTIFY, 4);
1924 VbglHGCMParmUInt32Set(&Msg.context, pCtx->uContextID);
1925 VbglHGCMParmUInt32Set(&Msg.type, GUEST_FILE_NOTIFYTYPE_WRITE);
1926 VbglHGCMParmUInt32Set(&Msg.rc, uRc);
1927 VbglHGCMParmUInt32Set(&Msg.u.write.written, cbWritten);
1928
1929 return VbglR3HGCMCall(&Msg.hdr, RT_UOFFSET_AFTER(HGCMReplyFileNotify, u.write));
1930}
1931
1932
1933VBGLR3DECL(int) VbglR3GuestCtrlFileCbWriteOffset(PVBGLR3GUESTCTRLCMDCTX pCtx, uint32_t uRc, uint32_t cbWritten, int64_t offNew)
1934{
1935 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1936
1937 HGCMReplyFileNotify Msg;
1938 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, GUEST_MSG_FILE_NOTIFY, 5);
1939 VbglHGCMParmUInt32Set(&Msg.context, pCtx->uContextID);
1940 VbglHGCMParmUInt32Set(&Msg.type, GUEST_FILE_NOTIFYTYPE_WRITE_OFFSET);
1941 VbglHGCMParmUInt32Set(&Msg.rc, uRc);
1942 VbglHGCMParmUInt32Set(&Msg.u.WriteOffset.cb32Written, cbWritten);
1943 VbglHGCMParmUInt64Set(&Msg.u.WriteOffset.off64New, (uint64_t)offNew);
1944
1945 return VbglR3HGCMCall(&Msg.hdr, RT_UOFFSET_AFTER(HGCMReplyFileNotify, u.WriteOffset));
1946}
1947
1948
1949VBGLR3DECL(int) VbglR3GuestCtrlFileCbSeek(PVBGLR3GUESTCTRLCMDCTX pCtx, uint32_t uRc, uint64_t offCurrent)
1950{
1951 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1952
1953 HGCMReplyFileNotify Msg;
1954 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, GUEST_MSG_FILE_NOTIFY, 4);
1955 VbglHGCMParmUInt32Set(&Msg.context, pCtx->uContextID);
1956 VbglHGCMParmUInt32Set(&Msg.type, GUEST_FILE_NOTIFYTYPE_SEEK);
1957 VbglHGCMParmUInt32Set(&Msg.rc, uRc);
1958 VbglHGCMParmUInt64Set(&Msg.u.seek.offset, offCurrent);
1959
1960 return VbglR3HGCMCall(&Msg.hdr, RT_UOFFSET_AFTER(HGCMReplyFileNotify, u.seek));
1961}
1962
1963
1964VBGLR3DECL(int) VbglR3GuestCtrlFileCbTell(PVBGLR3GUESTCTRLCMDCTX pCtx, uint32_t uRc, uint64_t offCurrent)
1965{
1966 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1967
1968 HGCMReplyFileNotify Msg;
1969 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, GUEST_MSG_FILE_NOTIFY, 4);
1970 VbglHGCMParmUInt32Set(&Msg.context, pCtx->uContextID);
1971 VbglHGCMParmUInt32Set(&Msg.type, GUEST_FILE_NOTIFYTYPE_TELL);
1972 VbglHGCMParmUInt32Set(&Msg.rc, uRc);
1973 VbglHGCMParmUInt64Set(&Msg.u.tell.offset, offCurrent);
1974
1975 return VbglR3HGCMCall(&Msg.hdr, RT_UOFFSET_AFTER(HGCMReplyFileNotify, u.tell));
1976}
1977
1978
1979VBGLR3DECL(int) VbglR3GuestCtrlFileCbSetSize(PVBGLR3GUESTCTRLCMDCTX pCtx, uint32_t uRc, uint64_t cbNew)
1980{
1981 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
1982
1983 HGCMReplyFileNotify Msg;
1984 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, GUEST_MSG_FILE_NOTIFY, 4);
1985 VbglHGCMParmUInt32Set(&Msg.context, pCtx->uContextID);
1986 VbglHGCMParmUInt32Set(&Msg.type, GUEST_FILE_NOTIFYTYPE_SET_SIZE);
1987 VbglHGCMParmUInt32Set(&Msg.rc, uRc);
1988 VbglHGCMParmUInt64Set(&Msg.u.SetSize.cb64Size, cbNew);
1989
1990 return VbglR3HGCMCall(&Msg.hdr, RT_UOFFSET_AFTER(HGCMReplyFileNotify, u.SetSize));
1991}
1992
1993
1994/**
1995 * Callback for reporting a guest process status (along with some other stuff) to the host.
1996 *
1997 * @returns VBox status code.
1998 ** @todo Docs!
1999 */
2000VBGLR3DECL(int) VbglR3GuestCtrlProcCbStatus(PVBGLR3GUESTCTRLCMDCTX pCtx,
2001 uint32_t uPID, uint32_t uStatus, uint32_t fFlags,
2002 void *pvData, uint32_t cbData)
2003{
2004 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
2005
2006 HGCMMsgProcStatus Msg;
2007 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, GUEST_MSG_EXEC_STATUS, 5);
2008 VbglHGCMParmUInt32Set(&Msg.context, pCtx->uContextID);
2009 VbglHGCMParmUInt32Set(&Msg.pid, uPID);
2010 VbglHGCMParmUInt32Set(&Msg.status, uStatus);
2011 VbglHGCMParmUInt32Set(&Msg.flags, fFlags);
2012 VbglHGCMParmPtrSet(&Msg.data, pvData, cbData);
2013
2014 return VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
2015}
2016
2017
2018/**
2019 * Sends output (from stdout/stderr) from a running process.
2020 *
2021 * @returns VBox status code.
2022 ** @todo Docs!
2023 */
2024VBGLR3DECL(int) VbglR3GuestCtrlProcCbOutput(PVBGLR3GUESTCTRLCMDCTX pCtx,
2025 uint32_t uPID,uint32_t uHandle, uint32_t fFlags,
2026 void *pvData, uint32_t cbData)
2027{
2028 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
2029
2030 HGCMMsgProcOutput Msg;
2031 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, GUEST_MSG_EXEC_OUTPUT, 5);
2032 VbglHGCMParmUInt32Set(&Msg.context, pCtx->uContextID);
2033 VbglHGCMParmUInt32Set(&Msg.pid, uPID);
2034 VbglHGCMParmUInt32Set(&Msg.handle, uHandle);
2035 VbglHGCMParmUInt32Set(&Msg.flags, fFlags);
2036 VbglHGCMParmPtrSet(&Msg.data, pvData, cbData);
2037
2038 return VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
2039}
2040
2041
2042/**
2043 * Callback for reporting back the input status of a guest process to the host.
2044 *
2045 * @returns VBox status code.
2046 ** @todo Docs!
2047 */
2048VBGLR3DECL(int) VbglR3GuestCtrlProcCbStatusInput(PVBGLR3GUESTCTRLCMDCTX pCtx,
2049 uint32_t uPID, uint32_t uStatus,
2050 uint32_t fFlags, uint32_t cbWritten)
2051{
2052 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
2053
2054 HGCMMsgProcStatusInput Msg;
2055 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, GUEST_MSG_EXEC_INPUT_STATUS, 5);
2056 VbglHGCMParmUInt32Set(&Msg.context, pCtx->uContextID);
2057 VbglHGCMParmUInt32Set(&Msg.pid, uPID);
2058 VbglHGCMParmUInt32Set(&Msg.status, uStatus);
2059 VbglHGCMParmUInt32Set(&Msg.flags, fFlags);
2060 VbglHGCMParmUInt32Set(&Msg.written, cbWritten);
2061
2062 return VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
2063}
2064
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