VirtualBox

source: vbox/trunk/src/VBox/Main/src-client/VMMDevInterface.cpp@ 75955

Last change on this file since 75955 was 75955, checked in by vboxsync, 6 years ago

Main: Load VBoxGuestPropSvc from the VMMDev driver.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 40.2 KB
Line 
1/* $Id: VMMDevInterface.cpp 75955 2018-12-04 21:08:55Z vboxsync $ */
2/** @file
3 * VirtualBox Driver Interface to VMM device.
4 */
5
6/*
7 * Copyright (C) 2006-2017 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.215389.xyz. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18#define LOG_GROUP LOG_GROUP_MAIN_VMMDEVINTERFACES
19#include "LoggingNew.h"
20
21#include "VMMDev.h"
22#include "ConsoleImpl.h"
23#include "DisplayImpl.h"
24#include "GuestImpl.h"
25#include "MouseImpl.h"
26
27#include <VBox/vmm/pdmdrv.h>
28#include <VBox/VMMDev.h>
29#include <VBox/shflsvc.h>
30#include <iprt/asm.h>
31#include <iprt/buildconfig.h>
32
33#ifdef VBOX_WITH_HGCM
34# include "HGCM.h"
35# include "HGCMObjects.h"
36# if defined(RT_OS_DARWIN) && defined(VBOX_WITH_CROGL)
37# include <VBox/HostServices/VBoxCrOpenGLSvc.h>
38# endif
39# ifdef VBOX_WITH_GUEST_PROPS
40# include <VBox/version.h>
41# endif
42#endif
43
44//
45// defines
46//
47
48#ifdef RT_OS_OS2
49# define VBOXSHAREDFOLDERS_DLL "VBoxSFld"
50#else
51# define VBOXSHAREDFOLDERS_DLL "VBoxSharedFolders"
52#endif
53
54//
55// globals
56//
57
58
59/**
60 * VMMDev driver instance data.
61 */
62typedef struct DRVMAINVMMDEV
63{
64 /** Pointer to the VMMDev object. */
65 VMMDev *pVMMDev;
66 /** Pointer to the driver instance structure. */
67 PPDMDRVINS pDrvIns;
68 /** Pointer to the VMMDev port interface of the driver/device above us. */
69 PPDMIVMMDEVPORT pUpPort;
70 /** Our VMM device connector interface. */
71 PDMIVMMDEVCONNECTOR Connector;
72
73#ifdef VBOX_WITH_HGCM
74 /** Pointer to the HGCM port interface of the driver/device above us. */
75 PPDMIHGCMPORT pHGCMPort;
76 /** Our HGCM connector interface. */
77 PDMIHGCMCONNECTOR HGCMConnector;
78#endif
79} DRVMAINVMMDEV, *PDRVMAINVMMDEV;
80
81//
82// constructor / destructor
83//
84VMMDev::VMMDev(Console *console)
85 : mpDrv(NULL)
86 , mParent(console)
87{
88 int rc = RTSemEventCreate(&mCredentialsEvent);
89 AssertRC(rc);
90#ifdef VBOX_WITH_HGCM
91 rc = HGCMHostInit();
92 AssertRC(rc);
93 m_fHGCMActive = true;
94#endif /* VBOX_WITH_HGCM */
95 mu32CredentialsFlags = 0;
96}
97
98VMMDev::~VMMDev()
99{
100#ifdef VBOX_WITH_HGCM
101 if (ASMAtomicCmpXchgBool(&m_fHGCMActive, false, true))
102 HGCMHostShutdown(true /*fUvmIsInvalid*/);
103#endif
104 RTSemEventDestroy(mCredentialsEvent);
105 if (mpDrv)
106 mpDrv->pVMMDev = NULL;
107 mpDrv = NULL;
108}
109
110PPDMIVMMDEVPORT VMMDev::getVMMDevPort()
111{
112 if (!mpDrv)
113 return NULL;
114 return mpDrv->pUpPort;
115}
116
117
118
119//
120// public methods
121//
122
123/**
124 * Wait on event semaphore for guest credential judgement result.
125 */
126int VMMDev::WaitCredentialsJudgement(uint32_t u32Timeout, uint32_t *pu32CredentialsFlags)
127{
128 if (u32Timeout == 0)
129 {
130 u32Timeout = 5000;
131 }
132
133 int rc = RTSemEventWait(mCredentialsEvent, u32Timeout);
134
135 if (RT_SUCCESS(rc))
136 {
137 *pu32CredentialsFlags = mu32CredentialsFlags;
138 }
139
140 return rc;
141}
142
143int VMMDev::SetCredentialsJudgementResult(uint32_t u32Flags)
144{
145 mu32CredentialsFlags = u32Flags;
146
147 int rc = RTSemEventSignal(mCredentialsEvent);
148 AssertRC(rc);
149
150 return rc;
151}
152
153
154/**
155 * @interface_method_impl{PDMIVMMDEVCONNECTOR,pfnUpdateGuestStatus}
156 */
157DECLCALLBACK(void) vmmdevUpdateGuestStatus(PPDMIVMMDEVCONNECTOR pInterface, uint32_t uFacility, uint16_t uStatus,
158 uint32_t fFlags, PCRTTIMESPEC pTimeSpecTS)
159{
160 PDRVMAINVMMDEV pDrv = RT_FROM_MEMBER(pInterface, DRVMAINVMMDEV, Connector);
161 Console *pConsole = pDrv->pVMMDev->getParent();
162
163 /* Store that information in IGuest */
164 Guest* guest = pConsole->i_getGuest();
165 AssertPtrReturnVoid(guest);
166
167 guest->i_setAdditionsStatus((VBoxGuestFacilityType)uFacility, (VBoxGuestFacilityStatus)uStatus, fFlags, pTimeSpecTS);
168 pConsole->i_onAdditionsStateChange();
169}
170
171
172/**
173 * @interface_method_impl{PDMIVMMDEVCONNECTOR,pfnUpdateGuestUserState}
174 */
175DECLCALLBACK(void) vmmdevUpdateGuestUserState(PPDMIVMMDEVCONNECTOR pInterface,
176 const char *pszUser, const char *pszDomain,
177 uint32_t uState,
178 const uint8_t *pabDetails, uint32_t cbDetails)
179{
180 PDRVMAINVMMDEV pDrv = RT_FROM_MEMBER(pInterface, DRVMAINVMMDEV, Connector);
181 AssertPtr(pDrv);
182 Console *pConsole = pDrv->pVMMDev->getParent();
183 AssertPtr(pConsole);
184
185 /* Store that information in IGuest. */
186 Guest* pGuest = pConsole->i_getGuest();
187 AssertPtrReturnVoid(pGuest);
188
189 pGuest->i_onUserStateChange(Bstr(pszUser), Bstr(pszDomain), (VBoxGuestUserState)uState,
190 pabDetails, cbDetails);
191}
192
193
194/**
195 * Reports Guest Additions API and OS version.
196 *
197 * Called whenever the Additions issue a guest version report request or the VM
198 * is reset.
199 *
200 * @param pInterface Pointer to this interface.
201 * @param guestInfo Pointer to guest information structure.
202 * @thread The emulation thread.
203 */
204DECLCALLBACK(void) vmmdevUpdateGuestInfo(PPDMIVMMDEVCONNECTOR pInterface, const VBoxGuestInfo *guestInfo)
205{
206 AssertPtrReturnVoid(guestInfo);
207
208 PDRVMAINVMMDEV pDrv = RT_FROM_MEMBER(pInterface, DRVMAINVMMDEV, Connector);
209 Console *pConsole = pDrv->pVMMDev->getParent();
210
211 /* Store that information in IGuest */
212 Guest* guest = pConsole->i_getGuest();
213 AssertPtrReturnVoid(guest);
214
215 if (guestInfo->interfaceVersion != 0)
216 {
217 char version[16];
218 RTStrPrintf(version, sizeof(version), "%d", guestInfo->interfaceVersion);
219 guest->i_setAdditionsInfo(Bstr(version), guestInfo->osType);
220
221 /*
222 * Tell the console interface about the event
223 * so that it can notify its consumers.
224 */
225 pConsole->i_onAdditionsStateChange();
226
227 if (guestInfo->interfaceVersion < VMMDEV_VERSION)
228 pConsole->i_onAdditionsOutdated();
229 }
230 else
231 {
232 /*
233 * The guest additions was disabled because of a reset
234 * or driver unload.
235 */
236 guest->i_setAdditionsInfo(Bstr(), guestInfo->osType); /* Clear interface version + OS type. */
237 /** @todo Would be better if GuestImpl.cpp did all this in the above method call
238 * while holding down the. */
239 guest->i_setAdditionsInfo2(0, "", 0, 0); /* Clear Guest Additions version. */
240 RTTIMESPEC TimeSpecTS;
241 RTTimeNow(&TimeSpecTS);
242 guest->i_setAdditionsStatus(VBoxGuestFacilityType_All, VBoxGuestFacilityStatus_Inactive, 0 /*fFlags*/, &TimeSpecTS);
243 pConsole->i_onAdditionsStateChange();
244 }
245}
246
247/**
248 * @interface_method_impl{PDMIVMMDEVCONNECTOR,pfnUpdateGuestInfo2}
249 */
250DECLCALLBACK(void) vmmdevUpdateGuestInfo2(PPDMIVMMDEVCONNECTOR pInterface, uint32_t uFullVersion,
251 const char *pszName, uint32_t uRevision, uint32_t fFeatures)
252{
253 PDRVMAINVMMDEV pDrv = RT_FROM_MEMBER(pInterface, DRVMAINVMMDEV, Connector);
254 AssertPtr(pszName);
255 Assert(uFullVersion);
256
257 /* Store that information in IGuest. */
258 Guest *pGuest = pDrv->pVMMDev->getParent()->i_getGuest();
259 AssertPtrReturnVoid(pGuest);
260
261 /* Just pass it on... */
262 pGuest->i_setAdditionsInfo2(uFullVersion, pszName, uRevision, fFeatures);
263
264 /*
265 * No need to tell the console interface about the update;
266 * vmmdevUpdateGuestInfo takes care of that when called as the
267 * last event in the chain.
268 */
269}
270
271/**
272 * Update the guest additions capabilities.
273 * This is called when the guest additions capabilities change. The new capabilities
274 * are given and the connector should update its internal state.
275 *
276 * @param pInterface Pointer to this interface.
277 * @param newCapabilities New capabilities.
278 * @thread The emulation thread.
279 */
280DECLCALLBACK(void) vmmdevUpdateGuestCapabilities(PPDMIVMMDEVCONNECTOR pInterface, uint32_t newCapabilities)
281{
282 PDRVMAINVMMDEV pDrv = RT_FROM_MEMBER(pInterface, DRVMAINVMMDEV, Connector);
283 AssertPtr(pDrv);
284 Console *pConsole = pDrv->pVMMDev->getParent();
285
286 /* store that information in IGuest */
287 Guest* pGuest = pConsole->i_getGuest();
288 AssertPtrReturnVoid(pGuest);
289
290 /*
291 * Report our current capabilities (and assume none is active yet).
292 */
293 pGuest->i_setSupportedFeatures(newCapabilities);
294
295 /*
296 * Tell the Display, so that it can update the "supports graphics"
297 * capability if the graphics card has not asserted it.
298 */
299 Display* pDisplay = pConsole->i_getDisplay();
300 AssertPtrReturnVoid(pDisplay);
301 pDisplay->i_handleUpdateVMMDevSupportsGraphics(RT_BOOL(newCapabilities & VMMDEV_GUEST_SUPPORTS_GRAPHICS));
302
303 /*
304 * Tell the console interface about the event
305 * so that it can notify its consumers.
306 */
307 pConsole->i_onAdditionsStateChange();
308}
309
310/**
311 * Update the mouse capabilities.
312 * This is called when the mouse capabilities change. The new capabilities
313 * are given and the connector should update its internal state.
314 *
315 * @param pInterface Pointer to this interface.
316 * @param fNewCaps New capabilities.
317 * @thread The emulation thread.
318 */
319DECLCALLBACK(void) vmmdevUpdateMouseCapabilities(PPDMIVMMDEVCONNECTOR pInterface, uint32_t fNewCaps)
320{
321 PDRVMAINVMMDEV pDrv = RT_FROM_MEMBER(pInterface, DRVMAINVMMDEV, Connector);
322 Console *pConsole = pDrv->pVMMDev->getParent();
323
324 /*
325 * Tell the console interface about the event
326 * so that it can notify its consumers.
327 */
328 Mouse *pMouse = pConsole->i_getMouse();
329 if (pMouse) /** @todo and if not? Can that actually happen? */
330 pMouse->i_onVMMDevGuestCapsChange(fNewCaps & VMMDEV_MOUSE_GUEST_MASK);
331}
332
333/**
334 * Update the pointer shape or visibility.
335 *
336 * This is called when the mouse pointer shape changes or pointer is hidden/displaying.
337 * The new shape is passed as a caller allocated buffer that will be freed after returning.
338 *
339 * @param pInterface Pointer to this interface.
340 * @param fVisible Whether the pointer is visible or not.
341 * @param fAlpha Alpha channel information is present.
342 * @param xHot Horizontal coordinate of the pointer hot spot.
343 * @param yHot Vertical coordinate of the pointer hot spot.
344 * @param width Pointer width in pixels.
345 * @param height Pointer height in pixels.
346 * @param pShape The shape buffer. If NULL, then only pointer visibility is being changed.
347 * @thread The emulation thread.
348 */
349DECLCALLBACK(void) vmmdevUpdatePointerShape(PPDMIVMMDEVCONNECTOR pInterface, bool fVisible, bool fAlpha,
350 uint32_t xHot, uint32_t yHot,
351 uint32_t width, uint32_t height,
352 void *pShape)
353{
354 PDRVMAINVMMDEV pDrv = RT_FROM_MEMBER(pInterface, DRVMAINVMMDEV, Connector);
355 Console *pConsole = pDrv->pVMMDev->getParent();
356
357 /* tell the console about it */
358 uint32_t cbShape = 0;
359 if (pShape)
360 {
361 cbShape = (width + 7) / 8 * height; /* size of the AND mask */
362 cbShape = ((cbShape + 3) & ~3) + width * 4 * height; /* + gap + size of the XOR mask */
363 }
364 pConsole->i_onMousePointerShapeChange(fVisible, fAlpha, xHot, yHot, width, height, (uint8_t *)pShape, cbShape);
365}
366
367DECLCALLBACK(int) iface_VideoAccelEnable(PPDMIVMMDEVCONNECTOR pInterface, bool fEnable, VBVAMEMORY *pVbvaMemory)
368{
369 PDRVMAINVMMDEV pDrv = RT_FROM_MEMBER(pInterface, DRVMAINVMMDEV, Connector);
370 Console *pConsole = pDrv->pVMMDev->getParent();
371
372 Display *display = pConsole->i_getDisplay();
373
374 if (display)
375 {
376 Log9(("MAIN::VMMDevInterface::iface_VideoAccelEnable: %d, %p\n", fEnable, pVbvaMemory));
377 return display->VideoAccelEnableVMMDev(fEnable, pVbvaMemory);
378 }
379
380 return VERR_NOT_SUPPORTED;
381}
382DECLCALLBACK(void) iface_VideoAccelFlush(PPDMIVMMDEVCONNECTOR pInterface)
383{
384 PDRVMAINVMMDEV pDrv = RT_FROM_MEMBER(pInterface, DRVMAINVMMDEV, Connector);
385 Console *pConsole = pDrv->pVMMDev->getParent();
386
387 Display *display = pConsole->i_getDisplay();
388
389 if (display)
390 {
391 Log9(("MAIN::VMMDevInterface::iface_VideoAccelFlush\n"));
392 display->VideoAccelFlushVMMDev();
393 }
394}
395
396DECLCALLBACK(int) vmmdevVideoModeSupported(PPDMIVMMDEVCONNECTOR pInterface, uint32_t display, uint32_t width, uint32_t height,
397 uint32_t bpp, bool *fSupported)
398{
399 PDRVMAINVMMDEV pDrv = RT_FROM_MEMBER(pInterface, DRVMAINVMMDEV, Connector);
400 Console *pConsole = pDrv->pVMMDev->getParent();
401
402 if (!fSupported)
403 return VERR_INVALID_PARAMETER;
404#ifdef DEBUG_sunlover
405 Log(("vmmdevVideoModeSupported: [%d]: %dx%dx%d\n", display, width, height, bpp));
406#endif
407 IFramebuffer *framebuffer = NULL;
408 HRESULT hrc = pConsole->i_getDisplay()->QueryFramebuffer(display, &framebuffer);
409 if (SUCCEEDED(hrc) && framebuffer)
410 {
411 framebuffer->VideoModeSupported(width, height, bpp, (BOOL*)fSupported);
412 framebuffer->Release();
413 }
414 else
415 {
416#ifdef DEBUG_sunlover
417 Log(("vmmdevVideoModeSupported: hrc %x, framebuffer %p!!!\n", hrc, framebuffer));
418#endif
419 *fSupported = true;
420 }
421 return VINF_SUCCESS;
422}
423
424DECLCALLBACK(int) vmmdevGetHeightReduction(PPDMIVMMDEVCONNECTOR pInterface, uint32_t *heightReduction)
425{
426 PDRVMAINVMMDEV pDrv = RT_FROM_MEMBER(pInterface, DRVMAINVMMDEV, Connector);
427 Console *pConsole = pDrv->pVMMDev->getParent();
428
429 if (!heightReduction)
430 return VERR_INVALID_PARAMETER;
431 IFramebuffer *framebuffer = NULL;
432 HRESULT hrc = pConsole->i_getDisplay()->QueryFramebuffer(0, &framebuffer);
433 if (SUCCEEDED(hrc) && framebuffer)
434 {
435 framebuffer->COMGETTER(HeightReduction)((ULONG*)heightReduction);
436 framebuffer->Release();
437 }
438 else
439 *heightReduction = 0;
440 return VINF_SUCCESS;
441}
442
443DECLCALLBACK(int) vmmdevSetCredentialsJudgementResult(PPDMIVMMDEVCONNECTOR pInterface, uint32_t u32Flags)
444{
445 PDRVMAINVMMDEV pDrv = RT_FROM_MEMBER(pInterface, DRVMAINVMMDEV, Connector);
446
447 if (pDrv->pVMMDev)
448 return pDrv->pVMMDev->SetCredentialsJudgementResult(u32Flags);
449
450 return VERR_GENERAL_FAILURE;
451}
452
453DECLCALLBACK(int) vmmdevSetVisibleRegion(PPDMIVMMDEVCONNECTOR pInterface, uint32_t cRect, PRTRECT pRect)
454{
455 PDRVMAINVMMDEV pDrv = RT_FROM_MEMBER(pInterface, DRVMAINVMMDEV, Connector);
456 Console *pConsole = pDrv->pVMMDev->getParent();
457
458 /* Forward to Display, which calls corresponding framebuffers. */
459 pConsole->i_getDisplay()->i_handleSetVisibleRegion(cRect, pRect);
460
461 return VINF_SUCCESS;
462}
463
464DECLCALLBACK(int) vmmdevQueryVisibleRegion(PPDMIVMMDEVCONNECTOR pInterface, uint32_t *pcRects, PRTRECT paRects)
465{
466 PDRVMAINVMMDEV pDrv = RT_FROM_MEMBER(pInterface, DRVMAINVMMDEV, Connector);
467 Console *pConsole = pDrv->pVMMDev->getParent();
468
469 /* Forward to Display, which calls corresponding framebuffers. */
470 pConsole->i_getDisplay()->i_handleQueryVisibleRegion(pcRects, paRects);
471
472 return VINF_SUCCESS;
473}
474
475/**
476 * Request the statistics interval
477 *
478 * @returns VBox status code.
479 * @param pInterface Pointer to this interface.
480 * @param pulInterval Pointer to interval in seconds
481 * @thread The emulation thread.
482 */
483DECLCALLBACK(int) vmmdevQueryStatisticsInterval(PPDMIVMMDEVCONNECTOR pInterface, uint32_t *pulInterval)
484{
485 PDRVMAINVMMDEV pDrv = RT_FROM_MEMBER(pInterface, DRVMAINVMMDEV, Connector);
486 Console *pConsole = pDrv->pVMMDev->getParent();
487 ULONG val = 0;
488
489 if (!pulInterval)
490 return VERR_INVALID_POINTER;
491
492 /* store that information in IGuest */
493 Guest* guest = pConsole->i_getGuest();
494 AssertPtrReturn(guest, VERR_GENERAL_FAILURE);
495
496 guest->COMGETTER(StatisticsUpdateInterval)(&val);
497 *pulInterval = val;
498 return VINF_SUCCESS;
499}
500
501/**
502 * Query the current balloon size
503 *
504 * @returns VBox status code.
505 * @param pInterface Pointer to this interface.
506 * @param pcbBalloon Balloon size
507 * @thread The emulation thread.
508 */
509DECLCALLBACK(int) vmmdevQueryBalloonSize(PPDMIVMMDEVCONNECTOR pInterface, uint32_t *pcbBalloon)
510{
511 PDRVMAINVMMDEV pDrv = RT_FROM_MEMBER(pInterface, DRVMAINVMMDEV, Connector);
512 Console *pConsole = pDrv->pVMMDev->getParent();
513 ULONG val = 0;
514
515 if (!pcbBalloon)
516 return VERR_INVALID_POINTER;
517
518 /* store that information in IGuest */
519 Guest* guest = pConsole->i_getGuest();
520 AssertPtrReturn(guest, VERR_GENERAL_FAILURE);
521
522 guest->COMGETTER(MemoryBalloonSize)(&val);
523 *pcbBalloon = val;
524 return VINF_SUCCESS;
525}
526
527/**
528 * Query the current page fusion setting
529 *
530 * @returns VBox status code.
531 * @param pInterface Pointer to this interface.
532 * @param pfPageFusionEnabled Pointer to boolean
533 * @thread The emulation thread.
534 */
535DECLCALLBACK(int) vmmdevIsPageFusionEnabled(PPDMIVMMDEVCONNECTOR pInterface, bool *pfPageFusionEnabled)
536{
537 PDRVMAINVMMDEV pDrv = RT_FROM_MEMBER(pInterface, DRVMAINVMMDEV, Connector);
538 Console *pConsole = pDrv->pVMMDev->getParent();
539
540 if (!pfPageFusionEnabled)
541 return VERR_INVALID_POINTER;
542
543 /* store that information in IGuest */
544 Guest* guest = pConsole->i_getGuest();
545 AssertPtrReturn(guest, VERR_GENERAL_FAILURE);
546
547 *pfPageFusionEnabled = !!guest->i_isPageFusionEnabled();
548 return VINF_SUCCESS;
549}
550
551/**
552 * Report new guest statistics
553 *
554 * @returns VBox status code.
555 * @param pInterface Pointer to this interface.
556 * @param pGuestStats Guest statistics
557 * @thread The emulation thread.
558 */
559DECLCALLBACK(int) vmmdevReportStatistics(PPDMIVMMDEVCONNECTOR pInterface, VBoxGuestStatistics *pGuestStats)
560{
561 PDRVMAINVMMDEV pDrv = RT_FROM_MEMBER(pInterface, DRVMAINVMMDEV, Connector);
562 Console *pConsole = pDrv->pVMMDev->getParent();
563
564 AssertPtrReturn(pGuestStats, VERR_INVALID_POINTER);
565
566 /* store that information in IGuest */
567 Guest* guest = pConsole->i_getGuest();
568 AssertPtrReturn(guest, VERR_GENERAL_FAILURE);
569
570 if (pGuestStats->u32StatCaps & VBOX_GUEST_STAT_CPU_LOAD_IDLE)
571 guest->i_setStatistic(pGuestStats->u32CpuId, GUESTSTATTYPE_CPUIDLE, pGuestStats->u32CpuLoad_Idle);
572
573 if (pGuestStats->u32StatCaps & VBOX_GUEST_STAT_CPU_LOAD_KERNEL)
574 guest->i_setStatistic(pGuestStats->u32CpuId, GUESTSTATTYPE_CPUKERNEL, pGuestStats->u32CpuLoad_Kernel);
575
576 if (pGuestStats->u32StatCaps & VBOX_GUEST_STAT_CPU_LOAD_USER)
577 guest->i_setStatistic(pGuestStats->u32CpuId, GUESTSTATTYPE_CPUUSER, pGuestStats->u32CpuLoad_User);
578
579
580 /** @todo r=bird: Convert from 4KB to 1KB units?
581 * CollectorGuestHAL::i_getGuestMemLoad says it returns KB units to
582 * preCollect(). I might be wrong ofc, this is convoluted code... */
583 if (pGuestStats->u32StatCaps & VBOX_GUEST_STAT_PHYS_MEM_TOTAL)
584 guest->i_setStatistic(pGuestStats->u32CpuId, GUESTSTATTYPE_MEMTOTAL, pGuestStats->u32PhysMemTotal);
585
586 if (pGuestStats->u32StatCaps & VBOX_GUEST_STAT_PHYS_MEM_AVAIL)
587 guest->i_setStatistic(pGuestStats->u32CpuId, GUESTSTATTYPE_MEMFREE, pGuestStats->u32PhysMemAvail);
588
589 if (pGuestStats->u32StatCaps & VBOX_GUEST_STAT_PHYS_MEM_BALLOON)
590 guest->i_setStatistic(pGuestStats->u32CpuId, GUESTSTATTYPE_MEMBALLOON, pGuestStats->u32PhysMemBalloon);
591
592 if (pGuestStats->u32StatCaps & VBOX_GUEST_STAT_MEM_SYSTEM_CACHE)
593 guest->i_setStatistic(pGuestStats->u32CpuId, GUESTSTATTYPE_MEMCACHE, pGuestStats->u32MemSystemCache);
594
595 if (pGuestStats->u32StatCaps & VBOX_GUEST_STAT_PAGE_FILE_SIZE)
596 guest->i_setStatistic(pGuestStats->u32CpuId, GUESTSTATTYPE_PAGETOTAL, pGuestStats->u32PageFileSize);
597
598 return VINF_SUCCESS;
599}
600
601#ifdef VBOX_WITH_HGCM
602
603/* HGCM connector interface */
604
605static DECLCALLBACK(int) iface_hgcmConnect(PPDMIHGCMCONNECTOR pInterface, PVBOXHGCMCMD pCmd,
606 PHGCMSERVICELOCATION pServiceLocation,
607 uint32_t *pu32ClientID)
608{
609 Log9(("Enter\n"));
610
611 PDRVMAINVMMDEV pDrv = RT_FROM_MEMBER(pInterface, DRVMAINVMMDEV, HGCMConnector);
612
613 if ( !pServiceLocation
614 || ( pServiceLocation->type != VMMDevHGCMLoc_LocalHost
615 && pServiceLocation->type != VMMDevHGCMLoc_LocalHost_Existing))
616 {
617 return VERR_INVALID_PARAMETER;
618 }
619
620 /* Check if service name is a string terminated by zero*/
621 size_t cchInfo = 0;
622 if (RTStrNLenEx(pServiceLocation->u.host.achName, sizeof(pServiceLocation->u.host.achName), &cchInfo) != VINF_SUCCESS)
623 {
624 return VERR_INVALID_PARAMETER;
625 }
626
627 if (!pDrv->pVMMDev || !pDrv->pVMMDev->hgcmIsActive())
628 return VERR_INVALID_STATE;
629 return HGCMGuestConnect(pDrv->pHGCMPort, pCmd, pServiceLocation->u.host.achName, pu32ClientID);
630}
631
632static DECLCALLBACK(int) iface_hgcmDisconnect(PPDMIHGCMCONNECTOR pInterface, PVBOXHGCMCMD pCmd, uint32_t u32ClientID)
633{
634 Log9(("Enter\n"));
635
636 PDRVMAINVMMDEV pDrv = RT_FROM_MEMBER(pInterface, DRVMAINVMMDEV, HGCMConnector);
637
638 if (!pDrv->pVMMDev || !pDrv->pVMMDev->hgcmIsActive())
639 return VERR_INVALID_STATE;
640
641 return HGCMGuestDisconnect(pDrv->pHGCMPort, pCmd, u32ClientID);
642}
643
644static DECLCALLBACK(int) iface_hgcmCall(PPDMIHGCMCONNECTOR pInterface, PVBOXHGCMCMD pCmd, uint32_t u32ClientID,
645 uint32_t u32Function, uint32_t cParms, PVBOXHGCMSVCPARM paParms, uint64_t tsArrival)
646{
647 Log9(("Enter\n"));
648
649 PDRVMAINVMMDEV pDrv = RT_FROM_MEMBER(pInterface, DRVMAINVMMDEV, HGCMConnector);
650
651 if (!pDrv->pVMMDev || !pDrv->pVMMDev->hgcmIsActive())
652 return VERR_INVALID_STATE;
653
654 return HGCMGuestCall(pDrv->pHGCMPort, pCmd, u32ClientID, u32Function, cParms, paParms, tsArrival);
655}
656
657/**
658 * Execute state save operation.
659 *
660 * @returns VBox status code.
661 * @param pDrvIns Driver instance of the driver which registered the data unit.
662 * @param pSSM SSM operation handle.
663 */
664static DECLCALLBACK(int) iface_hgcmSave(PPDMDRVINS pDrvIns, PSSMHANDLE pSSM)
665{
666 RT_NOREF(pDrvIns);
667 Log9(("Enter\n"));
668 return HGCMHostSaveState(pSSM);
669}
670
671
672/**
673 * Execute state load operation.
674 *
675 * @returns VBox status code.
676 * @param pDrvIns Driver instance of the driver which registered the data unit.
677 * @param pSSM SSM operation handle.
678 * @param uVersion Data layout version.
679 * @param uPass The data pass.
680 */
681static DECLCALLBACK(int) iface_hgcmLoad(PPDMDRVINS pDrvIns, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass)
682{
683 RT_NOREF(pDrvIns);
684 LogFlowFunc(("Enter\n"));
685
686 if ( uVersion != HGCM_SAVED_STATE_VERSION
687 && uVersion != HGCM_SAVED_STATE_VERSION_V2)
688 return VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION;
689 Assert(uPass == SSM_PASS_FINAL); NOREF(uPass);
690
691 return HGCMHostLoadState(pSSM, uVersion);
692}
693
694int VMMDev::hgcmLoadService(const char *pszServiceLibrary, const char *pszServiceName)
695{
696 if (!hgcmIsActive())
697 return VERR_INVALID_STATE;
698
699 /** @todo Construct all the services in the VMMDev::drvConstruct()!! */
700 Assert( (mpDrv && mpDrv->pHGCMPort)
701 || !strcmp(pszServiceLibrary, "VBoxHostChannel")
702 || !strcmp(pszServiceLibrary, "VBoxSharedClipboard")
703 || !strcmp(pszServiceLibrary, "VBoxDragAndDropSvc")
704 || !strcmp(pszServiceLibrary, "VBoxGuestPropSvc")
705 || !strcmp(pszServiceLibrary, "VBoxSharedCrOpenGL")
706 );
707 Console::SafeVMPtrQuiet ptrVM(mParent);
708 return HGCMHostLoad(pszServiceLibrary, pszServiceName, ptrVM.rawUVM(), mpDrv ? mpDrv->pHGCMPort : NULL);
709}
710
711int VMMDev::hgcmHostCall(const char *pszServiceName, uint32_t u32Function,
712 uint32_t cParms, PVBOXHGCMSVCPARM paParms)
713{
714 if (!hgcmIsActive())
715 return VERR_INVALID_STATE;
716 return HGCMHostCall(pszServiceName, u32Function, cParms, paParms);
717}
718
719/**
720 * Used by Console::i_powerDown to shut down the services before the VM is destroyed.
721 */
722void VMMDev::hgcmShutdown(bool fUvmIsInvalid /*= false*/)
723{
724 if (ASMAtomicCmpXchgBool(&m_fHGCMActive, false, true))
725 HGCMHostShutdown(fUvmIsInvalid);
726}
727
728# ifdef VBOX_WITH_CRHGSMI
729int VMMDev::hgcmHostSvcHandleCreate(const char *pszServiceName, HGCMCVSHANDLE * phSvc)
730{
731 if (!hgcmIsActive())
732 return VERR_INVALID_STATE;
733 return HGCMHostSvcHandleCreate(pszServiceName, phSvc);
734}
735
736int VMMDev::hgcmHostSvcHandleDestroy(HGCMCVSHANDLE hSvc)
737{
738 if (!hgcmIsActive())
739 return VERR_INVALID_STATE;
740 return HGCMHostSvcHandleDestroy(hSvc);
741}
742
743int VMMDev::hgcmHostFastCallAsync(HGCMCVSHANDLE hSvc, uint32_t function, PVBOXHGCMSVCPARM pParm,
744 PHGCMHOSTFASTCALLCB pfnCompletion, void *pvCompletion)
745{
746 if (!hgcmIsActive())
747 return VERR_INVALID_STATE;
748 return HGCMHostFastCallAsync(hSvc, function, pParm, pfnCompletion, pvCompletion);
749}
750# endif
751
752#endif /* HGCM */
753
754
755/**
756 * @interface_method_impl{PDMIBASE,pfnQueryInterface}
757 */
758DECLCALLBACK(void *) VMMDev::drvQueryInterface(PPDMIBASE pInterface, const char *pszIID)
759{
760 PPDMDRVINS pDrvIns = PDMIBASE_2_PDMDRV(pInterface);
761 PDRVMAINVMMDEV pDrv = PDMINS_2_DATA(pDrvIns, PDRVMAINVMMDEV);
762
763 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pDrvIns->IBase);
764 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIVMMDEVCONNECTOR, &pDrv->Connector);
765#ifdef VBOX_WITH_HGCM
766 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIHGCMCONNECTOR, &pDrv->HGCMConnector);
767#endif
768 return NULL;
769}
770
771/**
772 * @interface_method_impl{PDMDRVREG,pfnReset}
773 */
774DECLCALLBACK(void) VMMDev::drvReset(PPDMDRVINS pDrvIns)
775{
776 RT_NOREF(pDrvIns);
777 LogFlow(("VMMDev::drvReset: iInstance=%d\n", pDrvIns->iInstance));
778#ifdef VBOX_WITH_HGCM
779 HGCMHostReset();
780#endif /* VBOX_WITH_HGCM */
781}
782
783/**
784 * @interface_method_impl{PDMDRVREG,pfnDestruct}
785 */
786DECLCALLBACK(void) VMMDev::drvDestruct(PPDMDRVINS pDrvIns)
787{
788 PDMDRV_CHECK_VERSIONS_RETURN_VOID(pDrvIns);
789 PDRVMAINVMMDEV pThis = PDMINS_2_DATA(pDrvIns, PDRVMAINVMMDEV);
790 LogFlow(("VMMDev::drvDestruct: iInstance=%d\n", pDrvIns->iInstance));
791
792 if (pThis->pVMMDev)
793 {
794#ifdef VBOX_WITH_HGCM
795 /* When VM construction goes wrong, we prefer shutting down HGCM here
796 while pUVM is still valid, rather than in ~VMMDev. */
797 if (ASMAtomicCmpXchgBool(&pThis->pVMMDev->m_fHGCMActive, false, true))
798 HGCMHostShutdown();
799#endif
800 pThis->pVMMDev->mpDrv = NULL;
801 }
802}
803
804#ifdef VBOX_WITH_GUEST_PROPS
805
806/**
807 * Set an array of guest properties
808 */
809void VMMDev::i_guestPropSetMultiple(void *names, void *values, void *timestamps, void *flags)
810{
811 VBOXHGCMSVCPARM parms[4];
812
813 parms[0].type = VBOX_HGCM_SVC_PARM_PTR;
814 parms[0].u.pointer.addr = names;
815 parms[0].u.pointer.size = 0; /* We don't actually care. */
816 parms[1].type = VBOX_HGCM_SVC_PARM_PTR;
817 parms[1].u.pointer.addr = values;
818 parms[1].u.pointer.size = 0; /* We don't actually care. */
819 parms[2].type = VBOX_HGCM_SVC_PARM_PTR;
820 parms[2].u.pointer.addr = timestamps;
821 parms[2].u.pointer.size = 0; /* We don't actually care. */
822 parms[3].type = VBOX_HGCM_SVC_PARM_PTR;
823 parms[3].u.pointer.addr = flags;
824 parms[3].u.pointer.size = 0; /* We don't actually care. */
825
826 hgcmHostCall("VBoxGuestPropSvc", GUEST_PROP_FN_HOST_SET_PROPS, 4, &parms[0]);
827}
828
829/**
830 * Set a single guest property
831 */
832void VMMDev::i_guestPropSet(const char *pszName, const char *pszValue, const char *pszFlags)
833{
834 VBOXHGCMSVCPARM parms[4];
835
836 AssertPtrReturnVoid(pszName);
837 AssertPtrReturnVoid(pszValue);
838 AssertPtrReturnVoid(pszFlags);
839 parms[0].type = VBOX_HGCM_SVC_PARM_PTR;
840 parms[0].u.pointer.addr = (void *)pszName;
841 parms[0].u.pointer.size = (uint32_t)strlen(pszName) + 1;
842 parms[1].type = VBOX_HGCM_SVC_PARM_PTR;
843 parms[1].u.pointer.addr = (void *)pszValue;
844 parms[1].u.pointer.size = (uint32_t)strlen(pszValue) + 1;
845 parms[2].type = VBOX_HGCM_SVC_PARM_PTR;
846 parms[2].u.pointer.addr = (void *)pszFlags;
847 parms[2].u.pointer.size = (uint32_t)strlen(pszFlags) + 1;
848 hgcmHostCall("VBoxGuestPropSvc", GUEST_PROP_FN_HOST_SET_PROP, 3, &parms[0]);
849}
850
851/**
852 * Set the global flags value by calling the service
853 * @returns the status returned by the call to the service
854 *
855 * @param pTable the service instance handle
856 * @param eFlags the flags to set
857 */
858int VMMDev::i_guestPropSetGlobalPropertyFlags(uint32_t fFlags)
859{
860 VBOXHGCMSVCPARM parm;
861 HGCMSvcSetU32(&parm, fFlags);
862 int rc = hgcmHostCall("VBoxGuestPropSvc", GUEST_PROP_FN_HOST_SET_GLOBAL_FLAGS, 1, &parm);
863 if (RT_FAILURE(rc))
864 {
865 char szFlags[GUEST_PROP_MAX_FLAGS_LEN];
866 if (RT_FAILURE(GuestPropWriteFlags(fFlags, szFlags)))
867 Log(("Failed to set the global flags.\n"));
868 else
869 Log(("Failed to set the global flags \"%s\".\n", szFlags));
870 }
871 return rc;
872}
873
874
875/**
876 * Set up the Guest Property service, populate it with properties read from
877 * the machine XML and set a couple of initial properties.
878 */
879int VMMDev::i_guestPropLoadAndConfigure()
880{
881 Assert(mpDrv);
882 ComObjPtr<Console> ptrConsole = this->mParent;
883 AssertReturn(ptrConsole.isNotNull(), VERR_INVALID_POINTER);
884
885 /* Load the service */
886 int rc = hgcmLoadService("VBoxGuestPropSvc", "VBoxGuestPropSvc");
887 if (RT_FAILURE(rc))
888 {
889 LogRel(("VBoxGuestPropSvc is not available. rc = %Rrc\n", rc));
890 return VINF_SUCCESS; /* That is not a fatal failure. */
891 }
892 /*
893 * Initialize built-in properties that can be changed and saved.
894 *
895 * These are typically transient properties that the guest cannot
896 * change.
897 */
898
899 /* Sysprep execution by VBoxService. */
900 i_guestPropSet("/VirtualBox/HostGuest/SysprepExec", "", "TRANSIENT, RDONLYGUEST");
901 i_guestPropSet("/VirtualBox/HostGuest/SysprepArgs", "", "TRANSIENT, RDONLYGUEST");
902
903 /*
904 * Pull over the properties from the server.
905 */
906 SafeArray<BSTR> namesOut;
907 SafeArray<BSTR> valuesOut;
908 SafeArray<LONG64> timestampsOut;
909 SafeArray<BSTR> flagsOut;
910 HRESULT hrc = ptrConsole->i_pullGuestProperties(ComSafeArrayAsOutParam(namesOut),
911 ComSafeArrayAsOutParam(valuesOut),
912 ComSafeArrayAsOutParam(timestampsOut),
913 ComSafeArrayAsOutParam(flagsOut));
914 AssertLogRelMsgReturn(SUCCEEDED(hrc), ("hrc=%Rhrc\n", hrc), VERR_MAIN_CONFIG_CONSTRUCTOR_COM_ERROR);
915 size_t const cProps = namesOut.size();
916 size_t const cAlloc = cProps + 1;
917 AssertLogRelReturn(valuesOut.size() == cProps, VERR_INTERNAL_ERROR_2);
918 AssertLogRelReturn(timestampsOut.size() == cProps, VERR_INTERNAL_ERROR_3);
919 AssertLogRelReturn(flagsOut.size() == cProps, VERR_INTERNAL_ERROR_4);
920
921 char szEmpty[] = "";
922 char **papszNames = (char **)RTMemTmpAllocZ(sizeof(char *) * cAlloc);
923 char **papszValues = (char **)RTMemTmpAllocZ(sizeof(char *) * cAlloc);
924 LONG64 *pai64Timestamps = (LONG64 *)RTMemTmpAllocZ(sizeof(LONG64) * cAlloc);
925 char **papszFlags = (char **)RTMemTmpAllocZ(sizeof(char *) * cAlloc);
926 if (papszNames && papszValues && pai64Timestamps && papszFlags)
927 {
928 for (unsigned i = 0; RT_SUCCESS(rc) && i < cProps; ++i)
929 {
930 AssertPtrBreakStmt(namesOut[i], rc = VERR_INVALID_PARAMETER);
931 rc = RTUtf16ToUtf8(namesOut[i], &papszNames[i]);
932 if (RT_FAILURE(rc))
933 break;
934 if (valuesOut[i])
935 rc = RTUtf16ToUtf8(valuesOut[i], &papszValues[i]);
936 else
937 papszValues[i] = szEmpty;
938 if (RT_FAILURE(rc))
939 break;
940 pai64Timestamps[i] = timestampsOut[i];
941 if (flagsOut[i])
942 rc = RTUtf16ToUtf8(flagsOut[i], &papszFlags[i]);
943 else
944 papszFlags[i] = szEmpty;
945 }
946 if (RT_SUCCESS(rc))
947 i_guestPropSetMultiple((void *)papszNames, (void *)papszValues, (void *)pai64Timestamps, (void *)papszFlags);
948 for (unsigned i = 0; i < cProps; ++i)
949 {
950 RTStrFree(papszNames[i]);
951 if (valuesOut[i])
952 RTStrFree(papszValues[i]);
953 if (flagsOut[i])
954 RTStrFree(papszFlags[i]);
955 }
956 }
957 else
958 rc = VERR_NO_MEMORY;
959 RTMemTmpFree(papszNames);
960 RTMemTmpFree(papszValues);
961 RTMemTmpFree(pai64Timestamps);
962 RTMemTmpFree(papszFlags);
963 AssertRCReturn(rc, rc);
964
965 /*
966 * These properties have to be set before pulling over the properties
967 * from the machine XML, to ensure that properties saved in the XML
968 * will override them.
969 */
970 /* Set the raw VBox version string as a guest property. Used for host/guest
971 * version comparison. */
972 i_guestPropSet("/VirtualBox/HostInfo/VBoxVer", VBOX_VERSION_STRING_RAW, "TRANSIENT, RDONLYGUEST");
973 /* Set the full VBox version string as a guest property. Can contain vendor-specific
974 * information/branding and/or pre-release tags. */
975 i_guestPropSet("/VirtualBox/HostInfo/VBoxVerExt", VBOX_VERSION_STRING, "TRANSIENT, RDONLYGUEST");
976 /* Set the VBox SVN revision as a guest property */
977 i_guestPropSet("/VirtualBox/HostInfo/VBoxRev", RTBldCfgRevisionStr(), "TRANSIENT, RDONLYGUEST");
978
979 /*
980 * Register the host notification callback
981 */
982 HGCMSVCEXTHANDLE hDummy;
983 HGCMHostRegisterServiceExtension(&hDummy, "VBoxGuestPropSvc", Console::i_doGuestPropNotification, ptrConsole.m_p);
984
985# ifdef VBOX_WITH_GUEST_PROPS_RDONLY_GUEST
986 rc = i_guestPropSetGlobalPropertyFlags(GUEST_PROP_F_RDONLYGUEST);
987 AssertRCReturn(rc, rc);
988# endif
989
990 Log(("Set VBoxGuestPropSvc property store\n"));
991 return VINF_SUCCESS;
992}
993
994#endif /* VBOX_WITH_GUEST_PROPS */
995
996/**
997 * @interface_method_impl{PDMDRVREG,pfnConstruct}
998 */
999DECLCALLBACK(int) VMMDev::drvConstruct(PPDMDRVINS pDrvIns, PCFGMNODE pCfgHandle, uint32_t fFlags)
1000{
1001 RT_NOREF(fFlags);
1002 PDMDRV_CHECK_VERSIONS_RETURN(pDrvIns);
1003 PDRVMAINVMMDEV pThis = PDMINS_2_DATA(pDrvIns, PDRVMAINVMMDEV);
1004 LogFlow(("Keyboard::drvConstruct: iInstance=%d\n", pDrvIns->iInstance));
1005
1006 /*
1007 * Validate configuration.
1008 */
1009 if (!CFGMR3AreValuesValid(pCfgHandle, "Object\0"))
1010 return VERR_PDM_DRVINS_UNKNOWN_CFG_VALUES;
1011 AssertMsgReturn(PDMDrvHlpNoAttach(pDrvIns) == VERR_PDM_NO_ATTACHED_DRIVER,
1012 ("Configuration error: Not possible to attach anything to this driver!\n"),
1013 VERR_PDM_DRVINS_NO_ATTACH);
1014
1015 /*
1016 * IBase.
1017 */
1018 pDrvIns->IBase.pfnQueryInterface = VMMDev::drvQueryInterface;
1019
1020 pThis->Connector.pfnUpdateGuestStatus = vmmdevUpdateGuestStatus;
1021 pThis->Connector.pfnUpdateGuestUserState = vmmdevUpdateGuestUserState;
1022 pThis->Connector.pfnUpdateGuestInfo = vmmdevUpdateGuestInfo;
1023 pThis->Connector.pfnUpdateGuestInfo2 = vmmdevUpdateGuestInfo2;
1024 pThis->Connector.pfnUpdateGuestCapabilities = vmmdevUpdateGuestCapabilities;
1025 pThis->Connector.pfnUpdateMouseCapabilities = vmmdevUpdateMouseCapabilities;
1026 pThis->Connector.pfnUpdatePointerShape = vmmdevUpdatePointerShape;
1027 pThis->Connector.pfnVideoAccelEnable = iface_VideoAccelEnable;
1028 pThis->Connector.pfnVideoAccelFlush = iface_VideoAccelFlush;
1029 pThis->Connector.pfnVideoModeSupported = vmmdevVideoModeSupported;
1030 pThis->Connector.pfnGetHeightReduction = vmmdevGetHeightReduction;
1031 pThis->Connector.pfnSetCredentialsJudgementResult = vmmdevSetCredentialsJudgementResult;
1032 pThis->Connector.pfnSetVisibleRegion = vmmdevSetVisibleRegion;
1033 pThis->Connector.pfnQueryVisibleRegion = vmmdevQueryVisibleRegion;
1034 pThis->Connector.pfnReportStatistics = vmmdevReportStatistics;
1035 pThis->Connector.pfnQueryStatisticsInterval = vmmdevQueryStatisticsInterval;
1036 pThis->Connector.pfnQueryBalloonSize = vmmdevQueryBalloonSize;
1037 pThis->Connector.pfnIsPageFusionEnabled = vmmdevIsPageFusionEnabled;
1038
1039#ifdef VBOX_WITH_HGCM
1040 pThis->HGCMConnector.pfnConnect = iface_hgcmConnect;
1041 pThis->HGCMConnector.pfnDisconnect = iface_hgcmDisconnect;
1042 pThis->HGCMConnector.pfnCall = iface_hgcmCall;
1043#endif
1044
1045 /*
1046 * Get the IVMMDevPort interface of the above driver/device.
1047 */
1048 pThis->pUpPort = PDMIBASE_QUERY_INTERFACE(pDrvIns->pUpBase, PDMIVMMDEVPORT);
1049 AssertMsgReturn(pThis->pUpPort, ("Configuration error: No VMMDev port interface above!\n"), VERR_PDM_MISSING_INTERFACE_ABOVE);
1050
1051#ifdef VBOX_WITH_HGCM
1052 pThis->pHGCMPort = PDMIBASE_QUERY_INTERFACE(pDrvIns->pUpBase, PDMIHGCMPORT);
1053 AssertMsgReturn(pThis->pHGCMPort, ("Configuration error: No HGCM port interface above!\n"), VERR_PDM_MISSING_INTERFACE_ABOVE);
1054#endif
1055
1056 /*
1057 * Get the Console object pointer and update the mpDrv member.
1058 */
1059 void *pv;
1060 int rc = CFGMR3QueryPtr(pCfgHandle, "Object", &pv);
1061 if (RT_FAILURE(rc))
1062 {
1063 AssertMsgFailed(("Configuration error: No/bad \"Object\" value! rc=%Rrc\n", rc));
1064 return rc;
1065 }
1066
1067 pThis->pVMMDev = (VMMDev*)pv; /** @todo Check this cast! */
1068 pThis->pVMMDev->mpDrv = pThis;
1069
1070#ifdef VBOX_WITH_HGCM
1071 /*
1072 * Load & configure the shared folders service.
1073 */
1074 rc = pThis->pVMMDev->hgcmLoadService(VBOXSHAREDFOLDERS_DLL, "VBoxSharedFolders");
1075 pThis->pVMMDev->fSharedFolderActive = RT_SUCCESS(rc);
1076 if (RT_SUCCESS(rc))
1077 {
1078 PPDMLED pLed;
1079 PPDMILEDPORTS pLedPort;
1080
1081 LogRel(("Shared Folders service loaded\n"));
1082 pLedPort = PDMIBASE_QUERY_INTERFACE(pDrvIns->pUpBase, PDMILEDPORTS);
1083 AssertMsgReturn(pLedPort, ("Configuration error: No LED port interface above!\n"), VERR_PDM_MISSING_INTERFACE_ABOVE);
1084 rc = pLedPort->pfnQueryStatusLed(pLedPort, 0, &pLed);
1085 if (RT_SUCCESS(rc) && pLed)
1086 {
1087 VBOXHGCMSVCPARM parm;
1088
1089 parm.type = VBOX_HGCM_SVC_PARM_PTR;
1090 parm.u.pointer.addr = pLed;
1091 parm.u.pointer.size = sizeof(*pLed);
1092
1093 rc = HGCMHostCall("VBoxSharedFolders", SHFL_FN_SET_STATUS_LED, 1, &parm);
1094 }
1095 else
1096 AssertMsgFailed(("pfnQueryStatusLed failed with %Rrc (pLed=%x)\n", rc, pLed));
1097 }
1098 else
1099 LogRel(("Failed to load Shared Folders service %Rrc\n", rc));
1100
1101
1102 /*
1103 * Load and configure the guest control service.
1104 */
1105# ifdef VBOX_WITH_GUEST_CONTROL
1106 rc = pThis->pVMMDev->hgcmLoadService("VBoxGuestControlSvc", "VBoxGuestControlSvc");
1107 if (RT_SUCCESS(rc))
1108 {
1109 HGCMSVCEXTHANDLE hDummy;
1110 rc = HGCMHostRegisterServiceExtension(&hDummy, "VBoxGuestControlSvc",
1111 &Guest::i_notifyCtrlDispatcher,
1112 pThis->pVMMDev->mParent->i_getGuest());
1113 if (RT_SUCCESS(rc))
1114 LogRel(("Guest Control service loaded\n"));
1115 else
1116 LogRel(("Warning: Cannot register VBoxGuestControlSvc extension! rc=%Rrc\n", rc));
1117 }
1118 else
1119 LogRel(("Warning!: Failed to load the Guest Control Service! %Rrc\n", rc));
1120# endif /* VBOX_WITH_GUEST_CONTROL */
1121
1122
1123 /*
1124 * Load and configure the guest properties service.
1125 */
1126# ifdef VBOX_WITH_GUEST_PROPS
1127 rc = pThis->pVMMDev->i_guestPropLoadAndConfigure();
1128 AssertLogRelRCReturn(rc, rc);
1129# endif
1130
1131
1132 /*
1133 * The HGCM saved state.
1134 */
1135 rc = PDMDrvHlpSSMRegisterEx(pDrvIns, HGCM_SAVED_STATE_VERSION, 4096 /* bad guess */,
1136 NULL, NULL, NULL,
1137 NULL, iface_hgcmSave, NULL,
1138 NULL, iface_hgcmLoad, NULL);
1139 if (RT_FAILURE(rc))
1140 return rc;
1141
1142#endif /* VBOX_WITH_HGCM */
1143
1144 return VINF_SUCCESS;
1145}
1146
1147
1148/**
1149 * VMMDevice driver registration record.
1150 */
1151const PDMDRVREG VMMDev::DrvReg =
1152{
1153 /* u32Version */
1154 PDM_DRVREG_VERSION,
1155 /* szName */
1156 "HGCM",
1157 /* szRCMod */
1158 "",
1159 /* szR0Mod */
1160 "",
1161 /* pszDescription */
1162 "Main VMMDev driver (Main as in the API).",
1163 /* fFlags */
1164 PDM_DRVREG_FLAGS_HOST_BITS_DEFAULT,
1165 /* fClass. */
1166 PDM_DRVREG_CLASS_VMMDEV,
1167 /* cMaxInstances */
1168 ~0U,
1169 /* cbInstance */
1170 sizeof(DRVMAINVMMDEV),
1171 /* pfnConstruct */
1172 VMMDev::drvConstruct,
1173 /* pfnDestruct */
1174 VMMDev::drvDestruct,
1175 /* pfnRelocate */
1176 NULL,
1177 /* pfnIOCtl */
1178 NULL,
1179 /* pfnPowerOn */
1180 NULL,
1181 /* pfnReset */
1182 VMMDev::drvReset,
1183 /* pfnSuspend */
1184 NULL,
1185 /* pfnResume */
1186 NULL,
1187 /* pfnAttach */
1188 NULL,
1189 /* pfnDetach */
1190 NULL,
1191 /* pfnPowerOff */
1192 NULL,
1193 /* pfnSoftReset */
1194 NULL,
1195 /* u32EndVersion */
1196 PDM_DRVREG_VERSION
1197};
1198/* 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