reactos/modules/rostests/apitests/shell32/ShellState.cpp
Carl J. Bialorucki b86422cd4b
[SHELL32_APITEST] Several fixes (#8266)
Fix the shell32 apitests so that they pass on Windows Server 2003 - Windows 10. Many of these fixes are for Vista+, but the most important fixes are for ShellExecCmdLine and FindExecutable which had issues closing windows after tests and deleting test files. Failing to delete these files breaks the other test (i.e. running ShellExecCmdLine would break FindExecutable and vis-versa.)
2025-07-29 14:06:13 -06:00

323 lines
9.7 KiB
C++

/*
* PROJECT: ReactOS API tests
* LICENSE: LGPLv2.1+ - See COPYING.LIB in the top level directory
* PURPOSE: Test for SHELLSTATE
* PROGRAMMERS: Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com>
*/
#include "shelltest.h"
#define NDEBUG
#include <debug.h>
#include <stdio.h>
#include <shellutils.h>
#include <strsafe.h>
#include <shlwapi.h>
#include <shlwapi_undoc.h>
/* [HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer] */
/* The contents of RegValue ShellState. */
typedef struct REGSHELLSTATE
{
DWORD dwSize;
SHELLSTATE ss;
} REGSHELLSTATE, *PREGSHELLSTATE;
static void dump(const char *name, const void *ptr, size_t siz)
{
char buf[256], sz[16];
StringCbCopyA(buf, sizeof(buf), name);
StringCbCatA(buf, sizeof(buf), ": ");
const BYTE *pb = reinterpret_cast<const BYTE *>(ptr);
while (siz--)
{
StringCbPrintfA(sz, sizeof(sz), "%02X ", *pb++);
StringCbCatA(buf, sizeof(buf), sz);
}
trace("%s\n", buf);
}
static int read_key(REGSHELLSTATE *prss)
{
HKEY hKey;
LONG result;
DWORD cb;
static const LPCWSTR s_pszExplorer =
L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer";
memset(prss, 0, sizeof(*prss));
result = RegOpenKeyExW(HKEY_CURRENT_USER, s_pszExplorer, 0, KEY_READ, &hKey);
ok(result == ERROR_SUCCESS, "result was %ld\n", result);
ok(hKey != NULL, "hKey was NULL\n");
if (result != ERROR_SUCCESS || !hKey)
{
skip("RegOpenKeyEx failed: %ld\n", result);
return 1;
}
cb = sizeof(*prss);
result = RegQueryValueExW(hKey, L"ShellState", NULL, NULL, reinterpret_cast<LPBYTE>(prss), &cb);
RegCloseKey(hKey);
ok(result == ERROR_SUCCESS, "result was %ld\n", result);
if (result != ERROR_SUCCESS)
{
skip("RegQueryValueEx failed: %ld\n", result);
return 2;
}
return 0;
}
static int read_advanced_key(SHELLSTATE* pss)
{
HKEY hKey;
DWORD dwValue, dwSize;
hKey = SHGetShellKey(1, L"Advanced", FALSE);
if (hKey == NULL)
{
return 0;
}
dwSize = sizeof(dwValue);
if (SHQueryValueExW(hKey, L"Hidden", NULL, NULL, &dwValue, &dwSize) == ERROR_SUCCESS)
{
pss->fShowAllObjects = (dwValue == 1);
pss->fShowSysFiles = (dwValue == 2);
}
dwSize = sizeof(dwValue);
if (SHQueryValueExW(hKey, L"HideFileExt", NULL, NULL, &dwValue, &dwSize) == ERROR_SUCCESS)
{
pss->fShowExtensions = (dwValue == 0);
}
dwSize = sizeof(dwValue);
if (SHQueryValueExW(hKey, L"DontPrettyPath", NULL, NULL, &dwValue, &dwSize) == ERROR_SUCCESS)
{
pss->fDontPrettyPath = (dwValue != 0);
}
dwSize = sizeof(dwValue);
if (SHQueryValueExW(hKey, L"MapNetDrvBtn", NULL, NULL, &dwValue, &dwSize) == ERROR_SUCCESS)
{
pss->fMapNetDrvBtn = (dwValue != 0);
}
dwSize = sizeof(dwValue);
if (SHQueryValueExW(hKey, L"ShowInfoTip", NULL, NULL, &dwValue, &dwSize) == ERROR_SUCCESS)
{
pss->fShowInfoTip = (dwValue != 0);
}
dwSize = sizeof(dwValue);
if (SHQueryValueExW(hKey, L"HideIcons", NULL, NULL, &dwValue, &dwSize) == ERROR_SUCCESS)
{
pss->fHideIcons = (dwValue != 0);
}
dwSize = sizeof(dwValue);
if (SHQueryValueExW(hKey, L"WebView", NULL, NULL, &dwValue, &dwSize) == ERROR_SUCCESS)
{
pss->fWebView = (dwValue != 0);
}
dwSize = sizeof(dwValue);
if (SHQueryValueExW(hKey, L"Filter", NULL, NULL, &dwValue, &dwSize) == ERROR_SUCCESS)
{
pss->fFilter = (dwValue != 0);
}
dwSize = sizeof(dwValue);
if (SHQueryValueExW(hKey, L"ShowSuperHidden", NULL, NULL, &dwValue, &dwSize) == ERROR_SUCCESS)
{
pss->fShowSuperHidden = (dwValue != 0);
}
dwSize = sizeof(dwValue);
if (SHQueryValueExW(hKey, L"NoNetCrawling", NULL, NULL, &dwValue, &dwSize) == ERROR_SUCCESS)
{
pss->fNoNetCrawling = (dwValue != 0);
}
RegCloseKey(hKey);
return 0;
}
static int dump_pss(SHELLSTATE *pss)
{
dump("SHELLSTATE", pss, sizeof(*pss));
return 0;
}
START_TEST(ShellState)
{
OSVERSIONINFO osinfo;
REGSHELLSTATE rss;
SHELLSTATE ss, *pss;
SHELLFLAGSTATE FlagState;
LPBYTE pb;
int ret;
trace("GetVersion(): 0x%08lX\n", GetVersion());
osinfo.dwOSVersionInfoSize = sizeof(osinfo);
GetVersionEx(&osinfo);
trace("osinfo.dwMajorVersion: 0x%08lX\n", osinfo.dwMajorVersion);
trace("osinfo.dwMinorVersion: 0x%08lX\n", osinfo.dwMinorVersion);
trace("osinfo.dwBuildNumber: 0x%08lX\n", osinfo.dwBuildNumber);
trace("osinfo.dwPlatformId: 0x%08lX\n", osinfo.dwPlatformId);
trace("WINVER: 0x%04X\n", WINVER);
trace("_WIN32_WINNT: 0x%04X\n", _WIN32_WINNT);
trace("_WIN32_IE: 0x%04X\n", _WIN32_IE);
trace("NTDDI_VERSION: 0x%08X\n", NTDDI_VERSION);
#ifdef _MSC_VER
trace("_MSC_VER: 0x%08X\n", int(_MSC_VER));
#elif defined(__MINGW32__)
trace("__MINGW32__: 0x%08X\n", int(__MINGW32__));
#elif defined(__clang__)
trace("__clang__: 0x%08X\n", int(__clang__));
#else
#error Unknown compiler.
#endif
ok(sizeof(REGSHELLSTATE) >= 0x24, "sizeof(REGSHELLSTATE) was %d\n", (int)sizeof(REGSHELLSTATE));
trace("sizeof(SHELLSTATE): %d\n", (int)sizeof(SHELLSTATE));
trace("__alignof(SHELLSTATE): %d\n", (int)__alignof(SHELLSTATE));
trace("sizeof(SHELLFLAGSTATE): %d\n", (int)sizeof(SHELLFLAGSTATE));
trace("sizeof(CABINETSTATE): %d\n", (int)sizeof(CABINETSTATE));
pss = &rss.ss;
pb = reinterpret_cast<LPBYTE>(pss);
ret = read_key(&rss);
if (ret)
{
return;
}
dump_pss(pss);
ok(rss.dwSize >= 0x24, "rss.dwSize was %ld (0x%lX).\n", rss.dwSize, rss.dwSize);
read_advanced_key(&rss.ss);
#define DUMP_LONG(x) trace(#x ": 0x%08X\n", int(x));
#define DUMP_BOOL(x) trace(#x ": %d\n", !!int(x));
DUMP_BOOL(pss->fShowAllObjects);
DUMP_BOOL(pss->fShowExtensions);
DUMP_BOOL(pss->fNoConfirmRecycle);
DUMP_BOOL(pss->fShowSysFiles);
DUMP_BOOL(pss->fShowCompColor);
DUMP_BOOL(pss->fDoubleClickInWebView);
DUMP_BOOL(pss->fDesktopHTML);
DUMP_BOOL(pss->fWin95Classic);
DUMP_BOOL(pss->fDontPrettyPath);
DUMP_BOOL(pss->fShowAttribCol);
DUMP_BOOL(pss->fMapNetDrvBtn);
DUMP_BOOL(pss->fShowInfoTip);
DUMP_BOOL(pss->fHideIcons);
DUMP_BOOL(pss->fWebView);
DUMP_BOOL(pss->fFilter);
DUMP_BOOL(pss->fShowSuperHidden);
DUMP_BOOL(pss->fNoNetCrawling);
DUMP_LONG(pss->lParamSort);
DUMP_LONG(pss->iSortDirection);
DUMP_LONG(pss->version);
DUMP_LONG(pss->lParamSort);
DUMP_LONG(pss->iSortDirection);
DUMP_LONG(pss->version);
DUMP_BOOL(pss->fSepProcess);
DUMP_BOOL(pss->fStartPanelOn);
DUMP_BOOL(pss->fShowStartPage);
#if NTDDI_VERSION >= 0x06000000 // for future use
DUMP_BOOL(pss->fIconsOnly);
DUMP_BOOL(pss->fShowTypeOverlay);
DUMP_BOOL(pss->fShowStatusBar);
#endif
#define SSF_MASK \
(SSF_SHOWALLOBJECTS | SSF_SHOWEXTENSIONS | SSF_NOCONFIRMRECYCLE | \
SSF_SHOWCOMPCOLOR | SSF_DOUBLECLICKINWEBVIEW | SSF_DESKTOPHTML | \
SSF_WIN95CLASSIC | SSF_DONTPRETTYPATH | SSF_SHOWATTRIBCOL | \
SSF_MAPNETDRVBUTTON | SSF_SHOWINFOTIP | SSF_HIDEICONS)
// For future:
// SSF_AUTOCHECKSELECT, SSF_ICONSONLY, SSF_SHOWTYPEOVERLAY, SSF_SHOWSTATUSBAR
/* Get the settings */
memset(&ss, 0, sizeof(ss));
SHGetSetSettings(&ss, SSF_MASK, FALSE);
#define CHECK_REG_FLAG(x) ok(pss->x == ss.x, "ss.%s expected %d, was %d\n", #x, (int)pss->x, (int)ss.x)
CHECK_REG_FLAG(fShowAllObjects);
CHECK_REG_FLAG(fShowExtensions);
CHECK_REG_FLAG(fNoConfirmRecycle);
if (GetNTVersion() != _WIN32_WINNT_VISTA)
CHECK_REG_FLAG(fShowSysFiles); // No use, test is broken on Vista
CHECK_REG_FLAG(fShowCompColor);
CHECK_REG_FLAG(fDoubleClickInWebView);
CHECK_REG_FLAG(fDesktopHTML);
CHECK_REG_FLAG(fWin95Classic);
CHECK_REG_FLAG(fDontPrettyPath);
CHECK_REG_FLAG(fShowAttribCol);
CHECK_REG_FLAG(fMapNetDrvBtn);
CHECK_REG_FLAG(fShowInfoTip);
CHECK_REG_FLAG(fHideIcons);
#if NTDDI_VERSION >= 0x06000000 // for future use
CHECK_REG_FLAG(fAutoCheckSelect);
CHECK_REG_FLAG(fIconsOnly);
#endif
/* Get the flag settings */
memset(&FlagState, 0, sizeof(FlagState));
SHGetSettings(&FlagState, SSF_MASK);
#define CHECK_FLAG(x) ok(ss.x == FlagState.x, "FlagState.%s expected %d, was %d\n", #x, (int)ss.x, (int)FlagState.x)
CHECK_FLAG(fShowAllObjects);
CHECK_FLAG(fShowExtensions);
CHECK_FLAG(fNoConfirmRecycle);
CHECK_FLAG(fShowSysFiles); // No use
CHECK_FLAG(fShowCompColor);
CHECK_FLAG(fDoubleClickInWebView);
CHECK_FLAG(fDesktopHTML);
CHECK_FLAG(fWin95Classic);
CHECK_FLAG(fDontPrettyPath);
CHECK_FLAG(fShowAttribCol);
CHECK_FLAG(fMapNetDrvBtn);
CHECK_FLAG(fShowInfoTip);
CHECK_FLAG(fHideIcons);
#if NTDDI_VERSION >= 0x06000000 // for future use
CHECK_FLAG(fAutoCheckSelect);
CHECK_FLAG(fIconsOnly);
#endif
#if 1
#define DO_IT(x) x
#else
#define DO_IT(x) do { trace(#x ";\n"); x; } while (0)
#endif
DO_IT(memset(pss, 0, sizeof(*pss)));
DO_IT(pss->dwWin95Unused = 1);
ok(pb[4] == 0x01 || dump_pss(pss), "Unexpected pss ^\n");
DO_IT(memset(pss, 0, sizeof(*pss)));
DO_IT(pss->lParamSort = 1);
ok(pb[12] == 0x01 || dump_pss(pss), "Unexpected pss ^\n");
DO_IT(memset(pss, 0, sizeof(*pss)));
DO_IT(pss->iSortDirection = 0xDEADBEEF);
ok(*(UNALIGNED DWORD *)(pb + 16) == 0xDEADBEEF || dump_pss(pss), "Unexpected pss ^\n");
DO_IT(memset(pss, 0, sizeof(*pss)));
DO_IT(pss->version = 0xDEADBEEF);
ok(*(UNALIGNED DWORD *)(pb + 20) == 0xDEADBEEF || dump_pss(pss), "Unexpected pss ^\n");
DO_IT(memset(pss, 0, sizeof(*pss)));
DO_IT(pss->fSepProcess = TRUE);
ok(pb[28] == 0x01 || dump_pss(pss), "Unexpected pss ^\n");
}