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/winent... ============================================================================== --- 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/win32... ============================================================================== --- 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/win32... ============================================================================== --- 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/win32... ============================================================================== --- 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/win32... ============================================================================== --- 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/win32... ============================================================================== --- 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/win32... ============================================================================== --- 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>