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 
15 /* [HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer] */
16 /* The contents of RegValue ShellState. */
17 typedef struct REGSHELLSTATE
18 {
19     DWORD dwSize;
20     SHELLSTATE ss;
21 } REGSHELLSTATE, *PREGSHELLSTATE;
22 
23 static void dump(const char *name, const void *ptr, size_t siz)
24 {
25     char buf[256], sz[16];
26 
27     StringCbCopyA(buf, sizeof(buf), name);
28     StringCbCatA(buf, sizeof(buf), ": ");
29 
30     const BYTE *pb = reinterpret_cast<const BYTE *>(ptr);
31     while (siz--)
32     {
33         StringCbPrintfA(sz, sizeof(sz), "%02X ", *pb++);
34         StringCbCatA(buf, sizeof(buf), sz);
35     }
36 
37     trace("%s\n", buf);
38 }
39 
40 static int read_key(REGSHELLSTATE *prss)
41 {
42     HKEY hKey;
43     LONG result;
44     DWORD cb;
45     static const LPCWSTR s_pszExplorer =
46         L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer";
47 
48     memset(prss, 0, sizeof(*prss));
49 
50     result = RegOpenKeyExW(HKEY_CURRENT_USER, s_pszExplorer, 0, KEY_READ, &hKey);
51     ok(result == ERROR_SUCCESS, "result was %ld\n", result);
52     ok(hKey != NULL, "hKey was NULL\n");
53 
54     if (result != ERROR_SUCCESS || !hKey)
55     {
56         skip("RegOpenKeyEx failed: %ld\n", result);
57         return 1;
58     }
59 
60     cb = sizeof(*prss);
61     result = RegQueryValueExW(hKey, L"ShellState", NULL, NULL, reinterpret_cast<LPBYTE>(prss), &cb);
62     RegCloseKey(hKey);
63 
64     ok(result == ERROR_SUCCESS, "result was %ld\n", result);
65     if (result != ERROR_SUCCESS)
66     {
67         skip("RegQueryValueEx failed: %ld\n", result);
68         return 2;
69     }
70 
71     return 0;
72 }
73 
74 static int dump_pss(SHELLSTATE *pss)
75 {
76     dump("SHELLSTATE", pss, sizeof(*pss));
77     return 0;
78 }
79 
80 START_TEST(ShellState)
81 {
82     OSVERSIONINFO osinfo;
83     REGSHELLSTATE rss;
84     SHELLSTATE *pss;
85     SHELLFLAGSTATE FlagState;
86     LPBYTE pb;
87     int ret;
88 
89     trace("GetVersion(): 0x%08lX", GetVersion());
90 
91     osinfo.dwOSVersionInfoSize = sizeof(osinfo);
92     GetVersionEx(&osinfo);
93     trace("osinfo.dwMajorVersion: 0x%08lX\n", osinfo.dwMajorVersion);
94     trace("osinfo.dwMinorVersion: 0x%08lX\n", osinfo.dwMinorVersion);
95     trace("osinfo.dwBuildNumber: 0x%08lX\n", osinfo.dwBuildNumber);
96     trace("osinfo.dwPlatformId: 0x%08lX\n", osinfo.dwPlatformId);
97 
98     trace("WINVER: 0x%04X\n", WINVER);
99     trace("_WIN32_WINNT: 0x%04X\n", _WIN32_WINNT);
100     trace("_WIN32_IE: 0x%04X\n", _WIN32_IE);
101     trace("NTDDI_VERSION: 0x%08X\n", NTDDI_VERSION);
102 
103 #ifdef _MSC_VER
104     trace("_MSC_VER: 0x%08X\n", int(_MSC_VER));
105 #elif defined(__MINGW32__)
106     trace("__MINGW32__: 0x%08X\n", int(__MINGW32__));
107 #elif defined(__clang__)
108     trace("__clang__: 0x%08X\n", int(__clang__));
109 #else
110     #error Unknown compiler.
111 #endif
112 
113     ok(sizeof(REGSHELLSTATE) >= 0x24, "sizeof(REGSHELLSTATE) was %d\n", (int)sizeof(REGSHELLSTATE));
114     trace("sizeof(SHELLSTATE): %d\n", (int)sizeof(SHELLSTATE));
115     trace("__alignof(SHELLSTATE): %d\n", (int)__alignof(SHELLSTATE));
116     trace("sizeof(SHELLFLAGSTATE): %d\n", (int)sizeof(SHELLFLAGSTATE));
117     trace("sizeof(CABINETSTATE): %d\n", (int)sizeof(CABINETSTATE));
118 
119     pss = &rss.ss;
120     pb = reinterpret_cast<LPBYTE>(pss);
121 
122     ret = read_key(&rss);
123     if (ret)
124     {
125         return;
126     }
127 
128     dump_pss(pss);
129     ok(rss.dwSize >= 0x24, "rss.dwSize was %ld (0x%lX).\n", rss.dwSize, rss.dwSize);
130 
131 #define DUMP_LONG(x) trace(#x ": 0x%08X\n", int(x));
132 #define DUMP_BOOL(x) trace(#x ": %d\n", !!int(x));
133     DUMP_BOOL(pss->fShowAllObjects);
134     DUMP_BOOL(pss->fShowExtensions);
135     DUMP_BOOL(pss->fNoConfirmRecycle);
136     DUMP_BOOL(pss->fShowSysFiles);
137     DUMP_BOOL(pss->fShowCompColor);
138     DUMP_BOOL(pss->fDoubleClickInWebView);
139     DUMP_BOOL(pss->fDesktopHTML);
140     DUMP_BOOL(pss->fWin95Classic);
141     DUMP_BOOL(pss->fDontPrettyPath);
142     DUMP_BOOL(pss->fShowAttribCol);
143     DUMP_BOOL(pss->fMapNetDrvBtn);
144     DUMP_BOOL(pss->fShowInfoTip);
145     DUMP_BOOL(pss->fHideIcons);
146     DUMP_BOOL(pss->fWebView);
147     DUMP_BOOL(pss->fFilter);
148     DUMP_BOOL(pss->fShowSuperHidden);
149     DUMP_BOOL(pss->fNoNetCrawling);
150     DUMP_LONG(pss->lParamSort);
151     DUMP_LONG(pss->iSortDirection);
152     DUMP_LONG(pss->version);
153     DUMP_LONG(pss->lParamSort);
154     DUMP_LONG(pss->iSortDirection);
155     DUMP_LONG(pss->version);
156     DUMP_BOOL(pss->fSepProcess);
157     DUMP_BOOL(pss->fStartPanelOn);
158     DUMP_BOOL(pss->fShowStartPage);
159 #if NTDDI_VERSION >= 0x06000000     // for future use
160     DUMP_BOOL(pss->fIconsOnly);
161     DUMP_BOOL(pss->fShowTypeOverlay);
162     DUMP_BOOL(pss->fShowStatusBar);
163 #endif
164 
165 #define SSF_MASK \
166     (SSF_SHOWALLOBJECTS | SSF_SHOWEXTENSIONS | SSF_NOCONFIRMRECYCLE | \
167      SSF_SHOWCOMPCOLOR | SSF_DOUBLECLICKINWEBVIEW | SSF_DESKTOPHTML | \
168      SSF_WIN95CLASSIC | SSF_DONTPRETTYPATH | SSF_SHOWATTRIBCOL | \
169      SSF_MAPNETDRVBUTTON | SSF_SHOWINFOTIP | SSF_HIDEICONS)
170     // For future:
171     // SSF_AUTOCHECKSELECT, SSF_ICONSONLY, SSF_SHOWTYPEOVERLAY, SSF_SHOWSTATUSBAR
172 
173     memset(&FlagState, 0, sizeof(FlagState));
174     SHGetSettings(&FlagState, SSF_MASK);
175 
176 #define CHECK_FLAG(x) ok(pss->x == FlagState.x, "FlagState.%s expected %d, was %d\n", #x, (int)pss->x, (int)FlagState.x)
177     CHECK_FLAG(fShowAllObjects);
178     CHECK_FLAG(fShowExtensions);
179     CHECK_FLAG(fNoConfirmRecycle);
180     //CHECK_FLAG(fShowSysFiles);    // No use
181     CHECK_FLAG(fShowCompColor);
182     CHECK_FLAG(fDoubleClickInWebView);
183     CHECK_FLAG(fDesktopHTML);
184     CHECK_FLAG(fWin95Classic);
185     CHECK_FLAG(fDontPrettyPath);
186     CHECK_FLAG(fShowAttribCol);
187     CHECK_FLAG(fMapNetDrvBtn);
188     CHECK_FLAG(fShowInfoTip);
189     CHECK_FLAG(fHideIcons);
190 #if NTDDI_VERSION >= 0x06000000     // for future use
191     CHECK_FLAG(fAutoCheckSelect);
192     CHECK_FLAG(fIconsOnly);
193 #endif
194 
195 #if 1
196     #define DO_IT(x) x
197 #else
198     #define DO_IT(x) do { trace(#x ";\n"); x; } while (0)
199 #endif
200 
201     DO_IT(memset(pss, 0, sizeof(*pss)));
202     DO_IT(pss->dwWin95Unused = 1);
203     ok(pb[4] == 0x01 || dump_pss(pss), "Unexpected pss ^\n");
204 
205     DO_IT(memset(pss, 0, sizeof(*pss)));
206     DO_IT(pss->lParamSort = 1);
207     ok(pb[12] == 0x01 || dump_pss(pss), "Unexpected pss ^\n");
208 
209     DO_IT(memset(pss, 0, sizeof(*pss)));
210     DO_IT(pss->iSortDirection = 0xDEADBEEF);
211     ok(*(UNALIGNED DWORD *)(pb + 16) == 0xDEADBEEF || dump_pss(pss), "Unexpected pss ^\n");
212 
213     DO_IT(memset(pss, 0, sizeof(*pss)));
214     DO_IT(pss->version = 0xDEADBEEF);
215     ok(*(UNALIGNED DWORD *)(pb + 20) == 0xDEADBEEF || dump_pss(pss), "Unexpected pss ^\n");
216 
217     DO_IT(memset(pss, 0, sizeof(*pss)));
218     DO_IT(pss->fSepProcess = TRUE);
219     ok(pb[28] == 0x01 || dump_pss(pss), "Unexpected pss ^\n");
220 }
221