VirtualBox

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

最後變更 在這個檔案從98293是 98272,由 vboxsync 提交於 2 年 前

Main/Guest*: rc -> hrc/vrc. bugref:10223

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

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