2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * PURPOSE: Video initialization and display settings
5 * FILE: subsystems/win32/win32k/ntuser/display.c
6 * PROGRAMER: Timo Kreuzer (timo.kreuzer@reactos.org)
16 PDEVOBJ
*gpdevPrimary
;
18 const PWCHAR KEY_ROOT
= L
"";
19 const PWCHAR KEY_VIDEO
= L
"\\Registry\\Machine\\HARDWARE\\DEVICEMAP\\VIDEO";
23 UserEnumDisplayDevices(
24 PUNICODE_STRING pustrDevice
,
26 PDISPLAY_DEVICEW pdispdev
,
30 RegWriteSZ(HKEY hkey
, PWSTR pwszValue
, PWSTR pwszData
)
32 UNICODE_STRING ustrValue
;
33 UNICODE_STRING ustrData
;
35 RtlInitUnicodeString(&ustrValue
, pwszValue
);
36 RtlInitUnicodeString(&ustrData
, pwszData
);
37 ZwSetValueKey(hkey
, &ustrValue
, 0, REG_SZ
, &ustrData
, ustrData
.Length
+ sizeof(WCHAR
));
41 RegWriteDWORD(HKEY hkey
, PWSTR pwszValue
, DWORD dwData
)
43 UNICODE_STRING ustrValue
;
45 RtlInitUnicodeString(&ustrValue
, pwszValue
);
46 ZwSetValueKey(hkey
, &ustrValue
, 0, REG_DWORD
, &dwData
, sizeof(DWORD
));
51 RegReadDWORD(HKEY hkey
, PWSTR pwszValue
, PDWORD pdwData
)
54 ULONG cbSize
= sizeof(DWORD
);
55 Status
= RegQueryValue(hkey
, pwszValue
, REG_DWORD
, pdwData
, &cbSize
);
56 return NT_SUCCESS(Status
);
60 RegWriteDisplaySettings(HKEY hkey
, PDEVMODEW pdm
)
62 RegWriteDWORD(hkey
, L
"DefaultSettings.BitsPerPel", pdm
->dmBitsPerPel
);
63 RegWriteDWORD(hkey
, L
"DefaultSettings.XResolution", pdm
->dmPelsWidth
);
64 RegWriteDWORD(hkey
, L
"DefaultSettings.YResolution", pdm
->dmPelsHeight
);
65 RegWriteDWORD(hkey
, L
"DefaultSettings.Flags", pdm
->dmDisplayFlags
);
66 RegWriteDWORD(hkey
, L
"DefaultSettings.VRefresh", pdm
->dmDisplayFrequency
);
67 RegWriteDWORD(hkey
, L
"DefaultSettings.XPanning", pdm
->dmPanningWidth
);
68 RegWriteDWORD(hkey
, L
"DefaultSettings.YPanning", pdm
->dmPanningHeight
);
69 RegWriteDWORD(hkey
, L
"DefaultSettings.Orientation", pdm
->dmDisplayOrientation
);
70 RegWriteDWORD(hkey
, L
"DefaultSettings.FixedOutput", pdm
->dmDisplayFixedOutput
);
71 RegWriteDWORD(hkey
, L
"Attach.RelativeX", pdm
->dmPosition
.x
);
72 RegWriteDWORD(hkey
, L
"Attach.RelativeY", pdm
->dmPosition
.y
);
73 // RegWriteDWORD(hkey, L"Attach.ToDesktop, pdm->dmBitsPerPel", pdm->);
77 RegReadDisplaySettings(HKEY hkey
, PDEVMODEW pdm
)
81 /* Zero out the structure */
82 RtlZeroMemory(pdm
, sizeof(DEVMODEW
));
85 #define READ(field, str, flag) \
86 if (RegReadDWORD(hkey, L##str, &dwValue)) \
88 pdm->field = dwValue; \
89 pdm->dmFields |= flag; \
92 /* Read all present settings */
93 READ(dmBitsPerPel
, "DefaultSettings.BitsPerPel", DM_BITSPERPEL
);
94 READ(dmPelsWidth
, "DefaultSettings.XResolution", DM_PELSWIDTH
);
95 READ(dmPelsHeight
, "DefaultSettings.YResolution", DM_PELSHEIGHT
);
96 READ(dmDisplayFlags
, "DefaultSettings.Flags", DM_DISPLAYFLAGS
);
97 READ(dmDisplayFrequency
, "DefaultSettings.VRefresh", DM_DISPLAYFREQUENCY
);
98 READ(dmPanningWidth
, "DefaultSettings.XPanning", DM_PANNINGWIDTH
);
99 READ(dmPanningHeight
, "DefaultSettings.YPanning", DM_PANNINGHEIGHT
);
100 READ(dmDisplayOrientation
, "DefaultSettings.Orientation", DM_DISPLAYORIENTATION
);
101 READ(dmDisplayFixedOutput
, "DefaultSettings.FixedOutput", DM_DISPLAYFIXEDOUTPUT
);
102 READ(dmPosition
.x
, "Attach.RelativeX", DM_POSITION
);
103 READ(dmPosition
.y
, "Attach.RelativeY", DM_POSITION
);
114 PUNICODE_STRING pustrRegPath
,
117 // PWSTR pwszDriverName;
118 RTL_QUERY_REGISTRY_TABLE QueryTable
[2];
121 /* Setup QueryTable for direct registry query */
122 RtlZeroMemory(QueryTable
, sizeof(QueryTable
));
123 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_REQUIRED
|RTL_QUERY_REGISTRY_DIRECT
;
126 /* Check if vga mode is requested */
127 if (flags
& VF_USEVGA
)
129 DWORD dwVgaCompatible
;
132 QueryTable
[0].Name
= L
"VgaCompatible";
133 QueryTable
[0].EntryContext
= &dwVgaCompatible
;
135 /* Check if the driver is vga */
136 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
137 pustrRegPath
->Buffer
,
142 if (!dwVgaCompatible
)
144 /* This driver is not a vga driver */
151 /* Query the adapter's registry path */
152 swprintf(awcBuffer
, L
"\\Device\\Video%lu", iDevNum
);
153 QueryTable
[0].Name
= pGraphicsDevice
->szNtDeviceName
;
155 /* Set string for the registry key */
156 ustrRegistryPath
.Buffer
= pdispdev
->DeviceKey
;
157 ustrRegistryPath
.Length
= 128;
158 ustrRegistryPath
.MaximumLength
= 128;
159 QueryTable
[0].EntryContext
= &ustrRegistryPath
;
161 /* Query the registry */
162 Status
= RtlQueryRegistryValues(RTL_REGISTRY_DEVICEMAP
,
168 RegQueryValue(KEY_VIDEO
, awcBuffer
, REG_SZ
, pdispdev
->DeviceKey
, 256);
173 hmod
= EngLoadImage(pwszDriverName
);
175 /* Jump to next name */
176 pwszDriverName
+= wcslen(pwszDriverName
) + 1;
178 while (pwszDriverName
< 0);
187 DisplayDriverQueryRoutine(
191 IN ULONG ValueLength
,
193 IN PVOID EntryContext
)
195 PWSTR pwszRegKey
= ValueData
;
196 PGRAPHICS_DEVICE pGraphicsDevice
;
197 UNICODE_STRING ustrDeviceName
, ustrDisplayDrivers
, ustrDescription
;
199 WCHAR awcBuffer
[128];
204 UNREFERENCED_PARAMETER(ValueLength
);
205 UNREFERENCED_PARAMETER(Context
);
206 UNREFERENCED_PARAMETER(EntryContext
);
208 DPRINT1("DisplayDriverQueryRoutine(%S, %S);\n",
209 ValueName
, pwszRegKey
);
211 /* Check if we have a correct entry */
212 if (ValueType
!= REG_SZ
|| ValueName
[0] != '\\')
214 /* Something else, just skip it */
215 return STATUS_SUCCESS
;
218 /* Open the driver's registry key */
219 Status
= RegOpenKey(pwszRegKey
, &hkey
);
220 if (!NT_SUCCESS(Status
))
222 DPRINT1("Failed to open registry key\n");
223 return STATUS_SUCCESS
;
226 // HACK: only use 1st adapter
227 //if (ValueName[13] != '0')
228 // return STATUS_SUCCESS;
230 /* Query the diplay drivers */
231 cbSize
= sizeof(awcBuffer
) - 10;
232 Status
= RegQueryValue(hkey
,
233 L
"InstalledDisplayDrivers",
237 if (!NT_SUCCESS(Status
))
239 DPRINT1("Didn't find 'InstalledDisplayDrivers', status = 0x%lx\n", Status
);
241 return STATUS_SUCCESS
;
244 /* Initialize the UNICODE_STRING */
245 ustrDisplayDrivers
.Buffer
= awcBuffer
;
246 ustrDisplayDrivers
.MaximumLength
= cbSize
;
247 ustrDisplayDrivers
.Length
= cbSize
;
249 /* Set Buffer for description and size of remaining buffer */
250 ustrDescription
.Buffer
= awcBuffer
+ (cbSize
/ sizeof(WCHAR
));
251 cbSize
= sizeof(awcBuffer
) - cbSize
;
253 /* Query the device string */
254 Status
= RegQueryValue(hkey
,
255 L
"Device Description",
257 ustrDescription
.Buffer
,
259 if (NT_SUCCESS(Status
))
261 ustrDescription
.MaximumLength
= cbSize
;
262 ustrDescription
.Length
= cbSize
;
266 RtlInitUnicodeString(&ustrDescription
, L
"<unknown>");
269 /* Query the default settings */
270 RegReadDisplaySettings(hkey
, &dmDefault
);
272 /* Close the registry key */
275 /* Register the device with GDI */
276 RtlInitUnicodeString(&ustrDeviceName
, ValueName
);
277 pGraphicsDevice
= EngpRegisterGraphicsDevice(&ustrDeviceName
,
282 // FIXME: what to do with pGraphicsDevice?
284 return STATUS_SUCCESS
;
287 BOOL
InitSysParams();
290 InitVideo(FLONG flags
)
292 RTL_QUERY_REGISTRY_TABLE QueryTable
[2];
295 DPRINT1("----------------------------- InitVideo() -------------------------------\n");
297 /* Setup QueryTable for registry query */
298 RtlZeroMemory(QueryTable
, sizeof(QueryTable
));
299 QueryTable
[0].QueryRoutine
= DisplayDriverQueryRoutine
;
301 /* Query the registry */
302 Status
= RtlQueryRegistryValues(RTL_REGISTRY_DEVICEMAP
,
316 UserEnumDisplayDevices(
317 PUNICODE_STRING pustrDevice
,
319 PDISPLAY_DEVICEW pdispdev
,
322 PGRAPHICS_DEVICE pGraphicsDevice
;
327 /* Ask gdi for the GRAPHICS_DEVICE */
328 pGraphicsDevice
= EngpFindGraphicsDevice(pustrDevice
, iDevNum
, 0);
329 if (!pGraphicsDevice
)
331 /* No device found */
332 DPRINT1("No GRAPHICS_DEVICE found\n");
333 return STATUS_UNSUCCESSFUL
;
336 /* Open thhe device map registry key */
337 Status
= RegOpenKey(KEY_VIDEO
, &hkey
);
338 if (!NT_SUCCESS(Status
))
340 /* No device found */
341 DPRINT1("Could not open reg key\n");
342 return STATUS_UNSUCCESSFUL
;
345 /* Query the registry path */
346 cbSize
= sizeof(pdispdev
->DeviceKey
);
348 pGraphicsDevice
->szNtDeviceName
,
353 /* Close registry key */
356 /* Copy device name, device string and StateFlags */
357 wcsncpy(pdispdev
->DeviceName
, pGraphicsDevice
->szWinDeviceName
, 32);
358 wcsncpy(pdispdev
->DeviceString
, pGraphicsDevice
->pwszDescription
, 128);
359 pdispdev
->StateFlags
= pGraphicsDevice
->StateFlags
;
361 // FIXME: fill in DEVICE ID
363 return STATUS_SUCCESS
;
369 NtUserEnumDisplayDevices(
370 PUNICODE_STRING pustrDevice
,
372 PDISPLAY_DEVICEW pDisplayDevice
,
375 UNICODE_STRING ustrDevice
;
376 WCHAR awcDevice
[CCHDEVICENAME
];
377 DISPLAY_DEVICEW dispdev
;
380 DPRINT1("Enter NtUserEnumDisplayDevices(%p, %ls, %ld)\n",
381 pustrDevice
, pustrDevice
? pustrDevice
->Buffer
: 0, iDevNum
);
383 // FIXME: HACK, desk.cpl passes broken crap
384 if (pustrDevice
&& iDevNum
!= 0)
387 dispdev
.cb
= sizeof(DISPLAY_DEVICEW
);
391 /* Initialize destination string */
392 RtlInitEmptyUnicodeString(&ustrDevice
, awcDevice
, sizeof(awcDevice
));
396 /* Probe the UNICODE_STRING and the buffer */
397 ProbeForRead(pustrDevice
, sizeof(UNICODE_STRING
), 1);
398 ProbeForRead(pustrDevice
->Buffer
, pustrDevice
->Length
, 1);
400 /* Copy the string */
401 RtlCopyUnicodeString(&ustrDevice
, pustrDevice
);
403 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
405 // _SEH2_YIELD(return _SEH2_GetExceptionCode());
406 _SEH2_YIELD(return NT_SUCCESS(_SEH2_GetExceptionCode()));
410 if (ustrDevice
.Length
> 0)
411 pustrDevice
= &ustrDevice
;
416 /* Acquire global USER lock */
417 UserEnterExclusive();
419 /* Call the internal function */
420 Status
= UserEnumDisplayDevices(pustrDevice
, iDevNum
, &dispdev
, dwFlags
);
425 /* On success copy data to caller */
426 if (NT_SUCCESS(Status
))
431 /* First probe the cb field */
432 ProbeForWrite(&pDisplayDevice
->cb
, sizeof(DWORD
), 1);
434 /* Check the buffer size */
435 if (pDisplayDevice
->cb
)
437 /* Probe the output buffer */
438 pDisplayDevice
->cb
= min(pDisplayDevice
->cb
, sizeof(dispdev
));
439 ProbeForWrite(pDisplayDevice
, pDisplayDevice
->cb
, 1);
441 /* Copy as much as the given buffer allows */
442 RtlCopyMemory(pDisplayDevice
, &dispdev
, pDisplayDevice
->cb
);
445 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
447 Status
= _SEH2_GetExceptionCode();
452 DPRINT1("Leave NtUserEnumDisplayDevices, Status = 0x%lx\n", Status
);
453 /* Return the result */
455 return NT_SUCCESS(Status
); // FIXME
460 UserEnumCurrentDisplaySettings(
461 PUNICODE_STRING pustrDevice
,
466 /* Get the PDEV for the device */
467 ppdev
= EngpGetPDEV(pustrDevice
);
470 /* No device found */
471 DPRINT1("No PDEV found!\n");
472 return STATUS_UNSUCCESSFUL
;
475 *ppdm
= ppdev
->pdmwDev
;
476 PDEVOBJ_vRelease(ppdev
);
478 return STATUS_SUCCESS
;
483 UserEnumDisplaySettings(
484 PUNICODE_STRING pustrDevice
,
489 PGRAPHICS_DEVICE pGraphicsDevice
;
490 PDEVMODEENTRY pdmentry
;
493 DPRINT1("Enter UserEnumDisplaySettings('%ls', %ld)\n",
494 pustrDevice
? pustrDevice
->Buffer
: NULL
, iModeNum
);
496 /* Ask gdi for the GRAPHICS_DEVICE */
497 pGraphicsDevice
= EngpFindGraphicsDevice(pustrDevice
, 0, 0);
498 if (!pGraphicsDevice
)
500 /* No device found */
501 DPRINT1("No device found!\n");
502 return STATUS_UNSUCCESSFUL
;
507 DPRINT1("Should initialize modes somehow\n");
508 // Update DISPLAY_DEVICEs?
512 for (i
= 0; i
< pGraphicsDevice
->cDevModes
; i
++)
514 pdmentry
= &pGraphicsDevice
->pDevModeList
[i
];
516 // if ((!(dwFlags & EDS_RAWMODE) && (pdmentry->dwFlags & 1)) || // FIXME!
517 // (dwFlags & EDS_RAWMODE))
519 /* Is this the one we want? */
520 if (iFoundMode
== iModeNum
)
522 *ppdm
= pdmentry
->pdm
;
523 return STATUS_SUCCESS
;
526 /* Increment number of found modes */
531 /* Nothing was found */
532 return STATUS_INVALID_PARAMETER
;
537 UserOpenDisplaySettingsKey(
539 IN PUNICODE_STRING pustrDevice
,
543 DISPLAY_DEVICEW dispdev
;
546 /* Get device info */
547 Status
= UserEnumDisplayDevices(pustrDevice
, 0, &dispdev
, 0);
548 if (!NT_SUCCESS(Status
))
553 // FIXME: need to fix the registry key somehow
556 /* Open the registry key */
557 Status
= RegOpenKey(dispdev
.DeviceKey
, &hkey
);
558 if (!NT_SUCCESS(Status
))
568 UserEnumRegistryDisplaySettings(
569 IN PUNICODE_STRING pustrDevice
,
573 NTSTATUS Status
= UserOpenDisplaySettingsKey(&hkey
, pustrDevice
, 0);
574 if(NT_SUCCESS(Status
))
576 RegReadDisplaySettings(hkey
, pdm
);
578 return STATUS_SUCCESS
;
586 NtUserEnumDisplaySettings(
587 IN PUNICODE_STRING pustrDevice
,
589 OUT LPDEVMODEW lpDevMode
,
592 UNICODE_STRING ustrDevice
;
593 WCHAR awcDevice
[CCHDEVICENAME
];
595 ULONG cbSize
, cbExtra
;
596 DEVMODEW dmReg
, *pdm
;
598 DPRINT1("Enter NtUserEnumDisplaySettings(%ls, %ld)\n",
599 pustrDevice
? pustrDevice
->Buffer
:0, iModeNum
);
603 /* Initialize destination string */
604 RtlInitEmptyUnicodeString(&ustrDevice
, awcDevice
, sizeof(awcDevice
));
608 /* Probe the UNICODE_STRING and the buffer */
609 ProbeForRead(pustrDevice
, sizeof(UNICODE_STRING
), 1);
610 ProbeForRead(pustrDevice
->Buffer
, pustrDevice
->Length
, 1);
612 /* Copy the string */
613 RtlCopyUnicodeString(&ustrDevice
, pustrDevice
);
615 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
617 _SEH2_YIELD(return _SEH2_GetExceptionCode());
621 pustrDevice
= &ustrDevice
;
624 /* Acquire global USER lock */
625 UserEnterExclusive();
627 if (iModeNum
== ENUM_REGISTRY_SETTINGS
)
629 /* Get the registry settings */
630 Status
= UserEnumRegistryDisplaySettings(pustrDevice
, &dmReg
);
633 else if (iModeNum
== ENUM_CURRENT_SETTINGS
)
635 /* Get the current settings */
636 Status
= UserEnumCurrentDisplaySettings(pustrDevice
, &pdm
);
640 /* Get specified settings */
641 Status
= UserEnumDisplaySettings(pustrDevice
, iModeNum
, &pdm
, dwFlags
);
647 /* Did we succeed? */
648 if (NT_SUCCESS(Status
))
650 /* Copy some information back */
653 ProbeForRead(lpDevMode
, sizeof(DEVMODEW
), 1);
654 cbSize
= lpDevMode
->dmSize
;
655 cbExtra
= lpDevMode
->dmDriverExtra
;
657 ProbeForWrite(lpDevMode
, cbSize
+ cbExtra
, 1);
658 /* Output what we got */
659 RtlCopyMemory(lpDevMode
, pdm
, min(cbSize
, pdm
->dmSize
));
661 /* output private/extra driver data */
662 if (cbExtra
> 0 && pdm
->dmDriverExtra
> 0)
664 RtlCopyMemory((PCHAR
)lpDevMode
+ cbSize
,
665 (PCHAR
)pdm
+ pdm
->dmSize
,
666 min(cbExtra
, pdm
->dmDriverExtra
));
669 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
671 Status
= _SEH2_GetExceptionCode();
679 BOOL APIENTRY
UserClipCursor(RECTL
*prcl
);
680 VOID APIENTRY
UserRedrawDesktop();
681 HCURSOR FASTCALL
UserSetCursor(PCURICON_OBJECT NewCursor
, BOOL ForceChange
);
685 UserChangeDisplaySettings(
686 PUNICODE_STRING pustrDevice
,
693 LONG lResult
= DISP_CHANGE_SUCCESSFUL
;
699 /* If no DEVMODE is given, use registry settings */
702 /* Get the registry settings */
703 Status
= UserEnumRegistryDisplaySettings(pustrDevice
, &dm
);
704 if (!NT_SUCCESS(Status
))
706 DPRINT1("Could not load registry settings\n");
707 return DISP_CHANGE_BADPARAM
;
710 else if (pdm
->dmSize
< FIELD_OFFSET(DEVMODEW
, dmFields
))
711 return DISP_CHANGE_BADMODE
; /* This is what winXP SP3 returns */
716 if ((dm
.dmFields
& (DM_PELSWIDTH
| DM_PELSHEIGHT
)) != (DM_PELSWIDTH
| DM_PELSHEIGHT
))
718 DPRINT1("devmode doesn't specify the resolution.\n");
719 return DISP_CHANGE_BADMODE
;
723 ppdev
= EngpGetPDEV(pustrDevice
);
726 DPRINT1("failed to get PDEV\n");
727 return DISP_CHANGE_BADPARAM
;
731 if((dm
.dmFields
& DM_BITSPERPEL
) && (dm
.dmBitsPerPel
== 0))
732 dm
.dmBitsPerPel
= ppdev
->pdmwDev
->dmBitsPerPel
;
733 if((dm
.dmFields
& DM_DISPLAYFREQUENCY
) && (dm
.dmDisplayFrequency
== 0))
734 dm
.dmDisplayFrequency
= ppdev
->pdmwDev
->dmDisplayFrequency
;
736 /* Look for the requested DEVMODE */
737 pdm
= PDEVOBJ_pdmMatchDevMode(ppdev
, &dm
);
740 DPRINT1("Could not find a matching DEVMODE\n");
741 lResult
= DISP_CHANGE_BADMODE
;
744 else if (flags
& CDS_TEST
)
746 /* It's possible, go ahead! */
747 lResult
= DISP_CHANGE_SUCCESSFUL
;
751 /* Shall we update the registry? */
752 if (flags
& CDS_UPDATEREGISTRY
)
754 /* Open the local or global settings key */
755 Status
= UserOpenDisplaySettingsKey(&hkey
, pustrDevice
, flags
& CDS_GLOBAL
);
756 if (NT_SUCCESS(Status
))
758 /* Store the settings */
759 RegWriteDisplaySettings(hkey
, pdm
);
761 /* Close the registry key */
766 DPRINT1("Could not open registry key\n");
767 lResult
= DISP_CHANGE_NOTUPDATED
;
771 /* Check if DEVMODE matches the current mode */
772 if (pdm
== ppdev
->pdmwDev
&& !(flags
& CDS_RESET
))
774 DPRINT1("DEVMODE matches, nothing to do\n");
778 /* Shall we apply the settings? */
779 if (!(flags
& CDS_NORESET
))
783 /* Remove mouse pointer */
784 UserSetCursor(NULL
, TRUE
);
786 /* Do the mode switch */
787 ulResult
= PDEVOBJ_bSwitchMode(ppdev
, pdm
);
789 /* Restore mouse pointer, no hooks called */
790 UserSetCursorPos(gpsi
->ptCursor
.x
, gpsi
->ptCursor
.y
, FALSE
);
792 /* Check for failure */
795 DPRINT1("failed to set mode\n");
796 lResult
= (lResult
== DISP_CHANGE_NOTUPDATED
) ?
797 DISP_CHANGE_FAILED
: DISP_CHANGE_RESTART
;
802 /* Update the system metrics */
805 //IntvGetDeviceCaps(&PrimarySurface, &GdiHandleTable->DevCaps);
807 /* Remove all cursor clipping */
808 UserClipCursor(NULL
);
810 pdesk
= IntGetActiveDesktop();
811 //IntHideDesktop(pdesk);
813 /* Send WM_DISPLAYCHANGE to all toplevel windows */
814 co_IntSendMessageTimeout(HWND_BROADCAST
,
816 (WPARAM
)ppdev
->gdiinfo
.cBitsPixel
,
817 (LPARAM
)(ppdev
->gdiinfo
.ulHorzRes
+ (ppdev
->gdiinfo
.ulVertRes
<< 16)),
822 //co_IntShowDesktop(pdesk, ppdev->gdiinfo.ulHorzRes, ppdev->gdiinfo.ulVertRes);
828 /* Release the PDEV */
829 PDEVOBJ_vRelease(ppdev
);
836 NtUserChangeDisplaySettings(
837 PUNICODE_STRING pustrDevice
,
838 LPDEVMODEW lpDevMode
,
843 WCHAR awcDevice
[CCHDEVICENAME
];
844 UNICODE_STRING ustrDevice
;
848 /* Check arguments */
849 if ((dwflags
!= CDS_VIDEOPARAMETERS
&& lParam
!= NULL
) ||
852 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
853 return DISP_CHANGE_BADPARAM
;
857 if ((dwflags
& (CDS_GLOBAL
|CDS_NORESET
)) && !(dwflags
& CDS_UPDATEREGISTRY
))
859 return DISP_CHANGE_BADFLAGS
;
862 /* Copy the device name */
865 /* Initialize destination string */
866 RtlInitEmptyUnicodeString(&ustrDevice
, awcDevice
, sizeof(awcDevice
));
870 /* Probe the UNICODE_STRING and the buffer */
871 ProbeForRead(pustrDevice
, sizeof(UNICODE_STRING
), 1);
872 ProbeForRead(pustrDevice
->Buffer
, pustrDevice
->Length
, 1);
874 /* Copy the string */
875 RtlCopyUnicodeString(&ustrDevice
, pustrDevice
);
877 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
879 /* Set and return error */
880 SetLastNtError(_SEH2_GetExceptionCode());
881 _SEH2_YIELD(return DISP_CHANGE_BADPARAM
);
885 pustrDevice
= &ustrDevice
;
893 /* Probe the size field of the structure */
894 ProbeForRead(lpDevMode
, sizeof(dmLocal
.dmSize
), 1);
896 /* Calculate usable size */
897 dmLocal
.dmSize
= min(sizeof(dmLocal
), lpDevMode
->dmSize
);
899 /* Probe and copy the full DEVMODE */
900 ProbeForRead(lpDevMode
, dmLocal
.dmSize
, 1);
901 RtlCopyMemory(&dmLocal
, lpDevMode
, dmLocal
.dmSize
);
903 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
905 /* Set and return error */
906 SetLastNtError(_SEH2_GetExceptionCode());
907 _SEH2_YIELD(return DISP_CHANGE_BADPARAM
);
911 /* Check for extra parameters */
912 if (dmLocal
.dmDriverExtra
> 0)
915 DPRINT1("lpDevMode->dmDriverExtra is IGNORED!\n");
916 dmLocal
.dmDriverExtra
= 0;
919 /* Use the local structure */
920 lpDevMode
= &dmLocal
;
923 // FIXME: Copy videoparameters
925 /* Acquire global USER lock */
926 UserEnterExclusive();
928 /* Call internal function */
929 lRet
= UserChangeDisplaySettings(pustrDevice
, lpDevMode
, hwnd
, dwflags
, NULL
);