VirtualBox

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

Last change on this file since 71783 was 71783, checked in by vboxsync, 7 years ago

Build fix (forgot a file).

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 34.4 KB
Line 
1/* $Id: GuestCtrlImplPrivate.h 71783 2018-04-09 15:54:39Z vboxsync $ */
2/** @file
3 * Internal helpers/structures for guest control functionality.
4 */
5
6/*
7 * Copyright (C) 2011-2018 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18#ifndef ____H_GUESTIMPLPRIVATE
19#define ____H_GUESTIMPLPRIVATE
20
21#include "ConsoleImpl.h"
22#include "Global.h"
23
24#include <iprt/asm.h>
25#include <iprt/env.h>
26#include <iprt/semaphore.h>
27#include <iprt/cpp/utils.h>
28
29#include <VBox/com/com.h>
30#include <VBox/com/ErrorInfo.h>
31#include <VBox/com/string.h>
32#include <VBox/com/VirtualBox.h>
33
34#include <map>
35#include <vector>
36
37using namespace com;
38
39#ifdef VBOX_WITH_GUEST_CONTROL
40# include <VBox/GuestHost/GuestControl.h>
41# include <VBox/HostServices/GuestControlSvc.h>
42using namespace guestControl;
43#endif
44
45/** Vector holding a process' CPU affinity. */
46typedef std::vector <LONG> ProcessAffinity;
47/** Vector holding process startup arguments. */
48typedef std::vector <Utf8Str> ProcessArguments;
49
50class GuestProcessStreamBlock;
51class GuestSession;
52
53
54/**
55 * Simple structure mantaining guest credentials.
56 */
57struct GuestCredentials
58{
59 Utf8Str mUser;
60 Utf8Str mPassword;
61 Utf8Str mDomain;
62};
63
64
65
66/**
67 * Wrapper around the RTEnv API, unusable base class.
68 *
69 * @remarks Feel free to elevate this class to iprt/cpp/env.h as RTCEnv.
70 */
71class GuestEnvironmentBase
72{
73public:
74 /**
75 * Default constructor.
76 *
77 * The user must invoke one of the init methods before using the object.
78 */
79 GuestEnvironmentBase(void)
80 : m_hEnv(NIL_RTENV)
81 , m_cRefs(1)
82 { }
83
84 /**
85 * Destructor.
86 */
87 virtual ~GuestEnvironmentBase(void)
88 {
89 Assert(m_cRefs <= 1);
90 int rc = RTEnvDestroy(m_hEnv); AssertRC(rc);
91 m_hEnv = NIL_RTENV;
92 }
93
94 /**
95 * Retains a reference to this object.
96 * @returns New reference count.
97 * @remarks Sharing an object is currently only safe if no changes are made to
98 * it because RTENV does not yet implement any locking. For the only
99 * purpose we need this, implementing IGuestProcess::environment by
100 * using IGuestSession::environmentBase, that's fine as the session
101 * base environment is immutable.
102 */
103 uint32_t retain(void)
104 {
105 uint32_t cRefs = ASMAtomicIncU32(&m_cRefs);
106 Assert(cRefs > 1); Assert(cRefs < _1M);
107 return cRefs;
108
109 }
110 /** Useful shortcut. */
111 uint32_t retainConst(void) const { return unconst(this)->retain(); }
112
113 /**
114 * Releases a reference to this object, deleting the object when reaching zero.
115 * @returns New reference count.
116 */
117 uint32_t release(void)
118 {
119 uint32_t cRefs = ASMAtomicDecU32(&m_cRefs);
120 Assert(cRefs < _1M);
121 if (cRefs == 0)
122 delete this;
123 return cRefs;
124 }
125
126 /** Useful shortcut. */
127 uint32_t releaseConst(void) const { return unconst(this)->retain(); }
128
129 /**
130 * Checks if the environment has been successfully initialized or not.
131 *
132 * @returns @c true if initialized, @c false if not.
133 */
134 bool isInitialized(void) const
135 {
136 return m_hEnv != NIL_RTENV;
137 }
138
139 /**
140 * Returns the variable count.
141 * @return Number of variables.
142 * @sa RTEnvCountEx
143 */
144 uint32_t count(void) const
145 {
146 return RTEnvCountEx(m_hEnv);
147 }
148
149 /**
150 * Deletes the environment change record entirely.
151 *
152 * The count() method will return zero after this call.
153 *
154 * @sa RTEnvReset
155 */
156 void reset(void)
157 {
158 int rc = RTEnvReset(m_hEnv);
159 AssertRC(rc);
160 }
161
162 /**
163 * Exports the environment change block as an array of putenv style strings.
164 *
165 *
166 * @returns VINF_SUCCESS or VERR_NO_MEMORY.
167 * @param pArray The output array.
168 */
169 int queryPutEnvArray(std::vector<com::Utf8Str> *pArray) const
170 {
171 uint32_t cVars = RTEnvCountEx(m_hEnv);
172 try
173 {
174 pArray->resize(cVars);
175 for (uint32_t iVar = 0; iVar < cVars; iVar++)
176 {
177 const char *psz = RTEnvGetByIndexRawEx(m_hEnv, iVar);
178 AssertReturn(psz, VERR_INTERNAL_ERROR_3); /* someone is racing us! */
179 (*pArray)[iVar] = psz;
180 }
181 return VINF_SUCCESS;
182 }
183 catch (std::bad_alloc &)
184 {
185 return VERR_NO_MEMORY;
186 }
187 }
188
189 /**
190 * Applies an array of putenv style strings.
191 *
192 * @returns IPRT status code.
193 * @param rArray The array with the putenv style strings.
194 * @sa RTEnvPutEnvEx
195 */
196 int applyPutEnvArray(const std::vector<com::Utf8Str> &rArray)
197 {
198 size_t cArray = rArray.size();
199 for (size_t i = 0; i < cArray; i++)
200 {
201 int rc = RTEnvPutEx(m_hEnv, rArray[i].c_str());
202 if (RT_FAILURE(rc))
203 return rc;
204 }
205 return VINF_SUCCESS;
206 }
207
208 /**
209 * Applies the changes from another environment to this.
210 *
211 * @returns IPRT status code.
212 * @param rChanges Reference to an environment which variables will be
213 * imported and, if it's a change record, schedule
214 * variable unsets will be applied.
215 * @sa RTEnvApplyChanges
216 */
217 int applyChanges(const GuestEnvironmentBase &rChanges)
218 {
219 return RTEnvApplyChanges(m_hEnv, rChanges.m_hEnv);
220 }
221
222
223 /**
224 * See RTEnvQueryUtf8Block for details.
225 * @returns IPRT status code.
226 * @param ppszzBlock Where to return the block pointer.
227 * @param pcbBlock Where to optionally return the block size.
228 * @sa RTEnvQueryUtf8Block
229 */
230 int queryUtf8Block(char **ppszzBlock, size_t *pcbBlock)
231 {
232 return RTEnvQueryUtf8Block(m_hEnv, true /*fSorted*/, ppszzBlock, pcbBlock);
233 }
234
235 /**
236 * Frees what queryUtf8Block returned, NULL ignored.
237 * @sa RTEnvFreeUtf8Block
238 */
239 static void freeUtf8Block(char *pszzBlock)
240 {
241 return RTEnvFreeUtf8Block(pszzBlock);
242 }
243
244 /**
245 * Applies a block on the format returned by queryUtf8Block.
246 *
247 * @returns IPRT status code.
248 * @param pszzBlock Pointer to the block.
249 * @param cbBlock The size of the block.
250 * @param fNoEqualMeansUnset Whether the lack of a '=' (equal) sign in a
251 * string means it should be unset (@c true), or if
252 * it means the variable should be defined with an
253 * empty value (@c false, the default).
254 * @todo move this to RTEnv!
255 */
256 int copyUtf8Block(const char *pszzBlock, size_t cbBlock, bool fNoEqualMeansUnset = false)
257 {
258 int rc = VINF_SUCCESS;
259 while (cbBlock > 0 && *pszzBlock != '\0')
260 {
261 const char *pszEnd = (const char *)memchr(pszzBlock, '\0', cbBlock);
262 if (!pszEnd)
263 return VERR_BUFFER_UNDERFLOW;
264 int rc2;
265 if (fNoEqualMeansUnset || strchr(pszzBlock, '='))
266 rc2 = RTEnvPutEx(m_hEnv, pszzBlock);
267 else
268 rc2 = RTEnvSetEx(m_hEnv, pszzBlock, "");
269 if (RT_FAILURE(rc2) && RT_SUCCESS(rc))
270 rc = rc2;
271
272 /* Advance. */
273 cbBlock -= pszEnd - pszzBlock;
274 if (cbBlock < 2)
275 return VERR_BUFFER_UNDERFLOW;
276 cbBlock--;
277 pszzBlock = pszEnd + 1;
278 }
279
280 /* The remainder must be zero padded. */
281 if (RT_SUCCESS(rc))
282 {
283 if (ASMMemIsZero(pszzBlock, cbBlock))
284 return VINF_SUCCESS;
285 return VERR_TOO_MUCH_DATA;
286 }
287 return rc;
288 }
289
290
291 /**
292 * Get an environment variable.
293 *
294 * @returns IPRT status code.
295 * @param rName The variable name.
296 * @param pValue Where to return the value.
297 * @sa RTEnvGetEx
298 */
299 int getVariable(const com::Utf8Str &rName, com::Utf8Str *pValue) const
300 {
301 size_t cchNeeded;
302 int rc = RTEnvGetEx(m_hEnv, rName.c_str(), NULL, 0, &cchNeeded);
303 if ( RT_SUCCESS(rc)
304 || rc == VERR_BUFFER_OVERFLOW)
305 {
306 try
307 {
308 pValue->reserve(cchNeeded + 1);
309 rc = RTEnvGetEx(m_hEnv, rName.c_str(), pValue->mutableRaw(), pValue->capacity(), NULL);
310 pValue->jolt();
311 }
312 catch (std::bad_alloc &)
313 {
314 rc = VERR_NO_STR_MEMORY;
315 }
316 }
317 return rc;
318 }
319
320 /**
321 * Checks if the given variable exists.
322 *
323 * @returns @c true if it exists, @c false if not or if it's an scheduled unset
324 * in a environment change record.
325 * @param rName The variable name.
326 * @sa RTEnvExistEx
327 */
328 bool doesVariableExist(const com::Utf8Str &rName) const
329 {
330 return RTEnvExistEx(m_hEnv, rName.c_str());
331 }
332
333 /**
334 * Set an environment variable.
335 *
336 * @returns IPRT status code.
337 * @param rName The variable name.
338 * @param rValue The value of the variable.
339 * @sa RTEnvSetEx
340 */
341 int setVariable(const com::Utf8Str &rName, const com::Utf8Str &rValue)
342 {
343 return RTEnvSetEx(m_hEnv, rName.c_str(), rValue.c_str());
344 }
345
346 /**
347 * Unset an environment variable.
348 *
349 * @returns IPRT status code.
350 * @param rName The variable name.
351 * @sa RTEnvUnsetEx
352 */
353 int unsetVariable(const com::Utf8Str &rName)
354 {
355 return RTEnvUnsetEx(m_hEnv, rName.c_str());
356 }
357
358protected:
359 /**
360 * Copy constructor.
361 * @throws HRESULT
362 */
363 GuestEnvironmentBase(const GuestEnvironmentBase &rThat, bool fChangeRecord)
364 : m_hEnv(NIL_RTENV)
365 , m_cRefs(1)
366 {
367 int rc = cloneCommon(rThat, fChangeRecord);
368 if (RT_FAILURE(rc))
369 throw (Global::vboxStatusCodeToCOM(rc));
370 }
371
372 /**
373 * Common clone/copy method with type conversion abilities.
374 *
375 * @returns IPRT status code.
376 * @param rThat The object to clone.
377 * @param fChangeRecord Whether the this instance is a change record (true)
378 * or normal (false) environment.
379 */
380 int cloneCommon(const GuestEnvironmentBase &rThat, bool fChangeRecord)
381 {
382 int rc = VINF_SUCCESS;
383 RTENV hNewEnv = NIL_RTENV;
384 if (rThat.m_hEnv != NIL_RTENV)
385 {
386 /*
387 * Clone it.
388 */
389 if (RTEnvIsChangeRecord(rThat.m_hEnv) == fChangeRecord)
390 rc = RTEnvClone(&hNewEnv, rThat.m_hEnv);
391 else
392 {
393 /* Need to type convert it. */
394 if (fChangeRecord)
395 rc = RTEnvCreateChangeRecord(&hNewEnv);
396 else
397 rc = RTEnvCreate(&hNewEnv);
398 if (RT_SUCCESS(rc))
399 {
400 rc = RTEnvApplyChanges(hNewEnv, rThat.m_hEnv);
401 if (RT_FAILURE(rc))
402 RTEnvDestroy(hNewEnv);
403 }
404 }
405 }
406 else
407 {
408 /*
409 * Create an empty one so the object works smoothly.
410 * (Relevant for GuestProcessStartupInfo and internal commands.)
411 */
412 if (fChangeRecord)
413 rc = RTEnvCreateChangeRecord(&hNewEnv);
414 else
415 rc = RTEnvCreate(&hNewEnv);
416 }
417 if (RT_SUCCESS(rc))
418 {
419 RTEnvDestroy(m_hEnv);
420 m_hEnv = hNewEnv;
421 }
422 return rc;
423 }
424
425
426 /** The environment change record. */
427 RTENV m_hEnv;
428 /** Reference counter. */
429 uint32_t volatile m_cRefs;
430};
431
432class GuestEnvironmentChanges;
433
434
435/**
436 * Wrapper around the RTEnv API for a normal environment.
437 */
438class GuestEnvironment : public GuestEnvironmentBase
439{
440public:
441 /**
442 * Default constructor.
443 *
444 * The user must invoke one of the init methods before using the object.
445 */
446 GuestEnvironment(void)
447 : GuestEnvironmentBase()
448 { }
449
450 /**
451 * Copy operator.
452 * @param rThat The object to copy.
453 * @throws HRESULT
454 */
455 GuestEnvironment(const GuestEnvironment &rThat)
456 : GuestEnvironmentBase(rThat, false /*fChangeRecord*/)
457 { }
458
459 /**
460 * Copy operator.
461 * @param rThat The object to copy.
462 * @throws HRESULT
463 */
464 GuestEnvironment(const GuestEnvironmentBase &rThat)
465 : GuestEnvironmentBase(rThat, false /*fChangeRecord*/)
466 { }
467
468 /**
469 * Initialize this as a normal environment block.
470 * @returns IPRT status code.
471 */
472 int initNormal(void)
473 {
474 AssertReturn(m_hEnv == NIL_RTENV, VERR_WRONG_ORDER);
475 return RTEnvCreate(&m_hEnv);
476 }
477
478 /**
479 * Replaces this environemnt with that in @a rThat.
480 *
481 * @returns IPRT status code
482 * @param rThat The environment to copy. If it's a different type
483 * we'll convert the data to a normal environment block.
484 */
485 int copy(const GuestEnvironmentBase &rThat)
486 {
487 return cloneCommon(rThat, false /*fChangeRecord*/);
488 }
489
490 /**
491 * @copydoc copy()
492 */
493 GuestEnvironment &operator=(const GuestEnvironmentBase &rThat)
494 {
495 int rc = cloneCommon(rThat, true /*fChangeRecord*/);
496 if (RT_FAILURE(rc))
497 throw (Global::vboxStatusCodeToCOM(rc));
498 return *this;
499 }
500
501 /** @copydoc copy() */
502 GuestEnvironment &operator=(const GuestEnvironment &rThat)
503 { return operator=((const GuestEnvironmentBase &)rThat); }
504
505 /** @copydoc copy() */
506 GuestEnvironment &operator=(const GuestEnvironmentChanges &rThat)
507 { return operator=((const GuestEnvironmentBase &)rThat); }
508
509};
510
511
512/**
513 * Wrapper around the RTEnv API for a environment change record.
514 *
515 * This class is used as a record of changes to be applied to a different
516 * environment block (in VBoxService before launching a new process).
517 */
518class GuestEnvironmentChanges : public GuestEnvironmentBase
519{
520public:
521 /**
522 * Default constructor.
523 *
524 * The user must invoke one of the init methods before using the object.
525 */
526 GuestEnvironmentChanges(void)
527 : GuestEnvironmentBase()
528 { }
529
530 /**
531 * Copy operator.
532 * @param rThat The object to copy.
533 * @throws HRESULT
534 */
535 GuestEnvironmentChanges(const GuestEnvironmentChanges &rThat)
536 : GuestEnvironmentBase(rThat, true /*fChangeRecord*/)
537 { }
538
539 /**
540 * Copy operator.
541 * @param rThat The object to copy.
542 * @throws HRESULT
543 */
544 GuestEnvironmentChanges(const GuestEnvironmentBase &rThat)
545 : GuestEnvironmentBase(rThat, true /*fChangeRecord*/)
546 { }
547
548 /**
549 * Initialize this as a environment change record.
550 * @returns IPRT status code.
551 */
552 int initChangeRecord(void)
553 {
554 AssertReturn(m_hEnv == NIL_RTENV, VERR_WRONG_ORDER);
555 return RTEnvCreateChangeRecord(&m_hEnv);
556 }
557
558 /**
559 * Replaces this environemnt with that in @a rThat.
560 *
561 * @returns IPRT status code
562 * @param rThat The environment to copy. If it's a different type
563 * we'll convert the data to a set of changes.
564 */
565 int copy(const GuestEnvironmentBase &rThat)
566 {
567 return cloneCommon(rThat, true /*fChangeRecord*/);
568 }
569
570 /**
571 * @copydoc copy()
572 */
573 GuestEnvironmentChanges &operator=(const GuestEnvironmentBase &rThat)
574 {
575 int rc = cloneCommon(rThat, true /*fChangeRecord*/);
576 if (RT_FAILURE(rc))
577 throw (Global::vboxStatusCodeToCOM(rc));
578 return *this;
579 }
580
581 /** @copydoc copy() */
582 GuestEnvironmentChanges &operator=(const GuestEnvironmentChanges &rThat)
583 { return operator=((const GuestEnvironmentBase &)rThat); }
584
585 /** @copydoc copy() */
586 GuestEnvironmentChanges &operator=(const GuestEnvironment &rThat)
587 { return operator=((const GuestEnvironmentBase &)rThat); }
588};
589
590
591/**
592 * Structure for keeping all the relevant guest directory
593 * information around.
594 */
595struct GuestDirectoryOpenInfo
596{
597 /** The directory path. */
598 Utf8Str mPath;
599 /** Then open filter. */
600 Utf8Str mFilter;
601 /** Opening flags. */
602 uint32_t mFlags;
603};
604
605
606/**
607 * Structure for keeping all the relevant guest file
608 * information around.
609 */
610struct GuestFileOpenInfo
611{
612 /** The filename. */
613 Utf8Str mFileName;
614 /** The file access mode. */
615 FileAccessMode_T mAccessMode;
616 /** String translation of mFileAccessMode for the GAs. */
617 const char *mpszAccessMode;
618 /** The file open action. */
619 FileOpenAction_T mOpenAction;
620 /** String translation of mOpenAction for the GAs. */
621 const char *mpszOpenAction;
622 /** The file sharing mode. */
623 FileSharingMode_T mSharingMode;
624 /** Octal creation mode. */
625 uint32_t mCreationMode;
626 /** Extended open flags (currently none defined). */
627 uint32_t mfOpenEx;
628 /** Initial file offset. */
629 uint64_t muOffset; /** @todo Remove this in the next protocol version. */
630};
631
632
633/**
634 * Structure representing information of a
635 * file system object.
636 */
637struct GuestFsObjData
638{
639 /** @name Helper functions to extract the data from a certin VBoxService tool's guest stream block.
640 * @{ */
641 int FromLs(const GuestProcessStreamBlock &strmBlk, bool fLong);
642 int FromMkTemp(const GuestProcessStreamBlock &strmBlk);
643 int FromStat(const GuestProcessStreamBlock &strmBlk);
644 /** @} */
645
646 /** @name Static helper functions to work with time from stream block keys.
647 * @{ */
648 static PRTTIMESPEC TimeSpecFromKey(const GuestProcessStreamBlock &strmBlk, const Utf8Str &strKey, PRTTIMESPEC pTimeSpec);
649 static int64_t UnixEpochNsFromKey(const GuestProcessStreamBlock &strmBlk, const Utf8Str &strKey);
650 /** @} */
651
652 int64_t mAccessTime;
653 int64_t mAllocatedSize;
654 int64_t mBirthTime;
655 int64_t mChangeTime;
656 uint32_t mDeviceNumber;
657 Utf8Str mFileAttrs;
658 uint32_t mGenerationID;
659 uint32_t mGID;
660 Utf8Str mGroupName;
661 uint32_t mNumHardLinks;
662 int64_t mModificationTime;
663 Utf8Str mName;
664 int64_t mNodeID;
665 uint32_t mNodeIDDevice;
666 int64_t mObjectSize;
667 FsObjType_T mType;
668 uint32_t mUID;
669 uint32_t mUserFlags;
670 Utf8Str mUserName;
671 Utf8Str mACL;
672};
673
674
675/**
676 * Structure for keeping all the relevant guest session
677 * startup parameters around.
678 */
679class GuestSessionStartupInfo
680{
681public:
682
683 GuestSessionStartupInfo(void)
684 : mIsInternal(false /* Non-internal session */),
685 mOpenTimeoutMS(30 * 1000 /* 30s opening timeout */),
686 mOpenFlags(0 /* No opening flags set */) { }
687
688 /** The session's friendly name. Optional. */
689 Utf8Str mName;
690 /** The session's unique ID. Used to encode a context ID. */
691 uint32_t mID;
692 /** Flag indicating if this is an internal session
693 * or not. Internal session are not accessible by
694 * public API clients. */
695 bool mIsInternal;
696 /** Timeout (in ms) used for opening the session. */
697 uint32_t mOpenTimeoutMS;
698 /** Session opening flags. */
699 uint32_t mOpenFlags;
700};
701
702
703/**
704 * Structure for keeping all the relevant guest process
705 * startup parameters around.
706 */
707class GuestProcessStartupInfo
708{
709public:
710
711 GuestProcessStartupInfo(void)
712 : mFlags(ProcessCreateFlag_None),
713 mTimeoutMS(UINT32_MAX /* No timeout by default */),
714 mPriority(ProcessPriority_Default) { }
715
716 /** The process' friendly name. */
717 Utf8Str mName;
718 /** The executable. */
719 Utf8Str mExecutable;
720 /** Arguments vector (starting with argument \#0). */
721 ProcessArguments mArguments;
722 /** The process environment change record. */
723 GuestEnvironmentChanges mEnvironmentChanges;
724 /** Process creation flags. */
725 uint32_t mFlags;
726 /** Timeout (in ms) the process is allowed to run.
727 * Specify UINT32_MAX if no timeout (unlimited run time) is given. */
728 ULONG mTimeoutMS;
729 /** Process priority. */
730 ProcessPriority_T mPriority;
731 /** Process affinity. At the moment we
732 * only support 64 VCPUs. API and
733 * guest can do more already! */
734 uint64_t mAffinity;
735};
736
737
738/**
739 * Class representing the "value" side of a "key=value" pair.
740 */
741class GuestProcessStreamValue
742{
743public:
744
745 GuestProcessStreamValue(void) { }
746 GuestProcessStreamValue(const char *pszValue)
747 : mValue(pszValue) {}
748
749 GuestProcessStreamValue(const GuestProcessStreamValue& aThat)
750 : mValue(aThat.mValue) { }
751
752 Utf8Str mValue;
753};
754
755/** Map containing "key=value" pairs of a guest process stream. */
756typedef std::pair< Utf8Str, GuestProcessStreamValue > GuestCtrlStreamPair;
757typedef std::map < Utf8Str, GuestProcessStreamValue > GuestCtrlStreamPairMap;
758typedef std::map < Utf8Str, GuestProcessStreamValue >::iterator GuestCtrlStreamPairMapIter;
759typedef std::map < Utf8Str, GuestProcessStreamValue >::const_iterator GuestCtrlStreamPairMapIterConst;
760
761/**
762 * Class representing a block of stream pairs (key=value). Each block in a raw guest
763 * output stream is separated by "\0\0", each pair is separated by "\0". The overall
764 * end of a guest stream is marked by "\0\0\0\0".
765 */
766class GuestProcessStreamBlock
767{
768public:
769
770 GuestProcessStreamBlock(void);
771
772 virtual ~GuestProcessStreamBlock(void);
773
774public:
775
776 void Clear(void);
777
778#ifdef DEBUG
779 void DumpToLog(void) const;
780#endif
781
782 int GetInt64Ex(const char *pszKey, int64_t *piVal) const;
783
784 int64_t GetInt64(const char *pszKey) const;
785
786 size_t GetCount(void) const;
787
788 int GetRc(void) const;
789
790 const char* GetString(const char *pszKey) const;
791
792 int GetUInt32Ex(const char *pszKey, uint32_t *puVal) const;
793
794 uint32_t GetUInt32(const char *pszKey) const;
795
796 bool IsEmpty(void) { return mPairs.empty(); }
797
798 int SetValue(const char *pszKey, const char *pszValue);
799
800protected:
801
802 GuestCtrlStreamPairMap mPairs;
803};
804
805/** Vector containing multiple allocated stream pair objects. */
806typedef std::vector< GuestProcessStreamBlock > GuestCtrlStreamObjects;
807typedef std::vector< GuestProcessStreamBlock >::iterator GuestCtrlStreamObjectsIter;
808typedef std::vector< GuestProcessStreamBlock >::const_iterator GuestCtrlStreamObjectsIterConst;
809
810/**
811 * Class for parsing machine-readable guest process output by VBoxService'
812 * toolbox commands ("vbox_ls", "vbox_stat" etc), aka "guest stream".
813 */
814class GuestProcessStream
815{
816
817public:
818
819 GuestProcessStream();
820
821 virtual ~GuestProcessStream();
822
823public:
824
825 int AddData(const BYTE *pbData, size_t cbData);
826
827 void Destroy();
828
829#ifdef DEBUG
830 void Dump(const char *pszFile);
831#endif
832
833 size_t GetOffset() { return m_offBuffer; }
834
835 size_t GetSize() { return m_cbUsed; }
836
837 int ParseBlock(GuestProcessStreamBlock &streamBlock);
838
839protected:
840
841 /** Currently allocated size of internal stream buffer. */
842 size_t m_cbAllocated;
843 /** Currently used size at m_offBuffer. */
844 size_t m_cbUsed;
845 /** Current byte offset within the internal stream buffer. */
846 size_t m_offBuffer;
847 /** Internal stream buffer. */
848 BYTE *m_pbBuffer;
849};
850
851class Guest;
852class Progress;
853
854class GuestTask
855{
856
857public:
858
859 enum TaskType
860 {
861 /** Copies a file from host to the guest. */
862 TaskType_CopyFileToGuest = 50,
863 /** Copies a file from guest to the host. */
864 TaskType_CopyFileFromGuest = 55,
865 /** Update Guest Additions by directly copying the required installer
866 * off the .ISO file, transfer it to the guest and execute the installer
867 * with system privileges. */
868 TaskType_UpdateGuestAdditions = 100
869 };
870
871 GuestTask(TaskType aTaskType, Guest *aThat, Progress *aProgress);
872
873 virtual ~GuestTask();
874
875 int startThread();
876
877 static int taskThread(RTTHREAD aThread, void *pvUser);
878 static int uploadProgress(unsigned uPercent, void *pvUser);
879 static HRESULT setProgressSuccess(ComObjPtr<Progress> pProgress);
880 static HRESULT setProgressErrorMsg(HRESULT hr,
881 ComObjPtr<Progress> pProgress, const char * pszText, ...);
882 static HRESULT setProgressErrorParent(HRESULT hr,
883 ComObjPtr<Progress> pProgress, ComObjPtr<Guest> pGuest);
884
885 TaskType taskType;
886 ComObjPtr<Guest> pGuest;
887 ComObjPtr<Progress> pProgress;
888 HRESULT rc;
889
890 /* Task data. */
891 Utf8Str strSource;
892 Utf8Str strDest;
893 Utf8Str strUserName;
894 Utf8Str strPassword;
895 ULONG uFlags;
896};
897
898class GuestWaitEventPayload
899{
900
901public:
902
903 GuestWaitEventPayload(void)
904 : uType(0),
905 cbData(0),
906 pvData(NULL) { }
907
908 GuestWaitEventPayload(uint32_t uTypePayload,
909 const void *pvPayload, uint32_t cbPayload)
910 : uType(0),
911 cbData(0),
912 pvData(NULL)
913 {
914 int rc = copyFrom(uTypePayload, pvPayload, cbPayload);
915 if (RT_FAILURE(rc))
916 throw rc;
917 }
918
919 virtual ~GuestWaitEventPayload(void)
920 {
921 Clear();
922 }
923
924 GuestWaitEventPayload& operator=(const GuestWaitEventPayload &that)
925 {
926 CopyFromDeep(that);
927 return *this;
928 }
929
930public:
931
932 void Clear(void)
933 {
934 if (pvData)
935 {
936 Assert(cbData);
937 RTMemFree(pvData);
938 cbData = 0;
939 pvData = NULL;
940 }
941 uType = 0;
942 }
943
944 int CopyFromDeep(const GuestWaitEventPayload &payload)
945 {
946 return copyFrom(payload.uType, payload.pvData, payload.cbData);
947 }
948
949 const void* Raw(void) const { return pvData; }
950
951 size_t Size(void) const { return cbData; }
952
953 uint32_t Type(void) const { return uType; }
954
955 void* MutableRaw(void) { return pvData; }
956
957 Utf8Str ToString(void)
958 {
959 const char *pszStr = (const char *)pvData;
960 size_t cbStr = cbData;
961
962 if (RT_FAILURE(RTStrValidateEncodingEx(pszStr, cbStr,
963 RTSTR_VALIDATE_ENCODING_ZERO_TERMINATED | RTSTR_VALIDATE_ENCODING_EXACT_LENGTH)))
964 {
965 AssertFailed();
966 return "";
967 }
968
969 return Utf8Str(pszStr, cbStr);
970 }
971
972protected:
973
974 int copyFrom(uint32_t uTypePayload, const void *pvPayload, uint32_t cbPayload)
975 {
976 if (cbPayload > _64K) /* Paranoia. */
977 return VERR_TOO_MUCH_DATA;
978
979 Clear();
980
981 int rc = VINF_SUCCESS;
982
983 if (cbPayload)
984 {
985 pvData = RTMemAlloc(cbPayload);
986 if (pvData)
987 {
988 uType = uTypePayload;
989
990 memcpy(pvData, pvPayload, cbPayload);
991 cbData = cbPayload;
992 }
993 else
994 rc = VERR_NO_MEMORY;
995 }
996 else
997 {
998 uType = uTypePayload;
999
1000 pvData = NULL;
1001 cbData = 0;
1002 }
1003
1004 return rc;
1005 }
1006
1007protected:
1008
1009 /** Type of payload. */
1010 uint32_t uType;
1011 /** Size (in bytes) of payload. */
1012 uint32_t cbData;
1013 /** Pointer to actual payload data. */
1014 void *pvData;
1015};
1016
1017class GuestWaitEventBase
1018{
1019
1020protected:
1021
1022 GuestWaitEventBase(void);
1023 virtual ~GuestWaitEventBase(void);
1024
1025public:
1026
1027 uint32_t ContextID(void) { return mCID; };
1028 int GuestResult(void) { return mGuestRc; }
1029 int Result(void) { return mRc; }
1030 GuestWaitEventPayload & Payload(void) { return mPayload; }
1031 int SignalInternal(int rc, int guestRc, const GuestWaitEventPayload *pPayload);
1032 int Wait(RTMSINTERVAL uTimeoutMS);
1033
1034protected:
1035
1036 int Init(uint32_t uCID);
1037
1038protected:
1039
1040 /* Shutdown indicator. */
1041 bool mfAborted;
1042 /* Associated context ID (CID). */
1043 uint32_t mCID;
1044 /** The event semaphore for triggering
1045 * the actual event. */
1046 RTSEMEVENT mEventSem;
1047 /** The event's overall result. If
1048 * set to VERR_GSTCTL_GUEST_ERROR,
1049 * mGuestRc will contain the actual
1050 * error code from the guest side. */
1051 int mRc;
1052 /** The event'S overall result from the
1053 * guest side. If used, mRc must be
1054 * set to VERR_GSTCTL_GUEST_ERROR. */
1055 int mGuestRc;
1056 /** The event's payload data. Optional. */
1057 GuestWaitEventPayload mPayload;
1058};
1059
1060/** List of public guest event types. */
1061typedef std::list < VBoxEventType_T > GuestEventTypes;
1062
1063class GuestWaitEvent : public GuestWaitEventBase
1064{
1065
1066public:
1067
1068 GuestWaitEvent(uint32_t uCID);
1069 GuestWaitEvent(uint32_t uCID, const GuestEventTypes &lstEvents);
1070 virtual ~GuestWaitEvent(void);
1071
1072public:
1073
1074 int Cancel(void);
1075 const ComPtr<IEvent> Event(void) { return mEvent; }
1076 int SignalExternal(IEvent *pEvent);
1077 const GuestEventTypes Types(void) { return mEventTypes; }
1078 size_t TypeCount(void) { return mEventTypes.size(); }
1079
1080protected:
1081
1082 int Init(uint32_t uCID);
1083
1084protected:
1085
1086 /** List of public event types this event should
1087 * be signalled on. Optional. */
1088 GuestEventTypes mEventTypes;
1089 /** Pointer to the actual public event, if any. */
1090 ComPtr<IEvent> mEvent;
1091};
1092/** Map of pointers to guest events. The primary key
1093 * contains the context ID. */
1094typedef std::map < uint32_t, GuestWaitEvent* > GuestWaitEvents;
1095/** Map of wait events per public guest event. Nice for
1096 * faster lookups when signalling a whole event group. */
1097typedef std::map < VBoxEventType_T, GuestWaitEvents > GuestEventGroup;
1098
1099class GuestBase
1100{
1101
1102public:
1103
1104 GuestBase(void);
1105 virtual ~GuestBase(void);
1106
1107public:
1108
1109 /** Signals a wait event using a public guest event; also used for
1110 * for external event listeners. */
1111 int signalWaitEvent(VBoxEventType_T aType, IEvent *aEvent);
1112 /** Signals a wait event using a guest rc. */
1113 int signalWaitEventInternal(PVBOXGUESTCTRLHOSTCBCTX pCbCtx, int guestRc, const GuestWaitEventPayload *pPayload);
1114 /** Signals a wait event without letting public guest events know,
1115 * extended director's cut version. */
1116 int signalWaitEventInternalEx(PVBOXGUESTCTRLHOSTCBCTX pCbCtx, int rc, int guestRc, const GuestWaitEventPayload *pPayload);
1117public:
1118
1119 int baseInit(void);
1120 void baseUninit(void);
1121 int cancelWaitEvents(void);
1122 int dispatchGeneric(PVBOXGUESTCTRLHOSTCBCTX pCtxCb, PVBOXGUESTCTRLHOSTCALLBACK pSvcCb);
1123 int generateContextID(uint32_t uSessionID, uint32_t uObjectID, uint32_t *puContextID);
1124 int registerWaitEvent(uint32_t uSessionID, uint32_t uObjectID, GuestWaitEvent **ppEvent);
1125 int registerWaitEventEx(uint32_t uSessionID, uint32_t uObjectID, const GuestEventTypes &lstEvents, GuestWaitEvent **ppEvent);
1126 int unregisterWaitEvent(GuestWaitEvent *pEvent);
1127 int waitForEvent(GuestWaitEvent *pEvent, uint32_t uTimeoutMS, VBoxEventType_T *pType, IEvent **ppEvent);
1128
1129protected:
1130
1131 /** Pointer to the console object. Needed
1132 * for HGCM (VMMDev) communication. */
1133 Console *mConsole;
1134 /** The next upcoming context ID for this object. */
1135 uint32_t mNextContextID;
1136 /** Local listener for handling the waiting events
1137 * internally. */
1138 ComPtr<IEventListener> mLocalListener;
1139 /** Critical section for wait events access. */
1140 RTCRITSECT mWaitEventCritSect;
1141 /** Map of registered wait events per event group. */
1142 GuestEventGroup mWaitEventGroups;
1143 /** Map of registered wait events. */
1144 GuestWaitEvents mWaitEvents;
1145};
1146
1147/**
1148 * Virtual class (interface) for guest objects (processes, files, ...) --
1149 * contains all per-object callback management.
1150 */
1151class GuestObject : public GuestBase
1152{
1153
1154public:
1155
1156 GuestObject(void);
1157 virtual ~GuestObject(void);
1158
1159public:
1160
1161 ULONG getObjectID(void) { return mObjectID; }
1162
1163protected:
1164
1165 virtual int i_onRemove(void) = 0;
1166
1167 /** Callback dispatcher -- must be implemented by the actual object. */
1168 virtual int i_callbackDispatcher(PVBOXGUESTCTRLHOSTCBCTX pCbCtx, PVBOXGUESTCTRLHOSTCALLBACK pSvcCb) = 0;
1169
1170protected:
1171
1172 int bindToSession(Console *pConsole, GuestSession *pSession, uint32_t uObjectID);
1173 int registerWaitEvent(const GuestEventTypes &lstEvents, GuestWaitEvent **ppEvent);
1174 int sendCommand(uint32_t uFunction, uint32_t cParms, PVBOXHGCMSVCPARM paParms);
1175
1176protected:
1177
1178 /** @name Common parameters for all derived objects. They have their own
1179 * mData structure to keep their specific data around.
1180 * @{ */
1181 /** Pointer to parent session. Per definition
1182 * this objects *always* lives shorter than the
1183 * parent.
1184 * @todo r=bird: When wanting to use mSession in the
1185 * IGuestProcess::getEnvironment() implementation I wanted to access
1186 * GuestSession::mData::mpBaseEnvironment. Seeing the comment in
1187 * GuestProcess::terminate() saying:
1188 * "Now only API clients still can hold references to it."
1189 * and recalling seeing similar things in VirtualBox.xidl or some such place,
1190 * I'm wondering how this "per definition" behavior is enforced. Is there any
1191 * GuestProcess:uninit() call or similar magic that invalidates objects that
1192 * GuestSession loses track of in place like GuestProcess::terminate() that I've
1193 * failed to spot?
1194 *
1195 * Please enlighten me.
1196 */
1197 GuestSession *mSession;
1198 /** The object ID -- must be unique for each guest
1199 * object and is encoded into the context ID. Must
1200 * be set manually when initializing the object.
1201 *
1202 * For guest processes this is the internal PID,
1203 * for guest files this is the internal file ID. */
1204 uint32_t mObjectID;
1205 /** @} */
1206};
1207#endif // !____H_GUESTIMPLPRIVATE
1208
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