_Out_ PDEVMODEW *pSelectedMode,
_In_ BOOL bSearchClosestMode)
{
+ DEVMODEW dmSearch;
PDEVMODEW pdmCurrent, pdm, pdmSelected = NULL;
ULONG i;
- DWORD dwFields;
+ ULONG ulVirtualWidth = 0, ulVirtualHeight = 0;
+ BOOL bResult = TRUE;
+ NTSTATUS Status;
if (!LDEVOBJ_bBuildDevmodeList(pGraphicsDevice))
return FALSE;
- if (bSearchClosestMode)
+ /* At first, load information from registry */
+ RtlZeroMemory(&dmSearch, sizeof(dmSearch));
+ Status = EngpGetDisplayDriverParameters(pGraphicsDevice, &dmSearch, NULL);
+ if (!NT_SUCCESS(Status))
{
- /* Search the closest mode */
- if (!LDEVOBJ_bGetClosestMode(pGraphicsDevice, RequestedMode, &pdmSelected))
- return FALSE;
- ASSERT(pdmSelected);
+ ERR("EngpGetDisplayDriverParameters() failed with status 0x%08x\n", Status);
+ return FALSE;
}
- else
+
+ /* Override values with the new ones provided */
+
+ _SEH2_TRY
{
- /* Search if requested mode exists */
- for (i = 0; i < pGraphicsDevice->cDevModes; i++)
+ bSearchClosestMode |= RequestedMode->dmFields == 0;
+
+ /* Copy standard fields (if provided) */
+ if (RequestedMode->dmFields & DM_BITSPERPEL && RequestedMode->dmBitsPerPel != 0)
+ dmSearch.dmBitsPerPel = RequestedMode->dmBitsPerPel;
+ if (RequestedMode->dmFields & DM_PELSWIDTH && RequestedMode->dmPelsWidth != 0)
+ dmSearch.dmPelsWidth = RequestedMode->dmPelsWidth;
+ if (RequestedMode->dmFields & DM_PELSHEIGHT && RequestedMode->dmPelsHeight != 0)
+ dmSearch.dmPelsHeight = RequestedMode->dmPelsHeight;
+ if (RequestedMode->dmFields & DM_DISPLAYFREQUENCY && RequestedMode->dmDisplayFrequency != 0)
+ dmSearch.dmDisplayFrequency = RequestedMode->dmDisplayFrequency;
+
+ if ((RequestedMode->dmFields & (DM_PANNINGWIDTH | DM_PANNINGHEIGHT)) == (DM_PANNINGWIDTH | DM_PANNINGHEIGHT) &&
+ RequestedMode->dmPanningWidth != 0 && RequestedMode->dmPanningHeight != 0 &&
+ RequestedMode->dmPanningWidth < dmSearch.dmPelsWidth &&
+ RequestedMode->dmPanningHeight < dmSearch.dmPelsHeight)
{
- pdmCurrent = pGraphicsDevice->pDevModeList[i].pdm;
-
- /* Compare asked DEVMODE fields
- * Only compare those that are valid in both DEVMODE structs */
- dwFields = pdmCurrent->dmFields & RequestedMode->dmFields;
-
- /* For now, we only need those */
- if ((dwFields & DM_BITSPERPEL) &&
- (pdmCurrent->dmBitsPerPel != RequestedMode->dmBitsPerPel)) continue;
- if ((dwFields & DM_PELSWIDTH) &&
- (pdmCurrent->dmPelsWidth != RequestedMode->dmPelsWidth)) continue;
- if ((dwFields & DM_PELSHEIGHT) &&
- (pdmCurrent->dmPelsHeight != RequestedMode->dmPelsHeight)) continue;
- if ((dwFields & DM_DISPLAYFREQUENCY) &&
- (pdmCurrent->dmDisplayFrequency != RequestedMode->dmDisplayFrequency)) continue;
-
- pdmSelected = pdmCurrent;
- break;
+ /* Get new panning values */
+ ulVirtualWidth = RequestedMode->dmPelsWidth;
+ ulVirtualHeight = RequestedMode->dmPelsHeight;
+ dmSearch.dmPelsWidth = RequestedMode->dmPanningWidth;
+ dmSearch.dmPelsHeight = RequestedMode->dmPanningHeight;
+ }
+ else if (dmSearch.dmPanningWidth != 0 && dmSearch.dmPanningHeight != 0 &&
+ dmSearch.dmPanningWidth < dmSearch.dmPelsWidth &&
+ dmSearch.dmPanningHeight < dmSearch.dmPelsHeight)
+ {
+ /* Keep existing panning values */
+ ulVirtualWidth = dmSearch.dmPelsWidth;
+ ulVirtualHeight = dmSearch.dmPelsHeight;
+ dmSearch.dmPelsWidth = dmSearch.dmPanningWidth;
+ dmSearch.dmPelsHeight = dmSearch.dmPanningHeight;
}
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ bResult = FALSE;
+ }
+ _SEH2_END;
+
+ if (!bResult)
+ return FALSE;
- if (!pdmSelected)
+ if (bSearchClosestMode)
+ {
+ if (LDEVOBJ_bGetClosestMode(pGraphicsDevice, &dmSearch, &pdmSelected))
{
- WARN("Requested mode not found (%dx%dx%d %d Hz)\n",
- RequestedMode->dmFields & DM_PELSWIDTH ? RequestedMode->dmPelsWidth : 0,
- RequestedMode->dmFields & DM_PELSHEIGHT ? RequestedMode->dmPelsHeight : 0,
- RequestedMode->dmFields & DM_BITSPERPEL ? RequestedMode->dmBitsPerPel : 0,
- RequestedMode->dmFields & DM_DISPLAYFREQUENCY ? RequestedMode->dmDisplayFrequency : 0);
- return FALSE;
+ /* Ok, found a closest mode. Update search */
+ dmSearch.dmBitsPerPel = pdmSelected->dmBitsPerPel;
+ dmSearch.dmPelsWidth = pdmSelected->dmPelsWidth;
+ dmSearch.dmPelsHeight = pdmSelected->dmPelsHeight;
+ dmSearch.dmDisplayFrequency = pdmSelected->dmDisplayFrequency;
}
}
+ /* Now, search the exact mode to return to caller */
+ for (i = 0; i < pGraphicsDevice->cDevModes; i++)
+ {
+ pdmCurrent = pGraphicsDevice->pDevModeList[i].pdm;
+
+ /* For now, we only need those */
+ if (pdmCurrent->dmBitsPerPel != dmSearch.dmBitsPerPel)
+ continue;
+ if (pdmCurrent->dmPelsWidth != dmSearch.dmPelsWidth)
+ continue;
+ if (pdmCurrent->dmPelsHeight != dmSearch.dmPelsHeight)
+ continue;
+ if (pdmCurrent->dmDisplayFrequency != dmSearch.dmDisplayFrequency)
+ continue;
+
+ pdmSelected = pdmCurrent;
+ break;
+ }
+
+ if (!pdmSelected)
+ {
+ ERR("Requested mode not found (%dx%dx%d %d Hz)\n",
+ dmSearch.dmPelsWidth,
+ dmSearch.dmPelsHeight,
+ dmSearch.dmBitsPerPel,
+ dmSearch.dmDisplayFrequency);
+ return FALSE;
+ }
+
/* Allocate memory for output */
pdm = ExAllocatePoolZero(PagedPool, pdmSelected->dmSize + pdmSelected->dmDriverExtra, GDITAG_DEVMODE);
if (!pdm)
(PVOID)((ULONG_PTR)pdmSelected + pdmSelected->dmSize),
pdmSelected->dmDriverExtra);
+ /* Add back panning */
+ if (ulVirtualWidth != 0 && ulVirtualHeight != 0 &&
+ pdm->dmPelsWidth < ulVirtualWidth &&
+ pdm->dmPelsHeight < ulVirtualHeight)
+ {
+ pdm->dmFields |= DM_PANNINGWIDTH | DM_PANNINGHEIGHT;
+ pdm->dmPanningWidth = pdm->dmPelsWidth;
+ pdm->dmPanningHeight = pdm->dmPelsHeight;
+ pdm->dmPelsWidth = ulVirtualWidth;
+ pdm->dmPelsHeight = ulVirtualHeight;
+ }
+
*pSelectedMode = pdm;
return TRUE;
}
if (!pdm)
{
- /* No settings requested. Read default settings from registry to dmDefault */
- HKEY hKey;
- WCHAR DeviceKey[128];
- ULONG cbSize;
- NTSTATUS Status;
- DWORD dwValue;
-
+ /* No settings requested. Provide nothing and LDEVOBJ_bProbeAndCaptureDevmode
+ * will read default settings from registry */
RtlZeroMemory(&dmDefault, sizeof(dmDefault));
dmDefault.dmSize = sizeof(dmDefault);
-
- Status = RegOpenKey(L"\\Registry\\Machine\\HARDWARE\\DEVICEMAP\\VIDEO", &hKey);
- if (!NT_SUCCESS(Status))
- {
- /* Ignore this device and continue */
- ERR("Failed to open VIDEO key: status 0x%08x\n", Status);
- continue;
- }
- cbSize = sizeof(DeviceKey);
- Status = RegQueryValue(hKey,
- pGraphicsDevice->szNtDeviceName,
- REG_SZ,
- DeviceKey,
- &cbSize);
- ZwClose(hKey);
- if (!NT_SUCCESS(Status))
- {
- /* Ignore this device and continue */
- ERR("Failed to open get device key for '%S': status 0x%08x\n", pGraphicsDevice->szNtDeviceName, Status);
- continue;
- }
- Status = RegOpenKey(DeviceKey, &hKey);
- if (!NT_SUCCESS(Status))
- {
- /* Ignore this device and continue */
- ERR("Failed to open open device key '%S' for '%S': status 0x%08x\n", DeviceKey, pGraphicsDevice->szNtDeviceName, Status);
- continue;
- }
-#define READ(field, str, flag) \
- if (RegReadDWORD(hKey, L##str, &dwValue)) \
- { \
- dmDefault.field = dwValue; \
- dmDefault.dmFields |= flag; \
- }
- READ(dmBitsPerPel, "DefaultSettings.BitsPerPel", DM_BITSPERPEL);
- READ(dmPelsWidth, "DefaultSettings.XResolution", DM_PELSWIDTH);
- READ(dmPelsHeight, "DefaultSettings.YResolution", DM_PELSHEIGHT);
- READ(dmDisplayFlags, "DefaultSettings.Flags", DM_DISPLAYFLAGS);
- READ(dmDisplayFrequency, "DefaultSettings.VRefresh", DM_DISPLAYFREQUENCY);
- READ(dmPanningWidth, "DefaultSettings.XPanning", DM_PANNINGWIDTH);
- READ(dmPanningHeight, "DefaultSettings.YPanning", DM_PANNINGHEIGHT);
- READ(dmDisplayOrientation, "DefaultSettings.Orientation", DM_DISPLAYORIENTATION);
- READ(dmDisplayFixedOutput, "DefaultSettings.FixedOutput", DM_DISPLAYFIXEDOUTPUT);
- READ(dmPosition.x, "Attach.RelativeX", DM_POSITION);
- READ(dmPosition.y, "Attach.RelativeY", DM_POSITION);
- RegReadDWORD(hKey, L"Acceleration.Level", &dwAccelerationLevel);
- ZwClose(hKey);
}
/* Get or create a PDEV for these settings */