NTSTATUS vboxWddmRegQueryDisplaySettingsKeyName(PVBOXMP_DEVEXT pDevExt, D3DDDI_VIDEO_PRESENT_SOURCE_ID VidPnSourceId, ULONG cbBuf, PWCHAR pBuf, PULONG pcbResult) { NTSTATUS Status = STATUS_SUCCESS; PWCHAR pSuffix; bool bFallback = false; const WCHAR* pKeyPrefix; UINT cbKeyPrefix; UNICODE_STRING* pVGuid = vboxWddmVGuidGet(pDevExt); Assert(pVGuid); if (!pVGuid) return STATUS_UNSUCCESSFUL; vboxWinVersion_t ver = VBoxQueryWinVersion(); if (ver == WINVISTA) { pKeyPrefix = VBOXWDDM_REG_DISPLAYSETTINGSKEY_PREFIX_VISTA; cbKeyPrefix = sizeof (VBOXWDDM_REG_DISPLAYSETTINGSKEY_PREFIX_VISTA); } else { Assert(ver == WIN7); pKeyPrefix = VBOXWDDM_REG_DISPLAYSETTINGSKEY_PREFIX_WIN7; cbKeyPrefix = sizeof (VBOXWDDM_REG_DISPLAYSETTINGSKEY_PREFIX_WIN7); } ULONG cbResult = cbKeyPrefix + pVGuid->Length + 2 + 8; // L"\\" + "XXXX" if (cbBuf >= cbResult) { wcscpy(pBuf, pKeyPrefix); pSuffix = pBuf + (cbKeyPrefix-2)/2; memcpy(pSuffix, pVGuid->Buffer, pVGuid->Length); pSuffix += pVGuid->Length/2; pSuffix[0] = L'\\'; pSuffix += 1; swprintf(pSuffix, L"%04d", VidPnSourceId); } else { Status = STATUS_BUFFER_TOO_SMALL; } *pcbResult = cbResult; return Status; }
/* Video Miniport Driver entry point */ ULONG DriverEntry(IN PVOID Context1, IN PVOID Context2) { PAGED_CODE(); int irc = RTR0Init(0); if (RT_FAILURE(irc)) { LogRel(("VBoxMP::failed to init IPRT (rc=%#x)", irc)); return ERROR_INVALID_FUNCTION; } LOGF_ENTER(); LOGREL(("VBox XPDM Driver for Windows version %d.%d.%dr%d, %d bit; Built %s %s", VBOX_VERSION_MAJOR, VBOX_VERSION_MINOR, VBOX_VERSION_BUILD, VBOX_SVN_REV, (sizeof (void*) << 3), __DATE__, __TIME__)); VIDEO_HW_INITIALIZATION_DATA vhwData; /*Zero the structure*/ VideoPortZeroMemory(&vhwData, sizeof(vhwData)); /*Required driver callbacks*/ vhwData.HwFindAdapter = VBoxDrvFindAdapter; vhwData.HwInitialize = VBoxDrvInitialize; vhwData.HwStartIO = VBoxDrvStartIO; vhwData.HwSetPowerState = VBoxDrvSetPowerState; vhwData.HwGetPowerState = VBoxDrvGetPowerState; vhwData.HwGetVideoChildDescriptor = VBoxDrvGetVideoChildDescriptor; /*Optional callbacks*/ vhwData.HwResetHw = VBoxDrvResetHW; #ifdef VBOX_WITH_VIDEOHWACCEL vhwData.HwInterrupt = VBoxDrvInterrupt; #endif /*Our private storage space*/ vhwData.HwDeviceExtensionSize = sizeof(VBOXMP_DEVEXT); /*Claim legacy VGA resource ranges*/ vhwData.HwLegacyResourceList = g_aVBoxLegacyVGAResources; vhwData.HwLegacyResourceCount = RT_ELEMENTS(g_aVBoxLegacyVGAResources); /*Size of this structure changes between windows/ddk versions, *so we query current version and report the expected size *to allow our driver to be loaded. */ switch (VBoxQueryWinVersion(NULL)) { case WINVERSION_NT4: LOG(("WINVERSION_NT4")); vhwData.HwInitDataSize = SIZE_OF_NT4_VIDEO_HW_INITIALIZATION_DATA; break; case WINVERSION_2K: LOG(("WINVERSION_2K")); vhwData.HwInitDataSize = SIZE_OF_W2K_VIDEO_HW_INITIALIZATION_DATA; break; default: vhwData.HwInitDataSize = sizeof(VIDEO_HW_INITIALIZATION_DATA); break; } /*Even though msdn claims that this field is ignored and should remain zero-initialized, windows NT4 SP0 dies without the following line. */ vhwData.AdapterInterfaceType = PCIBus; /*Allocate system resources*/ ULONG rc = VideoPortInitialize(Context1, Context2, &vhwData, NULL); if (rc != NO_ERROR) LOG(("VideoPortInitialize failed with %#x", rc)); LOGF_LEAVE(); return rc; }
/* Checks if we have a device supported by our driver and initialize * our driver/card specific information. * In particular we obtain VM monitors configuration and configure related structures. */ static VP_STATUS VBoxDrvFindAdapter(IN PVOID HwDeviceExtension, IN PVOID HwContext, IN PWSTR ArgumentString, IN OUT PVIDEO_PORT_CONFIG_INFO ConfigInfo, OUT PUCHAR Again) { RT_NOREF(HwContext, ArgumentString, Again); PVBOXMP_DEVEXT pExt = (PVBOXMP_DEVEXT) HwDeviceExtension; VP_STATUS rc; USHORT DispiId; ULONG cbVRAM = VBE_DISPI_TOTAL_VIDEO_MEMORY_BYTES; PHYSICAL_ADDRESS phVRAM = {0}; ULONG ulApertureSize = 0; PAGED_CODE(); LOGF_ENTER(); /* Init video port api */ VBoxSetupVideoPortAPI(pExt, ConfigInfo); VideoPortWritePortUshort((PUSHORT)VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_ID); VideoPortWritePortUshort((PUSHORT)VBE_DISPI_IOPORT_DATA, VBE_DISPI_ID2); DispiId = VideoPortReadPortUshort((PUSHORT)VBE_DISPI_IOPORT_DATA); if (DispiId != VBE_DISPI_ID2) { WARN(("VBE card not found, returning ERROR_DEV_NOT_EXIST")); return ERROR_DEV_NOT_EXIST; } LOG(("found the VBE card")); /* * Query the adapter's memory size. It's a bit of a hack, we just read * an ULONG from the data port without setting an index before. */ cbVRAM = VideoPortReadPortUlong((PULONG)VBE_DISPI_IOPORT_DATA); /* Write hw information to registry, so that it's visible in windows property dialog */ rc = VideoPortSetRegistryParameters(pExt, L"HardwareInformation.ChipType", g_wszVBoxChipType, sizeof(g_wszVBoxChipType)); VBOXMP_WARN_VPS(rc); rc = VideoPortSetRegistryParameters(pExt, L"HardwareInformation.DacType", g_wszVBoxDACType, sizeof(g_wszVBoxDACType)); VBOXMP_WARN_VPS(rc); rc = VideoPortSetRegistryParameters(pExt, L"HardwareInformation.MemorySize", &cbVRAM, sizeof(ULONG)); VBOXMP_WARN_VPS(rc); rc = VideoPortSetRegistryParameters(pExt, L"HardwareInformation.AdapterString", g_wszVBoxAdapterString, sizeof(g_wszVBoxAdapterString)); VBOXMP_WARN_VPS(rc); rc = VideoPortSetRegistryParameters(pExt, L"HardwareInformation.BiosString", g_wszVBoxBiosString, sizeof(g_wszVBoxBiosString)); VBOXMP_WARN_VPS(rc); /* Call VideoPortGetAccessRanges to ensure interrupt info in ConfigInfo gets set up * and to get LFB aperture data. */ { VIDEO_ACCESS_RANGE tmpRanges[4]; ULONG slot = 0; VideoPortZeroMemory(tmpRanges, sizeof(tmpRanges)); if (VBoxQueryWinVersion(NULL) == WINVERSION_NT4) { /* NT crashes if either of 'vendorId, 'deviceId' or 'slot' parameters is NULL, * and needs PCI ids for a successful VideoPortGetAccessRanges call. */ ULONG vendorId = 0x80EE; ULONG deviceId = 0xBEEF; rc = VideoPortGetAccessRanges(pExt, 0, NULL, RT_ELEMENTS(tmpRanges), tmpRanges, &vendorId, &deviceId, &slot); } else { rc = VideoPortGetAccessRanges(pExt, 0, NULL, RT_ELEMENTS(tmpRanges), tmpRanges, NULL, NULL, &slot); } VBOXMP_WARN_VPS(rc); if (rc != NO_ERROR) { return rc; } /* The first non-IO range is the framebuffer. We require that information. */ for (int iRange = 0; iRange < RT_ELEMENTS(tmpRanges); ++iRange) { if (!tmpRanges[iRange].RangeInIoSpace) { phVRAM = tmpRanges[iRange].RangeStart; ulApertureSize = tmpRanges[iRange].RangeLength; break; } } } /* Initialize VBoxGuest library, which is used for requests which go through VMMDev. */ rc = VbglR0InitClient(); VBOXMP_WARN_VPS(rc); /* Preinitialize the primary extension. */ pExt->pNext = NULL; pExt->pPrimary = pExt; pExt->iDevice = 0; pExt->ulFrameBufferOffset = 0; pExt->ulFrameBufferSize = 0; pExt->u.primary.ulVbvaEnabled = 0; VideoPortZeroMemory(&pExt->areaDisplay, sizeof(HGSMIAREA)); /* Guest supports only HGSMI, the old VBVA via VMMDev is not supported. Old * code will be ifdef'ed and later removed. * The host will however support both old and new interface to keep compatibility * with old guest additions. */ VBoxSetupDisplaysHGSMI(&pExt->u.primary.commonInfo, phVRAM, ulApertureSize, cbVRAM, 0); /* Check if the chip restricts horizontal resolution or not. * Must be done after VBoxSetupDisplaysHGSMI, because it initializes the common structure. */ VideoPortWritePortUshort((PUSHORT)VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_ID); VideoPortWritePortUshort((PUSHORT)VBE_DISPI_IOPORT_DATA, VBE_DISPI_ID_ANYX); DispiId = VideoPortReadPortUshort((PUSHORT)VBE_DISPI_IOPORT_DATA); if (DispiId == VBE_DISPI_ID_ANYX) VBoxCommonFromDeviceExt(pExt)->fAnyX = TRUE; else VBoxCommonFromDeviceExt(pExt)->fAnyX = FALSE; if (pExt->u.primary.commonInfo.bHGSMI) { LOGREL(("using HGSMI")); VBoxCreateDisplays(pExt, ConfigInfo); } /** @todo pretend success to make the driver work. */ rc = NO_ERROR; LOGF_LEAVE(); VBOXMP_WARN_VPS(rc); return rc; }
/*Query video port for api functions or fill with stubs if those are not supported*/ void VBoxSetupVideoPortAPI(PVBOXMP_DEVEXT pExt, PVIDEO_PORT_CONFIG_INFO pConfigInfo) { VBOXVIDEOPORTPROCS *pAPI = &pExt->u.primary.VideoPortProcs; VideoPortZeroMemory(pAPI, sizeof(VBOXVIDEOPORTPROCS)); if (VBoxQueryWinVersion() <= WINVERSION_NT4) { /* VideoPortGetProcAddress is available for >= win2k */ pAPI->pfnWaitForSingleObject = vboxWaitForSingleObjectVoid; pAPI->pfnSetEvent = vboxSetEventVoid; pAPI->pfnClearEvent = vboxClearEventVoid; pAPI->pfnCreateEvent = vboxCreateEventVoid; pAPI->pfnDeleteEvent = vboxDeleteEventVoid; pAPI->pfnAllocatePool = vboxAllocatePoolVoid; pAPI->pfnFreePool = vboxFreePoolVoid; pAPI->pfnQueueDpc = vboxQueueDpcVoid; pAPI->pfnCreateSecondaryDisplay = vboxCreateSecondaryDisplayVoid; return; } VP_GETPROC(pfnWaitForSingleObject, PFNWAITFORSINGLEOBJECT, "VideoPortWaitForSingleObject"); VP_GETPROC(pfnSetEvent, PFNSETEVENT, "VideoPortSetEvent"); VP_GETPROC(pfnClearEvent, PFNCLEAREVENT, "VideoPortClearEvent"); VP_GETPROC(pfnCreateEvent, PFNCREATEEVENT, "VideoPortCreateEvent"); VP_GETPROC(pfnDeleteEvent, PFNDELETEEVENT, "VideoPortDeleteEvent"); if(pAPI->pfnWaitForSingleObject && pAPI->pfnSetEvent && pAPI->pfnClearEvent && pAPI->pfnCreateEvent && pAPI->pfnDeleteEvent) { pAPI->fSupportedTypes |= VBOXVIDEOPORTPROCS_EVENT; } else { pAPI->pfnWaitForSingleObject = vboxWaitForSingleObjectVoid; pAPI->pfnSetEvent = vboxSetEventVoid; pAPI->pfnClearEvent = vboxClearEventVoid; pAPI->pfnCreateEvent = vboxCreateEventVoid; pAPI->pfnDeleteEvent = vboxDeleteEventVoid; } VP_GETPROC(pfnAllocatePool, PFNALLOCATEPOOL, "VideoPortAllocatePool"); VP_GETPROC(pfnFreePool, PFNFREEPOOL, "VideoPortFreePool"); if(pAPI->pfnAllocatePool && pAPI->pfnFreePool) { pAPI->fSupportedTypes |= VBOXVIDEOPORTPROCS_POOL; } else { pAPI->pfnAllocatePool = vboxAllocatePoolVoid; pAPI->pfnFreePool = vboxFreePoolVoid; } VP_GETPROC(pfnQueueDpc, PFNQUEUEDPC, "VideoPortQueueDpc"); if(pAPI->pfnQueueDpc) { pAPI->fSupportedTypes |= VBOXVIDEOPORTPROCS_DPC; } else { pAPI->pfnQueueDpc = vboxQueueDpcVoid; } VP_GETPROC(pfnCreateSecondaryDisplay, PFNCREATESECONDARYDISPLAY, "VideoPortCreateSecondaryDisplay"); if (pAPI->pfnCreateSecondaryDisplay) { pAPI->fSupportedTypes |= VBOXVIDEOPORTPROCS_CSD; } else { pAPI->pfnCreateSecondaryDisplay = vboxCreateSecondaryDisplayVoid; } }
/* Helper function to dynamically build our table of standard video * modes. We take the amount of VRAM and create modes with standard * geometries until we've either reached the maximum number of modes * or the available VRAM does not allow for additional modes. * We also check registry for manually added video modes. * Returns number of modes added to the table. */ static uint32_t VBoxMPFillModesTable(PVBOXMP_DEVEXT pExt, int iDisplay, PVIDEO_MODE_INFORMATION pModesTable, size_t tableSize, int32_t *pPrefModeIdx) { /* the resolution matrix */ struct { uint16_t xRes; uint16_t yRes; } resolutionMatrix[] = { /* standard modes */ { 640, 480 }, { 800, 600 }, { 1024, 768 }, { 1152, 864 }, { 1280, 960 }, { 1280, 1024 }, { 1400, 1050 }, { 1600, 1200 }, { 1920, 1440 }, #ifndef VBOX_WITH_WDDM /* multi screen modes with 1280x1024 */ { 2560, 1024 }, { 3840, 1024 }, { 5120, 1024 }, /* multi screen modes with 1600x1200 */ { 3200, 1200 }, { 4800, 1200 }, { 6400, 1200 }, #endif }; #ifdef VBOX_XPDM_MINIPORT ULONG vramSize = pExt->pPrimary->u.primary.ulMaxFrameBufferSize; #else ULONG vramSize = vboxWddmVramCpuVisibleSegmentSize(pExt); vramSize /= pExt->u.primary.commonInfo.cDisplays; # ifdef VBOX_WDDM_WIN8 if (!g_VBoxDisplayOnly) # endif { /* at least two surfaces will be needed: primary & shadow */ vramSize /= 2; } vramSize &= ~PAGE_OFFSET_MASK; #endif uint32_t iMode=0, iPrefIdx=0; /* there are 4 color depths: 8, 16, 24 and 32bpp and we reserve 50% of the modes for other sources */ size_t maxModesPerColorDepth = VBOXMP_MAX_VIDEO_MODES / 2 / 4; /* Always add 800x600 video modes. Windows XP+ needs at least 800x600 resolution * and fallbacks to 800x600x4bpp VGA mode if the driver did not report suitable modes. * This resolution could be rejected by a low resolution host (netbooks, etc). */ #ifdef VBOX_WITH_8BPP_MODES int bytesPerPixel=1; #else int bytesPerPixel=2; #endif for (; bytesPerPixel<=4; bytesPerPixel++) { int bitsPerPixel = 8*bytesPerPixel; if (800*600*bytesPerPixel > (LONG)vramSize) { /* we don't have enough VRAM for this mode */ continue; } if (!VBoxMPValidateVideoModeParamsGuest(pExt, iMode, 800, 600, bitsPerPixel)) continue; VBoxFillVidModeInfo(&pModesTable[iMode], 800, 600, bitsPerPixel, iMode+1, 0); if (32==bitsPerPixel) { iPrefIdx = iMode; } ++iMode; } /* Query yoffset from the host */ ULONG yOffset = VBoxGetHeightReduction(); /* Iterate through our static resolution table and add supported video modes for different bpp's */ #ifdef VBOX_WITH_8BPP_MODES bytesPerPixel=1; #else bytesPerPixel=2; #endif for (; bytesPerPixel<=4; bytesPerPixel++) { int bitsPerPixel = 8*bytesPerPixel; size_t cAdded, resIndex; for (cAdded=0, resIndex=0; resIndex<RT_ELEMENTS(resolutionMatrix) && cAdded<maxModesPerColorDepth; resIndex++) { if (resolutionMatrix[resIndex].xRes * resolutionMatrix[resIndex].yRes * bytesPerPixel > (LONG)vramSize) { /* we don't have enough VRAM for this mode */ continue; } if (yOffset == 0 && resolutionMatrix[resIndex].xRes == 800 && resolutionMatrix[resIndex].yRes == 600) { /* this mode was already added */ continue; } if ( #ifdef VBOX_WDDM_MINIPORT /* 1024x768 resolution is a minimal resolutions for win8 to make most metro apps run. * For small host display resolutions, host will dislike the mode 1024x768 and above * if the framebuffer window requires scrolling to fit the guest resolution. * So add 1024x768 resolution for win8 guest to allow user switch to it */ ( (VBoxQueryWinVersion() != WIN8 && VBoxQueryWinVersion() != WIN81) || resolutionMatrix[resIndex].xRes != 1024 || resolutionMatrix[resIndex].yRes != 768) && #endif !VBoxLikesVideoMode(iDisplay, resolutionMatrix[resIndex].xRes, resolutionMatrix[resIndex].yRes - yOffset, bitsPerPixel)) { /* host doesn't like this mode */ continue; } if (!VBoxMPValidateVideoModeParamsGuest(pExt, iDisplay, resolutionMatrix[resIndex].xRes, resolutionMatrix[resIndex].yRes, bitsPerPixel)) { /* guest does not like this mode */ continue; } /* Sanity check, we shouldn't ever get here */ if (iMode >= tableSize) { WARN(("video modes table overflow!")); break; } VBoxFillVidModeInfo(&pModesTable[iMode], resolutionMatrix[resIndex].xRes, resolutionMatrix[resIndex].yRes, bitsPerPixel, iMode+1, yOffset); ++iMode; ++cAdded; } } /* Check registry for manually added modes, up to 128 entries is supported * Give up on the first error encountered. */ VBOXMPCMNREGISTRY Registry; int fPrefSet=0; VP_STATUS rc; rc = VBoxMPCmnRegInit(pExt, &Registry); VBOXMP_WARN_VPS(rc); for (int curKey=0; curKey<128; curKey++) { if (iMode>=tableSize) { WARN(("ignoring possible custom mode(s), table is full!")); break; } wchar_t keyname[24]; uint32_t xres, yres, bpp = 0; swprintf(keyname, L"CustomMode%dWidth", curKey); rc = VBoxMPCmnRegQueryDword(Registry, keyname, &xres); VBOXMP_CHECK_VPS_BREAK(rc); swprintf(keyname, L"CustomMode%dHeight", curKey); rc = VBoxMPCmnRegQueryDword(Registry, keyname, &yres); VBOXMP_CHECK_VPS_BREAK(rc); swprintf(keyname, L"CustomMode%dBPP", curKey); rc = VBoxMPCmnRegQueryDword(Registry, keyname, &bpp); VBOXMP_CHECK_VPS_BREAK(rc); LOG(("got custom mode[%u]=%ux%u:%u", curKey, xres, yres, bpp)); /* round down width to be a multiple of 8 if necessary */ if (!VBoxCommonFromDeviceExt(pExt)->fAnyX) { xres &= 0xFFF8; } if ( (xres > (1 << 16)) || (yres > (1 << 16)) || ( (bpp != 16) && (bpp != 24) && (bpp != 32))) { /* incorrect values */ break; } /* does it fit within our VRAM? */ if (xres * yres * (bpp / 8) > vramSize) { /* we don't have enough VRAM for this mode */ break; } if (!VBoxLikesVideoMode(iDisplay, xres, yres, bpp)) { /* host doesn't like this mode */ break; } if (!VBoxMPValidateVideoModeParamsGuest(pExt, iDisplay, xres, yres, bpp)) { /* guest does not like this mode */ continue; } LOG(("adding video mode from registry.")); VBoxFillVidModeInfo(&pModesTable[iMode], xres, yres, bpp, iMode+1, yOffset); if (!fPrefSet) { fPrefSet = 1; iPrefIdx = iMode; } #ifdef VBOX_WDDM_MINIPORT /*check if the same mode has been added to the table already*/ int foundIdx = VBoxMPFindVideoMode(pModesTable, iMode, &pModesTable[iMode]); if (foundIdx>=0) { if (iPrefIdx==iMode) { iPrefIdx=foundIdx; } } else #endif { ++iMode; } } rc = VBoxMPCmnRegFini(Registry); VBOXMP_WARN_VPS(rc); if (pPrefModeIdx) { *pPrefModeIdx = iPrefIdx; } return iMode; }
/* Checks if we have a device supported by our driver and initialize * our driver/card specific information. * In particular we obtain VM monitors configuration and configure related structures. */ static VP_STATUS VBoxDrvFindAdapter(IN PVOID HwDeviceExtension, IN PVOID HwContext, IN PWSTR ArgumentString, IN OUT PVIDEO_PORT_CONFIG_INFO ConfigInfo, OUT PUCHAR Again) { PVBOXMP_DEVEXT pExt = (PVBOXMP_DEVEXT) HwDeviceExtension; VP_STATUS rc; USHORT DispiId; ULONG AdapterMemorySize = VBE_DISPI_TOTAL_VIDEO_MEMORY_BYTES; PAGED_CODE(); LOGF_ENTER(); /* Init video port api */ VBoxSetupVideoPortAPI(pExt, ConfigInfo); VideoPortWritePortUshort((PUSHORT)VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_ID); VideoPortWritePortUshort((PUSHORT)VBE_DISPI_IOPORT_DATA, VBE_DISPI_ID2); DispiId = VideoPortReadPortUshort((PUSHORT)VBE_DISPI_IOPORT_DATA); if (DispiId != VBE_DISPI_ID2) { WARN(("VBE card not found, returning ERROR_DEV_NOT_EXIST")); return ERROR_DEV_NOT_EXIST; } LOG(("found the VBE card")); /* * Query the adapter's memory size. It's a bit of a hack, we just read * an ULONG from the data port without setting an index before. */ AdapterMemorySize = VideoPortReadPortUlong((PULONG)VBE_DISPI_IOPORT_DATA); /* Write hw information to registry, so that it's visible in windows property dialog */ rc = VideoPortSetRegistryParameters(pExt, L"HardwareInformation.ChipType", VBoxChipType, sizeof(VBoxChipType)); VBOXMP_WARN_VPS(rc); rc = VideoPortSetRegistryParameters(pExt, L"HardwareInformation.DacType", VBoxDACType, sizeof(VBoxDACType)); VBOXMP_WARN_VPS(rc); rc = VideoPortSetRegistryParameters(pExt, L"HardwareInformation.MemorySize", &AdapterMemorySize, sizeof(ULONG)); VBOXMP_WARN_VPS(rc); rc = VideoPortSetRegistryParameters(pExt, L"HardwareInformation.AdapterString", VBoxAdapterString, sizeof(VBoxAdapterString)); VBOXMP_WARN_VPS(rc); rc = VideoPortSetRegistryParameters(pExt, L"HardwareInformation.BiosString", VBoxBiosString, sizeof(VBoxBiosString)); VBOXMP_WARN_VPS(rc); /* Call VideoPortGetAccessRanges to ensure interrupt info in ConfigInfo gets set up */ { VIDEO_ACCESS_RANGE tmpRanges[4]; ULONG slot = 0; VideoPortZeroMemory(tmpRanges, sizeof(tmpRanges)); if (VBoxQueryWinVersion() == WINNT4) { /* NT crashes if either of 'vendorId, 'deviceId' or 'slot' parameters is NULL, * and needs PCI ids for a successful VideoPortGetAccessRanges call. */ ULONG vendorId = 0x80EE; ULONG deviceId = 0xBEEF; rc = VideoPortGetAccessRanges(pExt, 0, NULL, RT_ELEMENTS(tmpRanges), tmpRanges, &vendorId, &deviceId, &slot); } else { rc = VideoPortGetAccessRanges(pExt, 0, NULL, RT_ELEMENTS(tmpRanges), tmpRanges, NULL, NULL, &slot); } VBOXMP_WARN_VPS(rc); } /* Initialize VBoxGuest library, which is used for requests which go through VMMDev. */ rc = VbglInit(); VBOXMP_WARN_VPS(rc); /* Preinitialize the primary extension. */ pExt->pNext = NULL; pExt->pPrimary = pExt; pExt->iDevice = 0; pExt->ulFrameBufferOffset = 0; pExt->ulFrameBufferSize = 0; pExt->u.primary.ulVbvaEnabled = 0; VideoPortZeroMemory(&pExt->areaDisplay, sizeof(HGSMIAREA)); /* Guest supports only HGSMI, the old VBVA via VMMDev is not supported. Old * code will be ifdef'ed and later removed. * The host will however support both old and new interface to keep compatibility * with old guest additions. */ VBoxSetupDisplaysHGSMI(&pExt->u.primary.commonInfo, AdapterMemorySize, 0); if (pExt->u.primary.commonInfo.bHGSMI) { LOGREL(("using HGSMI")); VBoxCreateDisplays(pExt, ConfigInfo); } /** @todo pretend success to make the driver work. */ rc = NO_ERROR; LOGF_LEAVE(); VBOXMP_WARN_VPS(rc); return rc; }