VirtualBox

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

Last change on this file since 56035 was 55668, checked in by vboxsync, 10 years ago

Modified IGuestSession::fileOpenEx: removed the 'offset' parameter and added generic flags parameter so we can easily add features later when we need them (see RTFILE_O_XXX for inspiration). Changed FileSeekOrigin_Set to FileSeekOrigin_Begin.

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