VirtualBox

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

Last change on this file since 83251 was 83142, checked in by vboxsync, 5 years ago

bugref:9637. Sending monitor positions (offsets) from GAs to svga device since vmwgfx fails to do so.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 40.9 KB
Line 
1/* $Id: VMMDevInterface.cpp 83142 2020-02-24 19:24:26Z vboxsync $ */
2/** @file
3 * VirtualBox Driver Interface to VMM device.
4 */
5
6/*
7 * Copyright (C) 2006-2020 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#endif
36
37//
38// defines
39//
40
41#ifdef RT_OS_OS2
42# define VBOXSHAREDFOLDERS_DLL "VBoxSFld"
43#else
44# define VBOXSHAREDFOLDERS_DLL "VBoxSharedFolders"
45#endif
46
47//
48// globals
49//
50
51
52/**
53 * VMMDev driver instance data.
54 */
55typedef struct DRVMAINVMMDEV
56{
57 /** Pointer to the VMMDev object. */
58 VMMDev *pVMMDev;
59 /** Pointer to the driver instance structure. */
60 PPDMDRVINS pDrvIns;
61 /** Pointer to the VMMDev port interface of the driver/device above us. */
62 PPDMIVMMDEVPORT pUpPort;
63 /** Our VMM device connector interface. */
64 PDMIVMMDEVCONNECTOR Connector;
65
66#ifdef VBOX_WITH_HGCM
67 /** Pointer to the HGCM port interface of the driver/device above us. */
68 PPDMIHGCMPORT pHGCMPort;
69 /** Our HGCM connector interface. */
70 PDMIHGCMCONNECTOR HGCMConnector;
71#endif
72
73#ifdef VBOX_WITH_GUEST_PROPS
74 HGCMSVCEXTHANDLE hHgcmSvcExtGstProps;
75#endif
76#ifdef VBOX_WITH_GUEST_CONTROL
77 HGCMSVCEXTHANDLE hHgcmSvcExtGstCtrl;
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) vmmdevUpdateMonitorPositions(PPDMIVMMDEVCONNECTOR pInterface, uint32_t cPositions, PRTPOINT pPositions)
465{
466 PDRVMAINVMMDEV pDrv = RT_FROM_MEMBER(pInterface, DRVMAINVMMDEV, Connector);
467 Console *pConsole = pDrv->pVMMDev->getParent();
468
469 pConsole->i_getDisplay()->i_handleUpdateMonitorPositions(cPositions, pPositions);
470
471 return VINF_SUCCESS;
472}
473
474DECLCALLBACK(int) vmmdevQueryVisibleRegion(PPDMIVMMDEVCONNECTOR pInterface, uint32_t *pcRects, PRTRECT paRects)
475{
476 PDRVMAINVMMDEV pDrv = RT_FROM_MEMBER(pInterface, DRVMAINVMMDEV, Connector);
477 Console *pConsole = pDrv->pVMMDev->getParent();
478
479 /* Forward to Display, which calls corresponding framebuffers. */
480 pConsole->i_getDisplay()->i_handleQueryVisibleRegion(pcRects, paRects);
481
482 return VINF_SUCCESS;
483}
484
485/**
486 * Request the statistics interval
487 *
488 * @returns VBox status code.
489 * @param pInterface Pointer to this interface.
490 * @param pulInterval Pointer to interval in seconds
491 * @thread The emulation thread.
492 */
493DECLCALLBACK(int) vmmdevQueryStatisticsInterval(PPDMIVMMDEVCONNECTOR pInterface, uint32_t *pulInterval)
494{
495 PDRVMAINVMMDEV pDrv = RT_FROM_MEMBER(pInterface, DRVMAINVMMDEV, Connector);
496 Console *pConsole = pDrv->pVMMDev->getParent();
497 ULONG val = 0;
498
499 if (!pulInterval)
500 return VERR_INVALID_POINTER;
501
502 /* store that information in IGuest */
503 Guest* guest = pConsole->i_getGuest();
504 AssertPtrReturn(guest, VERR_GENERAL_FAILURE);
505
506 guest->COMGETTER(StatisticsUpdateInterval)(&val);
507 *pulInterval = val;
508 return VINF_SUCCESS;
509}
510
511/**
512 * Query the current balloon size
513 *
514 * @returns VBox status code.
515 * @param pInterface Pointer to this interface.
516 * @param pcbBalloon Balloon size
517 * @thread The emulation thread.
518 */
519DECLCALLBACK(int) vmmdevQueryBalloonSize(PPDMIVMMDEVCONNECTOR pInterface, uint32_t *pcbBalloon)
520{
521 PDRVMAINVMMDEV pDrv = RT_FROM_MEMBER(pInterface, DRVMAINVMMDEV, Connector);
522 Console *pConsole = pDrv->pVMMDev->getParent();
523 ULONG val = 0;
524
525 if (!pcbBalloon)
526 return VERR_INVALID_POINTER;
527
528 /* store that information in IGuest */
529 Guest* guest = pConsole->i_getGuest();
530 AssertPtrReturn(guest, VERR_GENERAL_FAILURE);
531
532 guest->COMGETTER(MemoryBalloonSize)(&val);
533 *pcbBalloon = val;
534 return VINF_SUCCESS;
535}
536
537/**
538 * Query the current page fusion setting
539 *
540 * @returns VBox status code.
541 * @param pInterface Pointer to this interface.
542 * @param pfPageFusionEnabled Pointer to boolean
543 * @thread The emulation thread.
544 */
545DECLCALLBACK(int) vmmdevIsPageFusionEnabled(PPDMIVMMDEVCONNECTOR pInterface, bool *pfPageFusionEnabled)
546{
547 PDRVMAINVMMDEV pDrv = RT_FROM_MEMBER(pInterface, DRVMAINVMMDEV, Connector);
548 Console *pConsole = pDrv->pVMMDev->getParent();
549
550 if (!pfPageFusionEnabled)
551 return VERR_INVALID_POINTER;
552
553 /* store that information in IGuest */
554 Guest* guest = pConsole->i_getGuest();
555 AssertPtrReturn(guest, VERR_GENERAL_FAILURE);
556
557 *pfPageFusionEnabled = !!guest->i_isPageFusionEnabled();
558 return VINF_SUCCESS;
559}
560
561/**
562 * Report new guest statistics
563 *
564 * @returns VBox status code.
565 * @param pInterface Pointer to this interface.
566 * @param pGuestStats Guest statistics
567 * @thread The emulation thread.
568 */
569DECLCALLBACK(int) vmmdevReportStatistics(PPDMIVMMDEVCONNECTOR pInterface, VBoxGuestStatistics *pGuestStats)
570{
571 PDRVMAINVMMDEV pDrv = RT_FROM_MEMBER(pInterface, DRVMAINVMMDEV, Connector);
572 Console *pConsole = pDrv->pVMMDev->getParent();
573
574 AssertPtrReturn(pGuestStats, VERR_INVALID_POINTER);
575
576 /* store that information in IGuest */
577 Guest* guest = pConsole->i_getGuest();
578 AssertPtrReturn(guest, VERR_GENERAL_FAILURE);
579
580 if (pGuestStats->u32StatCaps & VBOX_GUEST_STAT_CPU_LOAD_IDLE)
581 guest->i_setStatistic(pGuestStats->u32CpuId, GUESTSTATTYPE_CPUIDLE, pGuestStats->u32CpuLoad_Idle);
582
583 if (pGuestStats->u32StatCaps & VBOX_GUEST_STAT_CPU_LOAD_KERNEL)
584 guest->i_setStatistic(pGuestStats->u32CpuId, GUESTSTATTYPE_CPUKERNEL, pGuestStats->u32CpuLoad_Kernel);
585
586 if (pGuestStats->u32StatCaps & VBOX_GUEST_STAT_CPU_LOAD_USER)
587 guest->i_setStatistic(pGuestStats->u32CpuId, GUESTSTATTYPE_CPUUSER, pGuestStats->u32CpuLoad_User);
588
589
590 /** @todo r=bird: Convert from 4KB to 1KB units?
591 * CollectorGuestHAL::i_getGuestMemLoad says it returns KB units to
592 * preCollect(). I might be wrong ofc, this is convoluted code... */
593 if (pGuestStats->u32StatCaps & VBOX_GUEST_STAT_PHYS_MEM_TOTAL)
594 guest->i_setStatistic(pGuestStats->u32CpuId, GUESTSTATTYPE_MEMTOTAL, pGuestStats->u32PhysMemTotal);
595
596 if (pGuestStats->u32StatCaps & VBOX_GUEST_STAT_PHYS_MEM_AVAIL)
597 guest->i_setStatistic(pGuestStats->u32CpuId, GUESTSTATTYPE_MEMFREE, pGuestStats->u32PhysMemAvail);
598
599 if (pGuestStats->u32StatCaps & VBOX_GUEST_STAT_PHYS_MEM_BALLOON)
600 guest->i_setStatistic(pGuestStats->u32CpuId, GUESTSTATTYPE_MEMBALLOON, pGuestStats->u32PhysMemBalloon);
601
602 if (pGuestStats->u32StatCaps & VBOX_GUEST_STAT_MEM_SYSTEM_CACHE)
603 guest->i_setStatistic(pGuestStats->u32CpuId, GUESTSTATTYPE_MEMCACHE, pGuestStats->u32MemSystemCache);
604
605 if (pGuestStats->u32StatCaps & VBOX_GUEST_STAT_PAGE_FILE_SIZE)
606 guest->i_setStatistic(pGuestStats->u32CpuId, GUESTSTATTYPE_PAGETOTAL, pGuestStats->u32PageFileSize);
607
608 return VINF_SUCCESS;
609}
610
611#ifdef VBOX_WITH_HGCM
612
613/* HGCM connector interface */
614
615static DECLCALLBACK(int) iface_hgcmConnect(PPDMIHGCMCONNECTOR pInterface, PVBOXHGCMCMD pCmd,
616 PHGCMSERVICELOCATION pServiceLocation,
617 uint32_t *pu32ClientID)
618{
619 Log9(("Enter\n"));
620
621 PDRVMAINVMMDEV pDrv = RT_FROM_MEMBER(pInterface, DRVMAINVMMDEV, HGCMConnector);
622
623 if ( !pServiceLocation
624 || ( pServiceLocation->type != VMMDevHGCMLoc_LocalHost
625 && pServiceLocation->type != VMMDevHGCMLoc_LocalHost_Existing))
626 {
627 return VERR_INVALID_PARAMETER;
628 }
629
630 /* Check if service name is a string terminated by zero*/
631 size_t cchInfo = 0;
632 if (RTStrNLenEx(pServiceLocation->u.host.achName, sizeof(pServiceLocation->u.host.achName), &cchInfo) != VINF_SUCCESS)
633 {
634 return VERR_INVALID_PARAMETER;
635 }
636
637 if (!pDrv->pVMMDev || !pDrv->pVMMDev->hgcmIsActive())
638 return VERR_INVALID_STATE;
639 return HGCMGuestConnect(pDrv->pHGCMPort, pCmd, pServiceLocation->u.host.achName, pu32ClientID);
640}
641
642static DECLCALLBACK(int) iface_hgcmDisconnect(PPDMIHGCMCONNECTOR pInterface, PVBOXHGCMCMD pCmd, uint32_t u32ClientID)
643{
644 Log9(("Enter\n"));
645
646 PDRVMAINVMMDEV pDrv = RT_FROM_MEMBER(pInterface, DRVMAINVMMDEV, HGCMConnector);
647
648 if (!pDrv->pVMMDev || !pDrv->pVMMDev->hgcmIsActive())
649 return VERR_INVALID_STATE;
650
651 return HGCMGuestDisconnect(pDrv->pHGCMPort, pCmd, u32ClientID);
652}
653
654static DECLCALLBACK(int) iface_hgcmCall(PPDMIHGCMCONNECTOR pInterface, PVBOXHGCMCMD pCmd, uint32_t u32ClientID,
655 uint32_t u32Function, uint32_t cParms, PVBOXHGCMSVCPARM paParms, uint64_t tsArrival)
656{
657 Log9(("Enter\n"));
658
659 PDRVMAINVMMDEV pDrv = RT_FROM_MEMBER(pInterface, DRVMAINVMMDEV, HGCMConnector);
660
661 if (!pDrv->pVMMDev || !pDrv->pVMMDev->hgcmIsActive())
662 return VERR_INVALID_STATE;
663
664 return HGCMGuestCall(pDrv->pHGCMPort, pCmd, u32ClientID, u32Function, cParms, paParms, tsArrival);
665}
666
667static DECLCALLBACK(void) iface_hgcmCancelled(PPDMIHGCMCONNECTOR pInterface, PVBOXHGCMCMD pCmd, uint32_t idClient)
668{
669 Log9(("Enter\n"));
670
671 PDRVMAINVMMDEV pDrv = RT_FROM_MEMBER(pInterface, DRVMAINVMMDEV, HGCMConnector);
672 if ( pDrv->pVMMDev
673 && pDrv->pVMMDev->hgcmIsActive())
674 return HGCMGuestCancelled(pDrv->pHGCMPort, pCmd, idClient);
675}
676
677/**
678 * Execute state save operation.
679 *
680 * @returns VBox status code.
681 * @param pDrvIns Driver instance of the driver which registered the data unit.
682 * @param pSSM SSM operation handle.
683 */
684static DECLCALLBACK(int) iface_hgcmSave(PPDMDRVINS pDrvIns, PSSMHANDLE pSSM)
685{
686 RT_NOREF(pDrvIns);
687 Log9(("Enter\n"));
688 return HGCMHostSaveState(pSSM);
689}
690
691
692/**
693 * Execute state load operation.
694 *
695 * @returns VBox status code.
696 * @param pDrvIns Driver instance of the driver which registered the data unit.
697 * @param pSSM SSM operation handle.
698 * @param uVersion Data layout version.
699 * @param uPass The data pass.
700 */
701static DECLCALLBACK(int) iface_hgcmLoad(PPDMDRVINS pDrvIns, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass)
702{
703 RT_NOREF(pDrvIns);
704 LogFlowFunc(("Enter\n"));
705
706 if ( uVersion != HGCM_SAVED_STATE_VERSION
707 && uVersion != HGCM_SAVED_STATE_VERSION_V2)
708 return VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION;
709 Assert(uPass == SSM_PASS_FINAL); NOREF(uPass);
710
711 return HGCMHostLoadState(pSSM, uVersion);
712}
713
714int VMMDev::hgcmLoadService(const char *pszServiceLibrary, const char *pszServiceName)
715{
716 if (!hgcmIsActive())
717 return VERR_INVALID_STATE;
718
719 /** @todo Construct all the services in the VMMDev::drvConstruct()!! */
720 Assert( (mpDrv && mpDrv->pHGCMPort)
721 || !strcmp(pszServiceLibrary, "VBoxHostChannel")
722 || !strcmp(pszServiceLibrary, "VBoxSharedClipboard")
723 || !strcmp(pszServiceLibrary, "VBoxDragAndDropSvc")
724 || !strcmp(pszServiceLibrary, "VBoxGuestPropSvc")
725 || !strcmp(pszServiceLibrary, "VBoxSharedCrOpenGL")
726 );
727 Console::SafeVMPtrQuiet ptrVM(mParent);
728 return HGCMHostLoad(pszServiceLibrary, pszServiceName, ptrVM.rawUVM(), mpDrv ? mpDrv->pHGCMPort : NULL);
729}
730
731int VMMDev::hgcmHostCall(const char *pszServiceName, uint32_t u32Function,
732 uint32_t cParms, PVBOXHGCMSVCPARM paParms)
733{
734 if (!hgcmIsActive())
735 return VERR_INVALID_STATE;
736 return HGCMHostCall(pszServiceName, u32Function, cParms, paParms);
737}
738
739/**
740 * Used by Console::i_powerDown to shut down the services before the VM is destroyed.
741 */
742void VMMDev::hgcmShutdown(bool fUvmIsInvalid /*= false*/)
743{
744#ifdef VBOX_WITH_GUEST_PROPS
745 if (mpDrv && mpDrv->hHgcmSvcExtGstProps)
746 {
747 HGCMHostUnregisterServiceExtension(mpDrv->hHgcmSvcExtGstProps);
748 mpDrv->hHgcmSvcExtGstProps = NULL;
749 }
750#endif
751
752#ifdef VBOX_WITH_GUEST_CONTROL
753 if (mpDrv && mpDrv->hHgcmSvcExtGstCtrl)
754 {
755 HGCMHostUnregisterServiceExtension(mpDrv->hHgcmSvcExtGstCtrl);
756 mpDrv->hHgcmSvcExtGstCtrl = NULL;
757 }
758#endif
759
760 if (ASMAtomicCmpXchgBool(&m_fHGCMActive, false, true))
761 HGCMHostShutdown(fUvmIsInvalid);
762}
763
764#endif /* HGCM */
765
766
767/**
768 * @interface_method_impl{PDMIBASE,pfnQueryInterface}
769 */
770DECLCALLBACK(void *) VMMDev::drvQueryInterface(PPDMIBASE pInterface, const char *pszIID)
771{
772 PPDMDRVINS pDrvIns = PDMIBASE_2_PDMDRV(pInterface);
773 PDRVMAINVMMDEV pDrv = PDMINS_2_DATA(pDrvIns, PDRVMAINVMMDEV);
774
775 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pDrvIns->IBase);
776 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIVMMDEVCONNECTOR, &pDrv->Connector);
777#ifdef VBOX_WITH_HGCM
778 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIHGCMCONNECTOR, &pDrv->HGCMConnector);
779#endif
780 return NULL;
781}
782
783/**
784 * @interface_method_impl{PDMDRVREG,pfnSuspend}
785 */
786/*static*/ DECLCALLBACK(void) VMMDev::drvSuspend(PPDMDRVINS pDrvIns)
787{
788 RT_NOREF(pDrvIns);
789#ifdef VBOX_WITH_HGCM
790 HGCMBroadcastEvent(HGCMNOTIFYEVENT_SUSPEND);
791#endif
792}
793
794/**
795 * @interface_method_impl{PDMDRVREG,pfnResume}
796 */
797/*static*/ DECLCALLBACK(void) VMMDev::drvResume(PPDMDRVINS pDrvIns)
798{
799 RT_NOREF(pDrvIns);
800#ifdef VBOX_WITH_HGCM
801 HGCMBroadcastEvent(HGCMNOTIFYEVENT_RESUME);
802#endif
803}
804
805/**
806 * @interface_method_impl{PDMDRVREG,pfnPowerOff}
807 */
808/*static*/ DECLCALLBACK(void) VMMDev::drvPowerOff(PPDMDRVINS pDrvIns)
809{
810 RT_NOREF(pDrvIns);
811#ifdef VBOX_WITH_HGCM
812 HGCMBroadcastEvent(HGCMNOTIFYEVENT_POWER_ON);
813#endif
814}
815
816/**
817 * @interface_method_impl{PDMDRVREG,pfnPowerOn}
818 */
819/*static*/ DECLCALLBACK(void) VMMDev::drvPowerOn(PPDMDRVINS pDrvIns)
820{
821 RT_NOREF(pDrvIns);
822#ifdef VBOX_WITH_HGCM
823 HGCMBroadcastEvent(HGCMNOTIFYEVENT_POWER_ON);
824#endif
825}
826
827/**
828 * @interface_method_impl{PDMDRVREG,pfnReset}
829 */
830DECLCALLBACK(void) VMMDev::drvReset(PPDMDRVINS pDrvIns)
831{
832 RT_NOREF(pDrvIns);
833 LogFlow(("VMMDev::drvReset: iInstance=%d\n", pDrvIns->iInstance));
834#ifdef VBOX_WITH_HGCM
835 HGCMHostReset(false /*fForShutdown*/);
836#endif
837}
838
839/**
840 * @interface_method_impl{PDMDRVREG,pfnDestruct}
841 */
842DECLCALLBACK(void) VMMDev::drvDestruct(PPDMDRVINS pDrvIns)
843{
844 PDMDRV_CHECK_VERSIONS_RETURN_VOID(pDrvIns);
845 PDRVMAINVMMDEV pThis = PDMINS_2_DATA(pDrvIns, PDRVMAINVMMDEV);
846 LogFlow(("VMMDev::drvDestruct: iInstance=%d\n", pDrvIns->iInstance));
847
848#ifdef VBOX_WITH_GUEST_PROPS
849 if (pThis->hHgcmSvcExtGstProps)
850 {
851 HGCMHostUnregisterServiceExtension(pThis->hHgcmSvcExtGstProps);
852 pThis->hHgcmSvcExtGstProps = NULL;
853 }
854#endif
855
856#ifdef VBOX_WITH_GUEST_CONTROL
857 if (pThis->hHgcmSvcExtGstCtrl)
858 {
859 HGCMHostUnregisterServiceExtension(pThis->hHgcmSvcExtGstCtrl);
860 pThis->hHgcmSvcExtGstCtrl = NULL;
861 }
862#endif
863
864 if (pThis->pVMMDev)
865 {
866#ifdef VBOX_WITH_HGCM
867 /* When VM construction goes wrong, we prefer shutting down HGCM here
868 while pUVM is still valid, rather than in ~VMMDev. */
869 if (ASMAtomicCmpXchgBool(&pThis->pVMMDev->m_fHGCMActive, false, true))
870 HGCMHostShutdown();
871#endif
872 pThis->pVMMDev->mpDrv = NULL;
873 }
874}
875
876#ifdef VBOX_WITH_GUEST_PROPS
877
878/**
879 * Set an array of guest properties
880 */
881void VMMDev::i_guestPropSetMultiple(void *names, void *values, void *timestamps, void *flags)
882{
883 VBOXHGCMSVCPARM parms[4];
884
885 parms[0].type = VBOX_HGCM_SVC_PARM_PTR;
886 parms[0].u.pointer.addr = names;
887 parms[0].u.pointer.size = 0; /* We don't actually care. */
888 parms[1].type = VBOX_HGCM_SVC_PARM_PTR;
889 parms[1].u.pointer.addr = values;
890 parms[1].u.pointer.size = 0; /* We don't actually care. */
891 parms[2].type = VBOX_HGCM_SVC_PARM_PTR;
892 parms[2].u.pointer.addr = timestamps;
893 parms[2].u.pointer.size = 0; /* We don't actually care. */
894 parms[3].type = VBOX_HGCM_SVC_PARM_PTR;
895 parms[3].u.pointer.addr = flags;
896 parms[3].u.pointer.size = 0; /* We don't actually care. */
897
898 hgcmHostCall("VBoxGuestPropSvc", GUEST_PROP_FN_HOST_SET_PROPS, 4, &parms[0]);
899}
900
901/**
902 * Set a single guest property
903 */
904void VMMDev::i_guestPropSet(const char *pszName, const char *pszValue, const char *pszFlags)
905{
906 VBOXHGCMSVCPARM parms[4];
907
908 AssertPtrReturnVoid(pszName);
909 AssertPtrReturnVoid(pszValue);
910 AssertPtrReturnVoid(pszFlags);
911 parms[0].type = VBOX_HGCM_SVC_PARM_PTR;
912 parms[0].u.pointer.addr = (void *)pszName;
913 parms[0].u.pointer.size = (uint32_t)strlen(pszName) + 1;
914 parms[1].type = VBOX_HGCM_SVC_PARM_PTR;
915 parms[1].u.pointer.addr = (void *)pszValue;
916 parms[1].u.pointer.size = (uint32_t)strlen(pszValue) + 1;
917 parms[2].type = VBOX_HGCM_SVC_PARM_PTR;
918 parms[2].u.pointer.addr = (void *)pszFlags;
919 parms[2].u.pointer.size = (uint32_t)strlen(pszFlags) + 1;
920 hgcmHostCall("VBoxGuestPropSvc", GUEST_PROP_FN_HOST_SET_PROP, 3, &parms[0]);
921}
922
923/**
924 * Set the global flags value by calling the service
925 * @returns the status returned by the call to the service
926 *
927 * @param pTable the service instance handle
928 * @param eFlags the flags to set
929 */
930int VMMDev::i_guestPropSetGlobalPropertyFlags(uint32_t fFlags)
931{
932 VBOXHGCMSVCPARM parm;
933 HGCMSvcSetU32(&parm, fFlags);
934 int rc = hgcmHostCall("VBoxGuestPropSvc", GUEST_PROP_FN_HOST_SET_GLOBAL_FLAGS, 1, &parm);
935 if (RT_FAILURE(rc))
936 {
937 char szFlags[GUEST_PROP_MAX_FLAGS_LEN];
938 if (RT_FAILURE(GuestPropWriteFlags(fFlags, szFlags)))
939 Log(("Failed to set the global flags.\n"));
940 else
941 Log(("Failed to set the global flags \"%s\".\n", szFlags));
942 }
943 return rc;
944}
945
946
947/**
948 * Set up the Guest Property service, populate it with properties read from
949 * the machine XML and set a couple of initial properties.
950 */
951int VMMDev::i_guestPropLoadAndConfigure()
952{
953 Assert(mpDrv);
954 ComObjPtr<Console> ptrConsole = this->mParent;
955 AssertReturn(ptrConsole.isNotNull(), VERR_INVALID_POINTER);
956
957 /*
958 * Load the service
959 */
960 int rc = hgcmLoadService("VBoxGuestPropSvc", "VBoxGuestPropSvc");
961 if (RT_FAILURE(rc))
962 {
963 LogRel(("VBoxGuestPropSvc is not available. rc = %Rrc\n", rc));
964 return VINF_SUCCESS; /* That is not a fatal failure. */
965 }
966
967 /*
968 * Pull over the properties from the server.
969 */
970 SafeArray<BSTR> namesOut;
971 SafeArray<BSTR> valuesOut;
972 SafeArray<LONG64> timestampsOut;
973 SafeArray<BSTR> flagsOut;
974 HRESULT hrc = ptrConsole->i_pullGuestProperties(ComSafeArrayAsOutParam(namesOut),
975 ComSafeArrayAsOutParam(valuesOut),
976 ComSafeArrayAsOutParam(timestampsOut),
977 ComSafeArrayAsOutParam(flagsOut));
978 AssertLogRelMsgReturn(SUCCEEDED(hrc), ("hrc=%Rhrc\n", hrc), VERR_MAIN_CONFIG_CONSTRUCTOR_COM_ERROR);
979 size_t const cProps = namesOut.size();
980 size_t const cAlloc = cProps + 1;
981 AssertLogRelReturn(valuesOut.size() == cProps, VERR_INTERNAL_ERROR_2);
982 AssertLogRelReturn(timestampsOut.size() == cProps, VERR_INTERNAL_ERROR_3);
983 AssertLogRelReturn(flagsOut.size() == cProps, VERR_INTERNAL_ERROR_4);
984
985 char szEmpty[] = "";
986 char **papszNames = (char **)RTMemTmpAllocZ(sizeof(char *) * cAlloc);
987 char **papszValues = (char **)RTMemTmpAllocZ(sizeof(char *) * cAlloc);
988 LONG64 *pai64Timestamps = (LONG64 *)RTMemTmpAllocZ(sizeof(LONG64) * cAlloc);
989 char **papszFlags = (char **)RTMemTmpAllocZ(sizeof(char *) * cAlloc);
990 if (papszNames && papszValues && pai64Timestamps && papszFlags)
991 {
992 for (unsigned i = 0; RT_SUCCESS(rc) && i < cProps; ++i)
993 {
994 AssertPtrBreakStmt(namesOut[i], rc = VERR_INVALID_PARAMETER);
995 rc = RTUtf16ToUtf8(namesOut[i], &papszNames[i]);
996 if (RT_FAILURE(rc))
997 break;
998 if (valuesOut[i])
999 rc = RTUtf16ToUtf8(valuesOut[i], &papszValues[i]);
1000 else
1001 papszValues[i] = szEmpty;
1002 if (RT_FAILURE(rc))
1003 break;
1004 pai64Timestamps[i] = timestampsOut[i];
1005 if (flagsOut[i])
1006 rc = RTUtf16ToUtf8(flagsOut[i], &papszFlags[i]);
1007 else
1008 papszFlags[i] = szEmpty;
1009 }
1010 if (RT_SUCCESS(rc))
1011 i_guestPropSetMultiple((void *)papszNames, (void *)papszValues, (void *)pai64Timestamps, (void *)papszFlags);
1012 for (unsigned i = 0; i < cProps; ++i)
1013 {
1014 RTStrFree(papszNames[i]);
1015 if (valuesOut[i])
1016 RTStrFree(papszValues[i]);
1017 if (flagsOut[i])
1018 RTStrFree(papszFlags[i]);
1019 }
1020 }
1021 else
1022 rc = VERR_NO_MEMORY;
1023 RTMemTmpFree(papszNames);
1024 RTMemTmpFree(papszValues);
1025 RTMemTmpFree(pai64Timestamps);
1026 RTMemTmpFree(papszFlags);
1027 AssertRCReturn(rc, rc);
1028
1029 /*
1030 * Register the host notification callback
1031 */
1032 HGCMHostRegisterServiceExtension(&mpDrv->hHgcmSvcExtGstProps, "VBoxGuestPropSvc", Console::i_doGuestPropNotification, ptrConsole.m_p);
1033
1034# ifdef VBOX_WITH_GUEST_PROPS_RDONLY_GUEST
1035 rc = i_guestPropSetGlobalPropertyFlags(GUEST_PROP_F_RDONLYGUEST);
1036 AssertRCReturn(rc, rc);
1037# endif
1038
1039 Log(("Set VBoxGuestPropSvc property store\n"));
1040 return VINF_SUCCESS;
1041}
1042
1043#endif /* VBOX_WITH_GUEST_PROPS */
1044
1045/**
1046 * @interface_method_impl{PDMDRVREG,pfnConstruct}
1047 */
1048DECLCALLBACK(int) VMMDev::drvConstruct(PPDMDRVINS pDrvIns, PCFGMNODE pCfgHandle, uint32_t fFlags)
1049{
1050 RT_NOREF(fFlags);
1051 PDMDRV_CHECK_VERSIONS_RETURN(pDrvIns);
1052 PDRVMAINVMMDEV pThis = PDMINS_2_DATA(pDrvIns, PDRVMAINVMMDEV);
1053 LogFlow(("Keyboard::drvConstruct: iInstance=%d\n", pDrvIns->iInstance));
1054
1055 /*
1056 * Validate configuration.
1057 */
1058 if (!CFGMR3AreValuesValid(pCfgHandle, "Object\0"))
1059 return VERR_PDM_DRVINS_UNKNOWN_CFG_VALUES;
1060 AssertMsgReturn(PDMDrvHlpNoAttach(pDrvIns) == VERR_PDM_NO_ATTACHED_DRIVER,
1061 ("Configuration error: Not possible to attach anything to this driver!\n"),
1062 VERR_PDM_DRVINS_NO_ATTACH);
1063
1064 /*
1065 * IBase.
1066 */
1067 pDrvIns->IBase.pfnQueryInterface = VMMDev::drvQueryInterface;
1068
1069 pThis->Connector.pfnUpdateGuestStatus = vmmdevUpdateGuestStatus;
1070 pThis->Connector.pfnUpdateGuestUserState = vmmdevUpdateGuestUserState;
1071 pThis->Connector.pfnUpdateGuestInfo = vmmdevUpdateGuestInfo;
1072 pThis->Connector.pfnUpdateGuestInfo2 = vmmdevUpdateGuestInfo2;
1073 pThis->Connector.pfnUpdateGuestCapabilities = vmmdevUpdateGuestCapabilities;
1074 pThis->Connector.pfnUpdateMouseCapabilities = vmmdevUpdateMouseCapabilities;
1075 pThis->Connector.pfnUpdatePointerShape = vmmdevUpdatePointerShape;
1076 pThis->Connector.pfnVideoAccelEnable = iface_VideoAccelEnable;
1077 pThis->Connector.pfnVideoAccelFlush = iface_VideoAccelFlush;
1078 pThis->Connector.pfnVideoModeSupported = vmmdevVideoModeSupported;
1079 pThis->Connector.pfnGetHeightReduction = vmmdevGetHeightReduction;
1080 pThis->Connector.pfnSetCredentialsJudgementResult = vmmdevSetCredentialsJudgementResult;
1081 pThis->Connector.pfnSetVisibleRegion = vmmdevSetVisibleRegion;
1082 pThis->Connector.pfnUpdateMonitorPositions = vmmdevUpdateMonitorPositions;
1083 pThis->Connector.pfnQueryVisibleRegion = vmmdevQueryVisibleRegion;
1084 pThis->Connector.pfnReportStatistics = vmmdevReportStatistics;
1085 pThis->Connector.pfnQueryStatisticsInterval = vmmdevQueryStatisticsInterval;
1086 pThis->Connector.pfnQueryBalloonSize = vmmdevQueryBalloonSize;
1087 pThis->Connector.pfnIsPageFusionEnabled = vmmdevIsPageFusionEnabled;
1088
1089#ifdef VBOX_WITH_HGCM
1090 pThis->HGCMConnector.pfnConnect = iface_hgcmConnect;
1091 pThis->HGCMConnector.pfnDisconnect = iface_hgcmDisconnect;
1092 pThis->HGCMConnector.pfnCall = iface_hgcmCall;
1093 pThis->HGCMConnector.pfnCancelled = iface_hgcmCancelled;
1094#endif
1095
1096 /*
1097 * Get the IVMMDevPort interface of the above driver/device.
1098 */
1099 pThis->pUpPort = PDMIBASE_QUERY_INTERFACE(pDrvIns->pUpBase, PDMIVMMDEVPORT);
1100 AssertMsgReturn(pThis->pUpPort, ("Configuration error: No VMMDev port interface above!\n"), VERR_PDM_MISSING_INTERFACE_ABOVE);
1101
1102#ifdef VBOX_WITH_HGCM
1103 pThis->pHGCMPort = PDMIBASE_QUERY_INTERFACE(pDrvIns->pUpBase, PDMIHGCMPORT);
1104 AssertMsgReturn(pThis->pHGCMPort, ("Configuration error: No HGCM port interface above!\n"), VERR_PDM_MISSING_INTERFACE_ABOVE);
1105#endif
1106
1107 /*
1108 * Get the Console object pointer and update the mpDrv member.
1109 */
1110 void *pv;
1111 int rc = CFGMR3QueryPtr(pCfgHandle, "Object", &pv);
1112 if (RT_FAILURE(rc))
1113 {
1114 AssertMsgFailed(("Configuration error: No/bad \"Object\" value! rc=%Rrc\n", rc));
1115 return rc;
1116 }
1117
1118 pThis->pVMMDev = (VMMDev*)pv; /** @todo Check this cast! */
1119 pThis->pVMMDev->mpDrv = pThis;
1120
1121#ifdef VBOX_WITH_HGCM
1122 /*
1123 * Load & configure the shared folders service.
1124 */
1125 rc = pThis->pVMMDev->hgcmLoadService(VBOXSHAREDFOLDERS_DLL, "VBoxSharedFolders");
1126 pThis->pVMMDev->fSharedFolderActive = RT_SUCCESS(rc);
1127 if (RT_SUCCESS(rc))
1128 {
1129 PPDMLED pLed;
1130 PPDMILEDPORTS pLedPort;
1131
1132 LogRel(("Shared Folders service loaded\n"));
1133 pLedPort = PDMIBASE_QUERY_INTERFACE(pDrvIns->pUpBase, PDMILEDPORTS);
1134 AssertMsgReturn(pLedPort, ("Configuration error: No LED port interface above!\n"), VERR_PDM_MISSING_INTERFACE_ABOVE);
1135 rc = pLedPort->pfnQueryStatusLed(pLedPort, 0, &pLed);
1136 if (RT_SUCCESS(rc) && pLed)
1137 {
1138 VBOXHGCMSVCPARM parm;
1139
1140 parm.type = VBOX_HGCM_SVC_PARM_PTR;
1141 parm.u.pointer.addr = pLed;
1142 parm.u.pointer.size = sizeof(*pLed);
1143
1144 rc = HGCMHostCall("VBoxSharedFolders", SHFL_FN_SET_STATUS_LED, 1, &parm);
1145 }
1146 else
1147 AssertMsgFailed(("pfnQueryStatusLed failed with %Rrc (pLed=%x)\n", rc, pLed));
1148 }
1149 else
1150 LogRel(("Failed to load Shared Folders service %Rrc\n", rc));
1151
1152
1153 /*
1154 * Load and configure the guest control service.
1155 */
1156# ifdef VBOX_WITH_GUEST_CONTROL
1157 rc = pThis->pVMMDev->hgcmLoadService("VBoxGuestControlSvc", "VBoxGuestControlSvc");
1158 if (RT_SUCCESS(rc))
1159 {
1160 rc = HGCMHostRegisterServiceExtension(&pThis->hHgcmSvcExtGstCtrl, "VBoxGuestControlSvc",
1161 &Guest::i_notifyCtrlDispatcher,
1162 pThis->pVMMDev->mParent->i_getGuest());
1163 if (RT_SUCCESS(rc))
1164 LogRel(("Guest Control service loaded\n"));
1165 else
1166 LogRel(("Warning: Cannot register VBoxGuestControlSvc extension! rc=%Rrc\n", rc));
1167 }
1168 else
1169 LogRel(("Warning!: Failed to load the Guest Control Service! %Rrc\n", rc));
1170# endif /* VBOX_WITH_GUEST_CONTROL */
1171
1172
1173 /*
1174 * Load and configure the guest properties service.
1175 */
1176# ifdef VBOX_WITH_GUEST_PROPS
1177 rc = pThis->pVMMDev->i_guestPropLoadAndConfigure();
1178 AssertLogRelRCReturn(rc, rc);
1179# endif
1180
1181
1182 /*
1183 * The HGCM saved state.
1184 */
1185 rc = PDMDrvHlpSSMRegisterEx(pDrvIns, HGCM_SAVED_STATE_VERSION, 4096 /* bad guess */,
1186 NULL, NULL, NULL,
1187 NULL, iface_hgcmSave, NULL,
1188 NULL, iface_hgcmLoad, NULL);
1189 if (RT_FAILURE(rc))
1190 return rc;
1191
1192#endif /* VBOX_WITH_HGCM */
1193
1194 return VINF_SUCCESS;
1195}
1196
1197
1198/**
1199 * VMMDevice driver registration record.
1200 */
1201const PDMDRVREG VMMDev::DrvReg =
1202{
1203 /* u32Version */
1204 PDM_DRVREG_VERSION,
1205 /* szName */
1206 "HGCM",
1207 /* szRCMod */
1208 "",
1209 /* szR0Mod */
1210 "",
1211 /* pszDescription */
1212 "Main VMMDev driver (Main as in the API).",
1213 /* fFlags */
1214 PDM_DRVREG_FLAGS_HOST_BITS_DEFAULT,
1215 /* fClass. */
1216 PDM_DRVREG_CLASS_VMMDEV,
1217 /* cMaxInstances */
1218 ~0U,
1219 /* cbInstance */
1220 sizeof(DRVMAINVMMDEV),
1221 /* pfnConstruct */
1222 VMMDev::drvConstruct,
1223 /* pfnDestruct */
1224 VMMDev::drvDestruct,
1225 /* pfnRelocate */
1226 NULL,
1227 /* pfnIOCtl */
1228 NULL,
1229 /* pfnPowerOn */
1230 VMMDev::drvPowerOn,
1231 /* pfnReset */
1232 VMMDev::drvReset,
1233 /* pfnSuspend */
1234 VMMDev::drvSuspend,
1235 /* pfnResume */
1236 VMMDev::drvResume,
1237 /* pfnAttach */
1238 NULL,
1239 /* pfnDetach */
1240 NULL,
1241 /* pfnPowerOff */
1242 VMMDev::drvPowerOff,
1243 /* pfnSoftReset */
1244 NULL,
1245 /* u32EndVersion */
1246 PDM_DRVREG_VERSION
1247};
1248/* 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