[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, _Out_ PDEVMODEW *pSelectedMode,
_In_ BOOL bSearchClosestMode) _In_ BOOL bSearchClosestMode)
{ {
DEVMODEW dmSearch;
PDEVMODEW pdmCurrent, pdm, pdmSelected = NULL; PDEVMODEW pdmCurrent, pdm, pdmSelected = NULL;
ULONG i; ULONG i;
DWORD dwFields; ULONG ulVirtualWidth = 0, ulVirtualHeight = 0;
BOOL bResult = TRUE;
NTSTATUS Status;
if (!LDEVOBJ_bBuildDevmodeList(pGraphicsDevice)) if (!LDEVOBJ_bBuildDevmodeList(pGraphicsDevice))
return FALSE; 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) if (bSearchClosestMode)
{ {
/* Search the closest mode */ if (LDEVOBJ_bGetClosestMode(pGraphicsDevice, &dmSearch, &pdmSelected))
if (!LDEVOBJ_bGetClosestMode(pGraphicsDevice, RequestedMode, &pdmSelected)) {
return FALSE; /* Ok, found a closest mode. Update search */
ASSERT(pdmSelected); 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 */ pdmCurrent = pGraphicsDevice->pDevModeList[i].pdm;
for (i = 0; i < pGraphicsDevice->cDevModes; i++)
{
pdmCurrent = pGraphicsDevice->pDevModeList[i].pdm;
/* Compare asked DEVMODE fields /* For now, we only need those */
* Only compare those that are valid in both DEVMODE structs */ if (pdmCurrent->dmBitsPerPel != dmSearch.dmBitsPerPel)
dwFields = pdmCurrent->dmFields & RequestedMode->dmFields; 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 */ pdmSelected = pdmCurrent;
if ((dwFields & DM_BITSPERPEL) && break;
(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; if (!pdmSelected)
break; {
} ERR("Requested mode not found (%dx%dx%d %d Hz)\n",
dmSearch.dmPelsWidth,
if (!pdmSelected) dmSearch.dmPelsHeight,
{ dmSearch.dmBitsPerPel,
WARN("Requested mode not found (%dx%dx%d %d Hz)\n", dmSearch.dmDisplayFrequency);
RequestedMode->dmFields & DM_PELSWIDTH ? RequestedMode->dmPelsWidth : 0, return FALSE;
RequestedMode->dmFields & DM_PELSHEIGHT ? RequestedMode->dmPelsHeight : 0,
RequestedMode->dmFields & DM_BITSPERPEL ? RequestedMode->dmBitsPerPel : 0,
RequestedMode->dmFields & DM_DISPLAYFREQUENCY ? RequestedMode->dmDisplayFrequency : 0);
return FALSE;
}
} }
/* Allocate memory for output */ /* Allocate memory for output */
@ -771,6 +828,18 @@ LDEVOBJ_bProbeAndCaptureDevmode(
(PVOID)((ULONG_PTR)pdmSelected + pdmSelected->dmSize), (PVOID)((ULONG_PTR)pdmSelected + pdmSelected->dmSize),
pdmSelected->dmDriverExtra); 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; *pSelectedMode = pdm;
return TRUE; return TRUE;
} }

View file

@ -99,62 +99,10 @@ MDEVOBJ_Create(
if (!pdm) if (!pdm)
{ {
/* No settings requested. Read default settings from registry to dmDefault */ /* No settings requested. Provide nothing and LDEVOBJ_bProbeAndCaptureDevmode
HKEY hKey; * will read default settings from registry */
WCHAR DeviceKey[128];
ULONG cbSize;
NTSTATUS Status;
DWORD dwValue;
RtlZeroMemory(&dmDefault, sizeof(dmDefault)); RtlZeroMemory(&dmDefault, sizeof(dmDefault));
dmDefault.dmSize = 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 */ /* Get or create a PDEV for these settings */