VirtualBox

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

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

GuestCtrl: Handle bad_alloc, warnings.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 60.0 KB
Line 
1
2/* $Id: GuestSessionImpl.cpp 43170 2012-09-04 16:37:40Z 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 try
1080 {
1081 ComObjPtr<Progress> pProgress;
1082 SessionTaskCopyFrom *pTask = new SessionTaskCopyFrom(this /* GuestSession */,
1083 Utf8Str(aSource), Utf8Str(aDest), fFlags);
1084 int rc = startTaskAsync(Utf8StrFmt(tr("Copying \"%ls\" from guest to \"%ls\" on the host"), aSource, aDest),
1085 pTask, pProgress);
1086 if (RT_SUCCESS(rc))
1087 {
1088 /* Return progress to the caller. */
1089 hr = pProgress.queryInterfaceTo(aProgress);
1090 }
1091 else
1092 hr = setError(VBOX_E_IPRT_ERROR,
1093 tr("Starting task for copying file \"%ls\" from guest to \"%ls\" on the host failed: %Rrc"), rc);
1094 }
1095 catch(std::bad_alloc &)
1096 {
1097 hr = E_OUTOFMEMORY;
1098 }
1099
1100 return hr;
1101#endif /* VBOX_WITH_GUEST_CONTROL */
1102}
1103
1104STDMETHODIMP GuestSession::CopyTo(IN_BSTR aSource, IN_BSTR aDest, ComSafeArrayIn(CopyFileFlag_T, aFlags), IProgress **aProgress)
1105{
1106#ifndef VBOX_WITH_GUEST_CONTROL
1107 ReturnComNotImplemented();
1108#else
1109 CheckComArgStrNotEmptyOrNull(aSource);
1110 CheckComArgStrNotEmptyOrNull(aDest);
1111 CheckComArgOutPointerValid(aProgress);
1112
1113 LogFlowThisFuncEnter();
1114
1115 if (RT_UNLIKELY((aSource) == NULL || *(aSource) == '\0'))
1116 return setError(E_INVALIDARG, tr("No source specified"));
1117 if (RT_UNLIKELY((aDest) == NULL || *(aDest) == '\0'))
1118 return setError(E_INVALIDARG, tr("No destination specified"));
1119
1120 AutoCaller autoCaller(this);
1121 if (FAILED(autoCaller.rc())) return autoCaller.rc();
1122
1123 uint32_t fFlags = CopyFileFlag_None;
1124 if (aFlags)
1125 {
1126 com::SafeArray<CopyFileFlag_T> flags(ComSafeArrayInArg(aFlags));
1127 for (size_t i = 0; i < flags.size(); i++)
1128 fFlags |= flags[i];
1129 }
1130
1131 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
1132
1133 HRESULT hr = S_OK;
1134
1135 try
1136 {
1137 ComObjPtr<Progress> pProgress;
1138 SessionTaskCopyTo *pTask = new SessionTaskCopyTo(this /* GuestSession */,
1139 Utf8Str(aSource), Utf8Str(aDest), fFlags);
1140 AssertPtrReturn(pTask, VERR_NO_MEMORY);
1141 int rc = startTaskAsync(Utf8StrFmt(tr("Copying \"%ls\" from host to \"%ls\" on the guest"), aSource, aDest),
1142 pTask, pProgress);
1143 if (RT_SUCCESS(rc))
1144 {
1145 /* Return progress to the caller. */
1146 hr = pProgress.queryInterfaceTo(aProgress);
1147 }
1148 else
1149 hr = setError(VBOX_E_IPRT_ERROR,
1150 tr("Starting task for copying file \"%ls\" from host to \"%ls\" on the guest failed: %Rrc"), rc);
1151 }
1152 catch(std::bad_alloc &)
1153 {
1154 hr = E_OUTOFMEMORY;
1155 }
1156
1157 return hr;
1158#endif /* VBOX_WITH_GUEST_CONTROL */
1159}
1160
1161STDMETHODIMP GuestSession::DirectoryCreate(IN_BSTR aPath, ULONG aMode,
1162 ComSafeArrayIn(DirectoryCreateFlag_T, aFlags))
1163{
1164#ifndef VBOX_WITH_GUEST_CONTROL
1165 ReturnComNotImplemented();
1166#else
1167 LogFlowThisFuncEnter();
1168
1169 if (RT_UNLIKELY((aPath) == NULL || *(aPath) == '\0'))
1170 return setError(E_INVALIDARG, tr("No directory to create specified"));
1171
1172 AutoCaller autoCaller(this);
1173 if (FAILED(autoCaller.rc())) return autoCaller.rc();
1174
1175 uint32_t fFlags = DirectoryCreateFlag_None;
1176 if (aFlags)
1177 {
1178 com::SafeArray<DirectoryCreateFlag_T> flags(ComSafeArrayInArg(aFlags));
1179 for (size_t i = 0; i < flags.size(); i++)
1180 fFlags |= flags[i];
1181
1182 if (fFlags)
1183 {
1184 if (!(fFlags & DirectoryCreateFlag_Parents))
1185 return setError(E_INVALIDARG, tr("Unknown flags (%#x)"), fFlags);
1186 }
1187 }
1188
1189 HRESULT hr = S_OK;
1190
1191 ComObjPtr <GuestDirectory> pDirectory; int guestRc;
1192 int rc = directoryCreateInternal(Utf8Str(aPath), (uint32_t)aMode, fFlags, &guestRc);
1193 if (RT_FAILURE(rc))
1194 {
1195 switch (rc)
1196 {
1197 case VERR_GENERAL_FAILURE: /** @todo Special guest control rc needed! */
1198 hr = GuestProcess::setErrorExternal(this, guestRc);
1199 break;
1200
1201 case VERR_INVALID_PARAMETER:
1202 hr = setError(VBOX_E_IPRT_ERROR, tr("Directory creation failed: Invalid parameters given"));
1203 break;
1204
1205 case VERR_BROKEN_PIPE:
1206 hr = setError(VBOX_E_IPRT_ERROR, tr("Directory creation failed: Unexpectedly aborted"));
1207 break;
1208
1209 case VERR_CANT_CREATE:
1210 hr = setError(VBOX_E_IPRT_ERROR, tr("Directory creation failed: Could not create directory"));
1211 break;
1212
1213 default:
1214 hr = setError(VBOX_E_IPRT_ERROR, tr("Directory creation failed: %Rrc"), rc);
1215 break;
1216 }
1217 }
1218
1219 return hr;
1220#endif /* VBOX_WITH_GUEST_CONTROL */
1221}
1222
1223STDMETHODIMP GuestSession::DirectoryCreateTemp(IN_BSTR aTemplate, ULONG aMode, IN_BSTR aPath, BOOL aSecure, BSTR *aDirectory)
1224{
1225#ifndef VBOX_WITH_GUEST_CONTROL
1226 ReturnComNotImplemented();
1227#else
1228 LogFlowThisFuncEnter();
1229
1230 if (RT_UNLIKELY((aTemplate) == NULL || *(aTemplate) == '\0'))
1231 return setError(E_INVALIDARG, tr("No template specified"));
1232 if (RT_UNLIKELY((aPath) == NULL || *(aPath) == '\0'))
1233 return setError(E_INVALIDARG, tr("No directory name specified"));
1234 CheckComArgOutPointerValid(aDirectory);
1235
1236 AutoCaller autoCaller(this);
1237 if (FAILED(autoCaller.rc())) return autoCaller.rc();
1238
1239 HRESULT hr = S_OK;
1240
1241 Utf8Str strName; int guestRc;
1242 int rc = objectCreateTempInternal(Utf8Str(aTemplate),
1243 Utf8Str(aPath),
1244 true /* Directory */, strName, &guestRc);
1245 if (RT_SUCCESS(rc))
1246 {
1247 strName.cloneTo(aDirectory);
1248 }
1249 else
1250 {
1251 switch (rc)
1252 {
1253 case VERR_GENERAL_FAILURE: /** @todo Special guest control rc needed! */
1254 hr = GuestProcess::setErrorExternal(this, guestRc);
1255 break;
1256
1257 default:
1258 hr = setError(VBOX_E_IPRT_ERROR, tr("Temporary directory creation \"%s\" with template \"%s\" failed: %Rrc"),
1259 Utf8Str(aPath).c_str(), Utf8Str(aTemplate).c_str(), rc);
1260 break;
1261 }
1262 }
1263
1264 return hr;
1265#endif /* VBOX_WITH_GUEST_CONTROL */
1266}
1267
1268STDMETHODIMP GuestSession::DirectoryExists(IN_BSTR aPath, BOOL *aExists)
1269{
1270#ifndef VBOX_WITH_GUEST_CONTROL
1271 ReturnComNotImplemented();
1272#else
1273 LogFlowThisFuncEnter();
1274
1275 if (RT_UNLIKELY((aPath) == NULL || *(aPath) == '\0'))
1276 return setError(E_INVALIDARG, tr("No directory to check existence for specified"));
1277 CheckComArgOutPointerValid(aExists);
1278
1279 AutoCaller autoCaller(this);
1280 if (FAILED(autoCaller.rc())) return autoCaller.rc();
1281
1282 HRESULT hr = S_OK;
1283
1284 GuestFsObjData objData; int guestRc;
1285 int rc = directoryQueryInfoInternal(Utf8Str(aPath), objData, &guestRc);
1286 if (RT_SUCCESS(rc))
1287 {
1288 *aExists = objData.mType == FsObjType_Directory;
1289 }
1290 else
1291 {
1292 switch (rc)
1293 {
1294 case VERR_GENERAL_FAILURE: /** @todo Special guest control rc needed! */
1295 hr = GuestProcess::setErrorExternal(this, guestRc);
1296 break;
1297
1298 default:
1299 hr = setError(VBOX_E_IPRT_ERROR, tr("Querying directory existence \"%s\" failed: %Rrc"),
1300 Utf8Str(aPath).c_str(), rc);
1301 break;
1302 }
1303 }
1304
1305 return hr;
1306#endif /* VBOX_WITH_GUEST_CONTROL */
1307}
1308
1309STDMETHODIMP GuestSession::DirectoryOpen(IN_BSTR aPath, IN_BSTR aFilter, ComSafeArrayIn(DirectoryOpenFlag_T, aFlags), IGuestDirectory **aDirectory)
1310{
1311#ifndef VBOX_WITH_GUEST_CONTROL
1312 ReturnComNotImplemented();
1313#else
1314 LogFlowThisFuncEnter();
1315
1316 if (RT_UNLIKELY((aPath) == NULL || *(aPath) == '\0'))
1317 return setError(E_INVALIDARG, tr("No directory to open specified"));
1318 if (RT_UNLIKELY((aFilter) != NULL && *(aFilter) != '\0'))
1319 return setError(E_INVALIDARG, tr("Directory filters are not implemented yet"));
1320 CheckComArgOutPointerValid(aDirectory);
1321
1322 AutoCaller autoCaller(this);
1323 if (FAILED(autoCaller.rc())) return autoCaller.rc();
1324
1325 uint32_t fFlags = DirectoryOpenFlag_None;
1326 if (aFlags)
1327 {
1328 com::SafeArray<DirectoryOpenFlag_T> flags(ComSafeArrayInArg(aFlags));
1329 for (size_t i = 0; i < flags.size(); i++)
1330 fFlags |= flags[i];
1331
1332 if (fFlags)
1333 return setError(E_INVALIDARG, tr("Open flags (%#x) not implemented yet"), fFlags);
1334 }
1335
1336 HRESULT hr = S_OK;
1337
1338 ComObjPtr <GuestDirectory> pDirectory;
1339 int rc = directoryOpenInternal(Utf8Str(aPath), Utf8Str(aFilter), fFlags, pDirectory);
1340 if (RT_SUCCESS(rc))
1341 {
1342 /* Return directory object to the caller. */
1343 hr = pDirectory.queryInterfaceTo(aDirectory);
1344 }
1345 else
1346 {
1347 switch (rc)
1348 {
1349 case VERR_INVALID_PARAMETER:
1350 hr = setError(VBOX_E_IPRT_ERROR, tr("Opening directory \"%s\" failed; invalid parameters given",
1351 Utf8Str(aPath).c_str()));
1352 break;
1353
1354 default:
1355 hr = setError(VBOX_E_IPRT_ERROR, tr("Opening directory \"%s\" failed: %Rrc"),
1356 Utf8Str(aPath).c_str(),rc);
1357 break;
1358 }
1359 }
1360
1361 return hr;
1362#endif /* VBOX_WITH_GUEST_CONTROL */
1363}
1364
1365STDMETHODIMP GuestSession::DirectoryQueryInfo(IN_BSTR aPath, IGuestFsObjInfo **aInfo)
1366{
1367#ifndef VBOX_WITH_GUEST_CONTROL
1368 ReturnComNotImplemented();
1369#else
1370 LogFlowThisFuncEnter();
1371
1372 if (RT_UNLIKELY((aPath) == NULL || *(aPath) == '\0'))
1373 return setError(E_INVALIDARG, tr("No directory to query information for specified"));
1374 CheckComArgOutPointerValid(aInfo);
1375
1376 AutoCaller autoCaller(this);
1377 if (FAILED(autoCaller.rc())) return autoCaller.rc();
1378
1379 HRESULT hr = S_OK;
1380
1381 GuestFsObjData objData; int guestRc;
1382 int vrc = directoryQueryInfoInternal(Utf8Str(aPath), objData, &guestRc);
1383 if (RT_SUCCESS(vrc))
1384 {
1385 if (objData.mType == FsObjType_Directory)
1386 {
1387 ComObjPtr<GuestFsObjInfo> pFsObjInfo;
1388 hr = pFsObjInfo.createObject();
1389 if (FAILED(hr)) return hr;
1390
1391 vrc = pFsObjInfo->init(objData);
1392 if (RT_SUCCESS(vrc))
1393 {
1394 hr = pFsObjInfo.queryInterfaceTo(aInfo);
1395 if (FAILED(hr)) return hr;
1396 }
1397 }
1398 }
1399
1400 if (RT_FAILURE(vrc))
1401 {
1402 switch (vrc)
1403 {
1404 case VERR_GENERAL_FAILURE: /** @todo Special guest control rc needed! */
1405 hr = GuestProcess::setErrorExternal(this, guestRc);
1406 break;
1407
1408 case VERR_NOT_A_DIRECTORY:
1409 hr = setError(VBOX_E_IPRT_ERROR, tr("Element \"%s\" exists but is not a directory",
1410 Utf8Str(aPath).c_str()));
1411 break;
1412
1413 default:
1414 hr = setError(VBOX_E_IPRT_ERROR, tr("Querying directory information for \"%s\" failed: %Rrc"),
1415 Utf8Str(aPath).c_str(), vrc);
1416 break;
1417 }
1418 }
1419
1420 return hr;
1421#endif /* VBOX_WITH_GUEST_CONTROL */
1422}
1423
1424STDMETHODIMP GuestSession::DirectoryRemove(IN_BSTR aPath)
1425{
1426#ifndef VBOX_WITH_GUEST_CONTROL
1427 ReturnComNotImplemented();
1428#else
1429 LogFlowThisFuncEnter();
1430
1431 AutoCaller autoCaller(this);
1432 if (FAILED(autoCaller.rc())) return autoCaller.rc();
1433
1434 ReturnComNotImplemented();
1435#endif /* VBOX_WITH_GUEST_CONTROL */
1436}
1437
1438STDMETHODIMP GuestSession::DirectoryRemoveRecursive(IN_BSTR aPath, ComSafeArrayIn(DirectoryRemoveRecFlag_T, aFlags), IProgress **aProgress)
1439{
1440#ifndef VBOX_WITH_GUEST_CONTROL
1441 ReturnComNotImplemented();
1442#else
1443 LogFlowThisFuncEnter();
1444
1445 AutoCaller autoCaller(this);
1446 if (FAILED(autoCaller.rc())) return autoCaller.rc();
1447
1448 ReturnComNotImplemented();
1449#endif /* VBOX_WITH_GUEST_CONTROL */
1450}
1451
1452STDMETHODIMP GuestSession::DirectoryRename(IN_BSTR aSource, IN_BSTR aDest, ComSafeArrayIn(PathRenameFlag_T, aFlags))
1453{
1454#ifndef VBOX_WITH_GUEST_CONTROL
1455 ReturnComNotImplemented();
1456#else
1457 LogFlowThisFuncEnter();
1458
1459 AutoCaller autoCaller(this);
1460 if (FAILED(autoCaller.rc())) return autoCaller.rc();
1461
1462 ReturnComNotImplemented();
1463#endif /* VBOX_WITH_GUEST_CONTROL */
1464}
1465
1466STDMETHODIMP GuestSession::DirectorySetACL(IN_BSTR aPath, IN_BSTR aACL)
1467{
1468#ifndef VBOX_WITH_GUEST_CONTROL
1469 ReturnComNotImplemented();
1470#else
1471 LogFlowThisFuncEnter();
1472
1473 AutoCaller autoCaller(this);
1474 if (FAILED(autoCaller.rc())) return autoCaller.rc();
1475
1476 ReturnComNotImplemented();
1477#endif /* VBOX_WITH_GUEST_CONTROL */
1478}
1479
1480STDMETHODIMP GuestSession::EnvironmentClear(void)
1481{
1482#ifndef VBOX_WITH_GUEST_CONTROL
1483 ReturnComNotImplemented();
1484#else
1485 LogFlowThisFuncEnter();
1486
1487 AutoCaller autoCaller(this);
1488 if (FAILED(autoCaller.rc())) return autoCaller.rc();
1489
1490 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
1491
1492 mData.mEnvironment.Clear();
1493
1494 LogFlowFuncLeaveRC(S_OK);
1495 return S_OK;
1496#endif /* VBOX_WITH_GUEST_CONTROL */
1497}
1498
1499STDMETHODIMP GuestSession::EnvironmentGet(IN_BSTR aName, BSTR *aValue)
1500{
1501#ifndef VBOX_WITH_GUEST_CONTROL
1502 ReturnComNotImplemented();
1503#else
1504 LogFlowThisFuncEnter();
1505
1506 if (RT_UNLIKELY((aName) == NULL || *(aName) == '\0'))
1507 return setError(E_INVALIDARG, tr("No value name specified"));
1508
1509 CheckComArgOutPointerValid(aValue);
1510
1511 AutoCaller autoCaller(this);
1512 if (FAILED(autoCaller.rc())) return autoCaller.rc();
1513
1514 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
1515
1516 Bstr strValue(mData.mEnvironment.Get(Utf8Str(aName)));
1517 strValue.cloneTo(aValue);
1518
1519 LogFlowFuncLeaveRC(S_OK);
1520 return S_OK;
1521#endif /* VBOX_WITH_GUEST_CONTROL */
1522}
1523
1524STDMETHODIMP GuestSession::EnvironmentSet(IN_BSTR aName, IN_BSTR aValue)
1525{
1526#ifndef VBOX_WITH_GUEST_CONTROL
1527 ReturnComNotImplemented();
1528#else
1529 LogFlowThisFuncEnter();
1530
1531 if (RT_UNLIKELY((aName) == NULL || *(aName) == '\0'))
1532 return setError(E_INVALIDARG, tr("No value name specified"));
1533
1534 AutoCaller autoCaller(this);
1535 if (FAILED(autoCaller.rc())) return autoCaller.rc();
1536
1537 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
1538
1539 int rc = mData.mEnvironment.Set(Utf8Str(aName), Utf8Str(aValue));
1540
1541 HRESULT hr = RT_SUCCESS(rc) ? S_OK : VBOX_E_IPRT_ERROR;
1542 LogFlowFuncLeaveRC(hr);
1543 return hr;
1544#endif /* VBOX_WITH_GUEST_CONTROL */
1545}
1546
1547STDMETHODIMP GuestSession::EnvironmentUnset(IN_BSTR aName)
1548{
1549#ifndef VBOX_WITH_GUEST_CONTROL
1550 ReturnComNotImplemented();
1551#else
1552 LogFlowThisFuncEnter();
1553
1554 AutoCaller autoCaller(this);
1555 if (FAILED(autoCaller.rc())) return autoCaller.rc();
1556
1557 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
1558
1559 mData.mEnvironment.Unset(Utf8Str(aName));
1560
1561 LogFlowFuncLeaveRC(S_OK);
1562 return S_OK;
1563#endif /* VBOX_WITH_GUEST_CONTROL */
1564}
1565
1566STDMETHODIMP GuestSession::FileCreateTemp(IN_BSTR aTemplate, ULONG aMode, IN_BSTR aPath, BOOL aSecure, IGuestFile **aFile)
1567{
1568#ifndef VBOX_WITH_GUEST_CONTROL
1569 ReturnComNotImplemented();
1570#else
1571 LogFlowThisFuncEnter();
1572
1573 AutoCaller autoCaller(this);
1574 if (FAILED(autoCaller.rc())) return autoCaller.rc();
1575
1576 ReturnComNotImplemented();
1577#endif /* VBOX_WITH_GUEST_CONTROL */
1578}
1579
1580STDMETHODIMP GuestSession::FileExists(IN_BSTR aPath, BOOL *aExists)
1581{
1582#ifndef VBOX_WITH_GUEST_CONTROL
1583 ReturnComNotImplemented();
1584#else
1585 LogFlowThisFuncEnter();
1586
1587 if (RT_UNLIKELY((aPath) == NULL || *(aPath) == '\0'))
1588 return setError(E_INVALIDARG, tr("No file to check existence for specified"));
1589 CheckComArgOutPointerValid(aExists);
1590
1591 AutoCaller autoCaller(this);
1592 if (FAILED(autoCaller.rc())) return autoCaller.rc();
1593
1594 GuestFsObjData objData; int guestRc;
1595 int vrc = fileQueryInfoInternal(Utf8Str(aPath), objData, &guestRc);
1596 if (RT_SUCCESS(vrc))
1597 {
1598 *aExists = TRUE;
1599 return S_OK;
1600 }
1601
1602 HRESULT hr = S_OK;
1603
1604 switch (vrc)
1605 {
1606 case VERR_GENERAL_FAILURE: /** @todo Special guest control rc needed! */
1607 hr = GuestProcess::setErrorExternal(this, guestRc);
1608 break;
1609
1610 case VERR_NOT_A_FILE:
1611 *aExists = FALSE;
1612 break;
1613
1614 default:
1615 hr = setError(VBOX_E_IPRT_ERROR, tr("Querying file information for \"%s\" failed: %Rrc"),
1616 Utf8Str(aPath).c_str(), vrc);
1617 break;
1618 }
1619
1620 return hr;
1621#endif /* VBOX_WITH_GUEST_CONTROL */
1622}
1623
1624STDMETHODIMP GuestSession::FileRemove(IN_BSTR aPath)
1625{
1626#ifndef VBOX_WITH_GUEST_CONTROL
1627 ReturnComNotImplemented();
1628#else
1629 LogFlowThisFuncEnter();
1630
1631 if (RT_UNLIKELY((aPath) == NULL || *(aPath) == '\0'))
1632 return setError(E_INVALIDARG, tr("No file to remove specified"));
1633
1634 AutoCaller autoCaller(this);
1635 if (FAILED(autoCaller.rc())) return autoCaller.rc();
1636
1637 HRESULT hr = S_OK;
1638
1639 int guestRc;
1640 int vrc = fileRemoveInternal(Utf8Str(aPath), &guestRc);
1641 if (RT_FAILURE(vrc))
1642 {
1643 switch (vrc)
1644 {
1645 case VERR_GENERAL_FAILURE: /** @todo Special guest control rc needed! */
1646 hr = GuestProcess::setErrorExternal(this, guestRc);
1647 break;
1648
1649 default:
1650 hr = setError(VBOX_E_IPRT_ERROR, tr("Removing file \"%s\" failed: %Rrc"),
1651 Utf8Str(aPath).c_str(), vrc);
1652 break;
1653 }
1654 }
1655
1656 return hr;
1657#endif /* VBOX_WITH_GUEST_CONTROL */
1658}
1659
1660STDMETHODIMP GuestSession::FileOpen(IN_BSTR aPath, IN_BSTR aOpenMode, IN_BSTR aDisposition, ULONG aCreationMode, LONG64 aOffset, IGuestFile **aFile)
1661{
1662#ifndef VBOX_WITH_GUEST_CONTROL
1663 ReturnComNotImplemented();
1664#else
1665 LogFlowThisFuncEnter();
1666
1667 if (RT_UNLIKELY((aPath) == NULL || *(aPath) == '\0'))
1668 return setError(E_INVALIDARG, tr("No file to open specified"));
1669 if (RT_UNLIKELY((aOpenMode) == NULL || *(aOpenMode) == '\0'))
1670 return setError(E_INVALIDARG, tr("No open mode specified"));
1671 if (RT_UNLIKELY((aDisposition) == NULL || *(aDisposition) == '\0'))
1672 return setError(E_INVALIDARG, tr("No disposition mode specified"));
1673
1674 CheckComArgOutPointerValid(aFile);
1675
1676 AutoCaller autoCaller(this);
1677 if (FAILED(autoCaller.rc())) return autoCaller.rc();
1678
1679 /** @todo Validate open mode. */
1680 /** @todo Validate disposition mode. */
1681
1682 /** @todo Validate creation mode. */
1683 uint32_t uCreationMode = 0;
1684
1685 HRESULT hr = S_OK;
1686
1687 ComObjPtr <GuestFile> pFile; int guestRc;
1688 int vrc = fileOpenInternal(Utf8Str(aPath), Utf8Str(aOpenMode), Utf8Str(aDisposition),
1689 aCreationMode, aOffset, pFile, &guestRc);
1690 if (RT_SUCCESS(vrc))
1691 {
1692 /* Return directory object to the caller. */
1693 hr = pFile.queryInterfaceTo(aFile);
1694 }
1695 else
1696 {
1697 switch (vrc)
1698 {
1699 case VERR_GENERAL_FAILURE: /** @todo Special guest control rc needed! */
1700 hr = GuestProcess::setErrorExternal(this, guestRc);
1701 break;
1702
1703 default:
1704 hr = setError(VBOX_E_IPRT_ERROR, tr("Opening file \"%s\" failed: %Rrc"),
1705 Utf8Str(aPath).c_str(), vrc);
1706 break;
1707 }
1708 }
1709
1710 return hr;
1711#endif /* VBOX_WITH_GUEST_CONTROL */
1712}
1713
1714STDMETHODIMP GuestSession::FileQueryInfo(IN_BSTR aPath, IGuestFsObjInfo **aInfo)
1715{
1716#ifndef VBOX_WITH_GUEST_CONTROL
1717 ReturnComNotImplemented();
1718#else
1719 LogFlowThisFuncEnter();
1720
1721 if (RT_UNLIKELY((aPath) == NULL || *(aPath) == '\0'))
1722 return setError(E_INVALIDARG, tr("No file to query information for specified"));
1723 CheckComArgOutPointerValid(aInfo);
1724
1725 AutoCaller autoCaller(this);
1726 if (FAILED(autoCaller.rc())) return autoCaller.rc();
1727
1728 HRESULT hr = S_OK;
1729
1730 GuestFsObjData objData; int guestRc;
1731 int vrc = fileQueryInfoInternal(Utf8Str(aPath), objData, &guestRc);
1732 if (RT_SUCCESS(vrc))
1733 {
1734 ComObjPtr<GuestFsObjInfo> pFsObjInfo;
1735 hr = pFsObjInfo.createObject();
1736 if (FAILED(hr)) return hr;
1737
1738 vrc = pFsObjInfo->init(objData);
1739 if (RT_SUCCESS(vrc))
1740 {
1741 hr = pFsObjInfo.queryInterfaceTo(aInfo);
1742 if (FAILED(hr)) return hr;
1743 }
1744 }
1745
1746 if (RT_FAILURE(vrc))
1747 {
1748 switch (vrc)
1749 {
1750 case VERR_GENERAL_FAILURE: /** @todo Special guest control rc needed! */
1751 hr = GuestProcess::setErrorExternal(this, guestRc);
1752 break;
1753
1754 case VERR_NOT_A_FILE:
1755 hr = setError(VBOX_E_IPRT_ERROR, tr("Element exists but is not a file"));
1756 break;
1757
1758 default:
1759 hr = setError(VBOX_E_IPRT_ERROR, tr("Querying file information failed: %Rrc"), vrc);
1760 break;
1761 }
1762 }
1763
1764 return hr;
1765#endif /* VBOX_WITH_GUEST_CONTROL */
1766}
1767
1768STDMETHODIMP GuestSession::FileQuerySize(IN_BSTR aPath, LONG64 *aSize)
1769{
1770#ifndef VBOX_WITH_GUEST_CONTROL
1771 ReturnComNotImplemented();
1772#else
1773 LogFlowThisFuncEnter();
1774
1775 if (RT_UNLIKELY((aPath) == NULL || *(aPath) == '\0'))
1776 return setError(E_INVALIDARG, tr("No file to query size for specified"));
1777 CheckComArgOutPointerValid(aSize);
1778
1779 AutoCaller autoCaller(this);
1780 if (FAILED(autoCaller.rc())) return autoCaller.rc();
1781
1782 HRESULT hr = S_OK;
1783
1784 int64_t llSize; int guestRc;
1785 int vrc = fileQuerySizeInternal(Utf8Str(aPath), &llSize, &guestRc);
1786 if (RT_SUCCESS(vrc))
1787 {
1788 *aSize = llSize;
1789 }
1790 else
1791 {
1792 switch (vrc)
1793 {
1794 case VERR_GENERAL_FAILURE: /** @todo Special guest control rc needed! */
1795 hr = GuestProcess::setErrorExternal(this, guestRc);
1796 break;
1797
1798 default:
1799 hr = setError(VBOX_E_IPRT_ERROR, tr("Querying file size failed: %Rrc"), vrc);
1800 break;
1801 }
1802 }
1803
1804 return hr;
1805#endif /* VBOX_WITH_GUEST_CONTROL */
1806}
1807
1808STDMETHODIMP GuestSession::FileRename(IN_BSTR aSource, IN_BSTR aDest, ComSafeArrayIn(PathRenameFlag_T, aFlags))
1809{
1810#ifndef VBOX_WITH_GUEST_CONTROL
1811 ReturnComNotImplemented();
1812#else
1813 LogFlowThisFuncEnter();
1814
1815 AutoCaller autoCaller(this);
1816 if (FAILED(autoCaller.rc())) return autoCaller.rc();
1817
1818 ReturnComNotImplemented();
1819#endif /* VBOX_WITH_GUEST_CONTROL */
1820}
1821
1822STDMETHODIMP GuestSession::FileSetACL(IN_BSTR aPath, IN_BSTR aACL)
1823{
1824#ifndef VBOX_WITH_GUEST_CONTROL
1825 ReturnComNotImplemented();
1826#else
1827 LogFlowThisFuncEnter();
1828
1829 AutoCaller autoCaller(this);
1830 if (FAILED(autoCaller.rc())) return autoCaller.rc();
1831
1832 ReturnComNotImplemented();
1833#endif /* VBOX_WITH_GUEST_CONTROL */
1834}
1835
1836STDMETHODIMP GuestSession::ProcessCreate(IN_BSTR aCommand, ComSafeArrayIn(IN_BSTR, aArguments), ComSafeArrayIn(IN_BSTR, aEnvironment),
1837 ComSafeArrayIn(ProcessCreateFlag_T, aFlags), ULONG aTimeoutMS, IGuestProcess **aProcess)
1838{
1839#ifndef VBOX_WITH_GUEST_CONTROL
1840 ReturnComNotImplemented();
1841#else
1842 LogFlowThisFuncEnter();
1843
1844 com::SafeArray<LONG> affinity;
1845
1846 return ProcessCreateEx(aCommand, ComSafeArrayInArg(aArguments), ComSafeArrayInArg(aEnvironment),
1847 ComSafeArrayInArg(aFlags), aTimeoutMS, ProcessPriority_Default, ComSafeArrayAsInParam(affinity), aProcess);
1848#endif /* VBOX_WITH_GUEST_CONTROL */
1849}
1850
1851STDMETHODIMP GuestSession::ProcessCreateEx(IN_BSTR aCommand, ComSafeArrayIn(IN_BSTR, aArguments), ComSafeArrayIn(IN_BSTR, aEnvironment),
1852 ComSafeArrayIn(ProcessCreateFlag_T, aFlags), ULONG aTimeoutMS,
1853 ProcessPriority_T aPriority, ComSafeArrayIn(LONG, aAffinity),
1854 IGuestProcess **aProcess)
1855{
1856#ifndef VBOX_WITH_GUEST_CONTROL
1857 ReturnComNotImplemented();
1858#else
1859 LogFlowThisFuncEnter();
1860
1861 if (RT_UNLIKELY((aCommand) == NULL || *(aCommand) == '\0'))
1862 return setError(E_INVALIDARG, tr("No command to execute specified"));
1863 CheckComArgOutPointerValid(aProcess);
1864
1865 AutoCaller autoCaller(this);
1866 if (FAILED(autoCaller.rc())) return autoCaller.rc();
1867
1868 GuestProcessStartupInfo procInfo;
1869 procInfo.mCommand = Utf8Str(aCommand);
1870
1871 if (aArguments)
1872 {
1873 com::SafeArray<IN_BSTR> arguments(ComSafeArrayInArg(aArguments));
1874 for (size_t i = 0; i < arguments.size(); i++)
1875 procInfo.mArguments.push_back(Utf8Str(arguments[i]));
1876 }
1877
1878 int rc = VINF_SUCCESS;
1879
1880 /*
1881 * Create the process environment:
1882 * - Apply the session environment in a first step, and
1883 * - Apply environment variables specified by this call to
1884 * have the chance of overwriting/deleting session entries.
1885 */
1886 procInfo.mEnvironment = mData.mEnvironment; /* Apply original session environment. */
1887
1888 if (aEnvironment)
1889 {
1890 com::SafeArray<IN_BSTR> environment(ComSafeArrayInArg(aEnvironment));
1891 for (size_t i = 0; i < environment.size() && RT_SUCCESS(rc); i++)
1892 rc = procInfo.mEnvironment.Set(Utf8Str(environment[i]));
1893 }
1894
1895 HRESULT hr = S_OK;
1896
1897 if (RT_SUCCESS(rc))
1898 {
1899 if (aFlags)
1900 {
1901 com::SafeArray<ProcessCreateFlag_T> flags(ComSafeArrayInArg(aFlags));
1902 for (size_t i = 0; i < flags.size(); i++)
1903 procInfo.mFlags |= flags[i];
1904 }
1905
1906 procInfo.mTimeoutMS = aTimeoutMS;
1907
1908 if (aAffinity)
1909 {
1910 com::SafeArray<LONG> affinity(ComSafeArrayInArg(aAffinity));
1911 for (size_t i = 0; i < affinity.size(); i++)
1912 procInfo.mAffinity[i] = affinity[i]; /** @todo Really necessary? Later. */
1913 }
1914
1915 procInfo.mPriority = aPriority;
1916
1917 ComObjPtr<GuestProcess> pProcess;
1918 rc = processCreateExInteral(procInfo, pProcess);
1919 if (RT_SUCCESS(rc))
1920 {
1921 /* Return guest session to the caller. */
1922 HRESULT hr2 = pProcess.queryInterfaceTo(aProcess);
1923 if (FAILED(hr2))
1924 rc = VERR_COM_OBJECT_NOT_FOUND;
1925
1926 if (RT_SUCCESS(rc))
1927 rc = pProcess->startProcessAsync();
1928 }
1929 }
1930
1931 if (RT_FAILURE(rc))
1932 {
1933 switch (rc)
1934 {
1935 case VERR_MAX_PROCS_REACHED:
1936 hr = setError(VBOX_E_IPRT_ERROR, tr("Maximum number of guest objects per session (%ld) reached"),
1937 VBOX_GUESTCTRL_MAX_OBJECTS);
1938 break;
1939
1940 /** @todo Add more errors here. */
1941
1942 default:
1943 hr = setError(VBOX_E_IPRT_ERROR, tr("Could not create guest process, rc=%Rrc"), rc);
1944 break;
1945 }
1946 }
1947
1948 LogFlowFuncLeaveRC(rc);
1949 return hr;
1950#endif /* VBOX_WITH_GUEST_CONTROL */
1951}
1952
1953STDMETHODIMP GuestSession::ProcessGet(ULONG aPID, IGuestProcess **aProcess)
1954{
1955#ifndef VBOX_WITH_GUEST_CONTROL
1956 ReturnComNotImplemented();
1957#else
1958 LogFlowThisFunc(("aPID=%RU32\n", aPID));
1959
1960 CheckComArgOutPointerValid(aProcess);
1961 if (aPID == 0)
1962 return setError(E_INVALIDARG, tr("No valid process ID (PID) specified"));
1963
1964 AutoCaller autoCaller(this);
1965 if (FAILED(autoCaller.rc())) return autoCaller.rc();
1966
1967 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
1968
1969 HRESULT hr = S_OK;
1970
1971 ComObjPtr<GuestProcess> pProcess;
1972 int rc = processGetByPID(aPID, &pProcess);
1973 if (RT_FAILURE(rc))
1974 hr = setError(E_INVALIDARG, tr("No process with PID %RU32 found"), aPID);
1975
1976 /* This will set (*aProcess) to NULL if pProgress is NULL. */
1977 HRESULT hr2 = pProcess.queryInterfaceTo(aProcess);
1978 if (SUCCEEDED(hr))
1979 hr = hr2;
1980
1981 LogFlowThisFunc(("aProcess=%p, hr=%Rhrc\n", *aProcess, hr));
1982 return hr;
1983#endif /* VBOX_WITH_GUEST_CONTROL */
1984}
1985
1986STDMETHODIMP GuestSession::SymlinkCreate(IN_BSTR aSource, IN_BSTR aTarget, SymlinkType_T aType)
1987{
1988#ifndef VBOX_WITH_GUEST_CONTROL
1989 ReturnComNotImplemented();
1990#else
1991 LogFlowThisFuncEnter();
1992
1993 AutoCaller autoCaller(this);
1994 if (FAILED(autoCaller.rc())) return autoCaller.rc();
1995
1996 ReturnComNotImplemented();
1997#endif /* VBOX_WITH_GUEST_CONTROL */
1998}
1999
2000STDMETHODIMP GuestSession::SymlinkExists(IN_BSTR aSymlink, BOOL *aExists)
2001{
2002#ifndef VBOX_WITH_GUEST_CONTROL
2003 ReturnComNotImplemented();
2004#else
2005 LogFlowThisFuncEnter();
2006
2007 AutoCaller autoCaller(this);
2008 if (FAILED(autoCaller.rc())) return autoCaller.rc();
2009
2010 ReturnComNotImplemented();
2011#endif /* VBOX_WITH_GUEST_CONTROL */
2012}
2013
2014STDMETHODIMP GuestSession::SymlinkRead(IN_BSTR aSymlink, ComSafeArrayIn(SymlinkReadFlag_T, aFlags), BSTR *aTarget)
2015{
2016#ifndef VBOX_WITH_GUEST_CONTROL
2017 ReturnComNotImplemented();
2018#else
2019 LogFlowThisFuncEnter();
2020
2021 AutoCaller autoCaller(this);
2022 if (FAILED(autoCaller.rc())) return autoCaller.rc();
2023
2024 ReturnComNotImplemented();
2025#endif /* VBOX_WITH_GUEST_CONTROL */
2026}
2027
2028STDMETHODIMP GuestSession::SymlinkRemoveDirectory(IN_BSTR aPath)
2029{
2030#ifndef VBOX_WITH_GUEST_CONTROL
2031 ReturnComNotImplemented();
2032#else
2033 LogFlowThisFuncEnter();
2034
2035 AutoCaller autoCaller(this);
2036 if (FAILED(autoCaller.rc())) return autoCaller.rc();
2037
2038 ReturnComNotImplemented();
2039#endif /* VBOX_WITH_GUEST_CONTROL */
2040}
2041
2042STDMETHODIMP GuestSession::SymlinkRemoveFile(IN_BSTR aFile)
2043{
2044#ifndef VBOX_WITH_GUEST_CONTROL
2045 ReturnComNotImplemented();
2046#else
2047 LogFlowThisFuncEnter();
2048
2049 AutoCaller autoCaller(this);
2050 if (FAILED(autoCaller.rc())) return autoCaller.rc();
2051
2052 ReturnComNotImplemented();
2053#endif /* VBOX_WITH_GUEST_CONTROL */
2054}
2055
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