VBoxDispIf.cpp revision a29027bb2378172c7c88610ad5311548b66f96f6
/** @file
* VBoxDispIf.cpp - Display Settings Interface abstraction for XPDM & WDDM.
*/
/*
* Copyright (C) 2006-2014 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
* General Public License (GPL) as published by the Free Software
* Foundation, in version 2 as it comes in the "COPYING" file of the
* VirtualBox OSE distribution. VirtualBox OSE is distributed in the
* hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
*/
#include "VBoxTray.h"
#include "VBoxDisplay.h"
#include <malloc.h>
#define _WIN32_WINNT 0x0601
#ifdef VBOX_WITH_WDDM
#endif
#ifndef NT_SUCCESS
#endif
typedef struct VBOXDISPIF_OP
{
DWORD EnableAndResizeDispDev(DEVMODE *paDeviceModes, DISPLAY_DEVICE *paDisplayDevices, DWORD totalDispNum, UINT Id, DWORD aWidth, DWORD aHeight,
static DWORD vboxDispIfWddmResizeDisplay(PCVBOXDISPIF const pIf, UINT Id, BOOL fEnable, DISPLAY_DEVICE * paDisplayDevices, DEVMODE *paDeviceMode, UINT devModes);
static DWORD vboxDispIfResizePerform(PCVBOXDISPIF const pIf, UINT iChangedMode, BOOL fEnable, BOOL fExtDispSup, DISPLAY_DEVICE *paDisplayDevices, DEVMODE *paDeviceModes, UINT cDevModes);
static DWORD vboxDispIfWddmEnableDisplaysTryingTopology(PCVBOXDISPIF const pIf, UINT cIds, UINT *pIds, BOOL fEnable);
/* APIs specific to win7 and above WDDM architecture. Not available for Vista WDDM.
* This is the reason they have not been put in the VBOXDISPIF struct in VBoxDispIf.h
*/
typedef struct _VBOXDISPLAYWDDMAPICONTEXT
{
LONG (WINAPI * pfnSetDisplayConfig)(UINT numPathArrayElements,DISPLAYCONFIG_PATH_INFO *pathArray,UINT numModeInfoArrayElements,
LONG (WINAPI * pfnQueryDisplayConfig)(UINT Flags,UINT *pNumPathArrayElements, DISPLAYCONFIG_PATH_INFO *pPathInfoArray,
LONG (WINAPI * pfnGetDisplayConfigBufferSizes)(UINT Flags, UINT *pNumPathArrayElements, UINT *pNumModeInfoArrayElements);
static _VBOXDISPLAYWDDMAPICONTEXT gCtx = {0};
typedef struct VBOXDISPIF_WDDM_DISPCFG
{
{
UINT32 cPathInfoArray = 0;
UINT32 cModeInfoArray = 0;
if (winEr != ERROR_SUCCESS)
{
return winEr;
}
/** @todo r=andy Why using malloc() instead of RTMemAlloc*? */
pPathInfoArray = (DISPLAYCONFIG_PATH_INFO *)malloc(cPathInfoArray * sizeof(DISPLAYCONFIG_PATH_INFO));
if (!pPathInfoArray)
{
LogFlowFunc(("Allocating pPathInfoArray failed\n"));
return ERROR_OUTOFMEMORY;
}
pModeInfoArray = (DISPLAYCONFIG_MODE_INFO *)malloc(cModeInfoArray * sizeof(DISPLAYCONFIG_MODE_INFO));
if (!pModeInfoArray)
{
LogFlowFunc(("Allocating pModeInfoArray failed\n"));
return ERROR_OUTOFMEMORY;
}
winEr = gCtx.pfnQueryDisplayConfig(fFlags, &cPathInfoArray, pPathInfoArray, &cModeInfoArray, pModeInfoArray, NULL);
if (winEr != ERROR_SUCCESS)
{
return winEr;
}
return ERROR_SUCCESS;
}
{
/** @todo r=andy Why using malloc() instead of RTMemAlloc*? */
if (pCfg->cPathInfoArray)
{
pCfgDst->pPathInfoArray = (DISPLAYCONFIG_PATH_INFO *)malloc(pCfg->cPathInfoArray * sizeof (DISPLAYCONFIG_PATH_INFO));
if (!pCfgDst->pPathInfoArray)
{
LogFlowFunc(("malloc failed!\n"));
return ERROR_OUTOFMEMORY;
}
memcpy(pCfgDst->pPathInfoArray, pCfg->pPathInfoArray, pCfg->cPathInfoArray * sizeof (DISPLAYCONFIG_PATH_INFO));
}
if (pCfg->cModeInfoArray)
{
pCfgDst->pModeInfoArray = (DISPLAYCONFIG_MODE_INFO *)malloc(pCfg->cModeInfoArray * sizeof (DISPLAYCONFIG_MODE_INFO));
if (!pCfgDst->pModeInfoArray)
{
LogFlowFunc(("malloc failed!\n"));
if (pCfgDst->pPathInfoArray)
{
}
return ERROR_OUTOFMEMORY;
}
memcpy(pCfgDst->pModeInfoArray, pCfg->pModeInfoArray, pCfg->cModeInfoArray * sizeof (DISPLAYCONFIG_MODE_INFO));
}
return ERROR_SUCCESS;
}
{
if (pCfg->pPathInfoArray)
if (pCfg->pModeInfoArray)
/* sanity */
}
static UINT32 g_cVBoxDispIfWddmDisplays = 0;
{
{
*pcDisplays = 0;
if (winEr != ERROR_SUCCESS)
{
return winEr;
}
int cDisplays = -1;
{
}
cDisplays++;
}
return ERROR_SUCCESS;
}
{
{
{
return (int)iter;
}
}
return -1;
}
{
if (idx < 0)
return idx;
return -1;
return idx;
}
{
}
{
{
}
if (pCfg->pModeInfoArray)
{
}
pCfg->cModeInfoArray = 0;
}
{
DISPLAYCONFIG_MODE_INFO *pModeInfoArray = (DISPLAYCONFIG_MODE_INFO *)malloc(cModeInfoArray * sizeof (DISPLAYCONFIG_MODE_INFO));
if (!pModeInfoArray)
{
LogFlowFunc(("malloc failed!\n"));
return ERROR_OUTOFMEMORY;
}
memcpy (pModeInfoArray, pCfg->pModeInfoArray, pCfg->cModeInfoArray * sizeof(DISPLAYCONFIG_MODE_INFO));
return ERROR_SUCCESS;
}
static DWORD vboxDispIfWddmDcSettingsUpdate(VBOXDISPIF_WDDM_DISPCFG *pCfg, int idx, DEVMODE *pDeviceMode, BOOL fInvalidateSrcMode, BOOL fEnable)
{
if (fInvalidateSrcMode)
else if (pDeviceMode)
{
{
LogFlowFunc(("no source mode index specified"));
if (winEr != ERROR_SUCCESS)
{
return winEr;
}
}
for (int i = 0; i < (int)pCfg->cPathInfoArray; ++i)
{
if (i == idx)
continue;
{
/* this is something we're not expecting/supporting */
LogFlowFunc(("multiple paths have the same mode index"));
return ERROR_NOT_SUPPORTED;
}
}
{
}
{
switch (pDeviceMode->dmBitsPerPel)
{
case 32:
break;
case 24:
break;
case 16:
break;
case 8:
break;
default:
break;
}
}
}
if (fEnable)
else
return ERROR_SUCCESS;
}
{
DWORD winEr = gCtx.pfnSetDisplayConfig(pCfg->cPathInfoArray, pCfg->pPathInfoArray, pCfg->cModeInfoArray, pCfg->pModeInfoArray, fFlags);
if (winEr != ERROR_SUCCESS)
return winEr;
}
{
{
continue;
continue;
}
return fAdjusted;
}
{
{
continue;
}
}
{
if (winEr != ERROR_SUCCESS)
{
return winEr;
}
DISPLAYCONFIG_PATH_INFO *pPathInfoArray = (DISPLAYCONFIG_PATH_INFO *)malloc(cDisplays * sizeof(DISPLAYCONFIG_PATH_INFO));
if (!pPathInfoArray)
{
LogFlowFunc(("malloc failed\n"));
return ERROR_OUTOFMEMORY;
}
{
if (idx < 0)
{
if (idx >= 0)
{
LogFlowFunc(("different source and target paare enabled, this is something we would not expect\n"));
}
}
if (idx >= 0)
else
{
if (!fAllCfgInited)
{
if (winEr != ERROR_SUCCESS)
{
return winEr;
}
}
if (idx < 0)
{
LogFlowFunc(("%d %d path not supported\n", i, i));
if (idx < 0)
{
}
}
if (idx >= 0)
{
{
LogFlowFunc(("disabled path %d %d is marked active\n",
}
Assert(pPathInfoArray[i].targetInfo.scanLineOrdering == DISPLAYCONFIG_SCANLINE_ORDERING_UNSPECIFIED);
}
else
{
pPathInfoArray[i].flags = 0;
}
}
}
if (fAllCfgInited)
return ERROR_SUCCESS;
}
{
{
{
hr = vboxDispKmtCreateContext(&pOp->Device, &pOp->Context, VBOXWDDM_CONTEXT_TYPE_CUSTOM_DISPIF_RESIZE,
return ERROR_SUCCESS;
else
}
else
}
return hr;
}
{
}
/* display driver interface abstraction for XPDM & WDDM
* with WDDM we can not use ExtEscape to communicate with our driver
* because we do not have XPDM display driver any more, i.e. escape requests are handled by cdd
* that knows nothing about us */
{
return NO_ERROR;
}
#ifdef VBOX_WITH_WDDM
#endif
{
#ifdef VBOX_WITH_WDDM
{
}
#endif
return NO_ERROR;
}
static DWORD vboxDispIfEscapeXPDM(PCVBOXDISPIF pIf, PVBOXDISPIFESCAPE pEscape, int cbData, int iDirection)
{
iDirection >= 0 ? cbData : 0,
iDirection <= 0 ? cbData : 0,
if (iRet > 0)
return VINF_SUCCESS;
else if (iRet == 0)
return ERROR_NOT_SUPPORTED;
/* else */
return ERROR_GEN_FAILURE;
}
#ifdef VBOX_WITH_WDDM
{
GetVersionEx (&OSinfo);
bool bSupported = true;
{
LogFlowFunc(("this is vista and up\n"));
if (hUser)
{
*(uintptr_t *)&pIf->modeData.wddm.pfnChangeDisplaySettingsEx = (uintptr_t)GetProcAddress(hUser, "ChangeDisplaySettingsExA");
*(uintptr_t *)&pIf->modeData.wddm.pfnEnumDisplayDevices = (uintptr_t)GetProcAddress(hUser, "EnumDisplayDevicesA");
/* for win 7 and above */
{
*(uintptr_t *)&gCtx.pfnGetDisplayConfigBufferSizes = (uintptr_t)GetProcAddress(hUser, "GetDisplayConfigBufferSizes");
}
/* this is vista and up */
{
}
}
else
{
}
}
else
{
LogFlowFunc(("Could not switch to VBOXDISPIF_MODE_WDDM, because os is not Vista or upper\n"));
}
if (err == ERROR_SUCCESS)
{
}
return err;
}
{
return vboxDispIfSwitchToWDDM(pIf);
}
{
for (int i = 0; ; ++i)
{
pDev, 0 /* DWORD dwFlags*/))
{
{
if (hDc)
{
return NO_ERROR;
}
else
{
winEr = GetLastError();
break;
}
}
LogFlowFunc(("display data no match display(%d): i(%d), flags(%d)", iDisplay, i, pDev->StateFlags));
}
else
{
winEr = GetLastError();
break;
}
}
return winEr;
}
static DWORD vboxDispIfEscapeWDDM(PCVBOXDISPIF pIf, PVBOXDISPIFESCAPE pEscape, int cbData, BOOL fHwAccess)
{
{
return hr;
}
D3DKMT_ESCAPE EscapeData = {0};
//EscapeData.hDevice = NULL;
if (fHwAccess)
//EscapeData.hContext = NULL;
if (NT_SUCCESS(Status))
else
{
}
return winEr;
}
#endif
{
{
case VBOXDISPIF_MODE_XPDM_NT4:
case VBOXDISPIF_MODE_XPDM:
#ifdef VBOX_WITH_WDDM
case VBOXDISPIF_MODE_WDDM:
case VBOXDISPIF_MODE_WDDM_W7:
#endif
default:
return ERROR_INVALID_PARAMETER;
}
}
{
{
case VBOXDISPIF_MODE_XPDM_NT4:
case VBOXDISPIF_MODE_XPDM:
#ifdef VBOX_WITH_WDDM
case VBOXDISPIF_MODE_WDDM:
case VBOXDISPIF_MODE_WDDM_W7:
#endif
default:
return ERROR_INVALID_PARAMETER;
}
}
#ifdef VBOX_WITH_WDDM
#define VBOXRR_TIMER_ID 1234
typedef struct VBOXRR
{
static void vboxRrRetryStopLocked()
{
{
if (pMon->paDisplayDevices)
{
}
if (pMon->paDeviceModes)
{
}
{
}
}
}
static void VBoxRrRetryStop()
{
}
//static DWORD vboxDispIfWddmValidateFixResize(PCVBOXDISPIF const pIf, DISPLAY_DEVICE *paDisplayDevices, DEVMODE *paDeviceModes, UINT cDevModes);
static void vboxRrRetryReschedule()
{
}
static void VBoxRrRetrySchedule(PCVBOXDISPIF const pIf, UINT iChangedMode, BOOL fEnable, BOOL fExtDispSup, DISPLAY_DEVICE *paDisplayDevices, DEVMODE *paDeviceModes, UINT cDevModes)
{
/** @todo r=andy Why using malloc() instead of RTMemAlloc*? */
if (cDevModes)
{
if (!pMon->paDisplayDevices)
{
LogFlowFunc(("malloc failed"));
return;
}
if (!pMon->paDeviceModes)
{
LogFlowFunc(("malloc failed"));
return;
}
}
{
}
}
static void vboxRrRetryPerform()
{
{
DWORD dwErr = vboxDispIfResizePerform(pMon->pIf, pMon->iChangedMode, pMon->fEnable, pMon->fExtDispSup, pMon->paDisplayDevices, pMon->paDeviceModes, pMon->cDevModes);
if (ERROR_RETRY != dwErr)
else
}
}
)
{
switch(uMsg)
{
case WM_DISPLAYCHANGE:
{
LogFlowFunc(("WM_DISPLAYCHANGE\n"));
return 0;
}
case WM_TIMER:
{
if (wParam == VBOXRR_TIMER_ID)
{
LogFlowFunc(("VBOXRR_TIMER_ID\n"));
return 0;
}
break;
}
case WM_CLOSE:
return 0;
case WM_DESTROY:
return 0;
case WM_NCHITTEST:
return HTNOWHERE;
default:
break;
}
}
#define VBOXRRWND_NAME "VBoxRrWnd"
{
/* Register the Window Class. */
{
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
if (!RegisterClass(&wc))
{
}
}
{
-100, -100,
10, 10,
NULL, //GetDesktopWindow() /* hWndParent */,
NULL /* hMenu */,
NULL /* lpParam */);
if (hWnd)
{
}
else
{
}
}
return hr;
}
{
if (bResult)
return S_OK;
return HRESULT_FROM_WIN32(winErr);
}
static HRESULT vboxRrWndInit()
{
}
{
return S_OK;
}
{
NULL /* HWND hWnd */,
WM_USER /* UINT wMsgFilterMin */,
WM_USER /* UINT wMsgFilterMax */,
do
{
0 /*HWND hWnd*/,
0 /*UINT wMsgFilterMin*/,
0 /*UINT wMsgFilterMax*/
);
if(!bResult) /* WM_QUIT was posted */
{
LogFlowFunc(("GetMessage returned FALSE\n"));
break;
}
{
/* just ensure we never return success in this case */
break;
}
{
case WM_VBOXRR_INIT_QUIT:
case WM_CLOSE:
{
PostQuitMessage(0);
break;
}
default:
break;
}
} while (1);
return 0;
}
{
if (!bRc)
{
}
{
}
return 0;
}
{
TRUE, /* BOOL bManualReset*/
FALSE, /* BOOL bInitialState */
NULL /* LPCTSTR lpName */
);
{
0 /* SIZE_T dwStackSize */,
pMon,
0 /* DWORD dwCreationFlags */,
{
if (dwResult == WAIT_OBJECT_0)
return S_OK;
else
{
LogFlowFunc(("WaitForSingleObject failed"));
}
}
else
{
}
}
else
{
}
return hr;
}
{
return;
if (bResult
|| (winErr = GetLastError()) == ERROR_INVALID_THREAD_ID) /* <- could be that the thread is terminated */
{
if (dwErr == WAIT_OBJECT_0)
{
}
else
{
winErr = GetLastError();
}
}
else
{
}
}
{
{
return ERROR_SUCCESS;
}
return hr;
}
{
VBoxRrTerm();
}
static DWORD vboxDispIfQueryDisplayConnection(VBOXDISPIF_OP *pOp, UINT32 iDisplay, BOOL *pfConnected)
{
{
/* @todo: do we need ti impl it? */
*pfConnected = TRUE;
return ERROR_SUCCESS;
}
*pfConnected = FALSE;
if (winEr != ERROR_SUCCESS)
{
return winEr;
}
*pfConnected = (idx >= 0);
return ERROR_SUCCESS;
}
{
do
{
Sleep(100);
if (Status != 0)
{
continue;
}
#if 0
for (UINT i = 0; i < VBOXWDDM_SCREENMASK_SIZE; ++i)
{
continue;
if (winEr != ERROR_SUCCESS)
{
return winEr;
}
if (!fConnected)
{
LogFlowFunc(("Display %d not connected, not expected\n", i));
break;
}
}
#endif
if (!fFound)
break;
} while (1);
return winEr;
}
{
D3DKMT_ESCAPE EscapeData = {0};
#ifdef VBOX_DISPIF_WITH_OPCONTEXT
/* win8.1 does not allow context-based escapes for display-only mode */
#endif
if (NT_SUCCESS(Status))
else
{
}
return winEr;
}
{
LogFlowFunc(("cancelling pending resize\n"));
return NO_ERROR;
}
static DWORD vboxDispIfWddmResizeDisplayVista(DEVMODE *paDeviceModes, DISPLAY_DEVICE *paDisplayDevices, DWORD cDevModes, UINT iChangedMode, BOOL fEnable, BOOL fExtDispSup)
{
/* Without this, Windows will not ask the miniport for its
* mode table but uses an internal cache instead.
*/
{
}
DWORD winEr = EnableAndResizeDispDev(paDeviceModes, paDisplayDevices, cDevModes, iChangedMode, paDeviceModes[iChangedMode].dmPelsWidth, paDeviceModes[iChangedMode].dmPelsHeight,
paDeviceModes[iChangedMode].dmBitsPerPel, paDeviceModes[iChangedMode].dmPosition.x, paDeviceModes[iChangedMode].dmPosition.y, fEnable, fExtDispSup);
return winEr;
}
static DWORD vboxDispIfResizePerform(PCVBOXDISPIF const pIf, UINT iChangedMode, BOOL fEnable, BOOL fExtDispSup, DISPLAY_DEVICE *paDisplayDevices, DEVMODE *paDeviceModes, UINT cDevModes)
{
{
winEr = vboxDispIfWddmResizeDisplay(pIf, iChangedMode, fEnable, paDisplayDevices, paDeviceModes, cDevModes);
}
else
{
winEr = vboxDispIfWddmResizeDisplayVista(paDeviceModes, paDisplayDevices, cDevModes, iChangedMode, fEnable, fExtDispSup);
}
return winEr;
}
DWORD vboxDispIfResizeModesWDDM(PCVBOXDISPIF const pIf, UINT iChangedMode, BOOL fEnable, BOOL fExtDispSup, DISPLAY_DEVICE *paDisplayDevices, DEVMODE *paDeviceModes, UINT cDevModes)
{
UINT i = 0;
LogFlowFunc(("vboxDispIfResizeModesWDDM\n"));
{
return winEr;
}
// if (fEnable)
{
}
winEr = vboxDispIfResizePerform(pIf, iChangedMode, fEnable, fExtDispSup, paDisplayDevices, paDeviceModes, cDevModes);
if (winEr == ERROR_RETRY)
{
VBoxRrRetrySchedule(pIf, iChangedMode, fEnable, fExtDispSup, paDisplayDevices, paDeviceModes, cDevModes);
/* just pretend everything is fine so far */
}
return winEr;
}
static DWORD vboxDispIfWddmEnableDisplays(PCVBOXDISPIF const pIf, UINT cIds, UINT *pIds, BOOL fEnabled, BOOL fSetTopology, DEVMODE *pDeviceMode)
{
int iPath;
if (winEr != ERROR_SUCCESS)
{
return winEr;
}
UINT cChangeIds = 0;
if (!pChangeIds)
{
LogFlowFunc(("Failed to alloc change ids\n"));
goto done;
}
{
bool fIsDup = false;
for (UINT j = 0; j < cChangeIds; ++j)
{
if (pChangeIds[j] == Id)
{
fIsDup = true;
break;
}
}
if (fIsDup)
continue;
if (!((iPath >= 0) && (DispCfg.pPathInfoArray[iPath].flags & DISPLAYCONFIG_PATH_ACTIVE)) != !fEnabled)
{
++cChangeIds;
}
}
if (cChangeIds == 0)
{
LogFlowFunc(("vboxDispIfWddmEnableDisplay: settings are up to date\n"));
goto done;
}
/* we want to set primary for every disabled for non-topoly mode only */
if (winEr != ERROR_SUCCESS)
{
return winEr;
}
if (fSetTopology)
for (UINT i = 0; i < cChangeIds; ++i)
{
/* re-query paths */
if (iPath < 0)
{
LogFlowFunc(("path index not found while it should"));
goto done;
}
winEr = vboxDispIfWddmDcSettingsUpdate(&DispCfg, iPath, pDeviceMode, !fEnabled || fSetTopology, fEnabled);
if (winEr != ERROR_SUCCESS)
{
goto done;
}
}
if (!fSetTopology)
#if 0
/* ensure the zero-index (primary) screen is enabled */
if (iPath < 0)
{
LogFlowFunc(("path index not found while it should"));
goto done;
}
winEr = vboxDispIfWddmDcSettingsUpdate(&DispCfg, iPath, /* just re-use device node here*/ pDeviceMode, fSetTopology, TRUE);
if (winEr != ERROR_SUCCESS)
{
goto done;
}
#endif
UINT fSetFlags = !fSetTopology ? (SDC_USE_SUPPLIED_DISPLAY_CONFIG) : (SDC_ALLOW_PATH_ORDER_CHANGES | SDC_TOPOLOGY_SUPPLIED);
if (winEr != ERROR_SUCCESS)
{
if (!fSetTopology)
{
}
else
{
goto done;
}
}
if (!fSetTopology)
if (winEr != ERROR_SUCCESS)
done:
return winEr;
}
static DWORD vboxDispIfWddmEnableDisplaysTryingTopology(PCVBOXDISPIF const pIf, UINT cIds, UINT *pIds, BOOL fEnable)
{
if (winEr != ERROR_SUCCESS)
{
if (fEnable)
else
if (winEr != ERROR_SUCCESS)
}
return winEr;
}
static DWORD vboxDispIfWddmResizeDisplay(PCVBOXDISPIF const pIf, UINT Id, BOOL fEnable, DISPLAY_DEVICE * paDisplayDevices, DEVMODE *paDeviceMode, UINT devModes)
{
int iPath;
if (winEr != ERROR_SUCCESS)
{
LogFlowFunc(("Failed vboxDispIfWddmDcCreate\n"));
return winEr;
}
if (iPath < 0)
{
if (!fEnable)
{
/* nothing to be done here, just leave */
return ERROR_SUCCESS;
}
if (winEr != ERROR_SUCCESS)
{
return winEr;
}
if (winEr != ERROR_SUCCESS)
{
return winEr;
}
if (iPath < 0)
{
return ERROR_RETRY;
}
}
if (!fEnable)
{
/* need to disable it, and we are done */
if (winEr != ERROR_SUCCESS)
{
return winEr;
}
return winEr;
}
if (winEr != ERROR_SUCCESS)
{
LogFlowFunc(("Failed vboxDispIfWddmDcSettingsUpdate\n"));
return winEr;
}
if (winEr != ERROR_SUCCESS)
{
}
if (winEr != ERROR_SUCCESS)
{
}
return winEr;
}
#endif /* VBOX_WITH_WDDM */
DWORD VBoxDispIfResizeModes(PCVBOXDISPIF const pIf, UINT iChangedMode, BOOL fEnable, BOOL fExtDispSup, DISPLAY_DEVICE *paDisplayDevices, DEVMODE *paDeviceModes, UINT cDevModes)
{
{
case VBOXDISPIF_MODE_XPDM_NT4:
return ERROR_NOT_SUPPORTED;
case VBOXDISPIF_MODE_XPDM:
return ERROR_NOT_SUPPORTED;
#ifdef VBOX_WITH_WDDM
case VBOXDISPIF_MODE_WDDM:
case VBOXDISPIF_MODE_WDDM_W7:
return vboxDispIfResizeModesWDDM(pIf, iChangedMode, fEnable, fExtDispSup, paDisplayDevices, paDeviceModes, cDevModes);
#endif
default:
return ERROR_INVALID_PARAMETER;
}
}
{
{
case VBOXDISPIF_MODE_XPDM_NT4:
return NO_ERROR;
case VBOXDISPIF_MODE_XPDM:
return NO_ERROR;
#ifdef VBOX_WITH_WDDM
case VBOXDISPIF_MODE_WDDM:
case VBOXDISPIF_MODE_WDDM_W7:
return vboxDispIfCancelPendingResizeWDDM(pIf);
#endif
default:
return ERROR_INVALID_PARAMETER;
}
}
{
VBOXDISPIFESCAPE EscapeHdr = {0};
EscapeHdr.u32CmdSpecific = 0;
D3DKMT_ESCAPE EscapeData = {0};
#ifdef VBOX_DISPIF_WITH_OPCONTEXT
/* win8.1 does not allow context-based escapes for display-only mode */
#endif
if (NT_SUCCESS(Status))
{
if (pcConnected)
return NO_ERROR;
}
return Status;
}
{
if (NumDevices == 0)
{
LogFlowFunc(("vboxDispIfResizeStartedWDDMOp: Zero devices found\n"));
return ERROR_GEN_FAILURE;
}
DWORD DevPrimaryNum = 0;
DWORD winEr = VBoxGetDisplayConfig(NumDevices, &DevPrimaryNum, &DevNum, paDisplayDevices, paDeviceModes);
{
return winEr;
}
if (NumDevices != DevNum)
uint32_t cConnected = 0;
{
return winEr;
}
if (!cConnected)
{
LogFlowFunc(("all targets already connected, nothing to do\n"));
return NO_ERROR;
}
LogFlowFunc(("vboxDispIfResizeStartedWDDMOp: vboxDispIfWaitDisplayDataInited failed winEr 0x%x\n", winEr));
if (NewNumDevices == 0)
{
LogFlowFunc(("vboxDispIfResizeStartedWDDMOp: Zero devices found\n"));
return ERROR_GEN_FAILURE;
}
if (NewNumDevices != NumDevices)
LogFlowFunc(("vboxDispIfResizeStartedWDDMOp: NumDevices(%d) != NewNumDevices(%d)\n", NumDevices, NewNumDevices));
DISPLAY_DEVICE *paNewDisplayDevices = (DISPLAY_DEVICE *)alloca (sizeof (DISPLAY_DEVICE) * NewNumDevices);
DWORD NewDevPrimaryNum = 0;
winEr = VBoxGetDisplayConfig(NewNumDevices, &NewDevPrimaryNum, &NewDevNum, paNewDisplayDevices, paNewDeviceModes);
{
LogFlowFunc(("vboxDispIfResizeStartedWDDMOp: VBoxGetDisplayConfig failed for new devices, %d\n", winEr));
return winEr;
}
if (NewNumDevices != NewDevNum)
LogFlowFunc(("vboxDispIfResizeStartedWDDMOp: NewNumDevices(%d) != NewDevNum(%d)\n", NewNumDevices, NewDevNum));
{
{
++cIds;
}
}
if (!cIds)
{
/* this is something we would not regularly expect */
LogFlowFunc(("all targets already have proper config, nothing to do\n"));
return NO_ERROR;
}
{
LogFlowFunc(("vboxDispIfWddmEnableDisplaysTryingTopology failed to record current settings, %d, ignoring\n", winEr));
}
else
{
{
winEr = vboxDispIfWddmResizeDisplayVista(paNewDeviceModes, paNewDisplayDevices, NewDevNum, i, FALSE, TRUE);
LogFlowFunc(("vboxDispIfResizeStartedWDDMOp: vboxDispIfWddmResizeDisplayVista failed winEr 0x%x\n", winEr));
}
}
return winEr;
}
{
{
return winEr;
}
{
}
return winEr;
}
{
{
case VBOXDISPIF_MODE_XPDM_NT4:
return NO_ERROR;
case VBOXDISPIF_MODE_XPDM:
return NO_ERROR;
#ifdef VBOX_WITH_WDDM
case VBOXDISPIF_MODE_WDDM:
case VBOXDISPIF_MODE_WDDM_W7:
return vboxDispIfResizeStartedWDDM(pIf);
#endif
default:
return ERROR_INVALID_PARAMETER;
}
}
{
return NO_ERROR;
}
{
GetVersionEx (&OSinfo);
{
{
bool bSupported = true;
*(uintptr_t *)&pIf->modeData.xpdm.pfnChangeDisplaySettingsEx = (uintptr_t)GetProcAddress(hUser, "ChangeDisplaySettingsExA");
if (!bSupported)
{
LogFlowFunc(("pfnChangeDisplaySettingsEx function pointer failed to initialize\n"));
}
}
else
{
}
}
else
{
LogFlowFunc(("can not switch to VBOXDISPIF_MODE_XPDM, because os is not >= w2k\n"));
}
return err;
}
{
/* @todo: may need to addd synchronization in case we want to change modes dynamically
* i.e. currently the mode is supposed to be initialized once on service initialization */
if (penmOldMode)
return NO_ERROR;
#ifdef VBOX_WITH_WDDM
{
}
#endif
switch (enmMode)
{
case VBOXDISPIF_MODE_XPDM_NT4:
LogFlowFunc(("request to switch to VBOXDISPIF_MODE_XPDM_NT4\n"));
{
LogFlowFunc(("successfully switched to XPDM_NT4 mode\n"));
}
else
break;
case VBOXDISPIF_MODE_XPDM:
LogFlowFunc(("request to switch to VBOXDISPIF_MODE_XPDM\n"));
{
LogFlowFunc(("successfully switched to XPDM mode\n"));
}
else
break;
#ifdef VBOX_WITH_WDDM
case VBOXDISPIF_MODE_WDDM:
{
LogFlowFunc(("request to switch to VBOXDISPIF_MODE_WDDM\n"));
{
LogFlowFunc(("successfully switched to WDDM mode\n"));
}
else
break;
}
case VBOXDISPIF_MODE_WDDM_W7:
{
LogFlowFunc(("request to switch to VBOXDISPIF_MODE_WDDM_W7\n"));
{
LogFlowFunc(("successfully switched to WDDM mode\n"));
}
else
break;
}
#endif
default:
break;
}
return err;
}
static DWORD vboxDispIfSeamlesCreateWDDM(PCVBOXDISPIF const pIf, VBOXDISPIF_SEAMLESS *pSeamless, HANDLE hEvent)
{
HRESULT hr = vboxDispKmtOpenAdapter(&pIf->modeData.wddm.KmtCallbacks, &pSeamless->modeData.wddm.Adapter);
{
#ifdef VBOX_DISPIF_WITH_OPCONTEXT
{
hr = vboxDispKmtCreateContext(&pSeamless->modeData.wddm.Device, &pSeamless->modeData.wddm.Context, VBOXWDDM_CONTEXT_TYPE_CUSTOM_DISPIF_SEAMLESS,
#endif
return ERROR_SUCCESS;
#ifdef VBOX_DISPIF_WITH_OPCONTEXT
else
}
else
#endif
}
return hr;
}
{
#ifdef VBOX_DISPIF_WITH_OPCONTEXT
#endif
return NO_ERROR;
}
static DWORD vboxDispIfSeamlesSubmitWDDM(VBOXDISPIF_SEAMLESS *pSeamless, VBOXDISPIFESCAPE *pData, int cbData)
{
D3DKMT_ESCAPE EscapeData = {0};
#ifdef VBOX_DISPIF_WITH_OPCONTEXT
#endif
/*EscapeData.Flags.HardwareAccess = 1;*/
if (NT_SUCCESS(Status))
return ERROR_SUCCESS;
return Status;
}
DWORD VBoxDispIfSeamlesCreate(PCVBOXDISPIF const pIf, VBOXDISPIF_SEAMLESS *pSeamless, HANDLE hEvent)
{
{
case VBOXDISPIF_MODE_XPDM_NT4:
case VBOXDISPIF_MODE_XPDM:
return NO_ERROR;
#ifdef VBOX_WITH_WDDM
case VBOXDISPIF_MODE_WDDM:
case VBOXDISPIF_MODE_WDDM_W7:
#endif
default:
return ERROR_INVALID_PARAMETER;
}
}
{
{
case VBOXDISPIF_MODE_XPDM_NT4:
case VBOXDISPIF_MODE_XPDM:
break;
#ifdef VBOX_WITH_WDDM
case VBOXDISPIF_MODE_WDDM:
case VBOXDISPIF_MODE_WDDM_W7:
break;
#endif
default:
break;
}
return winEr;
}
{
{
return ERROR_INVALID_PARAMETER;
}
{
case VBOXDISPIF_MODE_XPDM_NT4:
case VBOXDISPIF_MODE_XPDM:
#ifdef VBOX_WITH_WDDM
case VBOXDISPIF_MODE_WDDM:
case VBOXDISPIF_MODE_WDDM_W7:
#endif
default:
return ERROR_INVALID_PARAMETER;
}
}