VBoxMPMisc.cpp revision 3a343ca21a267ec3c54e2317e2ed18fe99b8ebbb
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync/* $Id$ */
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync/** @file
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync * VBox WDDM Miniport driver
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync */
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync/*
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync * Copyright (C) 2011 Oracle Corporation
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync *
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync * available from http://www.virtualbox.org. This file is free software;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync * you can redistribute it and/or modify it under the terms of the GNU
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync * General Public License (GPL) as published by the Free Software
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync */
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync#include "VBoxMPWddm.h"
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync#include <VBox/Hardware/VBoxVideoVBE.h>
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync#include <stdio.h>
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync/* simple handle -> value table API */
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsyncNTSTATUS vboxWddmHTableCreate(PVBOXWDDM_HTABLE pTbl, uint32_t cSize)
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync{
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync memset(pTbl, 0, sizeof (*pTbl));
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync pTbl->paData = (PVOID*)vboxWddmMemAllocZero(sizeof (pTbl->paData[0]) * cSize);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync if (pTbl->paData)
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync {
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync pTbl->cSize = cSize;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync return STATUS_SUCCESS;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync }
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync return STATUS_NO_MEMORY;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync}
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsyncVOID vboxWddmHTableDestroy(PVBOXWDDM_HTABLE pTbl)
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync{
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync if (!pTbl->paData)
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync return;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync vboxWddmMemFree(pTbl->paData);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync}
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsyncDECLINLINE(VBOXWDDM_HANDLE) vboxWddmHTableIndex2Handle(uint32_t iIndex)
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync{
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync return iIndex+1;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync}
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsyncDECLINLINE(uint32_t) vboxWddmHTableHandle2Index(VBOXWDDM_HANDLE hHandle)
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync{
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync return hHandle-1;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync}
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsyncNTSTATUS vboxWddmHTableRealloc(PVBOXWDDM_HTABLE pTbl, uint32_t cNewSize)
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync{
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync Assert(cNewSize > pTbl->cSize);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync if (cNewSize > pTbl->cSize)
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync {
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync PVOID *pvNewData = (PVOID*)vboxWddmMemAllocZero(sizeof (pTbl->paData[0]) * cNewSize);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync if (!pvNewData)
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync {
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync WARN(("vboxWddmMemAllocZero failed for size (%d)", sizeof (pTbl->paData[0]) * cNewSize));
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync return STATUS_NO_MEMORY;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync }
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync memcpy(pvNewData, pTbl->paData, sizeof (pTbl->paData[0]) * pTbl->cSize);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync vboxWddmMemFree(pTbl->paData);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync pTbl->iNext2Search = pTbl->cSize;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync pTbl->cSize = cNewSize;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync pTbl->paData = pvNewData;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync return STATUS_SUCCESS;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync }
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync else if (cNewSize >= pTbl->cData)
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync {
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync AssertFailed();
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync return STATUS_NOT_IMPLEMENTED;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync }
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync return STATUS_INVALID_PARAMETER;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync}
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsyncVBOXWDDM_HANDLE vboxWddmHTablePut(PVBOXWDDM_HTABLE pTbl, PVOID pvData)
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync{
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync if (pTbl->cSize == pTbl->cData)
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync {
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync NTSTATUS Status = vboxWddmHTableRealloc(pTbl, pTbl->cSize + RT_MAX(10, pTbl->cSize/4));
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync Assert(Status == STATUS_SUCCESS);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync if (Status != STATUS_SUCCESS)
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync return VBOXWDDM_HANDLE_INVALID;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync }
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync for (UINT i = pTbl->iNext2Search; ; ++i, i %= pTbl->cSize)
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync {
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync Assert(i < pTbl->cSize);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync if (!pTbl->paData[i])
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync {
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync pTbl->paData[i] = pvData;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync ++pTbl->cData;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync Assert(pTbl->cData <= pTbl->cSize);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync ++pTbl->iNext2Search;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync pTbl->iNext2Search %= pTbl->cSize;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync return vboxWddmHTableIndex2Handle(i);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync }
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync }
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync Assert(0);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync return VBOXWDDM_HANDLE_INVALID;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync}
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsyncPVOID vboxWddmHTableRemove(PVBOXWDDM_HTABLE pTbl, VBOXWDDM_HANDLE hHandle)
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync{
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync uint32_t iIndex = vboxWddmHTableHandle2Index(hHandle);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync Assert(iIndex < pTbl->cSize);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync if (iIndex < pTbl->cSize)
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync {
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync PVOID pvData = pTbl->paData[iIndex];
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync pTbl->paData[iIndex] = NULL;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync --pTbl->cData;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync Assert(pTbl->cData <= pTbl->cSize);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync pTbl->iNext2Search = iIndex;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync return pvData;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync }
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync return NULL;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync}
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsyncPVOID vboxWddmHTableGet(PVBOXWDDM_HTABLE pTbl, VBOXWDDM_HANDLE hHandle)
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync{
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync uint32_t iIndex = vboxWddmHTableHandle2Index(hHandle);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync Assert(iIndex < pTbl->cSize);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync if (iIndex < pTbl->cSize)
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync return pTbl->paData[iIndex];
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync return NULL;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync}
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsyncVOID vboxWddmHTableIterInit(PVBOXWDDM_HTABLE pTbl, PVBOXWDDM_HTABLE_ITERATOR pIter)
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync{
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync pIter->pTbl = pTbl;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync pIter->iCur = ~0UL;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync pIter->cLeft = pTbl->cData;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync}
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsyncBOOL vboxWddmHTableIterHasNext(PVBOXWDDM_HTABLE_ITERATOR pIter)
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync{
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync return pIter->cLeft;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync}
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsyncPVOID vboxWddmHTableIterNext(PVBOXWDDM_HTABLE_ITERATOR pIter, VBOXWDDM_HANDLE *phHandle)
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync{
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync if (vboxWddmHTableIterHasNext(pIter))
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync {
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync for (uint32_t i = pIter->iCur+1; i < pIter->pTbl->cSize ; ++i)
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync {
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync if (pIter->pTbl->paData[i])
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync {
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync pIter->iCur = i;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync --pIter->cLeft;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync VBOXWDDM_HANDLE hHandle = vboxWddmHTableIndex2Handle(i);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync Assert(hHandle);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync if (phHandle)
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync *phHandle = hHandle;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync return pIter->pTbl->paData[i];
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync }
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync }
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync }
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync Assert(!vboxWddmHTableIterHasNext(pIter));
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync if (phHandle)
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync *phHandle = VBOXWDDM_HANDLE_INVALID;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync return NULL;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync}
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsyncPVOID vboxWddmHTableIterRemoveCur(PVBOXWDDM_HTABLE_ITERATOR pIter)
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync{
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync VBOXWDDM_HANDLE hHandle = vboxWddmHTableIndex2Handle(pIter->iCur);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync Assert(hHandle);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync if (hHandle)
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync {
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync PVOID pRet = vboxWddmHTableRemove(pIter->pTbl, hHandle);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync Assert(pRet);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync return pRet;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync }
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync return NULL;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync}
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsyncPVBOXWDDM_SWAPCHAIN vboxWddmSwapchainCreate()
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync{
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync PVBOXWDDM_SWAPCHAIN pSwapchain = (PVBOXWDDM_SWAPCHAIN)vboxWddmMemAllocZero(sizeof (VBOXWDDM_SWAPCHAIN));
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync Assert(pSwapchain);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync if (pSwapchain)
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync {
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync InitializeListHead(&pSwapchain->AllocList);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync pSwapchain->enmState = VBOXWDDM_OBJSTATE_TYPE_INITIALIZED;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync pSwapchain->cRefs = 1;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync }
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync return pSwapchain;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync}
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsyncDECLINLINE(BOOLEAN) vboxWddmSwapchainRetainLocked(PVBOXWDDM_SWAPCHAIN pSwapchain)
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync{
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync if (pSwapchain->enmState == VBOXWDDM_OBJSTATE_TYPE_INITIALIZED)
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync {
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync ASMAtomicIncU32(&pSwapchain->cRefs);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync return TRUE;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync }
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync return FALSE;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync}
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsyncDECLINLINE(BOOLEAN) vboxWddmSwapchainRetain(PVBOXMP_DEVEXT pDevExt, PVBOXWDDM_SWAPCHAIN pSwapchain)
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync{
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync KIRQL OldIrql;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync BOOLEAN bRc;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync KeAcquireSpinLock(&pDevExt->SynchLock, &OldIrql);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync bRc = vboxWddmSwapchainRetainLocked(pSwapchain);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync KeReleaseSpinLock(&pDevExt->SynchLock, OldIrql);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync return bRc;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync}
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsyncDECLINLINE(VOID) vboxWddmSwapchainRelease(PVBOXWDDM_SWAPCHAIN pSwapchain)
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync{
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync const uint32_t cRefs = ASMAtomicDecU32(&pSwapchain->cRefs);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync Assert(cRefs < UINT32_MAX/2);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync if (!cRefs)
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync {
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync vboxWddmMemFree(pSwapchain);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync }
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync}
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsyncPVBOXWDDM_SWAPCHAIN vboxWddmSwapchainRetainByAlloc(PVBOXMP_DEVEXT pDevExt, PVBOXWDDM_ALLOCATION pAlloc)
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync{
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync KIRQL OldIrql;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync PVBOXWDDM_SWAPCHAIN pSwapchain;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync KeAcquireSpinLock(&pDevExt->SynchLock, &OldIrql);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync pSwapchain = pAlloc->pSwapchain;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync if (pSwapchain && !vboxWddmSwapchainRetainLocked(pSwapchain))
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync pSwapchain = NULL;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync KeReleaseSpinLock(&pDevExt->SynchLock, OldIrql);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync return pSwapchain;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync}
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsyncVOID vboxWddmSwapchainAllocRemove(PVBOXMP_DEVEXT pDevExt, PVBOXWDDM_SWAPCHAIN pSwapchain, PVBOXWDDM_ALLOCATION pAlloc)
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync{
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync KIRQL OldIrql;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync KeAcquireSpinLock(&pDevExt->SynchLock, &OldIrql);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync Assert(pAlloc->pSwapchain == pSwapchain);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync pAlloc->pSwapchain = NULL;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync RemoveEntryList(&pAlloc->SwapchainEntry);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync KeReleaseSpinLock(&pDevExt->SynchLock, OldIrql);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync vboxWddmSwapchainRelease(pSwapchain);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync}
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsyncBOOLEAN vboxWddmSwapchainAllocAdd(PVBOXMP_DEVEXT pDevExt, PVBOXWDDM_SWAPCHAIN pSwapchain, PVBOXWDDM_ALLOCATION pAlloc)
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync{
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync KIRQL OldIrql;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync BOOLEAN bRc;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync Assert(!pAlloc->pSwapchain);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync KeAcquireSpinLock(&pDevExt->SynchLock, &OldIrql);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync bRc = vboxWddmSwapchainRetainLocked(pSwapchain);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync if (bRc)
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync {
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync if (pAlloc->pSwapchain)
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync {
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync RemoveEntryList(&pAlloc->SwapchainEntry);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync }
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync InsertTailList(&pSwapchain->AllocList, &pAlloc->SwapchainEntry);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync pAlloc->pSwapchain = pSwapchain;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync }
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync KeReleaseSpinLock(&pDevExt->SynchLock, OldIrql);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync return bRc;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync}
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync#define VBOXSCENTRY_2_ALLOC(_pE) ((PVBOXWDDM_ALLOCATION)((uint8_t*)(_pE) - RT_OFFSETOF(VBOXWDDM_ALLOCATION, SwapchainEntry)))
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsyncstatic VOID vboxWddmSwapchainAllocRemoveAllInternal(PVBOXMP_DEVEXT pDevExt, PVBOXWDDM_SWAPCHAIN pSwapchain, BOOLEAN bOnDestroy)
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync{
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync KIRQL OldIrql;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync UINT cRemoved = 0;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync KeAcquireSpinLock(&pDevExt->SynchLock, &OldIrql);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync PLIST_ENTRY pEntry = pSwapchain->AllocList.Flink;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync do
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync {
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync if (pEntry != &pSwapchain->AllocList)
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync {
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync PVBOXWDDM_ALLOCATION pAlloc = VBOXSCENTRY_2_ALLOC(pEntry);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync pEntry = pEntry->Flink;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync Assert(pAlloc->pSwapchain == pSwapchain);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync pAlloc->pSwapchain = NULL;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync RemoveEntryList(&pAlloc->SwapchainEntry);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync ++cRemoved;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync }
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync else
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync break;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync } while (1);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync if (bOnDestroy)
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync pSwapchain->enmState = VBOXWDDM_OBJSTATE_TYPE_TERMINATED;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync KeReleaseSpinLock(&pDevExt->SynchLock, OldIrql);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync for (UINT i = 0; i < cRemoved; ++i)
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync vboxWddmSwapchainRelease(pSwapchain);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync}
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsyncVOID vboxWddmSwapchainAllocRemoveAll(PVBOXMP_DEVEXT pDevExt, PVBOXWDDM_SWAPCHAIN pSwapchain)
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync{
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync vboxWddmSwapchainAllocRemoveAllInternal(pDevExt, pSwapchain, FALSE);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync}
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsyncVOID vboxWddmSwapchainDestroy(PVBOXMP_DEVEXT pDevExt, PVBOXWDDM_SWAPCHAIN pSwapchain)
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync{
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync vboxWddmSwapchainAllocRemoveAllInternal(pDevExt, pSwapchain, TRUE);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync Assert(pSwapchain->pContext);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync if (pSwapchain->pContext)
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync {
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync NTSTATUS tmpStatus = vboxVdmaGgCmdCancel(pDevExt, pSwapchain->pContext, pSwapchain);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync if (tmpStatus != STATUS_SUCCESS)
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync {
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync WARN(("vboxVdmaGgCmdCancel returned Status (0x%x)", tmpStatus));
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync }
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync }
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync vboxWddmSwapchainRelease(pSwapchain);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync}
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsyncstatic BOOLEAN vboxWddmSwapchainCtxAddLocked(PVBOXMP_DEVEXT pDevExt, PVBOXWDDM_CONTEXT pContext, PVBOXWDDM_SWAPCHAIN pSwapchain)
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync{
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync if (vboxWddmSwapchainRetain(pDevExt, pSwapchain))
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync {
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync Assert(!pSwapchain->hSwapchainKm);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync Assert(!pSwapchain->pContext);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync pSwapchain->pContext = pContext;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync pSwapchain->hSwapchainKm = vboxWddmHTablePut(&pContext->Swapchains, pSwapchain);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync InsertHeadList(&pDevExt->SwapchainList3D, &pSwapchain->DevExtListEntry);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync return TRUE;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync }
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync return FALSE;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync}
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsyncstatic VOID vboxWddmSwapchainCtxRemoveLocked(PVBOXMP_DEVEXT pDevExt, PVBOXWDDM_CONTEXT pContext, PVBOXWDDM_SWAPCHAIN pSwapchain)
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync{
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync Assert(pSwapchain->hSwapchainKm);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync Assert(pSwapchain->pContext);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync void * pTst = vboxWddmHTableRemove(&pContext->Swapchains, pSwapchain->hSwapchainKm);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync Assert(pTst == pSwapchain);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync RemoveEntryList(&pSwapchain->DevExtListEntry);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync pSwapchain->hSwapchainKm = NULL;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync if (pSwapchain->pLastReportedRects)
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync {
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync vboxVideoCmCmdRelease(pSwapchain->pLastReportedRects);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync pSwapchain->pLastReportedRects = NULL;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync }
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync vboxWddmSwapchainRelease(pSwapchain);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync}
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync/* adds the given swapchain to the context's swapchain list
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync * @return true on success */
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsyncBOOLEAN vboxWddmSwapchainCtxAdd(PVBOXMP_DEVEXT pDevExt, PVBOXWDDM_CONTEXT pContext, PVBOXWDDM_SWAPCHAIN pSwapchain)
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync{
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync BOOLEAN bRc;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync ExAcquireFastMutex(&pDevExt->ContextMutex);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync bRc = vboxWddmSwapchainCtxAddLocked(pDevExt, pContext, pSwapchain);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync ExReleaseFastMutex(&pDevExt->ContextMutex);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync return bRc;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync}
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync/* removes the given swapchain from the context's swapchain list
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync * */
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsyncVOID vboxWddmSwapchainCtxRemove(PVBOXMP_DEVEXT pDevExt, PVBOXWDDM_CONTEXT pContext, PVBOXWDDM_SWAPCHAIN pSwapchain)
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync{
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync ExAcquireFastMutex(&pDevExt->ContextMutex);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync vboxWddmSwapchainCtxRemoveLocked(pDevExt, pContext, pSwapchain);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync ExReleaseFastMutex(&pDevExt->ContextMutex);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync}
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync/* destroys all swapchains for the given context
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync * */
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsyncVOID vboxWddmSwapchainCtxDestroyAll(PVBOXMP_DEVEXT pDevExt, PVBOXWDDM_CONTEXT pContext)
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync{
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync VBOXWDDM_HTABLE_ITERATOR Iter;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync do
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync {
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync ExAcquireFastMutex(&pDevExt->ContextMutex);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync vboxWddmHTableIterInit(&pContext->Swapchains, &Iter);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync PVBOXWDDM_SWAPCHAIN pSwapchain = (PVBOXWDDM_SWAPCHAIN)vboxWddmHTableIterNext(&Iter, NULL);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync if (!pSwapchain)
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync break;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync /* yes, we can call remove locked even when using iterator */
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync vboxWddmSwapchainCtxRemoveLocked(pDevExt, pContext, pSwapchain);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync ExReleaseFastMutex(&pDevExt->ContextMutex);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync /* we must not do vboxWddmSwapchainDestroy inside a context mutex */
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync vboxWddmSwapchainDestroy(pDevExt, pSwapchain);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync /* start from the very beginning, we will quit the loop when no swapchains left */
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync } while (1);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync /* no swapchains left, we exiteed the while loop via the "break", and we still owning the mutex */
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync ExReleaseFastMutex(&pDevExt->ContextMutex);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync}
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync/* process the swapchain info passed from user-mode display driver & synchronizes the driver state with it */
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsyncNTSTATUS vboxWddmSwapchainCtxEscape(PVBOXMP_DEVEXT pDevExt, PVBOXWDDM_CONTEXT pContext, PVBOXDISPIFESCAPE_SWAPCHAININFO pSwapchainInfo, UINT cbSize)
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync{
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync Assert((cbSize >= RT_OFFSETOF(VBOXDISPIFESCAPE_SWAPCHAININFO, SwapchainInfo.ahAllocs[0])));
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync if (cbSize < RT_OFFSETOF(VBOXDISPIFESCAPE_SWAPCHAININFO, SwapchainInfo.ahAllocs[0]))
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync return STATUS_INVALID_PARAMETER;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync Assert(cbSize >= RT_OFFSETOF(VBOXDISPIFESCAPE_SWAPCHAININFO, SwapchainInfo.ahAllocs[pSwapchainInfo->SwapchainInfo.cAllocs]));
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync if (cbSize < RT_OFFSETOF(VBOXDISPIFESCAPE_SWAPCHAININFO, SwapchainInfo.ahAllocs[pSwapchainInfo->SwapchainInfo.cAllocs]))
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync return STATUS_INVALID_PARAMETER;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync PVBOXWDDM_SWAPCHAIN pSwapchain = NULL;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync PVBOXWDDM_ALLOCATION *apAlloc = NULL;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync Assert(KeGetCurrentIrql() == PASSIVE_LEVEL);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync NTSTATUS Status = STATUS_SUCCESS;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync do {
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync if (pSwapchainInfo->SwapchainInfo.cAllocs)
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync {
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync apAlloc = (PVBOXWDDM_ALLOCATION *)vboxWddmMemAlloc(sizeof (PVBOXWDDM_ALLOCATION) * pSwapchainInfo->SwapchainInfo.cAllocs);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync Assert(apAlloc);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync if (!apAlloc)
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync {
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync Status = STATUS_NO_MEMORY;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync break;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync }
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync for (UINT i = 0; i < pSwapchainInfo->SwapchainInfo.cAllocs; ++i)
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync {
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync DXGKARGCB_GETHANDLEDATA GhData;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync GhData.hObject = pSwapchainInfo->SwapchainInfo.ahAllocs[i];
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync GhData.Type = DXGK_HANDLE_ALLOCATION;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync GhData.Flags.Value = 0;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync PVBOXWDDM_ALLOCATION pAlloc = (PVBOXWDDM_ALLOCATION)pDevExt->u.primary.DxgkInterface.DxgkCbGetHandleData(&GhData);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync Assert(pAlloc);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync if (!pAlloc)
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync {
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync Status = STATUS_INVALID_PARAMETER;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync break;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync }
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync apAlloc[i] = pAlloc;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync }
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync if (!NT_SUCCESS(Status))
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync break;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync }
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync if (pSwapchainInfo->SwapchainInfo.hSwapchainKm)
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync {
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync ExAcquireFastMutex(&pDevExt->ContextMutex);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync pSwapchain = (PVBOXWDDM_SWAPCHAIN)vboxWddmHTableGet(&pContext->Swapchains, (VBOXWDDM_HANDLE)pSwapchainInfo->SwapchainInfo.hSwapchainKm);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync Assert(pSwapchain);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync if (!pSwapchain)
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync {
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync ExReleaseFastMutex(&pDevExt->ContextMutex);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync Status = STATUS_INVALID_PARAMETER;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync break;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync }
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync Assert(pSwapchain->hSwapchainKm == pSwapchainInfo->SwapchainInfo.hSwapchainKm);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync Assert(pSwapchain->pContext == pContext);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync if (pSwapchain->pContext != pContext)
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync {
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync ExReleaseFastMutex(&pDevExt->ContextMutex);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync Status = STATUS_INVALID_PARAMETER;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync break;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync }
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync }
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync else if (pSwapchainInfo->SwapchainInfo.cAllocs)
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync {
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync pSwapchain = vboxWddmSwapchainCreate();
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync if (!pSwapchain)
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync {
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync Status = STATUS_NO_MEMORY;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync break;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync }
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync ExAcquireFastMutex(&pDevExt->ContextMutex);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync BOOLEAN bRc = vboxWddmSwapchainCtxAddLocked(pDevExt, pContext, pSwapchain);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync Assert(bRc);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync }
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync else
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync {
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync Status = STATUS_INVALID_PARAMETER;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync break;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync }
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync /* do not zero up the view rect since it may still be valid */
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync// memset(&pSwapchain->ViewRect, 0, sizeof (pSwapchain->ViewRect));
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync if (pSwapchain->pLastReportedRects)
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync {
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync vboxVideoCmCmdRelease(pSwapchain->pLastReportedRects);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync pSwapchain->pLastReportedRects = NULL;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync }
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync vboxWddmSwapchainAllocRemoveAll(pDevExt, pSwapchain);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync if (pSwapchainInfo->SwapchainInfo.cAllocs)
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync {
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync for (UINT i = 0; i < pSwapchainInfo->SwapchainInfo.cAllocs; ++i)
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync {
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync vboxWddmSwapchainAllocAdd(pDevExt, pSwapchain, apAlloc[i]);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync }
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync pSwapchain->hSwapchainUm = pSwapchainInfo->SwapchainInfo.hSwapchainUm;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync }
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync else
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync {
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync vboxWddmSwapchainCtxRemoveLocked(pDevExt, pContext, pSwapchain);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync }
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync ExReleaseFastMutex(&pDevExt->ContextMutex);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync if (pSwapchainInfo->SwapchainInfo.cAllocs)
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync {
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync Assert(pSwapchain->pContext);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync Assert(pSwapchain->hSwapchainKm);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync pSwapchainInfo->SwapchainInfo.hSwapchainKm = pSwapchain->hSwapchainKm;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync }
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync else
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync {
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync vboxWddmSwapchainDestroy(pDevExt, pSwapchain);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync pSwapchainInfo->SwapchainInfo.hSwapchainKm = 0;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync }
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync Assert(Status == STATUS_SUCCESS);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync } while (0);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync /* cleanup */
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync if (apAlloc)
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync vboxWddmMemFree(apAlloc);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync return Status;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync}
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsyncNTSTATUS vboxWddmSwapchainCtxInit(PVBOXMP_DEVEXT pDevExt, PVBOXWDDM_CONTEXT pContext)
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync{
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync NTSTATUS Status = vboxWddmHTableCreate(&pContext->Swapchains, 4);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync if (!NT_SUCCESS(Status))
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync {
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync WARN(("vboxWddmHTableCreate failes, Status (x%x)", Status));
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync return Status;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync }
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync return STATUS_SUCCESS;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync}
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsyncVOID vboxWddmSwapchainCtxTerm(PVBOXMP_DEVEXT pDevExt, PVBOXWDDM_CONTEXT pContext)
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync{
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync vboxWddmSwapchainCtxDestroyAll(pDevExt, pContext);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync vboxWddmHTableDestroy(&pContext->Swapchains);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync}
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync#define VBOXWDDM_REG_DRVKEY_PREFIX L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Class\\"
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsyncNTSTATUS vboxWddmRegQueryDrvKeyName(PVBOXMP_DEVEXT pDevExt, ULONG cbBuf, PWCHAR pBuf, PULONG pcbResult)
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync{
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync WCHAR fallBackBuf[2];
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync PWCHAR pSuffix;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync bool bFallback = false;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync if (cbBuf > sizeof(VBOXWDDM_REG_DRVKEY_PREFIX))
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync {
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync memcpy(pBuf, VBOXWDDM_REG_DRVKEY_PREFIX, sizeof (VBOXWDDM_REG_DRVKEY_PREFIX));
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync pSuffix = pBuf + (sizeof (VBOXWDDM_REG_DRVKEY_PREFIX)-2)/2;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync cbBuf -= sizeof (VBOXWDDM_REG_DRVKEY_PREFIX)-2;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync }
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync else
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync {
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync pSuffix = fallBackBuf;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync cbBuf = sizeof (fallBackBuf);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync bFallback = true;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync }
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync NTSTATUS Status = IoGetDeviceProperty (pDevExt->pPDO,
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync DevicePropertyDriverKeyName,
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync cbBuf,
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync pSuffix,
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync &cbBuf);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync if (Status == STATUS_SUCCESS && bFallback)
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync Status = STATUS_BUFFER_TOO_SMALL;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync if (Status == STATUS_BUFFER_TOO_SMALL)
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync *pcbResult = cbBuf + sizeof (VBOXWDDM_REG_DRVKEY_PREFIX)-2;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync return Status;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync}
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync#define VBOXWDDM_REG_DISPLAYSETTINGSKEY_PREFIX_VISTA L"\\Registry\\Machine\\System\\CurrentControlSet\\Hardware Profiles\\Current\\System\\CurrentControlSet\\Control\\VIDEO\\"
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync#define VBOXWDDM_REG_DISPLAYSETTINGSKEY_PREFIX_WIN7 L"\\Registry\\Machine\\System\\CurrentControlSet\\Hardware Profiles\\UnitedVideo\\CONTROL\\VIDEO\\"
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync#define VBOXWDDM_REG_DISPLAYSETTINGS_ATTACH_RELX L"Attach.RelativeX"
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync#define VBOXWDDM_REG_DISPLAYSETTINGS_ATTACH_RELY L"Attach.RelativeY"
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync#define VBOXWDDM_REG_DISPLAYSETTINGS_ATTACH_DESKTOP L"Attach.ToDesktop"
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsyncNTSTATUS vboxWddmRegQueryDisplaySettingsKeyName(PVBOXMP_DEVEXT pDevExt, D3DDDI_VIDEO_PRESENT_SOURCE_ID VidPnSourceId,
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync ULONG cbBuf, PWCHAR pBuf, PULONG pcbResult)
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync{
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync NTSTATUS Status = STATUS_SUCCESS;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync PWCHAR pSuffix;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync bool bFallback = false;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync const WCHAR* pKeyPrefix;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync UINT cbKeyPrefix;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync UNICODE_STRING* pVGuid = vboxWddmVGuidGet(pDevExt);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync Assert(pVGuid);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync if (!pVGuid)
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync return STATUS_UNSUCCESSFUL;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync vboxWinVersion_t ver = VBoxQueryWinVersion();
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync if (ver == WINVISTA)
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync {
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync pKeyPrefix = VBOXWDDM_REG_DISPLAYSETTINGSKEY_PREFIX_VISTA;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync cbKeyPrefix = sizeof (VBOXWDDM_REG_DISPLAYSETTINGSKEY_PREFIX_VISTA);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync }
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync else
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync {
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync Assert(ver == WIN7 || ver == WIN8);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync pKeyPrefix = VBOXWDDM_REG_DISPLAYSETTINGSKEY_PREFIX_WIN7;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync cbKeyPrefix = sizeof (VBOXWDDM_REG_DISPLAYSETTINGSKEY_PREFIX_WIN7);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync }
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync ULONG cbResult = cbKeyPrefix + pVGuid->Length + 2 + 8; // L"\\" + "XXXX"
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync if (cbBuf >= cbResult)
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync {
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync wcscpy(pBuf, pKeyPrefix);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync pSuffix = pBuf + (cbKeyPrefix-2)/2;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync memcpy(pSuffix, pVGuid->Buffer, pVGuid->Length);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync pSuffix += pVGuid->Length/2;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync pSuffix[0] = L'\\';
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync pSuffix += 1;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync swprintf(pSuffix, L"%04d", VidPnSourceId);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync }
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync else
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync {
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync Status = STATUS_BUFFER_TOO_SMALL;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync }
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync *pcbResult = cbResult;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync return Status;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync}
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync#define VBOXWDDM_REG_DISPLAYSETTINGSVIDEOKEY L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Video\\"
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync#define VBOXWDDM_REG_DISPLAYSETTINGSVIDEOKEY_SUBKEY L"\\Video"
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsyncNTSTATUS vboxWddmRegQueryVideoGuidString(ULONG cbBuf, PWCHAR pBuf, PULONG pcbResult)
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync{
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync HANDLE hKey;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync NTSTATUS Status = vboxWddmRegOpenKey(&hKey, VBOXWDDM_REG_DISPLAYSETTINGSVIDEOKEY, GENERIC_READ);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync Assert(Status == STATUS_SUCCESS);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync if (Status == STATUS_SUCCESS)
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync {
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync struct
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync {
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync KEY_BASIC_INFORMATION Name;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync WCHAR Buf[256];
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync } Buf;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync WCHAR KeyBuf[sizeof (VBOXWDDM_REG_DISPLAYSETTINGSVIDEOKEY)/2 + 256 + 64];
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync wcscpy(KeyBuf, VBOXWDDM_REG_DISPLAYSETTINGSVIDEOKEY);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync ULONG ResultLength;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync BOOL bFound = FALSE;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync for (ULONG i = 0; !bFound; ++i)
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync {
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync RtlZeroMemory(&Buf, sizeof (Buf));
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync Status = ZwEnumerateKey(hKey, i, KeyBasicInformation, &Buf, sizeof (Buf), &ResultLength);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync Assert(Status == STATUS_SUCCESS);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync /* we should not encounter STATUS_NO_MORE_ENTRIES here since this would mean we did not find our entry */
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync if (Status != STATUS_SUCCESS)
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync break;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync HANDLE hSubKey;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync PWCHAR pSubBuf = KeyBuf + (sizeof (VBOXWDDM_REG_DISPLAYSETTINGSVIDEOKEY) - 2)/2;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync memcpy(pSubBuf, Buf.Name.Name, Buf.Name.NameLength);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync pSubBuf += Buf.Name.NameLength/2;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync memcpy(pSubBuf, VBOXWDDM_REG_DISPLAYSETTINGSVIDEOKEY_SUBKEY, sizeof (VBOXWDDM_REG_DISPLAYSETTINGSVIDEOKEY_SUBKEY));
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync Status = vboxWddmRegOpenKey(&hSubKey, KeyBuf, GENERIC_READ);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync Assert(Status == STATUS_SUCCESS);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync if (Status == STATUS_SUCCESS)
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync {
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync struct
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync {
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync KEY_VALUE_PARTIAL_INFORMATION Info;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync UCHAR Buf[sizeof (L"VBoxVideoWddm")]; /* should be enough */
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync } KeyData;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync ULONG cbResult;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync UNICODE_STRING RtlStr;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync RtlInitUnicodeString(&RtlStr, L"Service");
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync Status = ZwQueryValueKey(hSubKey,
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync &RtlStr,
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync KeyValuePartialInformation,
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync &KeyData.Info,
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync sizeof(KeyData),
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync &cbResult);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync Assert(Status == STATUS_SUCCESS || STATUS_BUFFER_TOO_SMALL || STATUS_BUFFER_OVERFLOW);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync if (Status == STATUS_SUCCESS)
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync {
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync if (KeyData.Info.Type == REG_SZ)
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync {
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync if (KeyData.Info.DataLength == sizeof (L"VBoxVideoWddm"))
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync {
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync if (!wcscmp(L"VBoxVideoWddm", (PWCHAR)KeyData.Info.Data))
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync {
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync bFound = TRUE;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync *pcbResult = Buf.Name.NameLength + 2;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync if (cbBuf >= Buf.Name.NameLength + 2)
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync {
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync memcpy(pBuf, Buf.Name.Name, Buf.Name.NameLength + 2);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync }
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync else
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync {
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync Status = STATUS_BUFFER_TOO_SMALL;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync }
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync }
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync }
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync }
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync }
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync NTSTATUS tmpStatus = ZwClose(hSubKey);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync Assert(tmpStatus == STATUS_SUCCESS);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync }
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync else
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync break;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync }
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync NTSTATUS tmpStatus = ZwClose(hKey);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync Assert(tmpStatus == STATUS_SUCCESS);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync }
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync return Status;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync}
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsyncNTSTATUS vboxWddmRegOpenKey(OUT PHANDLE phKey, IN PWCHAR pName, IN ACCESS_MASK fAccess)
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync{
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync OBJECT_ATTRIBUTES ObjAttr;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync UNICODE_STRING RtlStr;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync RtlInitUnicodeString(&RtlStr, pName);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync InitializeObjectAttributes(&ObjAttr, &RtlStr, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync return ZwOpenKey(phKey, fAccess, &ObjAttr);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync}
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsyncNTSTATUS vboxWddmRegOpenDisplaySettingsKey(IN PVBOXMP_DEVEXT pDeviceExtension, D3DDDI_VIDEO_PRESENT_SOURCE_ID VidPnSourceId, OUT PHANDLE phKey)
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync{
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync WCHAR Buf[512];
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync ULONG cbBuf = sizeof(Buf);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync NTSTATUS Status = vboxWddmRegQueryDisplaySettingsKeyName(pDeviceExtension, VidPnSourceId, cbBuf, Buf, &cbBuf);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync Assert(Status == STATUS_SUCCESS);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync if (Status == STATUS_SUCCESS)
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync {
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync Status = vboxWddmRegOpenKey(phKey, Buf, GENERIC_READ);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync Assert(Status == STATUS_SUCCESS);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync if(Status == STATUS_SUCCESS)
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync return STATUS_SUCCESS;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync }
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync /* fall-back to make the subsequent VBoxVideoCmnRegXxx calls treat the fail accordingly
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync * basically needed to make as less modifications to the current XPDM code as possible */
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync *phKey = NULL;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync return Status;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync}
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsyncNTSTATUS vboxWddmRegDisplaySettingsQueryRelX(HANDLE hKey, int * pResult)
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync{
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync DWORD dwVal;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync NTSTATUS Status = vboxWddmRegQueryValueDword(hKey, VBOXWDDM_REG_DISPLAYSETTINGS_ATTACH_RELX, &dwVal);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync Assert(Status == STATUS_SUCCESS);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync if (Status == STATUS_SUCCESS)
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync {
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync *pResult = (int)dwVal;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync }
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync return Status;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync}
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsyncNTSTATUS vboxWddmRegDisplaySettingsQueryRelY(HANDLE hKey, int * pResult)
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync{
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync DWORD dwVal;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync NTSTATUS Status = vboxWddmRegQueryValueDword(hKey, VBOXWDDM_REG_DISPLAYSETTINGS_ATTACH_RELY, &dwVal);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync Assert(Status == STATUS_SUCCESS);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync if (Status == STATUS_SUCCESS)
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync {
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync *pResult = (int)dwVal;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync }
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync return Status;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync}
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsyncNTSTATUS vboxWddmDisplaySettingsQueryPos(IN PVBOXMP_DEVEXT pDeviceExtension, D3DDDI_VIDEO_PRESENT_SOURCE_ID VidPnSourceId, POINT * pPos)
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync{
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync Assert(KeGetCurrentIrql() == PASSIVE_LEVEL);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync HANDLE hKey;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync NTSTATUS Status = vboxWddmRegOpenDisplaySettingsKey(pDeviceExtension, VidPnSourceId, &hKey);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync Assert(Status == STATUS_SUCCESS);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync if (Status == STATUS_SUCCESS)
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync {
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync int x, y;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync Status = vboxWddmRegDisplaySettingsQueryRelX(hKey, &x);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync Assert(Status == STATUS_SUCCESS);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync if (Status == STATUS_SUCCESS)
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync {
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync Status = vboxWddmRegDisplaySettingsQueryRelY(hKey, &y);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync Assert(Status == STATUS_SUCCESS);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync if (Status == STATUS_SUCCESS)
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync {
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync pPos->x = x;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync pPos->y = y;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync }
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync }
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync NTSTATUS tmpStatus = ZwClose(hKey);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync Assert(tmpStatus == STATUS_SUCCESS);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync }
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync return Status;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync}
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsyncNTSTATUS vboxWddmRegQueryValueDword(IN HANDLE hKey, IN PWCHAR pName, OUT PDWORD pDword)
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync{
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync struct
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync {
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync KEY_VALUE_PARTIAL_INFORMATION Info;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync UCHAR Buf[32]; /* should be enough */
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync } Buf;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync ULONG cbBuf;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync UNICODE_STRING RtlStr;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync RtlInitUnicodeString(&RtlStr, pName);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync NTSTATUS Status = ZwQueryValueKey(hKey,
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync &RtlStr,
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync KeyValuePartialInformation,
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync &Buf.Info,
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync sizeof(Buf),
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync &cbBuf);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync if (Status == STATUS_SUCCESS)
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync {
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync if (Buf.Info.Type == REG_DWORD)
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync {
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync Assert(Buf.Info.DataLength == 4);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync *pDword = *((PULONG)Buf.Info.Data);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync return STATUS_SUCCESS;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync }
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync }
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync return STATUS_INVALID_PARAMETER;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync}
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsyncNTSTATUS vboxWddmRegSetValueDword(IN HANDLE hKey, IN PWCHAR pName, OUT DWORD val)
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync{
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync UNICODE_STRING RtlStr;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync RtlInitUnicodeString(&RtlStr, pName);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync return ZwSetValueKey(hKey, &RtlStr,
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync NULL, /* IN ULONG TitleIndex OPTIONAL, reserved */
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync REG_DWORD,
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync &val,
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync sizeof(val));
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync}
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsyncUNICODE_STRING* vboxWddmVGuidGet(PVBOXMP_DEVEXT pDevExt)
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync{
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync if (pDevExt->VideoGuid.Buffer)
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync return &pDevExt->VideoGuid;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync Assert(KeGetCurrentIrql() == PASSIVE_LEVEL);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync WCHAR VideoGuidBuf[512];
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync ULONG cbVideoGuidBuf = sizeof (VideoGuidBuf);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync NTSTATUS Status = vboxWddmRegQueryVideoGuidString(cbVideoGuidBuf, VideoGuidBuf, &cbVideoGuidBuf);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync Assert(Status == STATUS_SUCCESS);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync if (Status == STATUS_SUCCESS)
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync {
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync PWCHAR pBuf = (PWCHAR)vboxWddmMemAllocZero(cbVideoGuidBuf);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync Assert(pBuf);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync if (pBuf)
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync {
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync memcpy(pBuf, VideoGuidBuf, cbVideoGuidBuf);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync RtlInitUnicodeString(&pDevExt->VideoGuid, pBuf);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync return &pDevExt->VideoGuid;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync }
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync }
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync return NULL;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync}
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsyncVOID vboxWddmVGuidFree(PVBOXMP_DEVEXT pDevExt)
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync{
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync if (pDevExt->VideoGuid.Buffer)
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync {
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync vboxWddmMemFree(pDevExt->VideoGuid.Buffer);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync pDevExt->VideoGuid.Buffer = NULL;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync }
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync}
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync/* mm */
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsyncNTSTATUS vboxMmInit(PVBOXWDDM_MM pMm, UINT cPages)
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync{
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync UINT cbBuffer = VBOXWDDM_ROUNDBOUND(cPages, 8) >> 3;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync cbBuffer = VBOXWDDM_ROUNDBOUND(cbBuffer, 4);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync PULONG pBuf = (PULONG)vboxWddmMemAllocZero(cbBuffer);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync if (!pBuf)
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync {
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync Assert(0);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync return STATUS_NO_MEMORY;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync }
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync RtlInitializeBitMap(&pMm->BitMap, pBuf, cPages);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync pMm->cPages = cPages;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync pMm->cAllocs = 0;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync pMm->pBuffer = pBuf;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync return STATUS_SUCCESS;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync}
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsyncULONG vboxMmAlloc(PVBOXWDDM_MM pMm, UINT cPages)
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync{
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync ULONG iPage = RtlFindClearBitsAndSet(&pMm->BitMap, cPages, 0);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync if (iPage == 0xFFFFFFFF)
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync {
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync Assert(0);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync return VBOXWDDM_MM_VOID;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync }
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync ++pMm->cAllocs;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync return iPage;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync}
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsyncVOID vboxMmFree(PVBOXWDDM_MM pMm, UINT iPage, UINT cPages)
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync{
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync Assert(RtlAreBitsSet(&pMm->BitMap, iPage, cPages));
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync RtlClearBits(&pMm->BitMap, iPage, cPages);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync --pMm->cAllocs;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync Assert(pMm->cAllocs < UINT32_MAX);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync}
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsyncNTSTATUS vboxMmTerm(PVBOXWDDM_MM pMm)
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync{
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync Assert(!pMm->cAllocs);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync vboxWddmMemFree(pMm->pBuffer);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync pMm->pBuffer = NULL;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync return STATUS_SUCCESS;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync}
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsynctypedef struct VBOXVIDEOCM_ALLOC
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync{
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync VBOXWDDM_HANDLE hGlobalHandle;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync uint32_t offData;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync uint32_t cbData;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync} VBOXVIDEOCM_ALLOC, *PVBOXVIDEOCM_ALLOC;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsynctypedef struct VBOXVIDEOCM_ALLOC_REF
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync{
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync PVBOXVIDEOCM_ALLOC_CONTEXT pContext;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync VBOXWDDM_HANDLE hSessionHandle;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync PVBOXVIDEOCM_ALLOC pAlloc;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync union
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync {
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync PKEVENT pSynchEvent;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync PRKSEMAPHORE pSynchSemaphore;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync };
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync VBOXUHGSMI_SYNCHOBJECT_TYPE enmSynchType;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync volatile uint32_t cRefs;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync MDL Mdl;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync} VBOXVIDEOCM_ALLOC_REF, *PVBOXVIDEOCM_ALLOC_REF;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsyncNTSTATUS vboxVideoCmAllocAlloc(PVBOXVIDEOCM_ALLOC_MGR pMgr, PVBOXVIDEOCM_ALLOC pAlloc)
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync{
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync NTSTATUS Status = STATUS_UNSUCCESSFUL;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync UINT cbSize = pAlloc->cbData;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync UINT cPages = BYTES_TO_PAGES(cbSize);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync ExAcquireFastMutex(&pMgr->Mutex);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync UINT iPage = vboxMmAlloc(&pMgr->Mm, cPages);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync if (iPage != VBOXWDDM_MM_VOID)
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync {
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync uint32_t offData = pMgr->offData + (iPage << PAGE_SHIFT);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync Assert(offData + cbSize <= pMgr->offData + pMgr->cbData);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync pAlloc->offData = offData;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync pAlloc->hGlobalHandle = vboxWddmHTablePut(&pMgr->AllocTable, pAlloc);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync ExReleaseFastMutex(&pMgr->Mutex);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync if (VBOXWDDM_HANDLE_INVALID != pAlloc->hGlobalHandle)
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync return STATUS_SUCCESS;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync Assert(0);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync Status = STATUS_NO_MEMORY;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync vboxMmFree(&pMgr->Mm, iPage, cPages);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync }
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync else
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync {
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync Assert(0);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync ExReleaseFastMutex(&pMgr->Mutex);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync Status = STATUS_INSUFFICIENT_RESOURCES;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync }
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync return Status;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync}
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsyncVOID vboxVideoCmAllocDealloc(PVBOXVIDEOCM_ALLOC_MGR pMgr, PVBOXVIDEOCM_ALLOC pAlloc)
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync{
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync UINT cbSize = pAlloc->cbData;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync UINT cPages = BYTES_TO_PAGES(cbSize);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync UINT iPage = BYTES_TO_PAGES(pAlloc->offData - pMgr->offData);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync ExAcquireFastMutex(&pMgr->Mutex);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync vboxWddmHTableRemove(&pMgr->AllocTable, pAlloc->hGlobalHandle);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync vboxMmFree(&pMgr->Mm, iPage, cPages);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync ExReleaseFastMutex(&pMgr->Mutex);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync}
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsyncNTSTATUS vboxVideoAMgrAllocCreate(PVBOXVIDEOCM_ALLOC_MGR pMgr, UINT cbSize, PVBOXVIDEOCM_ALLOC *ppAlloc)
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync{
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync NTSTATUS Status = STATUS_SUCCESS;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync PVBOXVIDEOCM_ALLOC pAlloc = (PVBOXVIDEOCM_ALLOC)vboxWddmMemAllocZero(sizeof (*pAlloc));
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync if (pAlloc)
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync {
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync pAlloc->cbData = cbSize;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync Status = vboxVideoCmAllocAlloc(pMgr, pAlloc);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync if (Status == STATUS_SUCCESS)
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync {
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync *ppAlloc = pAlloc;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync return STATUS_SUCCESS;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync }
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync Assert(0);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync vboxWddmMemFree(pAlloc);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync }
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync else
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync {
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync Assert(0);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync Status = STATUS_NO_MEMORY;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync }
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync return Status;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync}
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsyncVOID vboxVideoAMgrAllocDestroy(PVBOXVIDEOCM_ALLOC_MGR pMgr, PVBOXVIDEOCM_ALLOC pAlloc)
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync{
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync vboxVideoCmAllocDealloc(pMgr, pAlloc);
vboxWddmMemFree(pAlloc);
}
NTSTATUS vboxVideoAMgrCtxAllocMap(PVBOXVIDEOCM_ALLOC_CONTEXT pContext, PVBOXVIDEOCM_ALLOC pAlloc, PVBOXVIDEOCM_UM_ALLOC pUmAlloc)
{
PVBOXVIDEOCM_ALLOC_MGR pMgr = pContext->pMgr;
NTSTATUS Status = STATUS_SUCCESS;
union
{
PKEVENT pSynchEvent;
PRKSEMAPHORE pSynchSemaphore;
};
switch (pUmAlloc->enmSynchType)
{
case VBOXUHGSMI_SYNCHOBJECT_TYPE_EVENT:
Status = ObReferenceObjectByHandle((HANDLE)pUmAlloc->hSynch, EVENT_MODIFY_STATE, *ExEventObjectType, UserMode,
(PVOID*)&pSynchEvent,
NULL);
Assert(Status == STATUS_SUCCESS);
Assert(pSynchEvent);
break;
case VBOXUHGSMI_SYNCHOBJECT_TYPE_SEMAPHORE:
Status = ObReferenceObjectByHandle((HANDLE)pUmAlloc->hSynch, EVENT_MODIFY_STATE, *ExSemaphoreObjectType, UserMode,
(PVOID*)&pSynchSemaphore,
NULL);
Assert(Status == STATUS_SUCCESS);
Assert(pSynchSemaphore);
break;
case VBOXUHGSMI_SYNCHOBJECT_TYPE_NONE:
pSynchEvent = NULL;
Status = STATUS_SUCCESS;
break;
default:
LOGREL(("ERROR: invalid synch info type(%d)", pUmAlloc->enmSynchType));
AssertBreakpoint();
Status = STATUS_INVALID_PARAMETER;
break;
}
if (Status == STATUS_SUCCESS)
{
PVOID BaseVa = pMgr->pvData + pAlloc->offData - pMgr->offData;
SIZE_T cbLength = pAlloc->cbData;
PVBOXVIDEOCM_ALLOC_REF pAllocRef = (PVBOXVIDEOCM_ALLOC_REF)vboxWddmMemAllocZero(sizeof (*pAllocRef) + sizeof (PFN_NUMBER) * ADDRESS_AND_SIZE_TO_SPAN_PAGES(BaseVa, cbLength));
if (pAllocRef)
{
pAllocRef->cRefs = 1;
MmInitializeMdl(&pAllocRef->Mdl, BaseVa, cbLength);
__try
{
MmProbeAndLockPages(&pAllocRef->Mdl, KernelMode, IoWriteAccess);
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
Assert(0);
Status = STATUS_UNSUCCESSFUL;
}
if (Status == STATUS_SUCCESS)
{
PVOID pvUm = MmMapLockedPagesSpecifyCache(&pAllocRef->Mdl, UserMode, MmNonCached,
NULL, /* PVOID BaseAddress */
FALSE, /* ULONG BugCheckOnFailure */
NormalPagePriority);
if (pvUm)
{
pAllocRef->pContext = pContext;
pAllocRef->pAlloc = pAlloc;
pAllocRef->enmSynchType = pUmAlloc->enmSynchType;
pAllocRef->pSynchEvent = pSynchEvent;
ExAcquireFastMutex(&pContext->Mutex);
pAllocRef->hSessionHandle = vboxWddmHTablePut(&pContext->AllocTable, pAllocRef);
ExReleaseFastMutex(&pContext->Mutex);
if (VBOXWDDM_HANDLE_INVALID != pAllocRef->hSessionHandle)
{
pUmAlloc->hAlloc = pAllocRef->hSessionHandle;
pUmAlloc->cbData = pAlloc->cbData;
pUmAlloc->pvData = (uint64_t)pvUm;
return STATUS_SUCCESS;
}
}
else
{
Assert(0);
Status = STATUS_INSUFFICIENT_RESOURCES;
}
MmUnlockPages(&pAllocRef->Mdl);
}
vboxWddmMemFree(pAllocRef);
}
else
{
Assert(0);
Status = STATUS_NO_MEMORY;
}
if (pSynchEvent)
{
ObDereferenceObject(pSynchEvent);
}
}
else
{
Assert(0);
}
return Status;
}
NTSTATUS vboxVideoAMgrCtxAllocUnmap(PVBOXVIDEOCM_ALLOC_CONTEXT pContext, VBOXDISP_KMHANDLE hSesionHandle, PVBOXVIDEOCM_ALLOC *ppAlloc)
{
NTSTATUS Status = STATUS_SUCCESS;
ExAcquireFastMutex(&pContext->Mutex);
PVBOXVIDEOCM_ALLOC_REF pAllocRef = (PVBOXVIDEOCM_ALLOC_REF)vboxWddmHTableRemove(&pContext->AllocTable, hSesionHandle);
ExReleaseFastMutex(&pContext->Mutex);
if (pAllocRef)
{
/* wait for the dereference, i.e. for all commands involving this allocation to complete */
vboxWddmCounterU32Wait(&pAllocRef->cRefs, 1);
MmUnlockPages(&pAllocRef->Mdl);
*ppAlloc = pAllocRef->pAlloc;
if (pAllocRef->pSynchEvent)
{
ObDereferenceObject(pAllocRef->pSynchEvent);
}
vboxWddmMemFree(pAllocRef);
}
else
{
Assert(0);
Status = STATUS_INVALID_PARAMETER;
}
return Status;
}
static PVBOXVIDEOCM_ALLOC_REF vboxVideoAMgrCtxAllocRefAcquire(PVBOXVIDEOCM_ALLOC_CONTEXT pContext, VBOXDISP_KMHANDLE hSesionHandle)
{
ExAcquireFastMutex(&pContext->Mutex);
PVBOXVIDEOCM_ALLOC_REF pAllocRef = (PVBOXVIDEOCM_ALLOC_REF)vboxWddmHTableGet(&pContext->AllocTable, hSesionHandle);
ASMAtomicIncU32(&pAllocRef->cRefs);
ExReleaseFastMutex(&pContext->Mutex);
return pAllocRef;
}
static VOID vboxVideoAMgrCtxAllocRefRelease(PVBOXVIDEOCM_ALLOC_REF pRef)
{
uint32_t cRefs = ASMAtomicDecU32(&pRef->cRefs);
Assert(cRefs < UINT32_MAX/2);
Assert(cRefs >= 1); /* we do not do cleanup-on-zero here, instead we wait for the cRefs to reach 1 in vboxVideoAMgrCtxAllocUnmap before unmapping */
}
NTSTATUS vboxVideoAMgrCtxAllocCreate(PVBOXVIDEOCM_ALLOC_CONTEXT pContext, PVBOXVIDEOCM_UM_ALLOC pUmAlloc)
{
PVBOXVIDEOCM_ALLOC pAlloc;
PVBOXVIDEOCM_ALLOC_MGR pMgr = pContext->pMgr;
NTSTATUS Status = vboxVideoAMgrAllocCreate(pMgr, pUmAlloc->cbData, &pAlloc);
if (Status == STATUS_SUCCESS)
{
Status = vboxVideoAMgrCtxAllocMap(pContext, pAlloc, pUmAlloc);
if (Status == STATUS_SUCCESS)
return STATUS_SUCCESS;
else
{
Assert(0);
}
vboxVideoAMgrAllocDestroy(pMgr, pAlloc);
}
else
{
Assert(0);
}
return Status;
}
NTSTATUS vboxVideoAMgrCtxAllocDestroy(PVBOXVIDEOCM_ALLOC_CONTEXT pContext, VBOXDISP_KMHANDLE hSesionHandle)
{
PVBOXVIDEOCM_ALLOC pAlloc;
PVBOXVIDEOCM_ALLOC_MGR pMgr = pContext->pMgr;
NTSTATUS Status = vboxVideoAMgrCtxAllocUnmap(pContext, hSesionHandle, &pAlloc);
if (Status == STATUS_SUCCESS)
{
vboxVideoAMgrAllocDestroy(pMgr, pAlloc);
}
else
{
Assert(0);
}
return Status;
}
#ifdef VBOX_WITH_CRHGSMI
static DECLCALLBACK(VOID) vboxVideoAMgrAllocSubmitCompletion(PVBOXMP_DEVEXT pDevExt, PVBOXVDMADDI_CMD pCmd, PVOID pvContext)
{
/* we should be called from our DPC routine */
Assert(KeGetCurrentIrql() == DISPATCH_LEVEL);
PVBOXVDMACBUF_DR pDr = (PVBOXVDMACBUF_DR)pvContext;
PVBOXVDMACMD pHdr = VBOXVDMACBUF_DR_TAIL(pDr, VBOXVDMACMD);
VBOXVDMACMD_CHROMIUM_CMD *pBody = VBOXVDMACMD_BODY(pHdr, VBOXVDMACMD_CHROMIUM_CMD);
UINT cBufs = pBody->cBuffers;
for (UINT i = 0; i < cBufs; ++i)
{
VBOXVDMACMD_CHROMIUM_BUFFER *pBufCmd = &pBody->aBuffers[i];
PVBOXVIDEOCM_ALLOC_REF pRef = (PVBOXVIDEOCM_ALLOC_REF)pBufCmd->u64GuesData;
if (!pBufCmd->u32GuesData)
{
/* signal completion */
switch (pRef->enmSynchType)
{
case VBOXUHGSMI_SYNCHOBJECT_TYPE_EVENT:
KeSetEvent(pRef->pSynchEvent, 3, FALSE);
break;
case VBOXUHGSMI_SYNCHOBJECT_TYPE_SEMAPHORE:
KeReleaseSemaphore(pRef->pSynchSemaphore,
3,
1,
FALSE);
break;
case VBOXUHGSMI_SYNCHOBJECT_TYPE_NONE:
break;
default:
Assert(0);
}
}
vboxVideoAMgrCtxAllocRefRelease(pRef);
}
vboxVdmaCBufDrFree(&pDevExt->u.primary.Vdma, pDr);
}
/* submits a set of chromium uhgsmi buffers to host for processing */
NTSTATUS vboxVideoAMgrCtxAllocSubmit(PVBOXMP_DEVEXT pDevExt, PVBOXVIDEOCM_ALLOC_CONTEXT pContext, UINT cBuffers, VBOXWDDM_UHGSMI_BUFFER_UI_INFO_ESCAPE *paBuffers)
{
NTSTATUS Status = STATUS_SUCCESS;
UINT cbCmd = VBOXVDMACMD_SIZE_FROMBODYSIZE(RT_OFFSETOF(VBOXVDMACMD_CHROMIUM_CMD, aBuffers[cBuffers]));
PVBOXVDMACBUF_DR pDr = vboxVdmaCBufDrCreate (&pDevExt->u.primary.Vdma, cbCmd);
if (pDr)
{
// vboxVdmaCBufDrCreate zero initializes the pDr
pDr->fFlags = VBOXVDMACBUF_FLAG_BUF_FOLLOWS_DR;
pDr->cbBuf = cbCmd;
pDr->rc = VERR_NOT_IMPLEMENTED;
PVBOXVDMACMD pHdr = VBOXVDMACBUF_DR_TAIL(pDr, VBOXVDMACMD);
pHdr->enmType = VBOXVDMACMD_TYPE_CHROMIUM_CMD;
pHdr->u32CmdSpecific = 0;
VBOXVDMACMD_CHROMIUM_CMD *pBody = VBOXVDMACMD_BODY(pHdr, VBOXVDMACMD_CHROMIUM_CMD);
pBody->cBuffers = cBuffers;
for (UINT i = 0; i < cBuffers; ++i)
{
VBOXVDMACMD_CHROMIUM_BUFFER *pBufCmd = &pBody->aBuffers[i];
VBOXWDDM_UHGSMI_BUFFER_UI_INFO_ESCAPE *pBufInfo = &paBuffers[i];
PVBOXVIDEOCM_ALLOC_REF pRef = vboxVideoAMgrCtxAllocRefAcquire(pContext, pBufInfo->hAlloc);
if (pRef)
{
#ifdef DEBUG_misha
Assert(pRef->cRefs == 2);
#endif
pBufCmd->offBuffer = pRef->pAlloc->offData + pBufInfo->Info.offData;
pBufCmd->cbBuffer = pBufInfo->Info.cbData;
pBufCmd->u32GuesData = pBufInfo->Info.fSubFlags.bDoNotSignalCompletion;
pBufCmd->u64GuesData = (uint64_t)pRef;
}
else
{
WARN(("vboxVideoAMgrCtxAllocRefAcquire failed for hAlloc(0x%x)\n", pBufInfo->hAlloc));
/* release all previously acquired aloc references */
for (UINT j = 0; j < i; ++j)
{
VBOXVDMACMD_CHROMIUM_BUFFER *pBufCmdJ = &pBody->aBuffers[j];
PVBOXVIDEOCM_ALLOC_REF pRefJ = (PVBOXVIDEOCM_ALLOC_REF)pBufCmdJ;
vboxVideoAMgrCtxAllocRefRelease(pRefJ);
}
Status = STATUS_INVALID_PARAMETER;
break;
}
}
if (Status == STATUS_SUCCESS)
{
PVBOXVDMADDI_CMD pDdiCmd = VBOXVDMADDI_CMD_FROM_BUF_DR(pDr);
vboxVdmaDdiCmdInit(pDdiCmd, 0, 0, vboxVideoAMgrAllocSubmitCompletion, pDr);
/* mark command as submitted & invisible for the dx runtime since dx did not originate it */
vboxVdmaDdiCmdSubmittedNotDx(pDdiCmd);
int rc = vboxVdmaCBufDrSubmit(pDevExt, &pDevExt->u.primary.Vdma, pDr);
if (RT_SUCCESS(rc))
{
return STATUS_SUCCESS;
}
WARN(("vboxVdmaCBufDrSubmit failed with rc (%d)\n", rc));
/* failure branch */
/* release all previously acquired aloc references */
for (UINT i = 0; i < cBuffers; ++i)
{
VBOXVDMACMD_CHROMIUM_BUFFER *pBufCmd = &pBody->aBuffers[i];
PVBOXVIDEOCM_ALLOC_REF pRef = (PVBOXVIDEOCM_ALLOC_REF)pBufCmd;
vboxVideoAMgrCtxAllocRefRelease(pRef);
}
}
vboxVdmaCBufDrFree(&pDevExt->u.primary.Vdma, pDr);
}
else
{
Assert(0);
/* @todo: try flushing.. */
LOGREL(("vboxVdmaCBufDrCreate returned NULL"));
Status = STATUS_INSUFFICIENT_RESOURCES;
}
return Status;
}
#endif
NTSTATUS vboxVideoAMgrCreate(PVBOXMP_DEVEXT pDevExt, PVBOXVIDEOCM_ALLOC_MGR pMgr, uint32_t offData, uint32_t cbData)
{
Assert(!(offData & (PAGE_SIZE -1)));
Assert(!(cbData & (PAGE_SIZE -1)));
offData = VBOXWDDM_ROUNDBOUND(offData, PAGE_SIZE);
cbData &= (~(PAGE_SIZE -1));
Assert(cbData);
if (!cbData)
return STATUS_INVALID_PARAMETER;
ExInitializeFastMutex(&pMgr->Mutex);
NTSTATUS Status = vboxWddmHTableCreate(&pMgr->AllocTable, 64);
Assert(Status == STATUS_SUCCESS);
if (Status == STATUS_SUCCESS)
{
Status = vboxMmInit(&pMgr->Mm, BYTES_TO_PAGES(cbData));
Assert(Status == STATUS_SUCCESS);
if (Status == STATUS_SUCCESS)
{
PHYSICAL_ADDRESS PhysicalAddress = {0};
PhysicalAddress.QuadPart = VBE_DISPI_LFB_PHYSICAL_ADDRESS + offData;
pMgr->pvData = (uint8_t*)MmMapIoSpace(PhysicalAddress, cbData, MmNonCached);
Assert(pMgr->pvData);
if (pMgr->pvData)
{
pMgr->offData = offData;
pMgr->cbData = cbData;
return STATUS_SUCCESS;
}
else
{
Status = STATUS_UNSUCCESSFUL;
}
vboxMmTerm(&pMgr->Mm);
}
vboxWddmHTableDestroy(&pMgr->AllocTable);
}
return Status;
}
NTSTATUS vboxVideoAMgrDestroy(PVBOXMP_DEVEXT pDevExt, PVBOXVIDEOCM_ALLOC_MGR pMgr)
{
MmUnmapIoSpace(pMgr->pvData, pMgr->cbData);
vboxMmTerm(&pMgr->Mm);
vboxWddmHTableDestroy(&pMgr->AllocTable);
return STATUS_SUCCESS;
}
NTSTATUS vboxVideoAMgrCtxCreate(PVBOXVIDEOCM_ALLOC_MGR pMgr, PVBOXVIDEOCM_ALLOC_CONTEXT pCtx)
{
NTSTATUS Status = STATUS_NOT_SUPPORTED;
if (pMgr->pvData)
{
ExInitializeFastMutex(&pCtx->Mutex);
Status = vboxWddmHTableCreate(&pCtx->AllocTable, 32);
Assert(Status == STATUS_SUCCESS);
if (Status == STATUS_SUCCESS)
{
pCtx->pMgr = pMgr;
return STATUS_SUCCESS;
}
}
return Status;
}
NTSTATUS vboxVideoAMgrCtxDestroy(PVBOXVIDEOCM_ALLOC_CONTEXT pCtx)
{
if (!pCtx->pMgr)
return STATUS_SUCCESS;
VBOXWDDM_HTABLE_ITERATOR Iter;
NTSTATUS Status = STATUS_SUCCESS;
vboxWddmHTableIterInit(&pCtx->AllocTable, &Iter);
do
{
PVBOXVIDEOCM_ALLOC_REF pRef = (PVBOXVIDEOCM_ALLOC_REF)vboxWddmHTableIterNext(&Iter, NULL);
if (!pRef)
break;
Status = vboxVideoAMgrCtxAllocDestroy(pCtx, pRef->hSessionHandle);
Assert(Status == STATUS_SUCCESS);
if (Status != STATUS_SUCCESS)
break;
// vboxWddmHTableIterRemoveCur(&Iter);
} while (1);
if (Status == STATUS_SUCCESS)
{
vboxWddmHTableDestroy(&pCtx->AllocTable);
}
return Status;
}
VOID vboxWddmSleep(uint32_t u32Val)
{
LARGE_INTEGER Interval;
Interval.QuadPart = -(int64_t) 2 /* ms */ * 10000;
KeDelayExecutionThread(KernelMode, FALSE, &Interval);
}
VOID vboxWddmCounterU32Wait(uint32_t volatile * pu32, uint32_t u32Val)
{
LARGE_INTEGER Interval;
Interval.QuadPart = -(int64_t) 2 /* ms */ * 10000;
uint32_t u32CurVal;
Assert(KeGetCurrentIrql() < DISPATCH_LEVEL);
while ((u32CurVal = ASMAtomicReadU32(pu32)) != u32Val)
{
Assert(u32CurVal >= u32Val);
Assert(u32CurVal < UINT32_MAX/2);
KeDelayExecutionThread(KernelMode, FALSE, &Interval);
}
}
#if 0
VOID vboxShRcTreeInit(PVBOXMP_DEVEXT pDevExt)
{
ExInitializeFastMutex(&pDevExt->ShRcTreeMutex);
pDevExt->ShRcTree = NULL;
}
VOID vboxShRcTreeTerm(PVBOXMP_DEVEXT pDevExt)
{
Assert(!pDevExt->ShRcTree);
pDevExt->ShRcTree = NULL;
}
BOOLEAN vboxShRcTreePut(PVBOXMP_DEVEXT pDevExt, PVBOXWDDM_ALLOCATION pAlloc)
{
HANDLE hSharedRc = pAlloc->hSharedHandle;
if (!hSharedRc)
{
WARN(("invalid call with zero shared handle!"));
return FALSE;
}
pAlloc->ShRcTreeEntry.Key = (AVLPVKEY)hSharedRc;
ExAcquireFastMutex(&pDevExt->ShRcTreeMutex);
bool bRc = RTAvlPVInsert(&pDevExt->ShRcTree, &pAlloc->ShRcTreeEntry);
ExReleaseFastMutex(&pDevExt->ShRcTreeMutex);
Assert(bRc);
return (BOOLEAN)bRc;
}
#define PVBOXWDDM_ALLOCATION_FROM_SHRCTREENODE(_p) ((PVBOXWDDM_ALLOCATION)(((uint8_t*)(_p)) - RT_OFFSETOF(VBOXWDDM_ALLOCATION, ShRcTreeEntry)))
PVBOXWDDM_ALLOCATION vboxShRcTreeGet(PVBOXMP_DEVEXT pDevExt, HANDLE hSharedRc)
{
ExAcquireFastMutex(&pDevExt->ShRcTreeMutex);
PAVLPVNODECORE pNode = RTAvlPVGet(&pDevExt->ShRcTree, (AVLPVKEY)hSharedRc);
ExReleaseFastMutex(&pDevExt->ShRcTreeMutex);
if (!pNode)
return NULL;
PVBOXWDDM_ALLOCATION pAlloc = PVBOXWDDM_ALLOCATION_FROM_SHRCTREENODE(pNode);
return pAlloc;
}
BOOLEAN vboxShRcTreeRemove(PVBOXMP_DEVEXT pDevExt, PVBOXWDDM_ALLOCATION pAlloc)
{
HANDLE hSharedRc = pAlloc->hSharedHandle;
if (!hSharedRc)
{
WARN(("invalid call with zero shared handle!"));
return FALSE;
}
ExAcquireFastMutex(&pDevExt->ShRcTreeMutex);
PAVLPVNODECORE pNode = RTAvlPVRemove(&pDevExt->ShRcTree, (AVLPVKEY)hSharedRc);
ExReleaseFastMutex(&pDevExt->ShRcTreeMutex);
if (!pNode)
return NULL;
PVBOXWDDM_ALLOCATION pRetAlloc = PVBOXWDDM_ALLOCATION_FROM_SHRCTREENODE(pNode);
Assert(pRetAlloc == pAlloc);
return !!pRetAlloc;
}
#endif