VirtualBox

source: vbox/trunk/src/VBox/Main/GuestImpl.cpp@ 28286

Last change on this file since 28286 was 28286, checked in by vboxsync, 15 years ago

Guest Control: Update (introducing contexts for callbacks).

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 24.2 KB
Line 
1/* $Id: GuestImpl.cpp 28286 2010-04-14 10:02:30Z vboxsync $ */
2
3/** @file
4 *
5 * VirtualBox COM class implementation
6 */
7
8/*
9 * Copyright (C) 2006-2008 Sun Microsystems, Inc.
10 *
11 * This file is part of VirtualBox Open Source Edition (OSE), as
12 * available from http://www.virtualbox.org. This file is free software;
13 * you can redistribute it and/or modify it under the terms of the GNU
14 * General Public License (GPL) as published by the Free Software
15 * Foundation, in version 2 as it comes in the "COPYING" file of the
16 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
17 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
18 *
19 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
20 * Clara, CA 95054 USA or visit http://www.sun.com if you need
21 * additional information or have any questions.
22 */
23
24#include "GuestImpl.h"
25
26#include "Global.h"
27#include "ConsoleImpl.h"
28#include "ProgressImpl.h"
29#include "VMMDev.h"
30
31#include "AutoCaller.h"
32#include "Logging.h"
33
34#include <VBox/VMMDev.h>
35#ifdef VBOX_WITH_GUEST_CONTROL
36# include <VBox/com/array.h>
37#endif
38#include <iprt/cpp/utils.h>
39#include <iprt/getopt.h>
40#include <VBox/pgm.h>
41
42// defines
43/////////////////////////////////////////////////////////////////////////////
44
45// constructor / destructor
46/////////////////////////////////////////////////////////////////////////////
47
48DEFINE_EMPTY_CTOR_DTOR (Guest)
49
50HRESULT Guest::FinalConstruct()
51{
52 return S_OK;
53}
54
55void Guest::FinalRelease()
56{
57 uninit ();
58}
59
60// public methods only for internal purposes
61/////////////////////////////////////////////////////////////////////////////
62
63/**
64 * Initializes the guest object.
65 */
66HRESULT Guest::init (Console *aParent)
67{
68 LogFlowThisFunc(("aParent=%p\n", aParent));
69
70 ComAssertRet(aParent, E_INVALIDARG);
71
72 /* Enclose the state transition NotReady->InInit->Ready */
73 AutoInitSpan autoInitSpan(this);
74 AssertReturn(autoInitSpan.isOk(), E_FAIL);
75
76 unconst(mParent) = aParent;
77
78 /* mData.mAdditionsActive is FALSE */
79
80 /* Confirm a successful initialization when it's the case */
81 autoInitSpan.setSucceeded();
82
83 ULONG aMemoryBalloonSize;
84 HRESULT ret = mParent->machine()->COMGETTER(MemoryBalloonSize)(&aMemoryBalloonSize);
85 if (ret == S_OK)
86 mMemoryBalloonSize = aMemoryBalloonSize;
87 else
88 mMemoryBalloonSize = 0; /* Default is no ballooning */
89
90 mStatUpdateInterval = 0; /* Default is not to report guest statistics at all */
91
92 /* Clear statistics. */
93 for (unsigned i = 0 ; i < GUESTSTATTYPE_MAX; i++)
94 mCurrentGuestStat[i] = 0;
95
96 /* Init the context ID counter at 1000. */
97 mNextContextID = 1000;
98
99 return S_OK;
100}
101
102/**
103 * Uninitializes the instance and sets the ready flag to FALSE.
104 * Called either from FinalRelease() or by the parent when it gets destroyed.
105 */
106void Guest::uninit()
107{
108 LogFlowThisFunc(("\n"));
109
110 /* Enclose the state transition Ready->InUninit->NotReady */
111 AutoUninitSpan autoUninitSpan(this);
112 if (autoUninitSpan.uninitDone())
113 return;
114
115 unconst(mParent) = NULL;
116}
117
118// IGuest properties
119/////////////////////////////////////////////////////////////////////////////
120
121STDMETHODIMP Guest::COMGETTER(OSTypeId) (BSTR *aOSTypeId)
122{
123 CheckComArgOutPointerValid(aOSTypeId);
124
125 AutoCaller autoCaller(this);
126 if (FAILED(autoCaller.rc())) return autoCaller.rc();
127
128 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
129
130 // redirect the call to IMachine if no additions are installed
131 if (mData.mAdditionsVersion.isEmpty())
132 return mParent->machine()->COMGETTER(OSTypeId)(aOSTypeId);
133
134 mData.mOSTypeId.cloneTo(aOSTypeId);
135
136 return S_OK;
137}
138
139STDMETHODIMP Guest::COMGETTER(AdditionsActive) (BOOL *aAdditionsActive)
140{
141 CheckComArgOutPointerValid(aAdditionsActive);
142
143 AutoCaller autoCaller(this);
144 if (FAILED(autoCaller.rc())) return autoCaller.rc();
145
146 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
147
148 *aAdditionsActive = mData.mAdditionsActive;
149
150 return S_OK;
151}
152
153STDMETHODIMP Guest::COMGETTER(AdditionsVersion) (BSTR *aAdditionsVersion)
154{
155 CheckComArgOutPointerValid(aAdditionsVersion);
156
157 AutoCaller autoCaller(this);
158 if (FAILED(autoCaller.rc())) return autoCaller.rc();
159
160 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
161
162 mData.mAdditionsVersion.cloneTo(aAdditionsVersion);
163
164 return S_OK;
165}
166
167STDMETHODIMP Guest::COMGETTER(SupportsSeamless) (BOOL *aSupportsSeamless)
168{
169 CheckComArgOutPointerValid(aSupportsSeamless);
170
171 AutoCaller autoCaller(this);
172 if (FAILED(autoCaller.rc())) return autoCaller.rc();
173
174 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
175
176 *aSupportsSeamless = mData.mSupportsSeamless;
177
178 return S_OK;
179}
180
181STDMETHODIMP Guest::COMGETTER(SupportsGraphics) (BOOL *aSupportsGraphics)
182{
183 CheckComArgOutPointerValid(aSupportsGraphics);
184
185 AutoCaller autoCaller(this);
186 if (FAILED(autoCaller.rc())) return autoCaller.rc();
187
188 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
189
190 *aSupportsGraphics = mData.mSupportsGraphics;
191
192 return S_OK;
193}
194
195STDMETHODIMP Guest::COMGETTER(MemoryBalloonSize) (ULONG *aMemoryBalloonSize)
196{
197 CheckComArgOutPointerValid(aMemoryBalloonSize);
198
199 AutoCaller autoCaller(this);
200 if (FAILED(autoCaller.rc())) return autoCaller.rc();
201
202 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
203
204 *aMemoryBalloonSize = mMemoryBalloonSize;
205
206 return S_OK;
207}
208
209STDMETHODIMP Guest::COMSETTER(MemoryBalloonSize) (ULONG aMemoryBalloonSize)
210{
211 AutoCaller autoCaller(this);
212 if (FAILED(autoCaller.rc())) return autoCaller.rc();
213
214 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
215
216 HRESULT ret = mParent->machine()->COMSETTER(MemoryBalloonSize)(aMemoryBalloonSize);
217 if (ret == S_OK)
218 {
219 mMemoryBalloonSize = aMemoryBalloonSize;
220 /* forward the information to the VMM device */
221 VMMDev *vmmDev = mParent->getVMMDev();
222 if (vmmDev)
223 vmmDev->getVMMDevPort()->pfnSetMemoryBalloon(vmmDev->getVMMDevPort(), aMemoryBalloonSize);
224 }
225
226 return ret;
227}
228
229STDMETHODIMP Guest::COMGETTER(StatisticsUpdateInterval)(ULONG *aUpdateInterval)
230{
231 CheckComArgOutPointerValid(aUpdateInterval);
232
233 AutoCaller autoCaller(this);
234 if (FAILED(autoCaller.rc())) return autoCaller.rc();
235
236 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
237
238 *aUpdateInterval = mStatUpdateInterval;
239 return S_OK;
240}
241
242STDMETHODIMP Guest::COMSETTER(StatisticsUpdateInterval)(ULONG aUpdateInterval)
243{
244 AutoCaller autoCaller(this);
245 if (FAILED(autoCaller.rc())) return autoCaller.rc();
246
247 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
248
249 mStatUpdateInterval = aUpdateInterval;
250 /* forward the information to the VMM device */
251 VMMDev *vmmDev = mParent->getVMMDev();
252 if (vmmDev)
253 vmmDev->getVMMDevPort()->pfnSetStatisticsInterval(vmmDev->getVMMDevPort(), aUpdateInterval);
254
255 return S_OK;
256}
257
258STDMETHODIMP Guest::InternalGetStatistics(ULONG *aCpuUser, ULONG *aCpuKernel, ULONG *aCpuIdle,
259 ULONG *aMemTotal, ULONG *aMemFree, ULONG *aMemBalloon,
260 ULONG *aMemCache, ULONG *aPageTotal,
261 ULONG *aMemAllocTotal, ULONG *aMemFreeTotal, ULONG *aMemBalloonTotal)
262{
263 CheckComArgOutPointerValid(aCpuUser);
264 CheckComArgOutPointerValid(aCpuKernel);
265 CheckComArgOutPointerValid(aCpuIdle);
266 CheckComArgOutPointerValid(aMemTotal);
267 CheckComArgOutPointerValid(aMemFree);
268 CheckComArgOutPointerValid(aMemBalloon);
269 CheckComArgOutPointerValid(aMemCache);
270 CheckComArgOutPointerValid(aPageTotal);
271
272 AutoCaller autoCaller(this);
273 if (FAILED(autoCaller.rc())) return autoCaller.rc();
274
275 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
276
277 *aCpuUser = mCurrentGuestStat[GUESTSTATTYPE_CPUUSER] * (_4K/_1K); /* page (4K) -> 1 KB units */
278 *aCpuKernel = mCurrentGuestStat[GUESTSTATTYPE_CPUKERNEL] * (_4K/_1K);
279 *aCpuIdle = mCurrentGuestStat[GUESTSTATTYPE_CPUIDLE] * (_4K/_1K);
280 *aMemTotal = mCurrentGuestStat[GUESTSTATTYPE_MEMTOTAL] * (_4K/_1K);
281 *aMemFree = mCurrentGuestStat[GUESTSTATTYPE_MEMFREE] * (_4K/_1K);
282 *aMemBalloon = mCurrentGuestStat[GUESTSTATTYPE_MEMBALLOON] * (_4K/_1K);
283 *aMemCache = mCurrentGuestStat[GUESTSTATTYPE_MEMCACHE] * (_4K/_1K);
284 *aPageTotal = mCurrentGuestStat[GUESTSTATTYPE_PAGETOTAL] * (_4K/_1K);
285
286 Console::SafeVMPtr pVM (mParent);
287 if (pVM.isOk())
288 {
289 uint64_t uFreeTotal, uAllocTotal, uBalloonedTotal;
290 *aMemFreeTotal = 0;
291 int rc = PGMR3QueryVMMMemoryStats(pVM.raw(), &uAllocTotal, &uFreeTotal, &uBalloonedTotal);
292 AssertRC(rc);
293 if (rc == VINF_SUCCESS)
294 {
295 *aMemAllocTotal = (ULONG)(uAllocTotal / _1K); /* bytes -> KB */
296 *aMemFreeTotal = (ULONG)(uFreeTotal / _1K);
297 *aMemBalloonTotal = (ULONG)(uBalloonedTotal / _1K);
298 }
299 }
300 else
301 *aMemFreeTotal = 0;
302
303 return S_OK;
304}
305
306HRESULT Guest::SetStatistic(ULONG aCpuId, GUESTSTATTYPE enmType, ULONG aVal)
307{
308 AutoCaller autoCaller(this);
309 if (FAILED(autoCaller.rc())) return autoCaller.rc();
310
311 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
312
313 if (enmType >= GUESTSTATTYPE_MAX)
314 return E_INVALIDARG;
315
316 mCurrentGuestStat[enmType] = aVal;
317 return S_OK;
318}
319
320STDMETHODIMP Guest::SetCredentials(IN_BSTR aUserName, IN_BSTR aPassword,
321 IN_BSTR aDomain, BOOL aAllowInteractiveLogon)
322{
323 AutoCaller autoCaller(this);
324 if (FAILED(autoCaller.rc())) return autoCaller.rc();
325
326 /* forward the information to the VMM device */
327 VMMDev *vmmDev = mParent->getVMMDev();
328 if (vmmDev)
329 {
330 uint32_t u32Flags = VMMDEV_SETCREDENTIALS_GUESTLOGON;
331 if (!aAllowInteractiveLogon)
332 u32Flags = VMMDEV_SETCREDENTIALS_NOLOCALLOGON;
333
334 vmmDev->getVMMDevPort()->pfnSetCredentials(vmmDev->getVMMDevPort(),
335 Utf8Str(aUserName).raw(), Utf8Str(aPassword).raw(),
336 Utf8Str(aDomain).raw(), u32Flags);
337 return S_OK;
338 }
339
340 return setError(VBOX_E_VM_ERROR,
341 tr("VMM device is not available (is the VM running?)"));
342}
343
344#ifdef VBOX_WITH_GUEST_CONTROL
345/**
346 * Creates the argument list as an array used for executing a program.
347 *
348 * @returns VBox status code.
349 *
350 * @todo
351 *
352 * @todo Respect spaces when quoting for arguments, e.g. "c:\\program files\\".
353 * @todo Handle empty ("") argguments.
354 */
355int Guest::prepareExecuteArgs(const char *pszArgs, void **ppvList, uint32_t *pcbList, uint32_t *pcArgs)
356{
357 char **ppaArg;
358 int iArgs;
359 int rc = RTGetOptArgvFromString(&ppaArg, &iArgs, pszArgs, NULL);
360 if (RT_SUCCESS(rc))
361 {
362 char *pszTemp = NULL;
363 *pcbList = 0;
364 for (int i=0; i<iArgs; i++)
365 {
366 if (i > 0) /* Insert space as delimiter. */
367 rc = RTStrAAppendN(&pszTemp, " ", 1);
368
369 if (RT_FAILURE(rc))
370 break;
371 else
372 {
373 rc = RTStrAAppendN(&pszTemp, ppaArg[i], strlen(ppaArg[i]));
374 if (RT_FAILURE(rc))
375 break;
376 }
377 }
378 RTGetOptArgvFree(ppaArg);
379 if (RT_SUCCESS(rc))
380 {
381 *ppvList = pszTemp;
382 *pcArgs = iArgs;
383 if (pszTemp)
384 *pcbList = strlen(pszTemp) + 1; /* Include zero termination. */
385 }
386 else
387 RTStrFree(pszTemp);
388 }
389 return rc;
390}
391
392/**
393 * Appends environment variables to the environment block. Each var=value pair is separated
394 * by NULL (\0) sequence. The whole block will be stored in one blob and disassembled on the
395 * guest side later to fit into the HGCM param structure.
396 *
397 * @returns VBox status code.
398 *
399 * @todo
400 *
401 */
402int Guest::prepareExecuteEnv(const char *pszEnv, void **ppvList, uint32_t *pcbList, uint32_t *pcEnv)
403{
404 int rc = VINF_SUCCESS;
405 uint32_t cbLen = strlen(pszEnv);
406 if (*ppvList)
407 {
408 uint32_t cbNewLen = *pcbList + cbLen + 1; /* Include zero termination. */
409 char *pvTmp = (char*)RTMemRealloc(*ppvList, cbNewLen);
410 if (NULL == pvTmp)
411 {
412 rc = VERR_NO_MEMORY;
413 }
414 else
415 {
416 memcpy(pvTmp + *pcbList, pszEnv, cbLen);
417 pvTmp[cbNewLen - 1] = '\0'; /* Add zero termination. */
418 *ppvList = (void**)pvTmp;
419 }
420 }
421 else
422 {
423 char *pcTmp;
424 if (RTStrAPrintf(&pcTmp, "%s", pszEnv) > 0)
425 {
426 *ppvList = (void**)pcTmp;
427 /* Reset counters. */
428 *pcEnv = 0;
429 *pcbList = 0;
430 }
431 }
432 if (RT_SUCCESS(rc))
433 {
434 *pcbList += cbLen + 1; /* Include zero termination. */
435 *pcEnv += 1; /* Increase env pairs count. */
436 }
437 return rc;
438}
439
440/**
441 * Static callback function for receiving updates on guest control commands
442 * from the guest. Acts as a dispatcher for the actual class instance.
443 *
444 * @returns VBox status code.
445 *
446 * @todo
447 *
448 */
449DECLCALLBACK(int) Guest::doGuestCtrlNotification(void *pvExtension,
450 uint32_t u32Function,
451 void *pvParms,
452 uint32_t cbParms)
453{
454 using namespace guestControl;
455
456 /*
457 * No locking, as this is purely a notification which does not make any
458 * changes to the object state.
459 */
460 LogFlowFunc(("pvExtension = %p, u32Function = %d, pvParms = %p, cbParms = %d\n",
461 pvExtension, u32Function, pvParms, cbParms));
462 ComObjPtr<Guest> pGuest = reinterpret_cast<Guest *>(pvExtension);
463
464 int rc = VINF_SUCCESS;
465 if (u32Function == GUEST_EXEC_SEND_STATUS)
466 {
467 LogFlowFunc(("GUEST_EXEC_SEND_STATUS\n"));
468
469 PHOSTEXECCALLBACKDATA pCBData = reinterpret_cast<PHOSTEXECCALLBACKDATA>(pvParms);
470 AssertPtr(pCBData);
471 AssertReturn(sizeof(HOSTEXECCALLBACKDATA) == cbParms, VERR_INVALID_PARAMETER);
472 AssertReturn(HOSTEXECCALLBACKDATAMAGIC == pCBData->hdr.u32Magic, VERR_INVALID_PARAMETER);
473
474 rc = pGuest->notifyCtrlExec(u32Function, pCBData);
475 }
476 else
477 rc = VERR_NOT_SUPPORTED;
478 return rc;
479}
480
481/* Notifier function for control execution stuff. */
482int Guest::notifyCtrlExec(uint32_t u32Function,
483 PHOSTEXECCALLBACKDATA pData)
484{
485 int rc = VINF_SUCCESS;
486
487 /* bool bFound = false;
488 for (int i=0; i<mList.size(); i++)
489 {
490 }
491 if(pData->hdr.u32ContextID == it->hdr.u32ContextID)
492 {
493 }*/
494 /*pExt->pid = pCBData->pid;
495 pExt->status = pCBData->status;
496 pExt->flags = pCBData->flags;*/
497 /** @todo Copy void* buffer! */
498
499 return rc;
500}
501
502void Guest::freeCtrlCallbackContextData(CallbackContext *pContext)
503{
504 AssertPtr(pContext);
505 if (pContext->cbData)
506 {
507 RTMemFree(pContext->pvData);
508 pContext->cbData = 0;
509 pContext->pvData = NULL;
510 }
511}
512
513uint32_t Guest::addCtrlCallbackContext(void *pvData, uint32_t cbData)
514{
515 uint32_t uNewContext = ASMAtomicIncU32(&mNextContextID);
516 /** @todo Add value clamping! */
517
518 CallbackContext context;
519 context.mContextID = uNewContext;
520 context.pvData = pvData;
521 context.cbData = cbData;
522
523 mCallbackList.push_back(context);
524 if (mCallbackList.size() > 256)
525 {
526 freeCtrlCallbackContextData(&mCallbackList.front());
527 mCallbackList.pop_front();
528 }
529 return uNewContext;
530}
531#endif /* VBOX_WITH_GUEST_CONTROL */
532
533STDMETHODIMP Guest::ExecuteProcess(IN_BSTR aCommand, ULONG aFlags,
534 ComSafeArrayIn(IN_BSTR, aArguments), ComSafeArrayIn(IN_BSTR, aEnvironment),
535 IN_BSTR aStdIn, IN_BSTR aStdOut, IN_BSTR aStdErr,
536 IN_BSTR aUserName, IN_BSTR aPassword,
537 ULONG aTimeoutMS, ULONG *aPID, IProgress **aProgress)
538{
539#ifndef VBOX_WITH_GUEST_CONTROL
540 ReturnComNotImplemented();
541#else /* VBOX_WITH_GUEST_CONTROL */
542 using namespace guestControl;
543
544 CheckComArgStrNotEmptyOrNull(aCommand);
545 CheckComArgOutPointerValid(aPID);
546 CheckComArgOutPointerValid(aProgress);
547 if (aFlags != 0) /* Flags are not supported at the moment. */
548 return E_INVALIDARG;
549
550 HRESULT rc = S_OK;
551
552 try
553 {
554 AutoCaller autoCaller(this);
555 if (FAILED(autoCaller.rc())) return autoCaller.rc();
556
557 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
558
559 /*
560 * Create progress object.
561 */
562#if 0
563 ComObjPtr <Progress> progress;
564 progress.createObject();
565 HRESULT rc = progress->init(/** @todo How to get the machine here? */
566 static_cast<IGuest*>(this),
567 BstrFmt(tr("Executing process")),
568 FALSE);
569 if (FAILED(rc)) return rc;
570#endif
571 /*
572 * Prepare process execution.
573 */
574 int vrc = VINF_SUCCESS;
575 Utf8Str Utf8Command(aCommand);
576
577 /* Prepare arguments. */
578 com::SafeArray<IN_BSTR> args(ComSafeArrayInArg(aArguments));
579 uint32_t uNumArgs = args.size();
580 char **papszArgv = NULL;
581 if(uNumArgs > 0)
582 {
583 papszArgv = (char**)RTMemAlloc(sizeof(char*) * (uNumArgs + 1));
584 AssertPtr(papszArgv);
585 for (unsigned i = 0; RT_SUCCESS(vrc) && i < uNumArgs; i++)
586 vrc = RTStrAPrintf(&papszArgv[i], "%s", Utf8Str(args[i]).raw());
587 papszArgv[uNumArgs] = NULL;
588 }
589
590 if (RT_SUCCESS(vrc))
591 {
592 char *pszArgs = NULL;
593 if (uNumArgs > 0)
594 vrc = RTGetOptArgvToString(&pszArgs, papszArgv, 0);
595 if (RT_SUCCESS(vrc))
596 {
597 uint32_t cbArgs = pszArgs ? strlen(pszArgs) + 1 : 0; /* Include terminating zero. */
598
599 /* Prepare environment. */
600 com::SafeArray<IN_BSTR> env(ComSafeArrayInArg(aEnvironment));
601
602 void *pvEnv = NULL;
603 uint32_t uNumEnv = 0;
604 uint32_t cbEnv = 0;
605
606 for (unsigned i = 0; i < env.size(); i++)
607 {
608 vrc = prepareExecuteEnv(Utf8Str(env[i]).raw(), &pvEnv, &cbEnv, &uNumEnv);
609 if (RT_FAILURE(vrc))
610 break;
611 }
612
613 if (RT_SUCCESS(vrc))
614 {
615 Utf8Str Utf8StdIn(aStdIn);
616 Utf8Str Utf8StdOut(aStdOut);
617 Utf8Str Utf8StdErr(aStdErr);
618 Utf8Str Utf8UserName(aUserName);
619 Utf8Str Utf8Password(aPassword);
620
621 PHOSTEXECCALLBACKDATA pData = (HOSTEXECCALLBACKDATA*)RTMemAlloc(sizeof(HOSTEXECCALLBACKDATA));
622 AssertPtr(pData);
623 uint32_t uContextID = addCtrlCallbackContext(pData, sizeof(HOSTEXECCALLBACKDATA));
624
625 VBOXHGCMSVCPARM paParms[15];
626 int i = 0;
627 paParms[i++].setUInt32(uContextID);
628 paParms[i++].setPointer((void*)Utf8Command.raw(), (uint32_t)strlen(Utf8Command.raw()) + 1);
629 paParms[i++].setUInt32(aFlags);
630 paParms[i++].setUInt32(uNumArgs);
631 paParms[i++].setPointer((void*)pszArgs, cbArgs);
632 paParms[i++].setUInt32(uNumEnv);
633 paParms[i++].setUInt32(cbEnv);
634 paParms[i++].setPointer((void*)pvEnv, cbEnv);
635 paParms[i++].setPointer((void*)Utf8StdIn.raw(), (uint32_t)strlen(Utf8StdIn.raw()) + 1);
636 paParms[i++].setPointer((void*)Utf8StdOut.raw(), (uint32_t)strlen(Utf8StdOut.raw()) + 1);
637 paParms[i++].setPointer((void*)Utf8StdErr.raw(), (uint32_t)strlen(Utf8StdErr.raw()) + 1);
638 paParms[i++].setPointer((void*)Utf8UserName.raw(), (uint32_t)strlen(Utf8UserName.raw()) + 1);
639 paParms[i++].setPointer((void*)Utf8Password.raw(), (uint32_t)strlen(Utf8Password.raw()) + 1);
640 paParms[i++].setUInt32(aTimeoutMS);
641
642 /* Forward the information to the VMM device. */
643 AssertPtr(mParent);
644 VMMDev *vmmDev = mParent->getVMMDev();
645 if (vmmDev)
646 {
647 LogFlowFunc(("hgcmHostCall numParms=%d\n", i));
648 vrc = vmmDev->hgcmHostCall("VBoxGuestControlSvc", HOST_EXEC_CMD,
649 i, paParms);
650 }
651 RTMemFree(pvEnv);
652 }
653 RTStrFree(pszArgs);
654 }
655 if (RT_SUCCESS(vrc))
656 {
657 LogFlowFunc(("Waiting for HGCM callback (timeout=%ldms) ...\n", aTimeoutMS));
658
659 /*
660 * Wait for the HGCM low level callback until the process
661 * has been started (or something went wrong). This is necessary to
662 * get the PID.
663 */
664#if 0
665 uint64_t u64Started = RTTimeMilliTS();
666 do
667 {
668 unsigned cMsWait;
669 if (aTimeoutMS == RT_INDEFINITE_WAIT)
670 cMsWait = 1000;
671 else
672 {
673 uint64_t cMsElapsed = RTTimeMilliTS() - u64Started;
674 if (cMsElapsed >= aTimeoutMS)
675 break; /* timed out */
676 cMsWait = RT_MIN(1000, aTimeoutMS - (uint32_t)cMsElapsed);
677 }
678 RTThreadSleep(100);
679 } while (!callbackData.called);
680
681 /* Did we get some status? */
682 if (callbackData.called)
683 {
684 switch (callbackData.status)
685 {
686 case PROC_STS_STARTED:
687 *aPID = callbackData.pid;
688 break;
689
690 case PROC_STS_ERROR:
691 vrc = callbackData.flags; /* flags member contains IPRT error code. */
692 break;
693
694 default:
695 vrc = VERR_INVALID_PARAMETER;
696 break;
697 }
698 }
699
700 if (RT_FAILURE(vrc))
701 {
702 if (vrc == VERR_FILE_NOT_FOUND) /* This is the most likely error. */
703 {
704 rc = setError(VBOX_E_IPRT_ERROR,
705 tr("The file \"%s\" was not found on guest"), Utf8Command.raw());
706 }
707 else
708 {
709 rc = setError(E_UNEXPECTED,
710 tr("The service call failed with the error %Rrc"), vrc);
711 }
712 }
713#endif
714#if 0
715 progress.queryInterfaceTo(aProgress);
716#endif
717 }
718 else
719 {
720 /* HGCM call went wrong. */
721 rc = setError(E_UNEXPECTED,
722 tr("The service call failed with error %Rrc"), vrc);
723 }
724
725 for (unsigned i = 0; i < uNumArgs; i++)
726 RTMemFree(papszArgv[i]);
727 RTMemFree(papszArgv);
728 }
729 }
730 catch (std::bad_alloc &)
731 {
732 rc = E_OUTOFMEMORY;
733 }
734 return rc;
735#endif /* VBOX_WITH_GUEST_CONTROL */
736}
737
738// public methods only for internal purposes
739/////////////////////////////////////////////////////////////////////////////
740
741void Guest::setAdditionsVersion(Bstr aVersion, VBOXOSTYPE aOsType)
742{
743 AutoCaller autoCaller(this);
744 AssertComRCReturnVoid (autoCaller.rc());
745
746 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
747
748 mData.mAdditionsVersion = aVersion;
749 mData.mAdditionsActive = !aVersion.isEmpty();
750 /* Older Additions didn't have this finer grained capability bit,
751 * so enable it by default. Newer Additions will disable it immediately
752 * if relevant. */
753 mData.mSupportsGraphics = mData.mAdditionsActive;
754
755 mData.mOSTypeId = Global::OSTypeId (aOsType);
756}
757
758void Guest::setSupportsSeamless (BOOL aSupportsSeamless)
759{
760 AutoCaller autoCaller(this);
761 AssertComRCReturnVoid (autoCaller.rc());
762
763 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
764
765 mData.mSupportsSeamless = aSupportsSeamless;
766}
767
768void Guest::setSupportsGraphics (BOOL aSupportsGraphics)
769{
770 AutoCaller autoCaller(this);
771 AssertComRCReturnVoid (autoCaller.rc());
772
773 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
774
775 mData.mSupportsGraphics = aSupportsGraphics;
776}
777/* vi: set tabstop=4 shiftwidth=4 expandtab: */
Note: See TracBrowser for help on using the repository browser.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette