1 /*
2 * PROJECT: ReactOS API tests
3 * LICENSE: LGPLv2.1+ - See COPYING.LIB in the top level directory
4 * PURPOSE: Test for SHELLSTATE
5 * PROGRAMMERS: Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com>
6 */
7 #include "shelltest.h"
8
9 #define NDEBUG
10 #include <debug.h>
11 #include <stdio.h>
12 #include <shellutils.h>
13 #include <strsafe.h>
14 #include <shlwapi.h>
15 #include <shlwapi_undoc.h>
16
17 /* [HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer] */
18 /* The contents of RegValue ShellState. */
19 typedef struct REGSHELLSTATE
20 {
21 DWORD dwSize;
22 SHELLSTATE ss;
23 } REGSHELLSTATE, *PREGSHELLSTATE;
24
dump(const char * name,const void * ptr,size_t siz)25 static void dump(const char *name, const void *ptr, size_t siz)
26 {
27 char buf[256], sz[16];
28
29 StringCbCopyA(buf, sizeof(buf), name);
30 StringCbCatA(buf, sizeof(buf), ": ");
31
32 const BYTE *pb = reinterpret_cast<const BYTE *>(ptr);
33 while (siz--)
34 {
35 StringCbPrintfA(sz, sizeof(sz), "%02X ", *pb++);
36 StringCbCatA(buf, sizeof(buf), sz);
37 }
38
39 trace("%s\n", buf);
40 }
41
read_key(REGSHELLSTATE * prss)42 static int read_key(REGSHELLSTATE *prss)
43 {
44 HKEY hKey;
45 LONG result;
46 DWORD cb;
47 static const LPCWSTR s_pszExplorer =
48 L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer";
49
50 memset(prss, 0, sizeof(*prss));
51
52 result = RegOpenKeyExW(HKEY_CURRENT_USER, s_pszExplorer, 0, KEY_READ, &hKey);
53 ok(result == ERROR_SUCCESS, "result was %ld\n", result);
54 ok(hKey != NULL, "hKey was NULL\n");
55
56 if (result != ERROR_SUCCESS || !hKey)
57 {
58 skip("RegOpenKeyEx failed: %ld\n", result);
59 return 1;
60 }
61
62 cb = sizeof(*prss);
63 result = RegQueryValueExW(hKey, L"ShellState", NULL, NULL, reinterpret_cast<LPBYTE>(prss), &cb);
64 RegCloseKey(hKey);
65
66 ok(result == ERROR_SUCCESS, "result was %ld\n", result);
67 if (result != ERROR_SUCCESS)
68 {
69 skip("RegQueryValueEx failed: %ld\n", result);
70 return 2;
71 }
72
73 return 0;
74 }
75
read_advanced_key(SHELLSTATE * pss)76 static int read_advanced_key(SHELLSTATE* pss)
77 {
78 HKEY hKey;
79 DWORD dwValue, dwSize;
80
81 hKey = SHGetShellKey(1, L"Advanced", FALSE);
82 if (hKey == NULL)
83 {
84 return 0;
85 }
86
87 dwSize = sizeof(dwValue);
88 if (SHQueryValueExW(hKey, L"Hidden", NULL, NULL, &dwValue, &dwSize) == ERROR_SUCCESS)
89 {
90 pss->fShowAllObjects = (dwValue == 1);
91 pss->fShowSysFiles = (dwValue == 2);
92 }
93
94 dwSize = sizeof(dwValue);
95 if (SHQueryValueExW(hKey, L"HideFileExt", NULL, NULL, &dwValue, &dwSize) == ERROR_SUCCESS)
96 {
97 pss->fShowExtensions = (dwValue == 0);
98 }
99
100 dwSize = sizeof(dwValue);
101 if (SHQueryValueExW(hKey, L"DontPrettyPath", NULL, NULL, &dwValue, &dwSize) == ERROR_SUCCESS)
102 {
103 pss->fDontPrettyPath = (dwValue != 0);
104 }
105
106 dwSize = sizeof(dwValue);
107 if (SHQueryValueExW(hKey, L"MapNetDrvBtn", NULL, NULL, &dwValue, &dwSize) == ERROR_SUCCESS)
108 {
109 pss->fMapNetDrvBtn = (dwValue != 0);
110 }
111
112 dwSize = sizeof(dwValue);
113 if (SHQueryValueExW(hKey, L"ShowInfoTip", NULL, NULL, &dwValue, &dwSize) == ERROR_SUCCESS)
114 {
115 pss->fShowInfoTip = (dwValue != 0);
116 }
117
118 dwSize = sizeof(dwValue);
119 if (SHQueryValueExW(hKey, L"HideIcons", NULL, NULL, &dwValue, &dwSize) == ERROR_SUCCESS)
120 {
121 pss->fHideIcons = (dwValue != 0);
122 }
123
124 dwSize = sizeof(dwValue);
125 if (SHQueryValueExW(hKey, L"WebView", NULL, NULL, &dwValue, &dwSize) == ERROR_SUCCESS)
126 {
127 pss->fWebView = (dwValue != 0);
128 }
129
130 dwSize = sizeof(dwValue);
131 if (SHQueryValueExW(hKey, L"Filter", NULL, NULL, &dwValue, &dwSize) == ERROR_SUCCESS)
132 {
133 pss->fFilter = (dwValue != 0);
134 }
135
136 dwSize = sizeof(dwValue);
137 if (SHQueryValueExW(hKey, L"ShowSuperHidden", NULL, NULL, &dwValue, &dwSize) == ERROR_SUCCESS)
138 {
139 pss->fShowSuperHidden = (dwValue != 0);
140 }
141
142 dwSize = sizeof(dwValue);
143 if (SHQueryValueExW(hKey, L"NoNetCrawling", NULL, NULL, &dwValue, &dwSize) == ERROR_SUCCESS)
144 {
145 pss->fNoNetCrawling = (dwValue != 0);
146 }
147
148 RegCloseKey(hKey);
149 return 0;
150 }
151
dump_pss(SHELLSTATE * pss)152 static int dump_pss(SHELLSTATE *pss)
153 {
154 dump("SHELLSTATE", pss, sizeof(*pss));
155 return 0;
156 }
157
START_TEST(ShellState)158 START_TEST(ShellState)
159 {
160 OSVERSIONINFO osinfo;
161 REGSHELLSTATE rss;
162 SHELLSTATE ss, *pss;
163 SHELLFLAGSTATE FlagState;
164 LPBYTE pb;
165 int ret;
166
167 trace("GetVersion(): 0x%08lX\n", GetVersion());
168
169 osinfo.dwOSVersionInfoSize = sizeof(osinfo);
170 GetVersionEx(&osinfo);
171 trace("osinfo.dwMajorVersion: 0x%08lX\n", osinfo.dwMajorVersion);
172 trace("osinfo.dwMinorVersion: 0x%08lX\n", osinfo.dwMinorVersion);
173 trace("osinfo.dwBuildNumber: 0x%08lX\n", osinfo.dwBuildNumber);
174 trace("osinfo.dwPlatformId: 0x%08lX\n", osinfo.dwPlatformId);
175
176 trace("WINVER: 0x%04X\n", WINVER);
177 trace("_WIN32_WINNT: 0x%04X\n", _WIN32_WINNT);
178 trace("_WIN32_IE: 0x%04X\n", _WIN32_IE);
179 trace("NTDDI_VERSION: 0x%08X\n", NTDDI_VERSION);
180
181 #ifdef _MSC_VER
182 trace("_MSC_VER: 0x%08X\n", int(_MSC_VER));
183 #elif defined(__MINGW32__)
184 trace("__MINGW32__: 0x%08X\n", int(__MINGW32__));
185 #elif defined(__clang__)
186 trace("__clang__: 0x%08X\n", int(__clang__));
187 #else
188 #error Unknown compiler.
189 #endif
190
191 ok(sizeof(REGSHELLSTATE) >= 0x24, "sizeof(REGSHELLSTATE) was %d\n", (int)sizeof(REGSHELLSTATE));
192 trace("sizeof(SHELLSTATE): %d\n", (int)sizeof(SHELLSTATE));
193 trace("__alignof(SHELLSTATE): %d\n", (int)__alignof(SHELLSTATE));
194 trace("sizeof(SHELLFLAGSTATE): %d\n", (int)sizeof(SHELLFLAGSTATE));
195 trace("sizeof(CABINETSTATE): %d\n", (int)sizeof(CABINETSTATE));
196
197 pss = &rss.ss;
198 pb = reinterpret_cast<LPBYTE>(pss);
199
200 ret = read_key(&rss);
201 if (ret)
202 {
203 return;
204 }
205
206 dump_pss(pss);
207 ok(rss.dwSize >= 0x24, "rss.dwSize was %ld (0x%lX).\n", rss.dwSize, rss.dwSize);
208
209 read_advanced_key(&rss.ss);
210
211 #define DUMP_LONG(x) trace(#x ": 0x%08X\n", int(x));
212 #define DUMP_BOOL(x) trace(#x ": %d\n", !!int(x));
213 DUMP_BOOL(pss->fShowAllObjects);
214 DUMP_BOOL(pss->fShowExtensions);
215 DUMP_BOOL(pss->fNoConfirmRecycle);
216 DUMP_BOOL(pss->fShowSysFiles);
217 DUMP_BOOL(pss->fShowCompColor);
218 DUMP_BOOL(pss->fDoubleClickInWebView);
219 DUMP_BOOL(pss->fDesktopHTML);
220 DUMP_BOOL(pss->fWin95Classic);
221 DUMP_BOOL(pss->fDontPrettyPath);
222 DUMP_BOOL(pss->fShowAttribCol);
223 DUMP_BOOL(pss->fMapNetDrvBtn);
224 DUMP_BOOL(pss->fShowInfoTip);
225 DUMP_BOOL(pss->fHideIcons);
226 DUMP_BOOL(pss->fWebView);
227 DUMP_BOOL(pss->fFilter);
228 DUMP_BOOL(pss->fShowSuperHidden);
229 DUMP_BOOL(pss->fNoNetCrawling);
230 DUMP_LONG(pss->lParamSort);
231 DUMP_LONG(pss->iSortDirection);
232 DUMP_LONG(pss->version);
233 DUMP_LONG(pss->lParamSort);
234 DUMP_LONG(pss->iSortDirection);
235 DUMP_LONG(pss->version);
236 DUMP_BOOL(pss->fSepProcess);
237 DUMP_BOOL(pss->fStartPanelOn);
238 DUMP_BOOL(pss->fShowStartPage);
239 #if NTDDI_VERSION >= 0x06000000 // for future use
240 DUMP_BOOL(pss->fIconsOnly);
241 DUMP_BOOL(pss->fShowTypeOverlay);
242 DUMP_BOOL(pss->fShowStatusBar);
243 #endif
244
245 #define SSF_MASK \
246 (SSF_SHOWALLOBJECTS | SSF_SHOWEXTENSIONS | SSF_NOCONFIRMRECYCLE | \
247 SSF_SHOWCOMPCOLOR | SSF_DOUBLECLICKINWEBVIEW | SSF_DESKTOPHTML | \
248 SSF_WIN95CLASSIC | SSF_DONTPRETTYPATH | SSF_SHOWATTRIBCOL | \
249 SSF_MAPNETDRVBUTTON | SSF_SHOWINFOTIP | SSF_HIDEICONS)
250 // For future:
251 // SSF_AUTOCHECKSELECT, SSF_ICONSONLY, SSF_SHOWTYPEOVERLAY, SSF_SHOWSTATUSBAR
252
253 /* Get the settings */
254 memset(&ss, 0, sizeof(ss));
255 SHGetSetSettings(&ss, SSF_MASK, FALSE);
256 #define CHECK_REG_FLAG(x) ok(pss->x == ss.x, "ss.%s expected %d, was %d\n", #x, (int)pss->x, (int)ss.x)
257 CHECK_REG_FLAG(fShowAllObjects);
258 CHECK_REG_FLAG(fShowExtensions);
259 CHECK_REG_FLAG(fNoConfirmRecycle);
260 CHECK_REG_FLAG(fShowSysFiles); // No use
261 CHECK_REG_FLAG(fShowCompColor);
262 CHECK_REG_FLAG(fDoubleClickInWebView);
263 CHECK_REG_FLAG(fDesktopHTML);
264 CHECK_REG_FLAG(fWin95Classic);
265 CHECK_REG_FLAG(fDontPrettyPath);
266 CHECK_REG_FLAG(fShowAttribCol);
267 CHECK_REG_FLAG(fMapNetDrvBtn);
268 CHECK_REG_FLAG(fShowInfoTip);
269 CHECK_REG_FLAG(fHideIcons);
270 #if NTDDI_VERSION >= 0x06000000 // for future use
271 CHECK_REG_FLAG(fAutoCheckSelect);
272 CHECK_REG_FLAG(fIconsOnly);
273 #endif
274
275 /* Get the flag settings */
276 memset(&FlagState, 0, sizeof(FlagState));
277 SHGetSettings(&FlagState, SSF_MASK);
278 #define CHECK_FLAG(x) ok(ss.x == FlagState.x, "FlagState.%s expected %d, was %d\n", #x, (int)ss.x, (int)FlagState.x)
279 CHECK_FLAG(fShowAllObjects);
280 CHECK_FLAG(fShowExtensions);
281 CHECK_FLAG(fNoConfirmRecycle);
282 CHECK_FLAG(fShowSysFiles); // No use
283 CHECK_FLAG(fShowCompColor);
284 CHECK_FLAG(fDoubleClickInWebView);
285 CHECK_FLAG(fDesktopHTML);
286 CHECK_FLAG(fWin95Classic);
287 CHECK_FLAG(fDontPrettyPath);
288 CHECK_FLAG(fShowAttribCol);
289 CHECK_FLAG(fMapNetDrvBtn);
290 CHECK_FLAG(fShowInfoTip);
291 CHECK_FLAG(fHideIcons);
292 #if NTDDI_VERSION >= 0x06000000 // for future use
293 CHECK_FLAG(fAutoCheckSelect);
294 CHECK_FLAG(fIconsOnly);
295 #endif
296
297 #if 1
298 #define DO_IT(x) x
299 #else
300 #define DO_IT(x) do { trace(#x ";\n"); x; } while (0)
301 #endif
302
303 DO_IT(memset(pss, 0, sizeof(*pss)));
304 DO_IT(pss->dwWin95Unused = 1);
305 ok(pb[4] == 0x01 || dump_pss(pss), "Unexpected pss ^\n");
306
307 DO_IT(memset(pss, 0, sizeof(*pss)));
308 DO_IT(pss->lParamSort = 1);
309 ok(pb[12] == 0x01 || dump_pss(pss), "Unexpected pss ^\n");
310
311 DO_IT(memset(pss, 0, sizeof(*pss)));
312 DO_IT(pss->iSortDirection = 0xDEADBEEF);
313 ok(*(UNALIGNED DWORD *)(pb + 16) == 0xDEADBEEF || dump_pss(pss), "Unexpected pss ^\n");
314
315 DO_IT(memset(pss, 0, sizeof(*pss)));
316 DO_IT(pss->version = 0xDEADBEEF);
317 ok(*(UNALIGNED DWORD *)(pb + 20) == 0xDEADBEEF || dump_pss(pss), "Unexpected pss ^\n");
318
319 DO_IT(memset(pss, 0, sizeof(*pss)));
320 DO_IT(pss->fSepProcess = TRUE);
321 ok(pb[28] == 0x01 || dump_pss(pss), "Unexpected pss ^\n");
322 }
323