Author: khornicek
Date: Wed Dec 2 14:17:44 2009
New Revision: 44361
URL:
http://svn.reactos.org/svn/reactos?rev=44361&view=rev
Log:
- bring support for EnumDisplaySettings and ChangeDisplaySettings from trunk
Added:
branches/arwinss/reactos/subsystems/win32/win32k/main/display.c (with props)
Modified:
branches/arwinss/reactos/dll/win32/winent.drv/userdrv.c
branches/arwinss/reactos/include/reactos/win32k/rosuser.h
branches/arwinss/reactos/subsystems/win32/win32k/eng/device.c
branches/arwinss/reactos/subsystems/win32/win32k/include/dc.h
branches/arwinss/reactos/subsystems/win32/win32k/include/gre.h
branches/arwinss/reactos/subsystems/win32/win32k/w32ksvc.db
branches/arwinss/reactos/subsystems/win32/win32k/win32k.rbuild
Modified: branches/arwinss/reactos/dll/win32/winent.drv/userdrv.c
URL:
http://svn.reactos.org/svn/reactos/branches/arwinss/reactos/dll/win32/winen…
==============================================================================
--- branches/arwinss/reactos/dll/win32/winent.drv/userdrv.c [iso-8859-1] (original)
+++ branches/arwinss/reactos/dll/win32/winent.drv/userdrv.c [iso-8859-1] Wed Dec 2
14:17:44 2009
@@ -366,8 +366,15 @@
LONG CDECL RosDrv_ChangeDisplaySettingsEx( LPCWSTR name, LPDEVMODEW mode, HWND hwnd,
DWORD flags, LPVOID lparam )
{
- UNIMPLEMENTED;
- return DISP_CHANGE_FAILED;
+ UNICODE_STRING usDeviceName, *pusDeviceName = NULL;
+
+ if (name)
+ {
+ RtlInitUnicodeString(&usDeviceName, name);
+ pusDeviceName = &usDeviceName;
+ }
+
+ return RosUserChangeDisplaySettings(pusDeviceName, mode, hwnd, flags, lparam);
}
BOOL CDECL RosDrv_EnumDisplayMonitors( HDC hdc, LPRECT rect, MONITORENUMPROC proc, LPARAM
lp )
@@ -433,8 +440,15 @@
BOOL CDECL RosDrv_EnumDisplaySettingsEx( LPCWSTR name, DWORD num, LPDEVMODEW mode, DWORD
flags )
{
- UNIMPLEMENTED;
- return FALSE;
+ UNICODE_STRING usDeviceName, *pusDeviceName = NULL;
+
+ if (name)
+ {
+ RtlInitUnicodeString(&usDeviceName, name);
+ pusDeviceName = &usDeviceName;
+ }
+
+ return NT_SUCCESS(RosUserEnumDisplaySettings(pusDeviceName, num, mode, flags));
}
BOOL CDECL RosDrv_GetMonitorInfo( HMONITOR handle, LPMONITORINFO info )
Modified: branches/arwinss/reactos/include/reactos/win32k/rosuser.h
URL:
http://svn.reactos.org/svn/reactos/branches/arwinss/reactos/include/reactos…
==============================================================================
--- branches/arwinss/reactos/include/reactos/win32k/rosuser.h [iso-8859-1] (original)
+++ branches/arwinss/reactos/include/reactos/win32k/rosuser.h [iso-8859-1] Wed Dec 2
14:17:44 2009
@@ -49,12 +49,29 @@
void NTAPI
RosUserSetCursor( ICONINFO* IconInfo );
+LONG
+APIENTRY
+RosUserChangeDisplaySettings(
+ PUNICODE_STRING lpszDeviceName,
+ LPDEVMODEW lpDevMode,
+ HWND hwnd,
+ DWORD dwflags,
+ LPVOID lParam);
+
INT
APIENTRY
RosUserEnumDisplayMonitors(
OPTIONAL OUT HMONITOR *hMonitorList,
OPTIONAL OUT PRECTL monitorRectList,
OPTIONAL IN DWORD listSize);
+
+NTSTATUS
+APIENTRY
+RosUserEnumDisplaySettings(
+ PUNICODE_STRING pusDeviceName,
+ DWORD iModeNum,
+ LPDEVMODEW lpDevMode,
+ DWORD dwFlags );
BOOL
APIENTRY
Modified: branches/arwinss/reactos/subsystems/win32/win32k/eng/device.c
URL:
http://svn.reactos.org/svn/reactos/branches/arwinss/reactos/subsystems/win3…
==============================================================================
--- branches/arwinss/reactos/subsystems/win32/win32k/eng/device.c [iso-8859-1] (original)
+++ branches/arwinss/reactos/subsystems/win32/win32k/eng/device.c [iso-8859-1] Wed Dec 2
14:17:44 2009
@@ -508,10 +508,10 @@
return FALSE;
}
- /*if (! PrepareVideoPrt())
+ if (! PrepareVideoPrt())
{
return FALSE;
- }*/
+ }
/* Enable the drawing surface */
PrimarySurface.pSurface =
@@ -568,6 +568,612 @@
KeResetEvent(&VideoDriverPrepared);
ObDereferenceObject(PrimarySurface.VideoFileObject);
+}
+
+NTSTATUS FASTCALL
+GetVideoRegistryKey(
+ OUT PUNICODE_STRING RegistryPath,
+ IN PCUNICODE_STRING DeviceName) /* ex: "\Device\Video0" */
+{
+ RTL_QUERY_REGISTRY_TABLE QueryTable[2];
+ NTSTATUS Status;
+
+ RtlInitUnicodeString(RegistryPath, NULL);
+ RtlZeroMemory(QueryTable, sizeof(QueryTable));
+ QueryTable[0].Flags = RTL_QUERY_REGISTRY_REQUIRED | RTL_QUERY_REGISTRY_DIRECT;
+ QueryTable[0].Name = DeviceName->Buffer;
+ QueryTable[0].EntryContext = RegistryPath;
+
+ Status = RtlQueryRegistryValues(RTL_REGISTRY_DEVICEMAP,
+ L"VIDEO",
+ QueryTable,
+ NULL,
+ NULL);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("No %wZ value in DEVICEMAP\\VIDEO found (Status 0x%08lx)\n",
DeviceName, Status);
+ return STATUS_NO_SUCH_DEVICE;
+ }
+
+ DPRINT("RegistryPath %wZ\n", RegistryPath);
+ return STATUS_SUCCESS;
+}
+
+static NTSTATUS FASTCALL
+GetVideoDeviceName(
+ OUT PUNICODE_STRING VideoDeviceName,
+ IN PCUNICODE_STRING DisplayDevice) /* ex: "\.\DISPLAY1" or
"\??\DISPLAY1" */
+{
+ UNICODE_STRING Prefix = RTL_CONSTANT_STRING(L"\\??\\");
+ UNICODE_STRING ObjectName;
+ UNICODE_STRING KernelModeName = { 0, };
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ USHORT LastSlash;
+ ULONG Length;
+ HANDLE LinkHandle = NULL;
+ NTSTATUS Status;
+
+ RtlInitUnicodeString(VideoDeviceName, NULL);
+
+ /* Get device name (DisplayDevice is "\.\xxx") */
+ for (LastSlash = DisplayDevice->Length / sizeof(WCHAR); LastSlash > 0;
LastSlash--)
+ {
+ if (DisplayDevice->Buffer[LastSlash - 1] == L'\\')
+ break;
+ }
+
+ if (LastSlash == 0)
+ {
+ DPRINT1("Invalid device name '%wZ'\n", DisplayDevice);
+ Status = STATUS_OBJECT_NAME_INVALID;
+ goto cleanup;
+ }
+ ObjectName = *DisplayDevice;
+ ObjectName.Length -= LastSlash * sizeof(WCHAR);
+ ObjectName.MaximumLength -= LastSlash * sizeof(WCHAR);
+ ObjectName.Buffer += LastSlash;
+
+ /* Create "\??\xxx" (ex: "\??\DISPLAY1") */
+ KernelModeName.MaximumLength = Prefix.Length + ObjectName.Length +
sizeof(UNICODE_NULL);
+ KernelModeName.Buffer = ExAllocatePoolWithTag(PagedPool,
+ KernelModeName.MaximumLength,
+ TAG_DC);
+ if (!KernelModeName.Buffer)
+ {
+ Status = STATUS_NO_MEMORY;
+ goto cleanup;
+ }
+ RtlCopyUnicodeString(&KernelModeName, &Prefix);
+ Status = RtlAppendUnicodeStringToString(&KernelModeName, &ObjectName);
+ if (!NT_SUCCESS(Status))
+ goto cleanup;
+
+ /* Open \??\xxx (ex: "\??\DISPLAY1") */
+ InitializeObjectAttributes(&ObjectAttributes,
+ &KernelModeName,
+ OBJ_KERNEL_HANDLE,
+ NULL,
+ NULL);
+ Status = ZwOpenSymbolicLinkObject(&LinkHandle,
+ GENERIC_READ,
+ &ObjectAttributes);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("Unable to open symbolic link %wZ (Status 0x%08lx)\n",
&KernelModeName, Status);
+ Status = STATUS_NO_SUCH_DEVICE;
+ goto cleanup;
+ }
+
+ Status = ZwQuerySymbolicLinkObject(LinkHandle, VideoDeviceName, &Length);
+ if (!NT_SUCCESS(Status) && Status != STATUS_BUFFER_TOO_SMALL)
+ {
+ DPRINT1("Unable to query symbolic link %wZ (Status 0x%08lx)\n",
&KernelModeName, Status);
+ Status = STATUS_NO_SUCH_DEVICE;
+ goto cleanup;
+ }
+ VideoDeviceName->MaximumLength = Length;
+ VideoDeviceName->Buffer = ExAllocatePoolWithTag(PagedPool,
+ VideoDeviceName->MaximumLength + sizeof(UNICODE_NULL),
+ TAG_DC);
+ if (!VideoDeviceName->Buffer)
+ {
+ Status = STATUS_NO_MEMORY;
+ goto cleanup;
+ }
+ Status = ZwQuerySymbolicLinkObject(LinkHandle, VideoDeviceName, NULL);
+ VideoDeviceName->Buffer[VideoDeviceName->MaximumLength / sizeof(WCHAR) - 1] =
UNICODE_NULL;
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("Unable to query symbolic link %wZ (Status 0x%08lx)\n",
&KernelModeName, Status);
+ Status = STATUS_NO_SUCH_DEVICE;
+ goto cleanup;
+ }
+ Status = STATUS_SUCCESS;
+
+cleanup:
+ if (!NT_SUCCESS(Status) && VideoDeviceName->Buffer)
+ ExFreePoolWithTag(VideoDeviceName->Buffer, TAG_DC);
+ if (KernelModeName.Buffer)
+ ExFreePoolWithTag(KernelModeName.Buffer, TAG_DC);
+ if (LinkHandle)
+ ZwClose(LinkHandle);
+ return Status;
+}
+
+LONG
+FASTCALL
+GreChangeDisplaySettings(
+ IN PUNICODE_STRING pDeviceName OPTIONAL,
+ IN LPDEVMODEW DevMode,
+ IN DWORD dwflags,
+ IN PVOID lParam OPTIONAL)
+{
+ BOOLEAN Global = FALSE;
+ BOOLEAN NoReset = FALSE;
+ BOOLEAN Reset = FALSE;
+ BOOLEAN SetPrimary = FALSE;
+ LONG Ret = DISP_CHANGE_SUCCESSFUL;
+ NTSTATUS Status ;
+
+ DPRINT1("display flags : %x\n",dwflags);
+
+ if ((dwflags & CDS_UPDATEREGISTRY) == CDS_UPDATEREGISTRY)
+ {
+ /* Check global, reset and noreset flags */
+ if ((dwflags & CDS_GLOBAL) == CDS_GLOBAL)
+ Global = TRUE;
+ if ((dwflags & CDS_NORESET) == CDS_NORESET)
+ NoReset = TRUE;
+ dwflags &= ~(CDS_GLOBAL | CDS_NORESET);
+ }
+ if ((dwflags & CDS_RESET) == CDS_RESET)
+ Reset = TRUE;
+ if ((dwflags & CDS_SET_PRIMARY) == CDS_SET_PRIMARY)
+ SetPrimary = TRUE;
+ dwflags &= ~(CDS_RESET | CDS_SET_PRIMARY);
+
+ if (Reset && NoReset)
+ return DISP_CHANGE_BADFLAGS;
+
+ if (dwflags == 0)
+ {
+ /* Dynamically change graphics mode */
+ DPRINT1("flag 0 UNIMPLEMENTED\n");
+ return DISP_CHANGE_FAILED;
+ SetLastWin32Error(ERROR_CALL_NOT_IMPLEMENTED);
+ }
+
+ if ((dwflags & CDS_TEST) == CDS_TEST)
+ {
+ /* Test resolution */
+ dwflags &= ~CDS_TEST;
+ Status = GreEnumDisplaySettings(pDeviceName, ENUM_REGISTRY_SETTINGS, DevMode,
0);
+ if (!NT_SUCCESS(Status))
+ Ret = DISP_CHANGE_BADMODE;
+ return Ret;
+ }
+
+ if ((dwflags & CDS_FULLSCREEN) == CDS_FULLSCREEN)
+ {
+ DEVMODEW lpDevMode;
+ /* Full Screen */
+ dwflags &= ~CDS_FULLSCREEN;
+ DPRINT1("flag CDS_FULLSCREEN partially implemented\n");
+ Ret = DISP_CHANGE_FAILED;
+
+ RtlZeroMemory(&lpDevMode, sizeof(DEVMODEW));
+ lpDevMode.dmSize = sizeof(DEVMODEW);
+
+ Status = GreEnumDisplaySettings(pDeviceName, ENUM_CURRENT_SETTINGS,
&lpDevMode, 0);
+ if (!NT_SUCCESS(Status))
+ return DISP_CHANGE_FAILED;
+
+ DPRINT1("Req Mode : %d x %d x %d\n",
DevMode->dmPelsWidth,DevMode->dmPelsHeight,DevMode->dmBitsPerPel);
+ DPRINT1("Current Mode : %d x %d x %d\n",
lpDevMode.dmPelsWidth,lpDevMode.dmPelsHeight, lpDevMode.dmBitsPerPel);
+
+
+ if ((lpDevMode.dmBitsPerPel == DevMode->dmBitsPerPel) &&
+ (lpDevMode.dmPelsWidth == DevMode->dmPelsWidth) &&
+ (lpDevMode.dmPelsHeight == DevMode->dmPelsHeight))
+ Ret = DISP_CHANGE_SUCCESSFUL;
+ }
+
+ if ((dwflags & CDS_VIDEOPARAMETERS) == CDS_VIDEOPARAMETERS)
+ {
+ dwflags &= ~CDS_VIDEOPARAMETERS;
+ if (lParam == NULL)
+ Ret=DISP_CHANGE_BADPARAM;
+ else
+ {
+ DPRINT1("flag CDS_VIDEOPARAMETERS UNIMPLEMENTED\n");
+ Ret = DISP_CHANGE_FAILED;
+ SetLastWin32Error(ERROR_CALL_NOT_IMPLEMENTED);
+ }
+
+ }
+
+ if ((dwflags & CDS_UPDATEREGISTRY) == CDS_UPDATEREGISTRY)
+ {
+
+ UNICODE_STRING DeviceName;
+ UNICODE_STRING RegistryKey;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ HANDLE DevInstRegKey;
+ ULONG NewValue;
+
+ DPRINT1("set CDS_UPDATEREGISTRY\n");
+
+ dwflags &= ~CDS_UPDATEREGISTRY;
+
+ /* Check if pDeviceName is NULL, we need to retrieve it */
+ if (pDeviceName == NULL)
+ {
+ // FIXME
+ DPRINT1("fixme: pDeviceName is NULL\n");
+ return DISP_CHANGE_FAILED;
+ }
+
+ Status = GetVideoDeviceName(&DeviceName, pDeviceName);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("Unable to get destination of '%wZ' (Status
0x%08lx)\n", pDeviceName, Status);
+ return DISP_CHANGE_FAILED;
+ }
+ Status = GetVideoRegistryKey(&RegistryKey, &DeviceName);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("Unable to get registry key for '%wZ' (Status
0x%08lx)\n", &DeviceName, Status);
+ ExFreePoolWithTag(DeviceName.Buffer, TAG_DC);
+ return DISP_CHANGE_FAILED;
+ }
+ ExFreePoolWithTag(DeviceName.Buffer, TAG_DC);
+
+ InitializeObjectAttributes(&ObjectAttributes, &RegistryKey,
+ OBJ_CASE_INSENSITIVE, NULL, NULL);
+ Status = ZwOpenKey(&DevInstRegKey, KEY_SET_VALUE, &ObjectAttributes);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("Unable to open registry key %wZ (Status 0x%08lx)\n",
&RegistryKey, Status);
+ ExFreePoolWithTag(RegistryKey.Buffer, TAG_RTLREGISTRY);
+ return DISP_CHANGE_FAILED;
+ }
+ ExFreePoolWithTag(RegistryKey.Buffer, TAG_RTLREGISTRY);
+
+ /* Update needed fields */
+ if (NT_SUCCESS(Status) && DevMode->dmFields & DM_BITSPERPEL)
+ {
+ RtlInitUnicodeString(&RegistryKey,
L"DefaultSettings.BitsPerPel");
+ NewValue = DevMode->dmBitsPerPel;
+ Status = ZwSetValueKey(DevInstRegKey, &RegistryKey, 0, REG_DWORD,
&NewValue, sizeof(NewValue));
+ }
+
+ if (NT_SUCCESS(Status) && DevMode->dmFields & DM_PELSWIDTH)
+ {
+ RtlInitUnicodeString(&RegistryKey,
L"DefaultSettings.XResolution");
+ NewValue = DevMode->dmPelsWidth;
+ Status = ZwSetValueKey(DevInstRegKey, &RegistryKey, 0, REG_DWORD,
&NewValue, sizeof(NewValue));
+ }
+
+ if (NT_SUCCESS(Status) && DevMode->dmFields & DM_PELSHEIGHT)
+ {
+ RtlInitUnicodeString(&RegistryKey,
L"DefaultSettings.YResolution");
+ NewValue = DevMode->dmPelsHeight;
+ Status = ZwSetValueKey(DevInstRegKey, &RegistryKey, 0, REG_DWORD,
&NewValue, sizeof(NewValue));
+ }
+
+ if (NT_SUCCESS(Status) && DevMode->dmFields &
DM_DISPLAYFREQUENCY)
+ {
+ RtlInitUnicodeString(&RegistryKey,
L"DefaultSettings.VRefresh");
+ NewValue = DevMode->dmDisplayFrequency;
+ Status = ZwSetValueKey(DevInstRegKey, &RegistryKey, 0, REG_DWORD,
&NewValue, sizeof(NewValue));
+ }
+
+ ZwClose(DevInstRegKey);
+ if (NT_SUCCESS(Status))
+ Ret = DISP_CHANGE_RESTART;
+ else
+ /* return DISP_CHANGE_NOTUPDATED when we can save to reg only valid for NT
*/
+ Ret = DISP_CHANGE_NOTUPDATED;
+ }
+
+ if (dwflags != 0)
+ Ret = DISP_CHANGE_BADFLAGS;
+
+ DPRINT("IntChangeDisplaySettings returning %x\n", Ret);
+ return Ret;
+}
+
+NTSTATUS FASTCALL
+GetDisplayNumberFromDeviceName(
+ IN PUNICODE_STRING pDeviceName OPTIONAL,
+ OUT ULONG *DisplayNumber)
+{
+ UNICODE_STRING DisplayString = RTL_CONSTANT_STRING(L"\\\\.\\DISPLAY");
+ NTSTATUS Status = STATUS_SUCCESS;
+ ULONG Length;
+ ULONG Number;
+ ULONG i;
+
+ if (DisplayNumber == NULL)
+ return STATUS_INVALID_PARAMETER_2;
+
+ /* Check if DeviceName is valid */
+ if (pDeviceName &&
+ pDeviceName->Length > 0 && pDeviceName->Length <=
DisplayString.Length)
+ return STATUS_OBJECT_NAME_INVALID;
+
+ if (pDeviceName == NULL || pDeviceName->Length == 0)
+ {
+ /* FIXME
+
+ PWINDOW_OBJECT DesktopObject;
+ HDC DesktopHDC;
+ PDC pDC;
+
+ DesktopObject = UserGetDesktopWindow();
+ DesktopHDC = UserGetWindowDC(DesktopObject);
+ pDC = DC_LockDc(DesktopHDC);
+
+ *DisplayNumber = pDC->ppdev->DisplayNumber;
+
+ DC_UnlockDc(pDC);
+ UserReleaseDC(DesktopObject, DesktopHDC, FALSE);
+ */
+ *DisplayNumber = 1;
+ DPRINT1("FIXME: DeviceName is NULL, trying display nr. 1\n");
+ return STATUS_SUCCESS;
+ }
+
+ /* Hack to check if the first parts are equal, by faking the device name length */
+ Length = pDeviceName->Length;
+ pDeviceName->Length = DisplayString.Length;
+ if (RtlEqualUnicodeString(&DisplayString, pDeviceName, FALSE) == FALSE)
+ Status = STATUS_OBJECT_NAME_INVALID;
+ pDeviceName->Length = Length;
+
+ if (NT_SUCCESS(Status))
+ {
+ /* Convert the last part of pDeviceName to a number */
+ Number = 0;
+ Length = pDeviceName->Length / sizeof(WCHAR);
+ for (i = DisplayString.Length / sizeof(WCHAR); i < Length; i++)
+ {
+ WCHAR Char = pDeviceName->Buffer[i];
+ if (Char >= L'0' && Char <= L'9')
+ Number = Number * 10 + Char - L'0';
+ else if (Char != L'\0')
+ return STATUS_OBJECT_NAME_INVALID;
+ }
+
+ *DisplayNumber = Number - 1;
+ }
+
+ return Status;
+}
+
+NTSTATUS
+FASTCALL
+GreEnumDisplaySettings(
+ IN PUNICODE_STRING pDeviceName OPTIONAL,
+ IN DWORD iModeNum,
+ IN OUT LPDEVMODEW pDevMode,
+ IN DWORD dwFlags)
+{
+ static DEVMODEW *CachedDevModes = NULL, *CachedDevModesEnd = NULL;
+ static DWORD SizeOfCachedDevModes = 0;
+ static UNICODE_STRING CachedDeviceName;
+ PDEVMODEW CachedMode = NULL;
+ DEVMODEW DevMode;
+ ULONG DisplayNumber;
+ NTSTATUS Status;
+
+ Status = GetDisplayNumberFromDeviceName(pDeviceName, &DisplayNumber);
+ if (!NT_SUCCESS(Status))
+ {
+ return Status;
+ }
+
+ DPRINT("DevMode->dmSize = %d\n", pDevMode->dmSize);
+ DPRINT("DevMode->dmExtraSize = %d\n", pDevMode->dmDriverExtra);
+
+ if (iModeNum == ENUM_CURRENT_SETTINGS)
+ {
+ CachedMode = &PrimarySurface.DMW;
+ ASSERT(CachedMode->dmSize > 0);
+ }
+ else if (iModeNum == ENUM_REGISTRY_SETTINGS)
+ {
+ RtlZeroMemory(&DevMode, sizeof (DevMode));
+ DevMode.dmSize = sizeof (DevMode);
+ DevMode.dmDriverExtra = 0;
+ if (SetupDevMode(&DevMode, DisplayNumber))
+ CachedMode = &DevMode;
+ else
+ {
+ return STATUS_UNSUCCESSFUL; // FIXME: what status?
+ }
+ /* FIXME: Maybe look for the matching devmode supplied by the
+ * driver so we can provide driver private/extra data?
+ */
+ }
+ else
+ {
+ BOOL IsCachedDevice = (CachedDevModes != NULL);
+
+ if (CachedDevModes &&
+ ((pDeviceName == NULL && CachedDeviceName.Length > 0) ||
+ (pDeviceName != NULL && pDeviceName->Buffer != NULL
&& CachedDeviceName.Length == 0) ||
+ (pDeviceName != NULL && pDeviceName->Buffer != NULL
&& CachedDeviceName.Length > 0 && RtlEqualUnicodeString(pDeviceName,
&CachedDeviceName, TRUE) == FALSE)))
+ {
+ IsCachedDevice = FALSE;
+ }
+
+ if (iModeNum == 0 || IsCachedDevice == FALSE) /* query modes from drivers */
+ {
+ UNICODE_STRING DriverFileNames;
+ LPWSTR CurrentName;
+ DRVENABLEDATA DrvEnableData;
+
+ /* Free resources from last driver cache */
+ if (IsCachedDevice == FALSE && CachedDeviceName.Buffer != NULL)
+ {
+ RtlFreeUnicodeString(&CachedDeviceName);
+ }
+
+ /* Retrieve DDI driver names from registry */
+ RtlInitUnicodeString(&DriverFileNames, NULL);
+ if (!FindDriverFileNames(&DriverFileNames, DisplayNumber))
+ {
+ DPRINT1("FindDriverFileNames failed\n");
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ if (!IntPrepareDriverIfNeeded())
+ {
+ DPRINT1("IntPrepareDriverIfNeeded failed\n");
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ /*
+ * DriverFileNames may be a list of drivers in REG_SZ_MULTI format,
+ * scan all of them until a good one found.
+ */
+ CurrentName = DriverFileNames.Buffer;
+ for (;CurrentName < DriverFileNames.Buffer + (DriverFileNames.Length /
sizeof (WCHAR));
+ CurrentName += wcslen(CurrentName) + 1)
+ {
+ INT i;
+ PFN_DrvEnableDriver GDEnableDriver;
+ PFN_DrvGetModes GetModes = NULL;
+ INT SizeNeeded, SizeUsed;
+
+ /* Get the DDI driver's entry point */
+ //GDEnableDriver = DRIVER_FindDDIDriver(CurrentName);
+ GDEnableDriver = DRIVER_FindExistingDDIDriver(L"DISPLAY");
+ if (NULL == GDEnableDriver)
+ {
+ DPRINT("FindDDIDriver failed for %S\n", CurrentName);
+ continue;
+ }
+
+ /* Call DDI driver's EnableDriver function */
+ RtlZeroMemory(&DrvEnableData, sizeof(DrvEnableData));
+
+ if (!GDEnableDriver(DDI_DRIVER_VERSION_NT5_01, sizeof (DrvEnableData),
&DrvEnableData))
+ {
+ DPRINT("DrvEnableDriver failed for %S\n", CurrentName);
+ continue;
+ }
+
+ CachedDevModesEnd = CachedDevModes;
+
+ /* find DrvGetModes function */
+ for (i = 0; i < DrvEnableData.c; i++)
+ {
+ PDRVFN DrvFn = DrvEnableData.pdrvfn + i;
+
+ if (DrvFn->iFunc == INDEX_DrvGetModes)
+ {
+ GetModes = (PFN_DrvGetModes)DrvFn->pfn;
+ break;
+ }
+ }
+
+ if (GetModes == NULL)
+ {
+ DPRINT("DrvGetModes doesn't exist for %S\n",
CurrentName);
+ continue;
+ }
+
+ /* make sure we have enough memory to hold the modes */
+ SizeNeeded =
GetModes((HANDLE)(PrimarySurface.VideoFileObject->DeviceObject), 0, NULL);
+ if (SizeNeeded <= 0)
+ {
+ DPRINT("DrvGetModes failed for %S\n", CurrentName);
+ break;
+ }
+
+ SizeUsed = (PCHAR)CachedDevModesEnd - (PCHAR)CachedDevModes;
+ if (SizeOfCachedDevModes < SizeUsed + SizeNeeded)
+ {
+ PVOID NewBuffer;
+
+ SizeOfCachedDevModes += SizeNeeded;
+ NewBuffer = ExAllocatePool(PagedPool, SizeOfCachedDevModes);
+ if (NewBuffer == NULL)
+ {
+ /* clean up */
+ ExFreePool(CachedDevModes);
+ CachedDevModes = NULL;
+ CachedDevModesEnd = NULL;
+ SizeOfCachedDevModes = 0;
+
+ if (CachedDeviceName.Buffer != NULL)
+ RtlFreeUnicodeString(&CachedDeviceName);
+
+ return STATUS_NO_MEMORY;
+ }
+ if (CachedDevModes != NULL)
+ {
+ RtlCopyMemory(NewBuffer, CachedDevModes, SizeUsed);
+ ExFreePool(CachedDevModes);
+ }
+ CachedDevModes = NewBuffer;
+ CachedDevModesEnd = (DEVMODEW *)((PCHAR)NewBuffer + SizeUsed);
+ }
+
+ if (!IsCachedDevice)
+ {
+ if (CachedDeviceName.Buffer != NULL)
+ RtlFreeUnicodeString(&CachedDeviceName);
+
+ if (pDeviceName)
+ RtlCopyUnicodeString(&CachedDeviceName, pDeviceName);
+
+ IsCachedDevice = TRUE;
+ }
+
+ /* query modes */
+ SizeNeeded =
GetModes((HANDLE)(PrimarySurface.VideoFileObject->DeviceObject),
+ SizeNeeded,
+ CachedDevModesEnd);
+ if (SizeNeeded <= 0)
+ {
+ DPRINT("DrvGetModes failed for %S\n", CurrentName);
+ }
+ else
+ {
+ CachedDevModesEnd = (DEVMODEW *)((PCHAR)CachedDevModesEnd +
SizeNeeded);
+ }
+ }
+
+ ExFreePoolWithTag(DriverFileNames.Buffer, TAG_RTLREGISTRY);
+ }
+
+ /* return cached info */
+ CachedMode = CachedDevModes;
+ if (CachedMode >= CachedDevModesEnd)
+ {
+ return STATUS_NO_MORE_ENTRIES;
+ }
+ while (iModeNum-- > 0 && CachedMode < CachedDevModesEnd)
+ {
+ assert(CachedMode->dmSize > 0);
+ CachedMode = (DEVMODEW *)((PCHAR)CachedMode + CachedMode->dmSize +
CachedMode->dmDriverExtra);
+ }
+ if (CachedMode >= CachedDevModesEnd)
+ {
+ return STATUS_NO_MORE_ENTRIES;
+ }
+ }
+
+ ASSERT(CachedMode != NULL);
+
+ RtlCopyMemory(pDevMode, CachedMode, min(pDevMode->dmSize,
CachedMode->dmSize));
+ RtlZeroMemory(pDevMode + pDevMode->dmSize, pDevMode->dmDriverExtra);
+ RtlCopyMemory(pDevMode + min(pDevMode->dmSize, CachedMode->dmSize), CachedMode
+ CachedMode->dmSize, min(pDevMode->dmDriverExtra, CachedMode->dmDriverExtra));
+
+ return STATUS_SUCCESS;
}
INT APIENTRY
Modified: branches/arwinss/reactos/subsystems/win32/win32k/include/dc.h
URL:
http://svn.reactos.org/svn/reactos/branches/arwinss/reactos/subsystems/win3…
==============================================================================
--- branches/arwinss/reactos/subsystems/win32/win32k/include/dc.h [iso-8859-1] (original)
+++ branches/arwinss/reactos/subsystems/win32/win32k/include/dc.h [iso-8859-1] Wed Dec 2
14:17:44 2009
@@ -34,7 +34,4 @@
((PDC) GDIOBJ_LockObj ((HGDIOBJ) hDC, GDI_OBJECT_TYPE_DC))
#define DC_Unlock(pDC) \
GDIOBJ_UnlockObjByPtr ((PBASEOBJECT)pDC)
-
-INT APIENTRY GreGetDeviceCaps(PDC pDC, INT cap);
-
#endif
Modified: branches/arwinss/reactos/subsystems/win32/win32k/include/gre.h
URL:
http://svn.reactos.org/svn/reactos/branches/arwinss/reactos/subsystems/win3…
==============================================================================
--- branches/arwinss/reactos/subsystems/win32/win32k/include/gre.h [iso-8859-1]
(original)
+++ branches/arwinss/reactos/subsystems/win32/win32k/include/gre.h [iso-8859-1] Wed Dec 2
14:17:44 2009
@@ -83,6 +83,14 @@
extern HGDIOBJ hStockBmp;
VOID CreateStockBitmap();
+/* device.c */
+LONG FASTCALL GreChangeDisplaySettings(PUNICODE_STRING pDeviceName,
+ LPDEVMODEW DevMode, DWORD dwflags,
+ PVOID lParam);
+NTSTATUS FASTCALL GreEnumDisplaySettings(PUNICODE_STRING pDeviceName, DWORD iModeNum,
+ LPDEVMODEW pDevMode, DWORD dwFlags);
+INT APIENTRY GreGetDeviceCaps(PDC pDC, INT cap);
+
/* font.c */
VOID NTAPI
GreTextOut(PDC pDC, INT x, INT y, UINT flags,
Added: branches/arwinss/reactos/subsystems/win32/win32k/main/display.c
URL:
http://svn.reactos.org/svn/reactos/branches/arwinss/reactos/subsystems/win3…
==============================================================================
--- branches/arwinss/reactos/subsystems/win32/win32k/main/display.c (added)
+++ branches/arwinss/reactos/subsystems/win32/win32k/main/display.c [iso-8859-1] Wed Dec
2 14:17:44 2009
@@ -1,0 +1,195 @@
+/*
+ * PROJECT: ReactOS Win32K
+ * LICENSE: LGPL - See COPYING in the top level directory
+ * FILE: subsystems/win32/win32k/main/display.c
+ * PURPOSE: ReactOS display settings support
+ */
+
+#include <win32k.h>
+#define NDEBUG
+#include <debug.h>
+
+
+NTSTATUS
+APIENTRY
+RosUserEnumDisplaySettings(
+ PUNICODE_STRING pusDeviceName,
+ DWORD iModeNum,
+ LPDEVMODEW lpDevMode,
+ DWORD dwFlags )
+{
+ NTSTATUS Status;
+ LPDEVMODEW pSafeDevMode = NULL;
+ PUNICODE_STRING pusSafeDeviceName = NULL;
+ UNICODE_STRING usSafeDeviceName;
+ USHORT ExtraSize = 0;
+
+ _SEH2_TRY
+ {
+ ProbeForRead(lpDevMode, sizeof(DEVMODEW), 1);
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ DPRINT("FIXME: DEVMODEW size out of range\n");
+ _SEH2_YIELD(return _SEH2_GetExceptionCode());
+ }
+ _SEH2_END;
+
+ if (lpDevMode->dmSize != sizeof(DEVMODEW))
+ {
+ return STATUS_BUFFER_TOO_SMALL;
+ }
+
+ pSafeDevMode = ExAllocatePool(PagedPool, sizeof(DEVMODEW) +
lpDevMode->dmDriverExtra);
+
+ if (pSafeDevMode == NULL)
+ {
+ return STATUS_NO_MEMORY;
+ }
+
+ pSafeDevMode->dmSize = sizeof(DEVMODEW);
+ pSafeDevMode->dmDriverExtra = lpDevMode->dmDriverExtra;
+
+ ExtraSize = pSafeDevMode->dmDriverExtra;
+
+ /* Copy the device name */
+ if (pusDeviceName != NULL)
+ {
+ _SEH2_TRY
+ {
+ RtlInitUnicodeString(&usSafeDeviceName, pusDeviceName->Buffer);
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ ExFreePool(pSafeDevMode);
+ _SEH2_YIELD(return STATUS_UNSUCCESSFUL);
+ }
+ _SEH2_END;
+ pusSafeDeviceName = &usSafeDeviceName;
+ }
+
+ /* Call internal function */
+ Status = GreEnumDisplaySettings(pusSafeDeviceName, iModeNum, pSafeDevMode, dwFlags);
+
+ if (!NT_SUCCESS(Status))
+ {
+ ExFreePool(pSafeDevMode);
+ return Status;
+ }
+
+ /* Copy some information back */
+ _SEH2_TRY
+ {
+ ProbeForWrite(lpDevMode,sizeof(DEVMODEW) + ExtraSize, 1);
+ lpDevMode->dmPelsWidth = pSafeDevMode->dmPelsWidth;
+ lpDevMode->dmPelsHeight = pSafeDevMode->dmPelsHeight;
+ lpDevMode->dmBitsPerPel = pSafeDevMode->dmBitsPerPel;
+ lpDevMode->dmDisplayFrequency = pSafeDevMode->dmDisplayFrequency;
+ lpDevMode->dmDisplayFlags = pSafeDevMode->dmDisplayFlags;
+
+ /* output private/extra driver data */
+ if (ExtraSize > 0)
+ {
+ memcpy((PCHAR)lpDevMode + sizeof(DEVMODEW), (PCHAR)pSafeDevMode +
sizeof(DEVMODEW), ExtraSize);
+ }
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ Status = _SEH2_GetExceptionCode();
+ }
+ _SEH2_END;
+
+ ExFreePool(pSafeDevMode);
+ return Status;
+}
+
+LONG
+APIENTRY
+RosUserChangeDisplaySettings(
+ PUNICODE_STRING pusDeviceName,
+ LPDEVMODEW lpDevMode,
+ HWND hwnd,
+ DWORD dwflags,
+ LPVOID lParam)
+{
+ LPDEVMODEW pSafeDevMode = NULL;
+ PUNICODE_STRING pusSafeDeviceName = NULL;
+ UNICODE_STRING usSafeDeviceName;
+ LONG Ret;
+ WORD Size;
+
+ /* Check arguments */
+#ifdef CDS_VIDEOPARAMETERS
+
+ if (dwflags != CDS_VIDEOPARAMETERS && lParam != NULL)
+#else
+
+ if (lParam != NULL)
+#endif
+
+ {
+ SetLastWin32Error(ERROR_INVALID_PARAMETER);
+ return DISP_CHANGE_BADPARAM;
+ }
+ if (hwnd != NULL)
+ {
+ SetLastWin32Error(ERROR_INVALID_PARAMETER);
+ return DISP_CHANGE_BADPARAM;
+ }
+
+ /* Copy devmode */
+ _SEH2_TRY
+ {
+ ProbeForRead(lpDevMode, sizeof(DEVMODEW), 1);
+ Size = lpDevMode->dmSize;
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ DPRINT("FIXME: DEVMODEW size out of range\n");
+ _SEH2_YIELD(return _SEH2_GetExceptionCode());
+ }
+ _SEH2_END;
+
+ if (Size != sizeof(DEVMODEW))
+ {
+ SetLastNtError(STATUS_BUFFER_TOO_SMALL);
+ return DISP_CHANGE_BADPARAM;
+ }
+
+ pSafeDevMode = ExAllocatePool(PagedPool, Size);
+
+ if (pSafeDevMode == NULL)
+ {
+ return DISP_CHANGE_BADPARAM;
+ }
+
+ pSafeDevMode->dmSize = Size;
+
+ if(lpDevMode->dmDriverExtra != 0)
+ DPRINT1("ignoring DriverExtra\n");
+
+ pSafeDevMode->dmDriverExtra = 0;
+
+ RtlCopyMemory(pSafeDevMode, lpDevMode, pSafeDevMode->dmSize);
+
+ /* Copy the device name */
+ if (pusDeviceName != NULL)
+ {
+ _SEH2_TRY
+ {
+ RtlInitUnicodeString(&usSafeDeviceName, pusDeviceName->Buffer);
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ ExFreePool(pSafeDevMode);
+ _SEH2_YIELD(return DISP_CHANGE_BADPARAM);
+ }
+ _SEH2_END;
+ pusSafeDeviceName = &usSafeDeviceName;
+ }
+
+ /* Call internal function */
+ Ret = GreChangeDisplaySettings(pusSafeDeviceName, pSafeDevMode, dwflags, lParam);
+
+ return Ret;
+}
Propchange: branches/arwinss/reactos/subsystems/win32/win32k/main/display.c
------------------------------------------------------------------------------
svn:eol-style = native
Modified: branches/arwinss/reactos/subsystems/win32/win32k/w32ksvc.db
URL:
http://svn.reactos.org/svn/reactos/branches/arwinss/reactos/subsystems/win3…
==============================================================================
--- branches/arwinss/reactos/subsystems/win32/win32k/w32ksvc.db [iso-8859-1] (original)
+++ branches/arwinss/reactos/subsystems/win32/win32k/w32ksvc.db [iso-8859-1] Wed Dec 2
14:17:44 2009
@@ -70,7 +70,9 @@
RosUserSetCursorPos 2
RosUserClipCursor 1
RosUserSetCursor 1
+RosUserChangeDisplaySettings 5
RosUserEnumDisplayMonitors 3
+RosUserEnumDisplaySettings 4
RosUserGetMonitorInfo 2
RosUserGetKeyboardLayout 1
RosUserGetKeyboardLayoutName 1
Modified: branches/arwinss/reactos/subsystems/win32/win32k/win32k.rbuild
URL:
http://svn.reactos.org/svn/reactos/branches/arwinss/reactos/subsystems/win3…
==============================================================================
--- branches/arwinss/reactos/subsystems/win32/win32k/win32k.rbuild [iso-8859-1]
(original)
+++ branches/arwinss/reactos/subsystems/win32/win32k/win32k.rbuild [iso-8859-1] Wed Dec 2
14:17:44 2009
@@ -112,6 +112,7 @@
<file>err.c</file>
<file>init.c</file>
<file>cursor.c</file>
+ <file>display.c</file>
<file>monitor.c</file>
<file>kbdlayout.c</file>
<file>keyboard.c</file>