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 RtlZeroMemory(pdm
, sizeof(DEVMODEW
));
83 if (RegReadDWORD(hkey
, L
"DefaultSettings.BitsPerPel", &dwValue
))
85 pdm
->dmBitsPerPel
= dwValue
;
86 pdm
->dmFields
|= DM_BITSPERPEL
;
88 if (RegReadDWORD(hkey
, L
"DefaultSettings.XResolution", &dwValue
))
90 pdm
->dmPelsWidth
= dwValue
;
91 // pdm->dmFields |= DM_XRESOLUTION;
93 if (RegReadDWORD(hkey
, L
"DefaultSettings.YResolution", &dwValue
))
95 pdm
->dmPelsHeight
= dwValue
;
96 pdm
->dmFields
|= DM_YRESOLUTION
;
98 if (RegReadDWORD(hkey
, L
"DefaultSettings.Flags", &dwValue
))
100 pdm
->dmDisplayFlags
= dwValue
;
101 pdm
->dmFields
|= DM_BITSPERPEL
;
103 if (RegReadDWORD(hkey
, L
"DefaultSettings.VRefresh", &dwValue
))
105 pdm
->dmDisplayFrequency
= dwValue
;
106 pdm
->dmFields
|= DM_DISPLAYFREQUENCY
;
108 if (RegReadDWORD(hkey
, L
"DefaultSettings.XPanning", &dwValue
))
110 pdm
->dmPanningWidth
= dwValue
;
111 pdm
->dmFields
|= DM_PANNINGWIDTH
;
113 if (RegReadDWORD(hkey
, L
"DefaultSettings.YPanning", &dwValue
))
115 pdm
->dmPanningHeight
= dwValue
;
116 pdm
->dmFields
|= DM_PANNINGHEIGHT
;
118 if (RegReadDWORD(hkey
, L
"DefaultSettings.Orientation", &dwValue
))
120 pdm
->dmDisplayOrientation
= dwValue
;
121 pdm
->dmFields
|= DM_DISPLAYORIENTATION
;
123 if (RegReadDWORD(hkey
, L
"DefaultSettings.FixedOutput", &dwValue
))
125 pdm
->dmDisplayFixedOutput
= dwValue
;
126 pdm
->dmFields
|= DM_BITSPERPEL
;
128 if (RegReadDWORD(hkey
, L
"Attach.RelativeX", &dwValue
))
130 pdm
->dmPosition
.x
= dwValue
;
131 pdm
->dmFields
|= DM_POSITION
;
133 if (RegReadDWORD(hkey
, L
"Attach.RelativeY", &dwValue
))
135 pdm
->dmPosition
.y
= dwValue
;
136 pdm
->dmFields
|= DM_POSITION
;
138 // RegReadDWORD(hkey, L"Attach.ToDesktop, pdm->dmBitsPerPel", &pdm->);
152 PUNICODE_STRING pustrRegPath
,
155 // PWSTR pwszDriverName;
156 RTL_QUERY_REGISTRY_TABLE QueryTable
[2];
159 /* Setup QueryTable for direct registry query */
160 RtlZeroMemory(QueryTable
, sizeof(QueryTable
));
161 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_REQUIRED
|RTL_QUERY_REGISTRY_DIRECT
;
164 /* Check if vga mode is requested */
165 if (flags
& VF_USEVGA
)
167 DWORD dwVgaCompatible
;
170 QueryTable
[0].Name
= L
"VgaCompatible";
171 QueryTable
[0].EntryContext
= &dwVgaCompatible
;
173 /* Check if the driver is vga */
174 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
175 pustrRegPath
->Buffer
,
180 if (!dwVgaCompatible
)
182 /* This driver is not a vga driver */
189 /* Query the adapter's registry path */
190 swprintf(awcBuffer
, L
"\\Device\\Video%lu", iDevNum
);
191 QueryTable
[0].Name
= pGraphicsDevice
->szNtDeviceName
;
193 /* Set string for the registry key */
194 ustrRegistryPath
.Buffer
= pdispdev
->DeviceKey
;
195 ustrRegistryPath
.Length
= 128;
196 ustrRegistryPath
.MaximumLength
= 128;
197 QueryTable
[0].EntryContext
= &ustrRegistryPath
;
199 /* Query the registry */
200 Status
= RtlQueryRegistryValues(RTL_REGISTRY_DEVICEMAP
,
206 RegQueryValue(KEY_VIDEO
, awcBuffer
, REG_SZ
, pdispdev
->DeviceKey
, 256);
211 hmod
= EngLoadImage(pwszDriverName
);
213 /* Jump to next name */
214 pwszDriverName
+= wcslen(pwszDriverName
) + 1;
216 while (pwszDriverName
< 0);
225 DisplayDriverQueryRoutine(
229 IN ULONG ValueLength
,
231 IN PVOID EntryContext
)
233 PWSTR pwszRegKey
= ValueData
;
234 PGRAPHICS_DEVICE pGraphicsDevice
;
235 UNICODE_STRING ustrDeviceName
, ustrDisplayDrivers
, ustrDescription
;
237 WCHAR awcBuffer
[128];
242 UNREFERENCED_PARAMETER(ValueLength
);
243 UNREFERENCED_PARAMETER(Context
);
244 UNREFERENCED_PARAMETER(EntryContext
);
246 DPRINT1("DisplayDriverQueryRoutine(%S, %S);\n",
247 ValueName
, pwszRegKey
);
249 /* Check if we have a correct entry */
250 if (ValueType
!= REG_SZ
|| ValueName
[0] != '\\')
252 /* Something else, just skip it */
253 return STATUS_SUCCESS
;
256 /* Open the driver's registry key */
257 Status
= RegOpenKey(pwszRegKey
, &hkey
);
258 if (!NT_SUCCESS(Status
))
260 DPRINT1("Failed to open registry key\n");
261 return STATUS_SUCCESS
;
264 // HACK: only use 1st adapter
265 //if (ValueName[13] != '0')
266 // return STATUS_SUCCESS;
268 /* Query the diplay drivers */
269 cbSize
= sizeof(awcBuffer
) - 10;
270 Status
= RegQueryValue(hkey
,
271 L
"InstalledDisplayDrivers",
275 if (!NT_SUCCESS(Status
))
277 DPRINT1("Didn't find 'InstalledDisplayDrivers', status = 0x%lx\n", Status
);
279 return STATUS_SUCCESS
;
282 /* Initialize the UNICODE_STRING */
283 ustrDisplayDrivers
.Buffer
= awcBuffer
;
284 ustrDisplayDrivers
.MaximumLength
= cbSize
;
285 ustrDisplayDrivers
.Length
= cbSize
;
287 /* Set Buffer for description and size of remaining buffer */
288 ustrDescription
.Buffer
= awcBuffer
+ (cbSize
/ sizeof(WCHAR
));
289 cbSize
= sizeof(awcBuffer
) - cbSize
;
291 /* Query the device string */
292 Status
= RegQueryValue(hkey
,
293 L
"Device Description",
295 ustrDescription
.Buffer
,
297 if (NT_SUCCESS(Status
))
299 ustrDescription
.MaximumLength
= cbSize
;
300 ustrDescription
.Length
= cbSize
;
304 RtlInitUnicodeString(&ustrDescription
, L
"<unknown>");
307 /* Query the default settings */
308 RegReadDisplaySettings(hkey
, &dmDefault
);
310 /* Close the registry key */
313 /* Register the device with GDI */
314 RtlInitUnicodeString(&ustrDeviceName
, ValueName
);
315 pGraphicsDevice
= EngpRegisterGraphicsDevice(&ustrDeviceName
,
320 // FIXME: what to do with pGraphicsDevice?
322 return STATUS_SUCCESS
;
325 BOOL
InitSysParams();
328 InitVideo(FLONG flags
)
330 RTL_QUERY_REGISTRY_TABLE QueryTable
[2];
333 DPRINT1("----------------------------- InitVideo() -------------------------------\n");
335 /* Setup QueryTable for registry query */
336 RtlZeroMemory(QueryTable
, sizeof(QueryTable
));
337 QueryTable
[0].QueryRoutine
= DisplayDriverQueryRoutine
;
339 /* Query the registry */
340 Status
= RtlQueryRegistryValues(RTL_REGISTRY_DEVICEMAP
,
354 UserEnumDisplayDevices(
355 PUNICODE_STRING pustrDevice
,
357 PDISPLAY_DEVICEW pdispdev
,
360 PGRAPHICS_DEVICE pGraphicsDevice
;
365 /* Ask gdi for the GRAPHICS_DEVICE */
366 pGraphicsDevice
= EngpFindGraphicsDevice(pustrDevice
, iDevNum
, 0);
367 if (!pGraphicsDevice
)
369 /* No device found */
370 DPRINT1("No GRAPHICS_DEVICE found\n");
371 return STATUS_UNSUCCESSFUL
;
374 /* Open thhe device map registry key */
375 Status
= RegOpenKey(KEY_VIDEO
, &hkey
);
376 if (!NT_SUCCESS(Status
))
378 /* No device found */
379 DPRINT1("Could not open reg key\n");
380 return STATUS_UNSUCCESSFUL
;
383 /* Query the registry path */
384 cbSize
= sizeof(pdispdev
->DeviceKey
);
386 pGraphicsDevice
->szNtDeviceName
,
391 /* Close registry key */
394 /* Copy device name, device string and StateFlags */
395 wcsncpy(pdispdev
->DeviceName
, pGraphicsDevice
->szWinDeviceName
, 32);
396 wcsncpy(pdispdev
->DeviceString
, pGraphicsDevice
->pwszDescription
, 128);
397 pdispdev
->StateFlags
= pGraphicsDevice
->StateFlags
;
399 // FIXME: fill in DEVICE ID
401 return STATUS_SUCCESS
;
407 NtUserEnumDisplayDevices(
408 PUNICODE_STRING pustrDevice
,
410 PDISPLAY_DEVICEW pDisplayDevice
,
413 UNICODE_STRING ustrDevice
;
414 WCHAR awcDevice
[CCHDEVICENAME
];
415 DISPLAY_DEVICEW dispdev
;
418 DPRINT1("Enter NtUserEnumDisplayDevices(%p, %ls, %ld)\n",
419 pustrDevice
, pustrDevice
? pustrDevice
->Buffer
: 0, iDevNum
);
421 // FIXME: HACK, desk.cpl passes broken crap
422 if (pustrDevice
&& iDevNum
!= 0)
425 dispdev
.cb
= sizeof(DISPLAY_DEVICEW
);
429 /* Initialize destination string */
430 RtlInitEmptyUnicodeString(&ustrDevice
, awcDevice
, sizeof(awcDevice
));
434 /* Probe the UNICODE_STRING and the buffer */
435 ProbeForRead(pustrDevice
, sizeof(UNICODE_STRING
), 1);
436 ProbeForRead(pustrDevice
->Buffer
, pustrDevice
->Length
, 1);
438 /* Copy the string */
439 RtlCopyUnicodeString(&ustrDevice
, pustrDevice
);
441 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
443 // _SEH2_YIELD(return _SEH2_GetExceptionCode());
444 _SEH2_YIELD(return NT_SUCCESS(_SEH2_GetExceptionCode()));
448 if (ustrDevice
.Length
> 0)
449 pustrDevice
= &ustrDevice
;
454 /* Acquire global USER lock */
455 UserEnterExclusive();
457 /* Call the internal function */
458 Status
= UserEnumDisplayDevices(pustrDevice
, iDevNum
, &dispdev
, dwFlags
);
463 /* On success copy data to caller */
464 if (NT_SUCCESS(Status
))
469 /* First probe the cb field */
470 ProbeForWrite(&pDisplayDevice
->cb
, sizeof(DWORD
), 1);
472 /* Check the buffer size */
473 if (pDisplayDevice
->cb
)
475 /* Probe the output buffer */
476 pDisplayDevice
->cb
= min(pDisplayDevice
->cb
, sizeof(dispdev
));
477 ProbeForWrite(pDisplayDevice
, pDisplayDevice
->cb
, 1);
479 /* Copy as much as the given buffer allows */
480 RtlCopyMemory(pDisplayDevice
, &dispdev
, pDisplayDevice
->cb
);
483 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
485 Status
= _SEH2_GetExceptionCode();
490 DPRINT1("Leave NtUserEnumDisplayDevices, Status = 0x%lx\n", Status
);
491 /* Return the result */
493 return NT_SUCCESS(Status
); // FIXME
498 UserEnumCurrentDisplaySettings(
499 PUNICODE_STRING pustrDevice
,
504 /* Get the PDEV for the device */
505 ppdev
= EngpGetPDEV(pustrDevice
);
508 /* No device found */
509 DPRINT1("No PDEV found!\n");
510 return STATUS_UNSUCCESSFUL
;
513 *ppdm
= ppdev
->pdmwDev
;
514 PDEVOBJ_vRelease(ppdev
);
516 return STATUS_SUCCESS
;
521 UserEnumDisplaySettings(
522 PUNICODE_STRING pustrDevice
,
527 PGRAPHICS_DEVICE pGraphicsDevice
;
528 PDEVMODEENTRY pdmentry
;
531 DPRINT1("Enter UserEnumDisplaySettings('%ls', %ld)\n",
532 pustrDevice
? pustrDevice
->Buffer
: NULL
, iModeNum
);
534 /* Ask gdi for the GRAPHICS_DEVICE */
535 pGraphicsDevice
= EngpFindGraphicsDevice(pustrDevice
, 0, 0);
536 if (!pGraphicsDevice
)
538 /* No device found */
539 DPRINT1("No device found!\n");
545 DPRINT1("Should initialize modes somehow\n");
546 // Update DISPLAY_DEVICEs?
550 for (i
= 0; i
< pGraphicsDevice
->cDevModes
; i
++)
552 pdmentry
= &pGraphicsDevice
->pDevModeList
[i
];
554 // if ((!(dwFlags & EDS_RAWMODE) && (pdmentry->dwFlags & 1)) || // FIXME!
555 // (dwFlags & EDS_RAWMODE))
557 /* Is this the one we want? */
558 if (iFoundMode
== iModeNum
)
560 *ppdm
= pdmentry
->pdm
;
561 return STATUS_SUCCESS
;
564 /* Increment number of found modes */
569 /* Nothing was found */
570 return STATUS_INVALID_PARAMETER
;
575 UserOpenDisplaySettingsKey(
577 IN PUNICODE_STRING pustrDevice
,
581 DISPLAY_DEVICEW dispdev
;
584 /* Get device info */
585 Status
= UserEnumDisplayDevices(pustrDevice
, 0, &dispdev
, 0);
586 if (!NT_SUCCESS(Status
))
591 // FIXME: need to fix the registry key somehow
594 /* Open the registry key */
595 Status
= RegOpenKey(dispdev
.DeviceKey
, &hkey
);
596 if (!NT_SUCCESS(Status
))
606 UserEnumRegistryDisplaySettings(
607 IN PUNICODE_STRING pustrDevice
,
611 return STATUS_NOT_IMPLEMENTED
;
617 NtUserEnumDisplaySettings(
618 IN PUNICODE_STRING pustrDevice
,
620 OUT LPDEVMODEW lpDevMode
,
623 UNICODE_STRING ustrDevice
;
624 WCHAR awcDevice
[CCHDEVICENAME
];
626 ULONG cbSize
, cbExtra
;
627 DEVMODEW dmReg
, *pdm
;
629 DPRINT1("Enter NtUserEnumDisplaySettings(%ls, %ld)\n",
630 pustrDevice
? pustrDevice
->Buffer
:0, iModeNum
);
634 /* Initialize destination string */
635 RtlInitEmptyUnicodeString(&ustrDevice
, awcDevice
, sizeof(awcDevice
));
639 /* Probe the UNICODE_STRING and the buffer */
640 ProbeForRead(pustrDevice
, sizeof(UNICODE_STRING
), 1);
641 ProbeForRead(pustrDevice
->Buffer
, pustrDevice
->Length
, 1);
643 /* Copy the string */
644 RtlCopyUnicodeString(&ustrDevice
, pustrDevice
);
646 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
648 _SEH2_YIELD(return _SEH2_GetExceptionCode());
652 pustrDevice
= &ustrDevice
;
655 /* Acquire global USER lock */
656 UserEnterExclusive();
658 if (iModeNum
== ENUM_REGISTRY_SETTINGS
)
660 /* Get the registry settings */
661 Status
= UserEnumRegistryDisplaySettings(pustrDevice
, &dmReg
);
664 else if (iModeNum
== ENUM_CURRENT_SETTINGS
)
666 /* Get the current settings */
667 Status
= UserEnumCurrentDisplaySettings(pustrDevice
, &pdm
);
671 /* Get specified settings */
672 Status
= UserEnumDisplaySettings(pustrDevice
, iModeNum
, &pdm
, dwFlags
);
678 /* Did we succeed? */
679 if (NT_SUCCESS(Status
))
681 /* Copy some information back */
684 ProbeForRead(lpDevMode
, sizeof(DEVMODEW
), 1);
685 cbSize
= lpDevMode
->dmSize
;
686 cbExtra
= lpDevMode
->dmDriverExtra
;
688 ProbeForWrite(lpDevMode
, cbSize
+ cbExtra
, 1);
689 lpDevMode
->dmPelsWidth
= pdm
->dmPelsWidth
;
690 lpDevMode
->dmPelsHeight
= pdm
->dmPelsHeight
;
691 lpDevMode
->dmBitsPerPel
= pdm
->dmBitsPerPel
;
692 lpDevMode
->dmDisplayFrequency
= pdm
->dmDisplayFrequency
;
693 lpDevMode
->dmDisplayFlags
= pdm
->dmDisplayFlags
;
695 /* output private/extra driver data */
696 if (cbExtra
> 0 && pdm
->dmDriverExtra
> 0)
698 RtlCopyMemory((PCHAR
)lpDevMode
+ cbSize
,
699 (PCHAR
)pdm
+ pdm
->dmSize
,
700 min(cbExtra
, pdm
->dmDriverExtra
));
703 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
705 Status
= _SEH2_GetExceptionCode();
713 BOOL APIENTRY
UserClipCursor(RECTL
*prcl
);
714 VOID APIENTRY
UserRedrawDesktop();
718 UserChangeDisplaySettings(
719 PUNICODE_STRING pustrDevice
,
726 LONG lResult
= DISP_CHANGE_SUCCESSFUL
;
732 /* If no DEVMODE is given, use registry settings */
735 /* Get the registry settings */
736 Status
= UserEnumRegistryDisplaySettings(pustrDevice
, &dmReg
);
737 if (!NT_SUCCESS(Status
))
739 DPRINT1("Could not load registry settings\n");
740 return DISP_CHANGE_BADPARAM
;
746 ppdev
= EngpGetPDEV(pustrDevice
);
749 DPRINT1("failed to get PDEV\n");
750 return DISP_CHANGE_BADPARAM
;
753 /* Look for the requested DEVMODE */
754 pdm
= PDEVOBJ_pdmMatchDevMode(ppdev
, pdm
);
757 DPRINT1("Could not find a matching DEVMODE\n");
758 lResult
= DISP_CHANGE_BADMODE
;
762 /* Shall we update the registry? */
763 if (flags
& CDS_UPDATEREGISTRY
)
765 /* Open the local or global settings key */
766 Status
= UserOpenDisplaySettingsKey(&hkey
, pustrDevice
, flags
& CDS_GLOBAL
);
767 if (NT_SUCCESS(Status
))
769 /* Store the settings */
770 RegWriteDisplaySettings(hkey
, pdm
);
772 /* Close the registry key */
777 DPRINT1("Could not open registry key\n");
778 lResult
= DISP_CHANGE_NOTUPDATED
;
782 /* Check if DEVMODE matches the current mode */
783 if (pdm
== ppdev
->pdmwDev
&& !(flags
& CDS_RESET
))
785 DPRINT1("DEVMODE matches, nothing to do\n");
789 /* Shall we apply the settings? */
790 if (!(flags
& CDS_NORESET
))
792 if (!PDEVOBJ_bSwitchMode(ppdev
, pdm
))
794 DPRINT1("failed to set mode\n");
795 lResult
= (lResult
== DISP_CHANGE_NOTUPDATED
) ?
796 DISP_CHANGE_FAILED
: DISP_CHANGE_RESTART
;
799 /* Update the system metrics */
802 /* Remove all cursor clipping */
803 UserClipCursor(NULL
);
805 pdesk
= IntGetActiveDesktop();
806 IntHideDesktop(pdesk
);
807 co_IntShowDesktop(pdesk
, ppdev
->gdiinfo
.ulHorzRes
, ppdev
->gdiinfo
.ulVertRes
);
808 //UserRedrawDesktop();
810 //IntvGetDeviceCaps(&PrimarySurface, &GdiHandleTable->DevCaps);
817 PDEVOBJ_vRelease(ppdev
);
824 NtUserChangeDisplaySettings(
825 PUNICODE_STRING pustrDevice
,
826 LPDEVMODEW lpDevMode
,
831 WCHAR awcDevice
[CCHDEVICENAME
];
832 UNICODE_STRING ustrDevice
;
836 /* Check arguments */
837 if ((dwflags
!= CDS_VIDEOPARAMETERS
&& lParam
!= NULL
) ||
840 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
841 return DISP_CHANGE_BADPARAM
;
845 if ((dwflags
& (CDS_GLOBAL
|CDS_NORESET
)) && !(dwflags
& CDS_UPDATEREGISTRY
))
847 return DISP_CHANGE_BADFLAGS
;
850 /* Copy the device name */
853 /* Initialize destination string */
854 RtlInitEmptyUnicodeString(&ustrDevice
, awcDevice
, sizeof(awcDevice
));
858 /* Probe the UNICODE_STRING and the buffer */
859 ProbeForRead(pustrDevice
, sizeof(UNICODE_STRING
), 1);
860 ProbeForRead(pustrDevice
->Buffer
, pustrDevice
->Length
, 1);
862 /* Copy the string */
863 RtlCopyUnicodeString(&ustrDevice
, pustrDevice
);
865 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
867 SetLastNtError(_SEH2_GetExceptionCode());
868 _SEH2_YIELD(return DISP_CHANGE_BADPARAM
);
872 pustrDevice
= &ustrDevice
;
880 ProbeForRead(lpDevMode
, sizeof(dmLocal
.dmSize
), 1);
881 dmLocal
.dmSize
= min(sizeof(dmLocal
), lpDevMode
->dmSize
);
882 ProbeForRead(lpDevMode
, dmLocal
.dmSize
, 1);
883 RtlCopyMemory(&dmLocal
, lpDevMode
, dmLocal
.dmSize
);
884 dmLocal
.dmSize
= sizeof(dmLocal
);
886 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
888 SetLastNtError(_SEH2_GetExceptionCode());
889 _SEH2_YIELD(return DISP_CHANGE_BADPARAM
);
893 if (dmLocal
.dmDriverExtra
> 0)
895 DPRINT1("lpDevMode->dmDriverExtra is IGNORED!\n");
896 dmLocal
.dmDriverExtra
= 0;
898 lpDevMode
= &dmLocal
;
901 // FIXME: Copy videoparameters
902 UserEnterExclusive();
904 /* Call internal function */
905 Ret
= UserChangeDisplaySettings(pustrDevice
, lpDevMode
, hwnd
, dwflags
, NULL
);