VirtualBox

source: vbox/trunk/src/VBox/Main/src-client/GuestSessionImpl.cpp@ 43168

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

Typo.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 59.8 KB
Line 
1
2/* $Id: GuestSessionImpl.cpp 43165 2012-09-04 14:31:29Z vboxsync $ */
3/** @file
4 * VirtualBox Main - XXX.
5 */
6
7/*
8 * Copyright (C) 2012 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
20/*******************************************************************************
21* Header Files *
22*******************************************************************************/
23#include "GuestImpl.h"
24#include "GuestSessionImpl.h"
25#include "GuestCtrlImplPrivate.h"
26
27#include "Global.h"
28#include "AutoCaller.h"
29#include "ProgressImpl.h"
30
31#include <memory> /* For auto_ptr. */
32
33#include <iprt/env.h>
34#include <iprt/file.h> /* For CopyTo/From. */
35
36#include <VBox/com/array.h>
37#include <VBox/version.h>
38
39#ifdef LOG_GROUP
40 #undef LOG_GROUP
41#endif
42#define LOG_GROUP LOG_GROUP_GUEST_CONTROL
43#include <VBox/log.h>
44
45
46// constructor / destructor
47/////////////////////////////////////////////////////////////////////////////
48
49DEFINE_EMPTY_CTOR_DTOR(GuestSession)
50
51HRESULT GuestSession::FinalConstruct(void)
52{
53 LogFlowThisFunc(("\n"));
54 return BaseFinalConstruct();
55}
56
57void GuestSession::FinalRelease(void)
58{
59 LogFlowThisFuncEnter();
60 uninit();
61 BaseFinalRelease();
62 LogFlowThisFuncLeave();
63}
64
65// public initializer/uninitializer for internal purposes only
66/////////////////////////////////////////////////////////////////////////////
67
68int GuestSession::init(Guest *aGuest, ULONG aSessionID,
69 Utf8Str aUser, Utf8Str aPassword, Utf8Str aDomain, Utf8Str aName)
70{
71 LogFlowThisFuncEnter();
72
73 AssertPtrReturn(aGuest, VERR_INVALID_POINTER);
74
75 /* Enclose the state transition NotReady->InInit->Ready. */
76 AutoInitSpan autoInitSpan(this);
77 AssertReturn(autoInitSpan.isOk(), VERR_OBJECT_DESTROYED);
78
79 mData.mTimeout = 30 * 60 * 1000; /* Session timeout is 30 mins by default. */
80 mData.mParent = aGuest;
81 mData.mId = aSessionID;
82
83 mData.mCredentials.mUser = aUser;
84 mData.mCredentials.mPassword = aPassword;
85 mData.mCredentials.mDomain = aDomain;
86 mData.mName = aName;
87 mData.mNumObjects = 0;
88
89 /* Confirm a successful initialization when it's the case. */
90 autoInitSpan.setSucceeded();
91
92 LogFlowFuncLeaveRC(VINF_SUCCESS);
93 return VINF_SUCCESS;
94}
95
96/**
97 * Uninitializes the instance.
98 * Called from FinalRelease().
99 */
100void GuestSession::uninit(void)
101{
102 LogFlowThisFuncEnter();
103
104 /* Enclose the state transition Ready->InUninit->NotReady. */
105 AutoUninitSpan autoUninitSpan(this);
106 if (autoUninitSpan.uninitDone())
107 return;
108
109 int rc = VINF_SUCCESS;
110
111#ifndef VBOX_WITH_GUEST_CONTROL
112 LogFlowThisFunc(("Closing directories (%RU64 total)\n",
113 mData.mDirectories.size()));
114 for (SessionDirectories::iterator itDirs = mData.mDirectories.begin();
115 itDirs != mData.mDirectories.end(); ++itDirs)
116 {
117#ifdef DEBUG
118 ULONG cRefs = (*itDirs)->AddRef();
119 LogFlowThisFunc(("pFile=%p, cRefs=%RU32\n", (*itDirs), cRefs));
120 (*itDirs)->Release();
121#endif
122 (*itDirs)->uninit();
123 }
124 mData.mDirectories.clear();
125
126 LogFlowThisFunc(("Closing files (%RU64 total)\n",
127 mData.mFiles.size()));
128 for (SessionFiles::iterator itFiles = mData.mFiles.begin();
129 itFiles != mData.mFiles.end(); ++itFiles)
130 {
131#ifdef DEBUG
132 ULONG cRefs = (*itFiles)->AddRef();
133 LogFlowThisFunc(("pFile=%p, cRefs=%RU32\n", (*itFiles), cRefs));
134 (*itFiles)->Release();
135#endif
136 (*itFiles)->uninit();
137 }
138 mData.mFiles.clear();
139
140 LogFlowThisFunc(("Closing processes (%RU64 total)\n",
141 mData.mProcesses.size()));
142 for (SessionProcesses::iterator itProcs = mData.mProcesses.begin();
143 itProcs != mData.mProcesses.end(); ++itProcs)
144 {
145#ifdef DEBUG
146 ULONG cRefs = itProcs->second->AddRef();
147 LogFlowThisFunc(("pProcess=%p, cRefs=%RU32\n", itProcs->second, cRefs));
148 itProcs->second->Release();
149#endif
150 itProcs->second->uninit();
151 }
152 mData.mProcesses.clear();
153
154 LogFlowThisFunc(("mNumObjects=%RU32\n", mData.mNumObjects));
155#endif
156 LogFlowFuncLeaveRC(rc);
157}
158
159// implementation of public getters/setters for attributes
160/////////////////////////////////////////////////////////////////////////////
161
162STDMETHODIMP GuestSession::COMGETTER(User)(BSTR *aUser)
163{
164#ifndef VBOX_WITH_GUEST_CONTROL
165 ReturnComNotImplemented();
166#else
167 LogFlowThisFuncEnter();
168
169 CheckComArgOutPointerValid(aUser);
170
171 AutoCaller autoCaller(this);
172 if (FAILED(autoCaller.rc())) return autoCaller.rc();
173
174 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
175
176 mData.mCredentials.mUser.cloneTo(aUser);
177
178 LogFlowFuncLeaveRC(S_OK);
179 return S_OK;
180#endif /* VBOX_WITH_GUEST_CONTROL */
181}
182
183STDMETHODIMP GuestSession::COMGETTER(Domain)(BSTR *aDomain)
184{
185#ifndef VBOX_WITH_GUEST_CONTROL
186 ReturnComNotImplemented();
187#else
188 LogFlowThisFuncEnter();
189
190 CheckComArgOutPointerValid(aDomain);
191
192 AutoCaller autoCaller(this);
193 if (FAILED(autoCaller.rc())) return autoCaller.rc();
194
195 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
196
197 mData.mCredentials.mDomain.cloneTo(aDomain);
198
199 LogFlowFuncLeaveRC(S_OK);
200 return S_OK;
201#endif /* VBOX_WITH_GUEST_CONTROL */
202}
203
204STDMETHODIMP GuestSession::COMGETTER(Name)(BSTR *aName)
205{
206#ifndef VBOX_WITH_GUEST_CONTROL
207 ReturnComNotImplemented();
208#else
209 LogFlowThisFuncEnter();
210
211 CheckComArgOutPointerValid(aName);
212
213 AutoCaller autoCaller(this);
214 if (FAILED(autoCaller.rc())) return autoCaller.rc();
215
216 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
217
218 mData.mName.cloneTo(aName);
219
220 LogFlowFuncLeaveRC(S_OK);
221 return S_OK;
222#endif /* VBOX_WITH_GUEST_CONTROL */
223}
224
225STDMETHODIMP GuestSession::COMGETTER(Id)(ULONG *aId)
226{
227#ifndef VBOX_WITH_GUEST_CONTROL
228 ReturnComNotImplemented();
229#else
230 LogFlowThisFuncEnter();
231
232 CheckComArgOutPointerValid(aId);
233
234 AutoCaller autoCaller(this);
235 if (FAILED(autoCaller.rc())) return autoCaller.rc();
236
237 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
238
239 *aId = mData.mId;
240
241 LogFlowFuncLeaveRC(S_OK);
242 return S_OK;
243#endif /* VBOX_WITH_GUEST_CONTROL */
244}
245
246STDMETHODIMP GuestSession::COMGETTER(Timeout)(ULONG *aTimeout)
247{
248#ifndef VBOX_WITH_GUEST_CONTROL
249 ReturnComNotImplemented();
250#else
251 LogFlowThisFuncEnter();
252
253 CheckComArgOutPointerValid(aTimeout);
254
255 AutoCaller autoCaller(this);
256 if (FAILED(autoCaller.rc())) return autoCaller.rc();
257
258 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
259
260 *aTimeout = mData.mTimeout;
261
262 LogFlowFuncLeaveRC(S_OK);
263 return S_OK;
264#endif /* VBOX_WITH_GUEST_CONTROL */
265}
266
267STDMETHODIMP GuestSession::COMSETTER(Timeout)(ULONG aTimeout)
268{
269#ifndef VBOX_WITH_GUEST_CONTROL
270 ReturnComNotImplemented();
271#else
272 LogFlowThisFuncEnter();
273
274 AutoCaller autoCaller(this);
275 if (FAILED(autoCaller.rc())) return autoCaller.rc();
276
277 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
278
279 mData.mTimeout = aTimeout;
280
281 LogFlowFuncLeaveRC(S_OK);
282 return S_OK;
283#endif /* VBOX_WITH_GUEST_CONTROL */
284}
285
286STDMETHODIMP GuestSession::COMGETTER(Environment)(ComSafeArrayOut(BSTR, aEnvironment))
287{
288#ifndef VBOX_WITH_GUEST_CONTROL
289 ReturnComNotImplemented();
290#else
291 LogFlowThisFuncEnter();
292
293 CheckComArgOutSafeArrayPointerValid(aEnvironment);
294
295 AutoCaller autoCaller(this);
296 if (FAILED(autoCaller.rc())) return autoCaller.rc();
297
298 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
299
300 size_t cEnvVars = mData.mEnvironment.Size();
301 LogFlowThisFunc(("%s cEnvVars=%RU32\n", mData.mName.c_str(), cEnvVars));
302 com::SafeArray<BSTR> environment(cEnvVars);
303
304 for (size_t i = 0; i < cEnvVars; i++)
305 {
306 Bstr strEnv(mData.mEnvironment.Get(i));
307 strEnv.cloneTo(&environment[i]);
308 }
309 environment.detachTo(ComSafeArrayOutArg(aEnvironment));
310
311 LogFlowFuncLeaveRC(S_OK);
312 return S_OK;
313#endif /* VBOX_WITH_GUEST_CONTROL */
314}
315
316STDMETHODIMP GuestSession::COMSETTER(Environment)(ComSafeArrayIn(IN_BSTR, aValues))
317{
318#ifndef VBOX_WITH_GUEST_CONTROL
319 ReturnComNotImplemented();
320#else
321 LogFlowThisFuncEnter();
322
323 AutoCaller autoCaller(this);
324 if (FAILED(autoCaller.rc())) return autoCaller.rc();
325
326 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
327
328 com::SafeArray<IN_BSTR> environment(ComSafeArrayInArg(aValues));
329
330 int rc = VINF_SUCCESS;
331 for (size_t i = 0; i < environment.size() && RT_SUCCESS(rc); i++)
332 {
333 Utf8Str strEnv(environment[i]);
334 if (!strEnv.isEmpty()) /* Silently skip empty entries. */
335 rc = mData.mEnvironment.Set(strEnv);
336 }
337
338 HRESULT hr = RT_SUCCESS(rc) ? S_OK : VBOX_E_IPRT_ERROR;
339 LogFlowFuncLeaveRC(hr);
340 return hr;
341#endif /* VBOX_WITH_GUEST_CONTROL */
342}
343
344STDMETHODIMP GuestSession::COMGETTER(Processes)(ComSafeArrayOut(IGuestProcess *, aProcesses))
345{
346#ifndef VBOX_WITH_GUEST_CONTROL
347 ReturnComNotImplemented();
348#else
349 LogFlowThisFuncEnter();
350
351 CheckComArgOutSafeArrayPointerValid(aProcesses);
352
353 AutoCaller autoCaller(this);
354 if (FAILED(autoCaller.rc())) return autoCaller.rc();
355
356 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
357
358 SafeIfaceArray<IGuestProcess> collection(mData.mProcesses);
359 collection.detachTo(ComSafeArrayOutArg(aProcesses));
360
361 LogFlowFuncLeaveRC(S_OK);
362 return S_OK;
363#endif /* VBOX_WITH_GUEST_CONTROL */
364}
365
366STDMETHODIMP GuestSession::COMGETTER(Directories)(ComSafeArrayOut(IGuestDirectory *, aDirectories))
367{
368#ifndef VBOX_WITH_GUEST_CONTROL
369 ReturnComNotImplemented();
370#else
371 LogFlowThisFuncEnter();
372
373 CheckComArgOutSafeArrayPointerValid(aDirectories);
374
375 AutoCaller autoCaller(this);
376 if (FAILED(autoCaller.rc())) return autoCaller.rc();
377
378 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
379
380 SafeIfaceArray<IGuestDirectory> collection(mData.mDirectories);
381 collection.detachTo(ComSafeArrayOutArg(aDirectories));
382
383 LogFlowFuncLeaveRC(S_OK);
384 return S_OK;
385#endif /* VBOX_WITH_GUEST_CONTROL */
386}
387
388STDMETHODIMP GuestSession::COMGETTER(Files)(ComSafeArrayOut(IGuestFile *, aFiles))
389{
390#ifndef VBOX_WITH_GUEST_CONTROL
391 ReturnComNotImplemented();
392#else
393 LogFlowThisFuncEnter();
394
395 CheckComArgOutSafeArrayPointerValid(aFiles);
396
397 AutoCaller autoCaller(this);
398 if (FAILED(autoCaller.rc())) return autoCaller.rc();
399
400 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
401
402 SafeIfaceArray<IGuestFile> collection(mData.mFiles);
403 collection.detachTo(ComSafeArrayOutArg(aFiles));
404
405 LogFlowFuncLeaveRC(S_OK);
406 return S_OK;
407#endif /* VBOX_WITH_GUEST_CONTROL */
408}
409
410// private methods
411/////////////////////////////////////////////////////////////////////////////
412
413int GuestSession::directoryRemoveFromList(GuestDirectory *pDirectory)
414{
415 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
416
417 for (SessionDirectories::iterator itDirs = mData.mDirectories.begin();
418 itDirs != mData.mDirectories.end(); ++itDirs)
419 {
420 if (pDirectory == (*itDirs))
421 {
422 Bstr strName;
423 HRESULT hr = (*itDirs)->COMGETTER(DirectoryName)(strName.asOutParam());
424 ComAssertComRC(hr);
425
426 Assert(mData.mDirectories.size());
427 LogFlowFunc(("Removing directory \"%s\" (Session: %RU32) (now total %ld directories)\n",
428 Utf8Str(strName).c_str(), mData.mId, mData.mDirectories.size() - 1));
429
430 mData.mDirectories.erase(itDirs);
431 return VINF_SUCCESS;
432 }
433 }
434
435 return VERR_NOT_FOUND;
436}
437
438int GuestSession::directoryCreateInternal(const Utf8Str &strPath, uint32_t uMode, uint32_t uFlags, int *pGuestRc)
439{
440 LogFlowThisFunc(("strPath=%s, uMode=%x, uFlags=%x\n",
441 strPath.c_str(), uMode, uFlags));
442
443 GuestProcessStartupInfo procInfo;
444 procInfo.mCommand = Utf8Str(VBOXSERVICE_TOOL_MKDIR);
445 procInfo.mFlags = ProcessCreateFlag_Hidden;
446
447 int vrc = VINF_SUCCESS;
448
449 /* Construct arguments. */
450 if (uFlags & DirectoryCreateFlag_Parents)
451 procInfo.mArguments.push_back(Utf8Str("--parents")); /* We also want to create the parent directories. */
452 if (uMode)
453 {
454 procInfo.mArguments.push_back(Utf8Str("--mode")); /* Set the creation mode. */
455
456 char szMode[16];
457 if (RTStrPrintf(szMode, sizeof(szMode), "%o", uMode))
458 {
459 procInfo.mArguments.push_back(Utf8Str(szMode));
460 }
461 else
462 vrc = VERR_BUFFER_OVERFLOW;
463 }
464 procInfo.mArguments.push_back(strPath); /* The directory we want to create. */
465
466 int guestRc;
467 if (RT_SUCCESS(vrc))
468 {
469 GuestProcessTool procTool;
470 vrc = procTool.Init(this, procInfo, false /* Async */, &guestRc);
471 if (RT_SUCCESS(vrc))
472 {
473 if (RT_SUCCESS(guestRc))
474 vrc = procTool.Wait(GUESTPROCESSTOOL_FLAG_NONE, &guestRc);
475 }
476
477 if (RT_SUCCESS(vrc))
478 {
479 if (RT_SUCCESS(guestRc))
480 guestRc = procTool.TerminatedOk(NULL /* Exit code */);
481 }
482
483 if (pGuestRc)
484 *pGuestRc = guestRc;
485 }
486
487 LogFlowFuncLeaveRC(vrc);
488 if (RT_FAILURE(vrc))
489 return vrc;
490 return RT_SUCCESS(guestRc) ? VINF_SUCCESS : VERR_GENERAL_FAILURE; /** @todo Special guest control rc needed! */
491}
492
493int GuestSession::directoryQueryInfoInternal(const Utf8Str &strPath, GuestFsObjData &objData, int *pGuestRc)
494{
495 LogFlowThisFunc(("strPath=%s\n", strPath.c_str()));
496
497 int vrc = fsQueryInfoInternal(strPath, objData, pGuestRc);
498 if (RT_SUCCESS(vrc))
499 {
500 vrc = objData.mType == FsObjType_Directory
501 ? VINF_SUCCESS : VERR_NOT_A_DIRECTORY;
502 }
503
504 LogFlowFuncLeaveRC(vrc);
505 return vrc;
506}
507
508int GuestSession::objectCreateTempInternal(const Utf8Str &strTemplate, const Utf8Str &strPath,
509 bool fDirectory, const Utf8Str &strName, int *pGuestRc)
510{
511 GuestProcessStartupInfo procInfo;
512 procInfo.mCommand = Utf8Str(VBOXSERVICE_TOOL_MKTEMP);
513 procInfo.mFlags = ProcessCreateFlag_WaitForStdOut;
514 procInfo.mArguments.push_back(Utf8Str("--machinereadable"));
515 if (fDirectory)
516 procInfo.mArguments.push_back(Utf8Str("-d"));
517 if (strPath.length()) /* Otherwise use /tmp or equivalent. */
518 {
519 procInfo.mArguments.push_back(Utf8Str("-t"));
520 procInfo.mArguments.push_back(strPath);
521 }
522 procInfo.mArguments.push_back(strTemplate);
523
524 GuestProcessTool procTool; int guestRc;
525 int vrc = procTool.Init(this, procInfo, false /* Async */, &guestRc);
526 if (RT_SUCCESS(vrc))
527 {
528 if (RT_SUCCESS(guestRc))
529 vrc = procTool.Wait(GUESTPROCESSTOOL_FLAG_NONE, &guestRc);
530 }
531
532 if (RT_SUCCESS(vrc))
533 {
534 if (RT_SUCCESS(guestRc))
535 guestRc = procTool.TerminatedOk(NULL /* Exit code */);
536 }
537
538 if (pGuestRc)
539 *pGuestRc = guestRc;
540
541 if (RT_FAILURE(vrc))
542 return vrc;
543 return RT_SUCCESS(guestRc) ? VINF_SUCCESS : VERR_GENERAL_FAILURE; /** @todo Special guest control rc needed! */
544}
545
546int GuestSession::directoryOpenInternal(const Utf8Str &strPath, const Utf8Str &strFilter,
547 uint32_t uFlags, ComObjPtr<GuestDirectory> &pDirectory)
548{
549 LogFlowThisFunc(("strPath=%s, strPath=%s, uFlags=%x\n",
550 strPath.c_str(), strFilter.c_str(), uFlags));
551
552 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
553
554 /* Create the directory object. */
555 HRESULT hr = pDirectory.createObject();
556 if (FAILED(hr))
557 return VERR_COM_UNEXPECTED;
558
559 int vrc = pDirectory->init(this /* Parent */,
560 strPath, strFilter, uFlags);
561 if (RT_FAILURE(vrc))
562 return vrc;
563
564 /* Add the created directory to our vector. */
565 mData.mDirectories.push_back(pDirectory);
566
567 LogFlowFunc(("Added new directory \"%s\" (Session: %RU32)\n",
568 strPath.c_str(), mData.mId));
569
570 LogFlowFuncLeaveRC(vrc);
571 return vrc;
572}
573
574int GuestSession::dispatchToProcess(uint32_t uContextID, uint32_t uFunction, void *pvData, size_t cbData)
575{
576 LogFlowFuncEnter();
577
578 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
579
580 uint32_t uProcessID = VBOX_GUESTCTRL_CONTEXTID_GET_OBJECT(uContextID);
581#ifdef DEBUG
582 LogFlowFunc(("uProcessID=%RU32 (%RU32 total)\n",
583 uProcessID, mData.mProcesses.size()));
584#endif
585 int rc;
586 SessionProcesses::const_iterator itProc
587 = mData.mProcesses.find(uProcessID);
588 if (itProc != mData.mProcesses.end())
589 {
590 ComObjPtr<GuestProcess> pProcess(itProc->second);
591 Assert(!pProcess.isNull());
592
593 alock.release();
594 rc = pProcess->callbackDispatcher(uContextID, uFunction, pvData, cbData);
595 }
596 else
597 rc = VERR_NOT_FOUND;
598
599 LogFlowFuncLeaveRC(rc);
600 return rc;
601}
602
603int GuestSession::fileRemoveFromList(GuestFile *pFile)
604{
605 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
606
607 for (SessionFiles::iterator itFiles = mData.mFiles.begin();
608 itFiles != mData.mFiles.end(); ++itFiles)
609 {
610 if (pFile == (*itFiles))
611 {
612 Bstr strName;
613 HRESULT hr = (*itFiles)->COMGETTER(FileName)(strName.asOutParam());
614 ComAssertComRC(hr);
615
616 Assert(mData.mNumObjects);
617 LogFlowThisFunc(("Removing file \"%s\" (Session: %RU32) (now total %ld files, %ld objects)\n",
618 Utf8Str(strName).c_str(), mData.mId, mData.mFiles.size() - 1, mData.mNumObjects - 1));
619#ifdef DEBUG
620 ULONG cRefs = pFile->AddRef();
621 LogFlowThisFunc(("pObject=%p, cRefs=%RU32\n", pFile, cRefs));
622 pFile->Release();
623#endif
624 mData.mFiles.erase(itFiles);
625 mData.mNumObjects--;
626 return VINF_SUCCESS;
627 }
628 }
629
630 return VERR_NOT_FOUND;
631}
632
633int GuestSession::fileRemoveInternal(const Utf8Str &strPath, int *pGuestRc)
634{
635 GuestProcessStartupInfo procInfo;
636 GuestProcessStream streamOut;
637
638 procInfo.mCommand = Utf8Str(VBOXSERVICE_TOOL_RM);
639 procInfo.mFlags = ProcessCreateFlag_WaitForStdOut;
640 procInfo.mArguments.push_back(Utf8Str("--machinereadable"));
641 procInfo.mArguments.push_back(strPath); /* The file we want to remove. */
642
643 GuestProcessTool procTool; int guestRc;
644 int vrc = procTool.Init(this, procInfo, false /* Async */, &guestRc);
645 if (RT_SUCCESS(vrc))
646 vrc = procTool.Wait(GUESTPROCESSTOOL_FLAG_NONE, &guestRc);
647
648 if (RT_SUCCESS(vrc))
649 {
650 if (RT_SUCCESS(guestRc))
651 guestRc = procTool.TerminatedOk(NULL /* Exit code */);
652 }
653
654 if (pGuestRc)
655 *pGuestRc = guestRc;
656
657 if (RT_FAILURE(vrc))
658 return vrc;
659 return RT_SUCCESS(guestRc) ? VINF_SUCCESS : VERR_GENERAL_FAILURE; /** @todo Special guest control rc needed! */
660}
661
662int GuestSession::fileOpenInternal(const Utf8Str &strPath, const Utf8Str &strOpenMode, const Utf8Str &strDisposition,
663 uint32_t uCreationMode, int64_t iOffset, ComObjPtr<GuestFile> &pFile, int *pGuestRc)
664{
665 LogFlowThisFunc(("strPath=%s, strOpenMode=%s, strDisposition=%s, uCreationMode=%x, iOffset=%RI64\n",
666 strPath.c_str(), strOpenMode.c_str(), strDisposition.c_str(), uCreationMode, iOffset));
667
668 /* Create the directory object. */
669 HRESULT hr = pFile.createObject();
670 if (FAILED(hr))
671 return VERR_COM_UNEXPECTED;
672
673 int vrc = pFile->init(this /* Parent */,
674 strPath, strOpenMode, strDisposition, uCreationMode, iOffset, pGuestRc);
675 if (RT_FAILURE(vrc))
676 return vrc;
677 /** @todo Handle guestRc. */
678
679 /* Add the created directory to our vector. */
680 mData.mFiles.push_back(pFile);
681 mData.mNumObjects++;
682 Assert(mData.mNumObjects <= VBOX_GUESTCTRL_MAX_OBJECTS);
683
684 LogFlowFunc(("Added new file \"%s\" (Session: %RU32) (now total %ld files, %ld objects)\n",
685 strPath.c_str(), mData.mId, mData.mProcesses.size(), mData.mNumObjects));
686
687 LogFlowFuncLeaveRC(vrc);
688 return vrc;
689}
690
691int GuestSession::fileQueryInfoInternal(const Utf8Str &strPath, GuestFsObjData &objData, int *pGuestRc)
692{
693 LogFlowThisFunc(("strPath=%s\n", strPath.c_str()));
694
695 int vrc = fsQueryInfoInternal(strPath, objData, pGuestRc);
696 if (RT_SUCCESS(vrc))
697 {
698 vrc = objData.mType == FsObjType_File
699 ? VINF_SUCCESS : VERR_NOT_A_FILE;
700 }
701
702 LogFlowFuncLeaveRC(vrc);
703 return vrc;
704}
705
706int GuestSession::fileQuerySizeInternal(const Utf8Str &strPath, int64_t *pllSize, int *pGuestRc)
707{
708 AssertPtrReturn(pllSize, VERR_INVALID_POINTER);
709
710 GuestFsObjData objData;
711 int vrc = fileQueryInfoInternal(strPath, objData, pGuestRc);
712 if (RT_SUCCESS(vrc))
713 *pllSize = objData.mObjectSize;
714
715 return vrc;
716}
717
718int GuestSession::fsQueryInfoInternal(const Utf8Str &strPath, GuestFsObjData &objData, int *pGuestRc)
719{
720 LogFlowThisFunc(("strPath=%s\n", strPath.c_str()));
721
722 /** @todo Merge this with IGuestFile::queryInfo(). */
723 GuestProcessStartupInfo procInfo;
724 procInfo.mCommand = Utf8Str(VBOXSERVICE_TOOL_STAT);
725 procInfo.mFlags = ProcessCreateFlag_WaitForStdOut;
726
727 /* Construct arguments. */
728 procInfo.mArguments.push_back(Utf8Str("--machinereadable"));
729 procInfo.mArguments.push_back(strPath);
730
731 GuestProcessTool procTool; int guestRc;
732 int vrc = procTool.Init(this, procInfo, false /* Async */, &guestRc);
733 if (RT_SUCCESS(vrc))
734 vrc = procTool.Wait(GUESTPROCESSTOOL_FLAG_NONE, &guestRc);
735 if (RT_SUCCESS(vrc))
736 {
737 guestRc = procTool.TerminatedOk(NULL /* Exit code */);
738 if (RT_SUCCESS(guestRc))
739 {
740 GuestProcessStreamBlock curBlock;
741 vrc = procTool.GetCurrentBlock(OUTPUT_HANDLE_ID_STDOUT, curBlock);
742 /** @todo Check for more / validate blocks! */
743 if (RT_SUCCESS(vrc))
744 vrc = objData.FromStat(curBlock);
745 }
746 }
747
748 if (pGuestRc)
749 *pGuestRc = guestRc;
750
751 LogFlowFuncLeaveRC(vrc);
752 if (RT_FAILURE(vrc))
753 return vrc;
754 return RT_SUCCESS(guestRc) ? VINF_SUCCESS : VERR_GENERAL_FAILURE; /** @todo Special guest control rc needed! */
755}
756
757const GuestCredentials& GuestSession::getCredentials(void)
758{
759 return mData.mCredentials;
760}
761
762const GuestEnvironment& GuestSession::getEnvironment(void)
763{
764 return mData.mEnvironment;
765}
766
767Utf8Str GuestSession::getName(void)
768{
769 return mData.mName;
770}
771
772int GuestSession::processRemoveFromList(GuestProcess *pProcess)
773{
774 LogFlowThisFuncEnter();
775
776 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
777
778 int rc = VERR_NOT_FOUND;
779
780 ULONG uPID;
781 HRESULT hr = pProcess->COMGETTER(PID)(&uPID);
782
783 LogFlowFunc(("Closing process (PID=%RU32) ...\n", uPID));
784
785 for (SessionProcesses::iterator itProcs = mData.mProcesses.begin();
786 itProcs != mData.mProcesses.end(); ++itProcs)
787 {
788 if (pProcess == itProcs->second)
789 {
790 GuestProcess *pCurProc = itProcs->second;
791 AssertPtr(pCurProc);
792
793 hr = pCurProc->COMGETTER(PID)(&uPID);
794 ComAssertComRC(hr);
795
796 Assert(mData.mNumObjects);
797 LogFlowFunc(("Removing process (Session: %RU32) with process ID=%RU32, guest PID=%RU32 (now total %ld processes, %ld objects)\n",
798 mData.mId, pCurProc->getProcessID(), uPID, mData.mProcesses.size() - 1, mData.mNumObjects - 1));
799
800 mData.mProcesses.erase(itProcs);
801 mData.mNumObjects--;
802
803 rc = VINF_SUCCESS;
804 break;
805 }
806 }
807
808 LogFlowFuncLeaveRC(rc);
809 return rc;
810}
811
812/**
813 * Creates but does *not* start the process yet. See GuestProcess::startProcess() or
814 * GuestProcess::startProcessAsync() for that.
815 *
816 * @return IPRT status code.
817 * @param procInfo
818 * @param pProcess
819 */
820int GuestSession::processCreateExInteral(GuestProcessStartupInfo &procInfo, ComObjPtr<GuestProcess> &pProcess)
821{
822 LogFlowFunc(("mCmd=%s, mFlags=%x, mTimeoutMS=%RU32\n",
823 procInfo.mCommand.c_str(), procInfo.mFlags, procInfo.mTimeoutMS));
824#ifdef DEBUG
825 if (procInfo.mArguments.size())
826 {
827 LogFlowFunc(("Arguments:"));
828 ProcessArguments::const_iterator it = procInfo.mArguments.begin();
829 while (it != procInfo.mArguments.end())
830 {
831 LogFlow((" %s", (*it).c_str()));
832 it++;
833 }
834 LogFlow(("\n"));
835 }
836#endif
837
838 /* Validate flags. */
839 if (procInfo.mFlags)
840 {
841 if ( !(procInfo.mFlags & ProcessCreateFlag_IgnoreOrphanedProcesses)
842 && !(procInfo.mFlags & ProcessCreateFlag_WaitForProcessStartOnly)
843 && !(procInfo.mFlags & ProcessCreateFlag_Hidden)
844 && !(procInfo.mFlags & ProcessCreateFlag_NoProfile)
845 && !(procInfo.mFlags & ProcessCreateFlag_WaitForStdOut)
846 && !(procInfo.mFlags & ProcessCreateFlag_WaitForStdErr))
847 {
848 return VERR_INVALID_PARAMETER;
849 }
850 }
851
852 /* Adjust timeout. If set to 0, we define
853 * an infinite timeout. */
854 if (procInfo.mTimeoutMS == 0)
855 procInfo.mTimeoutMS = UINT32_MAX;
856
857 /** @tood Implement process priority + affinity. */
858
859 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
860
861 int rc = VERR_MAX_PROCS_REACHED;
862 if (mData.mNumObjects >= VBOX_GUESTCTRL_MAX_OBJECTS)
863 return rc;
864
865 /* Create a new (host-based) process ID and assign it. */
866 uint32_t uNewProcessID = 0;
867 ULONG uTries = 0;
868
869 for (;;)
870 {
871 /* Is the context ID already used? */
872 if (!processExists(uNewProcessID, NULL /* pProgress */))
873 {
874 /* Callback with context ID was not found. This means
875 * we can use this context ID for our new callback we want
876 * to add below. */
877 rc = VINF_SUCCESS;
878 break;
879 }
880 uNewProcessID++;
881 if (uNewProcessID == VBOX_GUESTCTRL_MAX_OBJECTS)
882 uNewProcessID = 0;
883
884 if (++uTries == UINT32_MAX)
885 break; /* Don't try too hard. */
886 }
887
888 if (RT_FAILURE(rc))
889 return rc;
890
891 /* Create the process object. */
892 HRESULT hr = pProcess.createObject();
893 if (FAILED(hr))
894 return VERR_COM_UNEXPECTED;
895
896 rc = pProcess->init(mData.mParent->getConsole() /* Console */, this /* Session */,
897 uNewProcessID, procInfo);
898 if (RT_FAILURE(rc))
899 return rc;
900
901 /* Add the created process to our map. */
902 mData.mProcesses[uNewProcessID] = pProcess;
903 mData.mNumObjects++;
904 Assert(mData.mNumObjects <= VBOX_GUESTCTRL_MAX_OBJECTS);
905
906 LogFlowFunc(("Added new process (Session: %RU32) with process ID=%RU32 (now total %ld processes, %ld objects)\n",
907 mData.mId, uNewProcessID, mData.mProcesses.size(), mData.mNumObjects));
908
909 return rc;
910}
911
912inline bool GuestSession::processExists(uint32_t uProcessID, ComObjPtr<GuestProcess> *pProcess)
913{
914 SessionProcesses::const_iterator it = mData.mProcesses.find(uProcessID);
915 if (it != mData.mProcesses.end())
916 {
917 if (pProcess)
918 *pProcess = it->second;
919 return true;
920 }
921 return false;
922}
923
924inline int GuestSession::processGetByPID(ULONG uPID, ComObjPtr<GuestProcess> *pProcess)
925{
926 AssertReturn(uPID, false);
927 /* pProcess is optional. */
928
929 SessionProcesses::iterator itProcs = mData.mProcesses.begin();
930 for (; itProcs != mData.mProcesses.end(); itProcs++)
931 {
932 ComObjPtr<GuestProcess> pCurProc = itProcs->second;
933 AutoCaller procCaller(pCurProc);
934 if (procCaller.rc())
935 return VERR_COM_INVALID_OBJECT_STATE;
936
937 ULONG uCurPID;
938 HRESULT hr = pCurProc->COMGETTER(PID)(&uCurPID);
939 ComAssertComRC(hr);
940
941 if (uCurPID == uPID)
942 {
943 if (pProcess)
944 *pProcess = pCurProc;
945 return VINF_SUCCESS;
946 }
947 }
948
949 return VERR_NOT_FOUND;
950}
951
952int GuestSession::startTaskAsync(const Utf8Str &strTaskDesc,
953 GuestSessionTask *pTask, ComObjPtr<Progress> &pProgress)
954{
955 LogFlowThisFunc(("strTaskDesc=%s, pTask=%p\n", strTaskDesc.c_str(), pTask));
956
957 AssertPtrReturn(pTask, VERR_INVALID_POINTER);
958
959 /* Create the progress object. */
960 HRESULT hr = pProgress.createObject();
961 if (FAILED(hr))
962 return VERR_COM_UNEXPECTED;
963
964 hr = pProgress->init(static_cast<IGuestSession*>(this),
965 Bstr(strTaskDesc).raw(),
966 TRUE /* aCancelable */);
967 if (FAILED(hr))
968 return VERR_COM_UNEXPECTED;
969
970 /* Initialize our worker task. */
971 std::auto_ptr<GuestSessionTask> task(pTask);
972
973 int rc = task->RunAsync(strTaskDesc, pProgress);
974 if (RT_FAILURE(rc))
975 return rc;
976
977 /* Don't destruct on success. */
978 task.release();
979
980 LogFlowFuncLeaveRC(rc);
981 return rc;
982}
983
984/**
985 * Queries/collects information prior to establishing a guest session.
986 * This is necessary to know which guest control protocol version to use,
987 * among other things (later).
988 *
989 * @return IPRT status code.
990 */
991int GuestSession::queryInfo(void)
992{
993#if 1
994 /* Since the new functions were not implemented yet, force Main to use protocol ver 1. */
995 mData.mProtocolVersion = 1;
996#else
997 /*
998 * Try querying the guest control protocol version running on the guest.
999 * This is done using the Guest Additions version
1000 */
1001 ComObjPtr<Guest> pGuest = mData.mParent;
1002 Assert(!pGuest.isNull());
1003
1004 uint32_t uVerAdditions = pGuest->getAdditionsVersion();
1005 mData.mProtocolVersion = ( VBOX_FULL_VERSION_GET_MAJOR(uVerAdditions) >= 4
1006 && VBOX_FULL_VERSION_GET_MINOR(uVerAdditions) >= 2) /** @todo What's about v5.0 ? */
1007 ? 2 /* Guest control 2.0. */
1008 : 1; /* Legacy guest control (VBox < 4.2). */
1009 /* Build revision is ignored. */
1010
1011 /* Tell the user but don't bitch too often. */
1012 static short s_gctrlLegacyWarning = 0;
1013 if (s_gctrlLegacyWarning++ < 3) /** @todo Find a bit nicer text. */
1014 LogRel((tr("Warning: Guest Additions are older (%ld.%ld) than host capabilities for guest control, please upgrade them. Using protocol version %ld now\n"),
1015 VBOX_FULL_VERSION_GET_MAJOR(uVerAdditions), VBOX_FULL_VERSION_GET_MINOR(uVerAdditions), mData.mProtocolVersion));
1016#endif
1017 return VINF_SUCCESS;
1018}
1019
1020// implementation of public methods
1021/////////////////////////////////////////////////////////////////////////////
1022
1023STDMETHODIMP GuestSession::Close(void)
1024{
1025#ifndef VBOX_WITH_GUEST_CONTROL
1026 ReturnComNotImplemented();
1027#else
1028 LogFlowThisFuncEnter();
1029
1030 AutoCaller autoCaller(this);
1031 if (FAILED(autoCaller.rc())) return autoCaller.rc();
1032
1033 /* Remove ourselves from the session list. */
1034 mData.mParent->sessionRemove(this);
1035
1036 /*
1037 * Release autocaller before calling uninit.
1038 */
1039 autoCaller.release();
1040
1041 uninit();
1042
1043 LogFlowFuncLeave();
1044 return S_OK;
1045#endif /* VBOX_WITH_GUEST_CONTROL */
1046}
1047
1048STDMETHODIMP GuestSession::CopyFrom(IN_BSTR aSource, IN_BSTR aDest, ComSafeArrayIn(CopyFileFlag_T, aFlags), IProgress **aProgress)
1049{
1050#ifndef VBOX_WITH_GUEST_CONTROL
1051 ReturnComNotImplemented();
1052#else
1053 CheckComArgStrNotEmptyOrNull(aSource);
1054 CheckComArgStrNotEmptyOrNull(aDest);
1055 CheckComArgOutPointerValid(aProgress);
1056
1057 LogFlowThisFuncEnter();
1058
1059 if (RT_UNLIKELY((aSource) == NULL || *(aSource) == '\0'))
1060 return setError(E_INVALIDARG, tr("No source specified"));
1061 if (RT_UNLIKELY((aDest) == NULL || *(aDest) == '\0'))
1062 return setError(E_INVALIDARG, tr("No destination specified"));
1063
1064 AutoCaller autoCaller(this);
1065 if (FAILED(autoCaller.rc())) return autoCaller.rc();
1066
1067 uint32_t fFlags = CopyFileFlag_None;
1068 if (aFlags)
1069 {
1070 com::SafeArray<CopyFileFlag_T> flags(ComSafeArrayInArg(aFlags));
1071 for (size_t i = 0; i < flags.size(); i++)
1072 fFlags |= flags[i];
1073 }
1074
1075 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
1076
1077 HRESULT hr = S_OK;
1078
1079 ComObjPtr<Progress> pProgress;
1080 SessionTaskCopyFrom *pTask = new SessionTaskCopyFrom(this /* GuestSession */,
1081 Utf8Str(aSource), Utf8Str(aDest), fFlags);
1082 AssertPtrReturn(pTask, VERR_NO_MEMORY);
1083 int rc = startTaskAsync(Utf8StrFmt(tr("Copying \"%ls\" from guest to \"%ls\" on the host"), aSource, aDest),
1084 pTask, pProgress);
1085 if (RT_SUCCESS(rc))
1086 {
1087 /* Return progress to the caller. */
1088 hr = pProgress.queryInterfaceTo(aProgress);
1089 }
1090 else
1091 hr = setError(VBOX_E_IPRT_ERROR,
1092 tr("Starting task for copying file \"%ls\" from guest to \"%ls\" on the host failed: %Rrc"), rc);
1093 return hr;
1094#endif /* VBOX_WITH_GUEST_CONTROL */
1095}
1096
1097STDMETHODIMP GuestSession::CopyTo(IN_BSTR aSource, IN_BSTR aDest, ComSafeArrayIn(CopyFileFlag_T, aFlags), IProgress **aProgress)
1098{
1099#ifndef VBOX_WITH_GUEST_CONTROL
1100 ReturnComNotImplemented();
1101#else
1102 CheckComArgStrNotEmptyOrNull(aSource);
1103 CheckComArgStrNotEmptyOrNull(aDest);
1104 CheckComArgOutPointerValid(aProgress);
1105
1106 LogFlowThisFuncEnter();
1107
1108 if (RT_UNLIKELY((aSource) == NULL || *(aSource) == '\0'))
1109 return setError(E_INVALIDARG, tr("No source specified"));
1110 if (RT_UNLIKELY((aDest) == NULL || *(aDest) == '\0'))
1111 return setError(E_INVALIDARG, tr("No destination specified"));
1112
1113 AutoCaller autoCaller(this);
1114 if (FAILED(autoCaller.rc())) return autoCaller.rc();
1115
1116 uint32_t fFlags = CopyFileFlag_None;
1117 if (aFlags)
1118 {
1119 com::SafeArray<CopyFileFlag_T> flags(ComSafeArrayInArg(aFlags));
1120 for (size_t i = 0; i < flags.size(); i++)
1121 fFlags |= flags[i];
1122 }
1123
1124 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
1125
1126 HRESULT hr = S_OK;
1127
1128 ComObjPtr<Progress> pProgress;
1129 SessionTaskCopyTo *pTask = new SessionTaskCopyTo(this /* GuestSession */,
1130 Utf8Str(aSource), Utf8Str(aDest), fFlags);
1131 AssertPtrReturn(pTask, VERR_NO_MEMORY);
1132 int rc = startTaskAsync(Utf8StrFmt(tr("Copying \"%ls\" from host to \"%ls\" on the guest"), aSource, aDest),
1133 pTask, pProgress);
1134 if (RT_SUCCESS(rc))
1135 {
1136 /* Return progress to the caller. */
1137 hr = pProgress.queryInterfaceTo(aProgress);
1138 }
1139 else
1140 hr = setError(VBOX_E_IPRT_ERROR,
1141 tr("Starting task for copying file \"%ls\" from host to \"%ls\" on the guest failed: %Rrc"), rc);
1142 return hr;
1143#endif /* VBOX_WITH_GUEST_CONTROL */
1144}
1145
1146STDMETHODIMP GuestSession::DirectoryCreate(IN_BSTR aPath, ULONG aMode,
1147 ComSafeArrayIn(DirectoryCreateFlag_T, aFlags))
1148{
1149#ifndef VBOX_WITH_GUEST_CONTROL
1150 ReturnComNotImplemented();
1151#else
1152 LogFlowThisFuncEnter();
1153
1154 if (RT_UNLIKELY((aPath) == NULL || *(aPath) == '\0'))
1155 return setError(E_INVALIDARG, tr("No directory to create specified"));
1156
1157 AutoCaller autoCaller(this);
1158 if (FAILED(autoCaller.rc())) return autoCaller.rc();
1159
1160 uint32_t fFlags = DirectoryCreateFlag_None;
1161 if (aFlags)
1162 {
1163 com::SafeArray<DirectoryCreateFlag_T> flags(ComSafeArrayInArg(aFlags));
1164 for (size_t i = 0; i < flags.size(); i++)
1165 fFlags |= flags[i];
1166
1167 if (fFlags)
1168 {
1169 if (!(fFlags & DirectoryCreateFlag_Parents))
1170 return setError(E_INVALIDARG, tr("Unknown flags (%#x)"), fFlags);
1171 }
1172 }
1173
1174 HRESULT hr = S_OK;
1175
1176 ComObjPtr <GuestDirectory> pDirectory; int guestRc;
1177 int rc = directoryCreateInternal(Utf8Str(aPath), (uint32_t)aMode, fFlags, &guestRc);
1178 if (RT_FAILURE(rc))
1179 {
1180 switch (rc)
1181 {
1182 case VERR_GENERAL_FAILURE: /** @todo Special guest control rc needed! */
1183 hr = GuestProcess::setErrorExternal(this, guestRc);
1184 break;
1185
1186 case VERR_INVALID_PARAMETER:
1187 hr = setError(VBOX_E_IPRT_ERROR, tr("Directory creation failed: Invalid parameters given"));
1188 break;
1189
1190 case VERR_BROKEN_PIPE:
1191 hr = setError(VBOX_E_IPRT_ERROR, tr("Directory creation failed: Unexpectedly aborted"));
1192 break;
1193
1194 case VERR_CANT_CREATE:
1195 hr = setError(VBOX_E_IPRT_ERROR, tr("Directory creation failed: Could not create directory"));
1196 break;
1197
1198 default:
1199 hr = setError(VBOX_E_IPRT_ERROR, tr("Directory creation failed: %Rrc"), rc);
1200 break;
1201 }
1202 }
1203
1204 return hr;
1205#endif /* VBOX_WITH_GUEST_CONTROL */
1206}
1207
1208STDMETHODIMP GuestSession::DirectoryCreateTemp(IN_BSTR aTemplate, ULONG aMode, IN_BSTR aPath, BOOL aSecure, BSTR *aDirectory)
1209{
1210#ifndef VBOX_WITH_GUEST_CONTROL
1211 ReturnComNotImplemented();
1212#else
1213 LogFlowThisFuncEnter();
1214
1215 if (RT_UNLIKELY((aTemplate) == NULL || *(aTemplate) == '\0'))
1216 return setError(E_INVALIDARG, tr("No template specified"));
1217 if (RT_UNLIKELY((aPath) == NULL || *(aPath) == '\0'))
1218 return setError(E_INVALIDARG, tr("No directory name specified"));
1219 CheckComArgOutPointerValid(aDirectory);
1220
1221 AutoCaller autoCaller(this);
1222 if (FAILED(autoCaller.rc())) return autoCaller.rc();
1223
1224 HRESULT hr = S_OK;
1225
1226 Utf8Str strName; int guestRc;
1227 int rc = objectCreateTempInternal(Utf8Str(aTemplate),
1228 Utf8Str(aPath),
1229 true /* Directory */, strName, &guestRc);
1230 if (RT_SUCCESS(rc))
1231 {
1232 strName.cloneTo(aDirectory);
1233 }
1234 else
1235 {
1236 switch (rc)
1237 {
1238 case VERR_GENERAL_FAILURE: /** @todo Special guest control rc needed! */
1239 hr = GuestProcess::setErrorExternal(this, guestRc);
1240 break;
1241
1242 default:
1243 hr = setError(VBOX_E_IPRT_ERROR, tr("Temporary directory creation \"%s\" with template \"%s\" failed: %Rrc"),
1244 Utf8Str(aPath).c_str(), Utf8Str(aTemplate).c_str(), rc);
1245 break;
1246 }
1247 }
1248
1249 return hr;
1250#endif /* VBOX_WITH_GUEST_CONTROL */
1251}
1252
1253STDMETHODIMP GuestSession::DirectoryExists(IN_BSTR aPath, BOOL *aExists)
1254{
1255#ifndef VBOX_WITH_GUEST_CONTROL
1256 ReturnComNotImplemented();
1257#else
1258 LogFlowThisFuncEnter();
1259
1260 if (RT_UNLIKELY((aPath) == NULL || *(aPath) == '\0'))
1261 return setError(E_INVALIDARG, tr("No directory to check existence for specified"));
1262 CheckComArgOutPointerValid(aExists);
1263
1264 AutoCaller autoCaller(this);
1265 if (FAILED(autoCaller.rc())) return autoCaller.rc();
1266
1267 HRESULT hr = S_OK;
1268
1269 GuestFsObjData objData; int guestRc;
1270 int rc = directoryQueryInfoInternal(Utf8Str(aPath), objData, &guestRc);
1271 if (RT_SUCCESS(rc))
1272 {
1273 *aExists = objData.mType == FsObjType_Directory;
1274 }
1275 else
1276 {
1277 switch (rc)
1278 {
1279 case VERR_GENERAL_FAILURE: /** @todo Special guest control rc needed! */
1280 hr = GuestProcess::setErrorExternal(this, guestRc);
1281 break;
1282
1283 default:
1284 hr = setError(VBOX_E_IPRT_ERROR, tr("Querying directory existence \"%s\" failed: %Rrc"),
1285 Utf8Str(aPath).c_str(), rc);
1286 break;
1287 }
1288 }
1289
1290 return hr;
1291#endif /* VBOX_WITH_GUEST_CONTROL */
1292}
1293
1294STDMETHODIMP GuestSession::DirectoryOpen(IN_BSTR aPath, IN_BSTR aFilter, ComSafeArrayIn(DirectoryOpenFlag_T, aFlags), IGuestDirectory **aDirectory)
1295{
1296#ifndef VBOX_WITH_GUEST_CONTROL
1297 ReturnComNotImplemented();
1298#else
1299 LogFlowThisFuncEnter();
1300
1301 if (RT_UNLIKELY((aPath) == NULL || *(aPath) == '\0'))
1302 return setError(E_INVALIDARG, tr("No directory to open specified"));
1303 if (RT_UNLIKELY((aFilter) != NULL && *(aFilter) != '\0'))
1304 return setError(E_INVALIDARG, tr("Directory filters are not implemented yet"));
1305 CheckComArgOutPointerValid(aDirectory);
1306
1307 AutoCaller autoCaller(this);
1308 if (FAILED(autoCaller.rc())) return autoCaller.rc();
1309
1310 uint32_t fFlags = DirectoryOpenFlag_None;
1311 if (aFlags)
1312 {
1313 com::SafeArray<DirectoryOpenFlag_T> flags(ComSafeArrayInArg(aFlags));
1314 for (size_t i = 0; i < flags.size(); i++)
1315 fFlags |= flags[i];
1316
1317 if (fFlags)
1318 return setError(E_INVALIDARG, tr("Open flags (%#x) not implemented yet"), fFlags);
1319 }
1320
1321 HRESULT hr = S_OK;
1322
1323 ComObjPtr <GuestDirectory> pDirectory;
1324 int rc = directoryOpenInternal(Utf8Str(aPath), Utf8Str(aFilter), fFlags, pDirectory);
1325 if (RT_SUCCESS(rc))
1326 {
1327 /* Return directory object to the caller. */
1328 hr = pDirectory.queryInterfaceTo(aDirectory);
1329 }
1330 else
1331 {
1332 switch (rc)
1333 {
1334 case VERR_INVALID_PARAMETER:
1335 hr = setError(VBOX_E_IPRT_ERROR, tr("Opening directory \"%s\" failed; invalid parameters given",
1336 Utf8Str(aPath).c_str()));
1337 break;
1338
1339 default:
1340 hr = setError(VBOX_E_IPRT_ERROR, tr("Opening directory \"%s\" failed: %Rrc"),
1341 Utf8Str(aPath).c_str(),rc);
1342 break;
1343 }
1344 }
1345
1346 return hr;
1347#endif /* VBOX_WITH_GUEST_CONTROL */
1348}
1349
1350STDMETHODIMP GuestSession::DirectoryQueryInfo(IN_BSTR aPath, IGuestFsObjInfo **aInfo)
1351{
1352#ifndef VBOX_WITH_GUEST_CONTROL
1353 ReturnComNotImplemented();
1354#else
1355 LogFlowThisFuncEnter();
1356
1357 if (RT_UNLIKELY((aPath) == NULL || *(aPath) == '\0'))
1358 return setError(E_INVALIDARG, tr("No directory to query information for specified"));
1359 CheckComArgOutPointerValid(aInfo);
1360
1361 AutoCaller autoCaller(this);
1362 if (FAILED(autoCaller.rc())) return autoCaller.rc();
1363
1364 HRESULT hr = S_OK;
1365
1366 GuestFsObjData objData; int guestRc;
1367 int vrc = directoryQueryInfoInternal(Utf8Str(aPath), objData, &guestRc);
1368 if (RT_SUCCESS(vrc))
1369 {
1370 if (objData.mType == FsObjType_Directory)
1371 {
1372 ComObjPtr<GuestFsObjInfo> pFsObjInfo;
1373 hr = pFsObjInfo.createObject();
1374 if (FAILED(hr)) return hr;
1375
1376 vrc = pFsObjInfo->init(objData);
1377 if (RT_SUCCESS(vrc))
1378 {
1379 hr = pFsObjInfo.queryInterfaceTo(aInfo);
1380 if (FAILED(hr)) return hr;
1381 }
1382 }
1383 }
1384
1385 if (RT_FAILURE(vrc))
1386 {
1387 switch (vrc)
1388 {
1389 case VERR_GENERAL_FAILURE: /** @todo Special guest control rc needed! */
1390 hr = GuestProcess::setErrorExternal(this, guestRc);
1391 break;
1392
1393 case VERR_NOT_A_DIRECTORY:
1394 hr = setError(VBOX_E_IPRT_ERROR, tr("Element \"%s\" exists but is not a directory",
1395 Utf8Str(aPath).c_str()));
1396 break;
1397
1398 default:
1399 hr = setError(VBOX_E_IPRT_ERROR, tr("Querying directory information for \"%s\" failed: %Rrc"),
1400 Utf8Str(aPath).c_str(), vrc);
1401 break;
1402 }
1403 }
1404
1405 return hr;
1406#endif /* VBOX_WITH_GUEST_CONTROL */
1407}
1408
1409STDMETHODIMP GuestSession::DirectoryRemove(IN_BSTR aPath)
1410{
1411#ifndef VBOX_WITH_GUEST_CONTROL
1412 ReturnComNotImplemented();
1413#else
1414 LogFlowThisFuncEnter();
1415
1416 AutoCaller autoCaller(this);
1417 if (FAILED(autoCaller.rc())) return autoCaller.rc();
1418
1419 ReturnComNotImplemented();
1420#endif /* VBOX_WITH_GUEST_CONTROL */
1421}
1422
1423STDMETHODIMP GuestSession::DirectoryRemoveRecursive(IN_BSTR aPath, ComSafeArrayIn(DirectoryRemoveRecFlag_T, aFlags), IProgress **aProgress)
1424{
1425#ifndef VBOX_WITH_GUEST_CONTROL
1426 ReturnComNotImplemented();
1427#else
1428 LogFlowThisFuncEnter();
1429
1430 AutoCaller autoCaller(this);
1431 if (FAILED(autoCaller.rc())) return autoCaller.rc();
1432
1433 ReturnComNotImplemented();
1434#endif /* VBOX_WITH_GUEST_CONTROL */
1435}
1436
1437STDMETHODIMP GuestSession::DirectoryRename(IN_BSTR aSource, IN_BSTR aDest, ComSafeArrayIn(PathRenameFlag_T, aFlags))
1438{
1439#ifndef VBOX_WITH_GUEST_CONTROL
1440 ReturnComNotImplemented();
1441#else
1442 LogFlowThisFuncEnter();
1443
1444 AutoCaller autoCaller(this);
1445 if (FAILED(autoCaller.rc())) return autoCaller.rc();
1446
1447 ReturnComNotImplemented();
1448#endif /* VBOX_WITH_GUEST_CONTROL */
1449}
1450
1451STDMETHODIMP GuestSession::DirectorySetACL(IN_BSTR aPath, IN_BSTR aACL)
1452{
1453#ifndef VBOX_WITH_GUEST_CONTROL
1454 ReturnComNotImplemented();
1455#else
1456 LogFlowThisFuncEnter();
1457
1458 AutoCaller autoCaller(this);
1459 if (FAILED(autoCaller.rc())) return autoCaller.rc();
1460
1461 ReturnComNotImplemented();
1462#endif /* VBOX_WITH_GUEST_CONTROL */
1463}
1464
1465STDMETHODIMP GuestSession::EnvironmentClear(void)
1466{
1467#ifndef VBOX_WITH_GUEST_CONTROL
1468 ReturnComNotImplemented();
1469#else
1470 LogFlowThisFuncEnter();
1471
1472 AutoCaller autoCaller(this);
1473 if (FAILED(autoCaller.rc())) return autoCaller.rc();
1474
1475 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
1476
1477 mData.mEnvironment.Clear();
1478
1479 LogFlowFuncLeaveRC(S_OK);
1480 return S_OK;
1481#endif /* VBOX_WITH_GUEST_CONTROL */
1482}
1483
1484STDMETHODIMP GuestSession::EnvironmentGet(IN_BSTR aName, BSTR *aValue)
1485{
1486#ifndef VBOX_WITH_GUEST_CONTROL
1487 ReturnComNotImplemented();
1488#else
1489 LogFlowThisFuncEnter();
1490
1491 if (RT_UNLIKELY((aName) == NULL || *(aName) == '\0'))
1492 return setError(E_INVALIDARG, tr("No value name specified"));
1493
1494 CheckComArgOutPointerValid(aValue);
1495
1496 AutoCaller autoCaller(this);
1497 if (FAILED(autoCaller.rc())) return autoCaller.rc();
1498
1499 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
1500
1501 Bstr strValue(mData.mEnvironment.Get(Utf8Str(aName)));
1502 strValue.cloneTo(aValue);
1503
1504 LogFlowFuncLeaveRC(S_OK);
1505 return S_OK;
1506#endif /* VBOX_WITH_GUEST_CONTROL */
1507}
1508
1509STDMETHODIMP GuestSession::EnvironmentSet(IN_BSTR aName, IN_BSTR aValue)
1510{
1511#ifndef VBOX_WITH_GUEST_CONTROL
1512 ReturnComNotImplemented();
1513#else
1514 LogFlowThisFuncEnter();
1515
1516 if (RT_UNLIKELY((aName) == NULL || *(aName) == '\0'))
1517 return setError(E_INVALIDARG, tr("No value name specified"));
1518
1519 AutoCaller autoCaller(this);
1520 if (FAILED(autoCaller.rc())) return autoCaller.rc();
1521
1522 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
1523
1524 int rc = mData.mEnvironment.Set(Utf8Str(aName), Utf8Str(aValue));
1525
1526 HRESULT hr = RT_SUCCESS(rc) ? S_OK : VBOX_E_IPRT_ERROR;
1527 LogFlowFuncLeaveRC(hr);
1528 return hr;
1529#endif /* VBOX_WITH_GUEST_CONTROL */
1530}
1531
1532STDMETHODIMP GuestSession::EnvironmentUnset(IN_BSTR aName)
1533{
1534#ifndef VBOX_WITH_GUEST_CONTROL
1535 ReturnComNotImplemented();
1536#else
1537 LogFlowThisFuncEnter();
1538
1539 AutoCaller autoCaller(this);
1540 if (FAILED(autoCaller.rc())) return autoCaller.rc();
1541
1542 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
1543
1544 mData.mEnvironment.Unset(Utf8Str(aName));
1545
1546 LogFlowFuncLeaveRC(S_OK);
1547 return S_OK;
1548#endif /* VBOX_WITH_GUEST_CONTROL */
1549}
1550
1551STDMETHODIMP GuestSession::FileCreateTemp(IN_BSTR aTemplate, ULONG aMode, IN_BSTR aPath, BOOL aSecure, IGuestFile **aFile)
1552{
1553#ifndef VBOX_WITH_GUEST_CONTROL
1554 ReturnComNotImplemented();
1555#else
1556 LogFlowThisFuncEnter();
1557
1558 AutoCaller autoCaller(this);
1559 if (FAILED(autoCaller.rc())) return autoCaller.rc();
1560
1561 ReturnComNotImplemented();
1562#endif /* VBOX_WITH_GUEST_CONTROL */
1563}
1564
1565STDMETHODIMP GuestSession::FileExists(IN_BSTR aPath, BOOL *aExists)
1566{
1567#ifndef VBOX_WITH_GUEST_CONTROL
1568 ReturnComNotImplemented();
1569#else
1570 LogFlowThisFuncEnter();
1571
1572 if (RT_UNLIKELY((aPath) == NULL || *(aPath) == '\0'))
1573 return setError(E_INVALIDARG, tr("No file to check existence for specified"));
1574 CheckComArgOutPointerValid(aExists);
1575
1576 AutoCaller autoCaller(this);
1577 if (FAILED(autoCaller.rc())) return autoCaller.rc();
1578
1579 GuestFsObjData objData; int guestRc;
1580 int vrc = fileQueryInfoInternal(Utf8Str(aPath), objData, &guestRc);
1581 if (RT_SUCCESS(vrc))
1582 {
1583 *aExists = TRUE;
1584 return S_OK;
1585 }
1586
1587 HRESULT hr = S_OK;
1588
1589 switch (vrc)
1590 {
1591 case VERR_GENERAL_FAILURE: /** @todo Special guest control rc needed! */
1592 hr = GuestProcess::setErrorExternal(this, guestRc);
1593 break;
1594
1595 case VERR_NOT_A_FILE:
1596 *aExists = FALSE;
1597 break;
1598
1599 default:
1600 hr = setError(VBOX_E_IPRT_ERROR, tr("Querying file information for \"%s\" failed: %Rrc"),
1601 Utf8Str(aPath).c_str(), vrc);
1602 break;
1603 }
1604
1605 return hr;
1606#endif /* VBOX_WITH_GUEST_CONTROL */
1607}
1608
1609STDMETHODIMP GuestSession::FileRemove(IN_BSTR aPath)
1610{
1611#ifndef VBOX_WITH_GUEST_CONTROL
1612 ReturnComNotImplemented();
1613#else
1614 LogFlowThisFuncEnter();
1615
1616 if (RT_UNLIKELY((aPath) == NULL || *(aPath) == '\0'))
1617 return setError(E_INVALIDARG, tr("No file to remove specified"));
1618
1619 AutoCaller autoCaller(this);
1620 if (FAILED(autoCaller.rc())) return autoCaller.rc();
1621
1622 HRESULT hr = S_OK;
1623
1624 int guestRc;
1625 int vrc = fileRemoveInternal(Utf8Str(aPath), &guestRc);
1626 if (RT_FAILURE(vrc))
1627 {
1628 switch (vrc)
1629 {
1630 case VERR_GENERAL_FAILURE: /** @todo Special guest control rc needed! */
1631 hr = GuestProcess::setErrorExternal(this, guestRc);
1632 break;
1633
1634 default:
1635 hr = setError(VBOX_E_IPRT_ERROR, tr("Removing file \"%s\" failed: %Rrc"),
1636 Utf8Str(aPath).c_str(), vrc);
1637 break;
1638 }
1639 }
1640
1641 return hr;
1642#endif /* VBOX_WITH_GUEST_CONTROL */
1643}
1644
1645STDMETHODIMP GuestSession::FileOpen(IN_BSTR aPath, IN_BSTR aOpenMode, IN_BSTR aDisposition, ULONG aCreationMode, LONG64 aOffset, IGuestFile **aFile)
1646{
1647#ifndef VBOX_WITH_GUEST_CONTROL
1648 ReturnComNotImplemented();
1649#else
1650 LogFlowThisFuncEnter();
1651
1652 if (RT_UNLIKELY((aPath) == NULL || *(aPath) == '\0'))
1653 return setError(E_INVALIDARG, tr("No file to open specified"));
1654 if (RT_UNLIKELY((aOpenMode) == NULL || *(aOpenMode) == '\0'))
1655 return setError(E_INVALIDARG, tr("No open mode specified"));
1656 if (RT_UNLIKELY((aDisposition) == NULL || *(aDisposition) == '\0'))
1657 return setError(E_INVALIDARG, tr("No disposition mode specified"));
1658
1659 CheckComArgOutPointerValid(aFile);
1660
1661 AutoCaller autoCaller(this);
1662 if (FAILED(autoCaller.rc())) return autoCaller.rc();
1663
1664 /** @todo Validate open mode. */
1665 /** @todo Validate disposition mode. */
1666
1667 /** @todo Validate creation mode. */
1668 uint32_t uCreationMode = 0;
1669
1670 HRESULT hr = S_OK;
1671
1672 ComObjPtr <GuestFile> pFile; int guestRc;
1673 int vrc = fileOpenInternal(Utf8Str(aPath), Utf8Str(aOpenMode), Utf8Str(aDisposition),
1674 aCreationMode, aOffset, pFile, &guestRc);
1675 if (RT_SUCCESS(vrc))
1676 {
1677 /* Return directory object to the caller. */
1678 hr = pFile.queryInterfaceTo(aFile);
1679 }
1680 else
1681 {
1682 switch (vrc)
1683 {
1684 case VERR_GENERAL_FAILURE: /** @todo Special guest control rc needed! */
1685 hr = GuestProcess::setErrorExternal(this, guestRc);
1686 break;
1687
1688 default:
1689 hr = setError(VBOX_E_IPRT_ERROR, tr("Opening file \"%s\" failed: %Rrc"),
1690 Utf8Str(aPath).c_str(), vrc);
1691 break;
1692 }
1693 }
1694
1695 return hr;
1696#endif /* VBOX_WITH_GUEST_CONTROL */
1697}
1698
1699STDMETHODIMP GuestSession::FileQueryInfo(IN_BSTR aPath, IGuestFsObjInfo **aInfo)
1700{
1701#ifndef VBOX_WITH_GUEST_CONTROL
1702 ReturnComNotImplemented();
1703#else
1704 LogFlowThisFuncEnter();
1705
1706 if (RT_UNLIKELY((aPath) == NULL || *(aPath) == '\0'))
1707 return setError(E_INVALIDARG, tr("No file to query information for specified"));
1708 CheckComArgOutPointerValid(aInfo);
1709
1710 AutoCaller autoCaller(this);
1711 if (FAILED(autoCaller.rc())) return autoCaller.rc();
1712
1713 HRESULT hr = S_OK;
1714
1715 GuestFsObjData objData; int guestRc;
1716 int vrc = fileQueryInfoInternal(Utf8Str(aPath), objData, &guestRc);
1717 if (RT_SUCCESS(vrc))
1718 {
1719 ComObjPtr<GuestFsObjInfo> pFsObjInfo;
1720 hr = pFsObjInfo.createObject();
1721 if (FAILED(hr)) return hr;
1722
1723 vrc = pFsObjInfo->init(objData);
1724 if (RT_SUCCESS(vrc))
1725 {
1726 hr = pFsObjInfo.queryInterfaceTo(aInfo);
1727 if (FAILED(hr)) return hr;
1728 }
1729 }
1730
1731 if (RT_FAILURE(vrc))
1732 {
1733 switch (vrc)
1734 {
1735 case VERR_GENERAL_FAILURE: /** @todo Special guest control rc needed! */
1736 hr = GuestProcess::setErrorExternal(this, guestRc);
1737 break;
1738
1739 case VERR_NOT_A_FILE:
1740 hr = setError(VBOX_E_IPRT_ERROR, tr("Element exists but is not a file"));
1741 break;
1742
1743 default:
1744 hr = setError(VBOX_E_IPRT_ERROR, tr("Querying file information failed: %Rrc"), vrc);
1745 break;
1746 }
1747 }
1748
1749 return hr;
1750#endif /* VBOX_WITH_GUEST_CONTROL */
1751}
1752
1753STDMETHODIMP GuestSession::FileQuerySize(IN_BSTR aPath, LONG64 *aSize)
1754{
1755#ifndef VBOX_WITH_GUEST_CONTROL
1756 ReturnComNotImplemented();
1757#else
1758 LogFlowThisFuncEnter();
1759
1760 if (RT_UNLIKELY((aPath) == NULL || *(aPath) == '\0'))
1761 return setError(E_INVALIDARG, tr("No file to query size for specified"));
1762 CheckComArgOutPointerValid(aSize);
1763
1764 AutoCaller autoCaller(this);
1765 if (FAILED(autoCaller.rc())) return autoCaller.rc();
1766
1767 HRESULT hr = S_OK;
1768
1769 int64_t llSize; int guestRc;
1770 int vrc = fileQuerySizeInternal(Utf8Str(aPath), &llSize, &guestRc);
1771 if (RT_SUCCESS(vrc))
1772 {
1773 *aSize = llSize;
1774 }
1775 else
1776 {
1777 switch (vrc)
1778 {
1779 case VERR_GENERAL_FAILURE: /** @todo Special guest control rc needed! */
1780 hr = GuestProcess::setErrorExternal(this, guestRc);
1781 break;
1782
1783 default:
1784 hr = setError(VBOX_E_IPRT_ERROR, tr("Querying file size failed: %Rrc"), vrc);
1785 break;
1786 }
1787 }
1788
1789 return hr;
1790#endif /* VBOX_WITH_GUEST_CONTROL */
1791}
1792
1793STDMETHODIMP GuestSession::FileRename(IN_BSTR aSource, IN_BSTR aDest, ComSafeArrayIn(PathRenameFlag_T, aFlags))
1794{
1795#ifndef VBOX_WITH_GUEST_CONTROL
1796 ReturnComNotImplemented();
1797#else
1798 LogFlowThisFuncEnter();
1799
1800 AutoCaller autoCaller(this);
1801 if (FAILED(autoCaller.rc())) return autoCaller.rc();
1802
1803 ReturnComNotImplemented();
1804#endif /* VBOX_WITH_GUEST_CONTROL */
1805}
1806
1807STDMETHODIMP GuestSession::FileSetACL(IN_BSTR aPath, IN_BSTR aACL)
1808{
1809#ifndef VBOX_WITH_GUEST_CONTROL
1810 ReturnComNotImplemented();
1811#else
1812 LogFlowThisFuncEnter();
1813
1814 AutoCaller autoCaller(this);
1815 if (FAILED(autoCaller.rc())) return autoCaller.rc();
1816
1817 ReturnComNotImplemented();
1818#endif /* VBOX_WITH_GUEST_CONTROL */
1819}
1820
1821STDMETHODIMP GuestSession::ProcessCreate(IN_BSTR aCommand, ComSafeArrayIn(IN_BSTR, aArguments), ComSafeArrayIn(IN_BSTR, aEnvironment),
1822 ComSafeArrayIn(ProcessCreateFlag_T, aFlags), ULONG aTimeoutMS, IGuestProcess **aProcess)
1823{
1824#ifndef VBOX_WITH_GUEST_CONTROL
1825 ReturnComNotImplemented();
1826#else
1827 LogFlowThisFuncEnter();
1828
1829 com::SafeArray<LONG> affinity;
1830
1831 return ProcessCreateEx(aCommand, ComSafeArrayInArg(aArguments), ComSafeArrayInArg(aEnvironment),
1832 ComSafeArrayInArg(aFlags), aTimeoutMS, ProcessPriority_Default, ComSafeArrayAsInParam(affinity), aProcess);
1833#endif /* VBOX_WITH_GUEST_CONTROL */
1834}
1835
1836STDMETHODIMP GuestSession::ProcessCreateEx(IN_BSTR aCommand, ComSafeArrayIn(IN_BSTR, aArguments), ComSafeArrayIn(IN_BSTR, aEnvironment),
1837 ComSafeArrayIn(ProcessCreateFlag_T, aFlags), ULONG aTimeoutMS,
1838 ProcessPriority_T aPriority, ComSafeArrayIn(LONG, aAffinity),
1839 IGuestProcess **aProcess)
1840{
1841#ifndef VBOX_WITH_GUEST_CONTROL
1842 ReturnComNotImplemented();
1843#else
1844 LogFlowThisFuncEnter();
1845
1846 if (RT_UNLIKELY((aCommand) == NULL || *(aCommand) == '\0'))
1847 return setError(E_INVALIDARG, tr("No command to execute specified"));
1848 CheckComArgOutPointerValid(aProcess);
1849
1850 AutoCaller autoCaller(this);
1851 if (FAILED(autoCaller.rc())) return autoCaller.rc();
1852
1853 GuestProcessStartupInfo procInfo;
1854 procInfo.mCommand = Utf8Str(aCommand);
1855
1856 if (aArguments)
1857 {
1858 com::SafeArray<IN_BSTR> arguments(ComSafeArrayInArg(aArguments));
1859 for (size_t i = 0; i < arguments.size(); i++)
1860 procInfo.mArguments.push_back(Utf8Str(arguments[i]));
1861 }
1862
1863 int rc = VINF_SUCCESS;
1864
1865 /*
1866 * Create the process environment:
1867 * - Apply the session environment in a first step, and
1868 * - Apply environment variables specified by this call to
1869 * have the chance of overwriting/deleting session entries.
1870 */
1871 procInfo.mEnvironment = mData.mEnvironment; /* Apply original session environment. */
1872
1873 if (aEnvironment)
1874 {
1875 com::SafeArray<IN_BSTR> environment(ComSafeArrayInArg(aEnvironment));
1876 for (size_t i = 0; i < environment.size() && RT_SUCCESS(rc); i++)
1877 rc = procInfo.mEnvironment.Set(Utf8Str(environment[i]));
1878 }
1879
1880 HRESULT hr = S_OK;
1881
1882 if (RT_SUCCESS(rc))
1883 {
1884 if (aFlags)
1885 {
1886 com::SafeArray<ProcessCreateFlag_T> flags(ComSafeArrayInArg(aFlags));
1887 for (size_t i = 0; i < flags.size(); i++)
1888 procInfo.mFlags |= flags[i];
1889 }
1890
1891 procInfo.mTimeoutMS = aTimeoutMS;
1892
1893 if (aAffinity)
1894 {
1895 com::SafeArray<LONG> affinity(ComSafeArrayInArg(aAffinity));
1896 for (size_t i = 0; i < affinity.size(); i++)
1897 procInfo.mAffinity[i] = affinity[i]; /** @todo Really necessary? Later. */
1898 }
1899
1900 procInfo.mPriority = aPriority;
1901
1902 ComObjPtr<GuestProcess> pProcess;
1903 rc = processCreateExInteral(procInfo, pProcess);
1904 if (RT_SUCCESS(rc))
1905 {
1906 /* Return guest session to the caller. */
1907 HRESULT hr2 = pProcess.queryInterfaceTo(aProcess);
1908 if (FAILED(hr2))
1909 rc = VERR_COM_OBJECT_NOT_FOUND;
1910
1911 if (RT_SUCCESS(rc))
1912 rc = pProcess->startProcessAsync();
1913 }
1914 }
1915
1916 if (RT_FAILURE(rc))
1917 {
1918 switch (rc)
1919 {
1920 case VERR_MAX_PROCS_REACHED:
1921 hr = setError(VBOX_E_IPRT_ERROR, tr("Maximum number of guest objects per session (%ld) reached"),
1922 VBOX_GUESTCTRL_MAX_OBJECTS);
1923 break;
1924
1925 /** @todo Add more errors here. */
1926
1927 default:
1928 hr = setError(VBOX_E_IPRT_ERROR, tr("Could not create guest process, rc=%Rrc"), rc);
1929 break;
1930 }
1931 }
1932
1933 LogFlowFuncLeaveRC(rc);
1934 return hr;
1935#endif /* VBOX_WITH_GUEST_CONTROL */
1936}
1937
1938STDMETHODIMP GuestSession::ProcessGet(ULONG aPID, IGuestProcess **aProcess)
1939{
1940#ifndef VBOX_WITH_GUEST_CONTROL
1941 ReturnComNotImplemented();
1942#else
1943 LogFlowThisFunc(("aPID=%RU32\n", aPID));
1944
1945 CheckComArgOutPointerValid(aProcess);
1946 if (aPID == 0)
1947 return setError(E_INVALIDARG, tr("No valid process ID (PID) specified"));
1948
1949 AutoCaller autoCaller(this);
1950 if (FAILED(autoCaller.rc())) return autoCaller.rc();
1951
1952 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
1953
1954 HRESULT hr = S_OK;
1955
1956 ComObjPtr<GuestProcess> pProcess;
1957 int rc = processGetByPID(aPID, &pProcess);
1958 if (RT_FAILURE(rc))
1959 hr = setError(E_INVALIDARG, tr("No process with PID %RU32 found"), aPID);
1960
1961 /* This will set (*aProcess) to NULL if pProgress is NULL. */
1962 HRESULT hr2 = pProcess.queryInterfaceTo(aProcess);
1963 if (SUCCEEDED(hr))
1964 hr = hr2;
1965
1966 LogFlowThisFunc(("aProcess=%p, hr=%Rhrc\n", *aProcess, hr));
1967 return hr;
1968#endif /* VBOX_WITH_GUEST_CONTROL */
1969}
1970
1971STDMETHODIMP GuestSession::SymlinkCreate(IN_BSTR aSource, IN_BSTR aTarget, SymlinkType_T aType)
1972{
1973#ifndef VBOX_WITH_GUEST_CONTROL
1974 ReturnComNotImplemented();
1975#else
1976 LogFlowThisFuncEnter();
1977
1978 AutoCaller autoCaller(this);
1979 if (FAILED(autoCaller.rc())) return autoCaller.rc();
1980
1981 ReturnComNotImplemented();
1982#endif /* VBOX_WITH_GUEST_CONTROL */
1983}
1984
1985STDMETHODIMP GuestSession::SymlinkExists(IN_BSTR aSymlink, BOOL *aExists)
1986{
1987#ifndef VBOX_WITH_GUEST_CONTROL
1988 ReturnComNotImplemented();
1989#else
1990 LogFlowThisFuncEnter();
1991
1992 AutoCaller autoCaller(this);
1993 if (FAILED(autoCaller.rc())) return autoCaller.rc();
1994
1995 ReturnComNotImplemented();
1996#endif /* VBOX_WITH_GUEST_CONTROL */
1997}
1998
1999STDMETHODIMP GuestSession::SymlinkRead(IN_BSTR aSymlink, ComSafeArrayIn(SymlinkReadFlag_T, aFlags), BSTR *aTarget)
2000{
2001#ifndef VBOX_WITH_GUEST_CONTROL
2002 ReturnComNotImplemented();
2003#else
2004 LogFlowThisFuncEnter();
2005
2006 AutoCaller autoCaller(this);
2007 if (FAILED(autoCaller.rc())) return autoCaller.rc();
2008
2009 ReturnComNotImplemented();
2010#endif /* VBOX_WITH_GUEST_CONTROL */
2011}
2012
2013STDMETHODIMP GuestSession::SymlinkRemoveDirectory(IN_BSTR aPath)
2014{
2015#ifndef VBOX_WITH_GUEST_CONTROL
2016 ReturnComNotImplemented();
2017#else
2018 LogFlowThisFuncEnter();
2019
2020 AutoCaller autoCaller(this);
2021 if (FAILED(autoCaller.rc())) return autoCaller.rc();
2022
2023 ReturnComNotImplemented();
2024#endif /* VBOX_WITH_GUEST_CONTROL */
2025}
2026
2027STDMETHODIMP GuestSession::SymlinkRemoveFile(IN_BSTR aFile)
2028{
2029#ifndef VBOX_WITH_GUEST_CONTROL
2030 ReturnComNotImplemented();
2031#else
2032 LogFlowThisFuncEnter();
2033
2034 AutoCaller autoCaller(this);
2035 if (FAILED(autoCaller.rc())) return autoCaller.rc();
2036
2037 ReturnComNotImplemented();
2038#endif /* VBOX_WITH_GUEST_CONTROL */
2039}
2040
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