VirtualBox

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

Last change on this file since 55631 was 55631, checked in by vboxsync, 9 years ago

IGuestSession:

  • Added pathStyle attribute and associated enum.
  • Added a currentDirectory attribute (stub).
  • Introduced fsObjExists (earlier fsExists) which works on all fs obj types.
  • Combined directoryQueryInfo and fileQueryInfo into fsObjQueryInfo (earlier fsQueryInfo) which works on all fs obj types. Caller can check the type attribute.
  • Combined fileRemove and symlinkRemove* into fsObjRemove both on suggestion from Michael and because it's impossible to implement correctly with introducing races. Besides, our implementation was already doing the fsObjRemove job, no type checks.
  • Combined directoryRename, fileRename and symlinkRename into fsObjRename since we cannot implement type specific renames without introducing races on all platforms, and again, the current implementation already does the whole shebang.
  • Combined directorySetACL and fileSetACL into fsObjSetACL, adding a UNIX-style mode parameter for use when the ACL string is empty.
  • Stubbed the recursive directory copy methods directoryCopy, directoryCopyToGuest, and directoryCopyFromGuest. These replaces the proposed FileCopyFlag::Recursive flag.
  • Stubbed a generic move-anything-inside-the-guest method, fsObjMove, for future explotations. (Considered this on file/dir level, but it's the rename and type race problem. So, did the 'mv' approach instead.)
  • Renamed CopyFileFlag to FileCopyFlag.
  • Prefixed copyTo and copyFrom with 'file' and added 'Guest' postfix to clarify the direction (now: fileCopyToGuest, fileCopyFromGuest).
  • Added fileCopy method for copy a guest file to another guest location.
  • directoryExists got a followSymlinks parameter.
  • fileExist and fileQuerySize all got a followSymlinks parameter.
  • Retired directoryRename in favor of fsObjRename.
  • Retired directorySetACL in favor of fsObjSetACL.
  • Retired fileSetACL in favor of fsObjSetACL.
  • Retired fileRemove in favor of fsObjRemove - fileRemove was already removing everything except directories, no need for ambiguous duplications.
  • Retired symlinkRemoveDirectory and symlinkRemoveFile in favor of fsObjRemove.
  • replaced the openMode string parameter int fileOpen[Ex] methods with an enum FileAccessMode (we made some wrong design choices way back).
  • replaced the disposition string parameter in fileOpen[Ex] methods with an enum FileOpenAction. This one was more obvious, should've seen this way back.
  • replaced the sharingMode stirng parameter in the fileOpenEx method with an enum FileSharingMode.
  • Documented directoryRemoveRecursive flags issue.


IFile,IGuestFile:

  • Stubbed querySize
  • Stubbed setSize.
  • Renamed FileSeekType to FileSeekOrigin.
  • Implemented seek() relative to end, flag was forgotten.
  • Made seek() return the new offset.
  • Extended setACL with a UNIX-style file mode argument that should be used if the ACL string is empty (this way we can actually get something implemented without 2 months of cross platform ACL research).
  • The openMode and disposition attributes has been updated to match the fileOpenEx enum changes.
  • 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 55631 2015-05-04 04:08:10Z vboxsync $ */
2/** @file
3 *
4 * Internal helpers/structures for guest control functionality.
5 */
6
7/*
8 * Copyright (C) 2011-2015 Oracle Corporation
9 *
10 * This file is part of VirtualBox Open Source Edition (OSE), as
11 * available from http://www.virtualbox.org. This file is free software;
12 * you can redistribute it and/or modify it under the terms of the GNU
13 * General Public License (GPL) as published by the Free Software
14 * Foundation, in version 2 as it comes in the "COPYING" file of the
15 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
16 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
17 */
18
19#ifndef ____H_GUESTIMPLPRIVATE
20#define ____H_GUESTIMPLPRIVATE
21
22#include "ConsoleImpl.h"
23#include "Global.h"
24
25#include <iprt/asm.h>
26#include <iprt/env.h>
27#include <iprt/semaphore.h>
28#include <iprt/cpp/utils.h>
29
30#include <VBox/com/com.h>
31#include <VBox/com/ErrorInfo.h>
32#include <VBox/com/string.h>
33#include <VBox/com/VirtualBox.h>
34
35#include <map>
36#include <vector>
37
38using namespace com;
39
40#ifdef VBOX_WITH_GUEST_CONTROL
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 (ASMMemIsAll8(pszzBlock, cbBlock, 0))
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 if (RTEnvIsChangeRecord(rThat.m_hEnv) == fChangeRecord)
387 rc = RTEnvClone(&hNewEnv, rThat.m_hEnv);
388 else
389 {
390 /* Need to type convert it. */
391 if (fChangeRecord)
392 rc = RTEnvCreateChangeRecord(&hNewEnv);
393 else
394 rc = RTEnvCreate(&hNewEnv);
395 if (RT_SUCCESS(rc))
396 {
397 rc = RTEnvApplyChanges(hNewEnv, rThat.m_hEnv);
398 if (RT_FAILURE(rc))
399 RTEnvDestroy(hNewEnv);
400 }
401 }
402
403 }
404 if (RT_SUCCESS(rc))
405 {
406 RTEnvDestroy(m_hEnv);
407 m_hEnv = hNewEnv;
408 }
409 return rc;
410 }
411
412
413 /** The environment change record. */
414 RTENV m_hEnv;
415 /** Reference counter. */
416 uint32_t volatile m_cRefs;
417};
418
419class GuestEnvironmentChanges;
420
421
422/**
423 * Wrapper around the RTEnv API for a normal environment.
424 */
425class GuestEnvironment : public GuestEnvironmentBase
426{
427public:
428 /**
429 * Default constructor.
430 *
431 * The user must invoke one of the init methods before using the object.
432 */
433 GuestEnvironment(void)
434 : GuestEnvironmentBase()
435 { }
436
437 /**
438 * Copy operator.
439 * @param rThat The object to copy.
440 * @throws HRESULT
441 */
442 GuestEnvironment(const GuestEnvironment &rThat)
443 : GuestEnvironmentBase(rThat, false /*fChangeRecord*/)
444 { }
445
446 /**
447 * Copy operator.
448 * @param rThat The object to copy.
449 * @throws HRESULT
450 */
451 GuestEnvironment(const GuestEnvironmentBase &rThat)
452 : GuestEnvironmentBase(rThat, false /*fChangeRecord*/)
453 { }
454
455 /**
456 * Initialize this as a normal environment block.
457 * @returns IPRT status code.
458 */
459 int initNormal(void)
460 {
461 AssertReturn(m_hEnv == NIL_RTENV, VERR_WRONG_ORDER);
462 return RTEnvCreate(&m_hEnv);
463 }
464
465 /**
466 * Replaces this environemnt with that in @a rThat.
467 *
468 * @returns IPRT status code
469 * @param rThat The environment to copy. If it's a different type
470 * we'll convert the data to a normal environment block.
471 */
472 int copy(const GuestEnvironmentBase &rThat)
473 {
474 return cloneCommon(rThat, false /*fChangeRecord*/);
475 }
476
477 /**
478 * @copydoc copy()
479 */
480 GuestEnvironment &operator=(const GuestEnvironmentBase &rThat)
481 {
482 int rc = cloneCommon(rThat, true /*fChangeRecord*/);
483 if (RT_FAILURE(rc))
484 throw (Global::vboxStatusCodeToCOM(rc));
485 return *this;
486 }
487
488 /** @copydoc copy() */
489 GuestEnvironment &operator=(const GuestEnvironment &rThat)
490 { return operator=((const GuestEnvironmentBase &)rThat); }
491
492 /** @copydoc copy() */
493 GuestEnvironment &operator=(const GuestEnvironmentChanges &rThat)
494 { return operator=((const GuestEnvironmentBase &)rThat); }
495
496};
497
498
499/**
500 * Wrapper around the RTEnv API for a environment change record.
501 *
502 * This class is used as a record of changes to be applied to a different
503 * environment block (in VBoxService before launching a new process).
504 */
505class GuestEnvironmentChanges : public GuestEnvironmentBase
506{
507public:
508 /**
509 * Default constructor.
510 *
511 * The user must invoke one of the init methods before using the object.
512 */
513 GuestEnvironmentChanges(void)
514 : GuestEnvironmentBase()
515 { }
516
517 /**
518 * Copy operator.
519 * @param rThat The object to copy.
520 * @throws HRESULT
521 */
522 GuestEnvironmentChanges(const GuestEnvironmentChanges &rThat)
523 : GuestEnvironmentBase(rThat, true /*fChangeRecord*/)
524 { }
525
526 /**
527 * Copy operator.
528 * @param rThat The object to copy.
529 * @throws HRESULT
530 */
531 GuestEnvironmentChanges(const GuestEnvironmentBase &rThat)
532 : GuestEnvironmentBase(rThat, true /*fChangeRecord*/)
533 { }
534
535 /**
536 * Initialize this as a environment change record.
537 * @returns IPRT status code.
538 */
539 int initChangeRecord(void)
540 {
541 AssertReturn(m_hEnv == NIL_RTENV, VERR_WRONG_ORDER);
542 return RTEnvCreateChangeRecord(&m_hEnv);
543 }
544
545 /**
546 * Replaces this environemnt with that in @a rThat.
547 *
548 * @returns IPRT status code
549 * @param rThat The environment to copy. If it's a different type
550 * we'll convert the data to a set of changes.
551 */
552 int copy(const GuestEnvironmentBase &rThat)
553 {
554 return cloneCommon(rThat, true /*fChangeRecord*/);
555 }
556
557 /**
558 * @copydoc copy()
559 */
560 GuestEnvironmentChanges &operator=(const GuestEnvironmentBase &rThat)
561 {
562 int rc = cloneCommon(rThat, true /*fChangeRecord*/);
563 if (RT_FAILURE(rc))
564 throw (Global::vboxStatusCodeToCOM(rc));
565 return *this;
566 }
567
568 /** @copydoc copy() */
569 GuestEnvironmentChanges &operator=(const GuestEnvironmentChanges &rThat)
570 { return operator=((const GuestEnvironmentBase &)rThat); }
571
572 /** @copydoc copy() */
573 GuestEnvironmentChanges &operator=(const GuestEnvironment &rThat)
574 { return operator=((const GuestEnvironmentBase &)rThat); }
575};
576
577
578/**
579 * Structure for keeping all the relevant guest directory
580 * information around.
581 */
582struct GuestDirectoryOpenInfo
583{
584 /** The directory path. */
585 Utf8Str mPath;
586 /** Then open filter. */
587 Utf8Str mFilter;
588 /** Opening flags. */
589 uint32_t mFlags;
590};
591
592
593/**
594 * Structure for keeping all the relevant guest file
595 * information around.
596 */
597struct GuestFileOpenInfo
598{
599 /** The filename. */
600 Utf8Str mFileName;
601 /** The file access mode. */
602 FileAccessMode_T mAccessMode;
603 /** String translation of mFileAccessMode for the GAs. */
604 const char *mpszAccessMode;
605 /** The file open action. */
606 FileOpenAction_T mOpenAction;
607 /** String translation of mOpenAction for the GAs. */
608 const char *mpszOpenAction;
609 /** The file sharing mode. */
610 FileSharingMode_T mSharingMode;
611 /** Octal creation mode. */
612 uint32_t mCreationMode;
613 /** The initial offset on open. */
614 uint64_t mInitialOffset;
615};
616
617
618/**
619 * Structure representing information of a
620 * file system object.
621 */
622struct GuestFsObjData
623{
624 /** Helper function to extract the data from
625 * a certin VBoxService tool's guest stream block. */
626 int FromLs(const GuestProcessStreamBlock &strmBlk);
627 int FromMkTemp(const GuestProcessStreamBlock &strmBlk);
628 int FromStat(const GuestProcessStreamBlock &strmBlk);
629
630 int64_t mAccessTime;
631 int64_t mAllocatedSize;
632 int64_t mBirthTime;
633 int64_t mChangeTime;
634 uint32_t mDeviceNumber;
635 Utf8Str mFileAttrs;
636 uint32_t mGenerationID;
637 uint32_t mGID;
638 Utf8Str mGroupName;
639 uint32_t mNumHardLinks;
640 int64_t mModificationTime;
641 Utf8Str mName;
642 int64_t mNodeID;
643 uint32_t mNodeIDDevice;
644 int64_t mObjectSize;
645 FsObjType_T mType;
646 uint32_t mUID;
647 uint32_t mUserFlags;
648 Utf8Str mUserName;
649 Utf8Str mACL;
650};
651
652
653/**
654 * Structure for keeping all the relevant guest session
655 * startup parameters around.
656 */
657class GuestSessionStartupInfo
658{
659public:
660
661 GuestSessionStartupInfo(void)
662 : mIsInternal(false /* Non-internal session */),
663 mOpenTimeoutMS(30 * 1000 /* 30s opening timeout */),
664 mOpenFlags(0 /* No opening flags set */) { }
665
666 /** The session's friendly name. Optional. */
667 Utf8Str mName;
668 /** The session's unique ID. Used to encode
669 * a context ID. */
670 uint32_t mID;
671 /** Flag indicating if this is an internal session
672 * or not. Internal session are not accessible by
673 * public API clients. */
674 bool mIsInternal;
675 /** Timeout (in ms) used for opening the session. */
676 uint32_t mOpenTimeoutMS;
677 /** Session opening flags. */
678 uint32_t mOpenFlags;
679};
680
681
682/**
683 * Structure for keeping all the relevant guest process
684 * startup parameters around.
685 */
686class GuestProcessStartupInfo
687{
688public:
689
690 GuestProcessStartupInfo(void)
691 : mFlags(ProcessCreateFlag_None),
692 mTimeoutMS(30 * 1000 /* 30s timeout by default */),
693 mPriority(ProcessPriority_Default) { }
694
695 /** The process' friendly name. */
696 Utf8Str mName;
697 /** The executable. */
698 Utf8Str mExecutable;
699 /** Arguments vector (starting with argument \#0). */
700 ProcessArguments mArguments;
701 /** The process environment change record. */
702 GuestEnvironmentChanges mEnvironmentChanges;
703 /** Process creation flags. */
704 uint32_t mFlags;
705 ULONG mTimeoutMS;
706 /** Process priority. */
707 ProcessPriority_T mPriority;
708 /** Process affinity. At the moment we
709 * only support 64 VCPUs. API and
710 * guest can do more already! */
711 uint64_t mAffinity;
712};
713
714
715/**
716 * Class representing the "value" side of a "key=value" pair.
717 */
718class GuestProcessStreamValue
719{
720public:
721
722 GuestProcessStreamValue(void) { }
723 GuestProcessStreamValue(const char *pszValue)
724 : mValue(pszValue) {}
725
726 GuestProcessStreamValue(const GuestProcessStreamValue& aThat)
727 : mValue(aThat.mValue) { }
728
729 Utf8Str mValue;
730};
731
732/** Map containing "key=value" pairs of a guest process stream. */
733typedef std::pair< Utf8Str, GuestProcessStreamValue > GuestCtrlStreamPair;
734typedef std::map < Utf8Str, GuestProcessStreamValue > GuestCtrlStreamPairMap;
735typedef std::map < Utf8Str, GuestProcessStreamValue >::iterator GuestCtrlStreamPairMapIter;
736typedef std::map < Utf8Str, GuestProcessStreamValue >::const_iterator GuestCtrlStreamPairMapIterConst;
737
738/**
739 * Class representing a block of stream pairs (key=value). Each block in a raw guest
740 * output stream is separated by "\0\0", each pair is separated by "\0". The overall
741 * end of a guest stream is marked by "\0\0\0\0".
742 */
743class GuestProcessStreamBlock
744{
745public:
746
747 GuestProcessStreamBlock(void);
748
749 virtual ~GuestProcessStreamBlock(void);
750
751public:
752
753 void Clear(void);
754
755#ifdef DEBUG
756 void DumpToLog(void) const;
757#endif
758
759 int GetInt64Ex(const char *pszKey, int64_t *piVal) const;
760
761 int64_t GetInt64(const char *pszKey) const;
762
763 size_t GetCount(void) const;
764
765 int GetRc(void) const;
766
767 const char* GetString(const char *pszKey) const;
768
769 int GetUInt32Ex(const char *pszKey, uint32_t *puVal) const;
770
771 uint32_t GetUInt32(const char *pszKey) const;
772
773 bool IsEmpty(void) { return mPairs.empty(); }
774
775 int SetValue(const char *pszKey, const char *pszValue);
776
777protected:
778
779 GuestCtrlStreamPairMap mPairs;
780};
781
782/** Vector containing multiple allocated stream pair objects. */
783typedef std::vector< GuestProcessStreamBlock > GuestCtrlStreamObjects;
784typedef std::vector< GuestProcessStreamBlock >::iterator GuestCtrlStreamObjectsIter;
785typedef std::vector< GuestProcessStreamBlock >::const_iterator GuestCtrlStreamObjectsIterConst;
786
787/**
788 * Class for parsing machine-readable guest process output by VBoxService'
789 * toolbox commands ("vbox_ls", "vbox_stat" etc), aka "guest stream".
790 */
791class GuestProcessStream
792{
793
794public:
795
796 GuestProcessStream();
797
798 virtual ~GuestProcessStream();
799
800public:
801
802 int AddData(const BYTE *pbData, size_t cbData);
803
804 void Destroy();
805
806#ifdef DEBUG
807 void Dump(const char *pszFile);
808#endif
809
810 uint32_t GetOffset() { return m_cbOffset; }
811
812 size_t GetSize() { return m_cbSize; }
813
814 int ParseBlock(GuestProcessStreamBlock &streamBlock);
815
816protected:
817
818 /** Currently allocated size of internal stream buffer. */
819 uint32_t m_cbAllocated;
820 /** Currently used size of allocated internal stream buffer. */
821 size_t m_cbSize;
822 /** Current offset within the internal stream buffer. */
823 uint32_t m_cbOffset;
824 /** Internal stream buffer. */
825 BYTE *m_pbBuffer;
826};
827
828class Guest;
829class Progress;
830
831class GuestTask
832{
833
834public:
835
836 enum TaskType
837 {
838 /** Copies a file from host to the guest. */
839 TaskType_CopyFileToGuest = 50,
840 /** Copies a file from guest to the host. */
841 TaskType_CopyFileFromGuest = 55,
842 /** Update Guest Additions by directly copying the required installer
843 * off the .ISO file, transfer it to the guest and execute the installer
844 * with system privileges. */
845 TaskType_UpdateGuestAdditions = 100
846 };
847
848 GuestTask(TaskType aTaskType, Guest *aThat, Progress *aProgress);
849
850 virtual ~GuestTask();
851
852 int startThread();
853
854 static int taskThread(RTTHREAD aThread, void *pvUser);
855 static int uploadProgress(unsigned uPercent, void *pvUser);
856 static HRESULT setProgressSuccess(ComObjPtr<Progress> pProgress);
857 static HRESULT setProgressErrorMsg(HRESULT hr,
858 ComObjPtr<Progress> pProgress, const char * pszText, ...);
859 static HRESULT setProgressErrorParent(HRESULT hr,
860 ComObjPtr<Progress> pProgress, ComObjPtr<Guest> pGuest);
861
862 TaskType taskType;
863 ComObjPtr<Guest> pGuest;
864 ComObjPtr<Progress> pProgress;
865 HRESULT rc;
866
867 /* Task data. */
868 Utf8Str strSource;
869 Utf8Str strDest;
870 Utf8Str strUserName;
871 Utf8Str strPassword;
872 ULONG uFlags;
873};
874
875class GuestWaitEventPayload
876{
877
878public:
879
880 GuestWaitEventPayload(void)
881 : uType(0),
882 cbData(0),
883 pvData(NULL) { }
884
885 GuestWaitEventPayload(uint32_t uTypePayload,
886 const void *pvPayload, uint32_t cbPayload)
887 {
888 if (cbPayload)
889 {
890 pvData = RTMemAlloc(cbPayload);
891 if (pvData)
892 {
893 uType = uTypePayload;
894
895 memcpy(pvData, pvPayload, cbPayload);
896 cbData = cbPayload;
897 }
898 else /* Throw IPRT error. */
899 throw VERR_NO_MEMORY;
900 }
901 else
902 {
903 uType = uTypePayload;
904
905 pvData = NULL;
906 cbData = 0;
907 }
908 }
909
910 virtual ~GuestWaitEventPayload(void)
911 {
912 Clear();
913 }
914
915 GuestWaitEventPayload& operator=(const GuestWaitEventPayload &that)
916 {
917 CopyFromDeep(that);
918 return *this;
919 }
920
921public:
922
923 void Clear(void)
924 {
925 if (pvData)
926 {
927 RTMemFree(pvData);
928 cbData = 0;
929 }
930 uType = 0;
931 }
932
933 int CopyFromDeep(const GuestWaitEventPayload &payload)
934 {
935 Clear();
936
937 int rc = VINF_SUCCESS;
938 if (payload.cbData)
939 {
940 Assert(payload.cbData);
941 pvData = RTMemAlloc(payload.cbData);
942 if (pvData)
943 {
944 memcpy(pvData, payload.pvData, payload.cbData);
945 cbData = payload.cbData;
946 uType = payload.uType;
947 }
948 else
949 rc = VERR_NO_MEMORY;
950 }
951
952 return rc;
953 }
954
955 const void* Raw(void) const { return pvData; }
956
957 size_t Size(void) const { return cbData; }
958
959 uint32_t Type(void) const { return uType; }
960
961 void* MutableRaw(void) { return pvData; }
962
963protected:
964
965 /** Type of payload. */
966 uint32_t uType;
967 /** Size (in bytes) of payload. */
968 uint32_t cbData;
969 /** Pointer to actual payload data. */
970 void *pvData;
971};
972
973class GuestWaitEventBase
974{
975
976protected:
977
978 GuestWaitEventBase(void);
979 virtual ~GuestWaitEventBase(void);
980
981public:
982
983 uint32_t ContextID(void) { return mCID; };
984 int GuestResult(void) { return mGuestRc; }
985 int Result(void) { return mRc; }
986 GuestWaitEventPayload & Payload(void) { return mPayload; }
987 int SignalInternal(int rc, int guestRc, const GuestWaitEventPayload *pPayload);
988 int Wait(RTMSINTERVAL uTimeoutMS);
989
990protected:
991
992 int Init(uint32_t uCID);
993
994protected:
995
996 /* Shutdown indicator. */
997 bool mfAborted;
998 /* Associated context ID (CID). */
999 uint32_t mCID;
1000 /** The event semaphore for triggering
1001 * the actual event. */
1002 RTSEMEVENT mEventSem;
1003 /** The event's overall result. If
1004 * set to VERR_GSTCTL_GUEST_ERROR,
1005 * mGuestRc will contain the actual
1006 * error code from the guest side. */
1007 int mRc;
1008 /** The event'S overall result from the
1009 * guest side. If used, mRc must be
1010 * set to VERR_GSTCTL_GUEST_ERROR. */
1011 int mGuestRc;
1012 /** The event's payload data. Optional. */
1013 GuestWaitEventPayload mPayload;
1014};
1015
1016/** List of public guest event types. */
1017typedef std::list < VBoxEventType_T > GuestEventTypes;
1018
1019class GuestWaitEvent : public GuestWaitEventBase
1020{
1021
1022public:
1023
1024 GuestWaitEvent(uint32_t uCID);
1025 GuestWaitEvent(uint32_t uCID, const GuestEventTypes &lstEvents);
1026 virtual ~GuestWaitEvent(void);
1027
1028public:
1029
1030 int Cancel(void);
1031 const ComPtr<IEvent> Event(void) { return mEvent; }
1032 int SignalExternal(IEvent *pEvent);
1033 const GuestEventTypes Types(void) { return mEventTypes; }
1034 size_t TypeCount(void) { return mEventTypes.size(); }
1035
1036protected:
1037
1038 int Init(uint32_t uCID);
1039
1040protected:
1041
1042 /** List of public event types this event should
1043 * be signalled on. Optional. */
1044 GuestEventTypes mEventTypes;
1045 /** Pointer to the actual public event, if any. */
1046 ComPtr<IEvent> mEvent;
1047};
1048/** Map of pointers to guest events. The primary key
1049 * contains the context ID. */
1050typedef std::map < uint32_t, GuestWaitEvent* > GuestWaitEvents;
1051/** Map of wait events per public guest event. Nice for
1052 * faster lookups when signalling a whole event group. */
1053typedef std::map < VBoxEventType_T, GuestWaitEvents > GuestEventGroup;
1054
1055class GuestBase
1056{
1057
1058public:
1059
1060 GuestBase(void);
1061 virtual ~GuestBase(void);
1062
1063public:
1064
1065 /** Signals a wait event using a public guest event; also used for
1066 * for external event listeners. */
1067 int signalWaitEvent(VBoxEventType_T aType, IEvent *aEvent);
1068 /** Signals a wait event using a guest rc. */
1069 int signalWaitEventInternal(PVBOXGUESTCTRLHOSTCBCTX pCbCtx, int guestRc, const GuestWaitEventPayload *pPayload);
1070 /** Signals a wait event without letting public guest events know,
1071 * extended director's cut version. */
1072 int signalWaitEventInternalEx(PVBOXGUESTCTRLHOSTCBCTX pCbCtx, int rc, int guestRc, const GuestWaitEventPayload *pPayload);
1073public:
1074
1075 int baseInit(void);
1076 void baseUninit(void);
1077 int cancelWaitEvents(void);
1078 int dispatchGeneric(PVBOXGUESTCTRLHOSTCBCTX pCtxCb, PVBOXGUESTCTRLHOSTCALLBACK pSvcCb);
1079 int generateContextID(uint32_t uSessionID, uint32_t uObjectID, uint32_t *puContextID);
1080 int registerWaitEvent(uint32_t uSessionID, uint32_t uObjectID, GuestWaitEvent **ppEvent);
1081 int registerWaitEvent(uint32_t uSessionID, uint32_t uObjectID, const GuestEventTypes &lstEvents, GuestWaitEvent **ppEvent);
1082 void unregisterWaitEvent(GuestWaitEvent *pEvent);
1083 int waitForEvent(GuestWaitEvent *pEvent, uint32_t uTimeoutMS, VBoxEventType_T *pType, IEvent **ppEvent);
1084
1085protected:
1086
1087 /** Pointer to the console object. Needed
1088 * for HGCM (VMMDev) communication. */
1089 Console *mConsole;
1090 /** The next upcoming context ID for this object. */
1091 uint32_t mNextContextID;
1092 /** Local listener for handling the waiting events
1093 * internally. */
1094 ComPtr<IEventListener> mLocalListener;
1095 /** Critical section for wait events access. */
1096 RTCRITSECT mWaitEventCritSect;
1097 /** Map of registered wait events per event group. */
1098 GuestEventGroup mWaitEventGroups;
1099 /** Map of registered wait events. */
1100 GuestWaitEvents mWaitEvents;
1101};
1102
1103/**
1104 * Virtual class (interface) for guest objects (processes, files, ...) --
1105 * contains all per-object callback management.
1106 */
1107class GuestObject : public GuestBase
1108{
1109
1110public:
1111
1112 GuestObject(void);
1113 virtual ~GuestObject(void);
1114
1115public:
1116
1117 ULONG getObjectID(void) { return mObjectID; }
1118
1119protected:
1120
1121 virtual int i_onRemove(void) = 0;
1122
1123 /** Callback dispatcher -- must be implemented by the actual object. */
1124 virtual int i_callbackDispatcher(PVBOXGUESTCTRLHOSTCBCTX pCbCtx, PVBOXGUESTCTRLHOSTCALLBACK pSvcCb) = 0;
1125
1126protected:
1127
1128 int bindToSession(Console *pConsole, GuestSession *pSession, uint32_t uObjectID);
1129 int registerWaitEvent(const GuestEventTypes &lstEvents, GuestWaitEvent **ppEvent);
1130 int sendCommand(uint32_t uFunction, uint32_t uParms, PVBOXHGCMSVCPARM paParms);
1131
1132protected:
1133
1134 /** @name Common parameters for all derived objects. They have their own
1135 * mData structure to keep their specific data around.
1136 * @{ */
1137 /** Pointer to parent session. Per definition
1138 * this objects *always* lives shorter than the
1139 * parent.
1140 * @todo r=bird: When wanting to use mSession in the
1141 * IGuestProcess::getEnvironment() implementation I wanted to access
1142 * GuestSession::mData::mpBaseEnvironment. Seeing the comment in
1143 * GuestProcess::terminate() saying:
1144 * "Now only API clients still can hold references to it."
1145 * and recalling seeing similar things in VirtualBox.xidl or some such place,
1146 * I'm wondering how this "per definition" behavior is enforced. Is there any
1147 * GuestProcess:uninit() call or similar magic that invalidates objects that
1148 * GuestSession loses track of in place like GuestProcess::terminate() that I've
1149 * failed to spot?
1150 *
1151 * Please enlighten me.
1152 */
1153 GuestSession *mSession;
1154 /** The object ID -- must be unique for each guest
1155 * object and is encoded into the context ID. Must
1156 * be set manually when initializing the object.
1157 *
1158 * For guest processes this is the internal PID,
1159 * for guest files this is the internal file ID. */
1160 uint32_t mObjectID;
1161 /** @} */
1162};
1163#endif // !____H_GUESTIMPLPRIVATE
1164
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