Index: /trunk/src/VBox/Additions/WINNT/Graphics/Video/mp/common/VBoxMPCommon.h
===================================================================
--- /trunk/src/VBox/Additions/WINNT/Graphics/Video/mp/common/VBoxMPCommon.h	(revision 42216)
+++ /trunk/src/VBox/Additions/WINNT/Graphics/Video/mp/common/VBoxMPCommon.h	(revision 42217)
@@ -42,6 +42,8 @@
 
 #ifdef VBOX_WDDM_MINIPORT
-void VBoxWddmInvalidateVideoModesInfo(PVBOXMP_DEVEXT pExt);
-PVBOXWDDM_VIDEOMODES_INFO VBoxWddmUpdateVideoModesInfo(PVBOXMP_DEVEXT pExt, PVBOXWDDM_RECOMMENDVIDPN pVidPnInfo);
+void VBoxWddmInvalidateAllVideoModesInfos(PVBOXMP_DEVEXT pExt);
+void VBoxWddmInvalidateVideoModesInfo(PVBOXMP_DEVEXT pExt, D3DDDI_VIDEO_PRESENT_TARGET_ID VidPnTargetId);
+PVBOXWDDM_VIDEOMODES_INFO VBoxWddmUpdateVideoModesInfoByMask(PVBOXMP_DEVEXT pExt, uint8_t *pScreenIdMask);
+PVBOXWDDM_VIDEOMODES_INFO VBoxWddmUpdateAllVideoModesInfos(PVBOXMP_DEVEXT pExt);
 NTSTATUS VBoxWddmGetModesForResolution(VIDEO_MODE_INFORMATION *pAllModes, uint32_t cAllModes, int iSearchPreferredMode,
                                        const D3DKMDT_2DREGION *pResolution, VIDEO_MODE_INFORMATION * pModes,
@@ -50,4 +52,7 @@
 PVBOXWDDM_VIDEOMODES_INFO VBoxWddmGetVideoModesInfo(PVBOXMP_DEVEXT pExt, D3DDDI_VIDEO_PRESENT_TARGET_ID VidPnTargetId);
 bool VBoxWddmFillMode(VIDEO_MODE_INFORMATION *pInfo, D3DDDIFORMAT enmFormat, ULONG w, ULONG h);
+bool VBoxWddmFillMode(VIDEO_MODE_INFORMATION *pInfo, D3DDDIFORMAT enmFormat, ULONG w, ULONG h);
+void VBoxWddmAdjustMode(PVBOXMP_DEVEXT pExt, PVBOXWDDM_ADJUSTVIDEOMODE pMode);
+void VBoxWddmAdjustModes(PVBOXMP_DEVEXT pExt, uint32_t cModes, PVBOXWDDM_ADJUSTVIDEOMODE aModes);
 #endif
 
Index: /trunk/src/VBox/Additions/WINNT/Graphics/Video/mp/common/VBoxMPVidModes.cpp
===================================================================
--- /trunk/src/VBox/Additions/WINNT/Graphics/Video/mp/common/VBoxMPVidModes.cpp	(revision 42216)
+++ /trunk/src/VBox/Additions/WINNT/Graphics/Video/mp/common/VBoxMPVidModes.cpp	(revision 42217)
@@ -1090,6 +1090,17 @@
 }
 
