VirtualBox

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

Last change on this file since 93115 was 93115, checked in by vboxsync, 3 years ago

scm --update-copyright-year

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