2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * PURPOSE: Video initialization and display settings
5 * FILE: win32ss/user/ntuser/display.c
6 * PROGRAMER: Timo Kreuzer (timo.kreuzer@reactos.org)
10 DBG_DEFAULT_CHANNEL(UserDisplay
);
13 static PPROCESSINFO gpFullscreen
= NULL
;
15 static const PWCHAR KEY_VIDEO
= L
"\\Registry\\Machine\\HARDWARE\\DEVICEMAP\\VIDEO";
18 RegWriteDisplaySettings(HKEY hkey
, PDEVMODEW pdm
)
20 RegWriteDWORD(hkey
, L
"DefaultSettings.BitsPerPel", pdm
->dmBitsPerPel
);
21 RegWriteDWORD(hkey
, L
"DefaultSettings.XResolution", pdm
->dmPelsWidth
);
22 RegWriteDWORD(hkey
, L
"DefaultSettings.YResolution", pdm
->dmPelsHeight
);
23 RegWriteDWORD(hkey
, L
"DefaultSettings.Flags", pdm
->dmDisplayFlags
);
24 RegWriteDWORD(hkey
, L
"DefaultSettings.VRefresh", pdm
->dmDisplayFrequency
);
25 RegWriteDWORD(hkey
, L
"DefaultSettings.XPanning", pdm
->dmPanningWidth
);
26 RegWriteDWORD(hkey
, L
"DefaultSettings.YPanning", pdm
->dmPanningHeight
);
27 RegWriteDWORD(hkey
, L
"DefaultSettings.Orientation", pdm
->dmDisplayOrientation
);
28 RegWriteDWORD(hkey
, L
"DefaultSettings.FixedOutput", pdm
->dmDisplayFixedOutput
);
29 RegWriteDWORD(hkey
, L
"Attach.RelativeX", pdm
->dmPosition
.x
);
30 RegWriteDWORD(hkey
, L
"Attach.RelativeY", pdm
->dmPosition
.y
);
31 // RegWriteDWORD(hkey, L"Attach.ToDesktop, pdm->dmBitsPerPel", pdm->);
35 RegReadDisplaySettings(HKEY hkey
, PDEVMODEW pdm
)
39 /* Zero out the structure */
40 RtlZeroMemory(pdm
, sizeof(DEVMODEW
));
43 #define READ(field, str, flag) \
44 if (RegReadDWORD(hkey, L##str, &dwValue)) \
46 pdm->field = dwValue; \
47 pdm->dmFields |= flag; \
50 /* Read all present settings */
51 READ(dmBitsPerPel
, "DefaultSettings.BitsPerPel", DM_BITSPERPEL
);
52 READ(dmPelsWidth
, "DefaultSettings.XResolution", DM_PELSWIDTH
);
53 READ(dmPelsHeight
, "DefaultSettings.YResolution", DM_PELSHEIGHT
);
54 READ(dmDisplayFlags
, "DefaultSettings.Flags", DM_DISPLAYFLAGS
);
55 READ(dmDisplayFrequency
, "DefaultSettings.VRefresh", DM_DISPLAYFREQUENCY
);
56 READ(dmPanningWidth
, "DefaultSettings.XPanning", DM_PANNINGWIDTH
);
57 READ(dmPanningHeight
, "DefaultSettings.YPanning", DM_PANNINGHEIGHT
);
58 READ(dmDisplayOrientation
, "DefaultSettings.Orientation", DM_DISPLAYORIENTATION
);
59 READ(dmDisplayFixedOutput
, "DefaultSettings.FixedOutput", DM_DISPLAYFIXEDOUTPUT
);
60 READ(dmPosition
.x
, "Attach.RelativeX", DM_POSITION
);
61 READ(dmPosition
.y
, "Attach.RelativeY", DM_POSITION
);
67 IN PWSTR pwszDeviceName
,
70 PGRAPHICS_DEVICE pGraphicsDevice
;
71 UNICODE_STRING ustrDeviceName
, ustrDisplayDrivers
, ustrDescription
;
79 TRACE("InitDisplayDriver(%S, %S);\n",
80 pwszDeviceName
, pwszRegKey
);
82 /* Open the driver's registry key */
83 Status
= RegOpenKey(pwszRegKey
, &hkey
);
84 if (!NT_SUCCESS(Status
))
86 ERR("Failed to open registry key: %ls\n", pwszRegKey
);
90 /* Query the diplay drivers */
91 cbSize
= sizeof(awcBuffer
) - 10;
92 Status
= RegQueryValue(hkey
,
93 L
"InstalledDisplayDrivers",
97 if (!NT_SUCCESS(Status
))
99 ERR("Didn't find 'InstalledDisplayDrivers', status = 0x%lx\n", Status
);
104 /* Initialize the UNICODE_STRING */
105 ustrDisplayDrivers
.Buffer
= awcBuffer
;
106 ustrDisplayDrivers
.MaximumLength
= (USHORT
)cbSize
;
107 ustrDisplayDrivers
.Length
= (USHORT
)cbSize
;
109 /* Set Buffer for description and size of remaining buffer */
110 ustrDescription
.Buffer
= awcBuffer
+ (cbSize
/ sizeof(WCHAR
));
111 cbSize
= sizeof(awcBuffer
) - cbSize
;
113 /* Query the device string */
114 Status
= RegQueryValue(hkey
,
115 L
"Device Description",
117 ustrDescription
.Buffer
,
119 if (NT_SUCCESS(Status
))
121 ustrDescription
.MaximumLength
= (USHORT
)cbSize
;
122 ustrDescription
.Length
= (USHORT
)cbSize
;
126 RtlInitUnicodeString(&ustrDescription
, L
"<unknown>");
129 /* Query the default settings */
130 RegReadDisplaySettings(hkey
, &dmDefault
);
132 /* Query if this is a VGA compatible driver */
133 cbSize
= sizeof(DWORD
);
134 Status
= RegQueryValue(hkey
, L
"VgaCompatible", REG_DWORD
, &dwVga
, &cbSize
);
135 if (!NT_SUCCESS(Status
)) dwVga
= 0;
137 /* Close the registry key */
140 /* Register the device with GDI */
141 RtlInitUnicodeString(&ustrDeviceName
, pwszDeviceName
);
142 pGraphicsDevice
= EngpRegisterGraphicsDevice(&ustrDeviceName
,
146 if (pGraphicsDevice
&& dwVga
)
148 pGraphicsDevice
->StateFlags
|= DISPLAY_DEVICE_VGA_COMPATIBLE
;
151 return pGraphicsDevice
;
158 ULONG iDevNum
, iVGACompatible
= -1, ulMaxObjectNumber
= 0;
159 WCHAR awcDeviceName
[20];
160 WCHAR awcBuffer
[256];
162 PGRAPHICS_DEVICE pGraphicsDevice
;
166 TRACE("----------------------------- InitVideo() -------------------------------\n");
168 /* Open the key for the boot command line */
169 Status
= RegOpenKey(L
"\\REGISTRY\\MACHINE\\SYSTEM\\CurrentControlSet\\Control", &hkey
);
170 if (NT_SUCCESS(Status
))
173 Status
= RegQueryValue(hkey
, L
"SystemStartOptions", REG_SZ
, awcBuffer
, &cbValue
);
174 if (NT_SUCCESS(Status
))
176 /* Check if VGA mode is requested. */
177 if (wcsstr(awcBuffer
, L
"BASEVIDEO") != 0)
179 ERR("VGA mode requested.\n");
187 /* Open the key for the adapters */
188 Status
= RegOpenKey(KEY_VIDEO
, &hkey
);
189 if (!NT_SUCCESS(Status
))
191 ERR("Could not open HARDWARE\\DEVICEMAP\\VIDEO registry key:0x%lx\n", Status
);
195 /* Read the name of the VGA adapter */
197 Status
= RegQueryValue(hkey
, L
"VgaCompatible", REG_SZ
, awcDeviceName
, &cbValue
);
198 if (NT_SUCCESS(Status
))
200 iVGACompatible
= _wtoi(&awcDeviceName
[13]);
201 ERR("VGA adapter = %lu\n", iVGACompatible
);
204 /* Get the maximum mumber of adapters */
205 if (!RegReadDWORD(hkey
, L
"MaxObjectNumber", &ulMaxObjectNumber
))
207 ERR("Could not read MaxObjectNumber, defaulting to 0.\n");
210 TRACE("Found %lu devices\n", ulMaxObjectNumber
+ 1);
212 /* Loop through all adapters */
213 for (iDevNum
= 0; iDevNum
<= ulMaxObjectNumber
; iDevNum
++)
215 /* Create the adapter's key name */
216 swprintf(awcDeviceName
, L
"\\Device\\Video%lu", iDevNum
);
218 /* Read the reg key name */
219 cbValue
= sizeof(awcBuffer
);
220 Status
= RegQueryValue(hkey
, awcDeviceName
, REG_SZ
, awcBuffer
, &cbValue
);
221 if (!NT_SUCCESS(Status
))
223 ERR("failed to query the registry path:0x%lx\n", Status
);
227 /* Initialize the driver for this device */
228 pGraphicsDevice
= InitDisplayDriver(awcDeviceName
, awcBuffer
);
229 if (!pGraphicsDevice
) continue;
231 /* Check if this is a VGA compatible adapter */
232 if (pGraphicsDevice
->StateFlags
& DISPLAY_DEVICE_VGA_COMPATIBLE
)
234 /* Save this as the VGA adapter */
235 if (!gpVgaGraphicsDevice
)
236 gpVgaGraphicsDevice
= pGraphicsDevice
;
237 TRACE("gpVgaGraphicsDevice = %p\n", gpVgaGraphicsDevice
);
241 /* Set the first one as primary device */
242 if (!gpPrimaryGraphicsDevice
)
243 gpPrimaryGraphicsDevice
= pGraphicsDevice
;
244 TRACE("gpPrimaryGraphicsDevice = %p\n", gpPrimaryGraphicsDevice
);
248 /* Close the device map registry key */
251 /* Was VGA mode requested? */
254 /* Check if we found a VGA compatible device */
255 if (gpVgaGraphicsDevice
)
257 /* Set the VgaAdapter as primary */
258 gpPrimaryGraphicsDevice
= gpVgaGraphicsDevice
;
263 ERR("Could not find VGA compatible driver. Trying normal.\n");
267 /* Check if we had any success */
268 if (!gpPrimaryGraphicsDevice
)
270 /* Check if there is a VGA device we skipped */
271 if (gpVgaGraphicsDevice
)
273 /* There is, use the VGA device */
274 gpPrimaryGraphicsDevice
= gpVgaGraphicsDevice
;
278 ERR("No usable display driver was found.\n");
279 return STATUS_UNSUCCESSFUL
;
290 UserEnumDisplayDevices(
291 PUNICODE_STRING pustrDevice
,
293 PDISPLAY_DEVICEW pdispdev
,
296 PGRAPHICS_DEVICE pGraphicsDevice
;
301 /* Ask gdi for the GRAPHICS_DEVICE */
302 pGraphicsDevice
= EngpFindGraphicsDevice(pustrDevice
, iDevNum
, 0);
303 if (!pGraphicsDevice
)
305 /* No device found */
306 ERR("No GRAPHICS_DEVICE found\n");
307 return STATUS_UNSUCCESSFUL
;
310 /* Open the device map registry key */
311 Status
= RegOpenKey(KEY_VIDEO
, &hkey
);
312 if (!NT_SUCCESS(Status
))
314 /* No device found */
315 ERR("Could not open reg key\n");
316 return STATUS_UNSUCCESSFUL
;
319 /* Query the registry path */
320 cbSize
= sizeof(pdispdev
->DeviceKey
);
322 pGraphicsDevice
->szNtDeviceName
,
327 /* Close registry key */
330 /* Copy device name, device string and StateFlags */
331 RtlStringCbCopyW(pdispdev
->DeviceName
, sizeof(pdispdev
->DeviceName
), pGraphicsDevice
->szWinDeviceName
);
332 RtlStringCbCopyW(pdispdev
->DeviceString
, sizeof(pdispdev
->DeviceString
), pGraphicsDevice
->pwszDescription
);
333 pdispdev
->StateFlags
= pGraphicsDevice
->StateFlags
;
334 // FIXME: fill in DEVICE ID
335 pdispdev
->DeviceID
[0] = UNICODE_NULL
;
337 return STATUS_SUCCESS
;
343 NtUserEnumDisplayDevices(
344 PUNICODE_STRING pustrDevice
,
346 PDISPLAY_DEVICEW pDisplayDevice
,
349 UNICODE_STRING ustrDevice
;
350 WCHAR awcDevice
[CCHDEVICENAME
];
351 DISPLAY_DEVICEW dispdev
;
354 TRACE("Enter NtUserEnumDisplayDevices(%wZ, %lu)\n",
355 pustrDevice
, iDevNum
);
357 dispdev
.cb
= sizeof(dispdev
);
361 /* Initialize destination string */
362 RtlInitEmptyUnicodeString(&ustrDevice
, awcDevice
, sizeof(awcDevice
));
366 /* Probe the UNICODE_STRING and the buffer */
367 ProbeForRead(pustrDevice
, sizeof(UNICODE_STRING
), 1);
368 ProbeForRead(pustrDevice
->Buffer
, pustrDevice
->Length
, 1);
370 /* Copy the string */
371 RtlCopyUnicodeString(&ustrDevice
, pustrDevice
);
373 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
375 // _SEH2_YIELD(return _SEH2_GetExceptionCode());
376 _SEH2_YIELD(return NT_SUCCESS(_SEH2_GetExceptionCode()));
380 if (ustrDevice
.Length
> 0)
381 pustrDevice
= &ustrDevice
;
386 /* If name is given only iDevNum==0 gives results */
387 if (pustrDevice
&& iDevNum
!= 0)
390 /* Acquire global USER lock */
393 /* Call the internal function */
394 Status
= UserEnumDisplayDevices(pustrDevice
, iDevNum
, &dispdev
, dwFlags
);
399 /* On success copy data to caller */
400 if (NT_SUCCESS(Status
))
405 /* First probe the cb field */
406 ProbeForWrite(&pDisplayDevice
->cb
, sizeof(DWORD
), 1);
408 /* Check the buffer size */
409 if (pDisplayDevice
->cb
)
411 /* Probe the output buffer */
412 pDisplayDevice
->cb
= min(pDisplayDevice
->cb
, sizeof(dispdev
));
413 ProbeForWrite(pDisplayDevice
, pDisplayDevice
->cb
, 1);
415 /* Copy as much as the given buffer allows */
416 RtlCopyMemory(pDisplayDevice
, &dispdev
, pDisplayDevice
->cb
);
419 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
421 Status
= _SEH2_GetExceptionCode();
426 TRACE("Leave NtUserEnumDisplayDevices, Status = 0x%lx\n", Status
);
427 /* Return the result */
429 return NT_SUCCESS(Status
); // FIXME
434 UserEnumCurrentDisplaySettings(
435 PUNICODE_STRING pustrDevice
,
440 /* Get the PDEV for the device */
441 ppdev
= EngpGetPDEV(pustrDevice
);
444 /* No device found */
445 ERR("No PDEV found!\n");
446 return STATUS_UNSUCCESSFUL
;
449 *ppdm
= ppdev
->pdmwDev
;
450 PDEVOBJ_vRelease(ppdev
);
452 return STATUS_SUCCESS
;
457 UserEnumDisplaySettings(
458 PUNICODE_STRING pustrDevice
,
463 PGRAPHICS_DEVICE pGraphicsDevice
;
464 PDEVMODEENTRY pdmentry
;
467 TRACE("Enter UserEnumDisplaySettings('%wZ', %lu)\n",
468 pustrDevice
, iModeNum
);
470 /* Ask GDI for the GRAPHICS_DEVICE */
471 pGraphicsDevice
= EngpFindGraphicsDevice(pustrDevice
, 0, 0);
473 if (!pGraphicsDevice
)
475 /* No device found */
476 ERR("No device found!\n");
477 return STATUS_UNSUCCESSFUL
;
480 if (iModeNum
>= pGraphicsDevice
->cDevModes
)
481 return STATUS_NO_MORE_ENTRIES
;
484 for (i
= 0; i
< pGraphicsDevice
->cDevModes
; i
++)
486 pdmentry
= &pGraphicsDevice
->pDevModeList
[i
];
488 /* FIXME: Consider EDS_RAWMODE */
490 if ((!(dwFlags
& EDS_RAWMODE
) && (pdmentry
->dwFlags
& 1)) ||!
491 (dwFlags
& EDS_RAWMODE
))
494 /* Is this the one we want? */
495 if (iFoundMode
== iModeNum
)
497 *ppdm
= pdmentry
->pdm
;
498 return STATUS_SUCCESS
;
501 /* Increment number of found modes */
506 /* Nothing was found */
507 return STATUS_INVALID_PARAMETER
;
512 UserOpenDisplaySettingsKey(
514 IN PUNICODE_STRING pustrDevice
,
518 DISPLAY_DEVICEW dispdev
;
521 /* Get device info */
522 Status
= UserEnumDisplayDevices(pustrDevice
, 0, &dispdev
, 0);
523 if (!NT_SUCCESS(Status
))
528 // FIXME: Need to fix the registry key somehow
531 /* Open the registry key */
532 Status
= RegOpenKey(dispdev
.DeviceKey
, &hkey
);
533 if (!NT_SUCCESS(Status
))
543 UserEnumRegistryDisplaySettings(
544 IN PUNICODE_STRING pustrDevice
,
548 NTSTATUS Status
= UserOpenDisplaySettingsKey(&hkey
, pustrDevice
, 0);
549 if(NT_SUCCESS(Status
))
551 RegReadDisplaySettings(hkey
, pdm
);
553 return STATUS_SUCCESS
;
560 NtUserEnumDisplaySettings(
561 IN PUNICODE_STRING pustrDevice
,
563 OUT LPDEVMODEW lpDevMode
,
566 UNICODE_STRING ustrDevice
;
567 WCHAR awcDevice
[CCHDEVICENAME
];
569 ULONG cbSize
, cbExtra
;
570 DEVMODEW dmReg
, *pdm
;
572 TRACE("Enter NtUserEnumDisplaySettings(%wZ, %lu, %p, 0x%lx)\n",
573 pustrDevice
, iModeNum
, lpDevMode
, dwFlags
);
577 /* Initialize destination string */
578 RtlInitEmptyUnicodeString(&ustrDevice
, awcDevice
, sizeof(awcDevice
));
582 /* Probe the UNICODE_STRING and the buffer */
583 ProbeForRead(pustrDevice
, sizeof(UNICODE_STRING
), 1);
584 ProbeForRead(pustrDevice
->Buffer
, pustrDevice
->Length
, 1);
586 /* Copy the string */
587 RtlCopyUnicodeString(&ustrDevice
, pustrDevice
);
589 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
591 _SEH2_YIELD(return _SEH2_GetExceptionCode());
595 pustrDevice
= &ustrDevice
;
598 /* Acquire global USER lock */
601 if (iModeNum
== ENUM_REGISTRY_SETTINGS
)
603 /* Get the registry settings */
604 Status
= UserEnumRegistryDisplaySettings(pustrDevice
, &dmReg
);
606 pdm
->dmSize
= sizeof(DEVMODEW
);
608 else if (iModeNum
== ENUM_CURRENT_SETTINGS
)
610 /* Get the current settings */
611 Status
= UserEnumCurrentDisplaySettings(pustrDevice
, &pdm
);
615 /* Get specified settings */
616 Status
= UserEnumDisplaySettings(pustrDevice
, iModeNum
, &pdm
, dwFlags
);
622 /* Did we succeed? */
623 if (NT_SUCCESS(Status
))
625 /* Copy some information back */
628 ProbeForRead(lpDevMode
, sizeof(DEVMODEW
), 1);
629 cbSize
= lpDevMode
->dmSize
;
630 cbExtra
= lpDevMode
->dmDriverExtra
;
632 ProbeForWrite(lpDevMode
, cbSize
+ cbExtra
, 1);
633 /* Output what we got */
634 RtlCopyMemory(lpDevMode
, pdm
, min(cbSize
, pdm
->dmSize
));
636 /* Output private/extra driver data */
637 if (cbExtra
> 0 && pdm
->dmDriverExtra
> 0)
639 RtlCopyMemory((PCHAR
)lpDevMode
+ cbSize
,
640 (PCHAR
)pdm
+ pdm
->dmSize
,
641 min(cbExtra
, pdm
->dmDriverExtra
));
644 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
646 Status
= _SEH2_GetExceptionCode();
655 UserUpdateFullscreen(
658 if (flags
& CDS_FULLSCREEN
)
659 gpFullscreen
= gptiCurrent
->ppi
;
666 UserChangeDisplaySettings(
667 PUNICODE_STRING pustrDevice
,
673 LONG lResult
= DISP_CHANGE_SUCCESSFUL
;
679 /* If no DEVMODE is given, use registry settings */
682 /* Get the registry settings */
683 Status
= UserEnumRegistryDisplaySettings(pustrDevice
, &dm
);
684 if (!NT_SUCCESS(Status
))
686 ERR("Could not load registry settings\n");
687 return DISP_CHANGE_BADPARAM
;
690 else if (pdm
->dmSize
< FIELD_OFFSET(DEVMODEW
, dmFields
))
691 return DISP_CHANGE_BADMODE
; /* This is what winXP SP3 returns */
696 if ((dm
.dmFields
& (DM_PELSWIDTH
| DM_PELSHEIGHT
)) != (DM_PELSWIDTH
| DM_PELSHEIGHT
))
698 ERR("Devmode doesn't specify the resolution.\n");
699 return DISP_CHANGE_BADMODE
;
703 ppdev
= EngpGetPDEV(pustrDevice
);
706 ERR("Failed to get PDEV\n");
707 return DISP_CHANGE_BADPARAM
;
711 if(dm
.dmBitsPerPel
== 0 || !(dm
.dmFields
& DM_BITSPERPEL
))
713 dm
.dmBitsPerPel
= ppdev
->pdmwDev
->dmBitsPerPel
;
714 dm
.dmFields
|= DM_BITSPERPEL
;
717 if((dm
.dmFields
& DM_DISPLAYFREQUENCY
) && (dm
.dmDisplayFrequency
== 0))
718 dm
.dmDisplayFrequency
= ppdev
->pdmwDev
->dmDisplayFrequency
;
720 /* Look for the requested DEVMODE */
721 pdm
= PDEVOBJ_pdmMatchDevMode(ppdev
, &dm
);
724 ERR("Could not find a matching DEVMODE\n");
725 lResult
= DISP_CHANGE_BADMODE
;
728 else if (flags
& CDS_TEST
)
730 /* It's possible, go ahead! */
731 lResult
= DISP_CHANGE_SUCCESSFUL
;
735 /* Shall we update the registry? */
736 if (flags
& CDS_UPDATEREGISTRY
)
738 /* Open the local or global settings key */
739 Status
= UserOpenDisplaySettingsKey(&hkey
, pustrDevice
, flags
& CDS_GLOBAL
);
740 if (NT_SUCCESS(Status
))
742 /* Store the settings */
743 RegWriteDisplaySettings(hkey
, pdm
);
745 /* Close the registry key */
750 ERR("Could not open registry key\n");
751 lResult
= DISP_CHANGE_NOTUPDATED
;
755 /* Check if DEVMODE matches the current mode */
756 if (pdm
== ppdev
->pdmwDev
&& !(flags
& CDS_RESET
))
758 ERR("DEVMODE matches, nothing to do\n");
762 /* Shall we apply the settings? */
763 if (!(flags
& CDS_NORESET
))
768 /* Remove mouse pointer */
769 pvOldCursor
= UserSetCursor(NULL
, TRUE
);
771 /* Do the mode switch */
772 ulResult
= PDEVOBJ_bSwitchMode(ppdev
, pdm
);
774 /* Restore mouse pointer, no hooks called */
775 pvOldCursor
= UserSetCursor(pvOldCursor
, TRUE
);
776 ASSERT(pvOldCursor
== NULL
);
778 /* Check for failure */
781 ERR("Failed to set mode\n");
782 lResult
= (lResult
== DISP_CHANGE_NOTUPDATED
) ?
783 DISP_CHANGE_FAILED
: DISP_CHANGE_RESTART
;
788 UserUpdateFullscreen(flags
);
790 /* Update the system metrics */
793 //IntvGetDeviceCaps(&PrimarySurface, &GdiHandleTable->DevCaps);
795 /* Set new size of the monitor */
796 UserUpdateMonitorSize((HDEV
)ppdev
);
798 /* Remove all cursor clipping */
799 UserClipCursor(NULL
);
801 //pdesk = IntGetActiveDesktop();
802 //IntHideDesktop(pdesk);
804 /* Send WM_DISPLAYCHANGE to all toplevel windows */
805 co_IntSendMessageTimeout(HWND_BROADCAST
,
807 (WPARAM
)ppdev
->gdiinfo
.cBitsPixel
,
808 (LPARAM
)(ppdev
->gdiinfo
.ulHorzRes
+ (ppdev
->gdiinfo
.ulVertRes
<< 16)),
813 //co_IntShowDesktop(pdesk, ppdev->gdiinfo.ulHorzRes, ppdev->gdiinfo.ulVertRes);
819 /* Release the PDEV */
820 PDEVOBJ_vRelease(ppdev
);
826 UserDisplayNotifyShutdown(
827 PPROCESSINFO ppiCurrent
)
829 if (ppiCurrent
== gpFullscreen
)
831 UserChangeDisplaySettings(NULL
, NULL
, 0, NULL
);
833 ERR("Failed to restore display mode!\n");
839 NtUserChangeDisplaySettings(
840 PUNICODE_STRING pustrDevice
,
841 LPDEVMODEW lpDevMode
,
845 WCHAR awcDevice
[CCHDEVICENAME
];
846 UNICODE_STRING ustrDevice
;
850 /* Check arguments */
851 if ((dwflags
!= CDS_VIDEOPARAMETERS
) && (lParam
!= NULL
))
853 EngSetLastError(ERROR_INVALID_PARAMETER
);
854 return DISP_CHANGE_BADPARAM
;
858 if ((dwflags
& (CDS_GLOBAL
|CDS_NORESET
)) && !(dwflags
& CDS_UPDATEREGISTRY
))
860 return DISP_CHANGE_BADFLAGS
;
863 /* Copy the device name */
866 /* Initialize destination string */
867 RtlInitEmptyUnicodeString(&ustrDevice
, awcDevice
, sizeof(awcDevice
));
871 /* Probe the UNICODE_STRING and the buffer */
872 ProbeForRead(pustrDevice
, sizeof(UNICODE_STRING
), 1);
873 ProbeForRead(pustrDevice
->Buffer
, pustrDevice
->Length
, 1);
875 /* Copy the string */
876 RtlCopyUnicodeString(&ustrDevice
, pustrDevice
);
878 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
880 /* Set and return error */
881 SetLastNtError(_SEH2_GetExceptionCode());
882 _SEH2_YIELD(return DISP_CHANGE_BADPARAM
);
886 pustrDevice
= &ustrDevice
;
894 /* Probe the size field of the structure */
895 ProbeForRead(lpDevMode
, sizeof(dmLocal
.dmSize
), 1);
897 /* Calculate usable size */
898 dmLocal
.dmSize
= min(sizeof(dmLocal
), lpDevMode
->dmSize
);
900 /* Probe and copy the full DEVMODE */
901 ProbeForRead(lpDevMode
, dmLocal
.dmSize
, 1);
902 RtlCopyMemory(&dmLocal
, lpDevMode
, dmLocal
.dmSize
);
904 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
906 /* Set and return error */
907 SetLastNtError(_SEH2_GetExceptionCode());
908 _SEH2_YIELD(return DISP_CHANGE_BADPARAM
);
912 /* Check for extra parameters */
913 if (dmLocal
.dmDriverExtra
> 0)
916 ERR("lpDevMode->dmDriverExtra is IGNORED!\n");
917 dmLocal
.dmDriverExtra
= 0;
920 /* Use the local structure */
921 lpDevMode
= &dmLocal
;
924 // FIXME: Copy videoparameters
926 /* Acquire global USER lock */
927 UserEnterExclusive();
929 /* Call internal function */
930 lRet
= UserChangeDisplaySettings(pustrDevice
, lpDevMode
, dwflags
, NULL
);