-void VBoxWddmInvalidateVideoModesInfo(PVBOXMP_DEVEXT pExt)
-{
+void VBoxWddmInvalidateVideoModesInfo(PVBOXMP_DEVEXT pExt, D3DDDI_VIDEO_PRESENT_TARGET_ID VidPnTargetId)
+{
+    if (VidPnTargetId != D3DDDI_ID_ALL)
+    {
+        if (VidPnTargetId >= RT_ELEMENTS(g_aVBoxVideoModeInfos))
+        {
+            WARN(("VidPnTargetId (%d) must be less than (%d)", VidPnTargetId, RT_ELEMENTS(g_aVBoxVideoModeInfos)));
+            return;
+        }
+        g_aVBoxVideoModeInfos[VidPnTargetId].cModes = 0;
+        return;
+    }
+
     for (UINT i = 0; i < RT_ELEMENTS(g_aVBoxVideoModeInfos); ++i)
     {
@@ -1098,51 +1109,15 @@
 }
 
-PVBOXWDDM_VIDEOMODES_INFO VBoxWddmUpdateVideoModesInfo(PVBOXMP_DEVEXT pExt, PVBOXWDDM_RECOMMENDVIDPN pVidPnInfo)
-{
-    VBoxWddmInvalidateVideoModesInfo(pExt);
-
-    if (pVidPnInfo)
-    {
-        for (UINT i = 0; i < pVidPnInfo->cScreenInfos; ++i)
-        {
-            PVBOXWDDM_RECOMMENDVIDPN_SCREEN_INFO pScreenInfo = &pVidPnInfo->aScreenInfos[i];
-            Assert(pScreenInfo->Id < (DWORD)VBoxCommonFromDeviceExt(pExt)->cDisplays);
-            if (pScreenInfo->Id < (DWORD)VBoxCommonFromDeviceExt(pExt)->cDisplays)
-            {
-                PVBOXWDDM_VIDEOMODES_INFO pInfo = &g_aVBoxVideoModeInfos[pScreenInfo->Id];
-                VIDEO_MODE_INFORMATION ModeInfo = {0};
-                D3DDDIFORMAT enmFormat;
-                switch (pScreenInfo->BitsPerPixel)
-                {
-                    case 32:
-                        enmFormat = D3DDDIFMT_A8R8G8B8;
-                        break;
-                    case 24:
-                        enmFormat = D3DDDIFMT_R8G8B8;
-                        break;
-                    case 16:
-                        enmFormat = D3DDDIFMT_R5G6B5;
-                        break;
-                    case 8:
-                        enmFormat = D3DDDIFMT_P8;
-                        break;
-                    default:
-                        Assert(0);
-                        enmFormat = D3DDDIFMT_UNKNOWN;
-                        break;
-                }
-                if (enmFormat != D3DDDIFMT_UNKNOWN)
-                {
-                    if (VBoxWddmFillMode(pExt, pScreenInfo->Id, &ModeInfo, enmFormat, pScreenInfo->Width, pScreenInfo->Height))
-                    {
-                        VBoxWddmBuildVideoModesInfo(pExt, pScreenInfo->Id, pInfo, &ModeInfo, 1);
-                    }
-                    else
-                    {
-                        Assert(0);
-                    }
-                }
-            }
-        }
+void VBoxWddmInvalidateAllVideoModesInfos(PVBOXMP_DEVEXT pExt)
+{
+    VBoxWddmInvalidateVideoModesInfo(pExt, D3DDDI_ID_ALL);
+}
+
+PVBOXWDDM_VIDEOMODES_INFO VBoxWddmUpdateVideoModesInfoByMask(PVBOXMP_DEVEXT pExt, uint8_t *pScreenIdMask)
+{
+    for (int i = 0; i < VBoxCommonFromDeviceExt(pExt)->cDisplays; ++i)
+    {
+        if (ASMBitTest(pScreenIdMask, i))
+            VBoxWddmInvalidateVideoModesInfo(pExt, i);
     }
 
@@ -1150,4 +1125,79 @@
     VBoxWddmGetAllVideoModesInfos(pExt);
     return g_aVBoxVideoModeInfos;
+}
+
+PVBOXWDDM_VIDEOMODES_INFO VBoxWddmUpdateAllVideoModesInfos(PVBOXMP_DEVEXT pExt)
+{
+    VBoxWddmInvalidateAllVideoModesInfos(pExt);
+
+    /* ensure we have all the rest populated */
+    VBoxWddmGetAllVideoModesInfos(pExt);
+    return g_aVBoxVideoModeInfos;
+}
+
+void VBoxWddmAdjustMode(PVBOXMP_DEVEXT pExt, PVBOXWDDM_ADJUSTVIDEOMODE pMode)
+{
+    pMode->fFlags = 0;
+
+    if (pMode->Mode.Id >= (UINT)VBoxCommonFromDeviceExt(pExt)->cDisplays)
+    {
+        WARN(("invalid screen id (%d)", pMode->Mode.Id));
+        pMode->fFlags = VBOXWDDM_ADJUSTVIDEOMODE_F_INVALISCREENID;
+        return;
+    }
+
+    PVBOXWDDM_TARGET pTarget = &pExt->aTargets[pMode->Mode.Id];
+    /* @todo: this info should go from the target actually */
+    PVBOXWDDM_SOURCE pSource = &pExt->aSources[pMode->Mode.Id];
+    if (pTarget->HeightVisible /* <- active */
+            && pSource->AllocData.SurfDesc.width == pMode->Mode.Width
+            && pSource->AllocData.SurfDesc.height == pMode->Mode.Height
+            && pSource->AllocData.SurfDesc.bpp == pMode->Mode.BitsPerPixel)
+    {
+        pMode->fFlags = VBOXWDDM_ADJUSTVIDEOMODE_F_CURRENT;
+        return;
+    }
+
+    UINT newWidth = pMode->Mode.Width;
+    UINT newHeight = pMode->Mode.Height;
+    UINT newBpp = pMode->Mode.BitsPerPixel;
+
+    if (!VBoxMPValidateVideoModeParams(pExt, pMode->Mode.Id, newWidth, newHeight, newBpp))
+    {
+        PVBOXWDDM_SOURCE pSource = &pExt->aSources[pMode->Mode.Id];
+        pMode->fFlags = VBOXWDDM_ADJUSTVIDEOMODE_F_UNSUPPORTED;
+    }
+
+    if (pMode->Mode.Width != newWidth
+            || pMode->Mode.Height != newHeight
+            || pMode->Mode.BitsPerPixel != newBpp)
+    {
+        pMode->fFlags |= VBOXWDDM_ADJUSTVIDEOMODE_F_ADJUSTED;
+        pMode->Mode.Width = newWidth;
+        pMode->Mode.Height = newHeight;
+        pMode->Mode.BitsPerPixel = newBpp;
+    }
+
+    if (pTarget->HeightVisible /* <- active */
+            && pSource->AllocData.SurfDesc.width == pMode->Mode.Width
+            && pSource->AllocData.SurfDesc.height == pMode->Mode.Height
+            && pSource->AllocData.SurfDesc.bpp == pMode->Mode.BitsPerPixel)
+    {
+        pMode->fFlags |= VBOXWDDM_ADJUSTVIDEOMODE_F_CURRENT;
+        if (pMode->fFlags & VBOXWDDM_ADJUSTVIDEOMODE_F_UNSUPPORTED)
+        {
+            WARN(("current mode is reported as unsupported, cleaning the unsupported flag"));
+            pMode->fFlags &= ~VBOXWDDM_ADJUSTVIDEOMODE_F_UNSUPPORTED;
+        }
+    }
+}
+
+void VBoxWddmAdjustModes(PVBOXMP_DEVEXT pExt, uint32_t cModes, PVBOXWDDM_ADJUSTVIDEOMODE aModes)
+{
+    for (UINT i = 0; i < cModes; ++i)
+    {
+        PVBOXWDDM_ADJUSTVIDEOMODE pMode = &aModes[i];
+        VBoxWddmAdjustMode(pExt, pMode);
+    }
 }
 
Index: /trunk/src/VBox/Additions/WINNT/Graphics/Video/mp/wddm/VBoxMPVidPn.cpp
===================================================================
--- /trunk/src/VBox/Additions/WINNT/Graphics/Video/mp/wddm/VBoxMPVidPn.cpp	(revision 42216)
+++ /trunk/src/VBox/Additions/WINNT/Graphics/Video/mp/wddm/VBoxMPVidPn.cpp	(revision 42217)
@@ -219,10 +219,10 @@
     NTSTATUS Status = STATUS_SUCCESS;
 
-    pVsi->VideoStandard  = D3DKMDT_VSS_VESA_DMT;
+    pVsi->VideoStandard  = D3DKMDT_VSS_OTHER;
     pVsi->ActiveSize = *pResolution;
     pVsi->VSyncFreq.Numerator = VSync * 1000;
     pVsi->VSyncFreq.Denominator = 1000;
-    pVsi->TotalSize.cx = pVsi->ActiveSize.cx + VBOXVDPN_C_DISPLAY_HBLANK_SIZE;
-    pVsi->TotalSize.cy = pVsi->ActiveSize.cy + VBOXVDPN_C_DISPLAY_VBLANK_SIZE;
+    pVsi->TotalSize.cx = pVsi->ActiveSize.cx;// + VBOXVDPN_C_DISPLAY_HBLANK_SIZE;
+    pVsi->TotalSize.cy = pVsi->ActiveSize.cy;// + VBOXVDPN_C_DISPLAY_VBLANK_SIZE;
     pVsi->PixelRate = pVsi->TotalSize.cx * pVsi->TotalSize.cy * VSync;
     pVsi->HSyncFreq.Numerator = (UINT)((pVsi->PixelRate / pVsi->TotalSize.cy) * 1000);
@@ -527,5 +527,5 @@
     D3DKMDT_2DREGION *paResolutions;
     uint32_t cResolutions;
-    BOOLEAN fMatch;
+    BOOLEAN fMatched;
 } VBOXVIDPNMATCHMONMODESENUM, *PVBOXVIDPNMATCHMONMODESENUM;
 
@@ -535,20 +535,25 @@
     PVBOXVIDPNMATCHMONMODESENUM pInfo = (PVBOXVIDPNMATCHMONMODESENUM)pContext;
 
-    Assert(pInfo->fMatch);
+    Assert(pInfo->fMatched);
+
+    BOOLEAN fFound = FALSE;
 
     for (UINT i = 0; i < pInfo->cResolutions; ++i)
     {
         D3DKMDT_2DREGION *pResolution = &pInfo->paResolutions[i];
-        if (pMonitorSMI->VideoSignalInfo.ActiveSize.cx != pResolution->cx
-                || pMonitorSMI->VideoSignalInfo.ActiveSize.cy != pResolution->cy)
-        {
-            pInfo->fMatch = FALSE;
+        if (pMonitorSMI->VideoSignalInfo.ActiveSize.cx == pResolution->cx
+                && pMonitorSMI->VideoSignalInfo.ActiveSize.cy == pResolution->cy)
+        {
+            fFound = TRUE;
             break;
         }
     }
 
+    if (!fFound)
+        pInfo->fMatched = FALSE;
+
     pMonitorSMSIf->pfnReleaseModeInfo(hMonitorSMS, pMonitorSMI);
 
-    return pInfo->fMatch;
+    return pInfo->fMatched;
 }
 
@@ -585,14 +590,26 @@
     }
 
-    VBOXVIDPNMATCHMONMODESENUM Info;
-    Info.paResolutions = pResolutions;
-    Info.cResolutions = cResolutions;
-    Info.fMatch = TRUE;
-
-    Status = vboxVidPnEnumMonitorSourceModes(hMonitorSMS, pMonitorSMSIf, vboxFidPnMatchMonitorModesEnum, &Info);
+    /* we care only about monitor modes covering all needed resolutions,
+     * we do NOT care if resolutions do not cover some monitor modes */
+    SIZE_T cModes = 0;
+    Status = pMonitorSMSIf->pfnGetNumModes(hMonitorSMS, &cModes);
     if (NT_SUCCESS(Status))
     {
-        *pfMatch = Info.fMatch;
-    }
+        if (cModes < cResolutions)
+            *pfMatch = FALSE;
+        else
+        {
+            VBOXVIDPNMATCHMONMODESENUM Info;
+            Info.paResolutions = pResolutions;
+            Info.cResolutions = cResolutions;
+            Info.fMatched = TRUE;
+
+            Status = vboxVidPnEnumMonitorSourceModes(hMonitorSMS, pMonitorSMSIf, vboxFidPnMatchMonitorModesEnum, &Info);
+            if (NT_SUCCESS(Status))
+                *pfMatch = Info.fMatched;
+        }
+    }
+    else
+        WARN(("pfnGetNumModes failed, Status 0x%x", Status));
 
     NTSTATUS tmpStatus = pMonitorInterface->pfnReleaseMonitorSourceModeSet(pDevExt->u.primary.DxgkInterface.DeviceHandle, hMonitorSMS);
@@ -1299,5 +1316,4 @@
                     {
                         Status = vboxVidPnPopulateTargetModeInfoFromLegacy(pNewVidPnTargetModeInfo, pResolution, i == pInfo->iPreferredResolution);
-                        Assert(Status == STATUS_SUCCESS);
                         if (NT_SUCCESS(Status))
                         {
@@ -1309,4 +1325,12 @@
                                 continue;
                             }
+                            else
+                            {
+                                WARN(("pfnAddMode failed, Status 0x%x", Status));
+                            }
+                        }
+                        else
+                        {
+                            WARN(("vboxVidPnPopulateTargetModeInfoFromLegacy failed, Status 0x%x", Status));
                         }
 
@@ -1314,7 +1338,10 @@
                         Assert(tmpStatus == STATUS_SUCCESS);
                     }
