https://git.reactos.org/?p=reactos.git;a=commitdiff;h=9db63ad59552fd58d9493…
commit 9db63ad59552fd58d94934ebb158b18177da468a
Author: Hervé Poussineau <hpoussin(a)reactos.org>
AuthorDate: Sun Mar 20 15:45:19 2022 +0100
Commit: hpoussin <32227662+hpoussin(a)users.noreply.github.com>
CommitDate: Fri Apr 15 23:09:16 2022 +0200
[WIN32SS] Add functions related to MDEV (creation, destruction...)
---
win32ss/gdi/eng/mdevobj.c | 195 ++++++++++++++++++++++++++++++++++++++++++++++
win32ss/gdi/eng/mdevobj.h | 29 +++++++
2 files changed, 224 insertions(+)
diff --git a/win32ss/gdi/eng/mdevobj.c b/win32ss/gdi/eng/mdevobj.c
index 25b85b6e94c..98d835e6c5a 100644
--- a/win32ss/gdi/eng/mdevobj.c
+++ b/win32ss/gdi/eng/mdevobj.c
@@ -9,5 +9,200 @@
#include <win32k.h>
#define NDEBUG
#include <debug.h>
+DBG_DEFAULT_CHANNEL(EngMDev);
PMDEVOBJ gpmdev = NULL; /* FIXME: should be stored in gpDispInfo->pmdev */
+
+VOID
+MDEVOBJ_vEnable(
+ _Inout_ PMDEVOBJ pmdev)
+{
+ ULONG i;
+
+ for (i = 0; i < pmdev->cDev; i++)
+ {
+ PDEVOBJ_vEnableDisplay(pmdev->dev[i].ppdev);
+ }
+}
+
+BOOL
+MDEVOBJ_bDisable(
+ _Inout_ PMDEVOBJ pmdev)
+{
+ BOOL bSuccess = TRUE;
+ ULONG i, j;
+
+ for (i = 0; i < pmdev->cDev; i++)
+ {
+ if (!PDEVOBJ_bDisableDisplay(pmdev->dev[i].ppdev))
+ {
+ bSuccess = FALSE;
+ break;
+ }
+ }
+
+ if (!bSuccess)
+ {
+ /* Failed to disable all PDEVs. Reenable those we have disabled */
+ for (j = 0; j < i; j++)
+ {
+ PDEVOBJ_vEnableDisplay(pmdev->dev[i].ppdev);
+ }
+ }
+
+ return bSuccess;
+}
+
+PMDEVOBJ
+MDEVOBJ_Create(
+ _In_opt_ PUNICODE_STRING pustrDeviceName,
+ _In_opt_ PDEVMODEW pdm)
+{
+ PMDEVOBJ pmdev = NULL;
+ PPDEVOBJ ppdev;
+ PGRAPHICS_DEVICE pGraphicsDevice;
+ DEVMODEW dmDefault;
+ PDEVMODEW localPdm;
+ ULONG iDevNum = 0;
+
+ TRACE("MDEVOBJ_Create('%wZ' '%dx%dx%d (%d Hz)')\n",
+ pustrDeviceName,
+ pdm ? pdm->dmPelsWidth : 0,
+ pdm ? pdm->dmPelsHeight : 0,
+ pdm ? pdm->dmBitsPerPel : 0,
+ pdm ? pdm->dmDisplayFrequency : 0);
+
+ pmdev = ExAllocatePoolZero(PagedPool, sizeof(MDEVOBJ), GDITAG_MDEV);
+ if (!pmdev)
+ {
+ ERR("Failed to allocate memory for MDEV\n");
+ return NULL;
+ }
+
+ pmdev->cDev = 0;
+
+ while (TRUE)
+ {
+ /* Get the right graphics devices: either the specified one, or all of them (one
after one) */
+ if (pustrDeviceName)
+ pGraphicsDevice = (iDevNum == 0) ? EngpFindGraphicsDevice(pustrDeviceName, 0)
: NULL;
+ else
+ pGraphicsDevice = EngpFindGraphicsDevice(NULL, iDevNum);
+ iDevNum++;
+
+ if (!pGraphicsDevice)
+ {
+ TRACE("Done enumeration of graphic devices (DeviceName '%wZ'
iDevNum %d)\n", pustrDeviceName, iDevNum);
+ break;
+ }
+
+ if (!pdm)
+ {
+ /* No settings requested. Read default settings from registry to dmDefault
*/
+ HKEY hKey;
+ WCHAR DeviceKey[128];
+ ULONG cbSize;
+ NTSTATUS Status;
+ DWORD dwValue;
+
+ 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);
+ ZwClose(hKey);
+ }
+
+ /* Get or create a PDEV for these settings */
+ if (LDEVOBJ_bProbeAndCaptureDevmode(pGraphicsDevice, pdm ? pdm : &dmDefault,
&localPdm, !pdm))
+ {
+ ppdev = PDEVOBJ_Create(pGraphicsDevice, localPdm, LDEV_DEVICE_DISPLAY);
+ }
+ else
+ {
+ ppdev = NULL;
+ }
+
+ if (ppdev)
+ {
+ /* Great. We have a found a matching PDEV. Store it in MDEV */
+ TRACE("Adding '%S' to MDEV %p\n",
pGraphicsDevice->szWinDeviceName, pmdev);
+ PDEVOBJ_vReference(ppdev);
+ pmdev->dev[pmdev->cDev].ppdev = ppdev;
+ pmdev->cDev++;
+ }
+ else
+ {
+ WARN("Failed to add '%S' to MDEV %p\n",
pGraphicsDevice->szWinDeviceName, pmdev);
+ }
+ }
+
+ if (pmdev->cDev == 0)
+ {
+ TRACE("Failed to add any device to MDEV. Returning NULL\n");
+ MDEVOBJ_vDestroy(pmdev);
+ return NULL;
+ }
+
+ TRACE("Returning new MDEV %p with %d devices\n", pmdev, pmdev->cDev);
+ return pmdev;
+}
+
+VOID
+MDEVOBJ_vDestroy(
+ _Inout_ PMDEVOBJ pmdev)
+{
+ ULONG i;
+
+ for (i = 0; i < pmdev->cDev; i++)
+ {
+ PDEVOBJ_vRelease(pmdev->dev[i].ppdev);
+ }
+
+ if (pmdev->cDev > 1)
+ PDEVOBJ_vRelease(pmdev->ppdevGlobal);
+
+ ExFreePoolWithTag(pmdev, GDITAG_MDEV);
+}
diff --git a/win32ss/gdi/eng/mdevobj.h b/win32ss/gdi/eng/mdevobj.h
index 1d687d436a4..6dfb7aea4cf 100644
--- a/win32ss/gdi/eng/mdevobj.h
+++ b/win32ss/gdi/eng/mdevobj.h
@@ -7,11 +7,40 @@ typedef struct _PDEVOBJ *PPDEVOBJ;
typedef struct _MDEVOBJ
{
+ ULONG cDev;
PPDEVOBJ ppdevGlobal;
+ struct
+ {
+ PPDEVOBJ ppdev;
+ } dev[10]; /* FIXME: max number of displays. Needs dynamic allocation */
} MDEVOBJ, *PMDEVOBJ;
/* Globals ********************************************************************/
extern PMDEVOBJ gpmdev; /* FIXME: should be stored in gpDispInfo->pmdev */
+/* Function prototypes ********************************************************/
+
+VOID
+MDEVOBJ_vEnable(
+ _Inout_ PMDEVOBJ pmdev);
+
+BOOL
+MDEVOBJ_bDisable(
+ _Inout_ PMDEVOBJ pmdev);
+
+/* Create a new MDEV:
+ * - pustrDeviceName: name of the device to put in MDEV. If NULL, will put all graphics
devices in MDEV
+ * - pdm: settings associated to pustrDeviceName. Unused if pustrDeviceName is NULL.
+ * Return value: the new MDEV (or NULL in case of error)
+ */
+PMDEVOBJ
+MDEVOBJ_Create(
+ _In_opt_ PUNICODE_STRING pustrDeviceName,
+ _In_opt_ PDEVMODEW pdm);
+
+VOID
+MDEVOBJ_vDestroy(
+ _Inout_ PMDEVOBJ pmdev);
+
#endif /* !__WIN32K_MDEVOBJ_H */