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