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
;
515 return STATUS_SUCCESS
;
520 UserEnumDisplaySettings(
521 PUNICODE_STRING pustrDevice
,
526 PGRAPHICS_DEVICE pGraphicsDevice
;
527 PDEVMODEENTRY pdmentry
;
530 DPRINT1("Enter UserEnumDisplaySettings('%ls', %ld)\n",
531 pustrDevice
? pustrDevice
->Buffer
: NULL
, iModeNum
);
533 /* Ask gdi for the GRAPHICS_DEVICE */
534 pGraphicsDevice
= EngpFindGraphicsDevice(pustrDevice
, 0, 0);
535 if (!pGraphicsDevice
)
537 /* No device found */
538 DPRINT1("No device found!\n");
544 DPRINT1("Should initialize modes somehow\n");
545 // Update DISPLAY_DEVICEs?
549 for (i
= 0; i
< pGraphicsDevice
->cDevModes
; i
++)
551 pdmentry
= &pGraphicsDevice
->pDevModeList
[i
];
553 // if ((!(dwFlags & EDS_RAWMODE) && (pdmentry->dwFlags & 1)) || // FIXME!
554 // (dwFlags & EDS_RAWMODE))
556 /* Is this the one we want? */
557 if (iFoundMode
== iModeNum
)
559 *ppdm
= pdmentry
->pdm
;
560 return STATUS_SUCCESS
;
563 /* Increment number of found modes */
568 /* Nothing was found */
569 return STATUS_INVALID_PARAMETER
;
574 UserOpenDisplaySettingsKey(
576 IN PUNICODE_STRING pustrDevice
,
580 DISPLAY_DEVICEW dispdev
;
583 /* Get device info */
584 Status
= UserEnumDisplayDevices(pustrDevice
, 0, &dispdev
, 0);
585 if (!NT_SUCCESS(Status
))
590 // FIXME: need to fix the registry key somehow
593 /* Open the registry key */
594 Status
= RegOpenKey(dispdev
.DeviceKey
, &hkey
);
595 if (!NT_SUCCESS(Status
))
605 UserEnumRegistryDisplaySettings(
606 IN PUNICODE_STRING pustrDevice
,
610 return STATUS_NOT_IMPLEMENTED
;
616 NtUserEnumDisplaySettings(
617 IN PUNICODE_STRING pustrDevice
,
619 OUT LPDEVMODEW lpDevMode
,
622 UNICODE_STRING ustrDevice
;
623 WCHAR awcDevice
[CCHDEVICENAME
];
625 ULONG cbSize
, cbExtra
;
626 DEVMODEW dmReg
, *pdm
;
628 DPRINT1("Enter NtUserEnumDisplaySettings(%ls, %ld)\n",
629 pustrDevice
? pustrDevice
->Buffer
:0, iModeNum
);
633 /* Initialize destination string */
634 RtlInitEmptyUnicodeString(&ustrDevice
, awcDevice
, sizeof(awcDevice
));
638 /* Probe the UNICODE_STRING and the buffer */
639 ProbeForRead(pustrDevice
, sizeof(UNICODE_STRING
), 1);
640 ProbeForRead(pustrDevice
->Buffer
, pustrDevice
->Length
, 1);
642 /* Copy the string */
643 RtlCopyUnicodeString(&ustrDevice
, pustrDevice
);
645 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
647 _SEH2_YIELD(return _SEH2_GetExceptionCode());
651 pustrDevice
= &ustrDevice
;
654 /* Acquire global USER lock */
655 UserEnterExclusive();
657 if (iModeNum
== ENUM_REGISTRY_SETTINGS
)
659 /* Get the registry settings */
660 Status
= UserEnumRegistryDisplaySettings(pustrDevice
, &dmReg
);
663 else if (iModeNum
== ENUM_CURRENT_SETTINGS
)
665 /* Get the current settings */
666 Status
= UserEnumCurrentDisplaySettings(pustrDevice
, &pdm
);
670 /* Get specified settings */
671 Status
= UserEnumDisplaySettings(pustrDevice
, iModeNum
, &pdm
, dwFlags
);
677 /* Did we succeed? */
678 if (NT_SUCCESS(Status
))
680 /* Copy some information back */
683 ProbeForRead(lpDevMode
, sizeof(DEVMODEW
), 1);
684 cbSize
= lpDevMode
->dmSize
;
685 cbExtra
= lpDevMode
->dmDriverExtra
;
687 ProbeForWrite(lpDevMode
, cbSize
+ cbExtra
, 1);
688 lpDevMode
->dmPelsWidth
= pdm
->dmPelsWidth
;
689 lpDevMode
->dmPelsHeight
= pdm
->dmPelsHeight
;
690 lpDevMode
->dmBitsPerPel
= pdm
->dmBitsPerPel
;
691 lpDevMode
->dmDisplayFrequency
= pdm
->dmDisplayFrequency
;
692 lpDevMode
->dmDisplayFlags
= pdm
->dmDisplayFlags
;
694 /* output private/extra driver data */
695 if (cbExtra
> 0 && pdm
->dmDriverExtra
> 0)
697 RtlCopyMemory((PCHAR
)lpDevMode
+ cbSize
,
698 (PCHAR
)pdm
+ pdm
->dmSize
,
699 min(cbExtra
, pdm
->dmDriverExtra
));
702 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
704 Status
= _SEH2_GetExceptionCode();
715 UserChangeDisplaySettings(
716 PUNICODE_STRING pustrDevice
,
723 LONG lResult
= DISP_CHANGE_SUCCESSFUL
;
728 /* If no DEVMODE is given, use registry settings */
731 /* Get the registry settings */
732 Status
= UserEnumRegistryDisplaySettings(pustrDevice
, &dmReg
);
733 if (!NT_SUCCESS(Status
))
735 DPRINT1("Could not load registry settings\n");
736 return DISP_CHANGE_BADPARAM
;
742 ppdev
= EngpGetPDEV(pustrDevice
);
745 DPRINT1("failed to get PDEV\n");
746 return DISP_CHANGE_BADPARAM
;
749 /* Look for the requested DEVMODE */
750 pdm
= PDEVOBJ_pdmMatchDevMode(ppdev
, pdm
);
753 DPRINT1("Could not find a matching DEVMODE\n");
754 lResult
= DISP_CHANGE_BADMODE
;
758 /* Shall we update the registry? */
759 if (flags
& CDS_UPDATEREGISTRY
)
761 /* Open the local or global settings key */
762 Status
= UserOpenDisplaySettingsKey(&hkey
, pustrDevice
, flags
& CDS_GLOBAL
);
763 if (NT_SUCCESS(Status
))
765 /* Store the settings */
766 RegWriteDisplaySettings(hkey
, pdm
);
768 /* Close the registry key */
773 DPRINT1("Could not open registry key\n");
774 lResult
= DISP_CHANGE_NOTUPDATED
;
778 /* Check if DEVMODE matches the current mode */
779 if (pdm
== ppdev
->pdmwDev
&& !(flags
& CDS_RESET
))
781 DPRINT1("DEVMODE matches, nothing to do\n");
785 /* Shall we apply the settings? */
786 if (!(flags
& CDS_NORESET
))
788 if (!PDEVOBJ_bSwitchMode(ppdev
, pdm
))
790 DPRINT1("failed to set mode\n");
791 lResult
= (lResult
== DISP_CHANGE_NOTUPDATED
) ?
792 DISP_CHANGE_FAILED
: DISP_CHANGE_RESTART
;
800 // PDEVOBJ_vReleasePdev(ppdev);
807 NtUserChangeDisplaySettings(
808 PUNICODE_STRING pustrDevice
,
809 LPDEVMODEW lpDevMode
,
814 WCHAR awcDevice
[CCHDEVICENAME
];
815 UNICODE_STRING ustrDevice
;
819 /* Check arguments */
820 if ((dwflags
!= CDS_VIDEOPARAMETERS
&& lParam
!= NULL
) ||
823 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
824 return DISP_CHANGE_BADPARAM
;
828 if ((dwflags
& (CDS_GLOBAL
|CDS_NORESET
)) && !(dwflags
& CDS_UPDATEREGISTRY
))
830 return DISP_CHANGE_BADFLAGS
;
833 /* Copy the device name */
836 /* Initialize destination string */
837 RtlInitEmptyUnicodeString(&ustrDevice
, awcDevice
, sizeof(awcDevice
));
841 /* Probe the UNICODE_STRING and the buffer */
842 ProbeForRead(pustrDevice
, sizeof(UNICODE_STRING
), 1);
843 ProbeForRead(pustrDevice
->Buffer
, pustrDevice
->Length
, 1);
845 /* Copy the string */
846 RtlCopyUnicodeString(&ustrDevice
, pustrDevice
);
848 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
850 SetLastNtError(_SEH2_GetExceptionCode());
851 _SEH2_YIELD(return DISP_CHANGE_BADPARAM
);
855 pustrDevice
= &ustrDevice
;
863 ProbeForRead(lpDevMode
, sizeof(dmLocal
.dmSize
), 1);
864 dmLocal
.dmSize
= min(sizeof(dmLocal
), lpDevMode
->dmSize
);
865 ProbeForRead(lpDevMode
, dmLocal
.dmSize
, 1);
866 RtlCopyMemory(&dmLocal
, lpDevMode
, dmLocal
.dmSize
);
867 dmLocal
.dmSize
= sizeof(dmLocal
);
869 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
871 SetLastNtError(_SEH2_GetExceptionCode());
872 _SEH2_YIELD(return DISP_CHANGE_BADPARAM
);
876 if (dmLocal
.dmDriverExtra
> 0)
878 DPRINT1("lpDevMode->dmDriverExtra is IGNORED!\n");
879 dmLocal
.dmDriverExtra
= 0;
881 lpDevMode
= &dmLocal
;
884 // FIXME: Copy videoparameters
886 /* Call internal function */
887 Ret
= UserChangeDisplaySettings(pustrDevice
, lpDevMode
, hwnd
, dwflags
, NULL
);