VirtualBox

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

Last change on this file since 99392 was 99392, checked in by vboxsync, 2 years ago

Guest Control: Completely revamped / overhauled the (now legacy) stream output parsing code and added lots of documentation to it. This way it should be a lot clearer what it's supposed to be doing.

Also, this now should fix some nasty bugs in that area we had in the past especially with some Linux guests (i.e. OL6), which sometimes send output data in a very unsteady manner.

Also overhauled the testcases while at it.

Luckily, this is all host-based code, so older Guest Additions also will benefit from this.

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

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