VBoxDispIf.cpp revision 635c83753ed04cf3637e019af0e15ba40e07f2fe
bcd589d9db90b68d3af5d6839c1d613bb64d4c04vboxsync/** @file
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync * VBoxTray - Display Settings Interface abstraction for XPDM & WDDM
bcd589d9db90b68d3af5d6839c1d613bb64d4c04vboxsync */
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync/*
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync * Copyright (C) 2006-2012 Oracle Corporation
c58f1213e628a545081c70e26c6b67a841cff880vboxsync *
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync * available from http://www.virtualbox.org. This file is free software;
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync * you can redistribute it and/or modify it under the terms of the GNU
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync * General Public License (GPL) as published by the Free Software
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync */
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync#include "VBoxTray.h"
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync#define _WIN32_WINNT 0x0601
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync#include <iprt/log.h>
c4bfe32373c55416bf49dc29ebf45dfa560b4692vboxsync#include <iprt/err.h>
2cb8d6f5cd0c9bf435c2d3fadd9ad873590e384bvboxsync#include <iprt/assert.h>
c4bfe32373c55416bf49dc29ebf45dfa560b4692vboxsync
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync#include <malloc.h>
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync#ifdef VBOX_WITH_WDDM
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync#include <iprt/asm.h>
61f058cfcc81ec889fc17ac84c25a118a91d1423vboxsync#endif
90fd0059d671978f9db54fab8d5daa3635a4b25avboxsync
8cb6f31c3048428b42c7370dfbb20e4de7254f40vboxsync#include "VBoxDisplay.h"
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync#ifndef NT_SUCCESS
8cb6f31c3048428b42c7370dfbb20e4de7254f40vboxsync# define NT_SUCCESS(_Status) ((_Status) >= 0)
8cb6f31c3048428b42c7370dfbb20e4de7254f40vboxsync#endif
8d1da51eb6665874aa82bf03668e03d1a0d63223vboxsync
8d1da51eb6665874aa82bf03668e03d1a0d63223vboxsynctypedef struct VBOXDISPIF_OP
8d1da51eb6665874aa82bf03668e03d1a0d63223vboxsync{
8d1da51eb6665874aa82bf03668e03d1a0d63223vboxsync PCVBOXDISPIF pIf;
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync VBOXDISPKMT_ADAPTER Adapter;
7cfcbe810de5334cdc2e8b92e77db705da143adavboxsync VBOXDISPKMT_DEVICE Device;
7cfcbe810de5334cdc2e8b92e77db705da143adavboxsync VBOXDISPKMT_CONTEXT Context;
bcd589d9db90b68d3af5d6839c1d613bb64d4c04vboxsync} VBOXDISPIF_OP;
bcd589d9db90b68d3af5d6839c1d613bb64d4c04vboxsync
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsyncDWORD EnableAndResizeDispDev(DEVMODE *paDeviceModes, DISPLAY_DEVICE *paDisplayDevices, DWORD totalDispNum, UINT Id, DWORD aWidth, DWORD aHeight,
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync DWORD aBitsPerPixel, DWORD aPosX, DWORD aPosY, BOOL fEnabled, BOOL fExtDispSup);
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsyncstatic DWORD vboxDispIfWddmResizeDisplay(PCVBOXDISPIF const pIf, UINT Id, BOOL fEnable, DISPLAY_DEVICE * paDisplayDevices, DEVMODE *paDeviceMode, UINT devModes);
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsyncstatic DWORD vboxDispIfResizePerform(PCVBOXDISPIF const pIf, UINT iChangedMode, BOOL fEnable, BOOL fExtDispSup, DISPLAY_DEVICE *paDisplayDevices, DEVMODE *paDeviceModes, UINT cDevModes);
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsyncstatic DWORD vboxDispIfWddmEnableDisplaysTryingTopology(PCVBOXDISPIF const pIf, UINT cIds, UINT *pIds, BOOL fEnable);
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsyncstatic DWORD vboxDispIfResizeStartedWDDMOp(VBOXDISPIF_OP *pOp);
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync/* APIs specific to win7 and above WDDM architecture. Not available for Vista WDDM.
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync * This is the reason they have not been put in the VBOXDISPIF struct in VBoxDispIf.h
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync */
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsynctypedef struct _VBOXDISPLAYWDDMAPICONTEXT
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync{
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync LONG (WINAPI * pfnSetDisplayConfig)(UINT numPathArrayElements,DISPLAYCONFIG_PATH_INFO *pathArray,UINT numModeInfoArrayElements,
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync DISPLAYCONFIG_MODE_INFO *modeInfoArray, UINT Flags);
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync LONG (WINAPI * pfnQueryDisplayConfig)(UINT Flags,UINT *pNumPathArrayElements, DISPLAYCONFIG_PATH_INFO *pPathInfoArray,
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync UINT *pNumModeInfoArrayElements, DISPLAYCONFIG_MODE_INFO *pModeInfoArray,
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync DISPLAYCONFIG_TOPOLOGY_ID *pCurrentTopologyId);
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync LONG (WINAPI * pfnGetDisplayConfigBufferSizes)(UINT Flags, UINT *pNumPathArrayElements, UINT *pNumModeInfoArrayElements);
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync} _VBOXDISPLAYWDDMAPICONTEXT;
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsyncstatic _VBOXDISPLAYWDDMAPICONTEXT gCtx = {0};
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsynctypedef struct VBOXDISPIF_WDDM_DISPCFG
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync{
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync UINT32 cPathInfoArray;
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync DISPLAYCONFIG_PATH_INFO *pPathInfoArray;
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync UINT32 cModeInfoArray;
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync DISPLAYCONFIG_MODE_INFO *pModeInfoArray;
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync} VBOXDISPIF_WDDM_DISPCFG;
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsyncstatic DWORD vboxDispIfWddmDcCreate(VBOXDISPIF_WDDM_DISPCFG *pCfg, UINT32 fFlags)
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync{
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync UINT32 cPathInfoArray = 0;
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync UINT32 cModeInfoArray = 0;
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync DISPLAYCONFIG_PATH_INFO *pPathInfoArray;
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync DISPLAYCONFIG_MODE_INFO *pModeInfoArray;
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync DWORD winEr = gCtx.pfnGetDisplayConfigBufferSizes(fFlags, &cPathInfoArray, &cModeInfoArray);
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync if (winEr != ERROR_SUCCESS)
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync {
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync WARN(("VBoxTray: (WDDM) Failed GetDisplayConfigBufferSizes\n"));
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync return winEr;
730f8be51b729e8a3c1e32c756cd0f4ec088dd4dvboxsync }
abb9f29bd46d8a8bab57155229f583db28b18f8dvboxsync
bcd589d9db90b68d3af5d6839c1d613bb64d4c04vboxsync pPathInfoArray = (DISPLAYCONFIG_PATH_INFO *)malloc(cPathInfoArray * sizeof(DISPLAYCONFIG_PATH_INFO));
bcd589d9db90b68d3af5d6839c1d613bb64d4c04vboxsync if (!pPathInfoArray)
730f8be51b729e8a3c1e32c756cd0f4ec088dd4dvboxsync {
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync WARN(("VBoxTray: (WDDM) malloc failed!\n"));
77db08a24f69bca943d5abc40b1930ee97f593edvboxsync return ERROR_OUTOFMEMORY;
bcd589d9db90b68d3af5d6839c1d613bb64d4c04vboxsync }
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync pModeInfoArray = (DISPLAYCONFIG_MODE_INFO *)malloc(cModeInfoArray * sizeof(DISPLAYCONFIG_MODE_INFO));
8cb6f31c3048428b42c7370dfbb20e4de7254f40vboxsync if (!pModeInfoArray)
8cb6f31c3048428b42c7370dfbb20e4de7254f40vboxsync {
8cb6f31c3048428b42c7370dfbb20e4de7254f40vboxsync WARN(("VBoxTray: (WDDM) malloc failed!\n"));
8cb6f31c3048428b42c7370dfbb20e4de7254f40vboxsync free(pPathInfoArray);
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync return ERROR_OUTOFMEMORY;
bcd589d9db90b68d3af5d6839c1d613bb64d4c04vboxsync }
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync
8cb6f31c3048428b42c7370dfbb20e4de7254f40vboxsync winEr = gCtx.pfnQueryDisplayConfig(fFlags, &cPathInfoArray, pPathInfoArray, &cModeInfoArray, pModeInfoArray, NULL);
8cb6f31c3048428b42c7370dfbb20e4de7254f40vboxsync if (winEr != ERROR_SUCCESS)
8cb6f31c3048428b42c7370dfbb20e4de7254f40vboxsync {
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync WARN(("VBoxTray: (WDDM) Failed QueryDisplayConfig\n"));
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync free(pPathInfoArray);
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync free(pModeInfoArray);
bcd589d9db90b68d3af5d6839c1d613bb64d4c04vboxsync return winEr;
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync }
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync
bcd589d9db90b68d3af5d6839c1d613bb64d4c04vboxsync pCfg->cPathInfoArray = cPathInfoArray;
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync pCfg->pPathInfoArray = pPathInfoArray;
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync pCfg->cModeInfoArray = cModeInfoArray;
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync pCfg->pModeInfoArray = pModeInfoArray;
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync return ERROR_SUCCESS;
bcd589d9db90b68d3af5d6839c1d613bb64d4c04vboxsync}
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsyncstatic DWORD vboxDispIfWddmDcClone(VBOXDISPIF_WDDM_DISPCFG *pCfg, VBOXDISPIF_WDDM_DISPCFG *pCfgDst)
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync{
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync memset(pCfgDst, 0, sizeof (*pCfgDst));
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync if (pCfg->cPathInfoArray)
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync {
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync pCfgDst->pPathInfoArray = (DISPLAYCONFIG_PATH_INFO *)malloc(pCfg->cPathInfoArray * sizeof (DISPLAYCONFIG_PATH_INFO));
aa131431882ca8e44b0480d4af0b5d139f1bde21vboxsync if (!pCfgDst->pPathInfoArray)
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync {
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync WARN(("VBoxTray: (WDDM) malloc failed!\n"));
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync return ERROR_OUTOFMEMORY;
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync }
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync memcpy(pCfgDst->pPathInfoArray, pCfg->pPathInfoArray, pCfg->cPathInfoArray * sizeof (DISPLAYCONFIG_PATH_INFO));
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync pCfgDst->cPathInfoArray = pCfg->cPathInfoArray;
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync }
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync if (pCfg->cModeInfoArray)
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync {
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync pCfgDst->pModeInfoArray = (DISPLAYCONFIG_MODE_INFO *)malloc(pCfg->cModeInfoArray * sizeof (DISPLAYCONFIG_MODE_INFO));
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync if (!pCfgDst->pModeInfoArray)
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync {
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync WARN(("VBoxTray: (WDDM) malloc failed!\n"));
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync if (pCfgDst->pPathInfoArray)
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync {
bcd589d9db90b68d3af5d6839c1d613bb64d4c04vboxsync free(pCfgDst->pPathInfoArray);
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync pCfgDst->pPathInfoArray = NULL;
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync }
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync return ERROR_OUTOFMEMORY;
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync }
bcd589d9db90b68d3af5d6839c1d613bb64d4c04vboxsync
bcd589d9db90b68d3af5d6839c1d613bb64d4c04vboxsync memcpy(pCfgDst->pModeInfoArray, pCfg->pModeInfoArray, pCfg->cModeInfoArray * sizeof (DISPLAYCONFIG_MODE_INFO));
bcd589d9db90b68d3af5d6839c1d613bb64d4c04vboxsync
bcd589d9db90b68d3af5d6839c1d613bb64d4c04vboxsync pCfgDst->cModeInfoArray = pCfg->cModeInfoArray;
bcd589d9db90b68d3af5d6839c1d613bb64d4c04vboxsync }
bcd589d9db90b68d3af5d6839c1d613bb64d4c04vboxsync
bcd589d9db90b68d3af5d6839c1d613bb64d4c04vboxsync return ERROR_SUCCESS;
bcd589d9db90b68d3af5d6839c1d613bb64d4c04vboxsync}
bcd589d9db90b68d3af5d6839c1d613bb64d4c04vboxsync
bcd589d9db90b68d3af5d6839c1d613bb64d4c04vboxsync
bcd589d9db90b68d3af5d6839c1d613bb64d4c04vboxsyncstatic VOID vboxDispIfWddmDcTerm(VBOXDISPIF_WDDM_DISPCFG *pCfg)
bcd589d9db90b68d3af5d6839c1d613bb64d4c04vboxsync{
bcd589d9db90b68d3af5d6839c1d613bb64d4c04vboxsync if (pCfg->pPathInfoArray)
bcd589d9db90b68d3af5d6839c1d613bb64d4c04vboxsync free(pCfg->pPathInfoArray);
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync if (pCfg->pModeInfoArray)
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync free(pCfg->pModeInfoArray);
bcd589d9db90b68d3af5d6839c1d613bb64d4c04vboxsync /* sanity */
bcd589d9db90b68d3af5d6839c1d613bb64d4c04vboxsync memset(pCfg, 0, sizeof (*pCfg));
bcd589d9db90b68d3af5d6839c1d613bb64d4c04vboxsync}
bcd589d9db90b68d3af5d6839c1d613bb64d4c04vboxsync
bcd589d9db90b68d3af5d6839c1d613bb64d4c04vboxsyncstatic UINT32 g_cVBoxDispIfWddmDisplays = 0;
bcd589d9db90b68d3af5d6839c1d613bb64d4c04vboxsyncstatic DWORD vboxDispIfWddmDcQueryNumDisplays(UINT32 *pcDisplays)
bcd589d9db90b68d3af5d6839c1d613bb64d4c04vboxsync{
bcd589d9db90b68d3af5d6839c1d613bb64d4c04vboxsync if (!g_cVBoxDispIfWddmDisplays)
bcd589d9db90b68d3af5d6839c1d613bb64d4c04vboxsync {
bcd589d9db90b68d3af5d6839c1d613bb64d4c04vboxsync VBOXDISPIF_WDDM_DISPCFG DispCfg;
bcd589d9db90b68d3af5d6839c1d613bb64d4c04vboxsync *pcDisplays = 0;
bcd589d9db90b68d3af5d6839c1d613bb64d4c04vboxsync DWORD winEr = vboxDispIfWddmDcCreate(&DispCfg, QDC_ALL_PATHS);
bcd589d9db90b68d3af5d6839c1d613bb64d4c04vboxsync if (winEr != ERROR_SUCCESS)
bcd589d9db90b68d3af5d6839c1d613bb64d4c04vboxsync {
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync WARN(("VBoxTray:(WDDM) vboxDispIfWddmDcCreate Failed winEr %d\n", winEr));
cbc215af8423a8326b27143c59c5d8fc9ffb0279vboxsync return winEr;
cbc215af8423a8326b27143c59c5d8fc9ffb0279vboxsync }
cbc215af8423a8326b27143c59c5d8fc9ffb0279vboxsync
cbc215af8423a8326b27143c59c5d8fc9ffb0279vboxsync int cDisplays = -1;
cbc215af8423a8326b27143c59c5d8fc9ffb0279vboxsync
cbc215af8423a8326b27143c59c5d8fc9ffb0279vboxsync for (UINT iter = 0; iter < DispCfg.cPathInfoArray; ++iter)
cbc215af8423a8326b27143c59c5d8fc9ffb0279vboxsync {
cbc215af8423a8326b27143c59c5d8fc9ffb0279vboxsync if (cDisplays < (int)(DispCfg.pPathInfoArray[iter].sourceInfo.id))
cbc215af8423a8326b27143c59c5d8fc9ffb0279vboxsync cDisplays = (int)(DispCfg.pPathInfoArray[iter].sourceInfo.id);
cbc215af8423a8326b27143c59c5d8fc9ffb0279vboxsync }
cbc215af8423a8326b27143c59c5d8fc9ffb0279vboxsync
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync cDisplays++;
ece707b8d97e63ed54d4b48d7a8d841187e0023cvboxsync
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync g_cVBoxDispIfWddmDisplays = cDisplays;
ece707b8d97e63ed54d4b48d7a8d841187e0023cvboxsync Assert(g_cVBoxDispIfWddmDisplays);
ece707b8d97e63ed54d4b48d7a8d841187e0023cvboxsync
ece707b8d97e63ed54d4b48d7a8d841187e0023cvboxsync vboxDispIfWddmDcTerm(&DispCfg);
ece707b8d97e63ed54d4b48d7a8d841187e0023cvboxsync }
ece707b8d97e63ed54d4b48d7a8d841187e0023cvboxsync
ece707b8d97e63ed54d4b48d7a8d841187e0023cvboxsync *pcDisplays = g_cVBoxDispIfWddmDisplays;
ece707b8d97e63ed54d4b48d7a8d841187e0023cvboxsync return ERROR_SUCCESS;
ece707b8d97e63ed54d4b48d7a8d841187e0023cvboxsync}
ece707b8d97e63ed54d4b48d7a8d841187e0023cvboxsync
ece707b8d97e63ed54d4b48d7a8d841187e0023cvboxsyncstatic int vboxDispIfWddmDcSearchPath(VBOXDISPIF_WDDM_DISPCFG *pCfg, UINT srcId, UINT trgId)
ece707b8d97e63ed54d4b48d7a8d841187e0023cvboxsync{
ece707b8d97e63ed54d4b48d7a8d841187e0023cvboxsync for (UINT iter = 0; iter < pCfg->cPathInfoArray; ++iter)
ece707b8d97e63ed54d4b48d7a8d841187e0023cvboxsync {
ece707b8d97e63ed54d4b48d7a8d841187e0023cvboxsync if ((srcId == ~0UL || pCfg->pPathInfoArray[iter].sourceInfo.id == srcId)
ece707b8d97e63ed54d4b48d7a8d841187e0023cvboxsync && (trgId == ~0UL || pCfg->pPathInfoArray[iter].targetInfo.id == trgId))
ece707b8d97e63ed54d4b48d7a8d841187e0023cvboxsync {
ece707b8d97e63ed54d4b48d7a8d841187e0023cvboxsync return (int)iter;
ece707b8d97e63ed54d4b48d7a8d841187e0023cvboxsync }
ece707b8d97e63ed54d4b48d7a8d841187e0023cvboxsync }
ece707b8d97e63ed54d4b48d7a8d841187e0023cvboxsync return -1;
ece707b8d97e63ed54d4b48d7a8d841187e0023cvboxsync}
ece707b8d97e63ed54d4b48d7a8d841187e0023cvboxsync
ece707b8d97e63ed54d4b48d7a8d841187e0023cvboxsyncstatic int vboxDispIfWddmDcSearchActivePath(VBOXDISPIF_WDDM_DISPCFG *pCfg, UINT srcId, UINT trgId)
ece707b8d97e63ed54d4b48d7a8d841187e0023cvboxsync{
ece707b8d97e63ed54d4b48d7a8d841187e0023cvboxsync int idx = vboxDispIfWddmDcSearchPath(pCfg, srcId, trgId);
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync if (idx < 0)
bcd589d9db90b68d3af5d6839c1d613bb64d4c04vboxsync return idx;
3a45119099f0df5230e8304145168aa5e2a3f1a1vboxsync
3a45119099f0df5230e8304145168aa5e2a3f1a1vboxsync if (!(pCfg->pPathInfoArray[idx].flags & DISPLAYCONFIG_PATH_ACTIVE))
3a45119099f0df5230e8304145168aa5e2a3f1a1vboxsync return -1;
3a45119099f0df5230e8304145168aa5e2a3f1a1vboxsync
3a45119099f0df5230e8304145168aa5e2a3f1a1vboxsync return idx;
3a45119099f0df5230e8304145168aa5e2a3f1a1vboxsync}
3a45119099f0df5230e8304145168aa5e2a3f1a1vboxsync
3a45119099f0df5230e8304145168aa5e2a3f1a1vboxsyncstatic VOID vboxDispIfWddmDcSettingsInvalidateModeIndex(VBOXDISPIF_WDDM_DISPCFG *pCfg, int idx)
3a45119099f0df5230e8304145168aa5e2a3f1a1vboxsync{
cbc215af8423a8326b27143c59c5d8fc9ffb0279vboxsync pCfg->pPathInfoArray[idx].sourceInfo.modeInfoIdx = DISPLAYCONFIG_PATH_MODE_IDX_INVALID;
3a45119099f0df5230e8304145168aa5e2a3f1a1vboxsync pCfg->pPathInfoArray[idx].targetInfo.modeInfoIdx = DISPLAYCONFIG_PATH_MODE_IDX_INVALID;
3a45119099f0df5230e8304145168aa5e2a3f1a1vboxsync}
3a45119099f0df5230e8304145168aa5e2a3f1a1vboxsync
3a45119099f0df5230e8304145168aa5e2a3f1a1vboxsyncstatic VOID vboxDispIfWddmDcSettingsInvalidateModeIndeces(VBOXDISPIF_WDDM_DISPCFG *pCfg)
3a45119099f0df5230e8304145168aa5e2a3f1a1vboxsync{
3a45119099f0df5230e8304145168aa5e2a3f1a1vboxsync for (UINT iter = 0; iter < pCfg->cPathInfoArray; ++iter)
3a45119099f0df5230e8304145168aa5e2a3f1a1vboxsync {
3a45119099f0df5230e8304145168aa5e2a3f1a1vboxsync vboxDispIfWddmDcSettingsInvalidateModeIndex(pCfg, (int)iter);
3a45119099f0df5230e8304145168aa5e2a3f1a1vboxsync }
3a45119099f0df5230e8304145168aa5e2a3f1a1vboxsync
3a45119099f0df5230e8304145168aa5e2a3f1a1vboxsync if (pCfg->pModeInfoArray)
3a45119099f0df5230e8304145168aa5e2a3f1a1vboxsync {
3a45119099f0df5230e8304145168aa5e2a3f1a1vboxsync free(pCfg->pModeInfoArray);
3a45119099f0df5230e8304145168aa5e2a3f1a1vboxsync pCfg->pModeInfoArray = NULL;
3a45119099f0df5230e8304145168aa5e2a3f1a1vboxsync }
3a45119099f0df5230e8304145168aa5e2a3f1a1vboxsync pCfg->cModeInfoArray = 0;
3a45119099f0df5230e8304145168aa5e2a3f1a1vboxsync}
3a45119099f0df5230e8304145168aa5e2a3f1a1vboxsync
3a45119099f0df5230e8304145168aa5e2a3f1a1vboxsyncstatic DWORD vboxDispIfWddmDcSettingsModeAdd(VBOXDISPIF_WDDM_DISPCFG *pCfg, UINT *pIdx)
3a45119099f0df5230e8304145168aa5e2a3f1a1vboxsync{
3a45119099f0df5230e8304145168aa5e2a3f1a1vboxsync UINT32 cModeInfoArray = pCfg->cModeInfoArray + 1;
3a45119099f0df5230e8304145168aa5e2a3f1a1vboxsync DISPLAYCONFIG_MODE_INFO *pModeInfoArray = (DISPLAYCONFIG_MODE_INFO *)malloc(cModeInfoArray * sizeof (DISPLAYCONFIG_MODE_INFO));
3a45119099f0df5230e8304145168aa5e2a3f1a1vboxsync if (!pModeInfoArray)
3a45119099f0df5230e8304145168aa5e2a3f1a1vboxsync {
3a45119099f0df5230e8304145168aa5e2a3f1a1vboxsync WARN(("VBoxTray: (WDDM) malloc failed!\n"));
3a45119099f0df5230e8304145168aa5e2a3f1a1vboxsync return ERROR_OUTOFMEMORY;
3a45119099f0df5230e8304145168aa5e2a3f1a1vboxsync }
3a45119099f0df5230e8304145168aa5e2a3f1a1vboxsync
3a45119099f0df5230e8304145168aa5e2a3f1a1vboxsync memcpy (pModeInfoArray, pCfg->pModeInfoArray, pCfg->cModeInfoArray * sizeof(DISPLAYCONFIG_MODE_INFO));
3a45119099f0df5230e8304145168aa5e2a3f1a1vboxsync memset(&pModeInfoArray[cModeInfoArray-1], 0, sizeof (pModeInfoArray[0]));
3a45119099f0df5230e8304145168aa5e2a3f1a1vboxsync free(pCfg->pModeInfoArray);
3a45119099f0df5230e8304145168aa5e2a3f1a1vboxsync *pIdx = cModeInfoArray-1;
3a45119099f0df5230e8304145168aa5e2a3f1a1vboxsync pCfg->pModeInfoArray = pModeInfoArray;
3a45119099f0df5230e8304145168aa5e2a3f1a1vboxsync pCfg->cModeInfoArray = cModeInfoArray;
3a45119099f0df5230e8304145168aa5e2a3f1a1vboxsync return ERROR_SUCCESS;
3a45119099f0df5230e8304145168aa5e2a3f1a1vboxsync}
3a45119099f0df5230e8304145168aa5e2a3f1a1vboxsync
3a45119099f0df5230e8304145168aa5e2a3f1a1vboxsyncstatic DWORD vboxDispIfWddmDcSettingsUpdate(VBOXDISPIF_WDDM_DISPCFG *pCfg, int idx, DEVMODE *pDeviceMode, BOOL fInvalidateSrcMode, BOOL fEnable)
3a45119099f0df5230e8304145168aa5e2a3f1a1vboxsync{
3a45119099f0df5230e8304145168aa5e2a3f1a1vboxsync UINT Id = pCfg->pPathInfoArray[idx].sourceInfo.id;
3a45119099f0df5230e8304145168aa5e2a3f1a1vboxsync
3a45119099f0df5230e8304145168aa5e2a3f1a1vboxsync if (fInvalidateSrcMode)
3a45119099f0df5230e8304145168aa5e2a3f1a1vboxsync pCfg->pPathInfoArray[idx].sourceInfo.modeInfoIdx = DISPLAYCONFIG_PATH_MODE_IDX_INVALID;
3a45119099f0df5230e8304145168aa5e2a3f1a1vboxsync else if (pDeviceMode)
3a45119099f0df5230e8304145168aa5e2a3f1a1vboxsync {
3a45119099f0df5230e8304145168aa5e2a3f1a1vboxsync UINT iSrcMode = pCfg->pPathInfoArray[idx].sourceInfo.modeInfoIdx;
3a45119099f0df5230e8304145168aa5e2a3f1a1vboxsync if (iSrcMode == DISPLAYCONFIG_PATH_MODE_IDX_INVALID)
3a45119099f0df5230e8304145168aa5e2a3f1a1vboxsync {
3a45119099f0df5230e8304145168aa5e2a3f1a1vboxsync
3a45119099f0df5230e8304145168aa5e2a3f1a1vboxsync WARN(("VBoxTray: (WDDM) no source mode index specified"));
3a45119099f0df5230e8304145168aa5e2a3f1a1vboxsync DWORD winEr = vboxDispIfWddmDcSettingsModeAdd(pCfg, &iSrcMode);
3a45119099f0df5230e8304145168aa5e2a3f1a1vboxsync if (winEr != ERROR_SUCCESS)
3a45119099f0df5230e8304145168aa5e2a3f1a1vboxsync {
3a45119099f0df5230e8304145168aa5e2a3f1a1vboxsync WARN(("VBoxTray:(WDDM) vboxDispIfWddmDcSettingsModeAdd Failed winEr %d\n", winEr));
3a45119099f0df5230e8304145168aa5e2a3f1a1vboxsync return winEr;
3a45119099f0df5230e8304145168aa5e2a3f1a1vboxsync }
3a45119099f0df5230e8304145168aa5e2a3f1a1vboxsync pCfg->pPathInfoArray[idx].sourceInfo.modeInfoIdx = iSrcMode;
bcd589d9db90b68d3af5d6839c1d613bb64d4c04vboxsync }
bcd589d9db90b68d3af5d6839c1d613bb64d4c04vboxsync
bcd589d9db90b68d3af5d6839c1d613bb64d4c04vboxsync for (int i = 0; i < (int)pCfg->cPathInfoArray; ++i)
bcd589d9db90b68d3af5d6839c1d613bb64d4c04vboxsync {
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync if (i == idx)
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync continue;
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync if (pCfg->pPathInfoArray[i].sourceInfo.modeInfoIdx == iSrcMode)
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync {
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync /* this is something we're not expecting/supporting */
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync WARN(("VBoxTray: (WDDM) multiple paths have the same mode index"));
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync return ERROR_NOT_SUPPORTED;
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync }
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync }
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync if (pDeviceMode->dmFields & DM_PELSWIDTH)
bcd589d9db90b68d3af5d6839c1d613bb64d4c04vboxsync pCfg->pModeInfoArray[iSrcMode].sourceMode.width = pDeviceMode->dmPelsWidth;
bcd589d9db90b68d3af5d6839c1d613bb64d4c04vboxsync if (pDeviceMode->dmFields & DM_PELSHEIGHT)
bcd589d9db90b68d3af5d6839c1d613bb64d4c04vboxsync pCfg->pModeInfoArray[iSrcMode].sourceMode.height = pDeviceMode->dmPelsHeight;
bcd589d9db90b68d3af5d6839c1d613bb64d4c04vboxsync if (pDeviceMode->dmFields & DM_POSITION)
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync {
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync pCfg->pModeInfoArray[iSrcMode].sourceMode.position.x = pDeviceMode->dmPosition.x;
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync pCfg->pModeInfoArray[iSrcMode].sourceMode.position.y = pDeviceMode->dmPosition.y;
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync }
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync if (pDeviceMode->dmFields & DM_BITSPERPEL)
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync {
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync switch (pDeviceMode->dmBitsPerPel)
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync {
2dd7b4388106de88d20f33a8aa6c85c8babf507bvboxsync case 32:
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync pCfg->pModeInfoArray[iSrcMode].sourceMode.pixelFormat = DISPLAYCONFIG_PIXELFORMAT_32BPP;
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync break;
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync case 24:
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync pCfg->pModeInfoArray[iSrcMode].sourceMode.pixelFormat = DISPLAYCONFIG_PIXELFORMAT_24BPP;
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync break;
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync case 16:
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync pCfg->pModeInfoArray[iSrcMode].sourceMode.pixelFormat = DISPLAYCONFIG_PIXELFORMAT_16BPP;
bcd589d9db90b68d3af5d6839c1d613bb64d4c04vboxsync break;
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync case 8:
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync pCfg->pModeInfoArray[iSrcMode].sourceMode.pixelFormat = DISPLAYCONFIG_PIXELFORMAT_8BPP;
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync break;
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync default:
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync LogRel(("VBoxTray: (WDDM) invalid bpp %d, using 32\n", pDeviceMode->dmBitsPerPel));
32e575e61406701e77c0527bfc843fdc85c4003fvboxsync pCfg->pModeInfoArray[iSrcMode].sourceMode.pixelFormat = DISPLAYCONFIG_PIXELFORMAT_32BPP;
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync break;
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync }
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync }
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync }
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync pCfg->pPathInfoArray[idx].targetInfo.modeInfoIdx = DISPLAYCONFIG_PATH_MODE_IDX_INVALID;
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync if (fEnable)
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync pCfg->pPathInfoArray[idx].flags |= DISPLAYCONFIG_PATH_ACTIVE;
bcd589d9db90b68d3af5d6839c1d613bb64d4c04vboxsync else
8d1da51eb6665874aa82bf03668e03d1a0d63223vboxsync pCfg->pPathInfoArray[idx].flags &= ~DISPLAYCONFIG_PATH_ACTIVE;
8d1da51eb6665874aa82bf03668e03d1a0d63223vboxsync
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync return ERROR_SUCCESS;
8cb6f31c3048428b42c7370dfbb20e4de7254f40vboxsync}
7cfcbe810de5334cdc2e8b92e77db705da143adavboxsync
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsyncstatic DWORD vboxDispIfWddmDcSet(VBOXDISPIF_WDDM_DISPCFG *pCfg, UINT fFlags)
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync{
a8d502445ce722c6b9700c5579b4a38b58827b7dvboxsync DWORD winEr = gCtx.pfnSetDisplayConfig(pCfg->cPathInfoArray, pCfg->pPathInfoArray, pCfg->cModeInfoArray, pCfg->pModeInfoArray, fFlags);
a8d502445ce722c6b9700c5579b4a38b58827b7dvboxsync if (winEr != ERROR_SUCCESS)
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync Log(("VBoxTray:(WDDM) pfnSetDisplayConfig Failed for Flags 0x%x\n", fFlags));
7cfcbe810de5334cdc2e8b92e77db705da143adavboxsync return winEr;
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync}
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsyncstatic BOOL vboxDispIfWddmDcSettingsAdjustSupportedPaths(VBOXDISPIF_WDDM_DISPCFG *pCfg)
2dd7b4388106de88d20f33a8aa6c85c8babf507bvboxsync{
2dd7b4388106de88d20f33a8aa6c85c8babf507bvboxsync BOOL fAdjusted = FALSE;
2dd7b4388106de88d20f33a8aa6c85c8babf507bvboxsync for (UINT iter = 0; iter < pCfg->cPathInfoArray; ++iter)
2dd7b4388106de88d20f33a8aa6c85c8babf507bvboxsync {
2dd7b4388106de88d20f33a8aa6c85c8babf507bvboxsync if (pCfg->pPathInfoArray[iter].sourceInfo.id == pCfg->pPathInfoArray[iter].targetInfo.id)
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync continue;
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync
a8d502445ce722c6b9700c5579b4a38b58827b7dvboxsync if (!(pCfg->pPathInfoArray[iter].flags & DISPLAYCONFIG_PATH_ACTIVE))
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync continue;
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync pCfg->pPathInfoArray[iter].flags &= ~DISPLAYCONFIG_PATH_ACTIVE;
a8d502445ce722c6b9700c5579b4a38b58827b7dvboxsync fAdjusted = TRUE;
a8d502445ce722c6b9700c5579b4a38b58827b7dvboxsync }
a8d502445ce722c6b9700c5579b4a38b58827b7dvboxsync
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync return fAdjusted;
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync}
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsyncstatic void vboxDispIfWddmDcSettingsAttachDisbledToPrimary(VBOXDISPIF_WDDM_DISPCFG *pCfg)
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync{
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync for (UINT iter = 0; iter < pCfg->cPathInfoArray; ++iter)
7cfcbe810de5334cdc2e8b92e77db705da143adavboxsync {
7cfcbe810de5334cdc2e8b92e77db705da143adavboxsync if ((pCfg->pPathInfoArray[iter].flags & DISPLAYCONFIG_PATH_ACTIVE))
01df41f7a4e5f7de195a059541d1c89676da9673vboxsync continue;
01df41f7a4e5f7de195a059541d1c89676da9673vboxsync
01df41f7a4e5f7de195a059541d1c89676da9673vboxsync pCfg->pPathInfoArray[iter].sourceInfo.id = 0;
01df41f7a4e5f7de195a059541d1c89676da9673vboxsync pCfg->pPathInfoArray[iter].sourceInfo.modeInfoIdx = DISPLAYCONFIG_PATH_MODE_IDX_INVALID;
01df41f7a4e5f7de195a059541d1c89676da9673vboxsync pCfg->pPathInfoArray[iter].targetInfo.modeInfoIdx = DISPLAYCONFIG_PATH_MODE_IDX_INVALID;
8cb6f31c3048428b42c7370dfbb20e4de7254f40vboxsync }
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync}
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync
6902a98267d5180fb081cb5273751d0a628bf04dvboxsyncstatic DWORD vboxDispIfWddmDcSettingsIncludeAllTargets(VBOXDISPIF_WDDM_DISPCFG *pCfg)
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync{
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync UINT32 cDisplays = 0;
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync VBOXDISPIF_WDDM_DISPCFG AllCfg;
3c9ed6defa3feca7e21adef4b5d1ba3002fc94c9vboxsync BOOL fAllCfgInited = FALSE;
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync DWORD winEr = vboxDispIfWddmDcQueryNumDisplays(&cDisplays);
bcd589d9db90b68d3af5d6839c1d613bb64d4c04vboxsync if (winEr != ERROR_SUCCESS)
bcd589d9db90b68d3af5d6839c1d613bb64d4c04vboxsync {
bcd589d9db90b68d3af5d6839c1d613bb64d4c04vboxsync WARN(("VBoxTray:(WDDM) vboxDispIfWddmDcQueryNumDisplays Failed winEr %d\n", winEr));
bcd589d9db90b68d3af5d6839c1d613bb64d4c04vboxsync return winEr;
bcd589d9db90b68d3af5d6839c1d613bb64d4c04vboxsync }
bcd589d9db90b68d3af5d6839c1d613bb64d4c04vboxsync
bcd589d9db90b68d3af5d6839c1d613bb64d4c04vboxsync DISPLAYCONFIG_PATH_INFO *pPathInfoArray = (DISPLAYCONFIG_PATH_INFO *)malloc(cDisplays * sizeof(DISPLAYCONFIG_PATH_INFO));
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync if (!pPathInfoArray)
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync {
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync WARN(("malloc failed\n"));
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync return ERROR_OUTOFMEMORY;
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync }
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync for (UINT i = 0; i < cDisplays; ++i)
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync {
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync int idx = vboxDispIfWddmDcSearchPath(pCfg, i, i);
bcd589d9db90b68d3af5d6839c1d613bb64d4c04vboxsync if (idx < 0)
bcd589d9db90b68d3af5d6839c1d613bb64d4c04vboxsync {
bcd589d9db90b68d3af5d6839c1d613bb64d4c04vboxsync idx = vboxDispIfWddmDcSearchPath(pCfg, -1, i);
bcd589d9db90b68d3af5d6839c1d613bb64d4c04vboxsync if (idx >= 0)
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync {
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync WARN(("VBoxTray:(WDDM) different source and target paare enabled, this is something we would not expect\n"));
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync }
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync }
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync if (idx >= 0)
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync pPathInfoArray[i] = pCfg->pPathInfoArray[idx];
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync else
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync {
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync if (!fAllCfgInited)
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync {
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync winEr = vboxDispIfWddmDcCreate(&AllCfg, QDC_ALL_PATHS);
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync if (winEr != ERROR_SUCCESS)
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync {
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync WARN(("VBoxTray:(WDDM) vboxDispIfWddmDcCreate Failed winEr %d\n", winEr));
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync free(pPathInfoArray);
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync return winEr;
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync }
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync fAllCfgInited = TRUE;
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync }
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync idx = vboxDispIfWddmDcSearchPath(&AllCfg, i, i);
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync if (idx < 0)
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync {
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync WARN(("VBoxTray:(WDDM) %d %d path not supported\n", i, i));
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync idx = vboxDispIfWddmDcSearchPath(pCfg, -1, i);
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync if (idx < 0)
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync {
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync WARN(("VBoxTray:(WDDM) %d %d path not supported\n", -1, i));
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync }
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync }
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync if (idx >= 0)
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync {
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync pPathInfoArray[i] = AllCfg.pPathInfoArray[idx];
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync if (pPathInfoArray[i].flags & DISPLAYCONFIG_PATH_ACTIVE)
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync {
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync WARN(("VBoxTray:(WDDM) disabled path %d %d is marked active\n",
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync pPathInfoArray[i].sourceInfo.id, pPathInfoArray[i].targetInfo.id));
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync pPathInfoArray[i].flags &= ~DISPLAYCONFIG_PATH_ACTIVE;
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync }
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync Assert(pPathInfoArray[i].sourceInfo.modeInfoIdx == DISPLAYCONFIG_PATH_MODE_IDX_INVALID);
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync Assert(pPathInfoArray[i].sourceInfo.statusFlags == 0);
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync Assert(pPathInfoArray[i].targetInfo.modeInfoIdx == DISPLAYCONFIG_PATH_MODE_IDX_INVALID);
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync Assert(pPathInfoArray[i].targetInfo.outputTechnology == DISPLAYCONFIG_OUTPUT_TECHNOLOGY_HD15);
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync Assert(pPathInfoArray[i].targetInfo.rotation == DISPLAYCONFIG_ROTATION_IDENTITY);
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync Assert(pPathInfoArray[i].targetInfo.scaling == DISPLAYCONFIG_SCALING_PREFERRED);
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync Assert(pPathInfoArray[i].targetInfo.refreshRate.Numerator == 0);
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync Assert(pPathInfoArray[i].targetInfo.refreshRate.Denominator == 0);
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync Assert(pPathInfoArray[i].targetInfo.scanLineOrdering == DISPLAYCONFIG_SCANLINE_ORDERING_UNSPECIFIED);
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync Assert(pPathInfoArray[i].targetInfo.targetAvailable == TRUE);
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync Assert(pPathInfoArray[i].targetInfo.statusFlags == DISPLAYCONFIG_TARGET_FORCIBLE);
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync Assert(pPathInfoArray[i].flags == 0);
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync }
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync else
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync {
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync pPathInfoArray[i].sourceInfo.adapterId = pCfg->pPathInfoArray[0].sourceInfo.adapterId;
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync pPathInfoArray[i].sourceInfo.id = i;
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync pPathInfoArray[i].sourceInfo.modeInfoIdx = DISPLAYCONFIG_PATH_MODE_IDX_INVALID;
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync pPathInfoArray[i].sourceInfo.statusFlags = 0;
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync pPathInfoArray[i].targetInfo.adapterId = pPathInfoArray[i].sourceInfo.adapterId;
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync pPathInfoArray[i].targetInfo.id = i;
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync pPathInfoArray[i].targetInfo.modeInfoIdx = DISPLAYCONFIG_PATH_MODE_IDX_INVALID;
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync pPathInfoArray[i].targetInfo.outputTechnology = DISPLAYCONFIG_OUTPUT_TECHNOLOGY_HD15;
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync pPathInfoArray[i].targetInfo.rotation = DISPLAYCONFIG_ROTATION_IDENTITY;
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync pPathInfoArray[i].targetInfo.scaling = DISPLAYCONFIG_SCALING_PREFERRED;
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync pPathInfoArray[i].targetInfo.refreshRate.Numerator = 0;
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync pPathInfoArray[i].targetInfo.refreshRate.Denominator = 0;
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync pPathInfoArray[i].targetInfo.scanLineOrdering = DISPLAYCONFIG_SCANLINE_ORDERING_UNSPECIFIED;
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync pPathInfoArray[i].targetInfo.targetAvailable = TRUE;
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync pPathInfoArray[i].targetInfo.statusFlags = DISPLAYCONFIG_TARGET_FORCIBLE;
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync pPathInfoArray[i].flags = 0;
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync }
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync }
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync }
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync free(pCfg->pPathInfoArray);
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync pCfg->pPathInfoArray = pPathInfoArray;
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync pCfg->cPathInfoArray = cDisplays;
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync if (fAllCfgInited)
2dd7b4388106de88d20f33a8aa6c85c8babf507bvboxsync vboxDispIfWddmDcTerm(&AllCfg);
2dd7b4388106de88d20f33a8aa6c85c8babf507bvboxsync
2dd7b4388106de88d20f33a8aa6c85c8babf507bvboxsync return ERROR_SUCCESS;
2dd7b4388106de88d20f33a8aa6c85c8babf507bvboxsync}
2dd7b4388106de88d20f33a8aa6c85c8babf507bvboxsync
2dd7b4388106de88d20f33a8aa6c85c8babf507bvboxsyncstatic DWORD vboxDispIfOpBegin(PCVBOXDISPIF pIf, VBOXDISPIF_OP *pOp)
2dd7b4388106de88d20f33a8aa6c85c8babf507bvboxsync{
2dd7b4388106de88d20f33a8aa6c85c8babf507bvboxsync pOp->pIf = pIf;
2dd7b4388106de88d20f33a8aa6c85c8babf507bvboxsync
2dd7b4388106de88d20f33a8aa6c85c8babf507bvboxsync HRESULT hr = vboxDispKmtOpenAdapter(&pIf->modeData.wddm.KmtCallbacks, &pOp->Adapter);
2dd7b4388106de88d20f33a8aa6c85c8babf507bvboxsync if (SUCCEEDED(hr))
2dd7b4388106de88d20f33a8aa6c85c8babf507bvboxsync {
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync hr = vboxDispKmtCreateDevice(&pOp->Adapter, &pOp->Device);
2dd7b4388106de88d20f33a8aa6c85c8babf507bvboxsync if (SUCCEEDED(hr))
2dd7b4388106de88d20f33a8aa6c85c8babf507bvboxsync {
2dd7b4388106de88d20f33a8aa6c85c8babf507bvboxsync hr = vboxDispKmtCreateContext(&pOp->Device, &pOp->Context, VBOXWDDM_CONTEXT_TYPE_CUSTOM_DISPIF_RESIZE,
2dd7b4388106de88d20f33a8aa6c85c8babf507bvboxsync 0, 0, NULL, 0ULL);
2dd7b4388106de88d20f33a8aa6c85c8babf507bvboxsync if (SUCCEEDED(hr))
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync return ERROR_SUCCESS;
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync else
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync WARN(("VBoxTray: vboxDispKmtCreateContext failed hr 0x%x", hr));
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync vboxDispKmtDestroyDevice(&pOp->Device);
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync }
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync else
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync WARN(("VBoxTray: vboxDispKmtCreateDevice failed hr 0x%x", hr));
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync vboxDispKmtCloseAdapter(&pOp->Adapter);
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync }
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync return hr;
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync}
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsyncstatic VOID vboxDispIfOpEnd(VBOXDISPIF_OP *pOp)
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync{
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync vboxDispKmtDestroyContext(&pOp->Context);
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync vboxDispKmtDestroyDevice(&pOp->Device);
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync vboxDispKmtCloseAdapter(&pOp->Adapter);
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync}
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync/* display driver interface abstraction for XPDM & WDDM
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync * with WDDM we can not use ExtEscape to communicate with our driver
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync * because we do not have XPDM display driver any more, i.e. escape requests are handled by cdd
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync * that knows nothing about us */
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsyncDWORD VBoxDispIfInit(PVBOXDISPIF pIf)
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync{
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync pIf->enmMode = VBOXDISPIF_MODE_XPDM;
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync return NO_ERROR;
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync}
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync#ifdef VBOX_WITH_WDDM
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsyncstatic void vboxDispIfWddmTerm(PCVBOXDISPIF pIf);
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsyncstatic DWORD vboxDispIfWddmInit(PCVBOXDISPIF pIf);
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync#endif
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsyncDWORD VBoxDispIfTerm(PVBOXDISPIF pIf)
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync{
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync#ifdef VBOX_WITH_WDDM
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync if (pIf->enmMode >= VBOXDISPIF_MODE_WDDM)
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync {
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync vboxDispIfWddmTerm(pIf);
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync vboxDispKmtCallbacksTerm(&pIf->modeData.wddm.KmtCallbacks);
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync }
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync#endif
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync pIf->enmMode = VBOXDISPIF_MODE_UNKNOWN;
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync return NO_ERROR;
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync}
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsyncstatic DWORD vboxDispIfEscapeXPDM(PCVBOXDISPIF pIf, PVBOXDISPIFESCAPE pEscape, int cbData, int iDirection)
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync{
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync HDC hdc = GetDC(HWND_DESKTOP);
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync VOID *pvData = cbData ? VBOXDISPIFESCAPE_DATA(pEscape, VOID) : NULL;
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync int iRet = ExtEscape(hdc, pEscape->escapeCode,
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync iDirection >= 0 ? cbData : 0,
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync iDirection >= 0 ? (LPSTR)pvData : NULL,
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync iDirection <= 0 ? cbData : 0,
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync iDirection <= 0 ? (LPSTR)pvData : NULL);
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync ReleaseDC(HWND_DESKTOP, hdc);
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync if (iRet > 0)
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync return VINF_SUCCESS;
c9a593aa048a154e59b52d1237d89e3cdaee9b3dvboxsync else if (iRet == 0)
c9a593aa048a154e59b52d1237d89e3cdaee9b3dvboxsync return ERROR_NOT_SUPPORTED;
c9a593aa048a154e59b52d1237d89e3cdaee9b3dvboxsync /* else */
c9a593aa048a154e59b52d1237d89e3cdaee9b3dvboxsync return ERROR_GEN_FAILURE;
c9a593aa048a154e59b52d1237d89e3cdaee9b3dvboxsync}
c9a593aa048a154e59b52d1237d89e3cdaee9b3dvboxsync
c9a593aa048a154e59b52d1237d89e3cdaee9b3dvboxsync#ifdef VBOX_WITH_WDDM
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsyncstatic DWORD vboxDispIfSwitchToWDDM(PVBOXDISPIF pIf)
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync{
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync DWORD err = NO_ERROR;
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync OSVERSIONINFO OSinfo;
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync OSinfo.dwOSVersionInfoSize = sizeof (OSinfo);
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync GetVersionEx (&OSinfo);
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync bool bSupported = true;
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync if (OSinfo.dwMajorVersion >= 6)
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync {
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync Log((__FUNCTION__": this is vista and up\n"));
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync HMODULE hUser = GetModuleHandle("user32.dll");
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync if (hUser)
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync {
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync *(uintptr_t *)&pIf->modeData.wddm.pfnChangeDisplaySettingsEx = (uintptr_t)GetProcAddress(hUser, "ChangeDisplaySettingsExA");
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync Log((__FUNCTION__": VBoxDisplayInit: pfnChangeDisplaySettingsEx = %p\n", pIf->modeData.wddm.pfnChangeDisplaySettingsEx));
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync bSupported &= !!(pIf->modeData.wddm.pfnChangeDisplaySettingsEx);
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync *(uintptr_t *)&pIf->modeData.wddm.pfnEnumDisplayDevices = (uintptr_t)GetProcAddress(hUser, "EnumDisplayDevicesA");
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync Log((__FUNCTION__": VBoxDisplayInit: pfnEnumDisplayDevices = %p\n", pIf->modeData.wddm.pfnEnumDisplayDevices));
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync bSupported &= !!(pIf->modeData.wddm.pfnEnumDisplayDevices);
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync /* for win 7 and above */
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync if (OSinfo.dwMinorVersion >= 1)
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync {
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync *(uintptr_t *)&gCtx.pfnSetDisplayConfig = (uintptr_t)GetProcAddress(hUser, "SetDisplayConfig");
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync Log((__FUNCTION__": VBoxDisplayInit: pfnSetDisplayConfig = %p\n", gCtx.pfnSetDisplayConfig));
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync bSupported &= !!(gCtx.pfnSetDisplayConfig);
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync *(uintptr_t *)&gCtx.pfnQueryDisplayConfig = (uintptr_t)GetProcAddress(hUser, "QueryDisplayConfig");
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync Log((__FUNCTION__": VBoxDisplayInit: pfnQueryDisplayConfig = %p\n", gCtx.pfnQueryDisplayConfig));
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync bSupported &= !!(gCtx.pfnQueryDisplayConfig);
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync *(uintptr_t *)&gCtx.pfnGetDisplayConfigBufferSizes = (uintptr_t)GetProcAddress(hUser, "GetDisplayConfigBufferSizes");
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync Log((__FUNCTION__": VBoxDisplayInit: pfnGetDisplayConfigBufferSizes = %p\n", gCtx.pfnGetDisplayConfigBufferSizes));
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync bSupported &= !!(gCtx.pfnGetDisplayConfigBufferSizes);
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync }
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync /* this is vista and up */
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync HRESULT hr = vboxDispKmtCallbacksInit(&pIf->modeData.wddm.KmtCallbacks);
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync if (FAILED(hr))
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync {
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync WARN(("VBoxTray: vboxDispKmtCallbacksInit failed hr 0x%x\n", hr));
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync err = hr;
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync }
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync }
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync else
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync {
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync WARN((__FUNCTION__": GetModuleHandle(USER32) failed, err(%d)\n", GetLastError()));
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync err = ERROR_NOT_SUPPORTED;
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync }
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync }
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync else
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync {
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync WARN((__FUNCTION__": can not switch to VBOXDISPIF_MODE_WDDM, because os is not Vista or upper\n"));
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync err = ERROR_NOT_SUPPORTED;
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync }
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync if (err == ERROR_SUCCESS)
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync {
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync err = vboxDispIfWddmInit(pIf);
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync }
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync return err;
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync}
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsyncstatic DWORD vboxDispIfSwitchToWDDM_W7(PVBOXDISPIF pIf)
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync{
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync return vboxDispIfSwitchToWDDM(pIf);
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync}
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsyncstatic DWORD vboxDispIfWDDMAdpHdcCreate(int iDisplay, HDC *phDc, DISPLAY_DEVICE *pDev)
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync{
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync DWORD winEr = ERROR_INVALID_STATE;
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync memset(pDev, 0, sizeof (*pDev));
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync pDev->cb = sizeof (*pDev);
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync for (int i = 0; ; ++i)
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync {
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync if (EnumDisplayDevices(NULL, /* LPCTSTR lpDevice */ i, /* DWORD iDevNum */
2dd7b4388106de88d20f33a8aa6c85c8babf507bvboxsync pDev, 0 /* DWORD dwFlags*/))
2dd7b4388106de88d20f33a8aa6c85c8babf507bvboxsync {
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync if (i == iDisplay || (iDisplay < 0 && pDev->StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE))
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync {
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync HDC hDc = CreateDC(NULL, pDev->DeviceName, NULL, NULL);
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync if (hDc)
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync {
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync *phDc = hDc;
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync return NO_ERROR;
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync }
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync else
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync {
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync winEr = GetLastError();
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync WARN(("CreateDC failed %d", winEr));
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync break;
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync }
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync }
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync Log(("display data no match display(%d): i(%d), flags(%d)", iDisplay, i, pDev->StateFlags));
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync }
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync else
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync {
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync winEr = GetLastError();
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync WARN(("EnumDisplayDevices failed %d", winEr));
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync break;
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync }
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync }
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync WARN(("vboxDispIfWDDMAdpHdcCreate failure branch %d", winEr));
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync return winEr;
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync}
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsyncstatic DWORD vboxDispIfEscapeWDDM(PCVBOXDISPIF pIf, PVBOXDISPIFESCAPE pEscape, int cbData, BOOL fHwAccess)
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync{
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync DWORD winEr = ERROR_SUCCESS;
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync VBOXDISPKMT_ADAPTER Adapter;
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync HRESULT hr = vboxDispKmtOpenAdapter(&pIf->modeData.wddm.KmtCallbacks, &Adapter);
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync if (!SUCCEEDED(hr))
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync {
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync WARN(("VBoxTray: vboxDispKmtOpenAdapter failed hr 0x%x\n", hr));
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync return hr;
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync }
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync D3DKMT_ESCAPE EscapeData = {0};
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync EscapeData.hAdapter = Adapter.hAdapter;
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync //EscapeData.hDevice = NULL;
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync EscapeData.Type = D3DKMT_ESCAPE_DRIVERPRIVATE;
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync if (fHwAccess)
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync EscapeData.Flags.HardwareAccess = 1;
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync EscapeData.pPrivateDriverData = pEscape;
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync EscapeData.PrivateDriverDataSize = VBOXDISPIFESCAPE_SIZE(cbData);
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync //EscapeData.hContext = NULL;
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync NTSTATUS Status = pIf->modeData.wddm.KmtCallbacks.pfnD3DKMTEscape(&EscapeData);
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync if (NT_SUCCESS(Status))
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync winEr = ERROR_SUCCESS;
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync else
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync {
a8d502445ce722c6b9700c5579b4a38b58827b7dvboxsync WARN(("VBoxTray: pfnD3DKMTEscape failed Status 0x%x\n", Status));
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync winEr = ERROR_GEN_FAILURE;
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync }
a8d502445ce722c6b9700c5579b4a38b58827b7dvboxsync
a8d502445ce722c6b9700c5579b4a38b58827b7dvboxsync vboxDispKmtCloseAdapter(&Adapter);
a8d502445ce722c6b9700c5579b4a38b58827b7dvboxsync
a8d502445ce722c6b9700c5579b4a38b58827b7dvboxsync return winEr;
a8d502445ce722c6b9700c5579b4a38b58827b7dvboxsync}
a8d502445ce722c6b9700c5579b4a38b58827b7dvboxsync#endif
a8d502445ce722c6b9700c5579b4a38b58827b7dvboxsync
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsyncDWORD VBoxDispIfEscape(PCVBOXDISPIF pIf, PVBOXDISPIFESCAPE pEscape, int cbData)
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync{
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync switch (pIf->enmMode)
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync {
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync case VBOXDISPIF_MODE_XPDM_NT4:
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync case VBOXDISPIF_MODE_XPDM:
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync return vboxDispIfEscapeXPDM(pIf, pEscape, cbData, 1);
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync#ifdef VBOX_WITH_WDDM
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync case VBOXDISPIF_MODE_WDDM:
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync case VBOXDISPIF_MODE_WDDM_W7:
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync return vboxDispIfEscapeWDDM(pIf, pEscape, cbData, TRUE /* BOOL fHwAccess */);
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync#endif
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync default:
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync Log((__FUNCTION__": unknown mode (%d)\n", pIf->enmMode));
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync return ERROR_INVALID_PARAMETER;
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync }
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync}
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsyncDWORD VBoxDispIfEscapeInOut(PCVBOXDISPIF const pIf, PVBOXDISPIFESCAPE pEscape, int cbData)
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync{
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync switch (pIf->enmMode)
a8d502445ce722c6b9700c5579b4a38b58827b7dvboxsync {
a8d502445ce722c6b9700c5579b4a38b58827b7dvboxsync case VBOXDISPIF_MODE_XPDM_NT4:
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync case VBOXDISPIF_MODE_XPDM:
a8d502445ce722c6b9700c5579b4a38b58827b7dvboxsync return vboxDispIfEscapeXPDM(pIf, pEscape, cbData, 0);
a8d502445ce722c6b9700c5579b4a38b58827b7dvboxsync#ifdef VBOX_WITH_WDDM
a8d502445ce722c6b9700c5579b4a38b58827b7dvboxsync case VBOXDISPIF_MODE_WDDM:
a8d502445ce722c6b9700c5579b4a38b58827b7dvboxsync case VBOXDISPIF_MODE_WDDM_W7:
a8d502445ce722c6b9700c5579b4a38b58827b7dvboxsync return vboxDispIfEscapeWDDM(pIf, pEscape, cbData, TRUE /* BOOL fHwAccess */);
a8d502445ce722c6b9700c5579b4a38b58827b7dvboxsync#endif
a8d502445ce722c6b9700c5579b4a38b58827b7dvboxsync default:
a8d502445ce722c6b9700c5579b4a38b58827b7dvboxsync Log((__FUNCTION__": unknown mode (%d)\n", pIf->enmMode));
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync return ERROR_INVALID_PARAMETER;
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync }
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync}
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync#ifdef VBOX_WITH_WDDM
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync#define VBOXRR_TIMER_ID 1234
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsynctypedef struct VBOXRR
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync{
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync HANDLE hThread;
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync DWORD idThread;
7cfcbe810de5334cdc2e8b92e77db705da143adavboxsync HANDLE hEvent;
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync HWND hWnd;
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync CRITICAL_SECTION CritSect;
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync UINT_PTR idTimer;
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync PCVBOXDISPIF pIf;
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync UINT iChangedMode;
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync BOOL fEnable;
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync BOOL fExtDispSup;
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync DISPLAY_DEVICE *paDisplayDevices;
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync DEVMODE *paDeviceModes;
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync UINT cDevModes;
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync} VBOXRR, *PVBOXRR;
8d1da51eb6665874aa82bf03668e03d1a0d63223vboxsync
8d1da51eb6665874aa82bf03668e03d1a0d63223vboxsyncstatic VBOXRR g_VBoxRr = {0};
8cb6f31c3048428b42c7370dfbb20e4de7254f40vboxsync
7cfcbe810de5334cdc2e8b92e77db705da143adavboxsync#define VBOX_E_INSUFFICIENT_BUFFER HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER)
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync#define VBOX_E_NOT_SUPPORTED HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED)
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync
a8d502445ce722c6b9700c5579b4a38b58827b7dvboxsyncstatic void vboxRrRetryStopLocked()
a8d502445ce722c6b9700c5579b4a38b58827b7dvboxsync{
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync PVBOXRR pMon = &g_VBoxRr;
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync if (pMon->pIf)
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync {
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync if (pMon->paDisplayDevices)
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync {
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync free(pMon->paDisplayDevices);
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync pMon->paDisplayDevices = NULL;
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync }
3c9ed6defa3feca7e21adef4b5d1ba3002fc94c9vboxsync
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync if (pMon->paDeviceModes)
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync {
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync free(pMon->paDeviceModes);
01df41f7a4e5f7de195a059541d1c89676da9673vboxsync pMon->paDeviceModes = NULL;
01df41f7a4e5f7de195a059541d1c89676da9673vboxsync }
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync if (pMon->idTimer)
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync {
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync KillTimer(pMon->hWnd, pMon->idTimer);
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync pMon->idTimer = 0;
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync }
3c9ed6defa3feca7e21adef4b5d1ba3002fc94c9vboxsync
3c9ed6defa3feca7e21adef4b5d1ba3002fc94c9vboxsync pMon->cDevModes = 0;
8cb6f31c3048428b42c7370dfbb20e4de7254f40vboxsync pMon->pIf = NULL;
8cb6f31c3048428b42c7370dfbb20e4de7254f40vboxsync }
8cb6f31c3048428b42c7370dfbb20e4de7254f40vboxsync}
01df41f7a4e5f7de195a059541d1c89676da9673vboxsync
01df41f7a4e5f7de195a059541d1c89676da9673vboxsyncstatic void VBoxRrRetryStop()
8cb6f31c3048428b42c7370dfbb20e4de7254f40vboxsync{
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync PVBOXRR pMon = &g_VBoxRr;
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync EnterCriticalSection(&pMon->CritSect);
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync vboxRrRetryStopLocked();
3c9ed6defa3feca7e21adef4b5d1ba3002fc94c9vboxsync LeaveCriticalSection(&pMon->CritSect);
3c9ed6defa3feca7e21adef4b5d1ba3002fc94c9vboxsync}
3c9ed6defa3feca7e21adef4b5d1ba3002fc94c9vboxsync
3c9ed6defa3feca7e21adef4b5d1ba3002fc94c9vboxsync//static DWORD vboxDispIfWddmValidateFixResize(PCVBOXDISPIF const pIf, DISPLAY_DEVICE *paDisplayDevices, DEVMODE *paDeviceModes, UINT cDevModes);
3c9ed6defa3feca7e21adef4b5d1ba3002fc94c9vboxsync
3c9ed6defa3feca7e21adef4b5d1ba3002fc94c9vboxsyncstatic void vboxRrRetryReschedule()
3c9ed6defa3feca7e21adef4b5d1ba3002fc94c9vboxsync{
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync}
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsyncstatic void VBoxRrRetrySchedule(PCVBOXDISPIF const pIf, UINT iChangedMode, BOOL fEnable, BOOL fExtDispSup, DISPLAY_DEVICE *paDisplayDevices, DEVMODE *paDeviceModes, UINT cDevModes)
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync{
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync PVBOXRR pMon = &g_VBoxRr;
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync EnterCriticalSection(&pMon->CritSect);
7cfcbe810de5334cdc2e8b92e77db705da143adavboxsync vboxRrRetryStopLocked();
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync pMon->pIf = pIf;
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync pMon->iChangedMode = iChangedMode;
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync pMon->fEnable = fEnable;
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync pMon->fExtDispSup = fExtDispSup;
3c9ed6defa3feca7e21adef4b5d1ba3002fc94c9vboxsync
3c9ed6defa3feca7e21adef4b5d1ba3002fc94c9vboxsync if (cDevModes)
3c9ed6defa3feca7e21adef4b5d1ba3002fc94c9vboxsync {
3c9ed6defa3feca7e21adef4b5d1ba3002fc94c9vboxsync pMon->paDisplayDevices = (DISPLAY_DEVICE*)malloc(sizeof (*paDisplayDevices) * cDevModes);
3c9ed6defa3feca7e21adef4b5d1ba3002fc94c9vboxsync Assert(pMon->paDisplayDevices);
01df41f7a4e5f7de195a059541d1c89676da9673vboxsync if (!pMon->paDisplayDevices)
3c9ed6defa3feca7e21adef4b5d1ba3002fc94c9vboxsync {
01df41f7a4e5f7de195a059541d1c89676da9673vboxsync Log(("malloc failed!"));
01df41f7a4e5f7de195a059541d1c89676da9673vboxsync vboxRrRetryStopLocked();
01df41f7a4e5f7de195a059541d1c89676da9673vboxsync LeaveCriticalSection(&pMon->CritSect);
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync return;
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync }
01df41f7a4e5f7de195a059541d1c89676da9673vboxsync memcpy(pMon->paDisplayDevices, paDisplayDevices, sizeof (*paDisplayDevices) * cDevModes);
01df41f7a4e5f7de195a059541d1c89676da9673vboxsync
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync pMon->paDeviceModes = (DEVMODE*)malloc(sizeof (*paDeviceModes) * cDevModes);
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync Assert(pMon->paDeviceModes);
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync if (!pMon->paDeviceModes)
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync {
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync Log(("malloc failed!"));
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync vboxRrRetryStopLocked();
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync LeaveCriticalSection(&pMon->CritSect);
2dd7b4388106de88d20f33a8aa6c85c8babf507bvboxsync return;
2dd7b4388106de88d20f33a8aa6c85c8babf507bvboxsync }
2dd7b4388106de88d20f33a8aa6c85c8babf507bvboxsync memcpy(pMon->paDeviceModes, paDeviceModes, sizeof (*paDeviceModes) * cDevModes);
2dd7b4388106de88d20f33a8aa6c85c8babf507bvboxsync }
2dd7b4388106de88d20f33a8aa6c85c8babf507bvboxsync pMon->cDevModes = cDevModes;
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync
2dd7b4388106de88d20f33a8aa6c85c8babf507bvboxsync pMon->idTimer = SetTimer(pMon->hWnd, VBOXRR_TIMER_ID, 1000, (TIMERPROC)NULL);
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync Assert(pMon->idTimer);
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync if (!pMon->idTimer)
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync {
2dd7b4388106de88d20f33a8aa6c85c8babf507bvboxsync WARN(("VBoxTray: SetTimer failed!, err %d\n", GetLastError()));
2dd7b4388106de88d20f33a8aa6c85c8babf507bvboxsync vboxRrRetryStopLocked();
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync }
2dd7b4388106de88d20f33a8aa6c85c8babf507bvboxsync
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync LeaveCriticalSection(&pMon->CritSect);
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync}
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync
2dd7b4388106de88d20f33a8aa6c85c8babf507bvboxsyncstatic void vboxRrRetryPerform()
2dd7b4388106de88d20f33a8aa6c85c8babf507bvboxsync{
2dd7b4388106de88d20f33a8aa6c85c8babf507bvboxsync PVBOXRR pMon = &g_VBoxRr;
2dd7b4388106de88d20f33a8aa6c85c8babf507bvboxsync EnterCriticalSection(&pMon->CritSect);
2dd7b4388106de88d20f33a8aa6c85c8babf507bvboxsync if (pMon->pIf)
2dd7b4388106de88d20f33a8aa6c85c8babf507bvboxsync {
2dd7b4388106de88d20f33a8aa6c85c8babf507bvboxsync DWORD dwErr = vboxDispIfResizePerform(pMon->pIf, pMon->iChangedMode, pMon->fEnable, pMon->fExtDispSup, pMon->paDisplayDevices, pMon->paDeviceModes, pMon->cDevModes);
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync if (ERROR_RETRY != dwErr)
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync VBoxRrRetryStop();
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync else
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync vboxRrRetryReschedule();
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync }
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync LeaveCriticalSection(&pMon->CritSect);
a8d502445ce722c6b9700c5579b4a38b58827b7dvboxsync}
a8d502445ce722c6b9700c5579b4a38b58827b7dvboxsync
7cfcbe810de5334cdc2e8b92e77db705da143adavboxsyncstatic LRESULT CALLBACK vboxRrWndProc(HWND hwnd,
3a45119099f0df5230e8304145168aa5e2a3f1a1vboxsync UINT uMsg,
3a45119099f0df5230e8304145168aa5e2a3f1a1vboxsync WPARAM wParam,
3a45119099f0df5230e8304145168aa5e2a3f1a1vboxsync LPARAM lParam
3a45119099f0df5230e8304145168aa5e2a3f1a1vboxsync)
3a45119099f0df5230e8304145168aa5e2a3f1a1vboxsync{
3a45119099f0df5230e8304145168aa5e2a3f1a1vboxsync switch(uMsg)
3a45119099f0df5230e8304145168aa5e2a3f1a1vboxsync {
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync case WM_DISPLAYCHANGE:
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync {
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync Log(("VBoxTray: WM_DISPLAYCHANGE\n"));
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync VBoxRrRetryStop();
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync return 0;
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync }
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync case WM_TIMER:
a8d502445ce722c6b9700c5579b4a38b58827b7dvboxsync {
a8d502445ce722c6b9700c5579b4a38b58827b7dvboxsync if (wParam == VBOXRR_TIMER_ID)
a8d502445ce722c6b9700c5579b4a38b58827b7dvboxsync {
a8d502445ce722c6b9700c5579b4a38b58827b7dvboxsync Log(("VBoxTray: VBOXRR_TIMER_ID\n"));
a8d502445ce722c6b9700c5579b4a38b58827b7dvboxsync vboxRrRetryPerform();
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync return 0;
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync }
9b7b32cdd4b2fcbf2796d9a09038670628c55592vboxsync break;
9b7b32cdd4b2fcbf2796d9a09038670628c55592vboxsync }
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync case WM_CLOSE:
a8d502445ce722c6b9700c5579b4a38b58827b7dvboxsync Log((__FUNCTION__": got WM_CLOSE for hwnd(0x%x)", hwnd));
a8d502445ce722c6b9700c5579b4a38b58827b7dvboxsync return 0;
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync case WM_DESTROY:
9b7b32cdd4b2fcbf2796d9a09038670628c55592vboxsync Log((__FUNCTION__": got WM_DESTROY for hwnd(0x%x)", hwnd));
a8d502445ce722c6b9700c5579b4a38b58827b7dvboxsync return 0;
a8d502445ce722c6b9700c5579b4a38b58827b7dvboxsync case WM_NCHITTEST:
3a45119099f0df5230e8304145168aa5e2a3f1a1vboxsync Log((__FUNCTION__": got WM_NCHITTEST for hwnd(0x%x)\n", hwnd));
3a45119099f0df5230e8304145168aa5e2a3f1a1vboxsync return HTNOWHERE;
3a45119099f0df5230e8304145168aa5e2a3f1a1vboxsync default:
3a45119099f0df5230e8304145168aa5e2a3f1a1vboxsync break;
3a45119099f0df5230e8304145168aa5e2a3f1a1vboxsync }
3a45119099f0df5230e8304145168aa5e2a3f1a1vboxsync
3a45119099f0df5230e8304145168aa5e2a3f1a1vboxsync return DefWindowProc(hwnd, uMsg, wParam, lParam);
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync}
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync#define VBOXRRWND_NAME "VBoxRrWnd"
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsyncstatic HRESULT vboxRrWndCreate(HWND *phWnd)
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync{
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync HRESULT hr = S_OK;
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync HINSTANCE hInstance = (HINSTANCE)GetModuleHandle(NULL);
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync /* Register the Window Class. */
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync WNDCLASS wc;
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync if (!GetClassInfo(hInstance, VBOXRRWND_NAME, &wc))
8d1da51eb6665874aa82bf03668e03d1a0d63223vboxsync {
8d1da51eb6665874aa82bf03668e03d1a0d63223vboxsync wc.style = 0;//CS_OWNDC;
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync wc.lpfnWndProc = vboxRrWndProc;
8d1da51eb6665874aa82bf03668e03d1a0d63223vboxsync wc.cbClsExtra = 0;
8cb6f31c3048428b42c7370dfbb20e4de7254f40vboxsync wc.cbWndExtra = 0;
8d1da51eb6665874aa82bf03668e03d1a0d63223vboxsync wc.hInstance = hInstance;
a8d502445ce722c6b9700c5579b4a38b58827b7dvboxsync wc.hIcon = NULL;
a8d502445ce722c6b9700c5579b4a38b58827b7dvboxsync wc.hCursor = NULL;
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync wc.hbrBackground = NULL;
a8d502445ce722c6b9700c5579b4a38b58827b7dvboxsync wc.lpszMenuName = NULL;
a8d502445ce722c6b9700c5579b4a38b58827b7dvboxsync wc.lpszClassName = VBOXRRWND_NAME;
a8d502445ce722c6b9700c5579b4a38b58827b7dvboxsync if (!RegisterClass(&wc))
a8d502445ce722c6b9700c5579b4a38b58827b7dvboxsync {
a8d502445ce722c6b9700c5579b4a38b58827b7dvboxsync DWORD winErr = GetLastError();
a8d502445ce722c6b9700c5579b4a38b58827b7dvboxsync WARN((__FUNCTION__": RegisterClass failed, winErr(%d)\n", winErr));
a8d502445ce722c6b9700c5579b4a38b58827b7dvboxsync hr = E_FAIL;
a8d502445ce722c6b9700c5579b4a38b58827b7dvboxsync }
a8d502445ce722c6b9700c5579b4a38b58827b7dvboxsync }
a8d502445ce722c6b9700c5579b4a38b58827b7dvboxsync
a8d502445ce722c6b9700c5579b4a38b58827b7dvboxsync if (hr == S_OK)
a8d502445ce722c6b9700c5579b4a38b58827b7dvboxsync {
a8d502445ce722c6b9700c5579b4a38b58827b7dvboxsync HWND hWnd = CreateWindowEx (WS_EX_TOOLWINDOW,
a8d502445ce722c6b9700c5579b4a38b58827b7dvboxsync VBOXRRWND_NAME, VBOXRRWND_NAME,
a8d502445ce722c6b9700c5579b4a38b58827b7dvboxsync WS_POPUP | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_DISABLED,
a8d502445ce722c6b9700c5579b4a38b58827b7dvboxsync -100, -100,
a8d502445ce722c6b9700c5579b4a38b58827b7dvboxsync 10, 10,
a8d502445ce722c6b9700c5579b4a38b58827b7dvboxsync NULL, //GetDesktopWindow() /* hWndParent */,
a8d502445ce722c6b9700c5579b4a38b58827b7dvboxsync NULL /* hMenu */,
a8d502445ce722c6b9700c5579b4a38b58827b7dvboxsync hInstance,
a8d502445ce722c6b9700c5579b4a38b58827b7dvboxsync NULL /* lpParam */);
a8d502445ce722c6b9700c5579b4a38b58827b7dvboxsync Assert(hWnd);
a8d502445ce722c6b9700c5579b4a38b58827b7dvboxsync if (hWnd)
a8d502445ce722c6b9700c5579b4a38b58827b7dvboxsync {
a8d502445ce722c6b9700c5579b4a38b58827b7dvboxsync *phWnd = hWnd;
a8d502445ce722c6b9700c5579b4a38b58827b7dvboxsync }
a8d502445ce722c6b9700c5579b4a38b58827b7dvboxsync else
a8d502445ce722c6b9700c5579b4a38b58827b7dvboxsync {
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync DWORD winErr = GetLastError();
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync WARN((__FUNCTION__": CreateWindowEx failed, winErr(%d)\n", winErr));
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync hr = E_FAIL;
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync }
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync }
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync return hr;
a8d502445ce722c6b9700c5579b4a38b58827b7dvboxsync}
cb445170c831c6c56d2d82261e9193b66ceb98a7vboxsync
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsyncstatic HRESULT vboxRrWndDestroy(HWND hWnd)
cb445170c831c6c56d2d82261e9193b66ceb98a7vboxsync{
cb445170c831c6c56d2d82261e9193b66ceb98a7vboxsync BOOL bResult = DestroyWindow(hWnd);
cb445170c831c6c56d2d82261e9193b66ceb98a7vboxsync if (bResult)
cb445170c831c6c56d2d82261e9193b66ceb98a7vboxsync return S_OK;
cb445170c831c6c56d2d82261e9193b66ceb98a7vboxsync
cb445170c831c6c56d2d82261e9193b66ceb98a7vboxsync DWORD winErr = GetLastError();
cb445170c831c6c56d2d82261e9193b66ceb98a7vboxsync WARN((__FUNCTION__": DestroyWindow failed, winErr(%d) for hWnd(0x%x)\n", winErr, hWnd));
cb445170c831c6c56d2d82261e9193b66ceb98a7vboxsync
cb445170c831c6c56d2d82261e9193b66ceb98a7vboxsync return HRESULT_FROM_WIN32(winErr);
cb445170c831c6c56d2d82261e9193b66ceb98a7vboxsync}
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync
cb445170c831c6c56d2d82261e9193b66ceb98a7vboxsyncstatic HRESULT vboxRrWndInit()
cb445170c831c6c56d2d82261e9193b66ceb98a7vboxsync{
cb445170c831c6c56d2d82261e9193b66ceb98a7vboxsync PVBOXRR pMon = &g_VBoxRr;
cb445170c831c6c56d2d82261e9193b66ceb98a7vboxsync return vboxRrWndCreate(&pMon->hWnd);
cb445170c831c6c56d2d82261e9193b66ceb98a7vboxsync}
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync
cb445170c831c6c56d2d82261e9193b66ceb98a7vboxsyncHRESULT vboxRrWndTerm()
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync{
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync PVBOXRR pMon = &g_VBoxRr;
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync HRESULT tmpHr = vboxRrWndDestroy(pMon->hWnd);
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync Assert(tmpHr == S_OK);
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync HINSTANCE hInstance = (HINSTANCE)GetModuleHandle(NULL);
8d1da51eb6665874aa82bf03668e03d1a0d63223vboxsync UnregisterClass(VBOXRRWND_NAME, hInstance);
8d1da51eb6665874aa82bf03668e03d1a0d63223vboxsync
8d1da51eb6665874aa82bf03668e03d1a0d63223vboxsync return S_OK;
8d1da51eb6665874aa82bf03668e03d1a0d63223vboxsync}
8d1da51eb6665874aa82bf03668e03d1a0d63223vboxsync
8d1da51eb6665874aa82bf03668e03d1a0d63223vboxsync#define WM_VBOXRR_INIT_QUIT (WM_APP+2)
8d1da51eb6665874aa82bf03668e03d1a0d63223vboxsync
8d1da51eb6665874aa82bf03668e03d1a0d63223vboxsyncHRESULT vboxRrRun()
8d1da51eb6665874aa82bf03668e03d1a0d63223vboxsync{
8d1da51eb6665874aa82bf03668e03d1a0d63223vboxsync PVBOXRR pMon = &g_VBoxRr;
8d1da51eb6665874aa82bf03668e03d1a0d63223vboxsync MSG Msg;
8d1da51eb6665874aa82bf03668e03d1a0d63223vboxsync
8d1da51eb6665874aa82bf03668e03d1a0d63223vboxsync HRESULT hr = S_FALSE;
cb445170c831c6c56d2d82261e9193b66ceb98a7vboxsync
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync PeekMessage(&Msg,
8d1da51eb6665874aa82bf03668e03d1a0d63223vboxsync NULL /* HWND hWnd */,
8d1da51eb6665874aa82bf03668e03d1a0d63223vboxsync WM_USER /* UINT wMsgFilterMin */,
8d1da51eb6665874aa82bf03668e03d1a0d63223vboxsync WM_USER /* UINT wMsgFilterMax */,
8d1da51eb6665874aa82bf03668e03d1a0d63223vboxsync PM_NOREMOVE);
8d1da51eb6665874aa82bf03668e03d1a0d63223vboxsync
8d1da51eb6665874aa82bf03668e03d1a0d63223vboxsync do
8d1da51eb6665874aa82bf03668e03d1a0d63223vboxsync {
8d1da51eb6665874aa82bf03668e03d1a0d63223vboxsync BOOL bResult = GetMessage(&Msg,
8d1da51eb6665874aa82bf03668e03d1a0d63223vboxsync 0 /*HWND hWnd*/,
8d1da51eb6665874aa82bf03668e03d1a0d63223vboxsync 0 /*UINT wMsgFilterMin*/,
8d1da51eb6665874aa82bf03668e03d1a0d63223vboxsync 0 /*UINT wMsgFilterMax*/
8d1da51eb6665874aa82bf03668e03d1a0d63223vboxsync );
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync if(!bResult) /* WM_QUIT was posted */
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync {
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync hr = S_FALSE;
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync Log(("VBoxTray: GetMessage returned FALSE\n"));
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync VBoxRrRetryStop();
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync break;
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync }
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync if(bResult == -1) /* error occurred */
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync {
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync DWORD winEr = GetLastError();
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync hr = HRESULT_FROM_WIN32(winEr);
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync /* just ensure we never return success in this case */
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync Assert(hr != S_OK);
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync Assert(hr != S_FALSE);
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync if (hr == S_OK || hr == S_FALSE)
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync hr = E_FAIL;
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync WARN(("VBoxTray: GetMessage returned -1, err %d\n", winEr));
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync VBoxRrRetryStop();
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync break;
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync }
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync switch (Msg.message)
3a45119099f0df5230e8304145168aa5e2a3f1a1vboxsync {
3a45119099f0df5230e8304145168aa5e2a3f1a1vboxsync case WM_VBOXRR_INIT_QUIT:
3a45119099f0df5230e8304145168aa5e2a3f1a1vboxsync case WM_CLOSE:
3a45119099f0df5230e8304145168aa5e2a3f1a1vboxsync {
3a45119099f0df5230e8304145168aa5e2a3f1a1vboxsync Log(("VBoxTray: closing Rr %d\n", Msg.message));
3a45119099f0df5230e8304145168aa5e2a3f1a1vboxsync VBoxRrRetryStop();
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync PostQuitMessage(0);
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync break;
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync }
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync default:
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync TranslateMessage(&Msg);
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync DispatchMessage(&Msg);
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync break;
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync }
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync } while (1);
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync return 0;
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync}
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsyncstatic DWORD WINAPI vboxRrRunnerThread(void *pvUser)
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync{
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync PVBOXRR pMon = &g_VBoxRr;
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync BOOL bRc = SetEvent(pMon->hEvent);
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync if (!bRc)
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync {
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync DWORD winErr = GetLastError();
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync WARN((__FUNCTION__": SetEvent failed, winErr = (%d)", winErr));
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync HRESULT tmpHr = HRESULT_FROM_WIN32(winErr);
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync Assert(tmpHr != S_OK);
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync }
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync HRESULT hr = vboxRrWndInit();
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync Assert(hr == S_OK);
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync if (hr == S_OK)
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync {
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync hr = vboxRrRun();
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync Assert(hr == S_OK);
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync vboxRrWndTerm();
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync }
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync return 0;
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync}
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync
129986ce8b48d5e5973ad84edae4465788db89aavboxsyncHRESULT VBoxRrInit()
129986ce8b48d5e5973ad84edae4465788db89aavboxsync{
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync HRESULT hr = E_FAIL;
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync PVBOXRR pMon = &g_VBoxRr;
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync memset(pMon, 0, sizeof (*pMon));
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync InitializeCriticalSection(&pMon->CritSect);
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync pMon->hEvent = CreateEvent(NULL, /* LPSECURITY_ATTRIBUTES lpEventAttributes*/
7cfcbe810de5334cdc2e8b92e77db705da143adavboxsync TRUE, /* BOOL bManualReset*/
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync FALSE, /* BOOL bInitialState */
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync NULL /* LPCTSTR lpName */
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync );
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync if (pMon->hEvent)
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync {
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync pMon->hThread = CreateThread(NULL /* LPSECURITY_ATTRIBUTES lpThreadAttributes */,
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync 0 /* SIZE_T dwStackSize */,
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync vboxRrRunnerThread,
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync pMon,
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync 0 /* DWORD dwCreationFlags */,
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync &pMon->idThread);
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync if (pMon->hThread)
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync {
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync DWORD dwResult = WaitForSingleObject(pMon->hEvent, INFINITE);
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync if (dwResult == WAIT_OBJECT_0)
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync return S_OK;
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync else
a8d502445ce722c6b9700c5579b4a38b58827b7dvboxsync {
7cfcbe810de5334cdc2e8b92e77db705da143adavboxsync Log(("WaitForSingleObject failed!"));
a8d502445ce722c6b9700c5579b4a38b58827b7dvboxsync hr = E_FAIL;
a8d502445ce722c6b9700c5579b4a38b58827b7dvboxsync }
a8d502445ce722c6b9700c5579b4a38b58827b7dvboxsync }
a8d502445ce722c6b9700c5579b4a38b58827b7dvboxsync else
a8d502445ce722c6b9700c5579b4a38b58827b7dvboxsync {
a8d502445ce722c6b9700c5579b4a38b58827b7dvboxsync DWORD winErr = GetLastError();
7cfcbe810de5334cdc2e8b92e77db705da143adavboxsync WARN((__FUNCTION__": CreateThread failed, winErr = (%d)", winErr));
a8d502445ce722c6b9700c5579b4a38b58827b7dvboxsync hr = HRESULT_FROM_WIN32(winErr);
a8d502445ce722c6b9700c5579b4a38b58827b7dvboxsync Assert(hr != S_OK);
7cfcbe810de5334cdc2e8b92e77db705da143adavboxsync }
a8d502445ce722c6b9700c5579b4a38b58827b7dvboxsync CloseHandle(pMon->hEvent);
a8d502445ce722c6b9700c5579b4a38b58827b7dvboxsync }
a8d502445ce722c6b9700c5579b4a38b58827b7dvboxsync else
ece707b8d97e63ed54d4b48d7a8d841187e0023cvboxsync {
a8d502445ce722c6b9700c5579b4a38b58827b7dvboxsync DWORD winErr = GetLastError();
ece707b8d97e63ed54d4b48d7a8d841187e0023cvboxsync WARN((__FUNCTION__": CreateEvent failed, winErr = (%d)", winErr));
a8d502445ce722c6b9700c5579b4a38b58827b7dvboxsync hr = HRESULT_FROM_WIN32(winErr);
a8d502445ce722c6b9700c5579b4a38b58827b7dvboxsync Assert(hr != S_OK);
a8d502445ce722c6b9700c5579b4a38b58827b7dvboxsync }
a8d502445ce722c6b9700c5579b4a38b58827b7dvboxsync
a8d502445ce722c6b9700c5579b4a38b58827b7dvboxsync DeleteCriticalSection(&pMon->CritSect);
a8d502445ce722c6b9700c5579b4a38b58827b7dvboxsync
a8d502445ce722c6b9700c5579b4a38b58827b7dvboxsync return hr;
a8d502445ce722c6b9700c5579b4a38b58827b7dvboxsync}
a8d502445ce722c6b9700c5579b4a38b58827b7dvboxsync
a8d502445ce722c6b9700c5579b4a38b58827b7dvboxsyncVOID VBoxRrTerm()
a8d502445ce722c6b9700c5579b4a38b58827b7dvboxsync{
a8d502445ce722c6b9700c5579b4a38b58827b7dvboxsync HRESULT hr;
a8d502445ce722c6b9700c5579b4a38b58827b7dvboxsync PVBOXRR pMon = &g_VBoxRr;
a8d502445ce722c6b9700c5579b4a38b58827b7dvboxsync if (!pMon->hThread)
a8d502445ce722c6b9700c5579b4a38b58827b7dvboxsync return;
a8d502445ce722c6b9700c5579b4a38b58827b7dvboxsync
a8d502445ce722c6b9700c5579b4a38b58827b7dvboxsync BOOL bResult = PostThreadMessage(pMon->idThread, WM_VBOXRR_INIT_QUIT, 0, 0);
a8d502445ce722c6b9700c5579b4a38b58827b7dvboxsync DWORD winErr;
a8d502445ce722c6b9700c5579b4a38b58827b7dvboxsync if (bResult
a8d502445ce722c6b9700c5579b4a38b58827b7dvboxsync || (winErr = GetLastError()) == ERROR_INVALID_THREAD_ID) /* <- could be that the thread is terminated */
a8d502445ce722c6b9700c5579b4a38b58827b7dvboxsync {
a8d502445ce722c6b9700c5579b4a38b58827b7dvboxsync DWORD dwErr = WaitForSingleObject(pMon->hThread, INFINITE);
a8d502445ce722c6b9700c5579b4a38b58827b7dvboxsync if (dwErr == WAIT_OBJECT_0)
a8d502445ce722c6b9700c5579b4a38b58827b7dvboxsync {
a8d502445ce722c6b9700c5579b4a38b58827b7dvboxsync hr = S_OK;
a8d502445ce722c6b9700c5579b4a38b58827b7dvboxsync }
a8d502445ce722c6b9700c5579b4a38b58827b7dvboxsync else
a8d502445ce722c6b9700c5579b4a38b58827b7dvboxsync {
a8d502445ce722c6b9700c5579b4a38b58827b7dvboxsync winErr = GetLastError();
7cfcbe810de5334cdc2e8b92e77db705da143adavboxsync hr = HRESULT_FROM_WIN32(winErr);
7cfcbe810de5334cdc2e8b92e77db705da143adavboxsync }
7cfcbe810de5334cdc2e8b92e77db705da143adavboxsync }
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync else
a8d502445ce722c6b9700c5579b4a38b58827b7dvboxsync {
a8d502445ce722c6b9700c5579b4a38b58827b7dvboxsync hr = HRESULT_FROM_WIN32(winErr);
a8d502445ce722c6b9700c5579b4a38b58827b7dvboxsync }
a8d502445ce722c6b9700c5579b4a38b58827b7dvboxsync
a8d502445ce722c6b9700c5579b4a38b58827b7dvboxsync DeleteCriticalSection(&pMon->CritSect);
a8d502445ce722c6b9700c5579b4a38b58827b7dvboxsync
a8d502445ce722c6b9700c5579b4a38b58827b7dvboxsync CloseHandle(pMon->hThread);
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync pMon->hThread = 0;
a8d502445ce722c6b9700c5579b4a38b58827b7dvboxsync CloseHandle(pMon->hEvent);
a8d502445ce722c6b9700c5579b4a38b58827b7dvboxsync pMon->hThread = 0;
a8d502445ce722c6b9700c5579b4a38b58827b7dvboxsync}
a8d502445ce722c6b9700c5579b4a38b58827b7dvboxsync
a8d502445ce722c6b9700c5579b4a38b58827b7dvboxsyncstatic DWORD vboxDispIfWddmInit(PCVBOXDISPIF pIf)
ece707b8d97e63ed54d4b48d7a8d841187e0023cvboxsync{
a8d502445ce722c6b9700c5579b4a38b58827b7dvboxsync HRESULT hr = VBoxRrInit();
a8d502445ce722c6b9700c5579b4a38b58827b7dvboxsync if (SUCCEEDED(hr))
ece707b8d97e63ed54d4b48d7a8d841187e0023cvboxsync {
a8d502445ce722c6b9700c5579b4a38b58827b7dvboxsync return ERROR_SUCCESS;
a8d502445ce722c6b9700c5579b4a38b58827b7dvboxsync }
a8d502445ce722c6b9700c5579b4a38b58827b7dvboxsync WARN(("VBoxTray: VBoxRrInit failed hr 0x%x\n", hr));
a8d502445ce722c6b9700c5579b4a38b58827b7dvboxsync return hr;
a8d502445ce722c6b9700c5579b4a38b58827b7dvboxsync}
a8d502445ce722c6b9700c5579b4a38b58827b7dvboxsync
a8d502445ce722c6b9700c5579b4a38b58827b7dvboxsyncstatic void vboxDispIfWddmTerm(PCVBOXDISPIF pIf)
a8d502445ce722c6b9700c5579b4a38b58827b7dvboxsync{
a8d502445ce722c6b9700c5579b4a38b58827b7dvboxsync VBoxRrTerm();
a8d502445ce722c6b9700c5579b4a38b58827b7dvboxsync}
a8d502445ce722c6b9700c5579b4a38b58827b7dvboxsync
a8d502445ce722c6b9700c5579b4a38b58827b7dvboxsyncstatic DWORD vboxDispIfQueryDisplayConnection(VBOXDISPIF_OP *pOp, UINT32 iDisplay, BOOL *pfConnected)
a8d502445ce722c6b9700c5579b4a38b58827b7dvboxsync{
a8d502445ce722c6b9700c5579b4a38b58827b7dvboxsync if (pOp->pIf->enmMode == VBOXDISPIF_MODE_WDDM)
a8d502445ce722c6b9700c5579b4a38b58827b7dvboxsync {
a8d502445ce722c6b9700c5579b4a38b58827b7dvboxsync /* @todo: do we need ti impl it? */
a8d502445ce722c6b9700c5579b4a38b58827b7dvboxsync *pfConnected = TRUE;
a8d502445ce722c6b9700c5579b4a38b58827b7dvboxsync return ERROR_SUCCESS;
a8d502445ce722c6b9700c5579b4a38b58827b7dvboxsync }
a8d502445ce722c6b9700c5579b4a38b58827b7dvboxsync
a8d502445ce722c6b9700c5579b4a38b58827b7dvboxsync *pfConnected = FALSE;
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync VBOXDISPIF_WDDM_DISPCFG DispCfg;
ece707b8d97e63ed54d4b48d7a8d841187e0023cvboxsync DWORD winEr = vboxDispIfWddmDcCreate(&DispCfg, QDC_ALL_PATHS);
ece707b8d97e63ed54d4b48d7a8d841187e0023cvboxsync if (winEr != ERROR_SUCCESS)
a8d502445ce722c6b9700c5579b4a38b58827b7dvboxsync {
ece707b8d97e63ed54d4b48d7a8d841187e0023cvboxsync WARN(("VBoxTray: (WDDM) Failed vboxDispIfWddmDcCreate winEr %d\n", winEr));
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync return winEr;
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync }
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync int idx = vboxDispIfWddmDcSearchPath(&DispCfg, iDisplay, iDisplay);
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync *pfConnected = (idx >= 0);
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync vboxDispIfWddmDcTerm(&DispCfg);
01df41f7a4e5f7de195a059541d1c89676da9673vboxsync
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync return ERROR_SUCCESS;
3a45119099f0df5230e8304145168aa5e2a3f1a1vboxsync}
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync
3a45119099f0df5230e8304145168aa5e2a3f1a1vboxsyncstatic DWORD vboxDispIfWaitDisplayDataInited(VBOXDISPIF_OP *pOp)
3a45119099f0df5230e8304145168aa5e2a3f1a1vboxsync{
3a45119099f0df5230e8304145168aa5e2a3f1a1vboxsync DWORD winEr = ERROR_SUCCESS;
3a45119099f0df5230e8304145168aa5e2a3f1a1vboxsync do
3a45119099f0df5230e8304145168aa5e2a3f1a1vboxsync {
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync Sleep(100);
3a45119099f0df5230e8304145168aa5e2a3f1a1vboxsync
3a45119099f0df5230e8304145168aa5e2a3f1a1vboxsync D3DKMT_POLLDISPLAYCHILDREN PollData = {0};
3a45119099f0df5230e8304145168aa5e2a3f1a1vboxsync PollData.hAdapter = pOp->Adapter.hAdapter;
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync PollData.NonDestructiveOnly = 1;
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync NTSTATUS Status = pOp->pIf->modeData.wddm.KmtCallbacks.pfnD3DKMTPollDisplayChildren(&PollData);
01df41f7a4e5f7de195a059541d1c89676da9673vboxsync if (Status != 0)
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync {
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync Log(("VBoxTray: (WDDM) pfnD3DKMTPollDisplayChildren failed, Status (0x%x)\n", Status));
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync continue;
fabb3e1e51b589494ebe849b7c000e8bcc9ff473vboxsync }
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync BOOL fFound = FALSE;
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync#if 0
fabb3e1e51b589494ebe849b7c000e8bcc9ff473vboxsync for (UINT i = 0; i < VBOXWDDM_SCREENMASK_SIZE; ++i)
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync {
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync if (pu8DisplayMask && !ASMBitTest(pu8DisplayMask, i))
fabb3e1e51b589494ebe849b7c000e8bcc9ff473vboxsync continue;
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync BOOL fConnected = FALSE;
fabb3e1e51b589494ebe849b7c000e8bcc9ff473vboxsync winEr = vboxDispIfQueryDisplayConnection(pOp, i, &fConnected);
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync if (winEr != ERROR_SUCCESS)
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync {
3a45119099f0df5230e8304145168aa5e2a3f1a1vboxsync WARN(("VBoxTray: (WDDM) Failed vboxDispIfQueryDisplayConnection winEr %d\n", winEr));
8d1da51eb6665874aa82bf03668e03d1a0d63223vboxsync return winEr;
8d1da51eb6665874aa82bf03668e03d1a0d63223vboxsync }
3a45119099f0df5230e8304145168aa5e2a3f1a1vboxsync
8d1da51eb6665874aa82bf03668e03d1a0d63223vboxsync if (!fConnected)
8d1da51eb6665874aa82bf03668e03d1a0d63223vboxsync {
8d1da51eb6665874aa82bf03668e03d1a0d63223vboxsync WARN(("VBoxTray: (WDDM) Display %d not connected, not expected\n", i));
8d1da51eb6665874aa82bf03668e03d1a0d63223vboxsync fFound = TRUE;
8d1da51eb6665874aa82bf03668e03d1a0d63223vboxsync break;
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync }
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync }
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync#endif
8d1da51eb6665874aa82bf03668e03d1a0d63223vboxsync if (!fFound)
8d1da51eb6665874aa82bf03668e03d1a0d63223vboxsync break;
8d1da51eb6665874aa82bf03668e03d1a0d63223vboxsync } while (1);
8d1da51eb6665874aa82bf03668e03d1a0d63223vboxsync
8d1da51eb6665874aa82bf03668e03d1a0d63223vboxsync return winEr;
8d1da51eb6665874aa82bf03668e03d1a0d63223vboxsync}
8d1da51eb6665874aa82bf03668e03d1a0d63223vboxsync
8d1da51eb6665874aa82bf03668e03d1a0d63223vboxsyncstatic DWORD vboxDispIfUpdateModesWDDM(VBOXDISPIF_OP *pOp, uint32_t u32TargetId, const RTRECTSIZE *pSize)
8d1da51eb6665874aa82bf03668e03d1a0d63223vboxsync{
8d1da51eb6665874aa82bf03668e03d1a0d63223vboxsync DWORD winEr = ERROR_SUCCESS;
8d1da51eb6665874aa82bf03668e03d1a0d63223vboxsync VBOXDISPIFESCAPE_UPDATEMODES EscData = {0};
8d1da51eb6665874aa82bf03668e03d1a0d63223vboxsync EscData.EscapeHdr.escapeCode = VBOXESC_UPDATEMODES;
8d1da51eb6665874aa82bf03668e03d1a0d63223vboxsync EscData.u32TargetId = u32TargetId;
8d1da51eb6665874aa82bf03668e03d1a0d63223vboxsync EscData.Size = *pSize;
8d1da51eb6665874aa82bf03668e03d1a0d63223vboxsync
8d1da51eb6665874aa82bf03668e03d1a0d63223vboxsync D3DKMT_ESCAPE EscapeData = {0};
8d1da51eb6665874aa82bf03668e03d1a0d63223vboxsync EscapeData.hAdapter = pOp->Adapter.hAdapter;
8d1da51eb6665874aa82bf03668e03d1a0d63223vboxsync#ifdef VBOX_DISPIF_WITH_OPCONTEXT
8d1da51eb6665874aa82bf03668e03d1a0d63223vboxsync /* win8.1 does not allow context-based escapes for display-only mode */
8d1da51eb6665874aa82bf03668e03d1a0d63223vboxsync EscapeData.hDevice = pOp->Device.hDevice;
8d1da51eb6665874aa82bf03668e03d1a0d63223vboxsync EscapeData.hContext = pOp->Context.hContext;
8d1da51eb6665874aa82bf03668e03d1a0d63223vboxsync#endif
8d1da51eb6665874aa82bf03668e03d1a0d63223vboxsync EscapeData.Type = D3DKMT_ESCAPE_DRIVERPRIVATE;
8d1da51eb6665874aa82bf03668e03d1a0d63223vboxsync EscapeData.Flags.HardwareAccess = 1;
01df41f7a4e5f7de195a059541d1c89676da9673vboxsync EscapeData.pPrivateDriverData = &EscData;
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync EscapeData.PrivateDriverDataSize = sizeof (EscData);
8f0f3548de344cfe3e49ffd3e4c338792e1729cevboxsync
8d1da51eb6665874aa82bf03668e03d1a0d63223vboxsync NTSTATUS Status = pOp->pIf->modeData.wddm.KmtCallbacks.pfnD3DKMTEscape(&EscapeData);
8f0f3548de344cfe3e49ffd3e4c338792e1729cevboxsync if (NT_SUCCESS(Status))
8f0f3548de344cfe3e49ffd3e4c338792e1729cevboxsync winEr = ERROR_SUCCESS;
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync else
01df41f7a4e5f7de195a059541d1c89676da9673vboxsync {
01df41f7a4e5f7de195a059541d1c89676da9673vboxsync WARN(("VBoxTray: pfnD3DKMTEscape VBOXESC_UPDATEMODES failed Status 0x%x\n", Status));
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync winEr = ERROR_GEN_FAILURE;
01df41f7a4e5f7de195a059541d1c89676da9673vboxsync }
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync winEr = vboxDispIfWaitDisplayDataInited(pOp);
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync if (winEr != NO_ERROR)
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync WARN(("VBoxTray: (WDDM) Failed vboxDispIfWaitDisplayDataInited winEr %d\n", winEr));
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync return winEr;
8d1da51eb6665874aa82bf03668e03d1a0d63223vboxsync}
a8d502445ce722c6b9700c5579b4a38b58827b7dvboxsync
a8d502445ce722c6b9700c5579b4a38b58827b7dvboxsyncDWORD vboxDispIfCancelPendingResizeWDDM(PCVBOXDISPIF const pIf)
8d1da51eb6665874aa82bf03668e03d1a0d63223vboxsync{
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync Log(("VBoxTray: cancelling pending resize\n"));
01df41f7a4e5f7de195a059541d1c89676da9673vboxsync VBoxRrRetryStop();
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync return NO_ERROR;
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync}
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync
8cfe2efff2058bd07777056112155ea5353dcfbavboxsyncstatic DWORD vboxDispIfWddmResizeDisplayVista(DEVMODE *paDeviceModes, DISPLAY_DEVICE *paDisplayDevices, DWORD cDevModes, UINT iChangedMode, BOOL fEnable, BOOL fExtDispSup)
3ea1dbf096240fc221aea99352a74c17a367a9b6vboxsync{
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync /* Without this, Windows will not ask the miniport for its
fabb3e1e51b589494ebe849b7c000e8bcc9ff473vboxsync * mode table but uses an internal cache instead.
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync */
01df41f7a4e5f7de195a059541d1c89676da9673vboxsync for (DWORD i = 0; i < cDevModes; i++)
8cb6f31c3048428b42c7370dfbb20e4de7254f40vboxsync {
8cb6f31c3048428b42c7370dfbb20e4de7254f40vboxsync DEVMODE tempDevMode;
8cb6f31c3048428b42c7370dfbb20e4de7254f40vboxsync ZeroMemory (&tempDevMode, sizeof (tempDevMode));
8cb6f31c3048428b42c7370dfbb20e4de7254f40vboxsync tempDevMode.dmSize = sizeof(DEVMODE);
8cb6f31c3048428b42c7370dfbb20e4de7254f40vboxsync EnumDisplaySettings((LPSTR)paDisplayDevices[i].DeviceName, 0xffffff, &tempDevMode);
8cb6f31c3048428b42c7370dfbb20e4de7254f40vboxsync Log(("VBoxTray: ResizeDisplayDevice: EnumDisplaySettings last error %d\n", GetLastError ()));
01df41f7a4e5f7de195a059541d1c89676da9673vboxsync }
01df41f7a4e5f7de195a059541d1c89676da9673vboxsync
01df41f7a4e5f7de195a059541d1c89676da9673vboxsync DWORD winEr = EnableAndResizeDispDev(paDeviceModes, paDisplayDevices, cDevModes, iChangedMode, paDeviceModes[iChangedMode].dmPelsWidth, paDeviceModes[iChangedMode].dmPelsHeight,
8d1da51eb6665874aa82bf03668e03d1a0d63223vboxsync paDeviceModes[iChangedMode].dmBitsPerPel, paDeviceModes[iChangedMode].dmPosition.x, paDeviceModes[iChangedMode].dmPosition.y, fEnable, fExtDispSup);
8d1da51eb6665874aa82bf03668e03d1a0d63223vboxsync if (winEr != NO_ERROR)
8d1da51eb6665874aa82bf03668e03d1a0d63223vboxsync WARN(("VBoxTray: (WDDM) Failed EnableAndResizeDispDev winEr %d\n", winEr));
8d1da51eb6665874aa82bf03668e03d1a0d63223vboxsync
8d1da51eb6665874aa82bf03668e03d1a0d63223vboxsync return winEr;
8d1da51eb6665874aa82bf03668e03d1a0d63223vboxsync}
8d1da51eb6665874aa82bf03668e03d1a0d63223vboxsync
01df41f7a4e5f7de195a059541d1c89676da9673vboxsyncstatic DWORD vboxDispIfResizePerform(PCVBOXDISPIF const pIf, UINT iChangedMode, BOOL fEnable, BOOL fExtDispSup, DISPLAY_DEVICE *paDisplayDevices, DEVMODE *paDeviceModes, UINT cDevModes)
8d1da51eb6665874aa82bf03668e03d1a0d63223vboxsync{
01df41f7a4e5f7de195a059541d1c89676da9673vboxsync DWORD winEr;
8d1da51eb6665874aa82bf03668e03d1a0d63223vboxsync if (pIf->enmMode > VBOXDISPIF_MODE_WDDM)
8d1da51eb6665874aa82bf03668e03d1a0d63223vboxsync {
8d1da51eb6665874aa82bf03668e03d1a0d63223vboxsync winEr = vboxDispIfWddmResizeDisplay(pIf, iChangedMode, fEnable, paDisplayDevices, paDeviceModes, cDevModes);
8d1da51eb6665874aa82bf03668e03d1a0d63223vboxsync if (winEr != NO_ERROR)
8d1da51eb6665874aa82bf03668e03d1a0d63223vboxsync WARN(("VBoxTray: (WDDM) Failed vboxDispIfWddmResizeDisplay winEr %d\n", winEr));
8d1da51eb6665874aa82bf03668e03d1a0d63223vboxsync }
8d1da51eb6665874aa82bf03668e03d1a0d63223vboxsync else
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync {
01df41f7a4e5f7de195a059541d1c89676da9673vboxsync winEr = vboxDispIfWddmResizeDisplayVista(paDeviceModes, paDisplayDevices, cDevModes, iChangedMode, fEnable, fExtDispSup);
01df41f7a4e5f7de195a059541d1c89676da9673vboxsync if (winEr != NO_ERROR)
01df41f7a4e5f7de195a059541d1c89676da9673vboxsync WARN(("VBoxTray: (WDDM) Failed vboxDispIfWddmResizeDisplayVista winEr %d\n", winEr));
a8d502445ce722c6b9700c5579b4a38b58827b7dvboxsync }
a8d502445ce722c6b9700c5579b4a38b58827b7dvboxsync return winEr;
8cb6f31c3048428b42c7370dfbb20e4de7254f40vboxsync}
8cb6f31c3048428b42c7370dfbb20e4de7254f40vboxsync
8cb6f31c3048428b42c7370dfbb20e4de7254f40vboxsyncDWORD vboxDispIfResizeModesWDDM(PCVBOXDISPIF const pIf, UINT iChangedMode, BOOL fEnable, BOOL fExtDispSup, DISPLAY_DEVICE *paDisplayDevices, DEVMODE *paDeviceModes, UINT cDevModes)
8cb6f31c3048428b42c7370dfbb20e4de7254f40vboxsync{
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync DWORD winEr = NO_ERROR;
8cb6f31c3048428b42c7370dfbb20e4de7254f40vboxsync
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync Log(("VBoxTray: vboxDispIfResizeModesWDDM\n"));
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync VBoxRrRetryStop();
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync VBOXDISPIF_OP Op;
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync winEr = vboxDispIfOpBegin(pIf, &Op);
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync if (winEr != NO_ERROR)
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync {
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync WARN(("VBoxTray: vboxDispIfOpBegin failed winEr 0x%x", winEr));
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync return winEr;
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync }
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync VBOXWDDM_RECOMMENDVIDPN VidPnData;
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync memset(&VidPnData, 0, sizeof (VidPnData));
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync
01df41f7a4e5f7de195a059541d1c89676da9673vboxsync uint32_t cElements = 0;
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync
7cfcbe810de5334cdc2e8b92e77db705da143adavboxsync for (uint32_t i = 0; i < cDevModes; ++i)
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync {
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync if ((i == iChangedMode) ? fEnable : (paDisplayDevices[i].StateFlags & DISPLAY_DEVICE_ACTIVE))
8cb6f31c3048428b42c7370dfbb20e4de7254f40vboxsync {
8cb6f31c3048428b42c7370dfbb20e4de7254f40vboxsync VidPnData.aSources[cElements].Size.cx = paDeviceModes[i].dmPelsWidth;
8cb6f31c3048428b42c7370dfbb20e4de7254f40vboxsync VidPnData.aSources[cElements].Size.cy = paDeviceModes[i].dmPelsHeight;
8cb6f31c3048428b42c7370dfbb20e4de7254f40vboxsync VidPnData.aTargets[cElements].iSource = cElements;
8cb6f31c3048428b42c7370dfbb20e4de7254f40vboxsync ++cElements;
8cb6f31c3048428b42c7370dfbb20e4de7254f40vboxsync }
8cb6f31c3048428b42c7370dfbb20e4de7254f40vboxsync else
8cb6f31c3048428b42c7370dfbb20e4de7254f40vboxsync VidPnData.aTargets[cElements].iSource = -1;
8cb6f31c3048428b42c7370dfbb20e4de7254f40vboxsync }
8cb6f31c3048428b42c7370dfbb20e4de7254f40vboxsync
8cb6f31c3048428b42c7370dfbb20e4de7254f40vboxsync D3DKMT_INVALIDATEACTIVEVIDPN DdiData = {0};
8cb6f31c3048428b42c7370dfbb20e4de7254f40vboxsync
8cb6f31c3048428b42c7370dfbb20e4de7254f40vboxsync DdiData.hAdapter = Op.Adapter.hAdapter;
8cb6f31c3048428b42c7370dfbb20e4de7254f40vboxsync DdiData.pPrivateDriverData = &VidPnData;
a8d502445ce722c6b9700c5579b4a38b58827b7dvboxsync DdiData.PrivateDriverDataSize = sizeof (VidPnData);
a8d502445ce722c6b9700c5579b4a38b58827b7dvboxsync
8d1da51eb6665874aa82bf03668e03d1a0d63223vboxsync NTSTATUS Status = Op.pIf->modeData.wddm.KmtCallbacks.pfnD3DKMTInvalidateActiveVidPn(&DdiData);
01df41f7a4e5f7de195a059541d1c89676da9673vboxsync if (NT_SUCCESS(Status))
8d1da51eb6665874aa82bf03668e03d1a0d63223vboxsync winEr = NO_ERROR;
01df41f7a4e5f7de195a059541d1c89676da9673vboxsync else
8cb6f31c3048428b42c7370dfbb20e4de7254f40vboxsync {
8cb6f31c3048428b42c7370dfbb20e4de7254f40vboxsync winEr = NO_ERROR;
8cb6f31c3048428b42c7370dfbb20e4de7254f40vboxsync
8d1da51eb6665874aa82bf03668e03d1a0d63223vboxsync if (fEnable)
8d1da51eb6665874aa82bf03668e03d1a0d63223vboxsync {
8d1da51eb6665874aa82bf03668e03d1a0d63223vboxsync RTRECTSIZE Size;
01df41f7a4e5f7de195a059541d1c89676da9673vboxsync Size.cx = paDeviceModes[iChangedMode].dmPelsWidth;
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync Size.cy = paDeviceModes[iChangedMode].dmPelsHeight;
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync winEr = vboxDispIfUpdateModesWDDM(&Op, iChangedMode, &Size);
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync if (winEr != NO_ERROR)
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync WARN(("vboxDispIfUpdateModesWDDM failed %d\n", winEr));
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync }
8d1da51eb6665874aa82bf03668e03d1a0d63223vboxsync
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync if (winEr == NO_ERROR)
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync {
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync winEr = vboxDispIfResizePerform(pIf, iChangedMode, fEnable, fExtDispSup, paDisplayDevices, paDeviceModes, cDevModes);
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync if (winEr == ERROR_RETRY)
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync {
01df41f7a4e5f7de195a059541d1c89676da9673vboxsync VBoxRrRetrySchedule(pIf, iChangedMode, fEnable, fExtDispSup, paDisplayDevices, paDeviceModes, cDevModes);
01df41f7a4e5f7de195a059541d1c89676da9673vboxsync /* just pretend everything is fine so far */
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync winEr = NO_ERROR;
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync }
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync }
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync }
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync vboxDispIfOpEnd(&Op);
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync return winEr;
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync}
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsyncstatic DWORD vboxDispIfWddmEnableDisplays(PCVBOXDISPIF const pIf, UINT cIds, UINT *pIds, BOOL fEnabled, BOOL fSetTopology, DEVMODE *pDeviceMode)
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync{
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync VBOXDISPIF_WDDM_DISPCFG DispCfg;
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync DWORD winEr;
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync int iPath;
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync winEr = vboxDispIfWddmDcCreate(&DispCfg, QDC_ONLY_ACTIVE_PATHS);
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync if (winEr != ERROR_SUCCESS)
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync {
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync WARN(("VBoxTray: (WDDM) Failed vboxDispIfWddmDcCreate winEr %d\n", winEr));
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync return winEr;
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync }
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync UINT cChangeIds = 0;
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync UINT *pChangeIds = (UINT*)alloca(cIds * sizeof (*pChangeIds));
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync if (!pChangeIds)
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync {
8d1da51eb6665874aa82bf03668e03d1a0d63223vboxsync WARN(("VBoxTray: (WDDM) Failed to alloc change ids\n"));
8d1da51eb6665874aa82bf03668e03d1a0d63223vboxsync winEr = ERROR_OUTOFMEMORY;
01df41f7a4e5f7de195a059541d1c89676da9673vboxsync goto done;
01df41f7a4e5f7de195a059541d1c89676da9673vboxsync }
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync for (UINT i = 0; i < cIds; ++i)
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync {
8cfe2efff2058bd07777056112155ea5353dcfbavboxsync UINT Id = pIds[i];
3ea1dbf096240fc221aea99352a74c17a367a9b6vboxsync bool fIsDup = false;
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync for (UINT j = 0; j < cChangeIds; ++j)
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync {
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync if (pChangeIds[j] == Id)
01df41f7a4e5f7de195a059541d1c89676da9673vboxsync {
8cb6f31c3048428b42c7370dfbb20e4de7254f40vboxsync fIsDup = true;
8cb6f31c3048428b42c7370dfbb20e4de7254f40vboxsync break;
8cb6f31c3048428b42c7370dfbb20e4de7254f40vboxsync }
8cb6f31c3048428b42c7370dfbb20e4de7254f40vboxsync }
8cb6f31c3048428b42c7370dfbb20e4de7254f40vboxsync
8cb6f31c3048428b42c7370dfbb20e4de7254f40vboxsync if (fIsDup)
8d1da51eb6665874aa82bf03668e03d1a0d63223vboxsync continue;
8d1da51eb6665874aa82bf03668e03d1a0d63223vboxsync
8d1da51eb6665874aa82bf03668e03d1a0d63223vboxsync iPath = vboxDispIfWddmDcSearchPath(&DispCfg, Id, Id);
8d1da51eb6665874aa82bf03668e03d1a0d63223vboxsync
8d1da51eb6665874aa82bf03668e03d1a0d63223vboxsync if (!((iPath >= 0) && (DispCfg.pPathInfoArray[iPath].flags & DISPLAYCONFIG_PATH_ACTIVE)) != !fEnabled)
8d1da51eb6665874aa82bf03668e03d1a0d63223vboxsync {
8d1da51eb6665874aa82bf03668e03d1a0d63223vboxsync pChangeIds[cChangeIds] = Id;
6e519506bee0a7f680824b1ca5d8e3fead3ae95evboxsync ++cChangeIds;
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync }
8d1da51eb6665874aa82bf03668e03d1a0d63223vboxsync }
8d1da51eb6665874aa82bf03668e03d1a0d63223vboxsync
8d1da51eb6665874aa82bf03668e03d1a0d63223vboxsync if (cChangeIds == 0)
8d1da51eb6665874aa82bf03668e03d1a0d63223vboxsync {
01df41f7a4e5f7de195a059541d1c89676da9673vboxsync Log(("VBoxTray: (WDDM) vboxDispIfWddmEnableDisplay: settings are up to date\n"));
8d1da51eb6665874aa82bf03668e03d1a0d63223vboxsync winEr = ERROR_SUCCESS;
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync goto done;
8d1da51eb6665874aa82bf03668e03d1a0d63223vboxsync }
8d1da51eb6665874aa82bf03668e03d1a0d63223vboxsync
8d1da51eb6665874aa82bf03668e03d1a0d63223vboxsync /* we want to set primary for every disabled for non-topoly mode only */
8d1da51eb6665874aa82bf03668e03d1a0d63223vboxsync winEr = vboxDispIfWddmDcSettingsIncludeAllTargets(&DispCfg);
8d1da51eb6665874aa82bf03668e03d1a0d63223vboxsync if (winEr != ERROR_SUCCESS)
8d1da51eb6665874aa82bf03668e03d1a0d63223vboxsync {
01df41f7a4e5f7de195a059541d1c89676da9673vboxsync WARN(("VBoxTray: (WDDM) Failed vboxDispIfWddmDcSettingsIncludeAllTargets winEr %d\n", winEr));
01df41f7a4e5f7de195a059541d1c89676da9673vboxsync return winEr;
01df41f7a4e5f7de195a059541d1c89676da9673vboxsync }
8cb6f31c3048428b42c7370dfbb20e4de7254f40vboxsync
8cb6f31c3048428b42c7370dfbb20e4de7254f40vboxsync if (fSetTopology)
8cb6f31c3048428b42c7370dfbb20e4de7254f40vboxsync vboxDispIfWddmDcSettingsInvalidateModeIndeces(&DispCfg);
8cb6f31c3048428b42c7370dfbb20e4de7254f40vboxsync
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync for (UINT i = 0; i < cChangeIds; ++i)
8cb6f31c3048428b42c7370dfbb20e4de7254f40vboxsync {
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync UINT Id = pChangeIds[i];
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync /* re-query paths */
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync iPath = vboxDispIfWddmDcSearchPath(&DispCfg, -1, Id);
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync if (iPath < 0)
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync {
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync WARN(("VBoxTray: (WDDM) path index not found while it should"));
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync winEr = ERROR_GEN_FAILURE;
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync goto done;
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync }
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync winEr = vboxDispIfWddmDcSettingsUpdate(&DispCfg, iPath, pDeviceMode, !fEnabled || fSetTopology, fEnabled);
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync if (winEr != ERROR_SUCCESS)
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync {
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync WARN(("VBoxTray: (WDDM) Failed vboxDispIfWddmDcSettingsUpdate winEr %d\n", winEr));
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync goto done;
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync }
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync }
8d1da51eb6665874aa82bf03668e03d1a0d63223vboxsync
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync if (!fSetTopology)
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync vboxDispIfWddmDcSettingsAttachDisbledToPrimary(&DispCfg);
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync#if 0
8d1da51eb6665874aa82bf03668e03d1a0d63223vboxsync /* ensure the zero-index (primary) screen is enabled */
8d1da51eb6665874aa82bf03668e03d1a0d63223vboxsync iPath = vboxDispIfWddmDcSearchPath(&DispCfg, 0, 0);
8d1da51eb6665874aa82bf03668e03d1a0d63223vboxsync if (iPath < 0)
8d1da51eb6665874aa82bf03668e03d1a0d63223vboxsync {
8d1da51eb6665874aa82bf03668e03d1a0d63223vboxsync WARN(("VBoxTray: (WDDM) path index not found while it should"));
8d1da51eb6665874aa82bf03668e03d1a0d63223vboxsync winEr = ERROR_GEN_FAILURE;
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync goto done;
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync }
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync winEr = vboxDispIfWddmDcSettingsUpdate(&DispCfg, iPath, /* just re-use device node here*/ pDeviceMode, fSetTopology, TRUE);
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync if (winEr != ERROR_SUCCESS)
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync {
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync WARN(("VBoxTray: (WDDM) Failed vboxDispIfWddmDcSettingsUpdate winEr %d\n", winEr));
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync goto done;
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync }
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync#endif
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync UINT fSetFlags = !fSetTopology ? (SDC_USE_SUPPLIED_DISPLAY_CONFIG) : (SDC_ALLOW_PATH_ORDER_CHANGES | SDC_TOPOLOGY_SUPPLIED);
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync winEr = vboxDispIfWddmDcSet(&DispCfg, fSetFlags | SDC_VALIDATE);
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync if (winEr != ERROR_SUCCESS)
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync {
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync if (!fSetTopology)
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync {
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync WARN(("VBoxTray: (WDDM) vboxDispIfWddmDcSet validation failed winEr, trying with changes %d\n", winEr));
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync fSetFlags |= SDC_ALLOW_CHANGES;
6902a98267d5180fb081cb5273751d0a628bf04dvboxsync }
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync else
77db08a24f69bca943d5abc40b1930ee97f593edvboxsync {
77db08a24f69bca943d5abc40b1930ee97f593edvboxsync Log(("VBoxTray: (WDDM) vboxDispIfWddmDcSet topology validation failed winEr %d\n", winEr));
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync goto done;
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync }
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync }
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync if (!fSetTopology)
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync fSetFlags |= SDC_SAVE_TO_DATABASE;
d862f0eeb9eacdb46b9f5cc420de30a3d7c2c3f6vboxsync
d862f0eeb9eacdb46b9f5cc420de30a3d7c2c3f6vboxsync winEr = vboxDispIfWddmDcSet(&DispCfg, fSetFlags | SDC_APPLY);
d862f0eeb9eacdb46b9f5cc420de30a3d7c2c3f6vboxsync if (winEr != ERROR_SUCCESS)
d862f0eeb9eacdb46b9f5cc420de30a3d7c2c3f6vboxsync WARN(("VBoxTray: (WDDM) vboxDispIfWddmDcSet apply failed winEr %d\n", winEr));
d862f0eeb9eacdb46b9f5cc420de30a3d7c2c3f6vboxsync
d862f0eeb9eacdb46b9f5cc420de30a3d7c2c3f6vboxsyncdone:
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync vboxDispIfWddmDcTerm(&DispCfg);
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync return winEr;
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync}
7cfcbe810de5334cdc2e8b92e77db705da143adavboxsync
3a45119099f0df5230e8304145168aa5e2a3f1a1vboxsyncstatic DWORD vboxDispIfWddmEnableDisplaysTryingTopology(PCVBOXDISPIF const pIf, UINT cIds, UINT *pIds, BOOL fEnable)
3a45119099f0df5230e8304145168aa5e2a3f1a1vboxsync{
3a45119099f0df5230e8304145168aa5e2a3f1a1vboxsync DWORD winEr = vboxDispIfWddmEnableDisplays(pIf, cIds, pIds, fEnable, FALSE, NULL);
3a45119099f0df5230e8304145168aa5e2a3f1a1vboxsync if (winEr != ERROR_SUCCESS)
3a45119099f0df5230e8304145168aa5e2a3f1a1vboxsync {
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync if (fEnable)
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync WARN(("VBoxTray: (WDDM) Failed vboxDispIfWddmEnableDisplay mode winEr %d\n", winEr));
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync else
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync Log(("VBoxTray: (WDDM) Failed vboxDispIfWddmEnableDisplay mode winEr %d\n", winEr));
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync winEr = vboxDispIfWddmEnableDisplays(pIf, cIds, pIds, fEnable, TRUE, NULL);
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync if (winEr != ERROR_SUCCESS)
9161d9a8318db73b2848c1feaef3880980474e64vboxsync WARN(("VBoxTray: (WDDM) Failed vboxDispIfWddmEnableDisplay mode winEr %d\n", winEr));
9161d9a8318db73b2848c1feaef3880980474e64vboxsync }
9161d9a8318db73b2848c1feaef3880980474e64vboxsync
9161d9a8318db73b2848c1feaef3880980474e64vboxsync return winEr;
9161d9a8318db73b2848c1feaef3880980474e64vboxsync}
9161d9a8318db73b2848c1feaef3880980474e64vboxsync
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsyncstatic DWORD vboxDispIfWddmResizeDisplay(PCVBOXDISPIF const pIf, UINT Id, BOOL fEnable, DISPLAY_DEVICE * paDisplayDevices, DEVMODE *paDeviceMode, UINT devModes)
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync{
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync VBOXDISPIF_WDDM_DISPCFG DispCfg;
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync DWORD winEr;
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync int iPath;
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync winEr = vboxDispIfWddmDcCreate(&DispCfg, QDC_ONLY_ACTIVE_PATHS);
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync if (winEr != ERROR_SUCCESS)
9161d9a8318db73b2848c1feaef3880980474e64vboxsync {
9161d9a8318db73b2848c1feaef3880980474e64vboxsync WARN(("VBoxTray: (WDDM) Failed vboxDispIfWddmDcCreate\n"));
9161d9a8318db73b2848c1feaef3880980474e64vboxsync return winEr;
9161d9a8318db73b2848c1feaef3880980474e64vboxsync }
8d1da51eb6665874aa82bf03668e03d1a0d63223vboxsync
9161d9a8318db73b2848c1feaef3880980474e64vboxsync iPath = vboxDispIfWddmDcSearchActivePath(&DispCfg, Id, Id);
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync
9161d9a8318db73b2848c1feaef3880980474e64vboxsync if (iPath < 0)
9161d9a8318db73b2848c1feaef3880980474e64vboxsync {
8d1da51eb6665874aa82bf03668e03d1a0d63223vboxsync vboxDispIfWddmDcTerm(&DispCfg);
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync if (!fEnable)
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync {
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync /* nothing to be done here, just leave */
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync return ERROR_SUCCESS;
9161d9a8318db73b2848c1feaef3880980474e64vboxsync }
9161d9a8318db73b2848c1feaef3880980474e64vboxsync
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync winEr = vboxDispIfWddmEnableDisplaysTryingTopology(pIf, 1, &Id, fEnable);
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync if (winEr != ERROR_SUCCESS)
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync {
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync WARN(("VBoxTray: (WDDM) Failed vboxDispIfWddmEnableDisplaysTryingTopology winEr %d\n", winEr));
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync return winEr;
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync }
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync winEr = vboxDispIfWddmDcCreate(&DispCfg, QDC_ONLY_ACTIVE_PATHS);
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync if (winEr != ERROR_SUCCESS)
ad1aea7f006b1feaea275f858b5b574ae61bfe39vboxsync {
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync WARN(("VBoxTray: (WDDM) Failed vboxDispIfWddmDcCreate winEr %d\n", winEr));
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync return winEr;
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync }
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync iPath = vboxDispIfWddmDcSearchPath(&DispCfg, Id, Id);
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync if (iPath < 0)
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync {
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync WARN(("VBoxTray: (WDDM) path (%d) is still disabled, going to retry winEr %d\n", winEr));
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync vboxDispIfWddmDcTerm(&DispCfg);
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync return ERROR_RETRY;
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync }
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync }
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync Assert(iPath >= 0);
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync if (!fEnable)
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync {
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync /* need to disable it, and we are done */
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync vboxDispIfWddmDcTerm(&DispCfg);
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync winEr = vboxDispIfWddmEnableDisplaysTryingTopology(pIf, 1, &Id, fEnable);
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync if (winEr != ERROR_SUCCESS)
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync {
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync WARN(("VBoxTray: (WDDM) Failed vboxDispIfWddmEnableDisplaysTryingTopology winEr %d\n", winEr));
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync return winEr;
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync }
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync return winEr;
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync }
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync Assert(fEnable);
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync winEr = vboxDispIfWddmDcSettingsUpdate(&DispCfg, iPath, &paDeviceMode[Id], FALSE, fEnable);
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync if (winEr != ERROR_SUCCESS)
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync {
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync WARN(("VBoxTray: (WDDM) Failed vboxDispIfWddmDcSettingsUpdate\n"));
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync vboxDispIfWddmDcTerm(&DispCfg);
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync return winEr;
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync }
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync UINT fSetFlags = SDC_USE_SUPPLIED_DISPLAY_CONFIG;
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync winEr = vboxDispIfWddmDcSet(&DispCfg, fSetFlags | SDC_VALIDATE);
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync if (winEr != ERROR_SUCCESS)
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync {
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync WARN(("VBoxTray:(WDDM) pfnSetDisplayConfig Failed to validate winEr %d.\n", winEr));
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync fSetFlags |= SDC_ALLOW_CHANGES;
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync }
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync winEr = vboxDispIfWddmDcSet(&DispCfg, fSetFlags | SDC_SAVE_TO_DATABASE | SDC_APPLY);
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync if (winEr != ERROR_SUCCESS)
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync {
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync WARN(("VBoxTray:(WDDM) pfnSetDisplayConfig Failed to validate winEr %d.\n", winEr));
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync }
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync vboxDispIfWddmDcTerm(&DispCfg);
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync return winEr;
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync}
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync#endif /* VBOX_WITH_WDDM */
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsyncDWORD VBoxDispIfResizeModes(PCVBOXDISPIF const pIf, UINT iChangedMode, BOOL fEnable, BOOL fExtDispSup, DISPLAY_DEVICE *paDisplayDevices, DEVMODE *paDeviceModes, UINT cDevModes)
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync{
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync switch (pIf->enmMode)
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync {
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync case VBOXDISPIF_MODE_XPDM_NT4:
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync return ERROR_NOT_SUPPORTED;
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync case VBOXDISPIF_MODE_XPDM:
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync return ERROR_NOT_SUPPORTED;
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync#ifdef VBOX_WITH_WDDM
aaa6e7826ca134b41d12c1f570bd7874ae1d8135vboxsync case VBOXDISPIF_MODE_WDDM:
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync case VBOXDISPIF_MODE_WDDM_W7:
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync return vboxDispIfResizeModesWDDM(pIf, iChangedMode, fEnable, fExtDispSup, paDisplayDevices, paDeviceModes, cDevModes);
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync#endif
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync default:
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync WARN((__FUNCTION__": unknown mode (%d)\n", pIf->enmMode));
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync return ERROR_INVALID_PARAMETER;
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync }
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync}
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsyncDWORD VBoxDispIfCancelPendingResize(PCVBOXDISPIF const pIf)
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync{
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync switch (pIf->enmMode)
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync {
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync case VBOXDISPIF_MODE_XPDM_NT4:
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync return NO_ERROR;
c4bfe32373c55416bf49dc29ebf45dfa560b4692vboxsync case VBOXDISPIF_MODE_XPDM:
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync return NO_ERROR;
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync#ifdef VBOX_WITH_WDDM
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync case VBOXDISPIF_MODE_WDDM:
730f8be51b729e8a3c1e32c756cd0f4ec088dd4dvboxsync case VBOXDISPIF_MODE_WDDM_W7:
01df41f7a4e5f7de195a059541d1c89676da9673vboxsync return vboxDispIfCancelPendingResizeWDDM(pIf);
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync#endif
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync default:
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync WARN((__FUNCTION__": unknown mode (%d)\n", pIf->enmMode));
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync return ERROR_INVALID_PARAMETER;
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync }
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync}
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsyncstatic DWORD vboxDispIfConfigureTargetsWDDM(VBOXDISPIF_OP *pOp, uint32_t *pcConnected)
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync{
7cfcbe810de5334cdc2e8b92e77db705da143adavboxsync VBOXDISPIFESCAPE EscapeHdr = {0};
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync EscapeHdr.escapeCode = VBOXESC_CONFIGURETARGETS;
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync EscapeHdr.u32CmdSpecific = 0;
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync D3DKMT_ESCAPE EscapeData = {0};
7cfcbe810de5334cdc2e8b92e77db705da143adavboxsync EscapeData.hAdapter = pOp->Adapter.hAdapter;
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync#ifdef VBOX_DISPIF_WITH_OPCONTEXT
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync /* win8.1 does not allow context-based escapes for display-only mode */
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync EscapeData.hDevice = pOp->Device.hDevice;
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync EscapeData.hContext = pOp->Context.hContext;
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync#endif
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync EscapeData.Type = D3DKMT_ESCAPE_DRIVERPRIVATE;
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync EscapeData.Flags.HardwareAccess = 1;
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync EscapeData.pPrivateDriverData = &EscapeHdr;
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync EscapeData.PrivateDriverDataSize = sizeof (EscapeHdr);
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync NTSTATUS Status = pOp->pIf->modeData.wddm.KmtCallbacks.pfnD3DKMTEscape(&EscapeData);
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync if (NT_SUCCESS(Status))
c4bfe32373c55416bf49dc29ebf45dfa560b4692vboxsync {
2dd7b4388106de88d20f33a8aa6c85c8babf507bvboxsync if (pcConnected)
2dd7b4388106de88d20f33a8aa6c85c8babf507bvboxsync *pcConnected = EscapeHdr.u32CmdSpecific;
2dd7b4388106de88d20f33a8aa6c85c8babf507bvboxsync return NO_ERROR;
2dd7b4388106de88d20f33a8aa6c85c8babf507bvboxsync }
2dd7b4388106de88d20f33a8aa6c85c8babf507bvboxsync WARN(("VBoxTray: pfnD3DKMTEscape VBOXESC_CONFIGURETARGETS failed Status 0x%x\n", Status));
2dd7b4388106de88d20f33a8aa6c85c8babf507bvboxsync return Status;
2dd7b4388106de88d20f33a8aa6c85c8babf507bvboxsync}
2dd7b4388106de88d20f33a8aa6c85c8babf507bvboxsync
3faac25bf74aedb359249d6acd6d8e4988acd332vboxsyncstatic DWORD vboxDispIfResizeStartedWDDMOp(VBOXDISPIF_OP *pOp)
3faac25bf74aedb359249d6acd6d8e4988acd332vboxsync{
3faac25bf74aedb359249d6acd6d8e4988acd332vboxsync DWORD NumDevices = VBoxGetDisplayConfigCount();
3faac25bf74aedb359249d6acd6d8e4988acd332vboxsync if (NumDevices == 0)
3faac25bf74aedb359249d6acd6d8e4988acd332vboxsync {
2dd7b4388106de88d20f33a8aa6c85c8babf507bvboxsync WARN(("VBoxTray: vboxDispIfResizeStartedWDDMOp: Zero devices found\n"));
2dd7b4388106de88d20f33a8aa6c85c8babf507bvboxsync return ERROR_GEN_FAILURE;
3faac25bf74aedb359249d6acd6d8e4988acd332vboxsync }
2dd7b4388106de88d20f33a8aa6c85c8babf507bvboxsync
3faac25bf74aedb359249d6acd6d8e4988acd332vboxsync DISPLAY_DEVICE *paDisplayDevices = (DISPLAY_DEVICE *)alloca (sizeof (DISPLAY_DEVICE) * NumDevices);
3faac25bf74aedb359249d6acd6d8e4988acd332vboxsync DEVMODE *paDeviceModes = (DEVMODE *)alloca (sizeof (DEVMODE) * NumDevices);
3faac25bf74aedb359249d6acd6d8e4988acd332vboxsync DWORD DevNum = 0;
a8d502445ce722c6b9700c5579b4a38b58827b7dvboxsync DWORD DevPrimaryNum = 0;
a8d502445ce722c6b9700c5579b4a38b58827b7dvboxsync
3faac25bf74aedb359249d6acd6d8e4988acd332vboxsync DWORD winEr = VBoxGetDisplayConfig(NumDevices, &DevPrimaryNum, &DevNum, paDisplayDevices, paDeviceModes);
2dd7b4388106de88d20f33a8aa6c85c8babf507bvboxsync if (winEr != NO_ERROR)
2dd7b4388106de88d20f33a8aa6c85c8babf507bvboxsync {
2dd7b4388106de88d20f33a8aa6c85c8babf507bvboxsync WARN(("VBoxTray: vboxDispIfResizeStartedWDDMOp: VBoxGetDisplayConfig failed, %d\n", winEr));
2dd7b4388106de88d20f33a8aa6c85c8babf507bvboxsync return winEr;
2dd7b4388106de88d20f33a8aa6c85c8babf507bvboxsync }
c4bfe32373c55416bf49dc29ebf45dfa560b4692vboxsync
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync if (NumDevices != DevNum)
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync WARN(("VBoxTray: vboxDispIfResizeStartedWDDMOp: NumDevices(%d) != DevNum(%d)\n", NumDevices, DevNum));
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync uint32_t cConnected = 0;
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync winEr = vboxDispIfConfigureTargetsWDDM(pOp, &cConnected);
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync if (winEr != NO_ERROR)
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync {
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync WARN(("VBoxTray: vboxDispIfConfigureTargetsWDDM failed winEr 0x%x\n", winEr));
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync return winEr;
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync }
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync
3c9ed6defa3feca7e21adef4b5d1ba3002fc94c9vboxsync if (!cConnected)
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync {
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync Log(("VBoxTray: all targets already connected, nothing to do\n"));
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync return NO_ERROR;
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync }
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync
3c9ed6defa3feca7e21adef4b5d1ba3002fc94c9vboxsync winEr = vboxDispIfWaitDisplayDataInited(pOp);
3c9ed6defa3feca7e21adef4b5d1ba3002fc94c9vboxsync if (winEr != NO_ERROR)
3c9ed6defa3feca7e21adef4b5d1ba3002fc94c9vboxsync WARN(("VBoxTray: vboxDispIfResizeStartedWDDMOp: vboxDispIfWaitDisplayDataInited failed winEr 0x%x\n", winEr));
3c9ed6defa3feca7e21adef4b5d1ba3002fc94c9vboxsync
8842b172df03540da1eba3c422804d54f29c9fb6vboxsync DWORD NewNumDevices = VBoxGetDisplayConfigCount();
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync if (NewNumDevices == 0)
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync {
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync WARN(("VBoxTray: vboxDispIfResizeStartedWDDMOp: Zero devices found\n"));
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync return ERROR_GEN_FAILURE;
3c9ed6defa3feca7e21adef4b5d1ba3002fc94c9vboxsync }
3c9ed6defa3feca7e21adef4b5d1ba3002fc94c9vboxsync
3c9ed6defa3feca7e21adef4b5d1ba3002fc94c9vboxsync if (NewNumDevices != NumDevices)
3c9ed6defa3feca7e21adef4b5d1ba3002fc94c9vboxsync WARN(("VBoxTray: vboxDispIfResizeStartedWDDMOp: NumDevices(%d) != NewNumDevices(%d)\n", NumDevices, NewNumDevices));
3c9ed6defa3feca7e21adef4b5d1ba3002fc94c9vboxsync
3c9ed6defa3feca7e21adef4b5d1ba3002fc94c9vboxsync DISPLAY_DEVICE *paNewDisplayDevices = (DISPLAY_DEVICE *)alloca (sizeof (DISPLAY_DEVICE) * NewNumDevices);
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync DEVMODE *paNewDeviceModes = (DEVMODE *)alloca (sizeof (DEVMODE) * NewNumDevices);
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync DWORD NewDevNum = 0;
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync DWORD NewDevPrimaryNum = 0;
416817daa142e9bb7eaf14a1b10577978a5e691bvboxsync
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync winEr = VBoxGetDisplayConfig(NewNumDevices, &NewDevPrimaryNum, &NewDevNum, paNewDisplayDevices, paNewDeviceModes);
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync if (winEr != NO_ERROR)
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync {
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync WARN(("VBoxTray: vboxDispIfResizeStartedWDDMOp: VBoxGetDisplayConfig failed for new devices, %d\n", winEr));
8842b172df03540da1eba3c422804d54f29c9fb6vboxsync return winEr;
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync }
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync if (NewNumDevices != NewDevNum)
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync WARN(("VBoxTray: vboxDispIfResizeStartedWDDMOp: NewNumDevices(%d) != NewDevNum(%d)\n", NewNumDevices, NewDevNum));
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync DWORD minDevNum = RT_MIN(DevNum, NewDevNum);
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync UINT *pIds = (UINT*)alloca (sizeof (UINT) * minDevNum);
c4bfe32373c55416bf49dc29ebf45dfa560b4692vboxsync UINT cIds = 0;
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync for (DWORD i = 0; i < minDevNum; ++i)
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync {
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync if ((paNewDisplayDevices[i].StateFlags & DISPLAY_DEVICE_ACTIVE)
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync && !(paDisplayDevices[i].StateFlags & DISPLAY_DEVICE_ACTIVE))
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync {
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync pIds[cIds] = i;
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync ++cIds;
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync }
c4bfe32373c55416bf49dc29ebf45dfa560b4692vboxsync }
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync if (!cIds)
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync {
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync /* this is something we would not regularly expect */
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync WARN(("VBoxTray: all targets already have proper config, nothing to do\n"));
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync return NO_ERROR;
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync }
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync if (pOp->pIf->enmMode > VBOXDISPIF_MODE_WDDM)
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync {
c4bfe32373c55416bf49dc29ebf45dfa560b4692vboxsync winEr = vboxDispIfWddmEnableDisplaysTryingTopology(pOp->pIf, cIds, pIds, FALSE);
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync if (winEr != NO_ERROR)
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync WARN(("VBoxTray: vboxDispIfWddmEnableDisplaysTryingTopology failed to record current settings, %d, ignoring\n", winEr));
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync }
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync else
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync {
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync for (DWORD i = 0; i < cIds; ++i)
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync {
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync winEr = vboxDispIfWddmResizeDisplayVista(paNewDeviceModes, paNewDisplayDevices, NewDevNum, i, FALSE, TRUE);
c4bfe32373c55416bf49dc29ebf45dfa560b4692vboxsync if (winEr != NO_ERROR)
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync WARN(("VBoxTray: vboxDispIfResizeStartedWDDMOp: vboxDispIfWddmResizeDisplayVista failed winEr 0x%x\n", winEr));
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync }
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync }
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync return winEr;
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync}
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync
c4bfe32373c55416bf49dc29ebf45dfa560b4692vboxsyncstatic DWORD vboxDispIfResizeStartedWDDM(PCVBOXDISPIF const pIf)
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync{
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync VBOXDISPIF_OP Op;
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync DWORD winEr = vboxDispIfOpBegin(pIf, &Op);
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync if (winEr != NO_ERROR)
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync {
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync WARN(("VBoxTray: vboxDispIfOpBegin failed winEr 0x%x\n", winEr));
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync return winEr;
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync }
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync winEr = vboxDispIfResizeStartedWDDMOp(&Op);
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync if (winEr != NO_ERROR)
01df41f7a4e5f7de195a059541d1c89676da9673vboxsync {
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync WARN(("VBoxTray: vboxDispIfResizeStartedWDDMOp failed winEr 0x%x\n", winEr));
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync }
ece707b8d97e63ed54d4b48d7a8d841187e0023cvboxsync
ece707b8d97e63ed54d4b48d7a8d841187e0023cvboxsync vboxDispIfOpEnd(&Op);
ece707b8d97e63ed54d4b48d7a8d841187e0023cvboxsync
ece707b8d97e63ed54d4b48d7a8d841187e0023cvboxsync return winEr;
ece707b8d97e63ed54d4b48d7a8d841187e0023cvboxsync}
ece707b8d97e63ed54d4b48d7a8d841187e0023cvboxsync
ece707b8d97e63ed54d4b48d7a8d841187e0023cvboxsyncDWORD VBoxDispIfResizeStarted(PCVBOXDISPIF const pIf)
ece707b8d97e63ed54d4b48d7a8d841187e0023cvboxsync{
ece707b8d97e63ed54d4b48d7a8d841187e0023cvboxsync switch (pIf->enmMode)
ece707b8d97e63ed54d4b48d7a8d841187e0023cvboxsync {
ece707b8d97e63ed54d4b48d7a8d841187e0023cvboxsync case VBOXDISPIF_MODE_XPDM_NT4:
ece707b8d97e63ed54d4b48d7a8d841187e0023cvboxsync return NO_ERROR;
ece707b8d97e63ed54d4b48d7a8d841187e0023cvboxsync case VBOXDISPIF_MODE_XPDM:
ece707b8d97e63ed54d4b48d7a8d841187e0023cvboxsync return NO_ERROR;
ece707b8d97e63ed54d4b48d7a8d841187e0023cvboxsync#ifdef VBOX_WITH_WDDM
ece707b8d97e63ed54d4b48d7a8d841187e0023cvboxsync case VBOXDISPIF_MODE_WDDM:
ece707b8d97e63ed54d4b48d7a8d841187e0023cvboxsync case VBOXDISPIF_MODE_WDDM_W7:
ece707b8d97e63ed54d4b48d7a8d841187e0023cvboxsync return vboxDispIfResizeStartedWDDM(pIf);
ece707b8d97e63ed54d4b48d7a8d841187e0023cvboxsync#endif
b57c052e6d9d432fa8b66fb33d373fc608d4d050vboxsync default:
3a45119099f0df5230e8304145168aa5e2a3f1a1vboxsync WARN((__FUNCTION__": unknown mode (%d)\n", pIf->enmMode));
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync return ERROR_INVALID_PARAMETER;
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync }
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync}
610972deee47d5e5229ccdb6c86cbb332d2b4626vboxsync
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsyncstatic DWORD vboxDispIfSwitchToXPDM_NT4(PVBOXDISPIF pIf)
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync{
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync return NO_ERROR;
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync}
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsyncstatic DWORD vboxDispIfSwitchToXPDM(PVBOXDISPIF pIf)
8be5264d31d6a6ec949ff2285764c9af57298b52vboxsync{
8be5264d31d6a6ec949ff2285764c9af57298b52vboxsync DWORD err = NO_ERROR;
8be5264d31d6a6ec949ff2285764c9af57298b52vboxsync AssertBreakpoint();
8be5264d31d6a6ec949ff2285764c9af57298b52vboxsync OSVERSIONINFO OSinfo;
8be5264d31d6a6ec949ff2285764c9af57298b52vboxsync OSinfo.dwOSVersionInfoSize = sizeof (OSinfo);
8be5264d31d6a6ec949ff2285764c9af57298b52vboxsync GetVersionEx (&OSinfo);
8be5264d31d6a6ec949ff2285764c9af57298b52vboxsync if (OSinfo.dwMajorVersion >= 5)
7cfcbe810de5334cdc2e8b92e77db705da143adavboxsync {
8be5264d31d6a6ec949ff2285764c9af57298b52vboxsync HMODULE hUser = GetModuleHandle("user32.dll");
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync if (NULL != hUser)
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync {
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync bool bSupported = true;
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync *(uintptr_t *)&pIf->modeData.xpdm.pfnChangeDisplaySettingsEx = (uintptr_t)GetProcAddress(hUser, "ChangeDisplaySettingsExA");
6902a98267d5180fb081cb5273751d0a628bf04dvboxsync Log((__FUNCTION__": pfnChangeDisplaySettingsEx = %p\n", pIf->modeData.xpdm.pfnChangeDisplaySettingsEx));
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync bSupported &= !!(pIf->modeData.xpdm.pfnChangeDisplaySettingsEx);
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync if (!bSupported)
2f4c1bacd54af5063c3185cc8eab03e4e8ef9b90vboxsync {
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync WARN((__FUNCTION__": pfnChangeDisplaySettingsEx function pointer failed to initialize\n"));
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync err = ERROR_NOT_SUPPORTED;
5a07658d13590eba51dd98ef335a73d2a11edaa7vboxsync }
}
else
{
WARN((__FUNCTION__": failed to get USER32 handle, err (%d)\n", GetLastError()));
err = ERROR_NOT_SUPPORTED;
}
}
else
{
WARN((__FUNCTION__": can not switch to VBOXDISPIF_MODE_XPDM, because os is not >= w2k\n"));
err = ERROR_NOT_SUPPORTED;
}
return err;
}
DWORD VBoxDispIfSwitchMode(PVBOXDISPIF pIf, VBOXDISPIF_MODE enmMode, VBOXDISPIF_MODE *penmOldMode)
{
/* @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)
*penmOldMode = pIf->enmMode;
if (enmMode == pIf->enmMode)
return NO_ERROR;
#ifdef VBOX_WITH_WDDM
if (pIf->enmMode >= VBOXDISPIF_MODE_WDDM)
{
vboxDispIfWddmTerm(pIf);
vboxDispKmtCallbacksTerm(&pIf->modeData.wddm.KmtCallbacks);
}
#endif
DWORD err = NO_ERROR;
switch (enmMode)
{
case VBOXDISPIF_MODE_XPDM_NT4:
Log((__FUNCTION__": request to switch to VBOXDISPIF_MODE_XPDM_NT4\n"));
err = vboxDispIfSwitchToXPDM_NT4(pIf);
if (err == NO_ERROR)
{
Log((__FUNCTION__": successfully switched to XPDM_NT4 mode\n"));
pIf->enmMode = VBOXDISPIF_MODE_XPDM_NT4;
}
else
WARN((__FUNCTION__": failed to switch to XPDM_NT4 mode, err (%d)\n", err));
break;
case VBOXDISPIF_MODE_XPDM:
Log((__FUNCTION__": request to switch to VBOXDISPIF_MODE_XPDM\n"));
err = vboxDispIfSwitchToXPDM(pIf);
if (err == NO_ERROR)
{
Log((__FUNCTION__": successfully switched to XPDM mode\n"));
pIf->enmMode = VBOXDISPIF_MODE_XPDM;
}
else
WARN((__FUNCTION__": failed to switch to XPDM mode, err (%d)\n", err));
break;
#ifdef VBOX_WITH_WDDM
case VBOXDISPIF_MODE_WDDM:
{
Log((__FUNCTION__": request to switch to VBOXDISPIF_MODE_WDDM\n"));
err = vboxDispIfSwitchToWDDM(pIf);
if (err == NO_ERROR)
{
Log((__FUNCTION__": successfully switched to WDDM mode\n"));
pIf->enmMode = VBOXDISPIF_MODE_WDDM;
}
else
WARN((__FUNCTION__": failed to switch to WDDM mode, err (%d)\n", err));
break;
}
case VBOXDISPIF_MODE_WDDM_W7:
{
Log((__FUNCTION__": request to switch to VBOXDISPIF_MODE_WDDM_W7\n"));
err = vboxDispIfSwitchToWDDM_W7(pIf);
if (err == NO_ERROR)
{
Log((__FUNCTION__": successfully switched to WDDM mode\n"));
pIf->enmMode = VBOXDISPIF_MODE_WDDM_W7;
}
else
WARN((__FUNCTION__": failed to switch to WDDM mode, err (%d)\n", err));
break;
}
#endif
default:
err = ERROR_INVALID_PARAMETER;
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);
if (SUCCEEDED(hr))
{
#ifdef VBOX_DISPIF_WITH_OPCONTEXT
hr = vboxDispKmtCreateDevice(&pSeamless->modeData.wddm.Adapter, &pSeamless->modeData.wddm.Device);
if (SUCCEEDED(hr))
{
hr = vboxDispKmtCreateContext(&pSeamless->modeData.wddm.Device, &pSeamless->modeData.wddm.Context, VBOXWDDM_CONTEXT_TYPE_CUSTOM_DISPIF_SEAMLESS,
0, 0, hEvent, 0ULL);
if (SUCCEEDED(hr))
#endif
return ERROR_SUCCESS;
#ifdef VBOX_DISPIF_WITH_OPCONTEXT
else
WARN(("VBoxTray: vboxDispKmtCreateContext failed hr 0x%x", hr));
vboxDispKmtDestroyDevice(&pSeamless->modeData.wddm.Device);
}
else
WARN(("VBoxTray: vboxDispKmtCreateDevice failed hr 0x%x", hr));
vboxDispKmtCloseAdapter(&pSeamless->modeData.wddm.Adapter);
#endif
}
return hr;
}
static DWORD vboxDispIfSeamlesTermWDDM(VBOXDISPIF_SEAMLESS *pSeamless)
{
#ifdef VBOX_DISPIF_WITH_OPCONTEXT
vboxDispKmtDestroyContext(&pSeamless->modeData.wddm.Context);
vboxDispKmtDestroyDevice(&pSeamless->modeData.wddm.Device);
#endif
vboxDispKmtCloseAdapter(&pSeamless->modeData.wddm.Adapter);
return NO_ERROR;
}
static DWORD vboxDispIfSeamlesSubmitWDDM(VBOXDISPIF_SEAMLESS *pSeamless, VBOXDISPIFESCAPE *pData, int cbData)
{
D3DKMT_ESCAPE EscapeData = {0};
EscapeData.hAdapter = pSeamless->modeData.wddm.Adapter.hAdapter;
#ifdef VBOX_DISPIF_WITH_OPCONTEXT
EscapeData.hDevice = pSeamless->modeData.wddm.Device.hDevice;
EscapeData.hContext = pSeamless->modeData.wddm.Context.hContext;
#endif
EscapeData.Type = D3DKMT_ESCAPE_DRIVERPRIVATE;
/*EscapeData.Flags.HardwareAccess = 1;*/
EscapeData.pPrivateDriverData = pData;
EscapeData.PrivateDriverDataSize = VBOXDISPIFESCAPE_SIZE(cbData);
NTSTATUS Status = pSeamless->pIf->modeData.wddm.KmtCallbacks.pfnD3DKMTEscape(&EscapeData);
if (NT_SUCCESS(Status))
return ERROR_SUCCESS;
WARN(("VBoxTray: pfnD3DKMTEscape Seamless failed Status 0x%x\n", Status));
return Status;
}
DWORD VBoxDispIfSeamlesCreate(PCVBOXDISPIF const pIf, VBOXDISPIF_SEAMLESS *pSeamless, HANDLE hEvent)
{
memset(pSeamless, 0, sizeof (*pSeamless));
pSeamless->pIf = pIf;
switch (pIf->enmMode)
{
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:
return vboxDispIfSeamlesCreateWDDM(pIf, pSeamless, hEvent);
#endif
default:
WARN(("VBoxTray: VBoxDispIfSeamlesCreate: invalid mode %d\n", pIf->enmMode));
return ERROR_INVALID_PARAMETER;
}
}
DWORD VBoxDispIfSeamlesTerm(VBOXDISPIF_SEAMLESS *pSeamless)
{
PCVBOXDISPIF const pIf = pSeamless->pIf;
DWORD winEr;
switch (pIf->enmMode)
{
case VBOXDISPIF_MODE_XPDM_NT4:
case VBOXDISPIF_MODE_XPDM:
winEr = NO_ERROR;
break;
#ifdef VBOX_WITH_WDDM
case VBOXDISPIF_MODE_WDDM:
case VBOXDISPIF_MODE_WDDM_W7:
winEr = vboxDispIfSeamlesTermWDDM(pSeamless);
break;
#endif
default:
WARN(("VBoxTray: VBoxDispIfSeamlesTerm: invalid mode %d\n", pIf->enmMode));
winEr = ERROR_INVALID_PARAMETER;
break;
}
if (winEr == NO_ERROR)
memset(pSeamless, 0, sizeof (*pSeamless));
return winEr;
}
DWORD VBoxDispIfSeamlesSubmit(VBOXDISPIF_SEAMLESS *pSeamless, VBOXDISPIFESCAPE *pData, int cbData)
{
PCVBOXDISPIF const pIf = pSeamless->pIf;
if (pData->escapeCode != VBOXESC_SETVISIBLEREGION)
{
WARN(("VBoxTray: invalid escape code for Seamless submit %d\n", pData->escapeCode));
return ERROR_INVALID_PARAMETER;
}
switch (pIf->enmMode)
{
case VBOXDISPIF_MODE_XPDM_NT4:
case VBOXDISPIF_MODE_XPDM:
return VBoxDispIfEscape(pIf, pData, cbData);
#ifdef VBOX_WITH_WDDM
case VBOXDISPIF_MODE_WDDM:
case VBOXDISPIF_MODE_WDDM_W7:
return vboxDispIfSeamlesSubmitWDDM(pSeamless, pData, cbData);
#endif
default:
WARN(("VBoxTray: VBoxDispIfSeamlesSubmit: invalid mode %d\n", pIf->enmMode));
return ERROR_INVALID_PARAMETER;
}
}