VirtualBox

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

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

HGCM,GuestProps: Added HGCM service notifications for VM power-on, VM resume, VM suspend, VM reset and VM power-off. Made use of the first two in guest properties to wake up guest programs waiting on any of the host version properties. Also moved inserting sysprep and host version properties to the services as that's a better home than ConsoleImpl/VMMDevInterface in my opinion.

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