VirtualBox

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

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

GuestCtrl: Infrastructure changes for handling and executing dedicated guest sessions and protocol versioning (untested, work in progress).

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 19.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 process
321 * starting parameters around.
322 */
323class GuestProcessStartupInfo
324{
325public:
326
327 GuestProcessStartupInfo(void)
328 : mFlags(ProcessCreateFlag_None),
329 mTimeoutMS(30 * 1000 /* 30s timeout by default */),
330 mPriority(ProcessPriority_Default) { }
331
332 /** The process' friendly name. */
333 Utf8Str mName;
334 /** The actual command to execute. */
335 Utf8Str mCommand;
336 ProcessArguments mArguments;
337 GuestEnvironment mEnvironment;
338 /** Process creation flags. */
339 uint32_t mFlags;
340 ULONG mTimeoutMS;
341 /** Process priority. */
342 ProcessPriority_T mPriority;
343 /** Process affinity. */
344 uint64_t mAffinity;
345};
346
347
348/**
349 * Class representing the "value" side of a "key=value" pair.
350 */
351class GuestProcessStreamValue
352{
353public:
354
355 GuestProcessStreamValue(void) { }
356 GuestProcessStreamValue(const char *pszValue)
357 : mValue(pszValue) {}
358
359 GuestProcessStreamValue(const GuestProcessStreamValue& aThat)
360 : mValue(aThat.mValue) { }
361
362 Utf8Str mValue;
363};
364
365/** Map containing "key=value" pairs of a guest process stream. */
366typedef std::pair< Utf8Str, GuestProcessStreamValue > GuestCtrlStreamPair;
367typedef std::map < Utf8Str, GuestProcessStreamValue > GuestCtrlStreamPairMap;
368typedef std::map < Utf8Str, GuestProcessStreamValue >::iterator GuestCtrlStreamPairMapIter;
369typedef std::map < Utf8Str, GuestProcessStreamValue >::const_iterator GuestCtrlStreamPairMapIterConst;
370
371/**
372 * Class representing a block of stream pairs (key=value). Each block in a raw guest
373 * output stream is separated by "\0\0", each pair is separated by "\0". The overall
374 * end of a guest stream is marked by "\0\0\0\0".
375 */
376class GuestProcessStreamBlock
377{
378public:
379
380 GuestProcessStreamBlock(void);
381
382 virtual ~GuestProcessStreamBlock(void);
383
384public:
385
386 void Clear(void);
387
388#ifdef DEBUG
389 void DumpToLog(void) const;
390#endif
391
392 int GetInt64Ex(const char *pszKey, int64_t *piVal) const;
393
394 int64_t GetInt64(const char *pszKey) const;
395
396 size_t GetCount(void) const;
397
398 const char* GetString(const char *pszKey) const;
399
400 int GetUInt32Ex(const char *pszKey, uint32_t *puVal) const;
401
402 uint32_t GetUInt32(const char *pszKey) const;
403
404 bool IsEmpty(void) { return mPairs.empty(); }
405
406 int SetValue(const char *pszKey, const char *pszValue);
407
408protected:
409
410 GuestCtrlStreamPairMap mPairs;
411};
412
413/** Vector containing multiple allocated stream pair objects. */
414typedef std::vector< GuestProcessStreamBlock > GuestCtrlStreamObjects;
415typedef std::vector< GuestProcessStreamBlock >::iterator GuestCtrlStreamObjectsIter;
416typedef std::vector< GuestProcessStreamBlock >::const_iterator GuestCtrlStreamObjectsIterConst;
417
418/**
419 * Class for parsing machine-readable guest process output by VBoxService'
420 * toolbox commands ("vbox_ls", "vbox_stat" etc), aka "guest stream".
421 */
422class GuestProcessStream
423{
424
425public:
426
427 GuestProcessStream();
428
429 virtual ~GuestProcessStream();
430
431public:
432
433 int AddData(const BYTE *pbData, size_t cbData);
434
435 void Destroy();
436
437#ifdef DEBUG
438 void Dump(const char *pszFile);
439#endif
440
441 uint32_t GetOffset();
442
443 uint32_t GetSize();
444
445 int ParseBlock(GuestProcessStreamBlock &streamBlock);
446
447protected:
448
449 /** Currently allocated size of internal stream buffer. */
450 uint32_t m_cbAllocated;
451 /** Currently used size of allocated internal stream buffer. */
452 uint32_t m_cbSize;
453 /** Current offset within the internal stream buffer. */
454 uint32_t m_cbOffset;
455 /** Internal stream buffer. */
456 BYTE *m_pbBuffer;
457};
458
459class Guest;
460class Progress;
461
462class GuestTask
463{
464
465public:
466
467 enum TaskType
468 {
469 /** Copies a file from host to the guest. */
470 TaskType_CopyFileToGuest = 50,
471 /** Copies a file from guest to the host. */
472 TaskType_CopyFileFromGuest = 55,
473 /** Update Guest Additions by directly copying the required installer
474 * off the .ISO file, transfer it to the guest and execute the installer
475 * with system privileges. */
476 TaskType_UpdateGuestAdditions = 100
477 };
478
479 GuestTask(TaskType aTaskType, Guest *aThat, Progress *aProgress);
480
481 virtual ~GuestTask();
482
483 int startThread();
484
485 static int taskThread(RTTHREAD aThread, void *pvUser);
486 static int uploadProgress(unsigned uPercent, void *pvUser);
487 static HRESULT setProgressSuccess(ComObjPtr<Progress> pProgress);
488 static HRESULT setProgressErrorMsg(HRESULT hr,
489 ComObjPtr<Progress> pProgress, const char * pszText, ...);
490 static HRESULT setProgressErrorParent(HRESULT hr,
491 ComObjPtr<Progress> pProgress, ComObjPtr<Guest> pGuest);
492
493 TaskType taskType;
494 ComObjPtr<Guest> pGuest;
495 ComObjPtr<Progress> pProgress;
496 HRESULT rc;
497
498 /* Task data. */
499 Utf8Str strSource;
500 Utf8Str strDest;
501 Utf8Str strUserName;
502 Utf8Str strPassword;
503 ULONG uFlags;
504};
505
506/**
507 * Pure virtual class (interface) for guest objects (processes, files, ...) --
508 * contains all per-object callback management.
509 */
510class GuestObject
511{
512
513public:
514
515 ULONG getObjectID(void) { return mObject.mObjectID; }
516
517protected:
518
519 /** Callback dispatcher -- must be implemented by the actual object. */
520 virtual int callbackDispatcher(PVBOXGUESTCTRLHOSTCBCTX pCbCtx, PVBOXGUESTCTRLHOSTCALLBACK pSvcCb) = 0;
521
522protected:
523
524 int bindToSession(Console *pConsole, GuestSession *pSession, uint32_t uObjectID);
525 int callbackAdd(GuestCtrlCallback *pCallback, uint32_t *puContextID);
526 bool callbackExists(uint32_t uContextID);
527 int callbackRemove(uint32_t uContextID);
528 int callbackRemoveAll(void);
529 int sendCommand(uint32_t uFunction, uint32_t uParms, PVBOXHGCMSVCPARM paParms);
530
531protected:
532
533 /**
534 * Commom structure for all derived objects, when then have
535 * an own mData structure to keep their specific data around.
536 */
537 struct Object
538 {
539 /** Pointer to parent session. Per definition
540 * this objects *always* lives shorter than the
541 * parent. */
542 GuestSession *mSession;
543 /** Pointer to the console object. Needed
544 * for HGCM (VMMDev) communication. */
545 Console *mConsole;
546 /** All related callbacks to this object. */
547 GuestCtrlCallbacks mCallbacks;
548 /** The next upcoming context ID for this object. */
549 ULONG mNextContextID;
550 /** The object ID -- must be unique for each guest
551 * session and is encoded into the context ID. Must
552 * be set manually when initializing the object.
553 *
554 * For guest processes this is the internal PID,
555 * for guest files this is the internal file ID. */
556 uint32_t mObjectID;
557 } mObject;
558};
559
560#if 0
561/*
562 * Guest (HGCM) callbacks. All classes will throw
563 * an exception on misuse.
564 */
565
566/** Callback class for guest process status. */
567class GuestCbProcessStatus : public GuestCtrlCallback
568{
569
570public:
571
572 int Init(uint32_t uProtocol, uint32_t uFunction,
573 PVBOXGUESTCTRLHOSTCALLBACK pSvcCb)
574 {
575 AssertPtrReturn(pSvcCb, VERR_INVALID_POINTER);
576
577 int rc = GuestCtrlCallback::Init();
578 if (RT_FAILURE(rc))
579 return rc;
580
581 if ( uFunction != GUEST_EXEC_SEND_STATUS
582 || pSvcCb->mParms < 5)
583 return VERR_INVALID_PARAMETER;
584
585 /* pSvcCb->mpaParms[0] always contains the context ID. */
586 pSvcCb->mpaParms[1].getUInt32(&mPID);
587 pSvcCb->mpaParms[2].getUInt32(&mStatus);
588 pSvcCb->mpaParms[3].getUInt32(&mFlags); /* Can contain an IPRT error, which is a signed int. */
589 pSvcCb->mpaParms[4].getPointer(&mData, &mcbData);
590
591 return VINF_SUCCESS;
592 }
593
594 void Destroy(void) { }
595
596 uint32_t mPID;
597 uint32_t mStatus;
598 uint32_t mFlags;
599 void *mData;
600 uint32_t mcbData;
601};
602
603/** Callback class for guest process input. */
604class GuestCbProcessInput : public GuestCtrlCallback
605{
606
607public:
608
609 int Init(uint32_t uProtocol, uint32_t uFunction,
610 PVBOXGUESTCTRLHOSTCALLBACK pSvcCb)
611 {
612 AssertPtrReturn(pSvcCb, VERR_INVALID_POINTER);
613
614 int rc = GuestCtrlCallback::Init();
615 if (RT_FAILURE(rc))
616 return rc;
617
618 if ( uFunction != GUEST_EXEC_SEND_INPUT_STATUS
619 || pSvcCb->mParms < 5)
620 return VERR_INVALID_PARAMETER;
621
622 /* pSvcCb->mpaParms[0] always contains the context ID. */
623 pSvcCb->mpaParms[1].getUInt32(&mPID);
624 /* Associated file handle. */
625 pSvcCb->mpaParms[2].getUInt32(&mStatus);
626 pSvcCb->mpaParms[3].getUInt32(&mFlags);
627 pSvcCb->mpaParms[4].getUInt32(&mProcessed);
628
629 return VINF_SUCCESS;
630 }
631
632 void Destroy(void) { }
633
634 GuestCbProcessInput& operator=(const GuestCbProcessInput &that)
635 {
636 mPID = that.mPID;
637 mStatus = that.mStatus;
638 mFlags = that.mFlags;
639 mProcessed = that.mProcessed;
640 return *this;
641 }
642
643 uint32_t mPID;
644 uint32_t mStatus;
645 uint32_t mFlags;
646 uint32_t mProcessed;
647};
648
649/** Callback class for guest process output. */
650class GuestCbProcessOutput : public GuestCtrlCallback
651{
652
653public:
654
655 int Init(uint32_t uProtocol, uint32_t uFunction,
656 PVBOXGUESTCTRLHOSTCALLBACK pSvcCb)
657 {
658 AssertPtrReturn(pSvcCb, VERR_INVALID_POINTER);
659
660 int rc = GuestCtrlCallback::Init();
661 if (RT_FAILURE(rc))
662 return rc;
663
664 if ( uFunction != GUEST_EXEC_SEND_OUTPUT
665 || pSvcCb->mParms < 5)
666 return VERR_INVALID_PARAMETER;
667
668 /* pSvcCb->mpaParms[0] always contains the context ID. */
669 pSvcCb->mpaParms[1].getUInt32(&mPID);
670 /* Associated file handle. */
671 pSvcCb->mpaParms[2].getUInt32(&mHandle);
672 pSvcCb->mpaParms[3].getUInt32(&mFlags);
673
674 void *pbData; uint32_t cbData;
675 rc = pSvcCb->mpaParms[4].getPointer(&pbData, &cbData);
676 if (RT_SUCCESS(rc))
677 {
678 Assert(cbData);
679 mData = RTMemAlloc(cbData);
680 AssertPtrReturn(mData, VERR_NO_MEMORY);
681 memcpy(mData, pbData, cbData);
682 mcbData = cbData;
683 }
684
685 return rc;
686 }
687
688 void Destroy(void)
689 {
690 if (mData)
691 {
692 RTMemFree(mData);
693 mData = NULL;
694 mcbData = 0;
695 }
696 }
697
698 GuestCbProcessOutput& operator=(const GuestCbProcessOutput &that)
699 {
700 mPID = that.mPID;
701 mHandle = that.mHandle;
702 mFlags = that.mFlags;
703
704 Destroy();
705 if (that.mcbData)
706 {
707 void *pvData = RTMemAlloc(that.mcbData);
708 if (pvData)
709 {
710 AssertPtr(pvData);
711 memcpy(pvData, that.mData, that.mcbData);
712 mData = pvData;
713 mcbData = that.mcbData;
714 }
715 }
716
717 return *this;
718 }
719
720 uint32_t mPID;
721 uint32_t mHandle;
722 uint32_t mFlags;
723 void *mData;
724 size_t mcbData;
725};
726
727/** Callback class for guest process IO notifications. */
728class GuestCbProcessIO : public GuestCtrlCallback
729{
730
731public:
732
733 int Init(uint32_t uProtocol, uint32_t uFunction,
734 PVBOXGUESTCTRLHOSTCALLBACK pSvcCb)
735 {
736 AssertPtrReturn(pSvcCb, VERR_INVALID_POINTER);
737
738 int rc = GuestCtrlCallback::Init();
739 if (RT_FAILURE(rc))
740 return rc;
741
742 return VERR_NOT_IMPLEMENTED;
743 }
744
745 void Destroy(void) { GuestCtrlCallback::Destroy(); }
746
747 GuestCbProcessIO& operator=(const GuestCbProcessIO &that)
748 {
749 return *this;
750 }
751};
752#endif
753#endif // ____H_GUESTIMPLPRIVATE
754
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