VirtualBox

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

Last change on this file since 98273 was 98103, checked in by vboxsync, 23 months ago

Copyright year updates by scm.

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