+
                     /* we're here because of an error */
                     Assert(!NT_SUCCESS(Status));
-                    break;
+                    /* ignore mode addition failure */
+                    Status = STATUS_SUCCESS;
+                    continue;
                 }
             }
Index: /trunk/src/VBox/Additions/WINNT/Graphics/Video/mp/wddm/VBoxMPWddm.cpp
===================================================================
--- /trunk/src/VBox/Additions/WINNT/Graphics/Video/mp/wddm/VBoxMPWddm.cpp	(revision 42216)
+++ /trunk/src/VBox/Additions/WINNT/Graphics/Video/mp/wddm/VBoxMPWddm.cpp	(revision 42217)
@@ -681,9 +681,18 @@
 
         bChanged[i] = !fMatch;
-
-        if (!fMatch)
-        {
-            Status = vboxWddmChildStatusReportReconnected(pDevExt, i);
-            if (!NT_SUCCESS(Status))
+    }
+
+    if (!NT_SUCCESS(Status))
+    {
+        WARN(("updating monitor modes failed, Status(0x%x)", Status));
+        return Status;
+    }
+
+    for (i = 0; i < VBoxCommonFromDeviceExt(pDevExt)->cDisplays; ++i)
+    {
+        if (bChanged[i])
+        {
+            NTSTATUS tmpStatus = vboxWddmChildStatusReportReconnected(pDevExt, i);
+            if (!NT_SUCCESS(tmpStatus))
             {
                 WARN(("vboxWddmChildStatusReportReconnected failed Status(0x%x)", Status));
@@ -692,10 +701,4 @@
             }
         }
-    }
-
-    if (!NT_SUCCESS(Status))
-    {
-        WARN(("updating monitor modes failed, Status(0x%x)", Status));
-        return Status;
     }
 
@@ -1121,5 +1124,7 @@
 
                     VBoxMPCmnInitCustomVideoModes(pDevExt);
-                    VBoxWddmInvalidateVideoModesInfo(pDevExt);
+                    VBoxWddmInvalidateAllVideoModesInfos(pDevExt);
+
+                    pDevExt->fAnyX = VBoxVideoAnyWidthAllowed();
 #if 0
                     vboxShRcTreeInit(pDevExt);
@@ -4137,6 +4142,13 @@
             case VBOXESC_REINITVIDEOMODES:
             {
-                PVBOXWDDM_VIDEOMODES_INFO pInfo = VBoxWddmUpdateVideoModesInfo(pDevExt, NULL);
-                Status = vboxWddmChildStatusCheck(pDevExt, pInfo);
+                if (pEscape->Flags.HardwareAccess)
+                {
+                    WARN(("VBOXESC_REINITVIDEOMODES called with HardwareAccess flag set, failing"));
+                    Status = STATUS_INVALID_PARAMETER;
+                    break;
+                }
+                WARN(("VBOXESC_REINITVIDEOMODESBYMASK should be called instead"));
+                PVBOXWDDM_VIDEOMODES_INFO pInfos = VBoxWddmUpdateAllVideoModesInfos(pDevExt);
+                Status = vboxWddmChildStatusCheck(pDevExt, pInfos);
                 if (!NT_SUCCESS(Status))
                 {
@@ -4144,4 +4156,53 @@
                 }
                 break;
+            }
+            case VBOXESC_REINITVIDEOMODESBYMASK:
+            {
+                BOOLEAN fCheckDisplayRecconect = (pEscapeHdr->u32CmdSpecific & VBOXWDDM_REINITVIDEOMODESBYMASK_F_RECONNECT_DISPLAYS_ON_CHANGE);
+                if (fCheckDisplayRecconect && pEscape->Flags.HardwareAccess)
+                {
+                    WARN(("VBOXESC_REINITVIDEOMODESBYMASK called with HardwareAccess flag set, failing"));
+                    Status = STATUS_INVALID_PARAMETER;
+                    break;
+                }
+                if (pEscape->PrivateDriverDataSize != sizeof (VBOXDISPIFESCAPE_REINITVIDEOMODESBYMASK))
+                {
+                    WARN(("invalid private driver size %d", pEscape->PrivateDriverDataSize));
+                    Status = STATUS_INVALID_PARAMETER;
+                    break;
+                }
+                PVBOXDISPIFESCAPE_REINITVIDEOMODESBYMASK pData = (PVBOXDISPIFESCAPE_REINITVIDEOMODESBYMASK)pEscapeHdr;
+                PVBOXWDDM_VIDEOMODES_INFO pInfos = VBoxWddmUpdateVideoModesInfoByMask(pDevExt, pData->ScreenMask);
+                if (fCheckDisplayRecconect)
+                {
+                    Status = vboxWddmChildStatusCheck(pDevExt, pInfos);
+                    if (!NT_SUCCESS(Status))
+                    {
+                        WARN(("vboxWddmChildStatusCheck failed, Status 0x%x", Status));
+                    }
+                }
+                break;
+            }
+            case VBOXESC_ADJUSTVIDEOMODES:
+            {
+                if (!pEscape->Flags.HardwareAccess)
+                {
+                    WARN(("VBOXESC_ADJUSTVIDEOMODES called without HardwareAccess flag set, failing"));
+                    Status = STATUS_INVALID_PARAMETER;
+                    break;
+                }
+
+                uint32_t cModes = pEscapeHdr->u32CmdSpecific;
+                if (cModes > VBOXWDDM_TRAILARRAY_MAXELEMENTSU32(VBOXDISPIFESCAPE_ADJUSTVIDEOMODES, aScreenInfos)
+                        || pEscape->PrivateDriverDataSize != RT_OFFSETOF(VBOXDISPIFESCAPE_ADJUSTVIDEOMODES, aScreenInfos[cModes]))
+                {
+                    WARN(("invalid modes count passed"));
+                    Status = STATUS_INVALID_PARAMETER;
+                    break;
+                }
+
+                PVBOXDISPIFESCAPE_ADJUSTVIDEOMODES pPodesInfo = (PVBOXDISPIFESCAPE_ADJUSTVIDEOMODES)pEscapeHdr;
+                VBoxWddmAdjustModes(pDevExt, cModes, pPodesInfo->aScreenInfos);
+                Status = STATUS_SUCCESS;
             }
             case VBOXESC_SHRC_ADDREF:
