VirtualBox

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

Last change on this file was 99775, checked in by vboxsync, 12 months ago

*: Mark functions as static if not used outside of a given compilation unit. Enables the compiler to optimize inlining, reduces the symbol tables, exposes unused functions and in some rare cases exposes mismtaches between function declarations and definitions, but most importantly reduces the number of parfait reports for the extern-function-no-forward-declaration category. This should not result in any functional changes, bugref:3409

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

© 2023 Oracle
ContactPrivacy policyTerms of Use