VirtualBox

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

Last change on this file since 55541 was 55535, checked in by vboxsync, 10 years ago

Main,VBoxManage,VBoxShell,ValidationKit: Changed the IGuestSession:createProcess[Ex] interfaces to take argv[0] as input separate from the executable name. This is not yet implemented on the guest side.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 18.4 KB
Line 
1/* $Id: GuestCtrlImplPrivate.h 55535 2015-04-30 02:13:56Z vboxsync $ */
2/** @file
3 *
4 * Internal helpers/structures for guest control functionality.
5 */
6
7/*
8 * Copyright (C) 2011-2013 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
24#include <iprt/asm.h>
25#include <iprt/semaphore.h>
26
27#include <VBox/com/com.h>
28#include <VBox/com/ErrorInfo.h>
29#include <VBox/com/string.h>
30#include <VBox/com/VirtualBox.h>
31
32#include <map>
33#include <vector>
34
35using namespace com;
36
37#ifdef VBOX_WITH_GUEST_CONTROL
38# include <VBox/HostServices/GuestControlSvc.h>
39using namespace guestControl;
40#endif
41
42/** Vector holding a process' CPU affinity. */
43typedef std::vector <LONG> ProcessAffinity;
44/** Vector holding process startup arguments. */
45typedef std::vector <Utf8Str> ProcessArguments;
46
47class GuestProcessStreamBlock;
48class GuestSession;
49
50
51/**
52 * Simple structure mantaining guest credentials.
53 */
54struct GuestCredentials
55{
56 Utf8Str mUser;
57 Utf8Str mPassword;
58 Utf8Str mDomain;
59};
60
61
62typedef std::vector <Utf8Str> GuestEnvironmentArray;
63class GuestEnvironment
64{
65public:
66
67 int BuildEnvironmentBlock(void **ppvEnv, size_t *pcbEnv, uint32_t *pcEnvVars);
68
69 void Clear(void);
70
71 int CopyFrom(const GuestEnvironmentArray &environment);
72
73 int CopyTo(GuestEnvironmentArray &environment);
74
75 static void FreeEnvironmentBlock(void *pvEnv);
76
77 Utf8Str Get(const Utf8Str &strKey);
78
79 Utf8Str Get(size_t nPos);
80
81 bool Has(const Utf8Str &strKey);
82
83 int Set(const Utf8Str &strKey, const Utf8Str &strValue);
84
85 int Set(const Utf8Str &strPair);
86
87 size_t Size(void);
88
89 int Unset(const Utf8Str &strKey);
90
91public:
92
93 GuestEnvironment& operator=(const GuestEnvironmentArray &that);
94
95 GuestEnvironment& operator=(const GuestEnvironment &that);
96
97protected:
98
99 int appendToEnvBlock(const char *pszEnv, void **ppvList, size_t *pcbList, uint32_t *pcEnvVars);
100
101protected:
102
103 std::map <Utf8Str, Utf8Str> mEnvironment;
104};
105
106
107/**
108 * Structure for keeping all the relevant guest directory
109 * information around.
110 */
111struct GuestDirectoryOpenInfo
112{
113 /** The directory path. */
114 Utf8Str mPath;
115 /** Then open filter. */
116 Utf8Str mFilter;
117 /** Opening flags. */
118 uint32_t mFlags;
119};
120
121
122/**
123 * Structure for keeping all the relevant guest file
124 * information around.
125 */
126struct GuestFileOpenInfo
127{
128 /** The filename. */
129 Utf8Str mFileName;
130 /** Then file's opening mode. */
131 Utf8Str mOpenMode;
132 /** The file's disposition mode. */
133 Utf8Str mDisposition;
134 /** The file's sharing mode.
135 **@todo Not implemented yet.*/
136 Utf8Str mSharingMode;
137 /** Octal creation mode. */
138 uint32_t mCreationMode;
139 /** The initial offset on open. */
140 uint64_t mInitialOffset;
141};
142
143
144/**
145 * Structure representing information of a
146 * file system object.
147 */
148struct GuestFsObjData
149{
150 /** Helper function to extract the data from
151 * a certin VBoxService tool's guest stream block. */
152 int FromLs(const GuestProcessStreamBlock &strmBlk);
153 int FromMkTemp(const GuestProcessStreamBlock &strmBlk);
154 int FromStat(const GuestProcessStreamBlock &strmBlk);
155
156 int64_t mAccessTime;
157 int64_t mAllocatedSize;
158 int64_t mBirthTime;
159 int64_t mChangeTime;
160 uint32_t mDeviceNumber;
161 Utf8Str mFileAttrs;
162 uint32_t mGenerationID;
163 uint32_t mGID;
164 Utf8Str mGroupName;
165 uint32_t mNumHardLinks;
166 int64_t mModificationTime;
167 Utf8Str mName;
168 int64_t mNodeID;
169 uint32_t mNodeIDDevice;
170 int64_t mObjectSize;
171 FsObjType_T mType;
172 uint32_t mUID;
173 uint32_t mUserFlags;
174 Utf8Str mUserName;
175 Utf8Str mACL;
176};
177
178
179/**
180 * Structure for keeping all the relevant guest session
181 * startup parameters around.
182 */
183class GuestSessionStartupInfo
184{
185public:
186
187 GuestSessionStartupInfo(void)
188 : mIsInternal(false /* Non-internal session */),
189 mOpenTimeoutMS(30 * 1000 /* 30s opening timeout */),
190 mOpenFlags(0 /* No opening flags set */) { }
191
192 /** The session's friendly name. Optional. */
193 Utf8Str mName;
194 /** The session's unique ID. Used to encode
195 * a context ID. */
196 uint32_t mID;
197 /** Flag indicating if this is an internal session
198 * or not. Internal session are not accessible by
199 * public API clients. */
200 bool mIsInternal;
201 /** Timeout (in ms) used for opening the session. */
202 uint32_t mOpenTimeoutMS;
203 /** Session opening flags. */
204 uint32_t mOpenFlags;
205};
206
207
208/**
209 * Structure for keeping all the relevant guest process
210 * startup parameters around.
211 */
212class GuestProcessStartupInfo
213{
214public:
215
216 GuestProcessStartupInfo(void)
217 : mFlags(ProcessCreateFlag_None),
218 mTimeoutMS(30 * 1000 /* 30s timeout by default */),
219 mPriority(ProcessPriority_Default) { }
220
221 /** The process' friendly name. */
222 Utf8Str mName;
223 /** The executable. */
224 Utf8Str mExecutable;
225 /** Arguments vector (starting with argument \#0). */
226 ProcessArguments mArguments;
227 GuestEnvironment mEnvironment;
228 /** Process creation flags. */
229 uint32_t mFlags;
230 ULONG mTimeoutMS;
231 /** Process priority. */
232 ProcessPriority_T mPriority;
233 /** Process affinity. At the moment we
234 * only support 64 VCPUs. API and
235 * guest can do more already! */
236 uint64_t mAffinity;
237};
238
239
240/**
241 * Class representing the "value" side of a "key=value" pair.
242 */
243class GuestProcessStreamValue
244{
245public:
246
247 GuestProcessStreamValue(void) { }
248 GuestProcessStreamValue(const char *pszValue)
249 : mValue(pszValue) {}
250
251 GuestProcessStreamValue(const GuestProcessStreamValue& aThat)
252 : mValue(aThat.mValue) { }
253
254 Utf8Str mValue;
255};
256
257/** Map containing "key=value" pairs of a guest process stream. */
258typedef std::pair< Utf8Str, GuestProcessStreamValue > GuestCtrlStreamPair;
259typedef std::map < Utf8Str, GuestProcessStreamValue > GuestCtrlStreamPairMap;
260typedef std::map < Utf8Str, GuestProcessStreamValue >::iterator GuestCtrlStreamPairMapIter;
261typedef std::map < Utf8Str, GuestProcessStreamValue >::const_iterator GuestCtrlStreamPairMapIterConst;
262
263/**
264 * Class representing a block of stream pairs (key=value). Each block in a raw guest
265 * output stream is separated by "\0\0", each pair is separated by "\0". The overall
266 * end of a guest stream is marked by "\0\0\0\0".
267 */
268class GuestProcessStreamBlock
269{
270public:
271
272 GuestProcessStreamBlock(void);
273
274 virtual ~GuestProcessStreamBlock(void);
275
276public:
277
278 void Clear(void);
279
280#ifdef DEBUG
281 void DumpToLog(void) const;
282#endif
283
284 int GetInt64Ex(const char *pszKey, int64_t *piVal) const;
285
286 int64_t GetInt64(const char *pszKey) const;
287
288 size_t GetCount(void) const;
289
290 int GetRc(void) const;
291
292 const char* GetString(const char *pszKey) const;
293
294 int GetUInt32Ex(const char *pszKey, uint32_t *puVal) const;
295
296 uint32_t GetUInt32(const char *pszKey) const;
297
298 bool IsEmpty(void) { return mPairs.empty(); }
299
300 int SetValue(const char *pszKey, const char *pszValue);
301
302protected:
303
304 GuestCtrlStreamPairMap mPairs;
305};
306
307/** Vector containing multiple allocated stream pair objects. */
308typedef std::vector< GuestProcessStreamBlock > GuestCtrlStreamObjects;
309typedef std::vector< GuestProcessStreamBlock >::iterator GuestCtrlStreamObjectsIter;
310typedef std::vector< GuestProcessStreamBlock >::const_iterator GuestCtrlStreamObjectsIterConst;
311
312/**
313 * Class for parsing machine-readable guest process output by VBoxService'
314 * toolbox commands ("vbox_ls", "vbox_stat" etc), aka "guest stream".
315 */
316class GuestProcessStream
317{
318
319public:
320
321 GuestProcessStream();
322
323 virtual ~GuestProcessStream();
324
325public:
326
327 int AddData(const BYTE *pbData, size_t cbData);
328
329 void Destroy();
330
331#ifdef DEBUG
332 void Dump(const char *pszFile);
333#endif
334
335 uint32_t GetOffset() { return m_cbOffset; }
336
337 size_t GetSize() { return m_cbSize; }
338
339 int ParseBlock(GuestProcessStreamBlock &streamBlock);
340
341protected:
342
343 /** Currently allocated size of internal stream buffer. */
344 uint32_t m_cbAllocated;
345 /** Currently used size of allocated internal stream buffer. */
346 size_t m_cbSize;
347 /** Current offset within the internal stream buffer. */
348 uint32_t m_cbOffset;
349 /** Internal stream buffer. */
350 BYTE *m_pbBuffer;
351};
352
353class Guest;
354class Progress;
355
356class GuestTask
357{
358
359public:
360
361 enum TaskType
362 {
363 /** Copies a file from host to the guest. */
364 TaskType_CopyFileToGuest = 50,
365 /** Copies a file from guest to the host. */
366 TaskType_CopyFileFromGuest = 55,
367 /** Update Guest Additions by directly copying the required installer
368 * off the .ISO file, transfer it to the guest and execute the installer
369 * with system privileges. */
370 TaskType_UpdateGuestAdditions = 100
371 };
372
373 GuestTask(TaskType aTaskType, Guest *aThat, Progress *aProgress);
374
375 virtual ~GuestTask();
376
377 int startThread();
378
379 static int taskThread(RTTHREAD aThread, void *pvUser);
380 static int uploadProgress(unsigned uPercent, void *pvUser);
381 static HRESULT setProgressSuccess(ComObjPtr<Progress> pProgress);
382 static HRESULT setProgressErrorMsg(HRESULT hr,
383 ComObjPtr<Progress> pProgress, const char * pszText, ...);
384 static HRESULT setProgressErrorParent(HRESULT hr,
385 ComObjPtr<Progress> pProgress, ComObjPtr<Guest> pGuest);
386
387 TaskType taskType;
388 ComObjPtr<Guest> pGuest;
389 ComObjPtr<Progress> pProgress;
390 HRESULT rc;
391
392 /* Task data. */
393 Utf8Str strSource;
394 Utf8Str strDest;
395 Utf8Str strUserName;
396 Utf8Str strPassword;
397 ULONG uFlags;
398};
399
400class GuestWaitEventPayload
401{
402
403public:
404
405 GuestWaitEventPayload(void)
406 : uType(0),
407 cbData(0),
408 pvData(NULL) { }
409
410 GuestWaitEventPayload(uint32_t uTypePayload,
411 const void *pvPayload, uint32_t cbPayload)
412 {
413 if (cbPayload)
414 {
415 pvData = RTMemAlloc(cbPayload);
416 if (pvData)
417 {
418 uType = uTypePayload;
419
420 memcpy(pvData, pvPayload, cbPayload);
421 cbData = cbPayload;
422 }
423 else /* Throw IPRT error. */
424 throw VERR_NO_MEMORY;
425 }
426 else
427 {
428 uType = uTypePayload;
429
430 pvData = NULL;
431 cbData = 0;
432 }
433 }
434
435 virtual ~GuestWaitEventPayload(void)
436 {
437 Clear();
438 }
439
440 GuestWaitEventPayload& operator=(const GuestWaitEventPayload &that)
441 {
442 CopyFromDeep(that);
443 return *this;
444 }
445
446public:
447
448 void Clear(void)
449 {
450 if (pvData)
451 {
452 RTMemFree(pvData);
453 cbData = 0;
454 }
455 uType = 0;
456 }
457
458 int CopyFromDeep(const GuestWaitEventPayload &payload)
459 {
460 Clear();
461
462 int rc = VINF_SUCCESS;
463 if (payload.cbData)
464 {
465 Assert(payload.cbData);
466 pvData = RTMemAlloc(payload.cbData);
467 if (pvData)
468 {
469 memcpy(pvData, payload.pvData, payload.cbData);
470 cbData = payload.cbData;
471 uType = payload.uType;
472 }
473 else
474 rc = VERR_NO_MEMORY;
475 }
476
477 return rc;
478 }
479
480 const void* Raw(void) const { return pvData; }
481
482 size_t Size(void) const { return cbData; }
483
484 uint32_t Type(void) const { return uType; }
485
486 void* MutableRaw(void) { return pvData; }
487
488protected:
489
490 /** Type of payload. */
491 uint32_t uType;
492 /** Size (in bytes) of payload. */
493 uint32_t cbData;
494 /** Pointer to actual payload data. */
495 void *pvData;
496};
497
498class GuestWaitEventBase
499{
500
501protected:
502
503 GuestWaitEventBase(void);
504 virtual ~GuestWaitEventBase(void);
505
506public:
507
508 uint32_t ContextID(void) { return mCID; };
509 int GuestResult(void) { return mGuestRc; }
510 int Result(void) { return mRc; }
511 GuestWaitEventPayload & Payload(void) { return mPayload; }
512 int SignalInternal(int rc, int guestRc, const GuestWaitEventPayload *pPayload);
513 int Wait(RTMSINTERVAL uTimeoutMS);
514
515protected:
516
517 int Init(uint32_t uCID);
518
519protected:
520
521 /* Shutdown indicator. */
522 bool mfAborted;
523 /* Associated context ID (CID). */
524 uint32_t mCID;
525 /** The event semaphore for triggering
526 * the actual event. */
527 RTSEMEVENT mEventSem;
528 /** The event's overall result. If
529 * set to VERR_GSTCTL_GUEST_ERROR,
530 * mGuestRc will contain the actual
531 * error code from the guest side. */
532 int mRc;
533 /** The event'S overall result from the
534 * guest side. If used, mRc must be
535 * set to VERR_GSTCTL_GUEST_ERROR. */
536 int mGuestRc;
537 /** The event's payload data. Optional. */
538 GuestWaitEventPayload mPayload;
539};
540
541/** List of public guest event types. */
542typedef std::list < VBoxEventType_T > GuestEventTypes;
543
544class GuestWaitEvent : public GuestWaitEventBase
545{
546
547public:
548
549 GuestWaitEvent(uint32_t uCID);
550 GuestWaitEvent(uint32_t uCID, const GuestEventTypes &lstEvents);
551 virtual ~GuestWaitEvent(void);
552
553public:
554
555 int Cancel(void);
556 const ComPtr<IEvent> Event(void) { return mEvent; }
557 int SignalExternal(IEvent *pEvent);
558 const GuestEventTypes Types(void) { return mEventTypes; }
559 size_t TypeCount(void) { return mEventTypes.size(); }
560
561protected:
562
563 int Init(uint32_t uCID);
564
565protected:
566
567 /** List of public event types this event should
568 * be signalled on. Optional. */
569 GuestEventTypes mEventTypes;
570 /** Pointer to the actual public event, if any. */
571 ComPtr<IEvent> mEvent;
572};
573/** Map of pointers to guest events. The primary key
574 * contains the context ID. */
575typedef std::map < uint32_t, GuestWaitEvent* > GuestWaitEvents;
576/** Map of wait events per public guest event. Nice for
577 * faster lookups when signalling a whole event group. */
578typedef std::map < VBoxEventType_T, GuestWaitEvents > GuestEventGroup;
579
580class GuestBase
581{
582
583public:
584
585 GuestBase(void);
586 virtual ~GuestBase(void);
587
588public:
589
590 /** Signals a wait event using a public guest event; also used for
591 * for external event listeners. */
592 int signalWaitEvent(VBoxEventType_T aType, IEvent *aEvent);
593 /** Signals a wait event using a guest rc. */
594 int signalWaitEventInternal(PVBOXGUESTCTRLHOSTCBCTX pCbCtx, int guestRc, const GuestWaitEventPayload *pPayload);
595 /** Signals a wait event without letting public guest events know,
596 * extended director's cut version. */
597 int signalWaitEventInternalEx(PVBOXGUESTCTRLHOSTCBCTX pCbCtx, int rc, int guestRc, const GuestWaitEventPayload *pPayload);
598public:
599
600 int baseInit(void);
601 void baseUninit(void);
602 int cancelWaitEvents(void);
603 int dispatchGeneric(PVBOXGUESTCTRLHOSTCBCTX pCtxCb, PVBOXGUESTCTRLHOSTCALLBACK pSvcCb);
604 int generateContextID(uint32_t uSessionID, uint32_t uObjectID, uint32_t *puContextID);
605 int registerWaitEvent(uint32_t uSessionID, uint32_t uObjectID, GuestWaitEvent **ppEvent);
606 int registerWaitEvent(uint32_t uSessionID, uint32_t uObjectID, const GuestEventTypes &lstEvents, GuestWaitEvent **ppEvent);
607 void unregisterWaitEvent(GuestWaitEvent *pEvent);
608 int waitForEvent(GuestWaitEvent *pEvent, uint32_t uTimeoutMS, VBoxEventType_T *pType, IEvent **ppEvent);
609
610protected:
611
612 /** Pointer to the console object. Needed
613 * for HGCM (VMMDev) communication. */
614 Console *mConsole;
615 /** The next upcoming context ID for this object. */
616 uint32_t mNextContextID;
617 /** Local listener for handling the waiting events
618 * internally. */
619 ComPtr<IEventListener> mLocalListener;
620 /** Critical section for wait events access. */
621 RTCRITSECT mWaitEventCritSect;
622 /** Map of registered wait events per event group. */
623 GuestEventGroup mWaitEventGroups;
624 /** Map of registered wait events. */
625 GuestWaitEvents mWaitEvents;
626};
627
628/**
629 * Virtual class (interface) for guest objects (processes, files, ...) --
630 * contains all per-object callback management.
631 */
632class GuestObject : public GuestBase
633{
634
635public:
636
637 GuestObject(void);
638 virtual ~GuestObject(void);
639
640public:
641
642 ULONG getObjectID(void) { return mObjectID; }
643
644protected:
645
646 virtual int i_onRemove(void) = 0;
647
648 /** Callback dispatcher -- must be implemented by the actual object. */
649 virtual int i_callbackDispatcher(PVBOXGUESTCTRLHOSTCBCTX pCbCtx, PVBOXGUESTCTRLHOSTCALLBACK pSvcCb) = 0;
650
651protected:
652
653 int bindToSession(Console *pConsole, GuestSession *pSession, uint32_t uObjectID);
654 int registerWaitEvent(const GuestEventTypes &lstEvents, GuestWaitEvent **ppEvent);
655 int sendCommand(uint32_t uFunction, uint32_t uParms, PVBOXHGCMSVCPARM paParms);
656
657protected:
658
659 /**
660 * Commom parameters for all derived objects, when then have
661 * an own mData structure to keep their specific data around.
662 */
663
664 /** Pointer to parent session. Per definition
665 * this objects *always* lives shorter than the
666 * parent. */
667 GuestSession *mSession;
668 /** The object ID -- must be unique for each guest
669 * object and is encoded into the context ID. Must
670 * be set manually when initializing the object.
671 *
672 * For guest processes this is the internal PID,
673 * for guest files this is the internal file ID. */
674 uint32_t mObjectID;
675};
676#endif // ____H_GUESTIMPLPRIVATE
677
Note: See TracBrowser for help on using the repository browser.

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