@@ -4394,5 +4455,5 @@
     PVBOXWDDM_RECOMMENDVIDPN pVidPnInfo = pRecommendFunctionalVidPnArg->PrivateDriverDataSize >= sizeof (VBOXWDDM_RECOMMENDVIDPN) ?
             (PVBOXWDDM_RECOMMENDVIDPN)pRecommendFunctionalVidPnArg->pPrivateDriverData : NULL;
-    PVBOXWDDM_VIDEOMODES_INFO pInfos = VBoxWddmUpdateVideoModesInfo(pDevExt, NULL /*pVidPnInfo*/);
+    PVBOXWDDM_VIDEOMODES_INFO pInfos = VBoxWddmUpdateAllVideoModesInfos(pDevExt);
     int i;
 
@@ -4410,8 +4471,7 @@
         Status = vboxVidPnCheckAddMonitorModes(pDevExt, i, D3DKMDT_MCO_DRIVER, pInfo->aResolutions, pInfo->cResolutions, pInfo->iPreferredResolution);
 #endif
-        Assert(Status == STATUS_SUCCESS);
         if (Status != STATUS_SUCCESS)
         {
-            LOGREL(("vboxVidPnCheckAddMonitorModes failed Status(0x%x)", Status));
+            WARN(("vboxVidPnCheckAddMonitorModes failed Status(0x%x)", Status));
             break;
         }
Index: /trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxDispIf.cpp
===================================================================
--- /trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxDispIf.cpp	(revision 42216)
+++ /trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxDispIf.cpp	(revision 42217)
@@ -23,4 +23,8 @@
 #include <malloc.h>
 
