b5986a58df2d3f246db27c1ecb3264b88206cf9f
[reactos.git] / reactos / subsystems / win32 / win32k / ntuser / display.c
1 /*
2 * PROJECT: ReactOS Kernel
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: subsystems/win32/win32k/ntuser/display.c
5 * PURPOSE: display settings
6 * COPYRIGHT: Copyright 2007 ReactOS
7 *
8 */
9
10 /* INCLUDES ******************************************************************/
11
12 #include <win32k.h>
13
14 #define NDEBUG
15 #include <debug.h>
16
17 #define SIZEOF_DEVMODEW_300 188
18 #define SIZEOF_DEVMODEW_400 212
19 #define SIZEOF_DEVMODEW_500 220
20
21 /* PUBLIC FUNCTIONS ***********************************************************/
22
23 NTSTATUS
24 APIENTRY
25 NtUserEnumDisplaySettings(
26 PUNICODE_STRING pusDeviceName,
27 DWORD iModeNum,
28 LPDEVMODEW lpDevMode, /* FIXME is this correct? */
29 DWORD dwFlags )
30 {
31 NTSTATUS Status;
32 LPDEVMODEW pSafeDevMode;
33 PUNICODE_STRING pusSafeDeviceName = NULL;
34 UNICODE_STRING usSafeDeviceName;
35 USHORT Size = 0, ExtraSize = 0;
36
37 /* Copy the devmode */
38 _SEH2_TRY
39 {
40 ProbeForRead(lpDevMode, sizeof(DEVMODEW), 1);
41 Size = lpDevMode->dmSize;
42 ExtraSize = lpDevMode->dmDriverExtra;
43 }
44 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
45 {
46 DPRINT("FIXME ? : Out of range of DEVMODEW size \n");
47 _SEH2_YIELD(return _SEH2_GetExceptionCode());
48 }
49 _SEH2_END;
50
51 if (Size != sizeof(DEVMODEW))
52 {
53 return STATUS_BUFFER_TOO_SMALL;
54 }
55
56 pSafeDevMode = ExAllocatePoolWithTag(PagedPool, Size + ExtraSize, GDITAG_DEVMODE);
57 if (pSafeDevMode == NULL)
58 {
59 return STATUS_NO_MEMORY;
60 }
61 pSafeDevMode->dmSize = Size;
62 pSafeDevMode->dmDriverExtra = ExtraSize;
63
64 /* Copy the device name */
65 if (pusDeviceName != NULL)
66 {
67 Status = IntSafeCopyUnicodeString(&usSafeDeviceName, pusDeviceName);
68 if (!NT_SUCCESS(Status))
69 {
70 ExFreePool(pSafeDevMode);
71 return Status;
72 }
73 pusSafeDeviceName = &usSafeDeviceName;
74 }
75
76 /* Call internal function */
77 Status = IntEnumDisplaySettings(pusSafeDeviceName, iModeNum, pSafeDevMode, dwFlags);
78
79 if (pusSafeDeviceName != NULL)
80 RtlFreeUnicodeString(pusSafeDeviceName);
81
82 if (!NT_SUCCESS(Status))
83 {
84 ExFreePool(pSafeDevMode);
85 return Status;
86 }
87
88 /* Copy some information back */
89 _SEH2_TRY
90 {
91 ProbeForWrite(lpDevMode,Size + ExtraSize, 1);
92 lpDevMode->dmPelsWidth = pSafeDevMode->dmPelsWidth;
93 lpDevMode->dmPelsHeight = pSafeDevMode->dmPelsHeight;
94 lpDevMode->dmBitsPerPel = pSafeDevMode->dmBitsPerPel;
95 lpDevMode->dmDisplayFrequency = pSafeDevMode->dmDisplayFrequency;
96 lpDevMode->dmDisplayFlags = pSafeDevMode->dmDisplayFlags;
97
98 /* output private/extra driver data */
99 if (ExtraSize > 0)
100 {
101 memcpy((PCHAR)lpDevMode + Size, (PCHAR)pSafeDevMode + Size, ExtraSize);
102 }
103 }
104 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
105 {
106 Status = _SEH2_GetExceptionCode();
107 }
108 _SEH2_END;
109
110 ExFreePool(pSafeDevMode);
111 return Status;
112 }
113
114
115 LONG
116 APIENTRY
117 NtUserChangeDisplaySettings(
118 PUNICODE_STRING lpszDeviceName,
119 LPDEVMODEW lpDevMode,
120 HWND hwnd,
121 DWORD dwflags,
122 LPVOID lParam)
123 {
124 NTSTATUS Status = STATUS_SUCCESS;
125 LPDEVMODEW lpSafeDevMode = NULL;
126 DEVMODEW DevMode;
127 PUNICODE_STRING pSafeDeviceName = NULL;
128 UNICODE_STRING SafeDeviceName;
129 LONG Ret;
130
131 /* Check arguments */
132 #ifdef CDS_VIDEOPARAMETERS
133 if (dwflags != CDS_VIDEOPARAMETERS && lParam != NULL)
134 #else
135 if (lParam != NULL)
136 #endif
137 {
138 SetLastWin32Error(ERROR_INVALID_PARAMETER);
139 return DISP_CHANGE_BADPARAM;
140 }
141
142 if (hwnd != NULL)
143 {
144 SetLastWin32Error(ERROR_INVALID_PARAMETER);
145 return DISP_CHANGE_BADPARAM;
146 }
147
148 /* Copy devmode */
149 if (lpDevMode != NULL)
150 {
151 _SEH2_TRY
152 {
153 ProbeForRead(lpDevMode, sizeof(DevMode.dmSize), 1);
154 DevMode.dmSize = lpDevMode->dmSize;
155 DevMode.dmSize = min(sizeof(DevMode), DevMode.dmSize);
156 ProbeForRead(lpDevMode, DevMode.dmSize, 1);
157 RtlCopyMemory(&DevMode, lpDevMode, DevMode.dmSize);
158 }
159 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
160 {
161 Status = _SEH2_GetExceptionCode();
162 }
163 _SEH2_END
164
165 if (!NT_SUCCESS(Status))
166 {
167 SetLastNtError(Status);
168 return DISP_CHANGE_BADPARAM;
169 }
170
171 if (DevMode.dmDriverExtra > 0)
172 {
173 DPRINT1("lpDevMode->dmDriverExtra is IGNORED!\n");
174 DevMode.dmDriverExtra = 0;
175 }
176 lpSafeDevMode = &DevMode;
177 }
178
179 /* Copy the device name */
180 if (lpszDeviceName != NULL)
181 {
182 Status = IntSafeCopyUnicodeString(&SafeDeviceName, lpszDeviceName);
183 if (!NT_SUCCESS(Status))
184 {
185 SetLastNtError(Status);
186 return DISP_CHANGE_BADPARAM;
187 }
188 pSafeDeviceName = &SafeDeviceName;
189 }
190
191 /* Call internal function */
192 Ret = IntChangeDisplaySettings(pSafeDeviceName, lpSafeDevMode, dwflags, lParam);
193
194 if (pSafeDeviceName != NULL)
195 RtlFreeUnicodeString(pSafeDeviceName);
196
197 return Ret;
198 }
199