[WIN32SS] Change LDEVOBJ_bProbeAndCaptureDevmode to load missing settings from registry

- use EngpGetDisplayDriverParameters to get display settings from registry
- update searched display settings with the provided ones (+ add missing SEH2)
- then, search exact mode

User can now change only one display setting, without specifying other ones.
This commit is contained in:
Hervé Poussineau 2022-05-22 14:23:26 +02:00
parent 9acd895f18
commit 588285881e
2 changed files with 106 additions and 89 deletions

View File

@ -710,54 +710,111 @@ LDEVOBJ_bProbeAndCaptureDevmode(
_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;
/* At first, load information from registry */
RtlZeroMemory(&dmSearch, sizeof(dmSearch));
Status = EngpGetDisplayDriverParameters(pGraphicsDevice, &dmSearch, NULL);
if (!NT_SUCCESS(Status))
{
ERR("EngpGetDisplayDriverParameters() failed with status 0x%08x\n", Status);
return FALSE;
}
/* Override values with the new ones provided */
_SEH2_TRY
{
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)
{
/* 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 (bSearchClosestMode)
{
/* Search the closest mode */
if (!LDEVOBJ_bGetClosestMode(pGraphicsDevice, RequestedMode, &pdmSelected))
return FALSE;
ASSERT(pdmSelected);
if (LDEVOBJ_bGetClosestMode(pGraphicsDevice, &dmSearch, &pdmSelected))
{
/* Ok, found a closest mode. Update search */
dmSearch.dmBitsPerPel = pdmSelected->dmBitsPerPel;
dmSearch.dmPelsWidth = pdmSelected->dmPelsWidth;
dmSearch.dmPelsHeight = pdmSelected->dmPelsHeight;
dmSearch.dmDisplayFrequency = pdmSelected->dmDisplayFrequency;
}
}
else
/* Now, search the exact mode to return to caller */
for (i = 0; i < pGraphicsDevice->cDevModes; i++)
{
/* Search if requested mode exists */
for (i = 0; i < pGraphicsDevice->cDevModes; i++)
{
pdmCurrent = pGraphicsDevice->pDevModeList[i].pdm;
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 (pdmCurrent->dmBitsPerPel != dmSearch.dmBitsPerPel)
continue;
if (pdmCurrent->dmPelsWidth != dmSearch.dmPelsWidth)
continue;
if (pdmCurrent->dmPelsHeight != dmSearch.dmPelsHeight)
continue;
if (pdmCurrent->dmDisplayFrequency != dmSearch.dmDisplayFrequency)
continue;
/* 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;
}
pdmSelected = pdmCurrent;
break;
}
if (!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;
}
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 */
@ -771,6 +828,18 @@ LDEVOBJ_bProbeAndCaptureDevmode(
(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;
}

View File

@ -99,62 +99,10 @@ MDEVOBJ_Create(
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 */