1 /*
2  * PROJECT:         ReactOS API tests
3  * LICENSE:         GPL - See COPYING in the top level directory
4  * PURPOSE:         Test for SystemParametersInfo function family
5  * PROGRAMMERS:     Giannis Adamopoulos
6  */
7 
8 #include "precomp.h"
9 
10 static HWND hWnd1, hWnd2;
11 
12 static BOOL g_bReadyForDisplayChange = FALSE;
13 static HANDLE g_hSemDisplayChange;
14 
15 /* FIXME: test for HWND_TOP, etc...*/
16 static int get_iwnd(HWND hWnd)
17 {
18     if(hWnd == hWnd1) return 1;
19     else if(hWnd == hWnd2) return 2;
20     else return 0;
21 }
22 
23 LRESULT CALLBACK SysParamsTestProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
24 {
25     int iwnd = get_iwnd(hWnd);
26 
27     if(message > WM_USER || !iwnd || IsDWmMsg(message) || IseKeyMsg(message))
28         return DefWindowProc(hWnd, message, wParam, lParam);
29 
30     switch(message)
31     {
32     case WM_GETICON :
33     case WM_SETICON:
34         break;
35     case WM_WINDOWPOSCHANGING:
36     case WM_WINDOWPOSCHANGED:
37         {
38             WINDOWPOS* pwp = (WINDOWPOS*)lParam;
39             ok(wParam==0,"expected wParam=0\n");
40             RECORD_MESSAGE(iwnd, message, SENT, get_iwnd(pwp->hwndInsertAfter), pwp->flags);
41             break;
42         }
43     case WM_DISPLAYCHANGE:
44         if (g_bReadyForDisplayChange)
45         {
46             g_bReadyForDisplayChange = FALSE;
47             ReleaseSemaphore(g_hSemDisplayChange, 1, 0);
48         }
49         break;
50     default:
51         RECORD_MESSAGE(iwnd, message, SENT, 0,0);
52     }
53     return DefWindowProc(hWnd, message, wParam, lParam);
54 }
55 
56 static void FlushMessages()
57 {
58     MSG msg;
59 
60     while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE ))
61     {
62         int iwnd = get_iwnd(msg.hwnd);
63         if(!(msg.message > WM_USER || !iwnd || IsDWmMsg(msg.message) || IseKeyMsg(msg.message)))
64             RECORD_MESSAGE(iwnd, msg.message, POST,0,0);
65         DispatchMessageA( &msg );
66     }
67 }
68 
69 static MSG_ENTRY NcMetricsChange_chain[]={
70     {2,WM_WINDOWPOSCHANGING, SENT, 0, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOCOPYBITS|SWP_NOMOVE|SWP_NOZORDER|SWP_NOREDRAW},
71     {2,WM_GETMINMAXINFO},
72     {2,WM_NCCALCSIZE},
73     {2,WM_WINDOWPOSCHANGED, SENT, 0, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOCOPYBITS|SWP_NOMOVE|SWP_NOZORDER|SWP_NOREDRAW | SWP_NOCLIENTSIZE | SWP_NOCLIENTMOVE | SWP_NOSIZE},
74     {1,WM_WINDOWPOSCHANGING, SENT, 0, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOCOPYBITS|SWP_NOMOVE|SWP_NOZORDER|SWP_NOREDRAW},
75     {1,WM_GETMINMAXINFO},
76     {1,WM_NCCALCSIZE},
77     {1,WM_WINDOWPOSCHANGED, SENT, 0, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOCOPYBITS|SWP_NOMOVE|SWP_NOZORDER|SWP_NOREDRAW | SWP_NOCLIENTSIZE | SWP_NOCLIENTMOVE | SWP_NOSIZE},
78     {0,0}};
79 
80 static MSG_ENTRY NcMetricsChange1_chain[]={
81     {2,WM_WINDOWPOSCHANGING, SENT, 0, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOCOPYBITS|SWP_NOMOVE|SWP_NOZORDER|SWP_NOREDRAW},
82     {2,WM_GETMINMAXINFO},
83     {2,WM_NCCALCSIZE},
84     {2,WM_WINDOWPOSCHANGED, SENT, 0,  SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOCOPYBITS|SWP_NOMOVE|SWP_NOZORDER|SWP_NOREDRAW | SWP_NOCLIENTSIZE | SWP_NOCLIENTMOVE | SWP_NOSIZE},
85     {1,WM_WINDOWPOSCHANGING, SENT, 0, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOCOPYBITS|SWP_NOMOVE|SWP_NOZORDER|SWP_NOREDRAW},
86     {1,WM_GETMINMAXINFO},
87     {1,WM_NCCALCSIZE},
88     {1,WM_WINDOWPOSCHANGED, SENT, 0,  SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOCOPYBITS|SWP_NOMOVE|SWP_NOZORDER|SWP_NOREDRAW | SWP_NOCLIENTSIZE | SWP_NOCLIENTMOVE | SWP_NOSIZE},
89     {2,WM_SETTINGCHANGE},
90     {1,WM_SETTINGCHANGE},
91     {0,0}};
92 
93 static MSG_ENTRY CaptionHeight_chain[]={
94     {2,WM_WINDOWPOSCHANGING, SENT, 0, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOCOPYBITS|SWP_NOMOVE|SWP_NOZORDER|SWP_NOREDRAW},
95     {2,WM_GETMINMAXINFO},
96     {2,WM_NCCALCSIZE},
97     {2,WM_WINDOWPOSCHANGED, SENT, 0, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOCOPYBITS|SWP_NOMOVE|SWP_NOZORDER|SWP_NOREDRAW | SWP_NOCLIENTSIZE},
98     {2,WM_MOVE},
99     {1,WM_WINDOWPOSCHANGING, SENT, 0, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOCOPYBITS|SWP_NOMOVE|SWP_NOZORDER|SWP_NOREDRAW},
100     {1,WM_GETMINMAXINFO},
101     {1,WM_NCCALCSIZE},
102     {1,WM_WINDOWPOSCHANGED, SENT, 0,  SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOCOPYBITS|SWP_NOMOVE|SWP_NOZORDER|SWP_NOREDRAW | SWP_NOCLIENTSIZE},
103     {1,WM_MOVE},
104     {0,0}};
105 
106 static void Test_NonClientMetrics()
107 {
108     NONCLIENTMETRICS NonClientMetrics;
109 
110     /* WARNING: this test requires themes and dwm to be disabled */
111 
112     SetCursorPos(0,0);
113 
114     /* Retrieve th non client metrics */
115     NonClientMetrics.cbSize = sizeof(NONCLIENTMETRICS);
116     SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS), &NonClientMetrics, 0);
117     FlushMessages();
118     COMPARE_CACHE(empty_chain);
119 
120     /* Set the non client metric without making any change */
121     SystemParametersInfo(SPI_SETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS), &NonClientMetrics, 0);
122     FlushMessages();
123     COMPARE_CACHE(NcMetricsChange_chain);
124 
125     /* Set the same metrics again with the SPIF_SENDCHANGE param */
126     SystemParametersInfo(SPI_SETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS), &NonClientMetrics, SPIF_SENDCHANGE|SPIF_UPDATEINIFILE );
127     FlushMessages();
128     COMPARE_CACHE(NcMetricsChange1_chain);
129 
130     /* Slightly change the caption height */
131     NonClientMetrics.iCaptionHeight += 1;
132     SystemParametersInfo(SPI_SETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS), &NonClientMetrics, 0);
133     FlushMessages();
134     COMPARE_CACHE(CaptionHeight_chain);
135 
136     /* Restore the original caption height */
137     NonClientMetrics.iCaptionHeight -= 1;
138     SystemParametersInfo(SPI_SETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS), &NonClientMetrics, 0);
139     FlushMessages();
140     COMPARE_CACHE(CaptionHeight_chain);
141 }
142 
143 static void Test_MouseSpeed()
144 {
145     ULONG ulMouseSpeed, temp;
146     BOOL ret;
147 
148     ret = SystemParametersInfo(SPI_GETMOUSESPEED, 0, &ulMouseSpeed, 0);
149     ok(ret, "SystemParametersInfo failed\n");
150     ok(ulMouseSpeed >= 1 && ulMouseSpeed <=20, "Wrong mouse speed (%d)\n", (int)ulMouseSpeed);
151 
152     temp = 1;
153     ret = SystemParametersInfo(SPI_SETMOUSESPEED, 0, UlongToPtr(temp), SPIF_SENDCHANGE | SPIF_UPDATEINIFILE);
154     ok(ret, "SystemParametersInfo failed\n");
155     ret = SystemParametersInfo(SPI_GETMOUSESPEED, 0, &temp, 0);
156     ok(ret, "SystemParametersInfo failed\n");
157     ok(temp == 1, "SPI_GETMOUSESPEED did not get value set by SPI_SETMOUSESPEED (%d instead of 1)\n", (int)temp);
158 
159     temp = 20;
160     ret = SystemParametersInfo(SPI_SETMOUSESPEED, 0, UlongToPtr(temp), SPIF_SENDCHANGE | SPIF_UPDATEINIFILE);
161     ok(ret, "SystemParametersInfo failed\n");
162     ret = SystemParametersInfo(SPI_GETMOUSESPEED, 0, &temp, 0);
163     ok(ret, "SystemParametersInfo failed\n");
164     ok(temp == 20, "SPI_GETMOUSESPEED did not get value set by SPI_SETMOUSESPEED (%d instead of 20)\n", (int)temp);
165 
166     temp = 21;
167     ret = SystemParametersInfo(SPI_SETMOUSESPEED, 0, UlongToPtr(temp), SPIF_SENDCHANGE | SPIF_UPDATEINIFILE);
168     ok(!ret, "expected SystemParametersInfo to fail\n");
169     ret = SystemParametersInfo(SPI_GETMOUSESPEED, 0, &temp, 0);
170     ok(ret, "SystemParametersInfo failed\n");
171     ok(temp == 20, "SPI_GETMOUSESPEED got unexpected value (%d instead of 20)\n", (int)temp);
172 
173     temp = 0;
174     ret = SystemParametersInfo(SPI_SETMOUSESPEED, 0, UlongToPtr(temp), SPIF_SENDCHANGE | SPIF_UPDATEINIFILE);
175     ok(!ret, "expected SystemParametersInfo to fail\n");
176     ret = SystemParametersInfo(SPI_GETMOUSESPEED, 0, &temp, 0);
177     ok(ret, "SystemParametersInfo failed\n");
178     ok(temp == 20, "SPI_GETMOUSESPEED got unexpected value (%d instead of 20)\n", (int)temp);
179 
180     ret = SystemParametersInfo(SPI_SETMOUSESPEED, 0, UlongToPtr(ulMouseSpeed), SPIF_SENDCHANGE | SPIF_UPDATEINIFILE);
181     ok(ret, "SystemParametersInfo failed\n");
182 }
183 
184 static void Test_GradientCaptions(void)
185 {
186     BOOL ret;
187     LONG lResult;
188     DWORD dwResult;
189     BOOL bGradientCaptions, bModeFound;
190     DEVMODEW OldDevMode, NewDevMode;
191     INT iMode;
192 
193     ret = SystemParametersInfo(SPI_GETGRADIENTCAPTIONS, 0, &bGradientCaptions, 0);
194     ok(ret, "SystemParametersInfo failed\n");
195     if (bGradientCaptions == FALSE)
196     {
197         skip("GRADIENTCAPTIONS value has changed from its original state\n");
198         return;
199     }
200 
201     /* Try to find a graphics mode with 16 or 256 colors */
202     iMode = 0;
203     bModeFound = FALSE;
204     while (EnumDisplaySettingsW(NULL, iMode, &NewDevMode))
205     {
206         if ((NewDevMode.dmBitsPerPel == 4) ||
207             (NewDevMode.dmBitsPerPel == 8))
208         {
209             bModeFound = TRUE;
210             break;
211         }
212 
213         ++iMode;
214     }
215     if (!bModeFound)
216     {
217         skip("4bpp/8bpp graphics mode is not supported\n");
218         return;
219     }
220 
221     /* Save the current graphics mode */
222     ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &OldDevMode);
223     ok(ret, "EnumDisplaySettingsW failed\n");
224 
225     g_hSemDisplayChange = CreateSemaphoreW(NULL, 0, 1, NULL);
226 
227     /* Switch to the new graphics mode */
228     g_bReadyForDisplayChange = TRUE;
229     lResult = ChangeDisplaySettingsExW(NULL, &NewDevMode, NULL, 0, NULL);
230     if (lResult == DISP_CHANGE_SUCCESSFUL)
231     {
232         dwResult = WaitForSingleObject(g_hSemDisplayChange, 10000);
233         ok(dwResult == WAIT_OBJECT_0, "Waiting for the WM_DISPLAYCHANGE message timed out\n");
234     }
235     g_bReadyForDisplayChange = FALSE;
236     ok(lResult == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsExW returned %ld\n", lResult);
237 
238     /* SPI_GETGRADIENTCAPTIONS will now always return FALSE */
239     ret = SystemParametersInfo(SPI_GETGRADIENTCAPTIONS, 0, &bGradientCaptions, 0);
240     ok(ret, "SystemParametersInfo failed\n");
241     ok(bGradientCaptions == FALSE, "SPI_GETGRADIENTCAPTIONS got unexpected value (%d instead of 0)\n", bGradientCaptions);
242 
243     /* Enable gradient captions */
244     bGradientCaptions = TRUE;
245     SystemParametersInfo(SPI_SETGRADIENTCAPTIONS, 0, UlongToPtr(bGradientCaptions), 0);
246 
247     /* Still FALSE */
248     ret = SystemParametersInfo(SPI_GETGRADIENTCAPTIONS, 0, &bGradientCaptions, 0);
249     ok(ret, "SystemParametersInfo failed\n");
250     ok(bGradientCaptions == FALSE, "SPI_GETGRADIENTCAPTIONS got unexpected value (%d instead of 0)\n", bGradientCaptions);
251 
252     /* Restore the previous graphics mode */
253     g_bReadyForDisplayChange = TRUE;
254     lResult = ChangeDisplaySettingsExW(NULL, &OldDevMode, NULL, 0, NULL);
255     if (lResult == DISP_CHANGE_SUCCESSFUL)
256     {
257         dwResult = WaitForSingleObject(g_hSemDisplayChange, 10000);
258         ok(dwResult == WAIT_OBJECT_0, "Waiting for the WM_DISPLAYCHANGE message timed out\n");
259     }
260     g_bReadyForDisplayChange = FALSE;
261     ok(lResult == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsExW returned %ld\n", lResult);
262 
263     /* The original value should be restored */
264     ret = SystemParametersInfo(SPI_GETGRADIENTCAPTIONS, 0, &bGradientCaptions, 0);
265     ok(ret, "SystemParametersInfo failed\n");
266     ok(bGradientCaptions == TRUE, "SPI_GETGRADIENTCAPTIONS got unexpected value (%d instead of 1)\n", bGradientCaptions);
267 
268     CloseHandle(g_hSemDisplayChange);
269 }
270 
271 START_TEST(SystemParametersInfo)
272 {
273     RegisterSimpleClass(SysParamsTestProc, L"sysparamstest");
274     hWnd1 = CreateWindowW(L"sysparamstest", L"sysparamstest", WS_OVERLAPPEDWINDOW,
275                         20, 20, 300, 300, NULL, NULL, 0, NULL);
276 
277     hWnd2 = CreateWindowW(L"sysparamstest", L"sysparamstest", WS_OVERLAPPEDWINDOW,
278                          200, 200, 300, 300, NULL, NULL, 0, NULL);
279 
280     Test_NonClientMetrics();
281     Test_MouseSpeed();
282     Test_GradientCaptions();
283 
284     DestroyWindow(hWnd1);
285     DestroyWindow(hWnd2);
286     UnregisterClassW(L"sysparamstest", 0);
287 }
288