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)
10 DBG_DEFAULT_CHANNEL(UserDisplay
);
14 static const PWCHAR KEY_VIDEO
= L
"\\Registry\\Machine\\HARDWARE\\DEVICEMAP\\VIDEO";
17 RegWriteDisplaySettings(HKEY hkey
, PDEVMODEW pdm
)
19 RegWriteDWORD(hkey
, L
"DefaultSettings.BitsPerPel", pdm
->dmBitsPerPel
);
20 RegWriteDWORD(hkey
, L
"DefaultSettings.XResolution", pdm
->dmPelsWidth
);
21 RegWriteDWORD(hkey
, L
"DefaultSettings.YResolution", pdm
->dmPelsHeight
);
22 RegWriteDWORD(hkey
, L
"DefaultSettings.Flags", pdm
->dmDisplayFlags
);
23 RegWriteDWORD(hkey
, L
"DefaultSettings.VRefresh", pdm
->dmDisplayFrequency
);
24 RegWriteDWORD(hkey
, L
"DefaultSettings.XPanning", pdm
->dmPanningWidth
);
25 RegWriteDWORD(hkey
, L
"DefaultSettings.YPanning", pdm
->dmPanningHeight
);
26 RegWriteDWORD(hkey
, L
"DefaultSettings.Orientation", pdm
->dmDisplayOrientation
);
27 RegWriteDWORD(hkey
, L
"DefaultSettings.FixedOutput", pdm
->dmDisplayFixedOutput
);
28 RegWriteDWORD(hkey
, L
"Attach.RelativeX", pdm
->dmPosition
.x
);
29 RegWriteDWORD(hkey
, L
"Attach.RelativeY", pdm
->dmPosition
.y
);
30 // RegWriteDWORD(hkey, L"Attach.ToDesktop, pdm->dmBitsPerPel", pdm->);
34 RegReadDisplaySettings(HKEY hkey
, PDEVMODEW pdm
)
38 /* Zero out the structure */
39 RtlZeroMemory(pdm
, sizeof(DEVMODEW
));
42 #define READ(field, str, flag) \
43 if (RegReadDWORD(hkey, L##str, &dwValue)) \
45 pdm->field = dwValue; \
46 pdm->dmFields |= flag; \
49 /* Read all present settings */
50 READ(dmBitsPerPel
, "DefaultSettings.BitsPerPel", DM_BITSPERPEL
);
51 READ(dmPelsWidth
, "DefaultSettings.XResolution", DM_PELSWIDTH
);
52 READ(dmPelsHeight
, "DefaultSettings.YResolution", DM_PELSHEIGHT
);
53 READ(dmDisplayFlags
, "DefaultSettings.Flags", DM_DISPLAYFLAGS
);
54 READ(dmDisplayFrequency
, "DefaultSettings.VRefresh", DM_DISPLAYFREQUENCY
);
55 READ(dmPanningWidth
, "DefaultSettings.XPanning", DM_PANNINGWIDTH
);
56 READ(dmPanningHeight
, "DefaultSettings.YPanning", DM_PANNINGHEIGHT
);
57 READ(dmDisplayOrientation
, "DefaultSettings.Orientation", DM_DISPLAYORIENTATION
);
58 READ(dmDisplayFixedOutput
, "DefaultSettings.FixedOutput", DM_DISPLAYFIXEDOUTPUT
);
59 READ(dmPosition
.x
, "Attach.RelativeX", DM_POSITION
);
60 READ(dmPosition
.y
, "Attach.RelativeY", DM_POSITION
);
66 IN PWSTR pwszDeviceName
,
69 PGRAPHICS_DEVICE pGraphicsDevice
;
70 UNICODE_STRING ustrDeviceName
, ustrDisplayDrivers
, ustrDescription
;
78 ERR("InitDisplayDriver(%S, %S);\n",
79 pwszDeviceName
, pwszRegKey
);
81 /* Open the driver's registry key */
82 Status
= RegOpenKey(pwszRegKey
, &hkey
);
83 if (!NT_SUCCESS(Status
))
85 ERR("Failed to open registry key: %ls\n", pwszRegKey
);
89 /* Query the diplay drivers */
90 cbSize
= sizeof(awcBuffer
) - 10;
91 Status
= RegQueryValue(hkey
,
92 L
"InstalledDisplayDrivers",
96 if (!NT_SUCCESS(Status
))
98 ERR("Didn't find 'InstalledDisplayDrivers', status = 0x%lx\n", Status
);
103 /* Initialize the UNICODE_STRING */
104 ustrDisplayDrivers
.Buffer
= awcBuffer
;
105 ustrDisplayDrivers
.MaximumLength
= (USHORT
)cbSize
;
106 ustrDisplayDrivers
.Length
= (USHORT
)cbSize
;
108 /* Set Buffer for description and size of remaining buffer */
109 ustrDescription
.Buffer
= awcBuffer
+ (cbSize
/ sizeof(WCHAR
));
110 cbSize
= sizeof(awcBuffer
) - cbSize
;
112 /* Query the device string */
113 Status
= RegQueryValue(hkey
,
114 L
"Device Description",
116 ustrDescription
.Buffer
,
118 if (NT_SUCCESS(Status
))
120 ustrDescription
.MaximumLength
= (USHORT
)cbSize
;
121 ustrDescription
.Length
= (USHORT
)cbSize
;
125 RtlInitUnicodeString(&ustrDescription
, L
"<unknown>");
128 /* Query the default settings */
129 RegReadDisplaySettings(hkey
, &dmDefault
);
131 /* Query if this is a VGA compatible driver */
132 cbSize
= sizeof(DWORD
);
133 Status
= RegQueryValue(hkey
, L
"VgaCompatible", REG_DWORD
, &dwVga
, &cbSize
);
134 if (!NT_SUCCESS(Status
)) dwVga
= 0;
136 /* Close the registry key */
139 /* Register the device with GDI */
140 RtlInitUnicodeString(&ustrDeviceName
, pwszDeviceName
);
141 pGraphicsDevice
= EngpRegisterGraphicsDevice(&ustrDeviceName
,
145 if (pGraphicsDevice
&& dwVga
)
147 pGraphicsDevice
->StateFlags
|= DISPLAY_DEVICE_VGA_COMPATIBLE
;
150 return pGraphicsDevice
;
157 ULONG iDevNum
, iVGACompatible
= -1, ulMaxObjectNumber
= 0;
158 WCHAR awcDeviceName
[20];
159 WCHAR awcBuffer
[256];
161 PGRAPHICS_DEVICE pGraphicsDevice
;
165 TRACE("----------------------------- InitVideo() -------------------------------\n");
167 /* Open the key for the boot command line */
168 Status
= RegOpenKey(L
"\\REGISTRY\\MACHINE\\SYSTEM\\CurrentControlSet\\Control", &hkey
);
169 if (NT_SUCCESS(Status
))
172 Status
= RegQueryValue(hkey
, L
"SystemStartOptions", REG_SZ
, awcBuffer
, &cbValue
);
173 if (NT_SUCCESS(Status
))
175 /* Check if VGA mode is requested. */
176 if (wcsstr(awcBuffer
, L
"BASEVIDEO") != 0)
178 ERR("VGA mode requested.\n");
186 /* Open the key for the adapters */
187 Status
= RegOpenKey(KEY_VIDEO
, &hkey
);
188 if (!NT_SUCCESS(Status
))
190 ERR("Could not open device registry key!\n");
194 /* Read the name of the VGA adapter */
196 Status
= RegQueryValue(hkey
, L
"VgaCompatible", REG_SZ
, awcDeviceName
, &cbValue
);
197 if (NT_SUCCESS(Status
))
199 iVGACompatible
= _wtoi(&awcDeviceName
[13]);
200 ERR("VGA adapter = %ld\n", iVGACompatible
);
203 /* Get the maximum mumber of adapters */
204 if (!RegReadDWORD(hkey
, L
"MaxObjectNumber", &ulMaxObjectNumber
))
206 ERR("Could not read MaxObjectNumber, defaulting to 0.\n");
209 TRACE("Found %ld devices\n", ulMaxObjectNumber
+ 1);
211 /* Loop through all adapters */
212 for (iDevNum
= 0; iDevNum
<= ulMaxObjectNumber
; iDevNum
++)
214 /* Create the adapter's key name */
215 swprintf(awcDeviceName
, L
"\\Device\\Video%lu", iDevNum
);
217 /* Read the reg key name */
218 cbValue
= sizeof(awcBuffer
);
219 Status
= RegQueryValue(hkey
, awcDeviceName
, REG_SZ
, awcBuffer
, &cbValue
);
220 if (!NT_SUCCESS(Status
))
222 ERR("failed to query the registry path:0x%lx\n", Status
);
226 /* Initialize the driver for this device */
227 pGraphicsDevice
= InitDisplayDriver(awcDeviceName
, awcBuffer
);
228 if (!pGraphicsDevice
) continue;
230 /* Check if this is a VGA compatible adapter */
231 if (pGraphicsDevice
->StateFlags
& DISPLAY_DEVICE_VGA_COMPATIBLE
)
233 /* Save this as the VGA adapter */
234 if (!gpVgaGraphicsDevice
)
235 gpVgaGraphicsDevice
= pGraphicsDevice
;
236 TRACE("gpVgaGraphicsDevice = %p\n", gpVgaGraphicsDevice
);
240 /* Set the first one as primary device */
241 if (!gpPrimaryGraphicsDevice
)
242 gpPrimaryGraphicsDevice
= pGraphicsDevice
;
243 TRACE("gpPrimaryGraphicsDevice = %p\n", gpPrimaryGraphicsDevice
);
247 /* Close the device map registry key */
250 /* Was VGA mode requested? */
253 /* Check if we found a VGA compatible device */
254 if (gpVgaGraphicsDevice
)
256 /* Set the VgaAdapter as primary */
257 gpPrimaryGraphicsDevice
= gpVgaGraphicsDevice
;
262 ERR("Could not find VGA compatible driver. Trying normal.\n");
266 /* Check if we had any success */
267 if (!gpPrimaryGraphicsDevice
)
269 /* Check if there is a VGA device we skipped */
270 if (gpVgaGraphicsDevice
)
272 /* There is, use the VGA device */
273 gpPrimaryGraphicsDevice
= gpVgaGraphicsDevice
;
277 ERR("No usable display driver was found.\n");
278 return STATUS_UNSUCCESSFUL
;
289 UserEnumDisplayDevices(
290 PUNICODE_STRING pustrDevice
,
292 PDISPLAY_DEVICEW pdispdev
,
295 PGRAPHICS_DEVICE pGraphicsDevice
;
300 /* Ask gdi for the GRAPHICS_DEVICE */
301 pGraphicsDevice
= EngpFindGraphicsDevice(pustrDevice
, iDevNum
, 0);
302 if (!pGraphicsDevice
)
304 /* No device found */
305 ERR("No GRAPHICS_DEVICE found\n");
306 return STATUS_UNSUCCESSFUL
;
309 /* Open the device map registry key */
310 Status
= RegOpenKey(KEY_VIDEO
, &hkey
);
311 if (!NT_SUCCESS(Status
))
313 /* No device found */
314 ERR("Could not open reg key\n");
315 return STATUS_UNSUCCESSFUL
;
318 /* Query the registry path */
319 cbSize
= sizeof(pdispdev
->DeviceKey
);
321 pGraphicsDevice
->szNtDeviceName
,
326 /* Close registry key */
329 /* Copy device name, device string and StateFlags */
330 RtlStringCbCopyW(pdispdev
->DeviceName
, sizeof(pdispdev
->DeviceName
), pGraphicsDevice
->szWinDeviceName
);
331 RtlStringCbCopyW(pdispdev
->DeviceString
, sizeof(pdispdev
->DeviceString
), pGraphicsDevice
->pwszDescription
);
332 pdispdev
->StateFlags
= pGraphicsDevice
->StateFlags
;
333 // FIXME: fill in DEVICE ID
334 pdispdev
->DeviceID
[0] = UNICODE_NULL
;
336 return STATUS_SUCCESS
;
342 NtUserEnumDisplayDevices(
343 PUNICODE_STRING pustrDevice
,
345 PDISPLAY_DEVICEW pDisplayDevice
,
348 UNICODE_STRING ustrDevice
;
349 WCHAR awcDevice
[CCHDEVICENAME
];
350 DISPLAY_DEVICEW dispdev
;
353 TRACE("Enter NtUserEnumDisplayDevices(%wZ, %ld)\n",
354 pustrDevice
, iDevNum
);
356 dispdev
.cb
= sizeof(dispdev
);
360 /* Initialize destination string */
361 RtlInitEmptyUnicodeString(&ustrDevice
, awcDevice
, sizeof(awcDevice
));
365 /* Probe the UNICODE_STRING and the buffer */
366 ProbeForRead(pustrDevice
, sizeof(UNICODE_STRING
), 1);
367 ProbeForRead(pustrDevice
->Buffer
, pustrDevice
->Length
, 1);
369 /* Copy the string */
370 RtlCopyUnicodeString(&ustrDevice
, pustrDevice
);
372 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
374 // _SEH2_YIELD(return _SEH2_GetExceptionCode());
375 _SEH2_YIELD(return NT_SUCCESS(_SEH2_GetExceptionCode()));
379 if (ustrDevice
.Length
> 0)
380 pustrDevice
= &ustrDevice
;
385 /* If name is given only iDevNum==0 gives results */
386 if (pustrDevice
&& iDevNum
!= 0)
389 /* Acquire global USER lock */
392 /* Call the internal function */
393 Status
= UserEnumDisplayDevices(pustrDevice
, iDevNum
, &dispdev
, dwFlags
);
398 /* On success copy data to caller */
399 if (NT_SUCCESS(Status
))
404 /* First probe the cb field */
405 ProbeForWrite(&pDisplayDevice
->cb
, sizeof(DWORD
), 1);
407 /* Check the buffer size */
408 if (pDisplayDevice
->cb
)
410 /* Probe the output buffer */
411 pDisplayDevice
->cb
= min(pDisplayDevice
->cb
, sizeof(dispdev
));
412 ProbeForWrite(pDisplayDevice
, pDisplayDevice
->cb
, 1);
414 /* Copy as much as the given buffer allows */
415 RtlCopyMemory(pDisplayDevice
, &dispdev
, pDisplayDevice
->cb
);
418 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
420 Status
= _SEH2_GetExceptionCode();
425 TRACE("Leave NtUserEnumDisplayDevices, Status = 0x%lx\n", Status
);
426 /* Return the result */
428 return NT_SUCCESS(Status
); // FIXME
433 UserEnumCurrentDisplaySettings(
434 PUNICODE_STRING pustrDevice
,
439 /* Get the PDEV for the device */
440 ppdev
= EngpGetPDEV(pustrDevice
);
443 /* No device found */
444 ERR("No PDEV found!\n");
445 return STATUS_UNSUCCESSFUL
;
448 *ppdm
= ppdev
->pdmwDev
;
449 PDEVOBJ_vRelease(ppdev
);
451 return STATUS_SUCCESS
;
456 UserEnumDisplaySettings(
457 PUNICODE_STRING pustrDevice
,
462 PGRAPHICS_DEVICE pGraphicsDevice
;
463 PDEVMODEENTRY pdmentry
;
466 TRACE("Enter UserEnumDisplaySettings('%wZ', %ld)\n",
467 pustrDevice
, iModeNum
);
469 /* Ask GDI for the GRAPHICS_DEVICE */
470 pGraphicsDevice
= EngpFindGraphicsDevice(pustrDevice
, 0, 0);
472 if (!pGraphicsDevice
)
474 /* No device found */
475 ERR("No device found!\n");
476 return STATUS_UNSUCCESSFUL
;
479 if (iModeNum
>= pGraphicsDevice
->cDevModes
)
480 return STATUS_NO_MORE_ENTRIES
;
483 for (i
= 0; i
< pGraphicsDevice
->cDevModes
; i
++)
485 pdmentry
= &pGraphicsDevice
->pDevModeList
[i
];
487 /* FIXME: Consider EDS_RAWMODE */
489 if ((!(dwFlags
& EDS_RAWMODE
) && (pdmentry
->dwFlags
& 1)) ||!
490 (dwFlags
& EDS_RAWMODE
))
493 /* Is this the one we want? */
494 if (iFoundMode
== iModeNum
)
496 *ppdm
= pdmentry
->pdm
;
497 return STATUS_SUCCESS
;
500 /* Increment number of found modes */
505 /* Nothing was found */
506 return STATUS_INVALID_PARAMETER
;
511 UserOpenDisplaySettingsKey(
513 IN PUNICODE_STRING pustrDevice
,
517 DISPLAY_DEVICEW dispdev
;
520 /* Get device info */
521 Status
= UserEnumDisplayDevices(pustrDevice
, 0, &dispdev
, 0);
522 if (!NT_SUCCESS(Status
))
527 // FIXME: Need to fix the registry key somehow
530 /* Open the registry key */
531 Status
= RegOpenKey(dispdev
.DeviceKey
, &hkey
);
532 if (!NT_SUCCESS(Status
))
542 UserEnumRegistryDisplaySettings(
543 IN PUNICODE_STRING pustrDevice
,
547 NTSTATUS Status
= UserOpenDisplaySettingsKey(&hkey
, pustrDevice
, 0);
548 if(NT_SUCCESS(Status
))
550 RegReadDisplaySettings(hkey
, pdm
);
552 return STATUS_SUCCESS
;
559 NtUserEnumDisplaySettings(
560 IN PUNICODE_STRING pustrDevice
,
562 OUT LPDEVMODEW lpDevMode
,
565 UNICODE_STRING ustrDevice
;
566 WCHAR awcDevice
[CCHDEVICENAME
];
568 ULONG cbSize
, cbExtra
;
569 DEVMODEW dmReg
, *pdm
;
571 TRACE("Enter NtUserEnumDisplaySettings(%wZ, %ld, %p, 0x%lx)\n",
572 pustrDevice
, iModeNum
, lpDevMode
, dwFlags
);
576 /* Initialize destination string */
577 RtlInitEmptyUnicodeString(&ustrDevice
, awcDevice
, sizeof(awcDevice
));
581 /* Probe the UNICODE_STRING and the buffer */
582 ProbeForRead(pustrDevice
, sizeof(UNICODE_STRING
), 1);
583 ProbeForRead(pustrDevice
->Buffer
, pustrDevice
->Length
, 1);
585 /* Copy the string */
586 RtlCopyUnicodeString(&ustrDevice
, pustrDevice
);
588 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
590 _SEH2_YIELD(return _SEH2_GetExceptionCode());
594 pustrDevice
= &ustrDevice
;
597 /* Acquire global USER lock */
600 if (iModeNum
== ENUM_REGISTRY_SETTINGS
)
602 /* Get the registry settings */
603 Status
= UserEnumRegistryDisplaySettings(pustrDevice
, &dmReg
);
606 else if (iModeNum
== ENUM_CURRENT_SETTINGS
)
608 /* Get the current settings */
609 Status
= UserEnumCurrentDisplaySettings(pustrDevice
, &pdm
);
613 /* Get specified settings */
614 Status
= UserEnumDisplaySettings(pustrDevice
, iModeNum
, &pdm
, dwFlags
);
620 /* Did we succeed? */
621 if (NT_SUCCESS(Status
))
623 /* Copy some information back */
626 ProbeForRead(lpDevMode
, sizeof(DEVMODEW
), 1);
627 cbSize
= lpDevMode
->dmSize
;
628 cbExtra
= lpDevMode
->dmDriverExtra
;
630 ProbeForWrite(lpDevMode
, cbSize
+ cbExtra
, 1);
631 /* Output what we got */
632 RtlCopyMemory(lpDevMode
, pdm
, min(cbSize
, pdm
->dmSize
));
634 /* Output private/extra driver data */
635 if (cbExtra
> 0 && pdm
->dmDriverExtra
> 0)
637 RtlCopyMemory((PCHAR
)lpDevMode
+ cbSize
,
638 (PCHAR
)pdm
+ pdm
->dmSize
,
639 min(cbExtra
, pdm
->dmDriverExtra
));
642 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
644 Status
= _SEH2_GetExceptionCode();
654 UserChangeDisplaySettings(
655 PUNICODE_STRING pustrDevice
,
662 LONG lResult
= DISP_CHANGE_SUCCESSFUL
;
668 /* If no DEVMODE is given, use registry settings */
671 /* Get the registry settings */
672 Status
= UserEnumRegistryDisplaySettings(pustrDevice
, &dm
);
673 if (!NT_SUCCESS(Status
))
675 ERR("Could not load registry settings\n");
676 return DISP_CHANGE_BADPARAM
;
679 else if (pdm
->dmSize
< FIELD_OFFSET(DEVMODEW
, dmFields
))
680 return DISP_CHANGE_BADMODE
; /* This is what winXP SP3 returns */
685 if ((dm
.dmFields
& (DM_PELSWIDTH
| DM_PELSHEIGHT
)) != (DM_PELSWIDTH
| DM_PELSHEIGHT
))
687 ERR("Devmode doesn't specify the resolution.\n");
688 return DISP_CHANGE_BADMODE
;
692 ppdev
= EngpGetPDEV(pustrDevice
);
695 ERR("Failed to get PDEV\n");
696 return DISP_CHANGE_BADPARAM
;
700 if(dm
.dmBitsPerPel
== 0 || !(dm
.dmFields
& DM_BITSPERPEL
))
702 dm
.dmBitsPerPel
= ppdev
->pdmwDev
->dmBitsPerPel
;
703 dm
.dmFields
|= DM_BITSPERPEL
;
706 if((dm
.dmFields
& DM_DISPLAYFREQUENCY
) && (dm
.dmDisplayFrequency
== 0))
707 dm
.dmDisplayFrequency
= ppdev
->pdmwDev
->dmDisplayFrequency
;
709 /* Look for the requested DEVMODE */
710 pdm
= PDEVOBJ_pdmMatchDevMode(ppdev
, &dm
);
713 ERR("Could not find a matching DEVMODE\n");
714 lResult
= DISP_CHANGE_BADMODE
;
717 else if (flags
& CDS_TEST
)
719 /* It's possible, go ahead! */
720 lResult
= DISP_CHANGE_SUCCESSFUL
;
724 /* Shall we update the registry? */
725 if (flags
& CDS_UPDATEREGISTRY
)
727 /* Open the local or global settings key */
728 Status
= UserOpenDisplaySettingsKey(&hkey
, pustrDevice
, flags
& CDS_GLOBAL
);
729 if (NT_SUCCESS(Status
))
731 /* Store the settings */
732 RegWriteDisplaySettings(hkey
, pdm
);
734 /* Close the registry key */
739 ERR("Could not open registry key\n");
740 lResult
= DISP_CHANGE_NOTUPDATED
;
744 /* Check if DEVMODE matches the current mode */
745 if (pdm
== ppdev
->pdmwDev
&& !(flags
& CDS_RESET
))
747 ERR("DEVMODE matches, nothing to do\n");
751 /* Shall we apply the settings? */
752 if (!(flags
& CDS_NORESET
))
757 /* Remove mouse pointer */
758 pvOldCursor
= UserSetCursor(NULL
, TRUE
);
760 /* Do the mode switch */
761 ulResult
= PDEVOBJ_bSwitchMode(ppdev
, pdm
);
763 /* Restore mouse pointer, no hooks called */
764 UserSetCursor(pvOldCursor
, TRUE
);
766 /* Check for failure */
769 ERR("Failed to set mode\n");
770 lResult
= (lResult
== DISP_CHANGE_NOTUPDATED
) ?
771 DISP_CHANGE_FAILED
: DISP_CHANGE_RESTART
;
776 /* Update the system metrics */
779 //IntvGetDeviceCaps(&PrimarySurface, &GdiHandleTable->DevCaps);
781 /* Set new size of the monitor */
782 UserUpdateMonitorSize((HDEV
)ppdev
);
784 /* Remove all cursor clipping */
785 UserClipCursor(NULL
);
787 //pdesk = IntGetActiveDesktop();
788 //IntHideDesktop(pdesk);
790 /* Send WM_DISPLAYCHANGE to all toplevel windows */
791 co_IntSendMessageTimeout(HWND_BROADCAST
,
793 (WPARAM
)ppdev
->gdiinfo
.cBitsPixel
,
794 (LPARAM
)(ppdev
->gdiinfo
.ulHorzRes
+ (ppdev
->gdiinfo
.ulVertRes
<< 16)),
799 //co_IntShowDesktop(pdesk, ppdev->gdiinfo.ulHorzRes, ppdev->gdiinfo.ulVertRes);
805 /* Release the PDEV */
806 PDEVOBJ_vRelease(ppdev
);
813 NtUserChangeDisplaySettings(
814 PUNICODE_STRING pustrDevice
,
815 LPDEVMODEW lpDevMode
,
820 WCHAR awcDevice
[CCHDEVICENAME
];
821 UNICODE_STRING ustrDevice
;
825 /* Check arguments */
826 if ((dwflags
!= CDS_VIDEOPARAMETERS
&& lParam
!= NULL
) ||
829 EngSetLastError(ERROR_INVALID_PARAMETER
);
830 return DISP_CHANGE_BADPARAM
;
834 if ((dwflags
& (CDS_GLOBAL
|CDS_NORESET
)) && !(dwflags
& CDS_UPDATEREGISTRY
))
836 return DISP_CHANGE_BADFLAGS
;
839 /* Copy the device name */
842 /* Initialize destination string */
843 RtlInitEmptyUnicodeString(&ustrDevice
, awcDevice
, sizeof(awcDevice
));
847 /* Probe the UNICODE_STRING and the buffer */
848 ProbeForRead(pustrDevice
, sizeof(UNICODE_STRING
), 1);
849 ProbeForRead(pustrDevice
->Buffer
, pustrDevice
->Length
, 1);
851 /* Copy the string */
852 RtlCopyUnicodeString(&ustrDevice
, pustrDevice
);
854 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
856 /* Set and return error */
857 SetLastNtError(_SEH2_GetExceptionCode());
858 _SEH2_YIELD(return DISP_CHANGE_BADPARAM
);
862 pustrDevice
= &ustrDevice
;
870 /* Probe the size field of the structure */
871 ProbeForRead(lpDevMode
, sizeof(dmLocal
.dmSize
), 1);
873 /* Calculate usable size */
874 dmLocal
.dmSize
= min(sizeof(dmLocal
), lpDevMode
->dmSize
);
876 /* Probe and copy the full DEVMODE */
877 ProbeForRead(lpDevMode
, dmLocal
.dmSize
, 1);
878 RtlCopyMemory(&dmLocal
, lpDevMode
, dmLocal
.dmSize
);
880 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
882 /* Set and return error */
883 SetLastNtError(_SEH2_GetExceptionCode());
884 _SEH2_YIELD(return DISP_CHANGE_BADPARAM
);
888 /* Check for extra parameters */
889 if (dmLocal
.dmDriverExtra
> 0)
892 ERR("lpDevMode->dmDriverExtra is IGNORED!\n");
893 dmLocal
.dmDriverExtra
= 0;
896 /* Use the local structure */
897 lpDevMode
= &dmLocal
;
900 // FIXME: Copy videoparameters
902 /* Acquire global USER lock */
903 UserEnterExclusive();
905 /* Call internal function */
906 lRet
= UserChangeDisplaySettings(pustrDevice
, lpDevMode
, hwnd
, dwflags
, NULL
);