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