VirtualBox

source: vbox/trunk/src/VBox/Main/include/GuestSessionImpl.h@ 55613

Last change on this file since 55613 was 55613, checked in by vboxsync, 9 years ago

IGuestSession: Added a pathStyle attribute (read-only) that translates the OS type reported by the guest additions into a DOS, UNIX or Unknown path styles values. Added two methods fsExists and fsQueryInfo that aren't as narrow minded as fileQueryInfo and directoryQueryInfo and has parameters for how to treat symbolic links.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 22.3 KB
Line 
1/* $Id: GuestSessionImpl.h 55613 2015-05-03 04:12:35Z vboxsync $ */
2/** @file
3 * VirtualBox Main - Guest session handling.
4 */
5
6/*
7 * Copyright (C) 2012-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_GUESTSESSIONIMPL
19#define ____H_GUESTSESSIONIMPL
20
21#include "GuestSessionWrap.h"
22#include "EventImpl.h"
23
24#include "GuestCtrlImplPrivate.h"
25#include "GuestProcessImpl.h"
26#include "GuestDirectoryImpl.h"
27#include "GuestFileImpl.h"
28#include "GuestFsObjInfoImpl.h"
29
30#include <iprt/isofs.h> /* For UpdateAdditions. */
31
32class Guest;
33
34/**
35 * Abstract base class for a lenghtly per-session operation which
36 * runs in a Main worker thread.
37 */
38class GuestSessionTask
39{
40public:
41
42 GuestSessionTask(GuestSession *pSession);
43
44 virtual ~GuestSessionTask(void);
45
46public:
47
48 virtual int Run(void) = 0;
49 virtual int RunAsync(const Utf8Str &strDesc, ComObjPtr<Progress> &pProgress) = 0;
50
51protected:
52
53 int getGuestProperty(const ComObjPtr<Guest> &pGuest,
54 const Utf8Str &strPath, Utf8Str &strValue);
55 int setProgress(ULONG uPercent);
56 int setProgressSuccess(void);
57 HRESULT setProgressErrorMsg(HRESULT hr, const Utf8Str &strMsg);
58
59protected:
60
61 Utf8Str mDesc;
62 GuestSession *mSession;
63 /** Progress object for getting updated when running
64 * asynchronously. Optional. */
65 ComObjPtr<Progress> mProgress;
66};
67
68/**
69 * Task for opening a guest session.
70 */
71class SessionTaskOpen : public GuestSessionTask
72{
73public:
74
75 SessionTaskOpen(GuestSession *pSession,
76 uint32_t uFlags,
77 uint32_t uTimeoutMS);
78
79 virtual ~SessionTaskOpen(void);
80
81public:
82
83 int Run(int *pGuestRc);
84 int RunAsync(const Utf8Str &strDesc, ComObjPtr<Progress> &pProgress);
85 static int taskThread(RTTHREAD Thread, void *pvUser);
86
87protected:
88
89 /** Session creation flags. */
90 uint32_t mFlags;
91 /** Session creation timeout (in ms). */
92 uint32_t mTimeoutMS;
93};
94
95/**
96 * Task for copying files from host to the guest.
97 */
98class SessionTaskCopyTo : public GuestSessionTask
99{
100public:
101
102 SessionTaskCopyTo(GuestSession *pSession,
103 const Utf8Str &strSource, const Utf8Str &strDest, uint32_t uFlags);
104
105 SessionTaskCopyTo(GuestSession *pSession,
106 PRTFILE pSourceFile, size_t cbSourceOffset, uint64_t cbSourceSize,
107 const Utf8Str &strDest, uint32_t uFlags);
108
109 virtual ~SessionTaskCopyTo(void);
110
111public:
112
113 int Run(void);
114 int RunAsync(const Utf8Str &strDesc, ComObjPtr<Progress> &pProgress);
115 static int taskThread(RTTHREAD Thread, void *pvUser);
116
117protected:
118
119 Utf8Str mSource;
120 PRTFILE mSourceFile;
121 size_t mSourceOffset;
122 uint64_t mSourceSize;
123 Utf8Str mDest;
124 uint32_t mCopyFileFlags;
125};
126
127/**
128 * Task for copying files from guest to the host.
129 */
130class SessionTaskCopyFrom : public GuestSessionTask
131{
132public:
133
134 SessionTaskCopyFrom(GuestSession *pSession,
135 const Utf8Str &strSource, const Utf8Str &strDest, uint32_t uFlags);
136
137 virtual ~SessionTaskCopyFrom(void);
138
139public:
140
141 int Run(void);
142 int RunAsync(const Utf8Str &strDesc, ComObjPtr<Progress> &pProgress);
143 static int taskThread(RTTHREAD Thread, void *pvUser);
144
145protected:
146
147 Utf8Str mSource;
148 Utf8Str mDest;
149 uint32_t mFlags;
150};
151
152/**
153 * Task for automatically updating the Guest Additions on the guest.
154 */
155class SessionTaskUpdateAdditions : public GuestSessionTask
156{
157public:
158
159 SessionTaskUpdateAdditions(GuestSession *pSession,
160 const Utf8Str &strSource, const ProcessArguments &aArguments,
161 uint32_t uFlags);
162
163 virtual ~SessionTaskUpdateAdditions(void);
164
165public:
166
167 int Run(void);
168 int RunAsync(const Utf8Str &strDesc, ComObjPtr<Progress> &pProgress);
169 static int taskThread(RTTHREAD Thread, void *pvUser);
170
171protected:
172
173 /**
174 * Suported OS types for automatic updating.
175 */
176 enum eOSType
177 {
178 eOSType_Unknown = 0,
179 eOSType_Windows = 1,
180 eOSType_Linux = 2,
181 eOSType_Solaris = 3
182 };
183
184 /**
185 * Structure representing a file to
186 * get off the .ISO, copied to the guest.
187 */
188 struct InstallerFile
189 {
190 InstallerFile(const Utf8Str &aSource,
191 const Utf8Str &aDest,
192 uint32_t aFlags = 0)
193 : strSource(aSource),
194 strDest(aDest),
195 fFlags(aFlags) { }
196
197 InstallerFile(const Utf8Str &aSource,
198 const Utf8Str &aDest,
199 uint32_t aFlags,
200 GuestProcessStartupInfo startupInfo)
201 : strSource(aSource),
202 strDest(aDest),
203 fFlags(aFlags),
204 mProcInfo(startupInfo)
205 {
206 mProcInfo.mExecutable = strDest;
207 if (mProcInfo.mName.isEmpty())
208 mProcInfo.mName = strDest;
209 }
210
211 /** Source file on .ISO. */
212 Utf8Str strSource;
213 /** Destination file on the guest. */
214 Utf8Str strDest;
215 /** File flags. */
216 uint32_t fFlags;
217 /** Optional arguments if this file needs to be
218 * executed. */
219 GuestProcessStartupInfo mProcInfo;
220 };
221
222 int i_addProcessArguments(ProcessArguments &aArgumentsDest,
223 const ProcessArguments &aArgumentsSource);
224 int i_copyFileToGuest(GuestSession *pSession, PRTISOFSFILE pISO,
225 Utf8Str const &strFileSource, const Utf8Str &strFileDest,
226 bool fOptional, uint32_t *pcbSize);
227 int i_runFileOnGuest(GuestSession *pSession, GuestProcessStartupInfo &procInfo);
228
229 /** Files to handle. */
230 std::vector<InstallerFile> mFiles;
231 /** The (optionally) specified Guest Additions .ISO on the host
232 * which will be used for the updating process. */
233 Utf8Str mSource;
234 /** (Optional) installer command line arguments. */
235 ProcessArguments mArguments;
236 /** Update flags. */
237 uint32_t mFlags;
238};
239
240/**
241 * Guest session implementation.
242 */
243class ATL_NO_VTABLE GuestSession :
244 public GuestSessionWrap,
245 public GuestBase
246{
247public:
248 /** @name COM and internal init/term/mapping cruft.
249 * @{ */
250 DECLARE_EMPTY_CTOR_DTOR(GuestSession)
251
252 int init(Guest *pGuest, const GuestSessionStartupInfo &ssInfo, const GuestCredentials &guestCreds);
253 void uninit(void);
254 HRESULT FinalConstruct(void);
255 void FinalRelease(void);
256 /** @} */
257
258private:
259
260 /** Wrapped @name IGuestSession properties.
261 * @{ */
262 HRESULT getUser(com::Utf8Str &aUser);
263 HRESULT getDomain(com::Utf8Str &aDomain);
264 HRESULT getName(com::Utf8Str &aName);
265 HRESULT getId(ULONG *aId);
266 HRESULT getTimeout(ULONG *aTimeout);
267 HRESULT setTimeout(ULONG aTimeout);
268 HRESULT getProtocolVersion(ULONG *aProtocolVersion);
269 HRESULT getStatus(GuestSessionStatus_T *aStatus);
270 HRESULT getEnvironmentChanges(std::vector<com::Utf8Str> &aEnvironmentChanges);
271 HRESULT setEnvironmentChanges(const std::vector<com::Utf8Str> &aEnvironmentChanges);
272 HRESULT getEnvironmentBase(std::vector<com::Utf8Str> &aEnvironmentBase);
273 HRESULT getProcesses(std::vector<ComPtr<IGuestProcess> > &aProcesses);
274 HRESULT getPathStyle(PathStyle_T *aPathStyle);
275 HRESULT getDirectories(std::vector<ComPtr<IGuestDirectory> > &aDirectories);
276 HRESULT getFiles(std::vector<ComPtr<IGuestFile> > &aFiles);
277 HRESULT getEventSource(ComPtr<IEventSource> &aEventSource);
278 /** @} */
279
280 /** Wrapped @name IGuestSession methods.
281 * @{ */
282 HRESULT close();
283 HRESULT copyFrom(const com::Utf8Str &aSource,
284 const com::Utf8Str &aDest,
285 const std::vector<CopyFileFlag_T> &aFlags,
286 ComPtr<IProgress> &aProgress);
287 HRESULT copyTo(const com::Utf8Str &aSource,
288 const com::Utf8Str &aDest,
289 const std::vector<CopyFileFlag_T> &aFlags,
290 ComPtr<IProgress> &aProgress);
291 HRESULT directoryCreate(const com::Utf8Str &aPath,
292 ULONG aMode,
293 const std::vector<DirectoryCreateFlag_T> &aFlags);
294 HRESULT directoryCreateTemp(const com::Utf8Str &aTemplateName,
295 ULONG aMode,
296 const com::Utf8Str &aPath,
297 BOOL aSecure,
298 com::Utf8Str &aDirectory);
299 HRESULT directoryExists(const com::Utf8Str &aPath,
300 BOOL *aExists);
301 HRESULT directoryOpen(const com::Utf8Str &aPath,
302 const com::Utf8Str &aFilter,
303 const std::vector<DirectoryOpenFlag_T> &aFlags,
304 ComPtr<IGuestDirectory> &aDirectory);
305 HRESULT directoryQueryInfo(const com::Utf8Str &aPath,
306 ComPtr<IGuestFsObjInfo> &aInfo);
307 HRESULT directoryRemove(const com::Utf8Str &aPath);
308 HRESULT directoryRemoveRecursive(const com::Utf8Str &aPath,
309 const std::vector<DirectoryRemoveRecFlag_T> &aFlags,
310 ComPtr<IProgress> &aProgress);
311 HRESULT directoryRename(const com::Utf8Str &aSource,
312 const com::Utf8Str &aDest,
313 const std::vector<PathRenameFlag_T> &aFlags);
314 HRESULT directorySetACL(const com::Utf8Str &aPath,
315 const com::Utf8Str &aAcl);
316 HRESULT environmentScheduleSet(const com::Utf8Str &aName,
317 const com::Utf8Str &aValue);
318 HRESULT environmentScheduleUnset(const com::Utf8Str &aName);
319 HRESULT environmentGetBaseVariable(const com::Utf8Str &aName,
320 com::Utf8Str &aValue);
321 HRESULT environmentDoesBaseVariableExist(const com::Utf8Str &aName,
322 BOOL *aExists);
323 HRESULT fileCreateTemp(const com::Utf8Str &aTemplateName,
324 ULONG aMode,
325 const com::Utf8Str &aPath,
326 BOOL aSecure,
327 ComPtr<IGuestFile> &aFile);
328 HRESULT fileExists(const com::Utf8Str &aPath,
329 BOOL *aExists);
330 HRESULT fileRemove(const com::Utf8Str &aPath);
331 HRESULT fileOpen(const com::Utf8Str &aPath,
332 const com::Utf8Str &aOpenMode,
333 const com::Utf8Str &aDisposition,
334 ULONG aCreationMode,
335 ComPtr<IGuestFile> &aFile);
336 HRESULT fileOpenEx(const com::Utf8Str &aPath,
337 const com::Utf8Str &aOpenMode,
338 const com::Utf8Str &aDisposition,
339 const com::Utf8Str &aSharingMode,
340 ULONG aCreationMode,
341 LONG64 aOffset,
342 ComPtr<IGuestFile> &aFile);
343 HRESULT fileQueryInfo(const com::Utf8Str &aPath,
344 ComPtr<IGuestFsObjInfo> &aInfo);
345 HRESULT fileQuerySize(const com::Utf8Str &aPath,
346 LONG64 *aSize);
347 HRESULT fileRename(const com::Utf8Str &aSource,
348 const com::Utf8Str &aDest,
349 const std::vector<PathRenameFlag_T> &aFlags);
350 HRESULT fileSetACL(const com::Utf8Str &aFile,
351 const com::Utf8Str &aAcl);
352 HRESULT fsExists(const com::Utf8Str &aPath,
353 BOOL aFollowSymlinks,
354 BOOL *pfExists);
355 HRESULT fsQueryInfo(const com::Utf8Str &aPath,
356 BOOL aFollowSymlinks,
357 ComPtr<IGuestFsObjInfo> &aInfo);
358 HRESULT processCreate(const com::Utf8Str &aCommand,
359 const std::vector<com::Utf8Str> &aArguments,
360 const std::vector<com::Utf8Str> &aEnvironment,
361 const std::vector<ProcessCreateFlag_T> &aFlags,
362 ULONG aTimeoutMS,
363 ComPtr<IGuestProcess> &aGuestProcess);
364 HRESULT processCreateEx(const com::Utf8Str &aCommand,
365 const std::vector<com::Utf8Str> &aArguments,
366 const std::vector<com::Utf8Str> &aEnvironment,
367 const std::vector<ProcessCreateFlag_T> &aFlags,
368 ULONG aTimeoutMS,
369 ProcessPriority_T aPriority,
370 const std::vector<LONG> &aAffinity,
371 ComPtr<IGuestProcess> &aGuestProcess);
372 HRESULT processGet(ULONG aPid,
373 ComPtr<IGuestProcess> &aGuestProcess);
374 HRESULT symlinkCreate(const com::Utf8Str &aSource,
375 const com::Utf8Str &aTarget,
376 SymlinkType_T aType);
377 HRESULT symlinkExists(const com::Utf8Str &aSymlink,
378 BOOL *aExists);
379 HRESULT symlinkRead(const com::Utf8Str &aSymlink,
380 const std::vector<SymlinkReadFlag_T> &aFlags,
381 com::Utf8Str &aTarget);
382 HRESULT symlinkRemoveDirectory(const com::Utf8Str &aPath);
383 HRESULT symlinkRemoveFile(const com::Utf8Str &aFile);
384 HRESULT waitFor(ULONG aWaitFor,
385 ULONG aTimeoutMS,
386 GuestSessionWaitResult_T *aReason);
387 HRESULT waitForArray(const std::vector<GuestSessionWaitForFlag_T> &aWaitFor,
388 ULONG aTimeoutMS,
389 GuestSessionWaitResult_T *aReason);
390 /** @} */
391
392 /** Map of guest directories. The key specifies the internal directory ID. */
393 typedef std::map <uint32_t, ComObjPtr<GuestDirectory> > SessionDirectories;
394 /** Map of guest files. The key specifies the internal file ID. */
395 typedef std::map <uint32_t, ComObjPtr<GuestFile> > SessionFiles;
396 /** Map of guest processes. The key specifies the internal process number.
397 * To retrieve the process' guest PID use the Id() method of the IProcess interface. */
398 typedef std::map <uint32_t, ComObjPtr<GuestProcess> > SessionProcesses;
399
400public:
401 /** @name Public internal methods.
402 * @todo r=bird: Most of these are public for no real reason...
403 * @{ */
404 int i_closeSession(uint32_t uFlags, uint32_t uTimeoutMS, int *pGuestRc);
405 inline bool i_directoryExists(uint32_t uDirID, ComObjPtr<GuestDirectory> *pDir);
406 int i_directoryRemoveFromList(GuestDirectory *pDirectory);
407 int i_directoryRemoveInternal(const Utf8Str &strPath, uint32_t uFlags, int *pGuestRc);
408 int i_directoryCreateInternal(const Utf8Str &strPath, uint32_t uMode, uint32_t uFlags, int *pGuestRc);
409 int i_objectCreateTempInternal(const Utf8Str &strTemplate, const Utf8Str &strPath, bool fDirectory,
410 Utf8Str &strName, int *pGuestRc);
411 int i_directoryOpenInternal(const GuestDirectoryOpenInfo &openInfo,
412 ComObjPtr<GuestDirectory> &pDirectory, int *pGuestRc);
413 int i_directoryQueryInfoInternal(const Utf8Str &strPath, bool fFollowSymlinks, GuestFsObjData &objData, int *pGuestRc);
414 int i_dispatchToDirectory(PVBOXGUESTCTRLHOSTCBCTX pCtxCb, PVBOXGUESTCTRLHOSTCALLBACK pSvcCb);
415 int i_dispatchToFile(PVBOXGUESTCTRLHOSTCBCTX pCtxCb, PVBOXGUESTCTRLHOSTCALLBACK pSvcCb);
416 int i_dispatchToObject(PVBOXGUESTCTRLHOSTCBCTX pCtxCb, PVBOXGUESTCTRLHOSTCALLBACK pSvcCb);
417 int i_dispatchToProcess(PVBOXGUESTCTRLHOSTCBCTX pCtxCb, PVBOXGUESTCTRLHOSTCALLBACK pSvcCb);
418 int i_dispatchToThis(PVBOXGUESTCTRLHOSTCBCTX pCtxCb, PVBOXGUESTCTRLHOSTCALLBACK pSvcCb);
419 inline bool i_fileExists(uint32_t uFileID, ComObjPtr<GuestFile> *pFile);
420 int i_fileRemoveFromList(GuestFile *pFile);
421 int i_fileRemoveInternal(const Utf8Str &strPath, int *pGuestRc);
422 int i_fileOpenInternal(const GuestFileOpenInfo &openInfo, ComObjPtr<GuestFile> &pFile, int *pGuestRc);
423 int i_fileQueryInfoInternal(const Utf8Str &strPath, bool fFollowSymlinks, GuestFsObjData &objData, int *pGuestRc);
424 int i_fileQuerySizeInternal(const Utf8Str &strPath, int64_t *pllSize, int *pGuestRc);
425 int i_fsQueryInfoInternal(const Utf8Str &strPath, bool fFollowSymlinks, GuestFsObjData &objData, int *pGuestRc);
426 const GuestCredentials &i_getCredentials(void);
427 EventSource *i_getEventSource(void) { return mEventSource; }
428 Utf8Str i_getName(void);
429 ULONG i_getId(void) { return mData.mSession.mID; }
430 static Utf8Str i_guestErrorToString(int guestRc);
431 HRESULT i_isReadyExternal(void);
432 int i_onRemove(void);
433 int i_onSessionStatusChange(PVBOXGUESTCTRLHOSTCBCTX pCbCtx, PVBOXGUESTCTRLHOSTCALLBACK pSvcCbData);
434 int i_startSessionInternal(int *pGuestRc);
435 int i_startSessionAsync(void);
436 static DECLCALLBACK(int)
437 i_startSessionThread(RTTHREAD Thread, void *pvUser);
438 Guest *i_getParent(void) { return mParent; }
439 uint32_t i_getProtocolVersion(void) { return mData.mProtocolVersion; }
440 int i_pathRenameInternal(const Utf8Str &strSource, const Utf8Str &strDest, uint32_t uFlags,
441 int *pGuestRc);
442 int i_processRemoveFromList(GuestProcess *pProcess);
443 int i_processCreateExInternal(GuestProcessStartupInfo &procInfo, ComObjPtr<GuestProcess> &pProgress);
444 inline bool i_processExists(uint32_t uProcessID, ComObjPtr<GuestProcess> *pProcess);
445 inline int i_processGetByPID(ULONG uPID, ComObjPtr<GuestProcess> *pProcess);
446 int i_sendCommand(uint32_t uFunction, uint32_t uParms, PVBOXHGCMSVCPARM paParms);
447 static HRESULT i_setErrorExternal(VirtualBoxBase *pInterface, int guestRc);
448 int i_setSessionStatus(GuestSessionStatus_T sessionStatus, int sessionRc);
449 int i_signalWaiters(GuestSessionWaitResult_T enmWaitResult, int rc /*= VINF_SUCCESS */);
450 int i_startTaskAsync(const Utf8Str &strTaskDesc, GuestSessionTask *pTask,
451 ComObjPtr<Progress> &pProgress);
452 int i_determineProtocolVersion(void);
453 int i_waitFor(uint32_t fWaitFlags, ULONG uTimeoutMS, GuestSessionWaitResult_T &waitResult, int *pGuestRc);
454 int i_waitForStatusChange(GuestWaitEvent *pEvent, uint32_t fWaitFlags, uint32_t uTimeoutMS,
455 GuestSessionStatus_T *pSessionStatus, int *pGuestRc);
456 /** @} */
457
458private:
459
460 /** Pointer to the parent (Guest). */
461 Guest *mParent;
462 /**
463 * The session's event source. This source is used for
464 * serving the internal listener as well as all other
465 * external listeners that may register to it.
466 *
467 * Note: This can safely be used without holding any locks.
468 * An AutoCaller suffices to prevent it being destroy while in use and
469 * internally there is a lock providing the necessary serialization.
470 */
471 const ComObjPtr<EventSource> mEventSource;
472
473 struct Data
474 {
475 /** The session credentials. */
476 GuestCredentials mCredentials;
477 /** The session's startup info. */
478 GuestSessionStartupInfo mSession;
479 /** The session's current status. */
480 GuestSessionStatus_T mStatus;
481 /** The set of environment changes for the session for use when
482 * creating new guest processes. */
483 GuestEnvironmentChanges mEnvironmentChanges;
484 /** Pointer to the immutable base environment for the session.
485 * @note This is not allocated until the guest reports it to the host. It is
486 * also shared with child processes. */
487 GuestEnvironment const *mpBaseEnvironment;
488 /** Directory objects bound to this session. */
489 SessionDirectories mDirectories;
490 /** File objects bound to this session. */
491 SessionFiles mFiles;
492 /** Process objects bound to this session. */
493 SessionProcesses mProcesses;
494 /** Guest control protocol version to be used.
495 * Guest Additions < VBox 4.3 have version 1,
496 * any newer version will have version 2. */
497 uint32_t mProtocolVersion;
498 /** Session timeout (in ms). */
499 uint32_t mTimeout;
500 /** Total number of session objects (processes,
501 * files, ...). */
502 uint32_t mNumObjects;
503 /** The last returned session status
504 * returned from the guest side. */
505 int mRC;
506
507 Data(void)
508 : mpBaseEnvironment(NULL)
509 { }
510 Data(const Data &rThat)
511 : mCredentials(rThat.mCredentials)
512 , mSession(rThat.mSession)
513 , mStatus(rThat.mStatus)
514 , mEnvironmentChanges(rThat.mEnvironmentChanges)
515 , mpBaseEnvironment(NULL)
516 , mDirectories(rThat.mDirectories)
517 , mFiles(rThat.mFiles)
518 , mProcesses(rThat.mProcesses)
519 , mProtocolVersion(rThat.mProtocolVersion)
520 , mTimeout(rThat.mTimeout)
521 , mNumObjects(rThat.mNumObjects)
522 , mRC(rThat.mRC)
523 { }
524 ~Data(void)
525 {
526 if (mpBaseEnvironment)
527 {
528 mpBaseEnvironment->releaseConst();
529 mpBaseEnvironment = NULL;
530 }
531 }
532 } mData;
533};
534
535#endif /* !____H_GUESTSESSIONIMPL */
536
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