+#ifdef VBOX_WITH_WDDM
+#include <iprt/asm.h>
+#endif
+
 /* display driver interface abstraction for XPDM & WDDM
  * with WDDM we can not use ExtEscape to communicate with our driver
@@ -33,6 +37,18 @@
 }
 
+#ifdef VBOX_WITH_WDDM
+static void vboxDispIfWddmTerm(PCVBOXDISPIF pIf);
+static DWORD vboxDispIfWddmInit(PCVBOXDISPIF pIf);
+#endif
+
 DWORD VBoxDispIfTerm(PVBOXDISPIF pIf)
 {
+#ifdef VBOX_WITH_WDDM
+    if (pIf->enmMode == VBOXDISPIF_MODE_WDDM)
+    {
+        vboxDispIfWddmTerm(pIf);
+    }
+#endif
+
     pIf->enmMode = VBOXDISPIF_MODE_UNKNOWN;
     return NO_ERROR;
@@ -123,4 +139,9 @@
         Log((__FUNCTION__": can not switch to VBOXDISPIF_MODE_WDDM, because os is not Vista or upper\n"));
         err = ERROR_NOT_SUPPORTED;
+    }
+
+    if (err == ERROR_SUCCESS)
+    {
+        err = vboxDispIfWddmInit(pIf);
     }
 
@@ -366,5 +387,345 @@
 }
 
-static BOOL vboxDispIfValidateResize(DISPLAY_DEVICE *paDisplayDevices, DEVMODE *paDeviceModes, UINT cDevModes)
+
+#ifdef VBOX_WITH_WDDM
+/**/
+typedef DECLCALLBACK(VOID) FNVBOXSCREENMONRUNNER_CB(void *pvCb);
+typedef FNVBOXSCREENMONRUNNER_CB *PFNVBOXSCREENMONRUNNER_CB;
+
+typedef struct VBOXSCREENMON
+{
+    HANDLE hThread;
+    DWORD idThread;
+    HANDLE hEvent;
+    HWND hWnd;
+    PFNVBOXSCREENMONRUNNER_CB pfnCb;
+    void *pvCb;
+} VBOXSCREENMON, *PVBOXSCREENMON;
+
+
+static VBOXSCREENMON g_VBoxScreenMon;
+
+
+#define VBOX_E_INSUFFICIENT_BUFFER HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER)
+#define VBOX_E_NOT_SUPPORTED HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED)
+
+
+static void vboxScreenMonOnChange()
+{
+    PVBOXSCREENMON pMon = &g_VBoxScreenMon;
+    pMon->pfnCb(pMon->pvCb);
+}
+
+static LRESULT CALLBACK vboxScreenMonWndProc(HWND hwnd,
+    UINT uMsg,
+    WPARAM wParam,
+    LPARAM lParam
+)
+{
+    switch(uMsg)
+    {
+        case WM_DISPLAYCHANGE:
+        {
+            vboxScreenMonOnChange();
+        }
+        case WM_CLOSE:
+            Log((__FUNCTION__": got WM_CLOSE for hwnd(0x%x)", hwnd));
+            return 0;
+        case WM_DESTROY:
+            Log((__FUNCTION__": got WM_DESTROY for hwnd(0x%x)", hwnd));
+            return 0;
+        case WM_NCHITTEST:
+            Log((__FUNCTION__": got WM_NCHITTEST for hwnd(0x%x)\n", hwnd));
+            return HTNOWHERE;
+    }
+
+    return DefWindowProc(hwnd, uMsg, wParam, lParam);
+}
+
+#define VBOXSCREENMONWND_NAME "VboxScreenMonWnd"
+
+static HRESULT vboxScreenMonWndCreate(HWND *phWnd)
+{
+    HRESULT hr = S_OK;
+    HINSTANCE hInstance = (HINSTANCE)GetModuleHandle(NULL);
+    /* Register the Window Class. */
+    WNDCLASS wc;
+    if (!GetClassInfo(hInstance, VBOXSCREENMONWND_NAME, &wc))
+    {
+        wc.style = 0;//CS_OWNDC;
+        wc.lpfnWndProc = vboxScreenMonWndProc;
+        wc.cbClsExtra = 0;
+        wc.cbWndExtra = 0;
+        wc.hInstance = hInstance;
+        wc.hIcon = NULL;
+        wc.hCursor = NULL;
+        wc.hbrBackground = NULL;
+        wc.lpszMenuName = NULL;
+        wc.lpszClassName = VBOXSCREENMONWND_NAME;
+        if (!RegisterClass(&wc))
+        {
+            DWORD winErr = GetLastError();
+            Log((__FUNCTION__": RegisterClass failed, winErr(%d)\n", winErr));
+            hr = E_FAIL;
+        }
+    }
+
+    if (hr == S_OK)
+    {
+        HWND hWnd = CreateWindowEx (WS_EX_TOOLWINDOW,
+                                        VBOXSCREENMONWND_NAME, VBOXSCREENMONWND_NAME,
+                                        WS_POPUP | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_DISABLED,
+                                        -100, -100,
+                                        10, 10,
+                                        NULL, //GetDesktopWindow() /* hWndParent */,
+                                        NULL /* hMenu */,
+                                        hInstance,
+                                        NULL /* lpParam */);
+        Assert(hWnd);
+        if (hWnd)
+        {
+            *phWnd = hWnd;
+        }
+        else
+        {
+            DWORD winErr = GetLastError();
+            Log((__FUNCTION__": CreateWindowEx failed, winErr(%d)\n", winErr));
+            hr = E_FAIL;
+        }
+    }
+
+    return hr;
+}
+
+static HRESULT vboxScreenMonWndDestroy(HWND hWnd)
+{
+    BOOL bResult = DestroyWindow(hWnd);
+    if (bResult)
+        return S_OK;
+
+    DWORD winErr = GetLastError();
+    Log((__FUNCTION__": DestroyWindow failed, winErr(%d) for hWnd(0x%x)\n", winErr, hWnd));
+    Assert(0);
+
+    return HRESULT_FROM_WIN32(winErr);
+}
+
+static HRESULT vboxScreenMonWndInit()
+{
+    PVBOXSCREENMON pMon = &g_VBoxScreenMon;
+    return vboxScreenMonWndCreate(&pMon->hWnd);
+}
+
+HRESULT vboxScreenMonWndTerm()
+{
+    PVBOXSCREENMON pMon = &g_VBoxScreenMon;
+    HRESULT tmpHr = vboxScreenMonWndDestroy(pMon->hWnd);
+    Assert(tmpHr == S_OK);
+
+    HINSTANCE hInstance = (HINSTANCE)GetModuleHandle(NULL);
+    UnregisterClass(VBOXSCREENMONWND_NAME, hInstance);
+
+    return S_OK;
+}
+
+#define WM_VBOXSCREENMON_INIT_QUIT (WM_APP+2)
+
+HRESULT vboxScreenMonRun()
+{
+    PVBOXSCREENMON pMon = &g_VBoxScreenMon;
+    MSG Msg;
+
+    HRESULT hr = S_FALSE;
+
+    PeekMessage(&Msg,
+            NULL /* HWND hWnd */,
+            WM_USER /* UINT wMsgFilterMin */,
+            WM_USER /* UINT wMsgFilterMax */,
+            PM_NOREMOVE);
+
+    BOOL bCheck = TRUE;
+
+    do
+    {
+        if (bCheck)
+        {
+            vboxScreenMonOnChange();
+
+            bCheck = FALSE;
+        }
+
+        BOOL bResult = GetMessage(&Msg,
+            0 /*HWND hWnd*/,
+            0 /*UINT wMsgFilterMin*/,
+            0 /*UINT wMsgFilterMax*/
+            );
+
+        if(!bResult) /* WM_QUIT was posted */
+        {
+            hr = S_FALSE;
+            break;
+        }
+
+        if(bResult == -1) /* error occurred */
+        {
+            DWORD winEr = GetLastError();
+            hr = HRESULT_FROM_WIN32(winEr);
+            Assert(0);
+            /* just ensure we never return success in this case */
+            Assert(hr != S_OK);
+            Assert(hr != S_FALSE);
+            if (hr == S_OK || hr == S_FALSE)
+                hr = E_FAIL;
+            break;
+        }
+
+        switch (Msg.message)
+        {
+            case WM_VBOXSCREENMON_INIT_QUIT:
+            case WM_CLOSE:
+            {
+                PostQuitMessage(0);
+                break;
+            }
+            case WM_DISPLAYCHANGE:
+                bCheck = TRUE;
+            default:
+                TranslateMessage(&Msg);
+                DispatchMessage(&Msg);
+                break;
+        }
+    } while (1);
+    return 0;
+}
+
+static DWORD WINAPI vboxScreenMonRunnerThread(void *pvUser)
+{
+    PVBOXSCREENMON pMon = &g_VBoxScreenMon;
+
+    BOOL bRc = SetEvent(pMon->hEvent);
+    if (!bRc)
+    {
+        DWORD winErr = GetLastError();
+        Log((__FUNCTION__": SetEvent failed, winErr = (%d)", winErr));
+        HRESULT tmpHr = HRESULT_FROM_WIN32(winErr);
+        Assert(0);
+        Assert(tmpHr != S_OK);
+    }
+
+    HRESULT hr = vboxScreenMonWndInit();
+    Assert(hr == S_OK);
+    if (hr == S_OK)
+    {
+        hr = vboxScreenMonRun();
+        Assert(hr == S_OK);
+
+        vboxScreenMonWndTerm();
+    }
+
+    return 0;
+}
+
+HRESULT VBoxScreenMonInit(PFNVBOXSCREENMONRUNNER_CB pfnCb, void *pvCb)
+{
+    HRESULT hr = E_FAIL;
+    PVBOXSCREENMON pMon = &g_VBoxScreenMon;
+    memset(pMon, 0, sizeof (*pMon));
+
+    pMon->pfnCb = pfnCb;
+    pMon->pvCb = pvCb;
+
+    pMon->hEvent = CreateEvent(NULL, /* LPSECURITY_ATTRIBUTES lpEventAttributes*/
+            TRUE, /* BOOL bManualReset*/
+            FALSE, /* BOOL bInitialState */
+            NULL /* LPCTSTR lpName */
+          );
+    if (pMon->hEvent)
+    {
+        pMon->hThread = CreateThread(NULL /* LPSECURITY_ATTRIBUTES lpThreadAttributes */,
+                                              0 /* SIZE_T dwStackSize */,
+                                              vboxScreenMonRunnerThread,
+                                              pMon,
+                                              0 /* DWORD dwCreationFlags */,
+                                              &pMon->idThread);
+        if (pMon->hThread)
+        {
+            DWORD dwResult = WaitForSingleObject(pMon->hEvent, INFINITE);
+            if (dwResult == WAIT_OBJECT_0)
+                return S_OK;
+            else
+            {
+                Log(("WaitForSingleObject failed!"));
+                hr = E_FAIL;
+            }
+        }
+        else
+        {
+            DWORD winErr = GetLastError();
+            Log((__FUNCTION__": CreateThread failed, winErr = (%d)", winErr));
+            hr = HRESULT_FROM_WIN32(winErr);
+            Assert(0);
+            Assert(hr != S_OK);
+        }
+        CloseHandle(pMon->hEvent);
+    }
+    else
+    {
+        DWORD winErr = GetLastError();
+        Log((__FUNCTION__": CreateEvent failed, winErr = (%d)", winErr));
+        hr = HRESULT_FROM_WIN32(winErr);
+        Assert(0);
+        Assert(hr != S_OK);
+    }
+
+    return hr;
+}
+
+VOID VBoxScreenMonTerm()
+{
+    HRESULT hr;
+    PVBOXSCREENMON pMon = &g_VBoxScreenMon;
+    if (!pMon->hThread)
+        return;
+
+    BOOL bResult = PostThreadMessage(pMon->idThread, WM_VBOXSCREENMON_INIT_QUIT, 0, 0);
+    DWORD winErr;
+    if (bResult
+            || (winErr = GetLastError()) == ERROR_INVALID_THREAD_ID) /* <- could be that the thread is terminated */
+    {
+        DWORD dwErr = WaitForSingleObject(pMon->hThread, INFINITE);
+        if (dwErr == WAIT_OBJECT_0)
+        {
+            hr = S_OK;
+        }
+        else
+        {
+            winErr = GetLastError();
+            hr = HRESULT_FROM_WIN32(winErr);
+            Assert(0);
+        }
+    }
+    else
+    {
+        hr = HRESULT_FROM_WIN32(winErr);
+        Assert(0);
+    }
+
+    CloseHandle(pMon->hThread);
+    pMon->hThread = 0;
+    CloseHandle(pMon->hEvent);
+    pMon->hThread = 0;
+}
+/**/
+
+typedef struct VBOXDISPIF_WDDM_INTERNAL
+{
+    PCVBOXDISPIF pIf;
+
+    HANDLE hResizeEvent;
+} VBOXDISPIF_WDDM_INTERNAL, *PVBOXDISPIF_WDDM_INTERNAL;
+
+static VBOXDISPIF_WDDM_INTERNAL g_VBoxDispIfWddm;
+
+static BOOL vboxDispIfWddmValidateResize(DISPLAY_DEVICE *paDisplayDevices, DEVMODE *paDeviceModes, UINT cDevModes)
 {
     DISPLAY_DEVICE DisplayDevice;
@@ -463,12 +824,118 @@
 }
 
