mirror of
https://github.com/reactos/reactos.git
synced 2025-08-03 13:35:47 +00:00
Git conversion: Make reactos the root directory, move rosapps, rostests, wallpapers into modules, and delete rossubsys.
This commit is contained in:
parent
b94e2d8ca0
commit
c2c66aff7d
24198 changed files with 0 additions and 37285 deletions
979
win32ss/user/ntuser/display.c
Normal file
979
win32ss/user/ntuser/display.c
Normal file
|
@ -0,0 +1,979 @@
|
|||
/*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS kernel
|
||||
* PURPOSE: Video initialization and display settings
|
||||
* FILE: win32ss/user/ntuser/display.c
|
||||
* PROGRAMER: Timo Kreuzer (timo.kreuzer@reactos.org)
|
||||
*/
|
||||
|
||||
#include <win32k.h>
|
||||
DBG_DEFAULT_CHANNEL(UserDisplay);
|
||||
|
||||
BOOL gbBaseVideo = 0;
|
||||
static PPROCESSINFO gpFullscreen = NULL;
|
||||
|
||||
static const PWCHAR KEY_VIDEO = L"\\Registry\\Machine\\HARDWARE\\DEVICEMAP\\VIDEO";
|
||||
|
||||
VOID
|
||||
RegWriteDisplaySettings(HKEY hkey, PDEVMODEW pdm)
|
||||
{
|
||||
RegWriteDWORD(hkey, L"DefaultSettings.BitsPerPel", pdm->dmBitsPerPel);
|
||||
RegWriteDWORD(hkey, L"DefaultSettings.XResolution", pdm->dmPelsWidth);
|
||||
RegWriteDWORD(hkey, L"DefaultSettings.YResolution", pdm->dmPelsHeight);
|
||||
RegWriteDWORD(hkey, L"DefaultSettings.Flags", pdm->dmDisplayFlags);
|
||||
RegWriteDWORD(hkey, L"DefaultSettings.VRefresh", pdm->dmDisplayFrequency);
|
||||
RegWriteDWORD(hkey, L"DefaultSettings.XPanning", pdm->dmPanningWidth);
|
||||
RegWriteDWORD(hkey, L"DefaultSettings.YPanning", pdm->dmPanningHeight);
|
||||
RegWriteDWORD(hkey, L"DefaultSettings.Orientation", pdm->dmDisplayOrientation);
|
||||
RegWriteDWORD(hkey, L"DefaultSettings.FixedOutput", pdm->dmDisplayFixedOutput);
|
||||
RegWriteDWORD(hkey, L"Attach.RelativeX", pdm->dmPosition.x);
|
||||
RegWriteDWORD(hkey, L"Attach.RelativeY", pdm->dmPosition.y);
|
||||
// RegWriteDWORD(hkey, L"Attach.ToDesktop, pdm->dmBitsPerPel", pdm->);
|
||||
}
|
||||
|
||||
VOID
|
||||
RegReadDisplaySettings(HKEY hkey, PDEVMODEW pdm)
|
||||
{
|
||||
DWORD dwValue;
|
||||
|
||||
/* Zero out the structure */
|
||||
RtlZeroMemory(pdm, sizeof(DEVMODEW));
|
||||
|
||||
/* Helper macro */
|
||||
#define READ(field, str, flag) \
|
||||
if (RegReadDWORD(hkey, L##str, &dwValue)) \
|
||||
{ \
|
||||
pdm->field = dwValue; \
|
||||
pdm->dmFields |= flag; \
|
||||
}
|
||||
|
||||
/* Read all present settings */
|
||||
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);
|
||||
}
|
||||
|
||||
PGRAPHICS_DEVICE
|
||||
NTAPI
|
||||
InitDisplayDriver(
|
||||
IN PWSTR pwszDeviceName,
|
||||
IN PWSTR pwszRegKey)
|
||||
{
|
||||
PGRAPHICS_DEVICE pGraphicsDevice;
|
||||
UNICODE_STRING ustrDeviceName, ustrDisplayDrivers, ustrDescription;
|
||||
NTSTATUS Status;
|
||||
WCHAR awcBuffer[128];
|
||||
ULONG cbSize;
|
||||
HKEY hkey;
|
||||
DEVMODEW dmDefault;
|
||||
DWORD dwVga;
|
||||
|
||||
TRACE("InitDisplayDriver(%S, %S);\n",
|
||||
pwszDeviceName, pwszRegKey);
|
||||
|
||||
/* Open the driver's registry key */
|
||||
Status = RegOpenKey(pwszRegKey, &hkey);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
ERR("Failed to open registry key: %ls\n", pwszRegKey);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Query the diplay drivers */
|
||||
cbSize = sizeof(awcBuffer) - 10;
|
||||
Status = RegQueryValue(hkey,
|
||||
L"InstalledDisplayDrivers",
|
||||
REG_MULTI_SZ,
|
||||
awcBuffer,
|
||||
&cbSize);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
ERR("Didn't find 'InstalledDisplayDrivers', status = 0x%lx\n", Status);
|
||||
ZwClose(hkey);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Initialize the UNICODE_STRING */
|
||||
ustrDisplayDrivers.Buffer = awcBuffer;
|
||||
ustrDisplayDrivers.MaximumLength = (USHORT)cbSize;
|
||||
ustrDisplayDrivers.Length = (USHORT)cbSize;
|
||||
|
||||
/* Set Buffer for description and size of remaining buffer */
|
||||
ustrDescription.Buffer = awcBuffer + (cbSize / sizeof(WCHAR));
|
||||
cbSize = sizeof(awcBuffer) - cbSize;
|
||||
|
||||
/* Query the device string */
|
||||
Status = RegQueryValue(hkey,
|
||||
L"Device Description",
|
||||
REG_SZ,
|
||||
ustrDescription.Buffer,
|
||||
&cbSize);
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
ustrDescription.MaximumLength = (USHORT)cbSize;
|
||||
ustrDescription.Length = (USHORT)cbSize;
|
||||
}
|
||||
else
|
||||
{
|
||||
RtlInitUnicodeString(&ustrDescription, L"<unknown>");
|
||||
}
|
||||
|
||||
/* Query the default settings */
|
||||
RegReadDisplaySettings(hkey, &dmDefault);
|
||||
|
||||
/* Query if this is a VGA compatible driver */
|
||||
cbSize = sizeof(DWORD);
|
||||
Status = RegQueryValue(hkey, L"VgaCompatible", REG_DWORD, &dwVga, &cbSize);
|
||||
if (!NT_SUCCESS(Status)) dwVga = 0;
|
||||
|
||||
/* Close the registry key */
|
||||
ZwClose(hkey);
|
||||
|
||||
/* Register the device with GDI */
|
||||
RtlInitUnicodeString(&ustrDeviceName, pwszDeviceName);
|
||||
pGraphicsDevice = EngpRegisterGraphicsDevice(&ustrDeviceName,
|
||||
&ustrDisplayDrivers,
|
||||
&ustrDescription,
|
||||
&dmDefault);
|
||||
if (pGraphicsDevice && dwVga)
|
||||
{
|
||||
pGraphicsDevice->StateFlags |= DISPLAY_DEVICE_VGA_COMPATIBLE;
|
||||
}
|
||||
|
||||
return pGraphicsDevice;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
InitVideo(VOID)
|
||||
{
|
||||
ULONG iDevNum, iVGACompatible = -1, ulMaxObjectNumber = 0;
|
||||
WCHAR awcDeviceName[20];
|
||||
WCHAR awcBuffer[256];
|
||||
NTSTATUS Status;
|
||||
PGRAPHICS_DEVICE pGraphicsDevice;
|
||||
ULONG cbValue;
|
||||
HKEY hkey;
|
||||
|
||||
TRACE("----------------------------- InitVideo() -------------------------------\n");
|
||||
|
||||
/* Open the key for the boot command line */
|
||||
Status = RegOpenKey(L"\\REGISTRY\\MACHINE\\SYSTEM\\CurrentControlSet\\Control", &hkey);
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
cbValue = 256;
|
||||
Status = RegQueryValue(hkey, L"SystemStartOptions", REG_SZ, awcBuffer, &cbValue);
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
/* Check if VGA mode is requested. */
|
||||
if (wcsstr(awcBuffer, L"BASEVIDEO") != 0)
|
||||
{
|
||||
ERR("VGA mode requested.\n");
|
||||
gbBaseVideo = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
ZwClose(hkey);
|
||||
}
|
||||
|
||||
/* Open the key for the adapters */
|
||||
Status = RegOpenKey(KEY_VIDEO, &hkey);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
ERR("Could not open HARDWARE\\DEVICEMAP\\VIDEO registry key:0x%lx\n", Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Read the name of the VGA adapter */
|
||||
cbValue = 20;
|
||||
Status = RegQueryValue(hkey, L"VgaCompatible", REG_SZ, awcDeviceName, &cbValue);
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
iVGACompatible = _wtoi(&awcDeviceName[13]);
|
||||
ERR("VGA adapter = %lu\n", iVGACompatible);
|
||||
}
|
||||
|
||||
/* Get the maximum mumber of adapters */
|
||||
if (!RegReadDWORD(hkey, L"MaxObjectNumber", &ulMaxObjectNumber))
|
||||
{
|
||||
ERR("Could not read MaxObjectNumber, defaulting to 0.\n");
|
||||
}
|
||||
|
||||
TRACE("Found %lu devices\n", ulMaxObjectNumber + 1);
|
||||
|
||||
/* Loop through all adapters */
|
||||
for (iDevNum = 0; iDevNum <= ulMaxObjectNumber; iDevNum++)
|
||||
{
|
||||
/* Create the adapter's key name */
|
||||
swprintf(awcDeviceName, L"\\Device\\Video%lu", iDevNum);
|
||||
|
||||
/* Read the reg key name */
|
||||
cbValue = sizeof(awcBuffer);
|
||||
Status = RegQueryValue(hkey, awcDeviceName, REG_SZ, awcBuffer, &cbValue);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
ERR("failed to query the registry path:0x%lx\n", Status);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Initialize the driver for this device */
|
||||
pGraphicsDevice = InitDisplayDriver(awcDeviceName, awcBuffer);
|
||||
if (!pGraphicsDevice) continue;
|
||||
|
||||
/* Check if this is a VGA compatible adapter */
|
||||
if (pGraphicsDevice->StateFlags & DISPLAY_DEVICE_VGA_COMPATIBLE)
|
||||
{
|
||||
/* Save this as the VGA adapter */
|
||||
if (!gpVgaGraphicsDevice)
|
||||
gpVgaGraphicsDevice = pGraphicsDevice;
|
||||
TRACE("gpVgaGraphicsDevice = %p\n", gpVgaGraphicsDevice);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Set the first one as primary device */
|
||||
if (!gpPrimaryGraphicsDevice)
|
||||
gpPrimaryGraphicsDevice = pGraphicsDevice;
|
||||
TRACE("gpPrimaryGraphicsDevice = %p\n", gpPrimaryGraphicsDevice);
|
||||
}
|
||||
}
|
||||
|
||||
/* Close the device map registry key */
|
||||
ZwClose(hkey);
|
||||
|
||||
/* Was VGA mode requested? */
|
||||
if (gbBaseVideo)
|
||||
{
|
||||
/* Check if we found a VGA compatible device */
|
||||
if (gpVgaGraphicsDevice)
|
||||
{
|
||||
/* Set the VgaAdapter as primary */
|
||||
gpPrimaryGraphicsDevice = gpVgaGraphicsDevice;
|
||||
// FIXME: DEVMODE
|
||||
}
|
||||
else
|
||||
{
|
||||
ERR("Could not find VGA compatible driver. Trying normal.\n");
|
||||
}
|
||||
}
|
||||
|
||||
/* Check if we had any success */
|
||||
if (!gpPrimaryGraphicsDevice)
|
||||
{
|
||||
/* Check if there is a VGA device we skipped */
|
||||
if (gpVgaGraphicsDevice)
|
||||
{
|
||||
/* There is, use the VGA device */
|
||||
gpPrimaryGraphicsDevice = gpVgaGraphicsDevice;
|
||||
}
|
||||
else
|
||||
{
|
||||
ERR("No usable display driver was found.\n");
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
}
|
||||
|
||||
InitSysParams();
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
UserEnumDisplayDevices(
|
||||
PUNICODE_STRING pustrDevice,
|
||||
DWORD iDevNum,
|
||||
PDISPLAY_DEVICEW pdispdev,
|
||||
DWORD dwFlags)
|
||||
{
|
||||
PGRAPHICS_DEVICE pGraphicsDevice;
|
||||
ULONG cbSize;
|
||||
HKEY hkey;
|
||||
NTSTATUS Status;
|
||||
|
||||
/* Ask gdi for the GRAPHICS_DEVICE */
|
||||
pGraphicsDevice = EngpFindGraphicsDevice(pustrDevice, iDevNum, 0);
|
||||
if (!pGraphicsDevice)
|
||||
{
|
||||
/* No device found */
|
||||
ERR("No GRAPHICS_DEVICE found\n");
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
/* Open the device map registry key */
|
||||
Status = RegOpenKey(KEY_VIDEO, &hkey);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
/* No device found */
|
||||
ERR("Could not open reg key\n");
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
/* Query the registry path */
|
||||
cbSize = sizeof(pdispdev->DeviceKey);
|
||||
RegQueryValue(hkey,
|
||||
pGraphicsDevice->szNtDeviceName,
|
||||
REG_SZ,
|
||||
pdispdev->DeviceKey,
|
||||
&cbSize);
|
||||
|
||||
/* Close registry key */
|
||||
ZwClose(hkey);
|
||||
|
||||
/* Copy device name, device string and StateFlags */
|
||||
RtlStringCbCopyW(pdispdev->DeviceName, sizeof(pdispdev->DeviceName), pGraphicsDevice->szWinDeviceName);
|
||||
RtlStringCbCopyW(pdispdev->DeviceString, sizeof(pdispdev->DeviceString), pGraphicsDevice->pwszDescription);
|
||||
pdispdev->StateFlags = pGraphicsDevice->StateFlags;
|
||||
// FIXME: fill in DEVICE ID
|
||||
pdispdev->DeviceID[0] = UNICODE_NULL;
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
//NTSTATUS
|
||||
BOOL
|
||||
NTAPI
|
||||
NtUserEnumDisplayDevices(
|
||||
PUNICODE_STRING pustrDevice,
|
||||
DWORD iDevNum,
|
||||
PDISPLAY_DEVICEW pDisplayDevice,
|
||||
DWORD dwFlags)
|
||||
{
|
||||
UNICODE_STRING ustrDevice;
|
||||
WCHAR awcDevice[CCHDEVICENAME];
|
||||
DISPLAY_DEVICEW dispdev;
|
||||
NTSTATUS Status;
|
||||
|
||||
TRACE("Enter NtUserEnumDisplayDevices(%wZ, %lu)\n",
|
||||
pustrDevice, iDevNum);
|
||||
|
||||
dispdev.cb = sizeof(dispdev);
|
||||
|
||||
if (pustrDevice)
|
||||
{
|
||||
/* Initialize destination string */
|
||||
RtlInitEmptyUnicodeString(&ustrDevice, awcDevice, sizeof(awcDevice));
|
||||
|
||||
_SEH2_TRY
|
||||
{
|
||||
/* Probe the UNICODE_STRING and the buffer */
|
||||
ProbeForRead(pustrDevice, sizeof(UNICODE_STRING), 1);
|
||||
ProbeForRead(pustrDevice->Buffer, pustrDevice->Length, 1);
|
||||
|
||||
/* Copy the string */
|
||||
RtlCopyUnicodeString(&ustrDevice, pustrDevice);
|
||||
}
|
||||
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
||||
{
|
||||
// _SEH2_YIELD(return _SEH2_GetExceptionCode());
|
||||
_SEH2_YIELD(return NT_SUCCESS(_SEH2_GetExceptionCode()));
|
||||
}
|
||||
_SEH2_END
|
||||
|
||||
if (ustrDevice.Length > 0)
|
||||
pustrDevice = &ustrDevice;
|
||||
else
|
||||
pustrDevice = NULL;
|
||||
}
|
||||
|
||||
/* If name is given only iDevNum==0 gives results */
|
||||
if (pustrDevice && iDevNum != 0)
|
||||
return FALSE;
|
||||
|
||||
/* Acquire global USER lock */
|
||||
UserEnterShared();
|
||||
|
||||
/* Call the internal function */
|
||||
Status = UserEnumDisplayDevices(pustrDevice, iDevNum, &dispdev, dwFlags);
|
||||
|
||||
/* Release lock */
|
||||
UserLeave();
|
||||
|
||||
/* On success copy data to caller */
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
/* Enter SEH */
|
||||
_SEH2_TRY
|
||||
{
|
||||
/* First probe the cb field */
|
||||
ProbeForWrite(&pDisplayDevice->cb, sizeof(DWORD), 1);
|
||||
|
||||
/* Check the buffer size */
|
||||
if (pDisplayDevice->cb)
|
||||
{
|
||||
/* Probe the output buffer */
|
||||
pDisplayDevice->cb = min(pDisplayDevice->cb, sizeof(dispdev));
|
||||
ProbeForWrite(pDisplayDevice, pDisplayDevice->cb, 1);
|
||||
|
||||
/* Copy as much as the given buffer allows */
|
||||
RtlCopyMemory(pDisplayDevice, &dispdev, pDisplayDevice->cb);
|
||||
}
|
||||
}
|
||||
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
||||
{
|
||||
Status = _SEH2_GetExceptionCode();
|
||||
}
|
||||
_SEH2_END
|
||||
}
|
||||
|
||||
TRACE("Leave NtUserEnumDisplayDevices, Status = 0x%lx\n", Status);
|
||||
/* Return the result */
|
||||
// return Status;
|
||||
return NT_SUCCESS(Status); // FIXME
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
UserEnumCurrentDisplaySettings(
|
||||
PUNICODE_STRING pustrDevice,
|
||||
PDEVMODEW *ppdm)
|
||||
{
|
||||
PPDEVOBJ ppdev;
|
||||
|
||||
/* Get the PDEV for the device */
|
||||
ppdev = EngpGetPDEV(pustrDevice);
|
||||
if (!ppdev)
|
||||
{
|
||||
/* No device found */
|
||||
ERR("No PDEV found!\n");
|
||||
return STATUS_INVALID_PARAMETER_1;
|
||||
}
|
||||
|
||||
*ppdm = ppdev->pdmwDev;
|
||||
PDEVOBJ_vRelease(ppdev);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
UserEnumDisplaySettings(
|
||||
PUNICODE_STRING pustrDevice,
|
||||
DWORD iModeNum,
|
||||
LPDEVMODEW *ppdm,
|
||||
DWORD dwFlags)
|
||||
{
|
||||
PGRAPHICS_DEVICE pGraphicsDevice;
|
||||
PDEVMODEENTRY pdmentry;
|
||||
ULONG i, iFoundMode;
|
||||
PPDEVOBJ ppdev;
|
||||
|
||||
TRACE("Enter UserEnumDisplaySettings('%wZ', %lu)\n",
|
||||
pustrDevice, iModeNum);
|
||||
|
||||
/* Ask GDI for the GRAPHICS_DEVICE */
|
||||
pGraphicsDevice = EngpFindGraphicsDevice(pustrDevice, 0, 0);
|
||||
ppdev = EngpGetPDEV(pustrDevice);
|
||||
|
||||
if (!pGraphicsDevice || !ppdev)
|
||||
{
|
||||
/* No device found */
|
||||
ERR("No device found!\n");
|
||||
return STATUS_INVALID_PARAMETER_1;
|
||||
}
|
||||
|
||||
/* let's politely ask the driver for an updated mode list,
|
||||
just in case there's something new in there (vbox) */
|
||||
|
||||
PDEVOBJ_vRefreshModeList(ppdev);
|
||||
PDEVOBJ_vRelease(ppdev);
|
||||
|
||||
iFoundMode = 0;
|
||||
for (i = 0; i < pGraphicsDevice->cDevModes; i++)
|
||||
{
|
||||
pdmentry = &pGraphicsDevice->pDevModeList[i];
|
||||
|
||||
/* FIXME: Consider EDS_RAWMODE */
|
||||
#if 0
|
||||
if ((!(dwFlags & EDS_RAWMODE) && (pdmentry->dwFlags & 1)) ||!
|
||||
(dwFlags & EDS_RAWMODE))
|
||||
#endif
|
||||
{
|
||||
/* Is this the one we want? */
|
||||
if (iFoundMode == iModeNum)
|
||||
{
|
||||
*ppdm = pdmentry->pdm;
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/* Increment number of found modes */
|
||||
iFoundMode++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Nothing was found */
|
||||
return STATUS_INVALID_PARAMETER_2;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
UserOpenDisplaySettingsKey(
|
||||
OUT PHKEY phkey,
|
||||
IN PUNICODE_STRING pustrDevice,
|
||||
IN BOOL bGlobal)
|
||||
{
|
||||
HKEY hkey;
|
||||
DISPLAY_DEVICEW dispdev;
|
||||
NTSTATUS Status;
|
||||
|
||||
/* Get device info */
|
||||
Status = UserEnumDisplayDevices(pustrDevice, 0, &dispdev, 0);
|
||||
if (!NT_SUCCESS(Status))
|
||||
return Status;
|
||||
|
||||
if (bGlobal)
|
||||
{
|
||||
// FIXME: Need to fix the registry key somehow
|
||||
}
|
||||
|
||||
/* Open the registry key */
|
||||
Status = RegOpenKey(dispdev.DeviceKey, &hkey);
|
||||
if (!NT_SUCCESS(Status))
|
||||
return Status;
|
||||
|
||||
*phkey = hkey;
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
UserEnumRegistryDisplaySettings(
|
||||
IN PUNICODE_STRING pustrDevice,
|
||||
OUT LPDEVMODEW pdm)
|
||||
{
|
||||
HKEY hkey;
|
||||
NTSTATUS Status = UserOpenDisplaySettingsKey(&hkey, pustrDevice, 0);
|
||||
if(NT_SUCCESS(Status))
|
||||
{
|
||||
RegReadDisplaySettings(hkey, pdm);
|
||||
ZwClose(hkey);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
return Status ;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
APIENTRY
|
||||
NtUserEnumDisplaySettings(
|
||||
IN PUNICODE_STRING pustrDevice,
|
||||
IN DWORD iModeNum,
|
||||
OUT LPDEVMODEW lpDevMode,
|
||||
IN DWORD dwFlags)
|
||||
{
|
||||
UNICODE_STRING ustrDevice;
|
||||
WCHAR awcDevice[CCHDEVICENAME];
|
||||
NTSTATUS Status;
|
||||
ULONG cbSize, cbExtra;
|
||||
DEVMODEW dmReg, *pdm;
|
||||
|
||||
TRACE("Enter NtUserEnumDisplaySettings(%wZ, %lu, %p, 0x%lx)\n",
|
||||
pustrDevice, iModeNum, lpDevMode, dwFlags);
|
||||
|
||||
_SEH2_TRY
|
||||
{
|
||||
ProbeForRead(lpDevMode, sizeof(DEVMODEW), sizeof(UCHAR));
|
||||
|
||||
cbSize = lpDevMode->dmSize;
|
||||
cbExtra = lpDevMode->dmDriverExtra;
|
||||
|
||||
ProbeForWrite(lpDevMode, cbSize + cbExtra, sizeof(UCHAR));
|
||||
}
|
||||
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
||||
{
|
||||
_SEH2_YIELD(return _SEH2_GetExceptionCode());
|
||||
}
|
||||
_SEH2_END;
|
||||
|
||||
if (lpDevMode->dmSize != sizeof(DEVMODEW))
|
||||
{
|
||||
return STATUS_BUFFER_TOO_SMALL;
|
||||
}
|
||||
|
||||
if (pustrDevice)
|
||||
{
|
||||
/* Initialize destination string */
|
||||
RtlInitEmptyUnicodeString(&ustrDevice, awcDevice, sizeof(awcDevice));
|
||||
|
||||
_SEH2_TRY
|
||||
{
|
||||
/* Probe the UNICODE_STRING and the buffer */
|
||||
ProbeForReadUnicodeString(pustrDevice);
|
||||
|
||||
if (!pustrDevice->Length || !pustrDevice->Buffer)
|
||||
ExRaiseStatus(STATUS_NO_MEMORY);
|
||||
|
||||
ProbeForRead(pustrDevice->Buffer, pustrDevice->Length, sizeof(UCHAR));
|
||||
|
||||
/* Copy the string */
|
||||
RtlCopyUnicodeString(&ustrDevice, pustrDevice);
|
||||
}
|
||||
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
||||
{
|
||||
_SEH2_YIELD(return STATUS_INVALID_PARAMETER_1);
|
||||
}
|
||||
_SEH2_END;
|
||||
|
||||
pustrDevice = &ustrDevice;
|
||||
}
|
||||
|
||||
/* Acquire global USER lock */
|
||||
UserEnterShared();
|
||||
|
||||
if (iModeNum == ENUM_REGISTRY_SETTINGS)
|
||||
{
|
||||
/* Get the registry settings */
|
||||
Status = UserEnumRegistryDisplaySettings(pustrDevice, &dmReg);
|
||||
pdm = &dmReg;
|
||||
pdm->dmSize = sizeof(DEVMODEW);
|
||||
}
|
||||
else if (iModeNum == ENUM_CURRENT_SETTINGS)
|
||||
{
|
||||
/* Get the current settings */
|
||||
Status = UserEnumCurrentDisplaySettings(pustrDevice, &pdm);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Get specified settings */
|
||||
Status = UserEnumDisplaySettings(pustrDevice, iModeNum, &pdm, dwFlags);
|
||||
}
|
||||
|
||||
/* Release lock */
|
||||
UserLeave();
|
||||
|
||||
/* Did we succeed? */
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
/* Copy some information back */
|
||||
_SEH2_TRY
|
||||
{
|
||||
/* Output what we got */
|
||||
RtlCopyMemory(lpDevMode, pdm, min(cbSize, pdm->dmSize));
|
||||
|
||||
/* Output private/extra driver data */
|
||||
if (cbExtra > 0 && pdm->dmDriverExtra > 0)
|
||||
{
|
||||
RtlCopyMemory((PCHAR)lpDevMode + cbSize,
|
||||
(PCHAR)pdm + pdm->dmSize,
|
||||
min(cbExtra, pdm->dmDriverExtra));
|
||||
}
|
||||
}
|
||||
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
||||
{
|
||||
Status = _SEH2_GetExceptionCode();
|
||||
}
|
||||
_SEH2_END;
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
VOID
|
||||
UserUpdateFullscreen(
|
||||
DWORD flags)
|
||||
{
|
||||
if (flags & CDS_FULLSCREEN)
|
||||
gpFullscreen = gptiCurrent->ppi;
|
||||
else
|
||||
gpFullscreen = NULL;
|
||||
}
|
||||
|
||||
LONG
|
||||
APIENTRY
|
||||
UserChangeDisplaySettings(
|
||||
PUNICODE_STRING pustrDevice,
|
||||
LPDEVMODEW pdm,
|
||||
DWORD flags,
|
||||
LPVOID lParam)
|
||||
{
|
||||
DEVMODEW dm;
|
||||
LONG lResult = DISP_CHANGE_SUCCESSFUL;
|
||||
HKEY hkey;
|
||||
NTSTATUS Status;
|
||||
PPDEVOBJ ppdev;
|
||||
WORD OrigBC;
|
||||
//PDESKTOP pdesk;
|
||||
|
||||
/* If no DEVMODE is given, use registry settings */
|
||||
if (!pdm)
|
||||
{
|
||||
/* Get the registry settings */
|
||||
Status = UserEnumRegistryDisplaySettings(pustrDevice, &dm);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
ERR("Could not load registry settings\n");
|
||||
return DISP_CHANGE_BADPARAM;
|
||||
}
|
||||
}
|
||||
else if (pdm->dmSize < FIELD_OFFSET(DEVMODEW, dmFields))
|
||||
return DISP_CHANGE_BADMODE; /* This is what winXP SP3 returns */
|
||||
else
|
||||
dm = *pdm;
|
||||
|
||||
/* Save original bit count */
|
||||
OrigBC = gpsi->BitCount;
|
||||
|
||||
/* Check params */
|
||||
if ((dm.dmFields & (DM_PELSWIDTH | DM_PELSHEIGHT)) != (DM_PELSWIDTH | DM_PELSHEIGHT))
|
||||
{
|
||||
ERR("Devmode doesn't specify the resolution.\n");
|
||||
return DISP_CHANGE_BADMODE;
|
||||
}
|
||||
|
||||
/* Get the PDEV */
|
||||
ppdev = EngpGetPDEV(pustrDevice);
|
||||
if (!ppdev)
|
||||
{
|
||||
ERR("Failed to get PDEV\n");
|
||||
return DISP_CHANGE_BADPARAM;
|
||||
}
|
||||
|
||||
/* Fixup values */
|
||||
if(dm.dmBitsPerPel == 0 || !(dm.dmFields & DM_BITSPERPEL))
|
||||
{
|
||||
dm.dmBitsPerPel = ppdev->pdmwDev->dmBitsPerPel;
|
||||
dm.dmFields |= DM_BITSPERPEL;
|
||||
}
|
||||
|
||||
if((dm.dmFields & DM_DISPLAYFREQUENCY) && (dm.dmDisplayFrequency == 0))
|
||||
dm.dmDisplayFrequency = ppdev->pdmwDev->dmDisplayFrequency;
|
||||
|
||||
/* Look for the requested DEVMODE */
|
||||
pdm = PDEVOBJ_pdmMatchDevMode(ppdev, &dm);
|
||||
if (!pdm)
|
||||
{
|
||||
ERR("Could not find a matching DEVMODE\n");
|
||||
lResult = DISP_CHANGE_BADMODE;
|
||||
goto leave;
|
||||
}
|
||||
else if (flags & CDS_TEST)
|
||||
{
|
||||
/* It's possible, go ahead! */
|
||||
lResult = DISP_CHANGE_SUCCESSFUL;
|
||||
goto leave;
|
||||
}
|
||||
|
||||
/* Shall we update the registry? */
|
||||
if (flags & CDS_UPDATEREGISTRY)
|
||||
{
|
||||
/* Open the local or global settings key */
|
||||
Status = UserOpenDisplaySettingsKey(&hkey, pustrDevice, flags & CDS_GLOBAL);
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
/* Store the settings */
|
||||
RegWriteDisplaySettings(hkey, pdm);
|
||||
|
||||
/* Close the registry key */
|
||||
ZwClose(hkey);
|
||||
}
|
||||
else
|
||||
{
|
||||
ERR("Could not open registry key\n");
|
||||
lResult = DISP_CHANGE_NOTUPDATED;
|
||||
}
|
||||
}
|
||||
|
||||
/* Shall we apply the settings? */
|
||||
if (!(flags & CDS_NORESET))
|
||||
{
|
||||
ULONG ulResult;
|
||||
PVOID pvOldCursor;
|
||||
TEXTMETRICW tmw;
|
||||
|
||||
/* Remove mouse pointer */
|
||||
pvOldCursor = UserSetCursor(NULL, TRUE);
|
||||
|
||||
/* Do the mode switch */
|
||||
ulResult = PDEVOBJ_bSwitchMode(ppdev, pdm);
|
||||
|
||||
/* Restore mouse pointer, no hooks called */
|
||||
pvOldCursor = UserSetCursor(pvOldCursor, TRUE);
|
||||
ASSERT(pvOldCursor == NULL);
|
||||
|
||||
/* Check for failure */
|
||||
if (!ulResult)
|
||||
{
|
||||
ERR("Failed to set mode\n");
|
||||
lResult = (lResult == DISP_CHANGE_NOTUPDATED) ?
|
||||
DISP_CHANGE_FAILED : DISP_CHANGE_RESTART;
|
||||
|
||||
goto leave;
|
||||
}
|
||||
|
||||
UserUpdateFullscreen(flags);
|
||||
|
||||
/* Update the system metrics */
|
||||
InitMetrics();
|
||||
|
||||
/* Set new size of the monitor */
|
||||
UserUpdateMonitorSize((HDEV)ppdev);
|
||||
|
||||
/* Update the SERVERINFO */
|
||||
gpsi->dmLogPixels = ppdev->gdiinfo.ulLogPixelsY;
|
||||
gpsi->Planes = ppdev->gdiinfo.cPlanes;
|
||||
gpsi->BitsPixel = ppdev->gdiinfo.cBitsPixel;
|
||||
gpsi->BitCount = gpsi->Planes * gpsi->BitsPixel;
|
||||
if (ppdev->gdiinfo.flRaster & RC_PALETTE)
|
||||
{
|
||||
gpsi->PUSIFlags |= PUSIF_PALETTEDISPLAY;
|
||||
}
|
||||
else
|
||||
gpsi->PUSIFlags &= ~PUSIF_PALETTEDISPLAY;
|
||||
// Font is realized and this dc was previously set to internal DC_ATTR.
|
||||
gpsi->cxSysFontChar = IntGetCharDimensions(hSystemBM, &tmw, (DWORD*)&gpsi->cySysFontChar);
|
||||
gpsi->tmSysFont = tmw;
|
||||
|
||||
/* Remove all cursor clipping */
|
||||
UserClipCursor(NULL);
|
||||
|
||||
//pdesk = IntGetActiveDesktop();
|
||||
//IntHideDesktop(pdesk);
|
||||
|
||||
/* Send WM_DISPLAYCHANGE to all toplevel windows */
|
||||
UserSendNotifyMessage( HWND_BROADCAST,
|
||||
WM_DISPLAYCHANGE,
|
||||
gpsi->BitCount,
|
||||
MAKELONG(gpsi->aiSysMet[SM_CXSCREEN], gpsi->aiSysMet[SM_CYSCREEN]) );
|
||||
|
||||
ERR("BitCount New %d Orig %d ChkNew %d\n",gpsi->BitCount,OrigBC,ppdev->gdiinfo.cBitsPixel);
|
||||
|
||||
/* Not full screen and different bit count, send messages */
|
||||
if (!(flags & CDS_FULLSCREEN) &&
|
||||
gpsi->BitCount != OrigBC )
|
||||
{
|
||||
ERR("Detect settings changed.\n");
|
||||
UserSendNotifyMessage( HWND_BROADCAST, WM_SETTINGCHANGE, 0, 0 );
|
||||
UserSendNotifyMessage( HWND_BROADCAST, WM_SYSCOLORCHANGE, 0, 0 );
|
||||
}
|
||||
|
||||
//co_IntShowDesktop(pdesk, ppdev->gdiinfo.ulHorzRes, ppdev->gdiinfo.ulVertRes);
|
||||
|
||||
UserRedrawDesktop();
|
||||
}
|
||||
|
||||
leave:
|
||||
/* Release the PDEV */
|
||||
PDEVOBJ_vRelease(ppdev);
|
||||
|
||||
return lResult;
|
||||
}
|
||||
|
||||
VOID
|
||||
UserDisplayNotifyShutdown(
|
||||
PPROCESSINFO ppiCurrent)
|
||||
{
|
||||
if (ppiCurrent == gpFullscreen)
|
||||
{
|
||||
UserChangeDisplaySettings(NULL, NULL, 0, NULL);
|
||||
if (gpFullscreen)
|
||||
ERR("Failed to restore display mode!\n");
|
||||
}
|
||||
}
|
||||
|
||||
LONG
|
||||
APIENTRY
|
||||
NtUserChangeDisplaySettings(
|
||||
PUNICODE_STRING pustrDevice,
|
||||
LPDEVMODEW lpDevMode,
|
||||
DWORD dwflags,
|
||||
LPVOID lParam)
|
||||
{
|
||||
WCHAR awcDevice[CCHDEVICENAME];
|
||||
UNICODE_STRING ustrDevice;
|
||||
DEVMODEW dmLocal;
|
||||
LONG lRet;
|
||||
|
||||
/* Check arguments */
|
||||
if ((dwflags != CDS_VIDEOPARAMETERS) && (lParam != NULL))
|
||||
{
|
||||
EngSetLastError(ERROR_INVALID_PARAMETER);
|
||||
return DISP_CHANGE_BADPARAM;
|
||||
}
|
||||
|
||||
/* Check flags */
|
||||
if ((dwflags & (CDS_GLOBAL|CDS_NORESET)) && !(dwflags & CDS_UPDATEREGISTRY))
|
||||
{
|
||||
return DISP_CHANGE_BADFLAGS;
|
||||
}
|
||||
|
||||
/* Copy the device name */
|
||||
if (pustrDevice)
|
||||
{
|
||||
/* Initialize destination string */
|
||||
RtlInitEmptyUnicodeString(&ustrDevice, awcDevice, sizeof(awcDevice));
|
||||
|
||||
_SEH2_TRY
|
||||
{
|
||||
/* Probe the UNICODE_STRING and the buffer */
|
||||
ProbeForRead(pustrDevice, sizeof(UNICODE_STRING), 1);
|
||||
ProbeForRead(pustrDevice->Buffer, pustrDevice->Length, 1);
|
||||
|
||||
/* Copy the string */
|
||||
RtlCopyUnicodeString(&ustrDevice, pustrDevice);
|
||||
}
|
||||
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
||||
{
|
||||
/* Set and return error */
|
||||
SetLastNtError(_SEH2_GetExceptionCode());
|
||||
_SEH2_YIELD(return DISP_CHANGE_BADPARAM);
|
||||
}
|
||||
_SEH2_END
|
||||
|
||||
pustrDevice = &ustrDevice;
|
||||
}
|
||||
|
||||
/* Copy devmode */
|
||||
if (lpDevMode)
|
||||
{
|
||||
_SEH2_TRY
|
||||
{
|
||||
/* Probe the size field of the structure */
|
||||
ProbeForRead(lpDevMode, sizeof(dmLocal.dmSize), 1);
|
||||
|
||||
/* Calculate usable size */
|
||||
dmLocal.dmSize = min(sizeof(dmLocal), lpDevMode->dmSize);
|
||||
|
||||
/* Probe and copy the full DEVMODE */
|
||||
ProbeForRead(lpDevMode, dmLocal.dmSize, 1);
|
||||
RtlCopyMemory(&dmLocal, lpDevMode, dmLocal.dmSize);
|
||||
}
|
||||
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
||||
{
|
||||
/* Set and return error */
|
||||
SetLastNtError(_SEH2_GetExceptionCode());
|
||||
_SEH2_YIELD(return DISP_CHANGE_BADPARAM);
|
||||
}
|
||||
_SEH2_END
|
||||
|
||||
/* Check for extra parameters */
|
||||
if (dmLocal.dmDriverExtra > 0)
|
||||
{
|
||||
/* FIXME: TODO */
|
||||
ERR("lpDevMode->dmDriverExtra is IGNORED!\n");
|
||||
dmLocal.dmDriverExtra = 0;
|
||||
}
|
||||
|
||||
/* Use the local structure */
|
||||
lpDevMode = &dmLocal;
|
||||
}
|
||||
|
||||
// FIXME: Copy videoparameters
|
||||
|
||||
/* Acquire global USER lock */
|
||||
UserEnterExclusive();
|
||||
|
||||
/* Call internal function */
|
||||
lRet = UserChangeDisplaySettings(pustrDevice, lpDevMode, dwflags, NULL);
|
||||
|
||||
/* Release lock */
|
||||
UserLeave();
|
||||
|
||||
return lRet;
|
||||
}
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue