VirtualBox

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

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

GuestCtrl: More stuff for IGuestFile and IGuestSession handling (work in progress).

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