-#ifdef VBOX_WITH_WDDM
-static DWORD vboxDispIfReinitVideoModes(PCVBOXDISPIF const pIf)
-{
-    VBOXDISPIFESCAPE escape = {0};
-    escape.escapeCode = VBOXESC_REINITVIDEOMODES;
-    DWORD err = vboxDispIfEscapeWDDM(pIf, &escape, 0, FALSE /* hw access must be false here,
+static DWORD vboxDispIfWddmValidateFixResize(PCVBOXDISPIF const pIf, DISPLAY_DEVICE *paDisplayDevices, DEVMODE *paDeviceModes, UINT cDevModes)
+{
+    if (vboxDispIfWddmValidateResize(paDisplayDevices, paDeviceModes, cDevModes))
+        return NO_ERROR;
+
+    DWORD winEr;
+    LONG status = DISP_CHANGE_SUCCESSFUL;
+
+    /* now try to resize in a "regular" way */
+    /* Assign the new rectangles to displays. */
+    for (UINT i = 0; i < cDevModes; i++)
+    {
+        /* On Vista one must specify DM_BITSPERPEL.
+         * Note that the current mode dmBitsPerPel is already in the DEVMODE structure.
+         */
+        paDeviceModes[i].dmFields = DM_POSITION | DM_PELSHEIGHT | DM_PELSWIDTH | DM_BITSPERPEL;
+
+        Log(("VBoxTray: ResizeDisplayDevice: pfnChangeDisplaySettingsEx %x: %dx%dx%d at %d,%d\n",
+                pIf->modeData.wddm.pfnChangeDisplaySettingsEx,
+              paDeviceModes[i].dmPelsWidth,
+              paDeviceModes[i].dmPelsHeight,
+              paDeviceModes[i].dmBitsPerPel,
+              paDeviceModes[i].dmPosition.x,
+              paDeviceModes[i].dmPosition.y));
+
+        /* the miniport might have been adjusted the display mode stuff,
+         * adjust the paDeviceModes[i] by picking the closest available one */
+//        DEVMODE AdjustedMode = paDeviceModes[i];
+//        vboxDispIfAdjustMode(&paDisplayDevices[i], &AdjustedMode);
+
+        LONG tmpStatus = pIf->modeData.wddm.pfnChangeDisplaySettingsEx((LPSTR)paDisplayDevices[i].DeviceName,
+                                        &paDeviceModes[i], NULL, CDS_NORESET | CDS_UPDATEREGISTRY, NULL);
+        Log(("VBoxTray: ResizeDisplayDevice: ChangeDisplaySettingsEx position status %d, err %d\n", tmpStatus, GetLastError ()));
+
+        if (tmpStatus != DISP_CHANGE_SUCCESSFUL)
+        {
+            status = tmpStatus;
+        }
+    }
+
+    /* A second call to ChangeDisplaySettings updates the monitor. */
+    LONG tmpStatus = pIf->modeData.wddm.pfnChangeDisplaySettingsEx(NULL, NULL, NULL, 0, NULL);
+    Log(("VBoxTray: ResizeDisplayDevice: ChangeDisplaySettings update status %d\n", status));
+    if (tmpStatus == DISP_CHANGE_SUCCESSFUL)
+    {
+        if (status == DISP_CHANGE_SUCCESSFUL)
+        {
+            return NO_ERROR;
+        }
+        tmpStatus = status;
+    }
+
+    if (tmpStatus == DISP_CHANGE_BADMODE)
+    {
+        /* Successfully set new video mode or our driver can not set the requested mode. Stop trying. */
+        winEr = ERROR_RETRY;
+    }
+    else
+    {
+        winEr = ERROR_GEN_FAILURE;
+    }
+    return winEr;
+}
+
+static DECLCALLBACK(VOID) vboxDispIfWddmScreenMonCb(void *pvCb)
+{
+    PVBOXDISPIF_WDDM_INTERNAL pData = (PVBOXDISPIF_WDDM_INTERNAL)pvCb;
+
+    SetEvent(pData->hResizeEvent);
+}
+
+static DWORD vboxDispIfWddmInit(PCVBOXDISPIF pIf)
+{
+    memset(&g_VBoxDispIfWddm, 0, sizeof (g_VBoxDispIfWddm));
+    g_VBoxDispIfWddm.pIf = pIf;
+    g_VBoxDispIfWddm.hResizeEvent = CreateEvent(NULL,
+                FALSE, /* BOOL bManualReset */
+                FALSE, /* BOOL bInitialState */
+                NULL /* LPCTSTR lpName */
+          );
+    if (g_VBoxDispIfWddm.hResizeEvent)
+    {
+        HRESULT hr = VBoxScreenMonInit(vboxDispIfWddmScreenMonCb, &g_VBoxDispIfWddm);
+        if (SUCCEEDED(hr))
+        {
+            /* ensure event is reset */
+            WaitForSingleObject(g_VBoxDispIfWddm.hResizeEvent, 0);
+            return ERROR_SUCCESS;
+        }
+        CloseHandle(g_VBoxDispIfWddm.hResizeEvent);
+    }
+    return ERROR_GEN_FAILURE;
+}
+
+static void vboxDispIfWddmTerm(PCVBOXDISPIF pIf)
+{
+    VBoxScreenMonTerm();
+    CloseHandle(g_VBoxDispIfWddm.hResizeEvent);
+    memset(&g_VBoxDispIfWddm, 0, sizeof (g_VBoxDispIfWddm));
+}
+
+static DWORD vboxDispIfReninitModesWDDM(PCVBOXDISPIF const pIf, uint8_t *pScreenIdMask, BOOL fReconnectDisplaysOnChange)
+{
+    VBOXDISPIFESCAPE_REINITVIDEOMODESBYMASK Data = {0};
+    Data.EscapeHdr.escapeCode = VBOXESC_REINITVIDEOMODESBYMASK;
+    if (fReconnectDisplaysOnChange)
+        Data.EscapeHdr.u32CmdSpecific = VBOXWDDM_REINITVIDEOMODESBYMASK_F_RECONNECT_DISPLAYS_ON_CHANGE;
+
+    memcpy(Data.ScreenMask, pScreenIdMask, sizeof (Data.ScreenMask));
+
+    DWORD err = vboxDispIfEscapeWDDM(pIf, &Data.EscapeHdr, sizeof (Data) - sizeof (Data.EscapeHdr), fReconnectDisplaysOnChange ? FALSE /* hw access must be false here,
                                                              * otherwise the miniport driver would fail
-                                                             * request to prevent a deadlock */);
+                                                             * request to prevent a deadlock */
+                                                        : TRUE);
     if (err != NO_ERROR)
     {
@@ -532,5 +999,22 @@
 }
 
-DWORD vboxDispIfResizeModesWDDM(PCVBOXDISPIF const pIf, DISPLAY_DEVICE *paDisplayDevices, DEVMODE *paDeviceModes, UINT cDevModes)
+static DWORD vboxDispIfAdjustModeValues(PCVBOXDISPIF const pIf, DISPLAY_DEVICE *pDisplayDevice, DEVMODE *pDeviceMode)
+{
+    VBOXDISPIFESCAPE_ADJUSTVIDEOMODES Data = {0};
+    Data.EscapeHdr.escapeCode = VBOXESC_REINITVIDEOMODESBYMASK;
+    Data.EscapeHdr.u32CmdSpecific = 1;
+    Data.aScreenInfos[0].Mode.Id =
+    Data.aScreenInfos[0].Mode.Width = pDeviceMode->dmPelsWidth;
+    Data.aScreenInfos[0].Mode.Height = pDeviceMode->dmPelsHeight;
+    Data.aScreenInfos[0].Mode.BitsPerPixel = pDeviceMode->dmBitsPerPel;
+    DWORD err = vboxDispIfEscapeWDDM(pIf, &Data.EscapeHdr, sizeof (Data) - sizeof (Data.EscapeHdr), TRUE);
+    if (err != NO_ERROR)
+    {
+        Log((__FUNCTION__": VBoxDispIfEscape failed with err (%d)\n", err));
+    }
+    return err;
+}
+
+DWORD vboxDispIfResizeModesWDDM(PCVBOXDISPIF const pIf, UINT iChangedMode, DISPLAY_DEVICE *paDisplayDevices, DEVMODE *paDeviceModes, UINT cDevModes)
 {
     UINT cbVidPnInfo = VBOXWDDM_RECOMMENDVIDPN_SIZE(cDevModes);
@@ -614,65 +1098,35 @@
     }
 
-    if (!fAbleToInvalidateVidPn)
-    {
-        /* fallback impl: make the driver invalidate VidPn,
+//    for (i = 0; i < cDevModes; i++)
+//    {
+//        vboxDispIfAdjustMode(&paDisplayDevices[i], &paDeviceModes[i]);
+//    }
+
+    if (fAbleToInvalidateVidPn)
+    {
+        winEr = vboxDispIfWddmValidateFixResize(pIf, paDisplayDevices, paDeviceModes, cDevModes);
+    }
+    else
+    {
+        /* fallback impl needed for display-only driver
+         * since D3DKMTInvalidateActiveVidPn is not available for WDDM > 1.0:
+         * make the driver invalidate VidPn,
          * which is done by emulating a monitor re-plug currently */
-        vboxDispIfReinitVideoModes(pIf);
-
-        /* sleep 2 seconds: dirty hack to wait for the new monitor info to be picked up,
-         * @todo: implement it properly by monitoring monitor device arrival/removal */
-        Sleep(2 * 1000);
-    }
-
-    /* ignore any prev errors and just check if resize is OK */
-    if (!vboxDispIfValidateResize(paDisplayDevices, paDeviceModes, cDevModes))
-    {
-        /* now try to resize in a "regular" way */
-        /* Assign the new rectangles to displays. */
-        for (i = 0; i < cDevModes; i++)
-        {
-            /* On Vista one must specify DM_BITSPERPEL.
-             * Note that the current mode dmBitsPerPel is already in the DEVMODE structure.
-             */
-            paDeviceModes[i].dmFields = DM_POSITION | DM_PELSHEIGHT | DM_PELSWIDTH | DM_BITSPERPEL;
-
-            Log(("VBoxTray: ResizeDisplayDevice: pfnChangeDisplaySettingsEx %x: %dx%dx%d at %d,%d\n",
-                    pIf->modeData.wddm.pfnChangeDisplaySettingsEx,
-                  paDeviceModes[i].dmPelsWidth,
-                  paDeviceModes[i].dmPelsHeight,
-                  paDeviceModes[i].dmBitsPerPel,
-                  paDeviceModes[i].dmPosition.x,
-                  paDeviceModes[i].dmPosition.y));
-
-            /* the miniport might have been adjusted the display mode stuff,
-             * adjust the paDeviceModes[i] by picking the closest available one */
-            DEVMODE AdjustedMode = paDeviceModes[i];
-            vboxDispIfAdjustMode(&paDisplayDevices[i], &AdjustedMode);
-
-            LONG status = pIf->modeData.wddm.pfnChangeDisplaySettingsEx((LPSTR)paDisplayDevices[i].DeviceName,
-                                            &AdjustedMode, NULL, CDS_NORESET | CDS_UPDATEREGISTRY, NULL);
-            Log(("VBoxTray: ResizeDisplayDevice: ChangeDisplaySettingsEx position status %d, err %d\n", status, GetLastError ()));
-        }
-
-        /* A second call to ChangeDisplaySettings updates the monitor. */
-        LONG status = pIf->modeData.wddm.pfnChangeDisplaySettingsEx(NULL, NULL, NULL, 0, NULL);
-        Log(("VBoxTray: ResizeDisplayDevice: ChangeDisplaySettings update status %d\n", status));
-        if (status == DISP_CHANGE_SUCCESSFUL)
-        {
-            winEr = NO_ERROR;
-        }
-        else if (status == DISP_CHANGE_BADMODE)
-        {
-            /* Successfully set new video mode or our driver can not set the requested mode. Stop trying. */
-            winEr = ERROR_RETRY;
-        }
-        else
-        {
-            winEr = ERROR_GEN_FAILURE;
-        }
-    }
-    else
-    {
-        winEr = NO_ERROR;
+        /* ensure event is reset */
+        WaitForSingleObject(g_VBoxDispIfWddm.hResizeEvent, 0);
+
+        uint8_t ScreenMask[VBOXWDDM_SCREENMASK_SIZE] = {0};
+        ASMBitSet(ScreenMask, iChangedMode);
+        vboxDispIfReninitModesWDDM(pIf, ScreenMask, TRUE);
+
+        for (UINT i = 0; i < 4; ++i)
+        {
+            WaitForSingleObject(g_VBoxDispIfWddm.hResizeEvent, 500);
+            winEr = vboxDispIfWddmValidateFixResize(pIf, paDisplayDevices, paDeviceModes, cDevModes);
+            if (winEr == NO_ERROR)
+                break;
+        }
+
+        Assert(winEr == NO_ERROR);
     }
 
@@ -681,5 +1135,5 @@
 #endif /* VBOX_WITH_WDDM */
 
-DWORD VBoxDispIfResizeModes(PCVBOXDISPIF const pIf, DISPLAY_DEVICE *paDisplayDevices, DEVMODE *paDeviceModes, UINT cDevModes)
+DWORD VBoxDispIfResizeModes(PCVBOXDISPIF const pIf, UINT iChangedMode, DISPLAY_DEVICE *paDisplayDevices, DEVMODE *paDeviceModes, UINT cDevModes)
 {
     switch (pIf->enmMode)
@@ -691,5 +1145,23 @@
 #ifdef VBOX_WITH_WDDM
         case VBOXDISPIF_MODE_WDDM:
-            return vboxDispIfResizeModesWDDM(pIf, paDisplayDevices, paDeviceModes, cDevModes);
+            return vboxDispIfResizeModesWDDM(pIf, iChangedMode, paDisplayDevices, paDeviceModes, cDevModes);
+#endif
+        default:
+            Log((__FUNCTION__": unknown mode (%d)\n", pIf->enmMode));
+            return ERROR_INVALID_PARAMETER;
+    }
+}
+
+DWORD VBoxDispIfReninitModes(PCVBOXDISPIF const pIf, uint8_t *pScreenIdMask, BOOL fReconnectDisplaysOnChange)
+{
+    switch (pIf->enmMode)
+    {
+        case VBOXDISPIF_MODE_XPDM_NT4:
+            return ERROR_NOT_SUPPORTED;
+        case VBOXDISPIF_MODE_XPDM:
+            return ERROR_NOT_SUPPORTED;
+#ifdef VBOX_WITH_WDDM
+        case VBOXDISPIF_MODE_WDDM:
+            return vboxDispIfReninitModesWDDM(pIf, pScreenIdMask, fReconnectDisplaysOnChange);
 #endif
         default:
@@ -750,5 +1222,12 @@
 
     if (enmMode == pIf->enmMode)
-        return VINF_ALREADY_INITIALIZED;
+        return NO_ERROR;
+
+#ifdef VBOX_WITH_WDDM
+    if (pIf->enmMode == VBOXDISPIF_MODE_WDDM)
+    {
+        vboxDispIfWddmTerm(pIf);
+    }
+#endif
 
     DWORD err = NO_ERROR;
Index: /trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxDispIf.h
===================================================================
--- /trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxDispIf.h	(revision 42216)
+++ /trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxDispIf.h	(revision 42217)
@@ -84,3 +84,4 @@
 DWORD VBoxDispIfEscape(PCVBOXDISPIF const pIf, PVBOXDISPIFESCAPE pEscape, int cbData);
 DWORD VBoxDispIfResize(PCVBOXDISPIF const pIf, ULONG Id, DWORD Width, DWORD Height, DWORD BitsPerPixel);
-DWORD VBoxDispIfResizeModes(PCVBOXDISPIF const pIf, DISPLAY_DEVICE *paDisplayDevices, DEVMODE *paDeviceModes, UINT cDevModes);
+DWORD VBoxDispIfResizeModes(PCVBOXDISPIF const pIf, UINT iChangedMode, DISPLAY_DEVICE *paDisplayDevices, DEVMODE *paDeviceModes, UINT cDevModes);
+//DWORD VBoxDispIfReninitModes(PCVBOXDISPIF const pIf, uint8_t *pScreenIdMask, BOOL fReconnectDisplaysOnChange);
Index: /trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxDisplay.cpp
===================================================================
--- /trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxDisplay.cpp	(revision 42216)
+++ /trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxDisplay.cpp	(revision 42217)
@@ -26,4 +26,7 @@
 #include <malloc.h>
 #include <VBoxGuestInternal.h>
+#ifdef VBOX_WITH_WDDM
+#include <iprt/asm.h>
+#endif
 
 typedef struct _VBOXDISPLAYCONTEXT
@@ -407,5 +410,5 @@
         }
 
-        DWORD err = VBoxDispIfResizeModes(&pCtx->pEnv->dispIf, paDisplayDevices, paDeviceModes, NumDevices);
+        DWORD err = VBoxDispIfResizeModes(&pCtx->pEnv->dispIf, Id, paDisplayDevices, paDeviceModes, NumDevices);
         if (err == NO_ERROR || err != ERROR_RETRY)
         {
Index: /trunk/src/VBox/Additions/WINNT/include/VBoxDisplay.h
===================================================================
--- /trunk/src/VBox/Additions/WINNT/include/VBoxDisplay.h	(revision 42216)
+++ /trunk/src/VBox/Additions/WINNT/include/VBoxDisplay.h	(revision 42217)
@@ -35,20 +35,9 @@
 # define VBOXESC_CRHGSMICTLCON_CALL         0xABCD900E
 # define VBOXESC_CRHGSMICTLCON_GETCLIENTID  0xABCD900F
+# define VBOXESC_REINITVIDEOMODESBYMASK     0xABCD9010
+# define VBOXESC_ADJUSTVIDEOMODES           0xABCD9011
 
-typedef struct
-{
-    DWORD Id;
-    DWORD Width;
-    DWORD Height;
-    DWORD BitsPerPixel;
-} VBOXWDDM_RECOMMENDVIDPN_SCREEN_INFO, *PVBOXWDDM_RECOMMENDVIDPN_SCREEN_INFO;
-
-typedef struct
-{
-    uint32_t cScreenInfos;
-    VBOXWDDM_RECOMMENDVIDPN_SCREEN_INFO aScreenInfos[1];
-} VBOXWDDM_RECOMMENDVIDPN, *PVBOXWDDM_RECOMMENDVIDPN;
-
-#define VBOXWDDM_RECOMMENDVIDPN_SIZE(_c) (RT_OFFSETOF(VBOXWDDM_RECOMMENDVIDPN, aScreenInfos[_c]))
+/* for VBOX_VIDEO_MAX_SCREENS definition */
+#include <VBox/Hardware/VBoxVideoVBE.h>
 
 #endif /* #ifdef VBOX_WITH_WDDM */
@@ -71,3 +60,54 @@
     CTL_CODE(FILE_DEVICE_VIDEO, 0xA01, METHOD_BUFFERED, FILE_ANY_ACCESS)
 
+#ifdef VBOX_WITH_WDDM
+
+typedef struct
+{
+    DWORD Id;
+    DWORD Width;
+    DWORD Height;
+    DWORD BitsPerPixel;
+} VBOXWDDM_RECOMMENDVIDPN_SCREEN_INFO, *PVBOXWDDM_RECOMMENDVIDPN_SCREEN_INFO;
+
+typedef struct
+{
+    uint32_t cScreenInfos;
+    VBOXWDDM_RECOMMENDVIDPN_SCREEN_INFO aScreenInfos[1];
+} VBOXWDDM_RECOMMENDVIDPN, *PVBOXWDDM_RECOMMENDVIDPN;
+
+#define VBOXWDDM_RECOMMENDVIDPN_SIZE(_c) (RT_OFFSETOF(VBOXWDDM_RECOMMENDVIDPN, aScreenInfos[_c]))
+
+/* the mode was adjusted */
+#define VBOXWDDM_ADJUSTVIDEOMODE_F_ADJUSTED       0x00000001
+/* the mode is the currently active one */
+#define VBOXWDDM_ADJUSTVIDEOMODE_F_CURRENT        0x00000002
+/* the mode is unsupported */
+#define VBOXWDDM_ADJUSTVIDEOMODE_F_UNSUPPORTED    0x00000004
+/* invalid screen id */
+#define VBOXWDDM_ADJUSTVIDEOMODE_F_INVALISCREENID 0x00000008
+
+typedef struct VBOXWDDM_ADJUSTVIDEOMODE
+{
+    uint32_t fFlags;
+    VBOXWDDM_RECOMMENDVIDPN_SCREEN_INFO Mode;
+} VBOXWDDM_ADJUSTVIDEOMODE, *PVBOXWDDM_ADJUSTVIDEOMODE;
+
+typedef struct VBOXDISPIFESCAPE_ADJUSTVIDEOMODES
+{
+    VBOXDISPIFESCAPE EscapeHdr;
+    VBOXWDDM_ADJUSTVIDEOMODE aScreenInfos[1];
+} VBOXDISPIFESCAPE_ADJUSTVIDEOMODES, *PVBOXDISPIFESCAPE_ADJUSTVIDEOMODES;
+
+#define VBOXWDDM_REINITVIDEOMODESBYMASK_F_RECONNECT_DISPLAYS_ON_CHANGE 0x00000001
+
+#define VBOXWDDM_SCREENMASK_SIZE ((VBOX_VIDEO_MAX_SCREENS + 7) >> 3)
+
+typedef struct VBOXDISPIFESCAPE_REINITVIDEOMODESBYMASK
+{
+    VBOXDISPIFESCAPE EscapeHdr;
+    uint8_t ScreenMask[VBOXWDDM_SCREENMASK_SIZE];
+} VBOXDISPIFESCAPE_REINITVIDEOMODESBYMASK, *PVBOXDISPIFESCAPE_REINITVIDEOMODESBYMASK;
+
+#endif /* VBOX_WITH_WDDM */
+
 #endif /* __VBoxDisplay_h__ */
