VirtualBox

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

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

Guest Control: Respect detached processes.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 60.3 KB
Line 
1
2/* $Id: GuestSessionImpl.cpp 43981 2012-11-28 11:44:04Z 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 if ( (procInfo.mFlags & ProcessCreateFlag_WaitForProcessStartOnly)
853 && ( (procInfo.mFlags & ProcessCreateFlag_WaitForStdOut)
854 || (procInfo.mFlags & ProcessCreateFlag_WaitForStdErr)
855 )
856 )
857 {
858 return VERR_INVALID_PARAMETER;
859 }
860
861 /* Adjust timeout. If set to 0, we define
862 * an infinite timeout. */
863 if (procInfo.mTimeoutMS == 0)
864 procInfo.mTimeoutMS = UINT32_MAX;
865
866 /** @tood Implement process priority + affinity. */
867
868 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
869
870 int rc = VERR_MAX_PROCS_REACHED;
871 if (mData.mNumObjects >= VBOX_GUESTCTRL_MAX_OBJECTS)
872 return rc;
873
874 /* Create a new (host-based) process ID and assign it. */
875 uint32_t uNewProcessID = 0;
876 ULONG uTries = 0;
877
878 for (;;)
879 {
880 /* Is the context ID already used? */
881 if (!processExists(uNewProcessID, NULL /* pProgress */))
882 {
883 /* Callback with context ID was not found. This means
884 * we can use this context ID for our new callback we want
885 * to add below. */
886 rc = VINF_SUCCESS;
887 break;
888 }
889 uNewProcessID++;
890 if (uNewProcessID == VBOX_GUESTCTRL_MAX_OBJECTS)
891 uNewProcessID = 0;
892
893 if (++uTries == UINT32_MAX)
894 break; /* Don't try too hard. */
895 }
896
897 if (RT_FAILURE(rc))
898 return rc;
899
900 /* Create the process object. */
901 HRESULT hr = pProcess.createObject();
902 if (FAILED(hr))
903 return VERR_COM_UNEXPECTED;
904
905 rc = pProcess->init(mData.mParent->getConsole() /* Console */, this /* Session */,
906 uNewProcessID, procInfo);
907 if (RT_FAILURE(rc))
908 return rc;
909
910 /* Add the created process to our map. */
911 mData.mProcesses[uNewProcessID] = pProcess;
912 mData.mNumObjects++;
913 Assert(mData.mNumObjects <= VBOX_GUESTCTRL_MAX_OBJECTS);
914
915 LogFlowFunc(("Added new process (Session: %RU32) with process ID=%RU32 (now total %ld processes, %ld objects)\n",
916 mData.mId, uNewProcessID, mData.mProcesses.size(), mData.mNumObjects));
917
918 return rc;
919}
920
921inline bool GuestSession::processExists(uint32_t uProcessID, ComObjPtr<GuestProcess> *pProcess)
922{
923 SessionProcesses::const_iterator it = mData.mProcesses.find(uProcessID);
924 if (it != mData.mProcesses.end())
925 {
926 if (pProcess)
927 *pProcess = it->second;
928 return true;
929 }
930 return false;
931}
932
933inline int GuestSession::processGetByPID(ULONG uPID, ComObjPtr<GuestProcess> *pProcess)
934{
935 AssertReturn(uPID, false);
936 /* pProcess is optional. */
937
938 SessionProcesses::iterator itProcs = mData.mProcesses.begin();
939 for (; itProcs != mData.mProcesses.end(); itProcs++)
940 {
941 ComObjPtr<GuestProcess> pCurProc = itProcs->second;
942 AutoCaller procCaller(pCurProc);
943 if (procCaller.rc())
944 return VERR_COM_INVALID_OBJECT_STATE;
945
946 ULONG uCurPID;
947 HRESULT hr = pCurProc->COMGETTER(PID)(&uCurPID);
948 ComAssertComRC(hr);
949
950 if (uCurPID == uPID)
951 {
952 if (pProcess)
953 *pProcess = pCurProc;
954 return VINF_SUCCESS;
955 }
956 }
957
958 return VERR_NOT_FOUND;
959}
960
961int GuestSession::startTaskAsync(const Utf8Str &strTaskDesc,
962 GuestSessionTask *pTask, ComObjPtr<Progress> &pProgress)
963{
964 LogFlowThisFunc(("strTaskDesc=%s, pTask=%p\n", strTaskDesc.c_str(), pTask));
965
966 AssertPtrReturn(pTask, VERR_INVALID_POINTER);
967
968 /* Create the progress object. */
969 HRESULT hr = pProgress.createObject();
970 if (FAILED(hr))
971 return VERR_COM_UNEXPECTED;
972
973 hr = pProgress->init(static_cast<IGuestSession*>(this),
974 Bstr(strTaskDesc).raw(),
975 TRUE /* aCancelable */);
976 if (FAILED(hr))
977 return VERR_COM_UNEXPECTED;
978
979 /* Initialize our worker task. */
980 std::auto_ptr<GuestSessionTask> task(pTask);
981
982 int rc = task->RunAsync(strTaskDesc, pProgress);
983 if (RT_FAILURE(rc))
984 return rc;
985
986 /* Don't destruct on success. */
987 task.release();
988
989 LogFlowFuncLeaveRC(rc);
990 return rc;
991}
992
993/**
994 * Queries/collects information prior to establishing a guest session.
995 * This is necessary to know which guest control protocol version to use,
996 * among other things (later).
997 *
998 * @return IPRT status code.
999 */
1000int GuestSession::queryInfo(void)
1001{
1002#if 1
1003 /* Since the new functions were not implemented yet, force Main to use protocol ver 1. */
1004 mData.mProtocolVersion = 1;
1005#else
1006 /*
1007 * Try querying the guest control protocol version running on the guest.
1008 * This is done using the Guest Additions version
1009 */
1010 ComObjPtr<Guest> pGuest = mData.mParent;
1011 Assert(!pGuest.isNull());
1012
1013 uint32_t uVerAdditions = pGuest->getAdditionsVersion();
1014 mData.mProtocolVersion = ( VBOX_FULL_VERSION_GET_MAJOR(uVerAdditions) >= 4
1015 && VBOX_FULL_VERSION_GET_MINOR(uVerAdditions) >= 2) /** @todo What's about v5.0 ? */
1016 ? 2 /* Guest control 2.0. */
1017 : 1; /* Legacy guest control (VBox < 4.2). */
1018 /* Build revision is ignored. */
1019
1020 /* Tell the user but don't bitch too often. */
1021 static short s_gctrlLegacyWarning = 0;
1022 if (s_gctrlLegacyWarning++ < 3) /** @todo Find a bit nicer text. */
1023 LogRel((tr("Warning: Guest Additions are older (%ld.%ld) than host capabilities for guest control, please upgrade them. Using protocol version %ld now\n"),
1024 VBOX_FULL_VERSION_GET_MAJOR(uVerAdditions), VBOX_FULL_VERSION_GET_MINOR(uVerAdditions), mData.mProtocolVersion));
1025#endif
1026 return VINF_SUCCESS;
1027}
1028
1029// implementation of public methods
1030/////////////////////////////////////////////////////////////////////////////
1031
1032STDMETHODIMP GuestSession::Close(void)
1033{
1034#ifndef VBOX_WITH_GUEST_CONTROL
1035 ReturnComNotImplemented();
1036#else
1037 LogFlowThisFuncEnter();
1038
1039 AutoCaller autoCaller(this);
1040 if (FAILED(autoCaller.rc())) return autoCaller.rc();
1041
1042 /* Remove ourselves from the session list. */
1043 mData.mParent->sessionRemove(this);
1044
1045 /*
1046 * Release autocaller before calling uninit.
1047 */
1048 autoCaller.release();
1049
1050 uninit();
1051
1052 LogFlowFuncLeave();
1053 return S_OK;
1054#endif /* VBOX_WITH_GUEST_CONTROL */
1055}
1056
1057STDMETHODIMP GuestSession::CopyFrom(IN_BSTR aSource, IN_BSTR aDest, ComSafeArrayIn(CopyFileFlag_T, aFlags), IProgress **aProgress)
1058{
1059#ifndef VBOX_WITH_GUEST_CONTROL
1060 ReturnComNotImplemented();
1061#else
1062 CheckComArgStrNotEmptyOrNull(aSource);
1063 CheckComArgStrNotEmptyOrNull(aDest);
1064 CheckComArgOutPointerValid(aProgress);
1065
1066 LogFlowThisFuncEnter();
1067
1068 if (RT_UNLIKELY((aSource) == NULL || *(aSource) == '\0'))
1069 return setError(E_INVALIDARG, tr("No source specified"));
1070 if (RT_UNLIKELY((aDest) == NULL || *(aDest) == '\0'))
1071 return setError(E_INVALIDARG, tr("No destination specified"));
1072
1073 AutoCaller autoCaller(this);
1074 if (FAILED(autoCaller.rc())) return autoCaller.rc();
1075
1076 uint32_t fFlags = CopyFileFlag_None;
1077 if (aFlags)
1078 {
1079 com::SafeArray<CopyFileFlag_T> flags(ComSafeArrayInArg(aFlags));
1080 for (size_t i = 0; i < flags.size(); i++)
1081 fFlags |= flags[i];
1082 }
1083
1084 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
1085
1086 HRESULT hr = S_OK;
1087
1088 try
1089 {
1090 ComObjPtr<Progress> pProgress;
1091 SessionTaskCopyFrom *pTask = new SessionTaskCopyFrom(this /* GuestSession */,
1092 Utf8Str(aSource), Utf8Str(aDest), fFlags);
1093 int rc = startTaskAsync(Utf8StrFmt(tr("Copying \"%ls\" from guest to \"%ls\" on the host"), aSource, aDest),
1094 pTask, pProgress);
1095 if (RT_SUCCESS(rc))
1096 {
1097 /* Return progress to the caller. */
1098 hr = pProgress.queryInterfaceTo(aProgress);
1099 }
1100 else
1101 hr = setError(VBOX_E_IPRT_ERROR,
1102 tr("Starting task for copying file \"%ls\" from guest to \"%ls\" on the host failed: %Rrc"), rc);
1103 }
1104 catch(std::bad_alloc &)
1105 {
1106 hr = E_OUTOFMEMORY;
1107 }
1108
1109 return hr;
1110#endif /* VBOX_WITH_GUEST_CONTROL */
1111}
1112
1113STDMETHODIMP GuestSession::CopyTo(IN_BSTR aSource, IN_BSTR aDest, ComSafeArrayIn(CopyFileFlag_T, aFlags), IProgress **aProgress)
1114{
1115#ifndef VBOX_WITH_GUEST_CONTROL
1116 ReturnComNotImplemented();
1117#else
1118 CheckComArgStrNotEmptyOrNull(aSource);
1119 CheckComArgStrNotEmptyOrNull(aDest);
1120 CheckComArgOutPointerValid(aProgress);
1121
1122 LogFlowThisFuncEnter();
1123
1124 if (RT_UNLIKELY((aSource) == NULL || *(aSource) == '\0'))
1125 return setError(E_INVALIDARG, tr("No source specified"));
1126 if (RT_UNLIKELY((aDest) == NULL || *(aDest) == '\0'))
1127 return setError(E_INVALIDARG, tr("No destination specified"));
1128
1129 AutoCaller autoCaller(this);
1130 if (FAILED(autoCaller.rc())) return autoCaller.rc();
1131
1132 uint32_t fFlags = CopyFileFlag_None;
1133 if (aFlags)
1134 {
1135 com::SafeArray<CopyFileFlag_T> flags(ComSafeArrayInArg(aFlags));
1136 for (size_t i = 0; i < flags.size(); i++)
1137 fFlags |= flags[i];
1138 }
1139
1140 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
1141
1142 HRESULT hr = S_OK;
1143
1144 try
1145 {
1146 ComObjPtr<Progress> pProgress;
1147 SessionTaskCopyTo *pTask = new SessionTaskCopyTo(this /* GuestSession */,
1148 Utf8Str(aSource), Utf8Str(aDest), fFlags);
1149 AssertPtrReturn(pTask, E_OUTOFMEMORY);
1150 int rc = startTaskAsync(Utf8StrFmt(tr("Copying \"%ls\" from host to \"%ls\" on the guest"), aSource, aDest),
1151 pTask, pProgress);
1152 if (RT_SUCCESS(rc))
1153 {
1154 /* Return progress to the caller. */
1155 hr = pProgress.queryInterfaceTo(aProgress);
1156 }
1157 else
1158 hr = setError(VBOX_E_IPRT_ERROR,
1159 tr("Starting task for copying file \"%ls\" from host to \"%ls\" on the guest failed: %Rrc"), rc);
1160 }
1161 catch(std::bad_alloc &)
1162 {
1163 hr = E_OUTOFMEMORY;
1164 }
1165
1166 return hr;
1167#endif /* VBOX_WITH_GUEST_CONTROL */
1168}
1169
1170STDMETHODIMP GuestSession::DirectoryCreate(IN_BSTR aPath, ULONG aMode,
1171 ComSafeArrayIn(DirectoryCreateFlag_T, aFlags))
1172{
1173#ifndef VBOX_WITH_GUEST_CONTROL
1174 ReturnComNotImplemented();
1175#else
1176 LogFlowThisFuncEnter();
1177
1178 if (RT_UNLIKELY((aPath) == NULL || *(aPath) == '\0'))
1179 return setError(E_INVALIDARG, tr("No directory to create specified"));
1180
1181 AutoCaller autoCaller(this);
1182 if (FAILED(autoCaller.rc())) return autoCaller.rc();
1183
1184 uint32_t fFlags = DirectoryCreateFlag_None;
1185 if (aFlags)
1186 {
1187 com::SafeArray<DirectoryCreateFlag_T> flags(ComSafeArrayInArg(aFlags));
1188 for (size_t i = 0; i < flags.size(); i++)
1189 fFlags |= flags[i];
1190
1191 if (fFlags)
1192 {
1193 if (!(fFlags & DirectoryCreateFlag_Parents))
1194 return setError(E_INVALIDARG, tr("Unknown flags (%#x)"), fFlags);
1195 }
1196 }
1197
1198 HRESULT hr = S_OK;
1199
1200 ComObjPtr <GuestDirectory> pDirectory; int guestRc;
1201 int rc = directoryCreateInternal(Utf8Str(aPath), (uint32_t)aMode, fFlags, &guestRc);
1202 if (RT_FAILURE(rc))
1203 {
1204 switch (rc)
1205 {
1206 case VERR_GENERAL_FAILURE: /** @todo Special guest control rc needed! */
1207 hr = GuestProcess::setErrorExternal(this, guestRc);
1208 break;
1209
1210 case VERR_INVALID_PARAMETER:
1211 hr = setError(VBOX_E_IPRT_ERROR, tr("Directory creation failed: Invalid parameters given"));
1212 break;
1213
1214 case VERR_BROKEN_PIPE:
1215 hr = setError(VBOX_E_IPRT_ERROR, tr("Directory creation failed: Unexpectedly aborted"));
1216 break;
1217
1218 case VERR_CANT_CREATE:
1219 hr = setError(VBOX_E_IPRT_ERROR, tr("Directory creation failed: Could not create directory"));
1220 break;
1221
1222 default:
1223 hr = setError(VBOX_E_IPRT_ERROR, tr("Directory creation failed: %Rrc"), rc);
1224 break;
1225 }
1226 }
1227
1228 return hr;
1229#endif /* VBOX_WITH_GUEST_CONTROL */
1230}
1231
1232STDMETHODIMP GuestSession::DirectoryCreateTemp(IN_BSTR aTemplate, ULONG aMode, IN_BSTR aPath, BOOL aSecure, BSTR *aDirectory)
1233{
1234#ifndef VBOX_WITH_GUEST_CONTROL
1235 ReturnComNotImplemented();
1236#else
1237 LogFlowThisFuncEnter();
1238
1239 if (RT_UNLIKELY((aTemplate) == NULL || *(aTemplate) == '\0'))
1240 return setError(E_INVALIDARG, tr("No template specified"));
1241 if (RT_UNLIKELY((aPath) == NULL || *(aPath) == '\0'))
1242 return setError(E_INVALIDARG, tr("No directory name specified"));
1243 CheckComArgOutPointerValid(aDirectory);
1244
1245 AutoCaller autoCaller(this);
1246 if (FAILED(autoCaller.rc())) return autoCaller.rc();
1247
1248 HRESULT hr = S_OK;
1249
1250 Utf8Str strName; int guestRc;
1251 int rc = objectCreateTempInternal(Utf8Str(aTemplate),
1252 Utf8Str(aPath),
1253 true /* Directory */, strName, &guestRc);
1254 if (RT_SUCCESS(rc))
1255 {
1256 strName.cloneTo(aDirectory);
1257 }
1258 else
1259 {
1260 switch (rc)
1261 {
1262 case VERR_GENERAL_FAILURE: /** @todo Special guest control rc needed! */
1263 hr = GuestProcess::setErrorExternal(this, guestRc);
1264 break;
1265
1266 default:
1267 hr = setError(VBOX_E_IPRT_ERROR, tr("Temporary directory creation \"%s\" with template \"%s\" failed: %Rrc"),
1268 Utf8Str(aPath).c_str(), Utf8Str(aTemplate).c_str(), rc);
1269 break;
1270 }
1271 }
1272
1273 return hr;
1274#endif /* VBOX_WITH_GUEST_CONTROL */
1275}
1276
1277STDMETHODIMP GuestSession::DirectoryExists(IN_BSTR aPath, BOOL *aExists)
1278{
1279#ifndef VBOX_WITH_GUEST_CONTROL
1280 ReturnComNotImplemented();
1281#else
1282 LogFlowThisFuncEnter();
1283
1284 if (RT_UNLIKELY((aPath) == NULL || *(aPath) == '\0'))
1285 return setError(E_INVALIDARG, tr("No directory to check existence for specified"));
1286 CheckComArgOutPointerValid(aExists);
1287
1288 AutoCaller autoCaller(this);
1289 if (FAILED(autoCaller.rc())) return autoCaller.rc();
1290
1291 HRESULT hr = S_OK;
1292
1293 GuestFsObjData objData; int guestRc;
1294 int rc = directoryQueryInfoInternal(Utf8Str(aPath), objData, &guestRc);
1295 if (RT_SUCCESS(rc))
1296 {
1297 *aExists = objData.mType == FsObjType_Directory;
1298 }
1299 else
1300 {
1301 switch (rc)
1302 {
1303 case VERR_GENERAL_FAILURE: /** @todo Special guest control rc needed! */
1304 hr = GuestProcess::setErrorExternal(this, guestRc);
1305 break;
1306
1307 default:
1308 hr = setError(VBOX_E_IPRT_ERROR, tr("Querying directory existence \"%s\" failed: %Rrc"),
1309 Utf8Str(aPath).c_str(), rc);
1310 break;
1311 }
1312 }
1313
1314 return hr;
1315#endif /* VBOX_WITH_GUEST_CONTROL */
1316}
1317
1318STDMETHODIMP GuestSession::DirectoryOpen(IN_BSTR aPath, IN_BSTR aFilter, ComSafeArrayIn(DirectoryOpenFlag_T, aFlags), IGuestDirectory **aDirectory)
1319{
1320#ifndef VBOX_WITH_GUEST_CONTROL
1321 ReturnComNotImplemented();
1322#else
1323 LogFlowThisFuncEnter();
1324
1325 if (RT_UNLIKELY((aPath) == NULL || *(aPath) == '\0'))
1326 return setError(E_INVALIDARG, tr("No directory to open specified"));
1327 if (RT_UNLIKELY((aFilter) != NULL && *(aFilter) != '\0'))
1328 return setError(E_INVALIDARG, tr("Directory filters are not implemented yet"));
1329 CheckComArgOutPointerValid(aDirectory);
1330
1331 AutoCaller autoCaller(this);
1332 if (FAILED(autoCaller.rc())) return autoCaller.rc();
1333
1334 uint32_t fFlags = DirectoryOpenFlag_None;
1335 if (aFlags)
1336 {
1337 com::SafeArray<DirectoryOpenFlag_T> flags(ComSafeArrayInArg(aFlags));
1338 for (size_t i = 0; i < flags.size(); i++)
1339 fFlags |= flags[i];
1340
1341 if (fFlags)
1342 return setError(E_INVALIDARG, tr("Open flags (%#x) not implemented yet"), fFlags);
1343 }
1344
1345 HRESULT hr = S_OK;
1346
1347 ComObjPtr <GuestDirectory> pDirectory;
1348 int rc = directoryOpenInternal(Utf8Str(aPath), Utf8Str(aFilter), fFlags, pDirectory);
1349 if (RT_SUCCESS(rc))
1350 {
1351 /* Return directory object to the caller. */
1352 hr = pDirectory.queryInterfaceTo(aDirectory);
1353 }
1354 else
1355 {
1356 switch (rc)
1357 {
1358 case VERR_INVALID_PARAMETER:
1359 hr = setError(VBOX_E_IPRT_ERROR, tr("Opening directory \"%s\" failed; invalid parameters given",
1360 Utf8Str(aPath).c_str()));
1361 break;
1362
1363 default:
1364 hr = setError(VBOX_E_IPRT_ERROR, tr("Opening directory \"%s\" failed: %Rrc"),
1365 Utf8Str(aPath).c_str(),rc);
1366 break;
1367 }
1368 }
1369
1370 return hr;
1371#endif /* VBOX_WITH_GUEST_CONTROL */
1372}
1373
1374STDMETHODIMP GuestSession::DirectoryQueryInfo(IN_BSTR aPath, IGuestFsObjInfo **aInfo)
1375{
1376#ifndef VBOX_WITH_GUEST_CONTROL
1377 ReturnComNotImplemented();
1378#else
1379 LogFlowThisFuncEnter();
1380
1381 if (RT_UNLIKELY((aPath) == NULL || *(aPath) == '\0'))
1382 return setError(E_INVALIDARG, tr("No directory to query information for specified"));
1383 CheckComArgOutPointerValid(aInfo);
1384
1385 AutoCaller autoCaller(this);
1386 if (FAILED(autoCaller.rc())) return autoCaller.rc();
1387
1388 HRESULT hr = S_OK;
1389
1390 GuestFsObjData objData; int guestRc;
1391 int vrc = directoryQueryInfoInternal(Utf8Str(aPath), objData, &guestRc);
1392 if (RT_SUCCESS(vrc))
1393 {
1394 if (objData.mType == FsObjType_Directory)
1395 {
1396 ComObjPtr<GuestFsObjInfo> pFsObjInfo;
1397 hr = pFsObjInfo.createObject();
1398 if (FAILED(hr)) return hr;
1399
1400 vrc = pFsObjInfo->init(objData);
1401 if (RT_SUCCESS(vrc))
1402 {
1403 hr = pFsObjInfo.queryInterfaceTo(aInfo);
1404 if (FAILED(hr)) return hr;
1405 }
1406 }
1407 }
1408
1409 if (RT_FAILURE(vrc))
1410 {
1411 switch (vrc)
1412 {
1413 case VERR_GENERAL_FAILURE: /** @todo Special guest control rc needed! */
1414 hr = GuestProcess::setErrorExternal(this, guestRc);
1415 break;
1416
1417 case VERR_NOT_A_DIRECTORY:
1418 hr = setError(VBOX_E_IPRT_ERROR, tr("Element \"%s\" exists but is not a directory",
1419 Utf8Str(aPath).c_str()));
1420 break;
1421
1422 default:
1423 hr = setError(VBOX_E_IPRT_ERROR, tr("Querying directory information for \"%s\" failed: %Rrc"),
1424 Utf8Str(aPath).c_str(), vrc);
1425 break;
1426 }
1427 }
1428
1429 return hr;
1430#endif /* VBOX_WITH_GUEST_CONTROL */
1431}
1432
1433STDMETHODIMP GuestSession::DirectoryRemove(IN_BSTR aPath)
1434{
1435#ifndef VBOX_WITH_GUEST_CONTROL
1436 ReturnComNotImplemented();
1437#else
1438 LogFlowThisFuncEnter();
1439
1440 AutoCaller autoCaller(this);
1441 if (FAILED(autoCaller.rc())) return autoCaller.rc();
1442
1443 ReturnComNotImplemented();
1444#endif /* VBOX_WITH_GUEST_CONTROL */
1445}
1446
1447STDMETHODIMP GuestSession::DirectoryRemoveRecursive(IN_BSTR aPath, ComSafeArrayIn(DirectoryRemoveRecFlag_T, aFlags), IProgress **aProgress)
1448{
1449#ifndef VBOX_WITH_GUEST_CONTROL
1450 ReturnComNotImplemented();
1451#else
1452 LogFlowThisFuncEnter();
1453
1454 AutoCaller autoCaller(this);
1455 if (FAILED(autoCaller.rc())) return autoCaller.rc();
1456
1457 ReturnComNotImplemented();
1458#endif /* VBOX_WITH_GUEST_CONTROL */
1459}
1460
1461STDMETHODIMP GuestSession::DirectoryRename(IN_BSTR aSource, IN_BSTR aDest, ComSafeArrayIn(PathRenameFlag_T, aFlags))
1462{
1463#ifndef VBOX_WITH_GUEST_CONTROL
1464 ReturnComNotImplemented();
1465#else
1466 LogFlowThisFuncEnter();
1467
1468 AutoCaller autoCaller(this);
1469 if (FAILED(autoCaller.rc())) return autoCaller.rc();
1470
1471 ReturnComNotImplemented();
1472#endif /* VBOX_WITH_GUEST_CONTROL */
1473}
1474
1475STDMETHODIMP GuestSession::DirectorySetACL(IN_BSTR aPath, IN_BSTR aACL)
1476{
1477#ifndef VBOX_WITH_GUEST_CONTROL
1478 ReturnComNotImplemented();
1479#else
1480 LogFlowThisFuncEnter();
1481
1482 AutoCaller autoCaller(this);
1483 if (FAILED(autoCaller.rc())) return autoCaller.rc();
1484
1485 ReturnComNotImplemented();
1486#endif /* VBOX_WITH_GUEST_CONTROL */
1487}
1488
1489STDMETHODIMP GuestSession::EnvironmentClear(void)
1490{
1491#ifndef VBOX_WITH_GUEST_CONTROL
1492 ReturnComNotImplemented();
1493#else
1494 LogFlowThisFuncEnter();
1495
1496 AutoCaller autoCaller(this);
1497 if (FAILED(autoCaller.rc())) return autoCaller.rc();
1498
1499 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
1500
1501 mData.mEnvironment.Clear();
1502
1503 LogFlowFuncLeaveRC(S_OK);
1504 return S_OK;
1505#endif /* VBOX_WITH_GUEST_CONTROL */
1506}
1507
1508STDMETHODIMP GuestSession::EnvironmentGet(IN_BSTR aName, BSTR *aValue)
1509{
1510#ifndef VBOX_WITH_GUEST_CONTROL
1511 ReturnComNotImplemented();
1512#else
1513 LogFlowThisFuncEnter();
1514
1515 if (RT_UNLIKELY((aName) == NULL || *(aName) == '\0'))
1516 return setError(E_INVALIDARG, tr("No value name specified"));
1517
1518 CheckComArgOutPointerValid(aValue);
1519
1520 AutoCaller autoCaller(this);
1521 if (FAILED(autoCaller.rc())) return autoCaller.rc();
1522
1523 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
1524
1525 Bstr strValue(mData.mEnvironment.Get(Utf8Str(aName)));
1526 strValue.cloneTo(aValue);
1527
1528 LogFlowFuncLeaveRC(S_OK);
1529 return S_OK;
1530#endif /* VBOX_WITH_GUEST_CONTROL */
1531}
1532
1533STDMETHODIMP GuestSession::EnvironmentSet(IN_BSTR aName, IN_BSTR aValue)
1534{
1535#ifndef VBOX_WITH_GUEST_CONTROL
1536 ReturnComNotImplemented();
1537#else
1538 LogFlowThisFuncEnter();
1539
1540 if (RT_UNLIKELY((aName) == NULL || *(aName) == '\0'))
1541 return setError(E_INVALIDARG, tr("No value name specified"));
1542
1543 AutoCaller autoCaller(this);
1544 if (FAILED(autoCaller.rc())) return autoCaller.rc();
1545
1546 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
1547
1548 int rc = mData.mEnvironment.Set(Utf8Str(aName), Utf8Str(aValue));
1549
1550 HRESULT hr = RT_SUCCESS(rc) ? S_OK : VBOX_E_IPRT_ERROR;
1551 LogFlowFuncLeaveRC(hr);
1552 return hr;
1553#endif /* VBOX_WITH_GUEST_CONTROL */
1554}
1555
1556STDMETHODIMP GuestSession::EnvironmentUnset(IN_BSTR aName)
1557{
1558#ifndef VBOX_WITH_GUEST_CONTROL
1559 ReturnComNotImplemented();
1560#else
1561 LogFlowThisFuncEnter();
1562
1563 AutoCaller autoCaller(this);
1564 if (FAILED(autoCaller.rc())) return autoCaller.rc();
1565
1566 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
1567
1568 mData.mEnvironment.Unset(Utf8Str(aName));
1569
1570 LogFlowFuncLeaveRC(S_OK);
1571 return S_OK;
1572#endif /* VBOX_WITH_GUEST_CONTROL */
1573}
1574
1575STDMETHODIMP GuestSession::FileCreateTemp(IN_BSTR aTemplate, ULONG aMode, IN_BSTR aPath, BOOL aSecure, IGuestFile **aFile)
1576{
1577#ifndef VBOX_WITH_GUEST_CONTROL
1578 ReturnComNotImplemented();
1579#else
1580 LogFlowThisFuncEnter();
1581
1582 AutoCaller autoCaller(this);
1583 if (FAILED(autoCaller.rc())) return autoCaller.rc();
1584
1585 ReturnComNotImplemented();
1586#endif /* VBOX_WITH_GUEST_CONTROL */
1587}
1588
1589STDMETHODIMP GuestSession::FileExists(IN_BSTR aPath, BOOL *aExists)
1590{
1591#ifndef VBOX_WITH_GUEST_CONTROL
1592 ReturnComNotImplemented();
1593#else
1594 LogFlowThisFuncEnter();
1595
1596 if (RT_UNLIKELY((aPath) == NULL || *(aPath) == '\0'))
1597 return setError(E_INVALIDARG, tr("No file to check existence for specified"));
1598 CheckComArgOutPointerValid(aExists);
1599
1600 AutoCaller autoCaller(this);
1601 if (FAILED(autoCaller.rc())) return autoCaller.rc();
1602
1603 GuestFsObjData objData; int guestRc;
1604 int vrc = fileQueryInfoInternal(Utf8Str(aPath), objData, &guestRc);
1605 if (RT_SUCCESS(vrc))
1606 {
1607 *aExists = TRUE;
1608 return S_OK;
1609 }
1610
1611 HRESULT hr = S_OK;
1612
1613 switch (vrc)
1614 {
1615 case VERR_GENERAL_FAILURE: /** @todo Special guest control rc needed! */
1616 hr = GuestProcess::setErrorExternal(this, guestRc);
1617 break;
1618
1619 case VERR_NOT_A_FILE:
1620 *aExists = FALSE;
1621 break;
1622
1623 default:
1624 hr = setError(VBOX_E_IPRT_ERROR, tr("Querying file information for \"%s\" failed: %Rrc"),
1625 Utf8Str(aPath).c_str(), vrc);
1626 break;
1627 }
1628
1629 return hr;
1630#endif /* VBOX_WITH_GUEST_CONTROL */
1631}
1632
1633STDMETHODIMP GuestSession::FileRemove(IN_BSTR aPath)
1634{
1635#ifndef VBOX_WITH_GUEST_CONTROL
1636 ReturnComNotImplemented();
1637#else
1638 LogFlowThisFuncEnter();
1639
1640 if (RT_UNLIKELY((aPath) == NULL || *(aPath) == '\0'))
1641 return setError(E_INVALIDARG, tr("No file to remove specified"));
1642
1643 AutoCaller autoCaller(this);
1644 if (FAILED(autoCaller.rc())) return autoCaller.rc();
1645
1646 HRESULT hr = S_OK;
1647
1648 int guestRc;
1649 int vrc = fileRemoveInternal(Utf8Str(aPath), &guestRc);
1650 if (RT_FAILURE(vrc))
1651 {
1652 switch (vrc)
1653 {
1654 case VERR_GENERAL_FAILURE: /** @todo Special guest control rc needed! */
1655 hr = GuestProcess::setErrorExternal(this, guestRc);
1656 break;
1657
1658 default:
1659 hr = setError(VBOX_E_IPRT_ERROR, tr("Removing file \"%s\" failed: %Rrc"),
1660 Utf8Str(aPath).c_str(), vrc);
1661 break;
1662 }
1663 }
1664
1665 return hr;
1666#endif /* VBOX_WITH_GUEST_CONTROL */
1667}
1668
1669STDMETHODIMP GuestSession::FileOpen(IN_BSTR aPath, IN_BSTR aOpenMode, IN_BSTR aDisposition, ULONG aCreationMode, LONG64 aOffset, IGuestFile **aFile)
1670{
1671#ifndef VBOX_WITH_GUEST_CONTROL
1672 ReturnComNotImplemented();
1673#else
1674 LogFlowThisFuncEnter();
1675
1676 if (RT_UNLIKELY((aPath) == NULL || *(aPath) == '\0'))
1677 return setError(E_INVALIDARG, tr("No file to open specified"));
1678 if (RT_UNLIKELY((aOpenMode) == NULL || *(aOpenMode) == '\0'))
1679 return setError(E_INVALIDARG, tr("No open mode specified"));
1680 if (RT_UNLIKELY((aDisposition) == NULL || *(aDisposition) == '\0'))
1681 return setError(E_INVALIDARG, tr("No disposition mode specified"));
1682
1683 CheckComArgOutPointerValid(aFile);
1684
1685 AutoCaller autoCaller(this);
1686 if (FAILED(autoCaller.rc())) return autoCaller.rc();
1687
1688 /** @todo Validate open mode. */
1689 /** @todo Validate disposition mode. */
1690
1691 /** @todo Validate creation mode. */
1692 uint32_t uCreationMode = 0;
1693
1694 HRESULT hr = S_OK;
1695
1696 ComObjPtr <GuestFile> pFile; int guestRc;
1697 int vrc = fileOpenInternal(Utf8Str(aPath), Utf8Str(aOpenMode), Utf8Str(aDisposition),
1698 aCreationMode, aOffset, pFile, &guestRc);
1699 if (RT_SUCCESS(vrc))
1700 {
1701 /* Return directory object to the caller. */
1702 hr = pFile.queryInterfaceTo(aFile);
1703 }
1704 else
1705 {
1706 switch (vrc)
1707 {
1708 case VERR_GENERAL_FAILURE: /** @todo Special guest control rc needed! */
1709 hr = GuestProcess::setErrorExternal(this, guestRc);
1710 break;
1711
1712 default:
1713 hr = setError(VBOX_E_IPRT_ERROR, tr("Opening file \"%s\" failed: %Rrc"),
1714 Utf8Str(aPath).c_str(), vrc);
1715 break;
1716 }
1717 }
1718
1719 return hr;
1720#endif /* VBOX_WITH_GUEST_CONTROL */
1721}
1722
1723STDMETHODIMP GuestSession::FileQueryInfo(IN_BSTR aPath, IGuestFsObjInfo **aInfo)
1724{
1725#ifndef VBOX_WITH_GUEST_CONTROL
1726 ReturnComNotImplemented();
1727#else
1728 LogFlowThisFuncEnter();
1729
1730 if (RT_UNLIKELY((aPath) == NULL || *(aPath) == '\0'))
1731 return setError(E_INVALIDARG, tr("No file to query information for specified"));
1732 CheckComArgOutPointerValid(aInfo);
1733
1734 AutoCaller autoCaller(this);
1735 if (FAILED(autoCaller.rc())) return autoCaller.rc();
1736
1737 HRESULT hr = S_OK;
1738
1739 GuestFsObjData objData; int guestRc;
1740 int vrc = fileQueryInfoInternal(Utf8Str(aPath), objData, &guestRc);
1741 if (RT_SUCCESS(vrc))
1742 {
1743 ComObjPtr<GuestFsObjInfo> pFsObjInfo;
1744 hr = pFsObjInfo.createObject();
1745 if (FAILED(hr)) return hr;
1746
1747 vrc = pFsObjInfo->init(objData);
1748 if (RT_SUCCESS(vrc))
1749 {
1750 hr = pFsObjInfo.queryInterfaceTo(aInfo);
1751 if (FAILED(hr)) return hr;
1752 }
1753 }
1754
1755 if (RT_FAILURE(vrc))
1756 {
1757 switch (vrc)
1758 {
1759 case VERR_GENERAL_FAILURE: /** @todo Special guest control rc needed! */
1760 hr = GuestProcess::setErrorExternal(this, guestRc);
1761 break;
1762
1763 case VERR_NOT_A_FILE:
1764 hr = setError(VBOX_E_IPRT_ERROR, tr("Element exists but is not a file"));
1765 break;
1766
1767 default:
1768 hr = setError(VBOX_E_IPRT_ERROR, tr("Querying file information failed: %Rrc"), vrc);
1769 break;
1770 }
1771 }
1772
1773 return hr;
1774#endif /* VBOX_WITH_GUEST_CONTROL */
1775}
1776
1777STDMETHODIMP GuestSession::FileQuerySize(IN_BSTR aPath, LONG64 *aSize)
1778{
1779#ifndef VBOX_WITH_GUEST_CONTROL
1780 ReturnComNotImplemented();
1781#else
1782 LogFlowThisFuncEnter();
1783
1784 if (RT_UNLIKELY((aPath) == NULL || *(aPath) == '\0'))
1785 return setError(E_INVALIDARG, tr("No file to query size for specified"));
1786 CheckComArgOutPointerValid(aSize);
1787
1788 AutoCaller autoCaller(this);
1789 if (FAILED(autoCaller.rc())) return autoCaller.rc();
1790
1791 HRESULT hr = S_OK;
1792
1793 int64_t llSize; int guestRc;
1794 int vrc = fileQuerySizeInternal(Utf8Str(aPath), &llSize, &guestRc);
1795 if (RT_SUCCESS(vrc))
1796 {
1797 *aSize = llSize;
1798 }
1799 else
1800 {
1801 switch (vrc)
1802 {
1803 case VERR_GENERAL_FAILURE: /** @todo Special guest control rc needed! */
1804 hr = GuestProcess::setErrorExternal(this, guestRc);
1805 break;
1806
1807 default:
1808 hr = setError(VBOX_E_IPRT_ERROR, tr("Querying file size failed: %Rrc"), vrc);
1809 break;
1810 }
1811 }
1812
1813 return hr;
1814#endif /* VBOX_WITH_GUEST_CONTROL */
1815}
1816
1817STDMETHODIMP GuestSession::FileRename(IN_BSTR aSource, IN_BSTR aDest, ComSafeArrayIn(PathRenameFlag_T, aFlags))
1818{
1819#ifndef VBOX_WITH_GUEST_CONTROL
1820 ReturnComNotImplemented();
1821#else
1822 LogFlowThisFuncEnter();
1823
1824 AutoCaller autoCaller(this);
1825 if (FAILED(autoCaller.rc())) return autoCaller.rc();
1826
1827 ReturnComNotImplemented();
1828#endif /* VBOX_WITH_GUEST_CONTROL */
1829}
1830
1831STDMETHODIMP GuestSession::FileSetACL(IN_BSTR aPath, IN_BSTR aACL)
1832{
1833#ifndef VBOX_WITH_GUEST_CONTROL
1834 ReturnComNotImplemented();
1835#else
1836 LogFlowThisFuncEnter();
1837
1838 AutoCaller autoCaller(this);
1839 if (FAILED(autoCaller.rc())) return autoCaller.rc();
1840
1841 ReturnComNotImplemented();
1842#endif /* VBOX_WITH_GUEST_CONTROL */
1843}
1844
1845STDMETHODIMP GuestSession::ProcessCreate(IN_BSTR aCommand, ComSafeArrayIn(IN_BSTR, aArguments), ComSafeArrayIn(IN_BSTR, aEnvironment),
1846 ComSafeArrayIn(ProcessCreateFlag_T, aFlags), ULONG aTimeoutMS, IGuestProcess **aProcess)
1847{
1848#ifndef VBOX_WITH_GUEST_CONTROL
1849 ReturnComNotImplemented();
1850#else
1851 LogFlowThisFuncEnter();
1852
1853 com::SafeArray<LONG> affinity;
1854
1855 return ProcessCreateEx(aCommand, ComSafeArrayInArg(aArguments), ComSafeArrayInArg(aEnvironment),
1856 ComSafeArrayInArg(aFlags), aTimeoutMS, ProcessPriority_Default, ComSafeArrayAsInParam(affinity), aProcess);
1857#endif /* VBOX_WITH_GUEST_CONTROL */
1858}
1859
1860STDMETHODIMP GuestSession::ProcessCreateEx(IN_BSTR aCommand, ComSafeArrayIn(IN_BSTR, aArguments), ComSafeArrayIn(IN_BSTR, aEnvironment),
1861 ComSafeArrayIn(ProcessCreateFlag_T, aFlags), ULONG aTimeoutMS,
1862 ProcessPriority_T aPriority, ComSafeArrayIn(LONG, aAffinity),
1863 IGuestProcess **aProcess)
1864{
1865#ifndef VBOX_WITH_GUEST_CONTROL
1866 ReturnComNotImplemented();
1867#else
1868 LogFlowThisFuncEnter();
1869
1870 if (RT_UNLIKELY((aCommand) == NULL || *(aCommand) == '\0'))
1871 return setError(E_INVALIDARG, tr("No command to execute specified"));
1872 CheckComArgOutPointerValid(aProcess);
1873
1874 AutoCaller autoCaller(this);
1875 if (FAILED(autoCaller.rc())) return autoCaller.rc();
1876
1877 GuestProcessStartupInfo procInfo;
1878 procInfo.mCommand = Utf8Str(aCommand);
1879
1880 if (aArguments)
1881 {
1882 com::SafeArray<IN_BSTR> arguments(ComSafeArrayInArg(aArguments));
1883 for (size_t i = 0; i < arguments.size(); i++)
1884 procInfo.mArguments.push_back(Utf8Str(arguments[i]));
1885 }
1886
1887 int rc = VINF_SUCCESS;
1888
1889 /*
1890 * Create the process environment:
1891 * - Apply the session environment in a first step, and
1892 * - Apply environment variables specified by this call to
1893 * have the chance of overwriting/deleting session entries.
1894 */
1895 procInfo.mEnvironment = mData.mEnvironment; /* Apply original session environment. */
1896
1897 if (aEnvironment)
1898 {
1899 com::SafeArray<IN_BSTR> environment(ComSafeArrayInArg(aEnvironment));
1900 for (size_t i = 0; i < environment.size() && RT_SUCCESS(rc); i++)
1901 rc = procInfo.mEnvironment.Set(Utf8Str(environment[i]));
1902 }
1903
1904 HRESULT hr = S_OK;
1905
1906 if (RT_SUCCESS(rc))
1907 {
1908 if (aFlags)
1909 {
1910 com::SafeArray<ProcessCreateFlag_T> flags(ComSafeArrayInArg(aFlags));
1911 for (size_t i = 0; i < flags.size(); i++)
1912 procInfo.mFlags |= flags[i];
1913 }
1914
1915 procInfo.mTimeoutMS = aTimeoutMS;
1916
1917 if (aAffinity)
1918 {
1919 com::SafeArray<LONG> affinity(ComSafeArrayInArg(aAffinity));
1920 for (size_t i = 0; i < affinity.size(); i++)
1921 procInfo.mAffinity[i] = affinity[i]; /** @todo Really necessary? Later. */
1922 }
1923
1924 procInfo.mPriority = aPriority;
1925
1926 ComObjPtr<GuestProcess> pProcess;
1927 rc = processCreateExInteral(procInfo, pProcess);
1928 if (RT_SUCCESS(rc))
1929 {
1930 /* Return guest session to the caller. */
1931 HRESULT hr2 = pProcess.queryInterfaceTo(aProcess);
1932 if (FAILED(hr2))
1933 rc = VERR_COM_OBJECT_NOT_FOUND;
1934
1935 if (RT_SUCCESS(rc))
1936 rc = pProcess->startProcessAsync();
1937 }
1938 }
1939
1940 if (RT_FAILURE(rc))
1941 {
1942 switch (rc)
1943 {
1944 case VERR_MAX_PROCS_REACHED:
1945 hr = setError(VBOX_E_IPRT_ERROR, tr("Maximum number of guest objects per session (%ld) reached"),
1946 VBOX_GUESTCTRL_MAX_OBJECTS);
1947 break;
1948
1949 /** @todo Add more errors here. */
1950
1951 default:
1952 hr = setError(VBOX_E_IPRT_ERROR, tr("Could not create guest process, rc=%Rrc"), rc);
1953 break;
1954 }
1955 }
1956
1957 LogFlowFuncLeaveRC(rc);
1958 return hr;
1959#endif /* VBOX_WITH_GUEST_CONTROL */
1960}
1961
1962STDMETHODIMP GuestSession::ProcessGet(ULONG aPID, IGuestProcess **aProcess)
1963{
1964#ifndef VBOX_WITH_GUEST_CONTROL
1965 ReturnComNotImplemented();
1966#else
1967 LogFlowThisFunc(("aPID=%RU32\n", aPID));
1968
1969 CheckComArgOutPointerValid(aProcess);
1970 if (aPID == 0)
1971 return setError(E_INVALIDARG, tr("No valid process ID (PID) specified"));
1972
1973 AutoCaller autoCaller(this);
1974 if (FAILED(autoCaller.rc())) return autoCaller.rc();
1975
1976 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
1977
1978 HRESULT hr = S_OK;
1979
1980 ComObjPtr<GuestProcess> pProcess;
1981 int rc = processGetByPID(aPID, &pProcess);
1982 if (RT_FAILURE(rc))
1983 hr = setError(E_INVALIDARG, tr("No process with PID %RU32 found"), aPID);
1984
1985 /* This will set (*aProcess) to NULL if pProgress is NULL. */
1986 HRESULT hr2 = pProcess.queryInterfaceTo(aProcess);
1987 if (SUCCEEDED(hr))
1988 hr = hr2;
1989
1990 LogFlowThisFunc(("aProcess=%p, hr=%Rhrc\n", *aProcess, hr));
1991 return hr;
1992#endif /* VBOX_WITH_GUEST_CONTROL */
1993}
1994
1995STDMETHODIMP GuestSession::SymlinkCreate(IN_BSTR aSource, IN_BSTR aTarget, SymlinkType_T aType)
1996{
1997#ifndef VBOX_WITH_GUEST_CONTROL
1998 ReturnComNotImplemented();
1999#else
2000 LogFlowThisFuncEnter();
2001
2002 AutoCaller autoCaller(this);
2003 if (FAILED(autoCaller.rc())) return autoCaller.rc();
2004
2005 ReturnComNotImplemented();
2006#endif /* VBOX_WITH_GUEST_CONTROL */
2007}
2008
2009STDMETHODIMP GuestSession::SymlinkExists(IN_BSTR aSymlink, BOOL *aExists)
2010{
2011#ifndef VBOX_WITH_GUEST_CONTROL
2012 ReturnComNotImplemented();
2013#else
2014 LogFlowThisFuncEnter();
2015
2016 AutoCaller autoCaller(this);
2017 if (FAILED(autoCaller.rc())) return autoCaller.rc();
2018
2019 ReturnComNotImplemented();
2020#endif /* VBOX_WITH_GUEST_CONTROL */
2021}
2022
2023STDMETHODIMP GuestSession::SymlinkRead(IN_BSTR aSymlink, ComSafeArrayIn(SymlinkReadFlag_T, aFlags), BSTR *aTarget)
2024{
2025#ifndef VBOX_WITH_GUEST_CONTROL
2026 ReturnComNotImplemented();
2027#else
2028 LogFlowThisFuncEnter();
2029
2030 AutoCaller autoCaller(this);
2031 if (FAILED(autoCaller.rc())) return autoCaller.rc();
2032
2033 ReturnComNotImplemented();
2034#endif /* VBOX_WITH_GUEST_CONTROL */
2035}
2036
2037STDMETHODIMP GuestSession::SymlinkRemoveDirectory(IN_BSTR aPath)
2038{
2039#ifndef VBOX_WITH_GUEST_CONTROL
2040 ReturnComNotImplemented();
2041#else
2042 LogFlowThisFuncEnter();
2043
2044 AutoCaller autoCaller(this);
2045 if (FAILED(autoCaller.rc())) return autoCaller.rc();
2046
2047 ReturnComNotImplemented();
2048#endif /* VBOX_WITH_GUEST_CONTROL */
2049}
2050
2051STDMETHODIMP GuestSession::SymlinkRemoveFile(IN_BSTR aFile)
2052{
2053#ifndef VBOX_WITH_GUEST_CONTROL
2054 ReturnComNotImplemented();
2055#else
2056 LogFlowThisFuncEnter();
2057
2058 AutoCaller autoCaller(this);
2059 if (FAILED(autoCaller.rc())) return autoCaller.rc();
2060
2061 ReturnComNotImplemented();
2062#endif /* VBOX_WITH_GUEST_CONTROL */
2063}
2064
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