/** Set a graphics mode. Poke any required values into registers, do an HGSMI * mode set and tell the host we support advanced graphics functions. */ static void vbox_do_modeset(struct drm_crtc *crtc, const struct drm_display_mode *mode) { struct vbox_crtc *vbox_crtc = to_vbox_crtc(crtc); struct vbox_private *vbox; int width, height, cBPP, pitch; unsigned iCrtc; uint16_t fFlags; LogFunc(("vboxvideo: %d: vbox_crtc=%p, CRTC_FB(crtc)=%p\n", __LINE__, vbox_crtc, CRTC_FB(crtc))); vbox = crtc->dev->dev_private; width = mode->hdisplay ? mode->hdisplay : 640; height = mode->vdisplay ? mode->vdisplay : 480; iCrtc = vbox_crtc->crtc_id; cBPP = crtc->enabled ? CRTC_FB(crtc)->bits_per_pixel : 32; #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 3, 0) pitch = crtc->enabled ? CRTC_FB(crtc)->pitch : width * cBPP / 8; #else pitch = crtc->enabled ? CRTC_FB(crtc)->pitches[0] : width * cBPP / 8; #endif /* if (vbox_crtc->crtc_id == 0 && crtc->enabled) VBoxVideoSetModeRegisters(width, height, pitch * 8 / cBPP, CRTC_FB(crtc)->bits_per_pixel, 0, crtc->x, crtc->y); */ fFlags = VBVA_SCREEN_F_ACTIVE; fFlags |= (crtc->enabled ? 0 : VBVA_SCREEN_F_DISABLED); VBoxHGSMIProcessDisplayInfo(&vbox->Ctx, vbox_crtc->crtc_id, crtc->x, crtc->y, crtc->x * cBPP / 8 + crtc->y * pitch, pitch, width, height, vbox_crtc->fBlanked ? 0 : cBPP, fFlags); LogFunc(("vboxvideo: %d\n", __LINE__)); }
/* Called to notify driver about various events */ VOID APIENTRY VBoxDispDrvNotify(SURFOBJ *pso, ULONG iType, PVOID pvData) { PVBOXDISPDEV pDev = (PVBOXDISPDEV)pso->dhpdev; LOGF_ENTER(); switch (iType) { case DN_DEVICE_ORIGIN: { /*device origin in dualview*/ POINTL *pOrg = (POINTL *)pvData; if (pOrg) { LOG(("DN_DEVICE_ORIGIN (pso=%p, pDev[%d]=%p) old=%d,%d new=%d,%d", pso, pDev->iDevice, pDev, pDev->orgDev.x, pDev->orgDev.y, pOrg->x, pOrg->y)); if (pDev->orgDev.x!=pOrg->x || pDev->orgDev.y!=pOrg->y) { pDev->orgDev = *pOrg; /* Inform host about display change */ VBoxHGSMIProcessDisplayInfo(&pDev->hgsmi.ctx, pDev->iDevice, pDev->orgDev.x, pDev->orgDev.y, 0, abs(pDev->mode.lScanlineStride), pDev->mode.ulWidth, pDev->mode.ulHeight, (uint16_t)pDev->mode.ulBitsPerPel, VBVA_SCREEN_F_ACTIVE); } } else { WARN(("DN_DEVICE_ORIGIN pvData==NULL")); } break; } case DN_DRAWING_BEGIN: { /*first drawing op is about to happen for this device*/ LOG(("DN_DRAWING_BEGIN (pso=%p, pDev[%d]=%p)", pso, pDev->iDevice, pDev)); break; } default: { LOG(("unknown iType=%#x", iType)); } } LOGF_LEAVE(); return; }
/** Set a graphics mode. Poke any required values into registers, do an HGSMI * mode set and tell the host we support advanced graphics functions. This * procedure is complicated by the fact that X.Org can implicitly disable a * screen by resizing the virtual framebuffer so that the screen is no longer * inside it. We have to spot and handle this. */ Bool VBOXSetMode(ScrnInfoPtr pScrn, unsigned cDisplay, unsigned cWidth, unsigned cHeight, int x, int y) { VBOXPtr pVBox = VBOXGetRec(pScrn); uint32_t offStart, cwReal = cWidth; TRACE_LOG("cDisplay=%u, cWidth=%u, cHeight=%u, x=%d, y=%d, displayWidth=%d\n", cDisplay, cWidth, cHeight, x, y, pScrn->displayWidth); offStart = y * pVBox->cbLine + x * vboxBPP(pScrn) / 8; /* Deactivate the screen if the mode - specifically the virtual width - is * too large for VRAM as we sometimes have to do this - see comments in * VBOXPreInit. */ if ( offStart + pVBox->cbLine * cHeight > pVBox->cbFBMax || pVBox->cbLine * pScrn->virtualY > pVBox->cbFBMax) return FALSE; /* Deactivate the screen if it is outside of the virtual framebuffer and * clamp it to lie inside if it is partly outside. */ if (x >= pScrn->displayWidth || x + (int) cWidth <= 0) return FALSE; else cwReal = RT_MIN((int) cWidth, pScrn->displayWidth - x); TRACE_LOG("pVBox->afDisabled[%u]=%d\n", cDisplay, (int)pVBox->afDisabled[cDisplay]); if (cDisplay == 0) VBoxVideoSetModeRegisters(cwReal, cHeight, pScrn->displayWidth, vboxBPP(pScrn), 0, x, y); /* Tell the host we support graphics */ if (vbox_device_available(pVBox)) vboxEnableGraphicsCap(pVBox); if (pVBox->fHaveHGSMI) { uint16_t fFlags = VBVA_SCREEN_F_ACTIVE; fFlags |= (pVBox->afDisabled[cDisplay] ? VBVA_SCREEN_F_DISABLED : 0); VBoxHGSMIProcessDisplayInfo(&pVBox->guestCtx, cDisplay, x, y, offStart, pVBox->cbLine, cwReal, cHeight, vboxBPP(pScrn), fFlags); } return TRUE; }
/* Called to reset device to default mode or to mode specified with dhpdev */ BOOL APIENTRY VBoxDispDrvAssertMode(DHPDEV dhpdev, BOOL bEnable) { PVBOXDISPDEV pDev = (PVBOXDISPDEV) dhpdev; DWORD dwrc; int rc; LOGF_ENTER(); if (!bEnable) { LOGF(("!bEnable")); #ifdef VBOX_WITH_VIDEOHWACCEL /* tells we can not process host commands any more and ensures that * we've completed processing of the host VHWA commands */ VBoxDispVHWADisable(pDev); #endif /* disable VBVA */ if (pDev->hgsmi.bSupported) { VBoxVBVADisable(&pDev->vbvaCtx, &pDev->hgsmi.ctx, -1); } /* reset the device to default mode */ rc = VBoxDispMPResetDevice(pDev->hDriver); VBOX_WARNRC_RETV(rc, FALSE); } else { LOGF(("bEnable")); /* switch device to previous pDev mode */ rc = VBoxDispMPSetCurrentMode(pDev->hDriver, pDev->mode.ulIndex); VBOX_WARNRC_RETV(rc, NULL); /* enable VBVA */ if (pDev->hgsmi.bSupported) { if (pDev->mode.ulBitsPerPel==16 || pDev->mode.ulBitsPerPel==24 || pDev->mode.ulBitsPerPel==32) { VBVABUFFER *pVBVA = (VBVABUFFER *)((uint8_t *)pDev->memInfo.VideoRamBase+pDev->layout.offVBVABuffer); pDev->hgsmi.bSupported = VBoxVBVAEnable(&pDev->vbvaCtx, &pDev->hgsmi.ctx, pVBVA, -1); LogRel(("VBoxDisp[%d]: VBVA %senabled\n", pDev->iDevice, pDev->hgsmi.bSupported? "":"not ")); } } /* inform host */ if (pDev->hgsmi.bSupported) { VBoxHGSMIProcessDisplayInfo(&pDev->hgsmi.ctx, pDev->iDevice, pDev->orgDev.x, pDev->orgDev.y, 0, abs(pDev->mode.lScanlineStride), pDev->mode.ulWidth, pDev->mode.ulHeight, (uint16_t)pDev->mode.ulBitsPerPel, VBVA_SCREEN_F_ACTIVE); } #ifdef VBOX_WITH_VIDEOHWACCEL /* tells we can process host commands */ VBoxDispVHWAEnable(pDev); #endif /* Associate back GDI bitmap residing in our framebuffer memory with GDI's handle to our device */ dwrc = EngAssociateSurface((HSURF)pDev->surface.hBitmap, pDev->hDevGDI, 0); if (dwrc != NO_ERROR) { WARN(("EngAssociateSurface on bitmap failed with %#x", dwrc)); return FALSE; } /* Associate device managed surface with GDI's handle to our device */ dwrc = EngAssociateSurface(pDev->surface.hSurface, pDev->hDevGDI, pDev->flDrawingHooks); if (dwrc != NO_ERROR) { WARN(("EngAssociateSurface on surface failed with %#x", dwrc)); return FALSE; } } LOGF_LEAVE(); return TRUE; }
/* Called to create and associate surface with device */ HSURF APIENTRY VBoxDispDrvEnableSurface(DHPDEV dhpdev) { int rc; PVBOXDISPDEV pDev = (PVBOXDISPDEV)dhpdev; LOGF_ENTER(); /* Switch device to mode requested in VBoxDispDrvEnablePDEV */ rc = VBoxDispMPSetCurrentMode(pDev->hDriver, pDev->mode.ulIndex); VBOX_WARNRC_RETV(rc, NULL); /* Map fb and vram */ rc = VBoxDispMPMapMemory(pDev, &pDev->memInfo); VBOX_WARNRC_RETV(rc, NULL); /* Clear mapped memory, to avoid garbage while video mode is switching */ /* @todo: VIDEO_MODE_NO_ZERO_MEMORY does nothing in miniport's IOCTL_VIDEO_SET_CURRENT_MODE*/ memset(pDev->memInfo.FrameBufferBase, 0, pDev->mode.ulHeight * abs(pDev->mode.lScanlineStride)); /* Allocate memory for pointer attrs */ rc = VBoxDispInitPointerAttrs(pDev); VBOX_WARNRC_RETV(rc, NULL); /* Init VBVA */ rc = VBoxDispVBVAInit(pDev); VBOX_WARNRC_RETV(rc, NULL); /* Enable VBVA */ if (pDev->hgsmi.bSupported) { if (pDev->mode.ulBitsPerPel==16 || pDev->mode.ulBitsPerPel==24 || pDev->mode.ulBitsPerPel==32) { VBVABUFFER *pVBVA = (VBVABUFFER *)((uint8_t *)pDev->memInfo.VideoRamBase+pDev->layout.offVBVABuffer); pDev->hgsmi.bSupported = VBoxVBVAEnable(&pDev->vbvaCtx, &pDev->hgsmi.ctx, pVBVA, -1); LogRel(("VBoxDisp[%d]: VBVA %senabled\n", pDev->iDevice, pDev->hgsmi.bSupported? "":"not ")); } } /* Inform host */ if (pDev->hgsmi.bSupported) { VBoxHGSMIProcessDisplayInfo(&pDev->hgsmi.ctx, pDev->iDevice, pDev->orgDev.x, pDev->orgDev.y, 0, abs(pDev->mode.lScanlineStride), pDev->mode.ulWidth, pDev->mode.ulHeight, (uint16_t)pDev->mode.ulBitsPerPel, VBVA_SCREEN_F_ACTIVE); } #ifdef VBOX_WITH_VIDEOHWACCEL VBoxDispVHWAEnable(pDev); #endif /* Set device palette if needed */ if (pDev->mode.ulBitsPerPel == 8) { rc = VBoxDispSetPalette8BPP(pDev); VBOX_WARNRC_RETV(rc, NULL); } pDev->orgDisp.x = 0; pDev->orgDisp.y = 0; /* Create GDI managed bitmap, which resides in our framebuffer memory */ ULONG iFormat; SIZEL size; switch (pDev->mode.ulBitsPerPel) { case 8: { iFormat = BMF_8BPP; break; } case 16: { iFormat = BMF_16BPP; break; } case 24: { iFormat = BMF_24BPP; break; } case 32: { iFormat = BMF_32BPP; break; } } size.cx = pDev->mode.ulWidth; size.cy = pDev->mode.ulHeight; pDev->surface.hBitmap = EngCreateBitmap(size, pDev->mode.lScanlineStride, iFormat, pDev->mode.lScanlineStride>0 ? BMF_TOPDOWN:0, pDev->memInfo.FrameBufferBase); if (!pDev->surface.hBitmap) { WARN(("EngCreateBitmap failed!")); return NULL; } pDev->surface.psoBitmap = EngLockSurface((HSURF)pDev->surface.hBitmap); /* Create device-managed surface */ pDev->surface.hSurface = EngCreateDeviceSurface((DHSURF)pDev, size, iFormat); if (!pDev->surface.hSurface) { WARN(("EngCreateDeviceSurface failed!")); VBoxDispDrvDisableSurface(dhpdev); return NULL; } FLONG flHooks = HOOK_BITBLT|HOOK_TEXTOUT|HOOK_FILLPATH|HOOK_COPYBITS|HOOK_STROKEPATH|HOOK_LINETO| HOOK_PAINT|HOOK_STRETCHBLT; /* Associate created surface with our device */ if (!EngAssociateSurface(pDev->surface.hSurface, pDev->hDevGDI, flHooks)) { WARN(("EngAssociateSurface failed!")); VBoxDispDrvDisableSurface(dhpdev); return NULL; } pDev->surface.ulFormat = iFormat; pDev->flDrawingHooks = flHooks; LOG(("Created surface %p for physical device %p", pDev->surface.hSurface, pDev)); LOGF_LEAVE(); return pDev->surface.hSurface; }
/* Process Video Request Packet. */ static BOOLEAN VBoxDrvStartIO(PVOID HwDeviceExtension, PVIDEO_REQUEST_PACKET RequestPacket) { PVBOXMP_DEVEXT pExt = (PVBOXMP_DEVEXT) HwDeviceExtension; PSTATUS_BLOCK pStatus = RequestPacket->StatusBlock; BOOLEAN bResult = FALSE; PAGED_CODE(); LOGF(("IOCTL %#x, fn(%#x)", RequestPacket->IoControlCode, (RequestPacket->IoControlCode >> 2) & 0xFFF)); pStatus->Status = NO_ERROR; switch (RequestPacket->IoControlCode) { /* ==================== System VRPs ==================== */ /*Maps FrameBuffer and video RAM to a caller's virtual adress space.*/ case IOCTL_VIDEO_MAP_VIDEO_MEMORY: { STARTIO_IN(VIDEO_MEMORY, pMemory); STARTIO_OUT(VIDEO_MEMORY_INFORMATION, pMemInfo); bResult = VBoxMPMapVideoMemory(pExt, pMemory, pMemInfo, pStatus); break; } /*Unmaps previously mapped FrameBuffer and video RAM from caller's virtual adress space.*/ case IOCTL_VIDEO_UNMAP_VIDEO_MEMORY: { STARTIO_IN(VIDEO_MEMORY, pMemory); bResult = VBoxMPUnmapVideoMemory(pExt, pMemory, pStatus); break; } /*Maps FrameBuffer as a linear frame buffer to a caller's virtual adress space. (obsolete)*/ case IOCTL_VIDEO_SHARE_VIDEO_MEMORY: { STARTIO_IN(VIDEO_SHARE_MEMORY, pShareMemory); STARTIO_OUT(VIDEO_SHARE_MEMORY_INFORMATION, pShareMemInfo); bResult = VBoxMPShareVideoMemory(pExt, pShareMemory, pShareMemInfo, pStatus); break; } /*Unmaps framebuffer previously mapped with IOCTL_VIDEO_SHARE_VIDEO_MEMORY*/ case IOCTL_VIDEO_UNSHARE_VIDEO_MEMORY: { STARTIO_IN(VIDEO_SHARE_MEMORY, pShareMemory); bResult = VBoxMPUnshareVideoMemory(pExt, pShareMemory, pStatus); break; } /*Reset device to a state it comes at system boot time.*/ case IOCTL_VIDEO_RESET_DEVICE: { bResult = VBoxMPResetDevice(pExt, pStatus); break; } /*Set adapter video mode.*/ case IOCTL_VIDEO_SET_CURRENT_MODE: { STARTIO_IN(VIDEO_MODE, pMode); bResult = VBoxMPSetCurrentMode(pExt, pMode, pStatus); break; } /*Returns information about current video mode.*/ case IOCTL_VIDEO_QUERY_CURRENT_MODE: { STARTIO_OUT(VIDEO_MODE_INFORMATION, pModeInfo); bResult = VBoxMPQueryCurrentMode(pExt, pModeInfo, pStatus); break; } /* Returns count of supported video modes and structure size in bytes, * used to allocate buffer for the following IOCTL_VIDEO_QUERY_AVAIL_MODES call. */ case IOCTL_VIDEO_QUERY_NUM_AVAIL_MODES: { STARTIO_OUT(VIDEO_NUM_MODES, pNumModes); bResult = VBoxMPQueryNumAvailModes(pExt, pNumModes, pStatus); break; } /* Returns information about supported video modes. */ case IOCTL_VIDEO_QUERY_AVAIL_MODES: { PVIDEO_MODE_INFORMATION pModes = (PVIDEO_MODE_INFORMATION) RequestPacket->OutputBuffer; if (RequestPacket->OutputBufferLength < VBoxMPXpdmGetVideoModesCount(pExt)*sizeof(VIDEO_MODE_INFORMATION)) { pStatus->Status = ERROR_INSUFFICIENT_BUFFER; break; } bResult = VBoxMPQueryAvailModes(pExt, pModes, pStatus); break; } /* Sets adapter's color registers, have to be implemented if we support palette based modes. */ case IOCTL_VIDEO_SET_COLOR_REGISTERS: { STARTIO_IN(VIDEO_CLUT, pClut); if (RequestPacket->InputBufferLength < (sizeof(VIDEO_CLUT) + pClut->NumEntries * sizeof(ULONG))) { pStatus->Status = ERROR_INSUFFICIENT_BUFFER; break; } bResult = VBoxMPSetColorRegisters(pExt, pClut, pStatus); break; } /* Sets pointer attributes. */ case IOCTL_VIDEO_SET_POINTER_ATTR: { STARTIO_IN(VIDEO_POINTER_ATTRIBUTES, pPointerAttrs); bResult = VBoxMPSetPointerAttr(pExt, pPointerAttrs, RequestPacket->InputBufferLength, pStatus); break; } /* Makes pointer visible. */ case IOCTL_VIDEO_ENABLE_POINTER: { bResult = VBoxMPEnablePointer(pExt, TRUE, pStatus); break; } /* Hides pointer. */ case IOCTL_VIDEO_DISABLE_POINTER: { bResult = VBoxMPEnablePointer(pExt, FALSE, pStatus); break; } /* Sets pointer position, is called after IOCTL_VIDEO_ENABLE_POINTER. */ case IOCTL_VIDEO_SET_POINTER_POSITION: { STARTIO_IN(VIDEO_POINTER_POSITION, pPos); NOREF(pPos); /** @todo set pointer position*/ bResult = VBoxMPEnablePointer(pExt, TRUE, pStatus); break; } /* Query pointer position. */ case IOCTL_VIDEO_QUERY_POINTER_POSITION: { STARTIO_OUT(VIDEO_POINTER_POSITION, pPos); bResult = VBoxMPQueryPointerPosition(pExt, pPos, pStatus); break; } /* Query supported hardware pointer feaures. */ case IOCTL_VIDEO_QUERY_POINTER_CAPABILITIES: { STARTIO_OUT(VIDEO_POINTER_CAPABILITIES, pCaps); bResult = VBoxMPQueryPointerCapabilities(pExt, pCaps, pStatus); break; } /* Query pointer attributes. (optional) */ case IOCTL_VIDEO_QUERY_POINTER_ATTR: { STARTIO_OUT(VIDEO_POINTER_ATTRIBUTES, pPointerAttrs); NOREF(pPointerAttrs); /* Not Implemented */ pStatus->Status = ERROR_INVALID_FUNCTION; bResult = FALSE; break; } /* Called when a secondary adapter is about to be enabled/disabled. */ case IOCTL_VIDEO_SWITCH_DUALVIEW: { STARTIO_IN(ULONG, pAttach); LOGF(("IOCTL_VIDEO_SWITCH_DUALVIEW: [%d] attach = %d", pExt->iDevice, *pAttach)); if (pExt->iDevice>0) { pExt->u.secondary.bEnabled = (BOOLEAN)(*pAttach); /* Inform the host. * Currently only about secondary devices, because the driver does not support * disconnecting the primary display (it does not allow to change the primary display). */ if (!pExt->u.secondary.bEnabled) { PVBOXMP_COMMON pCommon = VBoxCommonFromDeviceExt(pExt); if (pCommon->bHGSMI) { VBoxHGSMIProcessDisplayInfo(&pCommon->guestCtx, pExt->iDevice, /* cOriginX = */ 0, /* cOriginY = */ 0, /* offStart = */ 0, /* cbPitch = */ 0, /* cWidth = */ 0, /* cHeight = */ 0, /* cBPP = */ 0, VBVA_SCREEN_F_ACTIVE | VBVA_SCREEN_F_DISABLED); } } } bResult = TRUE; break; } /* Called to get child device status */ case IOCTL_VIDEO_GET_CHILD_STATE: { STARTIO_IN(ULONG, pChildIndex); STARTIO_OUT(ULONG, pChildState); LOGF(("IOCTL_VIDEO_GET_CHILD_STATE: [%d] idx = %d", pExt->iDevice, *pChildIndex)); if (*pChildIndex>0 && *pChildIndex<=(ULONG)VBoxCommonFromDeviceExt(pExt)->cDisplays) { *pChildState = VIDEO_CHILD_ACTIVE; pStatus->Information = sizeof(ULONG); bResult = TRUE; } else { pStatus->Status = ERROR_INVALID_PARAMETER; bResult = FALSE; } break; } /* ==================== VirtualBox specific VRPs ==================== */ /* Called by the display driver when it is ready to switch to VBVA operation mode. */ case IOCTL_VIDEO_VBVA_ENABLE: { STARTIO_IN(ULONG, pEnable); STARTIO_OUT(VBVAENABLERESULT, pResult); bResult = VBoxMPVBVAEnable(pExt, (BOOLEAN)*pEnable, pResult, pStatus); break; } /* Called by the display driver when it recieves visible regions information. */ case IOCTL_VIDEO_VBOX_SETVISIBLEREGION: { STARTIO_IN(RTRECT, pRects); uint32_t cRects = RequestPacket->InputBufferLength/sizeof(RTRECT); /*Sanity check*/ if ( cRects > _1M || RequestPacket->InputBufferLength != cRects * sizeof(RTRECT)) { pStatus->Status = ERROR_INSUFFICIENT_BUFFER; break; } bResult = VBoxMPSetVisibleRegion(cRects, pRects, pStatus); break; } /* Returns video port api function pointers. */ case IOCTL_VIDEO_HGSMI_QUERY_PORTPROCS: { STARTIO_OUT(HGSMIQUERYCPORTPROCS, pProcs); bResult = VBoxMPHGSMIQueryPortProcs(pExt, pProcs, pStatus); break; } /* Returns HGSMI related callbacks. */ case IOCTL_VIDEO_HGSMI_QUERY_CALLBACKS: { STARTIO_OUT(HGSMIQUERYCALLBACKS, pCallbacks); bResult = VBoxMPHGSMIQueryCallbacks(pExt, pCallbacks, pStatus); break; } /* Returns hgsmi info for this adapter. */ case IOCTL_VIDEO_QUERY_HGSMI_INFO: { STARTIO_OUT(QUERYHGSMIRESULT, pResult); bResult = VBoxMPQueryHgsmiInfo(pExt, pResult, pStatus); break; } /* Enables HGSMI miniport channel. */ case IOCTL_VIDEO_HGSMI_HANDLER_ENABLE: { STARTIO_IN(HGSMIHANDLERENABLE, pChannel); bResult = VBoxMPHgsmiHandlerEnable(pExt, pChannel, pStatus); break; } case IOCTL_VIDEO_HGSMI_HANDLER_DISABLE: { /** @todo not implemented */ break; } #ifdef VBOX_WITH_VIDEOHWACCEL /* Returns framebuffer offset. */ case IOCTL_VIDEO_VHWA_QUERY_INFO: { STARTIO_OUT(VHWAQUERYINFO, pInfo); bResult = VBoxMPVhwaQueryInfo(pExt, pInfo, pStatus); break; } #endif case IOCTL_VIDEO_VBOX_ISANYX: { STARTIO_OUT(uint32_t, pu32AnyX); *pu32AnyX = VBoxCommonFromDeviceExt(pExt)->fAnyX; pStatus->Information = sizeof (uint32_t); bResult = TRUE; break; } case IOCTL_VIDEO_QUERY_VBOXVIDEO_INFO: { STARTIO_IN(ULONG, pulInfoLevel); if (*pulInfoLevel == VBOXVIDEO_INFO_LEVEL_REGISTRY_FLAGS) { STARTIO_OUT(ULONG, pulFlags); bResult = VBoxMPQueryRegistryFlags(pExt, pulFlags, pStatus); } else { pStatus->Status = ERROR_INVALID_PARAMETER; bResult = FALSE; } break; } default: { WARN(("unsupported IOCTL %#x, fn(%#x)", RequestPacket->IoControlCode, (RequestPacket->IoControlCode >> 2) & 0xFFF)); RequestPacket->StatusBlock->Status = ERROR_INVALID_FUNCTION; } } if (!bResult) { pStatus->Information = NULL; } VBOXMP_WARN_VPS(pStatus->Status); LOGF_LEAVE(); return TRUE; }