VirtualBox

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

Last change on this file since 44935 was 44935, checked in by vboxsync, 12 years ago

GuestCtrl: More code for guest session infrastructure handling (untested, work in progress). Added IGuestSession.status for (later) asynchronous handling.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 20.0 KB
Line 
1/** @file
2 *
3 * Internal helpers/structures for guest control functionality.
4 */
5
6/*
7 * Copyright (C) 2011-2013 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18#ifndef ____H_GUESTIMPLPRIVATE
19#define ____H_GUESTIMPLPRIVATE
20
21#include "ConsoleImpl.h"
22
23#include <iprt/asm.h>
24#include <iprt/semaphore.h>
25
26#include <VBox/com/com.h>
27#include <VBox/com/ErrorInfo.h>
28#include <VBox/com/string.h>
29#include <VBox/com/VirtualBox.h>
30
31#include <map>
32#include <vector>
33
34using namespace com;
35
36#ifdef VBOX_WITH_GUEST_CONTROL
37# include <VBox/HostServices/GuestControlSvc.h>
38using namespace guestControl;
39#endif
40
41/** Vector holding a process' CPU affinity. */
42typedef std::vector <LONG> ProcessAffinity;
43/** Vector holding process startup arguments. */
44typedef std::vector <Utf8Str> ProcessArguments;
45
46class GuestProcessStreamBlock;
47class GuestSession;
48
49
50/**
51 * Base class for a all guest control callbacks/events.
52 */
53class GuestCtrlEvent
54{
55public:
56
57 GuestCtrlEvent(void);
58
59 virtual ~GuestCtrlEvent(void);
60
61 /** @todo Copy/comparison operator? */
62
63public:
64
65 int Cancel(void);
66
67 bool Canceled(void);
68
69 virtual void Destroy(void);
70
71 int Init(void);
72
73 virtual int Signal(int rc = VINF_SUCCESS);
74
75 int GetResultCode(void) { return mRC; }
76
77 int Wait(ULONG uTimeoutMS);
78
79protected:
80
81 /** Was the callback canceled? */
82 bool fCanceled;
83 /** Did the callback complete? */
84 bool fCompleted;
85 /** The event semaphore for triggering
86 * the actual event. */
87 RTSEMEVENT hEventSem;
88 /** The waiting mutex. */
89 RTSEMMUTEX hEventMutex;
90 /** Overall result code. */
91 int mRC;
92};
93
94
95/*
96 * Enumeration holding the host callback types.
97 */
98enum CALLBACKTYPE
99{
100 CALLBACKTYPE_UNKNOWN = 0,
101 /** Guest session status. */
102 CALLBACKTYPE_SESSION_NOTIFY = 10,
103 /** Guest process status. */
104 CALLBACKTYPE_PROC_STATUS = 100,
105 /** Guest process output notification. */
106 CALLBACKTYPE_PROC_OUTPUT = 105,
107 /** Guest process input notification. */
108 CALLBACKTYPE_PROC_INPUT = 106,
109 /** @todo Docs! */
110 CALLBACKTYPE_FILE_OPEN = 210,
111 CALLBACKTYPE_FILE_CLOSE = 215,
112 CALLBACKTYPE_FILE_READ = 230,
113 CALLBACKTYPE_FILE_WRITE = 240,
114 CALLBACKTYPE_FILE_SEEK = 250,
115 CALLBACKTYPE_FILE_TELL = 260
116};
117
118
119/*
120 * Class representing a guest control callback.
121 */
122class GuestCtrlCallback : public GuestCtrlEvent
123{
124
125public:
126
127 GuestCtrlCallback(void);
128
129 GuestCtrlCallback(CALLBACKTYPE enmType);
130
131 virtual ~GuestCtrlCallback(void);
132
133public:
134
135 void Destroy(void);
136
137 int Init(CALLBACKTYPE enmType);
138
139 CALLBACKTYPE GetCallbackType(void) { return mType; }
140
141 const void* GetDataRaw(void) const { return pvData; }
142
143 size_t GetDataSize(void) { return cbData; }
144
145 const void* GetPayloadRaw(void) const { return pvPayload; }
146
147 size_t GetPayloadSize(void) { return cbPayload; }
148
149 int SetData(const void *pvCallback, size_t cbCallback);
150
151 int SetPayload(const void *pvToWrite, size_t cbToWrite);
152
153protected:
154
155 /** Pointer to actual callback data. */
156 void *pvData;
157 /** Size of user-supplied data. */
158 size_t cbData;
159 /** The callback type. */
160 CALLBACKTYPE mType;
161 /** Callback flags. */
162 uint32_t uFlags;
163 /** Payload which will be available on successful
164 * waiting (optional). */
165 void *pvPayload;
166 /** Size of the payload (optional). */
167 size_t cbPayload;
168};
169typedef std::map < uint32_t, GuestCtrlCallback* > GuestCtrlCallbacks;
170
171
172/*
173 * Class representing a guest control process waiting
174 * event.
175 */
176class GuestProcessWaitEvent : public GuestCtrlEvent
177{
178public:
179
180 GuestProcessWaitEvent(void);
181
182 GuestProcessWaitEvent(uint32_t uWaitFlags);
183
184 virtual ~GuestProcessWaitEvent(void);
185
186public:
187
188 void Destroy(void);
189
190 int Init(uint32_t uWaitFlags);
191
192 uint32_t GetWaitFlags(void) { return ASMAtomicReadU32(&mFlags); }
193
194 ProcessWaitResult_T GetWaitResult(void) { return mResult; }
195
196 int GetWaitRc(void) { return mRC; }
197
198 int Signal(ProcessWaitResult_T enmResult, int rc = VINF_SUCCESS);
199
200protected:
201
202 /** The waiting flag(s). The specifies what to
203 * wait for. See ProcessWaitFlag_T. */
204 uint32_t mFlags;
205 /** Structure containing the overall result. */
206 ProcessWaitResult_T mResult;
207};
208
209
210/**
211 * Simple structure mantaining guest credentials.
212 */
213struct GuestCredentials
214{
215 Utf8Str mUser;
216 Utf8Str mPassword;
217 Utf8Str mDomain;
218};
219
220
221typedef std::vector <Utf8Str> GuestEnvironmentArray;
222class GuestEnvironment
223{
224public:
225
226 int BuildEnvironmentBlock(void **ppvEnv, size_t *pcbEnv, uint32_t *pcEnvVars);
227
228 void Clear(void);
229
230 int CopyFrom(const GuestEnvironmentArray &environment);
231
232 int CopyTo(GuestEnvironmentArray &environment);
233
234 static void FreeEnvironmentBlock(void *pvEnv);
235
236 Utf8Str Get(const Utf8Str &strKey);
237
238 Utf8Str Get(size_t nPos);
239
240 bool Has(const Utf8Str &strKey);
241
242 int Set(const Utf8Str &strKey, const Utf8Str &strValue);
243
244 int Set(const Utf8Str &strPair);
245
246 size_t Size(void);
247
248 int Unset(const Utf8Str &strKey);
249
250public:
251
252 GuestEnvironment& operator=(const GuestEnvironmentArray &that);
253
254 GuestEnvironment& operator=(const GuestEnvironment &that);
255
256protected:
257
258 int appendToEnvBlock(const char *pszEnv, void **ppvList, size_t *pcbList, uint32_t *pcEnvVars);
259
260protected:
261
262 std::map <Utf8Str, Utf8Str> mEnvironment;
263};
264
265
266/**
267 * Structure for keeping all the relevant guest file
268 * information around.
269 */
270struct GuestFileOpenInfo
271{
272 /** The filename. */
273 Utf8Str mFileName;
274 /** Then file's opening mode. */
275 Utf8Str mOpenMode;
276 /** The file's disposition mode. */
277 Utf8Str mDisposition;
278 /** Octal creation mode. */
279 uint32_t mCreationMode;
280 /** The initial offset on open. */
281 int64_t mInitialOffset;
282};
283
284
285/**
286 * Structure representing information of a
287 * file system object.
288 */
289struct GuestFsObjData
290{
291 /** Helper function to extract the data from
292 * a certin VBoxService tool's guest stream block. */
293 int FromLs(const GuestProcessStreamBlock &strmBlk);
294 int FromStat(const GuestProcessStreamBlock &strmBlk);
295
296 int64_t mAccessTime;
297 int64_t mAllocatedSize;
298 int64_t mBirthTime;
299 int64_t mChangeTime;
300 uint32_t mDeviceNumber;
301 Utf8Str mFileAttrs;
302 uint32_t mGenerationID;
303 uint32_t mGID;
304 Utf8Str mGroupName;
305 uint32_t mNumHardLinks;
306 int64_t mModificationTime;
307 Utf8Str mName;
308 int64_t mNodeID;
309 uint32_t mNodeIDDevice;
310 int64_t mObjectSize;
311 FsObjType_T mType;
312 uint32_t mUID;
313 uint32_t mUserFlags;
314 Utf8Str mUserName;
315 Utf8Str mACL;
316};
317
318
319/**
320 * Structure for keeping all the relevant guest session
321 * startup parameters around.
322 */
323class GuestSessionStartupInfo
324{
325public:
326
327 GuestSessionStartupInfo(void)
328 : mIsInternal(false /* Non-internal session */),
329 mOpenTimeoutMS(30 * 1000 /* 30s opening timeout */),
330 mOpenFlags(0 /* No opening flags set */) { }
331
332 /** The session's friendly name. Optional. */
333 Utf8Str mName;
334 /** The session's unique ID. Used to encode
335 * a context ID. */
336 uint32_t mID;
337 /** Flag indicating if this is an internal session
338 * or not. Internal session are not accessible by
339 * public API clients. */
340 bool mIsInternal;
341 /** Timeout (in ms) used for opening the session. */
342 uint32_t mOpenTimeoutMS;
343 /** Session opening flags. */
344 uint32_t mOpenFlags;
345};
346
347
348/**
349 * Structure for keeping all the relevant guest process
350 * startup parameters around.
351 */
352class GuestProcessStartupInfo
353{
354public:
355
356 GuestProcessStartupInfo(void)
357 : mFlags(ProcessCreateFlag_None),
358 mTimeoutMS(30 * 1000 /* 30s timeout by default */),
359 mPriority(ProcessPriority_Default) { }
360
361 /** The process' friendly name. */
362 Utf8Str mName;
363 /** The actual command to execute. */
364 Utf8Str mCommand;
365 ProcessArguments mArguments;
366 GuestEnvironment mEnvironment;
367 /** Process creation flags. */
368 uint32_t mFlags;
369 ULONG mTimeoutMS;
370 /** Process priority. */
371 ProcessPriority_T mPriority;
372 /** Process affinity. At the moment we
373 * only support 64 VCPUs. API and
374 * guest can do more already! */
375 uint64_t mAffinity;
376};
377
378
379/**
380 * Class representing the "value" side of a "key=value" pair.
381 */
382class GuestProcessStreamValue
383{
384public:
385
386 GuestProcessStreamValue(void) { }
387 GuestProcessStreamValue(const char *pszValue)
388 : mValue(pszValue) {}
389
390 GuestProcessStreamValue(const GuestProcessStreamValue& aThat)
391 : mValue(aThat.mValue) { }
392
393 Utf8Str mValue;
394};
395
396/** Map containing "key=value" pairs of a guest process stream. */
397typedef std::pair< Utf8Str, GuestProcessStreamValue > GuestCtrlStreamPair;
398typedef std::map < Utf8Str, GuestProcessStreamValue > GuestCtrlStreamPairMap;
399typedef std::map < Utf8Str, GuestProcessStreamValue >::iterator GuestCtrlStreamPairMapIter;
400typedef std::map < Utf8Str, GuestProcessStreamValue >::const_iterator GuestCtrlStreamPairMapIterConst;
401
402/**
403 * Class representing a block of stream pairs (key=value). Each block in a raw guest
404 * output stream is separated by "\0\0", each pair is separated by "\0". The overall
405 * end of a guest stream is marked by "\0\0\0\0".
406 */
407class GuestProcessStreamBlock
408{
409public:
410
411 GuestProcessStreamBlock(void);
412
413 virtual ~GuestProcessStreamBlock(void);
414
415public:
416
417 void Clear(void);
418
419#ifdef DEBUG
420 void DumpToLog(void) const;
421#endif
422
423 int GetInt64Ex(const char *pszKey, int64_t *piVal) const;
424
425 int64_t GetInt64(const char *pszKey) const;
426
427 size_t GetCount(void) const;
428
429 const char* GetString(const char *pszKey) const;
430
431 int GetUInt32Ex(const char *pszKey, uint32_t *puVal) const;
432
433 uint32_t GetUInt32(const char *pszKey) const;
434
435 bool IsEmpty(void) { return mPairs.empty(); }
436
437 int SetValue(const char *pszKey, const char *pszValue);
438
439protected:
440
441 GuestCtrlStreamPairMap mPairs;
442};
443
444/** Vector containing multiple allocated stream pair objects. */
445typedef std::vector< GuestProcessStreamBlock > GuestCtrlStreamObjects;
446typedef std::vector< GuestProcessStreamBlock >::iterator GuestCtrlStreamObjectsIter;
447typedef std::vector< GuestProcessStreamBlock >::const_iterator GuestCtrlStreamObjectsIterConst;
448
449/**
450 * Class for parsing machine-readable guest process output by VBoxService'
451 * toolbox commands ("vbox_ls", "vbox_stat" etc), aka "guest stream".
452 */
453class GuestProcessStream
454{
455
456public:
457
458 GuestProcessStream();
459
460 virtual ~GuestProcessStream();
461
462public:
463
464 int AddData(const BYTE *pbData, size_t cbData);
465
466 void Destroy();
467
468#ifdef DEBUG
469 void Dump(const char *pszFile);
470#endif
471
472 uint32_t GetOffset();
473
474 uint32_t GetSize();
475
476 int ParseBlock(GuestProcessStreamBlock &streamBlock);
477
478protected:
479
480 /** Currently allocated size of internal stream buffer. */
481 uint32_t m_cbAllocated;
482 /** Currently used size of allocated internal stream buffer. */
483 uint32_t m_cbSize;
484 /** Current offset within the internal stream buffer. */
485 uint32_t m_cbOffset;
486 /** Internal stream buffer. */
487 BYTE *m_pbBuffer;
488};
489
490class Guest;
491class Progress;
492
493class GuestTask
494{
495
496public:
497
498 enum TaskType
499 {
500 /** Copies a file from host to the guest. */
501 TaskType_CopyFileToGuest = 50,
502 /** Copies a file from guest to the host. */
503 TaskType_CopyFileFromGuest = 55,
504 /** Update Guest Additions by directly copying the required installer
505 * off the .ISO file, transfer it to the guest and execute the installer
506 * with system privileges. */
507 TaskType_UpdateGuestAdditions = 100
508 };
509
510 GuestTask(TaskType aTaskType, Guest *aThat, Progress *aProgress);
511
512 virtual ~GuestTask();
513
514 int startThread();
515
516 static int taskThread(RTTHREAD aThread, void *pvUser);
517 static int uploadProgress(unsigned uPercent, void *pvUser);
518 static HRESULT setProgressSuccess(ComObjPtr<Progress> pProgress);
519 static HRESULT setProgressErrorMsg(HRESULT hr,
520 ComObjPtr<Progress> pProgress, const char * pszText, ...);
521 static HRESULT setProgressErrorParent(HRESULT hr,
522 ComObjPtr<Progress> pProgress, ComObjPtr<Guest> pGuest);
523
524 TaskType taskType;
525 ComObjPtr<Guest> pGuest;
526 ComObjPtr<Progress> pProgress;
527 HRESULT rc;
528
529 /* Task data. */
530 Utf8Str strSource;
531 Utf8Str strDest;
532 Utf8Str strUserName;
533 Utf8Str strPassword;
534 ULONG uFlags;
535};
536
537/**
538 * Pure virtual class (interface) for guest objects (processes, files, ...) --
539 * contains all per-object callback management.
540 */
541class GuestObject
542{
543
544public:
545
546 ULONG getObjectID(void) { return mObject.mObjectID; }
547
548protected:
549
550 /** Callback dispatcher -- must be implemented by the actual object. */
551 virtual int callbackDispatcher(PVBOXGUESTCTRLHOSTCBCTX pCbCtx, PVBOXGUESTCTRLHOSTCALLBACK pSvcCb) = 0;
552
553protected:
554
555 int bindToSession(Console *pConsole, GuestSession *pSession, uint32_t uObjectID);
556 int callbackAdd(GuestCtrlCallback *pCallback, uint32_t *puContextID);
557 bool callbackExists(uint32_t uContextID);
558 int callbackRemove(uint32_t uContextID);
559 int callbackRemoveAll(void);
560 int sendCommand(uint32_t uFunction, uint32_t uParms, PVBOXHGCMSVCPARM paParms);
561
562protected:
563
564 /**
565 * Commom structure for all derived objects, when then have
566 * an own mData structure to keep their specific data around.
567 */
568 struct Object
569 {
570 /** Pointer to parent session. Per definition
571 * this objects *always* lives shorter than the
572 * parent. */
573 GuestSession *mSession;
574 /** Pointer to the console object. Needed
575 * for HGCM (VMMDev) communication. */
576 Console *mConsole;
577 /** All related callbacks to this object. */
578 GuestCtrlCallbacks mCallbacks;
579 /** The next upcoming context ID for this object. */
580 ULONG mNextContextID;
581 /** The object ID -- must be unique for each guest
582 * session and is encoded into the context ID. Must
583 * be set manually when initializing the object.
584 *
585 * For guest processes this is the internal PID,
586 * for guest files this is the internal file ID. */
587 uint32_t mObjectID;
588 } mObject;
589};
590
591#if 0
592/*
593 * Guest (HGCM) callbacks. All classes will throw
594 * an exception on misuse.
595 */
596
597/** Callback class for guest process status. */
598class GuestCbProcessStatus : public GuestCtrlCallback
599{
600
601public:
602
603 int Init(uint32_t uProtocol, uint32_t uFunction,
604 PVBOXGUESTCTRLHOSTCALLBACK pSvcCb)
605 {
606 AssertPtrReturn(pSvcCb, VERR_INVALID_POINTER);
607
608 int rc = GuestCtrlCallback::Init();
609 if (RT_FAILURE(rc))
610 return rc;
611
612 if ( uFunction != GUEST_EXEC_SEND_STATUS
613 || pSvcCb->mParms < 5)
614 return VERR_INVALID_PARAMETER;
615
616 /* pSvcCb->mpaParms[0] always contains the context ID. */
617 pSvcCb->mpaParms[1].getUInt32(&mPID);
618 pSvcCb->mpaParms[2].getUInt32(&mStatus);
619 pSvcCb->mpaParms[3].getUInt32(&mFlags); /* Can contain an IPRT error, which is a signed int. */
620 pSvcCb->mpaParms[4].getPointer(&mData, &mcbData);
621
622 return VINF_SUCCESS;
623 }
624
625 void Destroy(void) { }
626
627 uint32_t mPID;
628 uint32_t mStatus;
629 uint32_t mFlags;
630 void *mData;
631 uint32_t mcbData;
632};
633
634/** Callback class for guest process input. */
635class GuestCbProcessInput : public GuestCtrlCallback
636{
637
638public:
639
640 int Init(uint32_t uProtocol, uint32_t uFunction,
641 PVBOXGUESTCTRLHOSTCALLBACK pSvcCb)
642 {
643 AssertPtrReturn(pSvcCb, VERR_INVALID_POINTER);
644
645 int rc = GuestCtrlCallback::Init();
646 if (RT_FAILURE(rc))
647 return rc;
648
649 if ( uFunction != GUEST_EXEC_SEND_INPUT_STATUS
650 || pSvcCb->mParms < 5)
651 return VERR_INVALID_PARAMETER;
652
653 /* pSvcCb->mpaParms[0] always contains the context ID. */
654 pSvcCb->mpaParms[1].getUInt32(&mPID);
655 /* Associated file handle. */
656 pSvcCb->mpaParms[2].getUInt32(&mStatus);
657 pSvcCb->mpaParms[3].getUInt32(&mFlags);
658 pSvcCb->mpaParms[4].getUInt32(&mProcessed);
659
660 return VINF_SUCCESS;
661 }
662
663 void Destroy(void) { }
664
665 GuestCbProcessInput& operator=(const GuestCbProcessInput &that)
666 {
667 mPID = that.mPID;
668 mStatus = that.mStatus;
669 mFlags = that.mFlags;
670 mProcessed = that.mProcessed;
671 return *this;
672 }
673
674 uint32_t mPID;
675 uint32_t mStatus;
676 uint32_t mFlags;
677 uint32_t mProcessed;
678};
679
680/** Callback class for guest process output. */
681class GuestCbProcessOutput : public GuestCtrlCallback
682{
683
684public:
685
686 int Init(uint32_t uProtocol, uint32_t uFunction,
687 PVBOXGUESTCTRLHOSTCALLBACK pSvcCb)
688 {
689 AssertPtrReturn(pSvcCb, VERR_INVALID_POINTER);
690
691 int rc = GuestCtrlCallback::Init();
692 if (RT_FAILURE(rc))
693 return rc;
694
695 if ( uFunction != GUEST_EXEC_SEND_OUTPUT
696 || pSvcCb->mParms < 5)
697 return VERR_INVALID_PARAMETER;
698
699 /* pSvcCb->mpaParms[0] always contains the context ID. */
700 pSvcCb->mpaParms[1].getUInt32(&mPID);
701 /* Associated file handle. */
702 pSvcCb->mpaParms[2].getUInt32(&mHandle);
703 pSvcCb->mpaParms[3].getUInt32(&mFlags);
704
705 void *pbData; uint32_t cbData;
706 rc = pSvcCb->mpaParms[4].getPointer(&pbData, &cbData);
707 if (RT_SUCCESS(rc))
708 {
709 Assert(cbData);
710 mData = RTMemAlloc(cbData);
711 AssertPtrReturn(mData, VERR_NO_MEMORY);
712 memcpy(mData, pbData, cbData);
713 mcbData = cbData;
714 }
715
716 return rc;
717 }
718
719 void Destroy(void)
720 {
721 if (mData)
722 {
723 RTMemFree(mData);
724 mData = NULL;
725 mcbData = 0;
726 }
727 }
728
729 GuestCbProcessOutput& operator=(const GuestCbProcessOutput &that)
730 {
731 mPID = that.mPID;
732 mHandle = that.mHandle;
733 mFlags = that.mFlags;
734
735 Destroy();
736 if (that.mcbData)
737 {
738 void *pvData = RTMemAlloc(that.mcbData);
739 if (pvData)
740 {
741 AssertPtr(pvData);
742 memcpy(pvData, that.mData, that.mcbData);
743 mData = pvData;
744 mcbData = that.mcbData;
745 }
746 }
747
748 return *this;
749 }
750
751 uint32_t mPID;
752 uint32_t mHandle;
753 uint32_t mFlags;
754 void *mData;
755 size_t mcbData;
756};
757
758/** Callback class for guest process IO notifications. */
759class GuestCbProcessIO : public GuestCtrlCallback
760{
761
762public:
763
764 int Init(uint32_t uProtocol, uint32_t uFunction,
765 PVBOXGUESTCTRLHOSTCALLBACK pSvcCb)
766 {
767 AssertPtrReturn(pSvcCb, VERR_INVALID_POINTER);
768
769 int rc = GuestCtrlCallback::Init();
770 if (RT_FAILURE(rc))
771 return rc;
772
773 return VERR_NOT_IMPLEMENTED;
774 }
775
776 void Destroy(void) { GuestCtrlCallback::Destroy(); }
777
778 GuestCbProcessIO& operator=(const GuestCbProcessIO &that)
779 {
780 return *this;
781 }
782};
783#endif
784#endif // ____H_GUESTIMPLPRIVATE
785
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