VirtualBox

source: vbox/trunk/src/VBox/Main/include/GuestCtrlImplPrivate.h@ 106516

Last change on this file since 106516 was 106516, checked in by vboxsync, 5 weeks ago

Main,settings.h: Workarounds for a handful warnings about default copy constructors & default copy assignment operators due to user defined destructors. jiraref:VBP-1171

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 55.5 KB
Line 
1/* $Id: GuestCtrlImplPrivate.h 106516 2024-10-20 02:01:39Z vboxsync $ */
2/** @file
3 * Internal helpers/structures for guest control functionality.
4 */
5
6/*
7 * Copyright (C) 2011-2024 Oracle and/or its affiliates.
8 *
9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.virtualbox.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * SPDX-License-Identifier: GPL-3.0-only
26 */
27
28#ifndef MAIN_INCLUDED_GuestCtrlImplPrivate_h
29#define MAIN_INCLUDED_GuestCtrlImplPrivate_h
30#ifndef RT_WITHOUT_PRAGMA_ONCE
31# pragma once
32#endif
33
34#include "ConsoleImpl.h"
35#include "Global.h"
36
37#include <iprt/asm-mem.h>
38#include <iprt/asm.h>
39#include <iprt/env.h>
40#include <iprt/semaphore.h>
41#include <iprt/cpp/utils.h>
42
43#include <VBox/com/com.h>
44#include <VBox/com/ErrorInfo.h>
45#include <VBox/com/string.h>
46#include <VBox/com/VirtualBox.h>
47#include <VBox/err.h> /* VERR_GSTCTL_GUEST_ERROR */
48
49#include <map>
50#include <vector>
51
52using namespace com;
53
54#ifdef VBOX_WITH_GUEST_CONTROL
55# include <VBox/GuestHost/GuestControl.h>
56# include <VBox/HostServices/GuestControlSvc.h>
57using namespace guestControl;
58#endif
59
60/** Vector holding a process' CPU affinity. */
61typedef std::vector<LONG> ProcessAffinity;
62/** Vector holding process startup arguments. */
63typedef std::vector<Utf8Str> ProcessArguments;
64
65class GuestToolboxStreamBlock;
66class GuestSession;
67
68
69/**
70 * Simple structure mantaining guest credentials.
71 */
72struct GuestCredentials
73{
74 Utf8Str mUser;
75 Utf8Str mPassword;
76 Utf8Str mDomain;
77};
78
79
80/**
81 * Wrapper around the RTEnv API, unusable base class.
82 *
83 * @remarks Feel free to elevate this class to iprt/cpp/env.h as RTCEnv.
84 */
85class GuestEnvironmentBase
86{
87public:
88 /**
89 * Default constructor.
90 *
91 * The user must invoke one of the init methods before using the object.
92 */
93 GuestEnvironmentBase(void)
94 : m_hEnv(NIL_RTENV)
95 , m_cRefs(1)
96 , m_fFlags(0)
97 { }
98
99 /**
100 * Destructor.
101 */
102 virtual ~GuestEnvironmentBase(void)
103 {
104 Assert(m_cRefs <= 1);
105 int vrc = RTEnvDestroy(m_hEnv); AssertRC(vrc);
106 m_hEnv = NIL_RTENV;
107 }
108
109 /**
110 * Retains a reference to this object.
111 * @returns New reference count.
112 * @remarks Sharing an object is currently only safe if no changes are made to
113 * it because RTENV does not yet implement any locking. For the only
114 * purpose we need this, implementing IGuestProcess::environment by
115 * using IGuestSession::environmentBase, that's fine as the session
116 * base environment is immutable.
117 */
118 uint32_t retain(void)
119 {
120 uint32_t cRefs = ASMAtomicIncU32(&m_cRefs);
121 Assert(cRefs > 1); Assert(cRefs < _1M);
122 return cRefs;
123
124 }
125 /** Useful shortcut. */
126 uint32_t retainConst(void) const { return unconst(this)->retain(); }
127
128 /**
129 * Releases a reference to this object, deleting the object when reaching zero.
130 * @returns New reference count.
131 */
132 uint32_t release(void)
133 {
134 uint32_t cRefs = ASMAtomicDecU32(&m_cRefs);
135 Assert(cRefs < _1M);
136 if (cRefs == 0)
137 delete this;
138 return cRefs;
139 }
140
141 /** Useful shortcut. */
142 uint32_t releaseConst(void) const { return unconst(this)->retain(); }
143
144 /**
145 * Checks if the environment has been successfully initialized or not.
146 *
147 * @returns @c true if initialized, @c false if not.
148 */
149 bool isInitialized(void) const
150 {
151 return m_hEnv != NIL_RTENV;
152 }
153
154 /**
155 * Returns the variable count.
156 * @return Number of variables.
157 * @sa RTEnvCountEx
158 */
159 uint32_t count(void) const
160 {
161 return RTEnvCountEx(m_hEnv);
162 }
163
164 /**
165 * Deletes the environment change record entirely.
166 *
167 * The count() method will return zero after this call.
168 *
169 * @sa RTEnvReset
170 */
171 void reset(void)
172 {
173 int vrc = RTEnvReset(m_hEnv);
174 AssertRC(vrc);
175 }
176
177 /**
178 * Exports the environment change block as an array of putenv style strings.
179 *
180 *
181 * @returns VINF_SUCCESS or VERR_NO_MEMORY.
182 * @param pArray The output array.
183 */
184 int queryPutEnvArray(std::vector<com::Utf8Str> *pArray) const
185 {
186 uint32_t cVars = RTEnvCountEx(m_hEnv);
187 try
188 {
189 pArray->resize(cVars);
190 for (uint32_t iVar = 0; iVar < cVars; iVar++)
191 {
192 const char *psz = RTEnvGetByIndexRawEx(m_hEnv, iVar);
193 AssertReturn(psz, VERR_INTERNAL_ERROR_3); /* someone is racing us! */
194 (*pArray)[iVar] = psz;
195 }
196 return VINF_SUCCESS;
197 }
198 catch (std::bad_alloc &)
199 {
200 return VERR_NO_MEMORY;
201 }
202 }
203
204 /**
205 * Applies an array of putenv style strings.
206 *
207 * @returns IPRT status code.
208 * @param rArray The array with the putenv style strings.
209 * @param pidxError Where to return the index causing trouble on
210 * failure. Optional.
211 * @sa RTEnvPutEx
212 */
213 int applyPutEnvArray(const std::vector<com::Utf8Str> &rArray, size_t *pidxError = NULL)
214 {
215 size_t const cArray = rArray.size();
216 for (size_t i = 0; i < cArray; i++)
217 {
218 int vrc = RTEnvPutEx(m_hEnv, rArray[i].c_str());
219 if (RT_FAILURE(vrc))
220 {
221 if (pidxError)
222 *pidxError = i;
223 return vrc;
224 }
225 }
226 return VINF_SUCCESS;
227 }
228
229 /**
230 * Applies the changes from another environment to this.
231 *
232 * @returns IPRT status code.
233 * @param rChanges Reference to an environment which variables will be
234 * imported and, if it's a change record, schedule
235 * variable unsets will be applied.
236 * @sa RTEnvApplyChanges
237 */
238 int applyChanges(const GuestEnvironmentBase &rChanges)
239 {
240 return RTEnvApplyChanges(m_hEnv, rChanges.m_hEnv);
241 }
242
243 /**
244 * See RTEnvQueryUtf8Block for details.
245 * @returns IPRT status code.
246 * @param ppszzBlock Where to return the block pointer.
247 * @param pcbBlock Where to optionally return the block size.
248 * @sa RTEnvQueryUtf8Block
249 */
250 int queryUtf8Block(char **ppszzBlock, size_t *pcbBlock)
251 {
252 return RTEnvQueryUtf8Block(m_hEnv, true /*fSorted*/, ppszzBlock, pcbBlock);
253 }
254
255 /**
256 * Frees what queryUtf8Block returned, NULL ignored.
257 * @sa RTEnvFreeUtf8Block
258 */
259 static void freeUtf8Block(char *pszzBlock)
260 {
261 return RTEnvFreeUtf8Block(pszzBlock);
262 }
263
264 /**
265 * Applies a block on the format returned by queryUtf8Block.
266 *
267 * @returns IPRT status code.
268 * @param pszzBlock Pointer to the block.
269 * @param cbBlock The size of the block.
270 * @param fNoEqualMeansUnset Whether the lack of a '=' (equal) sign in a
271 * string means it should be unset (@c true), or if
272 * it means the variable should be defined with an
273 * empty value (@c false, the default).
274 * @todo move this to RTEnv!
275 */
276 int copyUtf8Block(const char *pszzBlock, size_t cbBlock, bool fNoEqualMeansUnset = false)
277 {
278 int vrc = VINF_SUCCESS;
279 while (cbBlock > 0 && *pszzBlock != '\0')
280 {
281 const char *pszEnd = (const char *)memchr(pszzBlock, '\0', cbBlock);
282 if (!pszEnd)
283 return VERR_BUFFER_UNDERFLOW;
284 int vrc2;
285 if (fNoEqualMeansUnset || strchr(pszzBlock, '='))
286 vrc2 = RTEnvPutEx(m_hEnv, pszzBlock);
287 else
288 vrc2 = RTEnvSetEx(m_hEnv, pszzBlock, "");
289 if (RT_FAILURE(vrc2) && RT_SUCCESS(vrc))
290 vrc = vrc2;
291
292 /* Advance. */
293 cbBlock -= pszEnd - pszzBlock;
294 if (cbBlock < 2)
295 return VERR_BUFFER_UNDERFLOW;
296 cbBlock--;
297 pszzBlock = pszEnd + 1;
298 }
299
300 /* The remainder must be zero padded. */
301 if (RT_SUCCESS(vrc))
302 {
303 if (ASMMemIsZero(pszzBlock, cbBlock))
304 return VINF_SUCCESS;
305 return VERR_TOO_MUCH_DATA;
306 }
307 return vrc;
308 }
309
310 /**
311 * Get an environment variable.
312 *
313 * @returns IPRT status code.
314 * @param rName The variable name.
315 * @param pValue Where to return the value.
316 * @sa RTEnvGetEx
317 */
318 int getVariable(const com::Utf8Str &rName, com::Utf8Str *pValue) const
319 {
320 size_t cchNeeded;
321 int vrc = RTEnvGetEx(m_hEnv, rName.c_str(), NULL, 0, &cchNeeded);
322 if ( RT_SUCCESS(vrc)
323 || vrc == VERR_BUFFER_OVERFLOW)
324 {
325 try
326 {
327 pValue->reserve(cchNeeded + 1);
328 vrc = RTEnvGetEx(m_hEnv, rName.c_str(), pValue->mutableRaw(), pValue->capacity(), NULL);
329 pValue->jolt();
330 }
331 catch (std::bad_alloc &)
332 {
333 vrc = VERR_NO_STR_MEMORY;
334 }
335 }
336 return vrc;
337 }
338
339 /**
340 * Checks if the given variable exists.
341 *
342 * @returns @c true if it exists, @c false if not or if it's an scheduled unset
343 * in a environment change record.
344 * @param rName The variable name.
345 * @sa RTEnvExistEx
346 */
347 bool doesVariableExist(const com::Utf8Str &rName) const
348 {
349 return RTEnvExistEx(m_hEnv, rName.c_str());
350 }
351
352 /**
353 * Set an environment variable.
354 *
355 * @returns IPRT status code.
356 * @param rName The variable name.
357 * @param rValue The value of the variable.
358 * @sa RTEnvSetEx
359 */
360 int setVariable(const com::Utf8Str &rName, const com::Utf8Str &rValue)
361 {
362 return RTEnvSetEx(m_hEnv, rName.c_str(), rValue.c_str());
363 }
364
365 /**
366 * Unset an environment variable.
367 *
368 * @returns IPRT status code.
369 * @param rName The variable name.
370 * @sa RTEnvUnsetEx
371 */
372 int unsetVariable(const com::Utf8Str &rName)
373 {
374 return RTEnvUnsetEx(m_hEnv, rName.c_str());
375 }
376
377protected:
378 /**
379 * Copy constructor.
380 * @throws HRESULT
381 */
382 GuestEnvironmentBase(const GuestEnvironmentBase &rThat, bool fChangeRecord, uint32_t fFlags = 0)
383 : m_hEnv(NIL_RTENV)
384 , m_cRefs(1)
385 , m_fFlags(fFlags)
386 {
387 int vrc = cloneCommon(rThat, fChangeRecord);
388 if (RT_FAILURE(vrc))
389 throw Global::vboxStatusCodeToCOM(vrc);
390 }
391
392 /**
393 * Common clone/copy method with type conversion abilities.
394 *
395 * @returns IPRT status code.
396 * @param rThat The object to clone.
397 * @param fChangeRecord Whether the this instance is a change record (true)
398 * or normal (false) environment.
399 */
400 int cloneCommon(const GuestEnvironmentBase &rThat, bool fChangeRecord)
401 {
402 int vrc = VINF_SUCCESS;
403 RTENV hNewEnv = NIL_RTENV;
404 if (rThat.m_hEnv != NIL_RTENV)
405 {
406 /*
407 * Clone it.
408 */
409 if (RTEnvIsChangeRecord(rThat.m_hEnv) == fChangeRecord)
410 vrc = RTEnvClone(&hNewEnv, rThat.m_hEnv);
411 else
412 {
413 /* Need to type convert it. */
414 if (fChangeRecord)
415 vrc = RTEnvCreateChangeRecordEx(&hNewEnv, rThat.m_fFlags);
416 else
417 vrc = RTEnvCreateEx(&hNewEnv, rThat.m_fFlags);
418 if (RT_SUCCESS(vrc))
419 {
420 vrc = RTEnvApplyChanges(hNewEnv, rThat.m_hEnv);
421 if (RT_FAILURE(vrc))
422 RTEnvDestroy(hNewEnv);
423 }
424 }
425 }
426 else
427 {
428 /*
429 * Create an empty one so the object works smoothly.
430 * (Relevant for GuestProcessStartupInfo and internal commands.)
431 */
432 if (fChangeRecord)
433 vrc = RTEnvCreateChangeRecordEx(&hNewEnv, rThat.m_fFlags);
434 else
435 vrc = RTEnvCreateEx(&hNewEnv, rThat.m_fFlags);
436 }
437 if (RT_SUCCESS(vrc))
438 {
439 RTEnvDestroy(m_hEnv);
440 m_hEnv = hNewEnv;
441 m_fFlags = rThat.m_fFlags;
442 }
443 return vrc;
444 }
445
446
447 /** The environment change record. */
448 RTENV m_hEnv;
449 /** Reference counter. */
450 uint32_t volatile m_cRefs;
451 /** RTENV_CREATE_F_XXX. */
452 uint32_t m_fFlags;
453};
454
455class GuestEnvironmentChanges;
456
457
458/**
459 * Wrapper around the RTEnv API for a normal environment.
460 */
461class GuestEnvironment : public GuestEnvironmentBase
462{
463public:
464 /**
465 * Default constructor.
466 *
467 * The user must invoke one of the init methods before using the object.
468 */
469 GuestEnvironment(void)
470 : GuestEnvironmentBase()
471 { }
472
473 /**
474 * Copy operator.
475 * @param rThat The object to copy.
476 * @throws HRESULT
477 */
478 GuestEnvironment(const GuestEnvironment &rThat)
479 : GuestEnvironmentBase(rThat, false /*fChangeRecord*/)
480 { }
481
482 /**
483 * Copy operator.
484 * @param rThat The object to copy.
485 * @throws HRESULT
486 */
487 GuestEnvironment(const GuestEnvironmentBase &rThat)
488 : GuestEnvironmentBase(rThat, false /*fChangeRecord*/)
489 { }
490
491 /**
492 * Initialize this as a normal environment block.
493 * @returns IPRT status code.
494 * @param fFlags RTENV_CREATE_F_XXX
495 */
496 int initNormal(uint32_t fFlags)
497 {
498 AssertReturn(m_hEnv == NIL_RTENV, VERR_WRONG_ORDER);
499 m_fFlags = fFlags;
500 return RTEnvCreateEx(&m_hEnv, fFlags);
501 }
502
503 /**
504 * Replaces this environemnt with that in @a rThat.
505 *
506 * @returns IPRT status code
507 * @param rThat The environment to copy. If it's a different type
508 * we'll convert the data to a normal environment block.
509 */
510 int copy(const GuestEnvironmentBase &rThat)
511 {
512 return cloneCommon(rThat, false /*fChangeRecord*/);
513 }
514
515 /**
516 * @copydoc GuestEnvironment::copy()
517 */
518 GuestEnvironment &operator=(const GuestEnvironmentBase &rThat)
519 {
520 int vrc = copy(rThat);
521 if (RT_FAILURE(vrc))
522 throw Global::vboxStatusCodeToCOM(vrc);
523 return *this;
524 }
525
526 /** @copydoc GuestEnvironment::copy() */
527 GuestEnvironment &operator=(const GuestEnvironment &rThat)
528 { return operator=((const GuestEnvironmentBase &)rThat); }
529
530 /** @copydoc GuestEnvironment::copy() */
531 GuestEnvironment &operator=(const GuestEnvironmentChanges &rThat)
532 { return operator=((const GuestEnvironmentBase &)rThat); }
533
534};
535
536
537/**
538 * Wrapper around the RTEnv API for a environment change record.
539 *
540 * This class is used as a record of changes to be applied to a different
541 * environment block (in VBoxService before launching a new process).
542 */
543class GuestEnvironmentChanges : public GuestEnvironmentBase
544{
545public:
546 /**
547 * Default constructor.
548 *
549 * The user must invoke one of the init methods before using the object.
550 */
551 GuestEnvironmentChanges(void)
552 : GuestEnvironmentBase()
553 { }
554
555 /**
556 * Copy operator.
557 * @param rThat The object to copy.
558 * @throws HRESULT
559 */
560 GuestEnvironmentChanges(const GuestEnvironmentChanges &rThat)
561 : GuestEnvironmentBase(rThat, true /*fChangeRecord*/)
562 { }
563
564 /**
565 * Copy operator.
566 * @param rThat The object to copy.
567 * @throws HRESULT
568 */
569 GuestEnvironmentChanges(const GuestEnvironmentBase &rThat)
570 : GuestEnvironmentBase(rThat, true /*fChangeRecord*/)
571 { }
572
573 /**
574 * Initialize this as a environment change record.
575 * @returns IPRT status code.
576 * @param fFlags RTENV_CREATE_F_XXX
577 */
578 int initChangeRecord(uint32_t fFlags)
579 {
580 AssertReturn(m_hEnv == NIL_RTENV, VERR_WRONG_ORDER);
581 m_fFlags = fFlags;
582 return RTEnvCreateChangeRecordEx(&m_hEnv, fFlags);
583 }
584
585 /**
586 * Replaces this environemnt with that in @a rThat.
587 *
588 * @returns IPRT status code
589 * @param rThat The environment to copy. If it's a different type
590 * we'll convert the data to a set of changes.
591 */
592 int copy(const GuestEnvironmentBase &rThat)
593 {
594 return cloneCommon(rThat, true /*fChangeRecord*/);
595 }
596
597 /**
598 * @copydoc GuestEnvironmentChanges::copy()
599 * @throws HRESULT
600 */
601 GuestEnvironmentChanges &operator=(const GuestEnvironmentBase &rThat)
602 {
603 int vrc = copy(rThat);
604 if (RT_FAILURE(vrc))
605 throw Global::vboxStatusCodeToCOM(vrc);
606 return *this;
607 }
608
609 /** @copydoc GuestEnvironmentChanges::copy()
610 * @throws HRESULT */
611 GuestEnvironmentChanges &operator=(const GuestEnvironmentChanges &rThat)
612 { return operator=((const GuestEnvironmentBase &)rThat); }
613
614 /** @copydoc GuestEnvironmentChanges::copy()
615 * @throws HRESULT */
616 GuestEnvironmentChanges &operator=(const GuestEnvironment &rThat)
617 { return operator=((const GuestEnvironmentBase &)rThat); }
618};
619
620/**
621 * Class for keeping guest error information.
622 */
623class GuestErrorInfo
624{
625public:
626
627 /**
628 * Enumeration for specifying the guest error type.
629 */
630 enum Type
631 {
632 /** Guest error is anonymous. Avoid this. */
633 Type_Anonymous = 0,
634 /** Guest error is from a guest session. */
635 Type_Session,
636 /** Guest error is from a guest process. */
637 Type_Process,
638 /** Guest error is from a guest file object. */
639 Type_File,
640 /** Guest error is from a guest directory object. */
641 Type_Directory,
642 /** Guest error is from a file system operation. */
643 Type_Fs,
644#ifdef VBOX_WITH_GSTCTL_TOOLBOX_SUPPORT
645 /** Guest error is from a the built-in toolbox "vbox_ls" command. */
646 Type_ToolLs,
647 /** Guest error is from a the built-in toolbox "vbox_rm" command. */
648 Type_ToolRm,
649 /** Guest error is from a the built-in toolbox "vbox_mkdir" command. */
650 Type_ToolMkDir,
651 /** Guest error is from a the built-in toolbox "vbox_mktemp" command. */
652 Type_ToolMkTemp,
653 /** Guest error is from a the built-in toolbox "vbox_stat" command. */
654 Type_ToolStat,
655#endif /* VBOX_WITH_GSTCTL_TOOLBOX_SUPPORT */
656 /** The usual 32-bit hack. */
657 Type_32BIT_HACK = 0x7fffffff
658 };
659
660 /**
661 * Initialization constructor.
662 *
663 * @param eType Error type to use.
664 * @param vrc VBox status code to use.
665 * @param pcszWhat Subject to use.
666 */
667 GuestErrorInfo(GuestErrorInfo::Type eType, int vrc, const char *pcszWhat)
668 {
669 int vrc2 = setV(eType, vrc, pcszWhat);
670 if (RT_FAILURE(vrc2))
671 throw vrc2;
672 }
673
674 /**
675 * Returns the VBox status code for this error.
676 *
677 * @returns VBox status code.
678 */
679 int getVrc(void) const { return mVrc; }
680
681 /**
682 * Returns the type of this error.
683 *
684 * @returns Error type.
685 */
686 Type getType(void) const { return mType; }
687
688 /**
689 * Returns the subject of this error.
690 *
691 * @returns Subject as a string.
692 */
693 Utf8Str getWhat(void) const { return mWhat; }
694
695 /**
696 * Sets the error information using a variable arguments list (va_list).
697 *
698 * @returns VBox status code.
699 * @param eType Error type to use.
700 * @param vrc VBox status code to use.
701 * @param pcszWhat Subject to use.
702 */
703 int setV(GuestErrorInfo::Type eType, int vrc, const char *pcszWhat)
704 {
705 mType = eType;
706 mVrc = vrc;
707 mWhat = pcszWhat;
708
709 return VINF_SUCCESS;
710 }
711
712protected:
713
714 /** Error type. */
715 Type mType;
716 /** VBox status (error) code. */
717 int mVrc;
718 /** Subject string related to this error. */
719 Utf8Str mWhat;
720};
721
722/**
723 * Structure for keeping all the relevant guest directory
724 * information around.
725 */
726struct GuestDirectoryOpenInfo
727{
728 GuestDirectoryOpenInfo(void)
729 : menmFilter(GSTCTLDIRFILTER_NONE)
730 , mFlags(GSTCTLDIR_F_NONE) { }
731
732 /** The directory path. */
733 Utf8Str mPath;
734 /** The filter to use (wildcard style). */
735 Utf8Str mFilter;
736 /** The filter option to use. */
737 GSTCTLDIRFILTER menmFilter;
738 /** Opening flags (of type GSTCTLDIR_F_XXX). */
739 uint32_t mFlags;
740};
741
742
743/**
744 * Structure for keeping all the relevant guest file
745 * information around.
746 */
747struct GuestFileOpenInfo
748{
749 GuestFileOpenInfo(void)
750 : mAccessMode((FileAccessMode_T)0)
751 , mOpenAction((FileOpenAction_T)0)
752 , mSharingMode((FileSharingMode_T)0)
753 , mCreationMode(0)
754 , mfOpenEx(0) { }
755
756 /**
757 * Validates a file open info.
758 *
759 * @returns \c true if valid, \c false if not.
760 */
761 bool IsValid(void) const
762 {
763 if (mfOpenEx) /** @todo Open flags not implemented yet. */
764 return false;
765
766 switch (mOpenAction)
767 {
768 case FileOpenAction_OpenExisting:
769 break;
770 case FileOpenAction_OpenOrCreate:
771 break;
772 case FileOpenAction_CreateNew:
773 break;
774 case FileOpenAction_CreateOrReplace:
775 break;
776 case FileOpenAction_OpenExistingTruncated:
777 {
778 if ( mAccessMode == FileAccessMode_ReadOnly
779 || mAccessMode == FileAccessMode_AppendOnly
780 || mAccessMode == FileAccessMode_AppendRead)
781 return false;
782 break;
783 }
784 case FileOpenAction_AppendOrCreate: /* Deprecated, do not use. */
785 break;
786 default:
787 AssertFailedReturn(false);
788 break;
789 }
790
791 return true; /** @todo Do we need more checks here? */
792 }
793
794 /** The filename. */
795 Utf8Str mFilename;
796 /** The file access mode. */
797 FileAccessMode_T mAccessMode;
798 /** The file open action. */
799 FileOpenAction_T mOpenAction;
800 /** The file sharing mode. */
801 FileSharingMode_T mSharingMode;
802 /** Octal creation mode. */
803 uint32_t mCreationMode;
804 /** Extended open flags (currently none defined). */
805 uint32_t mfOpenEx;
806};
807
808
809/**
810 * Helper class for guest file system operations.
811 */
812class GuestFs
813{
814 DECLARE_TRANSLATE_METHODS(GuestFs)
815
816private:
817
818 /* Not directly instantiable. */
819 GuestFs(void) { }
820
821public:
822
823 static Utf8Str guestErrorToString(const GuestErrorInfo &guestErrorInfo);
824};
825
826
827/**
828 * Structure representing information of a
829 * file system object.
830 */
831struct GuestFsObjData
832{
833 GuestFsObjData(const Utf8Str &strName = "")
834 : mType(FsObjType_Unknown)
835 , mObjectSize(0)
836 , mAllocatedSize(0)
837 , mAccessTime(0)
838 , mBirthTime(0)
839 , mChangeTime(0)
840 , mModificationTime(0)
841 , mUID(0)
842 , mGID(0)
843 , mNodeID(0)
844 , mNodeIDDevice(0)
845 , mNumHardLinks(0)
846 , mDeviceNumber(0)
847 , mGenerationID(0)
848 , mUserFlags(0) { mName = strName; }
849
850 void Init(const Utf8Str &strName) { mName = strName; }
851
852#ifdef VBOX_WITH_GSTCTL_TOOLBOX_AS_CMDS
853 int FromGuestDirEntryEx(PCGSTCTLDIRENTRYEX pDirEntryEx, const Utf8Str &strUser = "", const Utf8Str &strGroups = "");
854 int FromGuestFsObjInfo(PCGSTCTLFSOBJINFO pFsObjInfo, const Utf8Str &strUser = "", const Utf8Str &strGroups = "");
855#endif
856
857#ifdef VBOX_WITH_GSTCTL_TOOLBOX_SUPPORT
858 /** @name Helper functions to extract the data from a certin VBoxService tool's guest stream block.
859 * @{ */
860 int FromToolboxLs(const GuestToolboxStreamBlock &strmBlk, bool fLong);
861 int FromToolboxRm(const GuestToolboxStreamBlock &strmBlk);
862 int FromToolboxStat(const GuestToolboxStreamBlock &strmBlk);
863 int FromToolboxMkTemp(const GuestToolboxStreamBlock &strmBlk);
864 /** @} */
865#endif
866
867#ifdef VBOX_WITH_GSTCTL_TOOLBOX_SUPPORT
868 /** @name Static helper functions to work with time from stream block keys.
869 * @{ */
870 static PRTTIMESPEC TimeSpecFromKey(const GuestToolboxStreamBlock &strmBlk, const Utf8Str &strKey, PRTTIMESPEC pTimeSpec);
871 static int64_t UnixEpochNsFromKey(const GuestToolboxStreamBlock &strmBlk, const Utf8Str &strKey);
872 /** @} */
873#endif
874
875 /** @name helper functions to work with IPRT stuff.
876 * @{ */
877 RTFMODE GetFileMode(void) const;
878 /** @} */
879
880 Utf8Str mName;
881 FsObjType_T mType;
882 Utf8Str mFileAttrs;
883 int64_t mObjectSize;
884 int64_t mAllocatedSize;
885 int64_t mAccessTime;
886 int64_t mBirthTime;
887 int64_t mChangeTime;
888 int64_t mModificationTime;
889 Utf8Str mUserName;
890 int32_t mUID;
891 int32_t mGID;
892 Utf8Str mGroupName;
893 Utf8Str mACL;
894 int64_t mNodeID;
895 uint32_t mNodeIDDevice;
896 uint32_t mNumHardLinks;
897 uint32_t mDeviceNumber;
898 uint32_t mGenerationID;
899 uint32_t mUserFlags;
900};
901
902
903/**
904 * Structure for keeping all the relevant guest session
905 * startup parameters around.
906 */
907class GuestSessionStartupInfo
908{
909public:
910
911 GuestSessionStartupInfo(void)
912 : mID(UINT32_MAX)
913 , mIsInternal(false /* Non-internal session */)
914 , mOpenTimeoutMS(GSTCTL_DEFAULT_TIMEOUT_MS)
915 , mOpenFlags(0 /* No opening flags set */) { }
916
917 /** The session's friendly name. Optional. */
918 Utf8Str mName;
919 /** The session's unique ID. Used to encode a context ID.
920 * UINT32_MAX if not initialized. */
921 uint32_t mID;
922 /** Flag indicating if this is an internal session
923 * or not. Internal session are not accessible by
924 * public API clients. */
925 bool mIsInternal;
926 /** Timeout (in ms) used for opening the session. */
927 uint32_t mOpenTimeoutMS;
928 /** Session opening flags. */
929 uint32_t mOpenFlags;
930};
931
932
933/**
934 * Structure for keeping all the relevant guest process
935 * startup parameters around.
936 */
937class GuestProcessStartupInfo
938{
939public:
940
941 GuestProcessStartupInfo(void)
942 : mFlags(ProcessCreateFlag_None)
943 , mTimeoutMS(UINT32_MAX /* No timeout by default */)
944 , mPriority(ProcessPriority_Default)
945 , mAffinity(0) { }
946
947 /** The process' friendly name. */
948 Utf8Str mName;
949 /** The executable. */
950 Utf8Str mExecutable;
951 /** The working directory. Optional, can be empty if not used. */
952 Utf8Str mCwd;
953 /** Arguments vector (starting with argument \#0). */
954 ProcessArguments mArguments;
955 /** The process environment change record. */
956 GuestEnvironmentChanges mEnvironmentChanges;
957 /** Process creation flags. */
958 uint32_t mFlags;
959 /** Timeout (in ms) the process is allowed to run.
960 * Specify UINT32_MAX if no timeout (unlimited run time) is given. */
961 ULONG mTimeoutMS;
962 /** Process priority. */
963 ProcessPriority_T mPriority;
964 /** Process affinity. At the moment we
965 * only support 64 VCPUs. API and
966 * guest can do more already! */
967 uint64_t mAffinity;
968};
969
970/**
971 * Generic class for handling a guest process output (i.e. stdout / stderr) stream.
972 */
973class GuestProcessOutputStream
974{
975public:
976
977 GuestProcessOutputStream();
978
979 virtual ~GuestProcessOutputStream();
980
981public:
982
983 int AddData(const BYTE *pbData, size_t cbData);
984
985 void Destroy();
986
987#ifdef DEBUG
988 void Dump(const char *pszFile);
989#endif
990
991 size_t GetOffset(void) const { return m_offBuf; }
992
993 size_t GetSize(void) const { return m_cbUsed; }
994
995 const BYTE *GetData(void) const { return m_pbBuffer; }
996
997protected:
998
999 /** Maximum allowed size the stream buffer can grow to.
1000 * Defaults to 32 MB. */
1001 size_t m_cbMax;
1002 /** Currently allocated size of internal stream buffer. */
1003 size_t m_cbAllocated;
1004 /** Currently used size at m_offBuffer. */
1005 size_t m_cbUsed;
1006 /** Current byte offset within the internal stream buffer. */
1007 size_t m_offBuf;
1008 /** Internal stream buffer. */
1009 BYTE *m_pbBuffer;
1010};
1011
1012/**
1013 * Class representing the "value" side of a "key=value" pair.
1014 */
1015class GuestToolboxStreamValue
1016{
1017public:
1018
1019 GuestToolboxStreamValue(void) { }
1020 GuestToolboxStreamValue(const char *pszValue, size_t cwcValue = RTSTR_MAX)
1021 : mValue(pszValue, cwcValue) {}
1022
1023 GuestToolboxStreamValue(const GuestToolboxStreamValue& aThat)
1024 : mValue(aThat.mValue) { }
1025
1026 /** Copy assignment operator. */
1027 GuestToolboxStreamValue &operator=(GuestToolboxStreamValue const &a_rThat) RT_NOEXCEPT
1028 {
1029 mValue = a_rThat.mValue;
1030
1031 return *this;
1032 }
1033
1034 Utf8Str mValue;
1035};
1036
1037/** Map containing "key=value" pairs of a guest process stream. */
1038typedef std::pair< Utf8Str, GuestToolboxStreamValue > GuestCtrlStreamPair;
1039typedef std::map < Utf8Str, GuestToolboxStreamValue > GuestCtrlStreamPairMap;
1040typedef std::map < Utf8Str, GuestToolboxStreamValue >::iterator GuestCtrlStreamPairMapIter;
1041typedef std::map < Utf8Str, GuestToolboxStreamValue >::const_iterator GuestCtrlStreamPairMapIterConst;
1042
1043class GuestToolboxStream;
1044
1045/**
1046 * Class representing a block of stream pairs (key=value). Each block in a raw guest
1047 * output stream is separated by "\0\0", each pair is separated by "\0". The overall
1048 * end of a guest stream is marked by "\0\0\0\0".
1049 *
1050 * An empty stream block will be treated as being incomplete.
1051 *
1052 * Only used for the busybox-like toolbox commands within VBoxService.
1053 *
1054 * Deprecated, do not use anymore.
1055 */
1056class GuestToolboxStreamBlock
1057{
1058 friend GuestToolboxStream;
1059
1060public:
1061
1062 GuestToolboxStreamBlock(void);
1063 virtual ~GuestToolboxStreamBlock(void);
1064
1065#if RT_CPLUSPLUS_PREREQ(201100) /* VC2022: Excplit default copy constructor and copy assignment operator to avoid warnings. */
1066 GuestToolboxStreamBlock(GuestToolboxStreamBlock const &) = default;
1067 GuestToolboxStreamBlock &operator=(GuestToolboxStreamBlock const &) = default;
1068#endif
1069
1070public:
1071
1072 void Clear(void);
1073
1074#ifdef DEBUG
1075 void DumpToLog(void) const;
1076#endif
1077
1078 const char *GetString(const char *pszKey) const;
1079 size_t GetCount(void) const;
1080 int GetVrc(bool fSucceedIfNotFound = false) const;
1081 int GetInt64Ex(const char *pszKey, int64_t *piVal) const;
1082 int64_t GetInt64(const char *pszKey) const;
1083 int GetUInt32Ex(const char *pszKey, uint32_t *puVal) const;
1084 uint32_t GetUInt32(const char *pszKey, uint32_t uDefault = 0) const;
1085 int32_t GetInt32(const char *pszKey, int32_t iDefault = 0) const;
1086
1087 bool IsComplete(void) const { return !m_mapPairs.empty() && m_fComplete; }
1088 bool IsEmpty(void) const { return m_mapPairs.empty(); }
1089
1090 int SetValueEx(const char *pszKey, size_t cwcKey, const char *pszValue, size_t cwcValue, bool fOverwrite = false);
1091 int SetValue(const char *pszKey, const char *pszValue);
1092
1093protected:
1094
1095 /** Wheter the stream block is marked as complete.
1096 * An empty stream block is considered as incomplete. */
1097 bool m_fComplete;
1098 /** Map of stream pairs this block contains.*/
1099 GuestCtrlStreamPairMap m_mapPairs;
1100};
1101
1102/** Vector containing multiple allocated stream pair objects. */
1103typedef std::vector< GuestToolboxStreamBlock > GuestCtrlStreamObjects;
1104typedef std::vector< GuestToolboxStreamBlock >::iterator GuestCtrlStreamObjectsIter;
1105typedef std::vector< GuestToolboxStreamBlock >::const_iterator GuestCtrlStreamObjectsIterConst;
1106
1107/** Defines a single terminator as a single char. */
1108#define GUESTTOOLBOX_STRM_TERM '\0'
1109/** Defines a single terminator as a string. */
1110#define GUESTTOOLBOX_STRM_TERM_STR "\0"
1111/** Defines the termination sequence for a single key/value pair. */
1112#define GUESTTOOLBOX_STRM_TERM_PAIR_STR GUESTTOOLBOX_STRM_TERM_STR
1113/** Defines the termination sequence for a single stream block. */
1114#define GUESTTOOLBOX_STRM_TERM_BLOCK_STR GUESTTOOLBOX_STRM_TERM_STR GUESTTOOLBOX_STRM_TERM_STR
1115/** Defines the termination sequence for the stream. */
1116#define GUESTTOOLBOX_STRM_TERM_STREAM_STR GUESTTOOLBOX_STRM_TERM_STR GUESTTOOLBOX_STRM_TERM_STR GUESTTOOLBOX_STRM_TERM_STR GUESTTOOLBOX_STRM_TERM_STR
1117/** Defines how many consequtive terminators a key/value pair has. */
1118#define GUESTTOOLBOX_STRM_PAIR_TERM_CNT 1
1119/** Defines how many consequtive terminators a stream block has. */
1120#define GUESTTOOLBOX_STRM_BLK_TERM_CNT 2
1121/** Defines how many consequtive terminators a stream has. */
1122#define GUESTTOOLBOX_STRM_TERM_CNT 4
1123
1124/**
1125 * Class for parsing machine-readable guest process output by VBoxService'
1126 * toolbox commands ("vbox_ls", "vbox_stat" etc), aka "guest stream".
1127 *
1128 * Deprecated, do not use anymore.
1129 */
1130class GuestToolboxStream : public GuestProcessOutputStream
1131{
1132
1133public:
1134
1135 GuestToolboxStream();
1136
1137 virtual ~GuestToolboxStream();
1138
1139public:
1140
1141 size_t GetBlocks(void) const { return m_cBlocks; }
1142
1143 int ParseBlock(GuestToolboxStreamBlock &streamBlock);
1144
1145protected:
1146
1147 /** How many completed stream blocks already were processed. */
1148 size_t m_cBlocks;
1149};
1150
1151class Guest;
1152class Progress;
1153
1154class GuestWaitEventPayload
1155{
1156
1157public:
1158
1159 GuestWaitEventPayload(void)
1160 : uType(0)
1161 , cbData(0)
1162 , pvData(NULL)
1163 { }
1164
1165 /**
1166 * Initialization constructor.
1167 *
1168 * @throws VBox status code (vrc).
1169 *
1170 * @param uTypePayload Payload type to set.
1171 * @param pvPayload Pointer to payload data to set (deep copy).
1172 * @param cbPayload Size (in bytes) of payload data to set.
1173 */
1174 GuestWaitEventPayload(uint32_t uTypePayload, const void *pvPayload, uint32_t cbPayload)
1175 : uType(0)
1176 , cbData(0)
1177 , pvData(NULL)
1178 {
1179 int vrc = copyFrom(uTypePayload, pvPayload, cbPayload);
1180 if (RT_FAILURE(vrc))
1181 throw vrc;
1182 }
1183
1184 virtual ~GuestWaitEventPayload(void)
1185 {
1186 Clear();
1187 }
1188
1189 GuestWaitEventPayload& operator=(const GuestWaitEventPayload &that)
1190 {
1191 CopyFromDeep(that);
1192 return *this;
1193 }
1194
1195public:
1196
1197 void Clear(void)
1198 {
1199 if (pvData)
1200 {
1201 Assert(cbData);
1202 RTMemFree(pvData);
1203 cbData = 0;
1204 pvData = NULL;
1205 }
1206 uType = 0;
1207 }
1208
1209 int CopyFromDeep(const GuestWaitEventPayload &payload)
1210 {
1211 return copyFrom(payload.uType, payload.pvData, payload.cbData);
1212 }
1213
1214 const void* Raw(void) const { return pvData; }
1215
1216 size_t Size(void) const { return cbData; }
1217
1218 uint32_t Type(void) const { return uType; }
1219
1220 void* MutableRaw(void) { return pvData; }
1221
1222 Utf8Str ToString(void)
1223 {
1224 const char *pszStr = (const char *)pvData;
1225 size_t cbStr = cbData;
1226
1227 if (RT_FAILURE(RTStrValidateEncodingEx(pszStr, cbStr,
1228 RTSTR_VALIDATE_ENCODING_ZERO_TERMINATED | RTSTR_VALIDATE_ENCODING_EXACT_LENGTH)))
1229 {
1230 AssertFailed();
1231 return "";
1232 }
1233
1234 return Utf8Str(pszStr, cbStr);
1235 }
1236
1237 /**
1238 * Returns the payload as a vector of strings, validated.
1239 *
1240 * The payload data must contain the strings separated by a string zero terminator each,
1241 * ending with a separate zero terminator. Incomplete data will considered as invalid data.
1242 *
1243 * Example: 'foo\0bar\0baz\0\0'.
1244 *
1245 * @returns VBox status code.
1246 * @param vecStrings Where to return the vector of strings on success.
1247 */
1248 int ToStringVector(std::vector<Utf8Str> &vecStrings)
1249 {
1250 int vrc = VINF_SUCCESS;
1251
1252 vecStrings.clear();
1253
1254 const char *psz = (const char *)pvData;
1255 if (psz)
1256 {
1257 size_t cb = cbData;
1258 while (cb)
1259 {
1260 size_t const cch = strnlen(psz, cb);
1261 if (!cch)
1262 break;
1263 size_t const cbStr = RT_MIN(cb, cch + 1 /* String terminator */);
1264 vrc = RTStrValidateEncodingEx(psz, cbStr,
1265 RTSTR_VALIDATE_ENCODING_ZERO_TERMINATED | RTSTR_VALIDATE_ENCODING_EXACT_LENGTH);
1266 if (RT_FAILURE(vrc))
1267 break;
1268 try
1269 {
1270 vecStrings.push_back(Utf8Str(psz, cch));
1271 }
1272 catch (std::bad_alloc &)
1273 {
1274 AssertFailedBreakStmt(vrc = VERR_NO_MEMORY);
1275 }
1276 AssertBreakStmt(cb >= cbStr, vrc = VERR_INVALID_PARAMETER);
1277 cb -= cbStr;
1278 psz += cbStr;
1279 }
1280
1281 if (RT_SUCCESS(vrc))
1282 AssertStmt(cb <= 1 /* Ending terminator */, vrc = VERR_INVALID_PARAMETER);
1283 }
1284 return vrc;
1285 }
1286
1287protected:
1288
1289 int copyFrom(uint32_t uTypePayload, const void *pvPayload, uint32_t cbPayload)
1290 {
1291 if (cbPayload > _64K) /* Paranoia. */
1292 return VERR_TOO_MUCH_DATA;
1293
1294 Clear();
1295
1296 int vrc = VINF_SUCCESS;
1297 if (cbPayload)
1298 {
1299 pvData = RTMemAlloc(cbPayload);
1300 if (pvData)
1301 {
1302 uType = uTypePayload;
1303
1304 memcpy(pvData, pvPayload, cbPayload);
1305 cbData = cbPayload;
1306 }
1307 else
1308 vrc = VERR_NO_MEMORY;
1309 }
1310 else
1311 {
1312 uType = uTypePayload;
1313
1314 pvData = NULL;
1315 cbData = 0;
1316 }
1317
1318 return vrc;
1319 }
1320
1321protected:
1322
1323 /** Type of payload. */
1324 uint32_t uType;
1325 /** Size (in bytes) of payload. */
1326 uint32_t cbData;
1327 /** Pointer to actual payload data. */
1328 void *pvData;
1329};
1330
1331class GuestWaitEventBase
1332{
1333
1334protected:
1335
1336 GuestWaitEventBase(void);
1337 virtual ~GuestWaitEventBase(void);
1338
1339public:
1340
1341 uint32_t ContextID(void) const { return mCID; };
1342 int GuestResult(void) const { return mGuestRc; }
1343 bool HasGuestError(void) const { return mVrc == VERR_GSTCTL_GUEST_ERROR; }
1344 int Result(void) const { return mVrc; }
1345 GuestWaitEventPayload &Payload(void) { return mPayload; }
1346 int SignalInternal(int vrc, int vrcGuest, const GuestWaitEventPayload *pPayload);
1347 int Wait(RTMSINTERVAL uTimeoutMS);
1348
1349protected:
1350
1351 int Init(uint32_t uCID);
1352
1353protected:
1354
1355 /** Shutdown indicator. */
1356 bool mfAborted;
1357 /** Associated context ID (CID). */
1358 uint32_t mCID;
1359 /** The event semaphore for triggering the actual event. */
1360 RTSEMEVENT mEventSem;
1361 /** The event's overall result.
1362 * If set to VERR_GSTCTL_GUEST_ERROR, mGuestRc will contain the actual
1363 * error code from the guest side. */
1364 int mVrc;
1365 /** The event'S overall result from the guest side.
1366 * If used, mVrc must be set to VERR_GSTCTL_GUEST_ERROR. */
1367 int mGuestRc;
1368 /** The event's payload data. Optional. */
1369 GuestWaitEventPayload mPayload;
1370};
1371
1372/** List of public guest event types. */
1373typedef std::list < VBoxEventType_T > GuestEventTypes;
1374
1375class GuestWaitEvent : public GuestWaitEventBase
1376{
1377
1378public:
1379
1380 GuestWaitEvent(void);
1381 virtual ~GuestWaitEvent(void);
1382
1383public:
1384
1385 int Init(uint32_t uCID);
1386 int Init(uint32_t uCID, const GuestEventTypes &lstEvents);
1387 int Cancel(void);
1388 const ComPtr<IEvent> Event(void) const { return mEvent; }
1389 int SignalExternal(IEvent *pEvent);
1390 const GuestEventTypes &Types(void) const { return mEventTypes; }
1391 size_t TypeCount(void) const { return mEventTypes.size(); }
1392
1393protected:
1394
1395 /** List of public event types this event should
1396 * be signalled on. Optional. */
1397 GuestEventTypes mEventTypes;
1398 /** Pointer to the actual public event, if any. */
1399 ComPtr<IEvent> mEvent;
1400};
1401/** Map of pointers to guest events. The primary key
1402 * contains the context ID. */
1403typedef std::map < uint32_t, GuestWaitEvent* > GuestWaitEvents;
1404/** Map of wait events per public guest event. Nice for
1405 * faster lookups when signalling a whole event group. */
1406typedef std::map < VBoxEventType_T, GuestWaitEvents > GuestEventGroup;
1407
1408class GuestBase
1409{
1410
1411public:
1412
1413 GuestBase(void);
1414 virtual ~GuestBase(void);
1415
1416public:
1417
1418 /** Signals a wait event using a public guest event; also used for
1419 * for external event listeners. */
1420 int signalWaitEvent(VBoxEventType_T aType, IEvent *aEvent);
1421 /** Signals a wait event using a guest vrc. */
1422 int signalWaitEventInternal(PVBOXGUESTCTRLHOSTCBCTX pCbCtx, int vrcGuest, const GuestWaitEventPayload *pPayload);
1423 /** Signals a wait event without letting public guest events know,
1424 * extended director's cut version. */
1425 int signalWaitEventInternalEx(PVBOXGUESTCTRLHOSTCBCTX pCbCtx, int vrc, int vrcGuest, const GuestWaitEventPayload *pPayload);
1426
1427public:
1428
1429 int baseInit(void);
1430 void baseUninit(void);
1431 int cancelWaitEvents(void);
1432 int dispatchGeneric(PVBOXGUESTCTRLHOSTCBCTX pCtxCb, PVBOXGUESTCTRLHOSTCALLBACK pSvcCb);
1433 int generateContextID(uint32_t uSessionID, uint32_t uObjectID, uint32_t *puContextID);
1434 int registerWaitEvent(uint32_t uSessionID, uint32_t uObjectID, GuestWaitEvent **ppEvent);
1435 int registerWaitEventEx(uint32_t uSessionID, uint32_t uObjectID, const GuestEventTypes &lstEvents, GuestWaitEvent **ppEvent);
1436 int unregisterWaitEvent(GuestWaitEvent *pEvent);
1437 int waitForEvent(GuestWaitEvent *pEvent, uint32_t uTimeoutMS, VBoxEventType_T *pType, IEvent **ppEvent);
1438
1439public:
1440
1441 static FsObjType_T fileModeToFsObjType(RTFMODE fMode);
1442 static const char *fsObjTypeToStr(FsObjType_T enmType);
1443 static const char *pathStyleToStr(PathStyle_T enmPathStyle);
1444 static Utf8Str getErrorAsString(const Utf8Str &strAction, const GuestErrorInfo& guestErrorInfo);
1445 static Utf8Str getErrorAsString(const GuestErrorInfo &guestErrorInfo);
1446
1447protected:
1448
1449 /** Pointer to the console object. Needed
1450 * for HGCM (VMMDev) communication. */
1451 Console *mConsole;
1452 /** The next context ID counter component for this object. */
1453 uint32_t mNextContextID;
1454 /** Local listener for handling the waiting events
1455 * internally. */
1456 ComPtr<IEventListener> mLocalListener;
1457 /** Critical section for wait events access. */
1458 RTCRITSECT mWaitEventCritSect;
1459 /** Map of registered wait events per event group. */
1460 GuestEventGroup mWaitEventGroups;
1461 /** Map of registered wait events. */
1462 GuestWaitEvents mWaitEvents;
1463};
1464
1465/**
1466 * Virtual class (interface) for guest objects (processes, files, ...) --
1467 * contains all per-object callback management.
1468 */
1469class GuestObject : public GuestBase
1470{
1471 friend class GuestSession;
1472
1473public:
1474
1475 GuestObject(void);
1476 virtual ~GuestObject(void);
1477
1478public:
1479
1480 ULONG getObjectID(void) { return mObjectID; }
1481
1482protected:
1483
1484 /**
1485 * Called by IGuestSession when the session status has been changed.
1486 *
1487 * @returns VBox status code.
1488 * @param enmSessionStatus New session status.
1489 */
1490 virtual int i_onSessionStatusChange(GuestSessionStatus_T enmSessionStatus) = 0;
1491
1492 /**
1493 * Called by IGuestSession right before this object gets
1494 * unregistered (removed) from the public object list.
1495 */
1496 virtual int i_onUnregister(void) = 0;
1497
1498 /** Callback dispatcher -- must be implemented by the actual object. */
1499 virtual int i_callbackDispatcher(PVBOXGUESTCTRLHOSTCBCTX pCbCtx, PVBOXGUESTCTRLHOSTCALLBACK pSvcCb) = 0;
1500
1501protected:
1502
1503 int bindToSession(Console *pConsole, GuestSession *pSession, uint32_t uObjectID);
1504 int registerWaitEvent(const GuestEventTypes &lstEvents, GuestWaitEvent **ppEvent);
1505 int sendMessage(uint32_t uFunction, uint32_t cParms, PVBOXHGCMSVCPARM paParms);
1506
1507protected:
1508
1509 /** @name Common parameters for all derived objects. They have their own
1510 * mData structure to keep their specific data around.
1511 * @{ */
1512 /** Pointer to parent session. Per definition
1513 * this objects *always* lives shorter than the
1514 * parent.
1515 * @todo r=bird: When wanting to use mSession in the
1516 * IGuestProcess::getEnvironment() implementation I wanted to access
1517 * GuestSession::mData::mpBaseEnvironment. Seeing the comment in
1518 * GuestProcess::terminate() saying:
1519 * "Now only API clients still can hold references to it."
1520 * and recalling seeing similar things in VirtualBox.xidl or some such place,
1521 * I'm wondering how this "per definition" behavior is enforced. Is there any
1522 * GuestProcess:uninit() call or similar magic that invalidates objects that
1523 * GuestSession loses track of in place like GuestProcess::terminate() that I've
1524 * failed to spot?
1525 *
1526 * Please enlighten me.
1527 */
1528 GuestSession *mSession;
1529 /** The object ID -- must be unique for each guest
1530 * object and is encoded into the context ID. Must
1531 * be set manually when initializing the object.
1532 *
1533 * For guest processes this is the internal PID,
1534 * for guest files this is the internal file ID. */
1535 uint32_t mObjectID;
1536 /** @} */
1537};
1538
1539/** Returns the path separator based on \a a_enmPathStyle as a C-string. */
1540#define PATH_STYLE_SEP_STR(a_enmPathStyle) (a_enmPathStyle == PathStyle_DOS ? "\\" : "/")
1541#if defined(RT_OS_WINDOWS) || defined(RT_OS_OS2)
1542# define PATH_STYLE_NATIVE PathStyle_DOS
1543#else
1544# define PATH_STYLE_NATIVE PathStyle_UNIX
1545#endif
1546
1547/**
1548 * Class for handling guest / host path functions.
1549 */
1550class GuestPath
1551{
1552private:
1553
1554 /**
1555 * Default constructor.
1556 *
1557 * Not directly instantiable (yet).
1558 */
1559 GuestPath(void) { }
1560
1561public:
1562
1563 /** @name Static helper functions.
1564 * @{ */
1565 static int BuildDestinationPath(const Utf8Str &strSrcPath, PathStyle_T enmSrcPathStyle, Utf8Str &strDstPath, PathStyle_T enmDstPathStyle);
1566 static int Translate(Utf8Str &strPath, PathStyle_T enmSrcPathStyle, PathStyle_T enmDstPathStyle, bool fForce = false);
1567 /** @} */
1568};
1569
1570
1571/*********************************************************************************************************************************
1572 * Callback data structures. *
1573 * *
1574 * These structures make up the actual low level HGCM callback data sent from *
1575 * the guest back to the host. *
1576 ********************************************************************************************************************************/
1577
1578/**
1579 * The guest control callback data header. Must come first
1580 * on each callback structure defined below this struct.
1581 */
1582typedef struct CALLBACKDATA_HEADER
1583{
1584 /** Context ID to identify callback data. This is
1585 * and *must* be the very first parameter in this
1586 * structure to still be backwards compatible. */
1587 uint32_t uContextID;
1588} CALLBACKDATA_HEADER;
1589/** Pointer to a CALLBACKDATA_HEADER struct. */
1590typedef CALLBACKDATA_HEADER *PCALLBACKDATA_HEADER;
1591
1592/**
1593 * Host service callback data when a HGCM client disconnected.
1594 */
1595typedef struct CALLBACKDATA_CLIENT_DISCONNECTED
1596{
1597 /** Callback data header. */
1598 CALLBACKDATA_HEADER hdr;
1599} CALLBACKDATA_CLIENT_DISCONNECTED;
1600/** Pointer to a CALLBACKDATA_CLIENT_DISCONNECTED struct. */
1601typedef CALLBACKDATA_CLIENT_DISCONNECTED *PCALLBACKDATA_CLIENT_DISCONNECTED;
1602
1603/**
1604 * Host service callback data for a generic guest reply.
1605 */
1606typedef struct CALLBACKDATA_MSG_REPLY
1607{
1608 /** Callback data header. */
1609 CALLBACKDATA_HEADER hdr;
1610 /** Notification type. */
1611 uint32_t uType;
1612 /** Notification result. Note: int vs. uint32! */
1613 uint32_t rc;
1614 /** Pointer to optional payload. */
1615 void *pvPayload;
1616 /** Payload size (in bytes). */
1617 uint32_t cbPayload;
1618} CALLBACKDATA_MSG_REPLY;
1619/** Pointer to a CALLBACKDATA_MSG_REPLY struct. */
1620typedef CALLBACKDATA_MSG_REPLY *PCALLBACKDATA_MSG_REPLY;
1621
1622/**
1623 * Host service callback data for guest session notifications.
1624 */
1625typedef struct CALLBACKDATA_SESSION_NOTIFY
1626{
1627 /** Callback data header. */
1628 CALLBACKDATA_HEADER hdr;
1629 /** Notification type. */
1630 uint32_t uType;
1631 /** Notification result. Note: int vs. uint32! */
1632 uint32_t uResult;
1633} CALLBACKDATA_SESSION_NOTIFY;
1634/** Pointer to a CALLBACKDATA_SESSION_NOTIFY struct. */
1635typedef CALLBACKDATA_SESSION_NOTIFY *PCALLBACKDATA_SESSION_NOTIFY;
1636
1637/**
1638 * Host service callback data for guest process status notifications.
1639 */
1640typedef struct CALLBACKDATA_PROC_STATUS
1641{
1642 /** Callback data header. */
1643 CALLBACKDATA_HEADER hdr;
1644 /** The process ID (PID). */
1645 uint32_t uPID;
1646 /** The process status. */
1647 uint32_t uStatus;
1648 /** Optional flags, varies, based on u32Status. */
1649 uint32_t uFlags;
1650 /** Optional data buffer (not used atm). */
1651 void *pvData;
1652 /** Size of optional data buffer (not used atm). */
1653 uint32_t cbData;
1654} CALLBACKDATA_PROC_STATUS;
1655/** Pointer to a CALLBACKDATA_PROC_OUTPUT struct. */
1656typedef CALLBACKDATA_PROC_STATUS* PCALLBACKDATA_PROC_STATUS;
1657
1658/**
1659 * Host service callback data for guest process output notifications.
1660 */
1661typedef struct CALLBACKDATA_PROC_OUTPUT
1662{
1663 /** Callback data header. */
1664 CALLBACKDATA_HEADER hdr;
1665 /** The process ID (PID). */
1666 uint32_t uPID;
1667 /** The handle ID (stdout/stderr). */
1668 uint32_t uHandle;
1669 /** Optional flags (not used atm). */
1670 uint32_t uFlags;
1671 /** Optional data buffer. */
1672 void *pvData;
1673 /** Size (in bytes) of optional data buffer. */
1674 uint32_t cbData;
1675} CALLBACKDATA_PROC_OUTPUT;
1676/** Pointer to a CALLBACKDATA_PROC_OUTPUT struct. */
1677typedef CALLBACKDATA_PROC_OUTPUT *PCALLBACKDATA_PROC_OUTPUT;
1678
1679/**
1680 * Host service callback data guest process input notifications.
1681 */
1682typedef struct CALLBACKDATA_PROC_INPUT
1683{
1684 /** Callback data header. */
1685 CALLBACKDATA_HEADER hdr;
1686 /** The process ID (PID). */
1687 uint32_t uPID;
1688 /** Current input status. */
1689 uint32_t uStatus;
1690 /** Optional flags. */
1691 uint32_t uFlags;
1692 /** Size (in bytes) of processed input data. */
1693 uint32_t uProcessed;
1694} CALLBACKDATA_PROC_INPUT;
1695/** Pointer to a CALLBACKDATA_PROC_INPUT struct. */
1696typedef CALLBACKDATA_PROC_INPUT *PCALLBACKDATA_PROC_INPUT;
1697
1698/**
1699 * General guest file notification callback.
1700 */
1701typedef struct CALLBACKDATA_FILE_NOTIFY
1702{
1703 /** Callback data header. */
1704 CALLBACKDATA_HEADER hdr;
1705 /** Notification type. */
1706 uint32_t uType;
1707 /** IPRT result of overall operation. */
1708 uint32_t rc;
1709 union
1710 {
1711 struct
1712 {
1713 /** Guest file handle. */
1714 uint32_t uHandle;
1715 } open;
1716 /** Note: Close does not have any additional data (yet). */
1717 struct
1718 {
1719 /** How much data (in bytes) have been read. */
1720 uint32_t cbData;
1721 /** Actual data read (if any). */
1722 void *pvData;
1723 } read;
1724 struct
1725 {
1726 /** How much data (in bytes) have been successfully written. */
1727 uint32_t cbWritten;
1728 } write;
1729 struct
1730 {
1731 /** New file offset after successful seek. */
1732 uint64_t uOffActual;
1733 } seek;
1734 struct
1735 {
1736 /** New file offset after successful tell. */
1737 uint64_t uOffActual;
1738 } tell;
1739 struct
1740 {
1741 /** The new file siz.e */
1742 uint64_t cbSize;
1743 } SetSize;
1744 } u;
1745} CALLBACKDATA_FILE_NOTIFY;
1746/** Pointer to a CALLBACKDATA_FILE_NOTIFY, struct. */
1747typedef CALLBACKDATA_FILE_NOTIFY *PCALLBACKDATA_FILE_NOTIFY;
1748
1749/**
1750 * Callback data for a single GSTCTLDIRENTRYEX entry.
1751 */
1752typedef struct CALLBACKDATA_DIR_ENTRY
1753{
1754 /** Pointer to directory entry information. */
1755 PGSTCTLDIRENTRYEX pDirEntryEx;
1756 /** Size (in bytes) of directory entry information. */
1757 uint32_t cbDirEntryEx;
1758 /** Resolved user name.
1759 * This is the object owner for UNIX-y Oses. */
1760 char *pszUser;
1761 /** Size (in bytes) of \a pszUser. */
1762 uint32_t cbUser;
1763 /** Resolved user group(s). */
1764 char *pszGroups;
1765 /** Size (in bytes) of \a pszGroups. */
1766 uint32_t cbGroups;
1767} CALLBACKDATA_DIR_ENTRY;
1768/** Pointer to a CALLBACKDATA_DIR_ENTRY struct. */
1769typedef CALLBACKDATA_DIR_ENTRY *PCALLBACKDATA_DIR_ENTRY;
1770
1771/**
1772 * Callback data for guest directory operations.
1773 */
1774typedef struct CALLBACKDATA_DIR_NOTIFY
1775{
1776 /** Callback data header. */
1777 CALLBACKDATA_HEADER hdr;
1778 /** Notification type. */
1779 uint32_t uType;
1780 /** IPRT result of overall operation. */
1781 uint32_t rc;
1782 union
1783 {
1784 struct
1785 {
1786 /** Pointer to directory information. */
1787 PGSTCTLFSOBJINFO pObjInfo;
1788 } info;
1789 struct
1790 {
1791 /** Guest directory handle. */
1792 uint32_t uHandle;
1793 } open;
1794 /** Note: Close does not have any additional data (yet). */
1795 struct
1796 {
1797 /** Single entry read. */
1798 CALLBACKDATA_DIR_ENTRY Entry;
1799 } read;
1800 struct
1801 {
1802 /** Number of entries in \a paEntries. */
1803 uint32_t cEntries;
1804 /** Array of entries read. */
1805 CALLBACKDATA_DIR_ENTRY **paEntries;
1806 } list;
1807 } u;
1808} CALLBACKDATA_DIR_NOTIFY;
1809/** Pointer to a CALLBACKDATA_DIR_NOTIFY struct. */
1810typedef CALLBACKDATA_DIR_NOTIFY *PCALLBACKDATA_DIR_NOTIFY;
1811
1812/**
1813 * Callback data for guest file system operations.
1814 */
1815typedef struct CALLBACKDATA_FS_NOTIFY
1816{
1817 /** Callback data header. */
1818 CALLBACKDATA_HEADER hdr;
1819 /** Notification type (of type GUEST_FS_NOTIFYTYPE_XXX). */
1820 uint32_t uType;
1821 /** IPRT result of overall operation. */
1822 uint32_t rc;
1823 union
1824 {
1825 /** Holds information for GUEST_FS_NOTIFYTYPE_CREATE_TEMP. */
1826 struct
1827 {
1828 /** Path of created temporary file / directory. */
1829 char *pszPath;
1830 /** Size (in bytes) of \a pszPath. */
1831 uint32_t cbPath;
1832 } CreateTemp;
1833 /** Holds information for GUEST_FS_NOTIFYTYPE_QUERY_OBJ_INFO. */
1834 struct
1835 {
1836 GSTCTLFSOBJINFO objInfo;
1837 /** Resolved user name. */
1838 char *pszUser;
1839 /** Size (in bytes) of \a pszUser. */
1840 uint32_t cbUser;
1841 /** Resolved user group(s). */
1842 char *pszGroups;
1843 /** Size (in bytes) of \a pszGroups. */
1844 uint32_t cbGroups;
1845 } QueryObjInfo;
1846 /** Holds information for GUEST_FS_NOTIFYTYPE_QUERY_INFO. */
1847 struct
1848 {
1849 /** The actual filesystem information. */
1850 GSTCTLFSINFO fsInfo;
1851 } QueryInfo;
1852 } u;
1853} CALLBACKDATA_FS_NOTIFY;
1854/** Pointer to a CALLBACKDATA_FS_NOTIFY struct. */
1855typedef CALLBACKDATA_FS_NOTIFY *PCALLBACKDATA_FS_NOTIFY;
1856#endif /* !MAIN_INCLUDED_GuestCtrlImplPrivate_h */
1857
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