mirror of
https://github.com/ApfelTeeSaft/reactos.git
synced 2026-08-27 03:43:36 +00:00
235 lines
6.9 KiB
C++
235 lines
6.9 KiB
C++
/*
|
|
* PROJECT: ReactOS API tests
|
|
* LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
|
|
* PURPOSE: Tests for CShellDispatch
|
|
* COPYRIGHT: Copyright 2026 Whindmar Saksit <[email protected]>
|
|
*/
|
|
|
|
#include "shelltest.h"
|
|
#include <oleauto.h>
|
|
#include <shellutils.h>
|
|
|
|
static int GetFileSize(PCWSTR Path)
|
|
{
|
|
WIN32_FIND_DATA wfd;
|
|
HANDLE hFind = FindFirstFileW(Path, &wfd);
|
|
if (hFind == INVALID_HANDLE_VALUE)
|
|
return -1;
|
|
FindClose(hFind);
|
|
return wfd.nFileSizeLow;
|
|
}
|
|
|
|
static void VariantClearAndInvalidate(VARIANT *pV)
|
|
{
|
|
if (!pV)
|
|
return;
|
|
VariantClear(pV);
|
|
V_BSTR(pV) = (BSTR)(SIZE_T)0xBAADF00Dul;
|
|
}
|
|
|
|
template<class T> static void SafeRelease(T &p)
|
|
{
|
|
if (!p)
|
|
return;
|
|
p->Release();
|
|
p = NULL;
|
|
}
|
|
|
|
template<class T> static HRESULT CreateFolderFromNameSpace(T Dir, Folder **ppsdf)
|
|
{
|
|
*ppsdf = NULL;
|
|
CComPtr<IShellDispatch> pSD;
|
|
HRESULT hr = CoCreateInstance(CLSID_Shell, NULL, CLSCTX_ALL, IID_PPV_ARG(IShellDispatch, &pSD));
|
|
if (FAILED(hr))
|
|
return -1; // Special return value so we know to skip
|
|
|
|
VARIANT vDir = { VT_I4 };
|
|
V_I4(&vDir) = (UINT)(SIZE_T)Dir;
|
|
if (!IS_INTRESOURCE((SIZE_T)Dir))
|
|
{
|
|
BSTR bs = SysAllocString((PCWSTR)(SIZE_T)Dir);
|
|
if (!bs)
|
|
return E_OUTOFMEMORY;
|
|
V_VT(&vDir) = VT_BSTR;
|
|
V_BSTR(&vDir) = bs;
|
|
}
|
|
hr = pSD->NameSpace(vDir, ppsdf);
|
|
VariantClear(&vDir);
|
|
return hr;
|
|
}
|
|
|
|
#define ok_NameSpaceFolderParseIsPath(ns, parse, path, mustexist, hrparse) do \
|
|
{ \
|
|
if ((mustexist) && GetFileAttributesW((path)) == INVALID_FILE_ATTRIBUTES) \
|
|
{ \
|
|
skip("Can't ParseName because \"%ls\" does not exist\n", (path)); \
|
|
break; \
|
|
} \
|
|
hr = CreateFolderFromNameSpace((ns), &psdf); \
|
|
ok_long(hr, S_OK); \
|
|
if (SUCCEEDED(hr) && psdf) \
|
|
{ \
|
|
FolderItem *pfi = NULL; \
|
|
hr = psdf->ParseName((BSTR)(parse), &pfi); \
|
|
ok_long(hr, (hrparse)); \
|
|
if (SUCCEEDED(hr) && pfi) \
|
|
{ \
|
|
BSTR bs = NULL; \
|
|
hr = pfi->get_Path(&bs); \
|
|
ok_long(hr, S_OK); \
|
|
ok(SUCCEEDED(hr) && !lstrcmpiW(bs, (path)), "ParseName path \"%ls\" is not \"%ls\"\n", bs, (path)); \
|
|
SysFreeString(SUCCEEDED(hr) ? bs : NULL); \
|
|
SafeRelease(pfi); \
|
|
} \
|
|
} \
|
|
SafeRelease(psdf); \
|
|
} while (0)
|
|
|
|
static void TestNameSpaceFolder()
|
|
{
|
|
HRESULT hr;
|
|
Folder *psdf = NULL;
|
|
FolderItem *psdfi = NULL;
|
|
WCHAR buf1[MAX_PATH], buf2[MAX_PATH];
|
|
|
|
hr = CreateFolderFromNameSpace(CSIDL_DESKTOP, &psdf); // Root folder
|
|
ok_long(hr, S_OK);
|
|
if (hr == -1)
|
|
{
|
|
skip("Unable to initialize test\n");
|
|
return;
|
|
}
|
|
SafeRelease(psdf);
|
|
|
|
hr = CreateFolderFromNameSpace(CSIDL_CONTROLS, &psdf); // Virtual folder
|
|
ok_long(hr, S_OK);
|
|
SafeRelease(psdf);
|
|
|
|
hr = CreateFolderFromNameSpace(CSIDL_DESKTOP, &psdf);
|
|
ok_long(hr, S_OK);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = psdf->ParseName((BSTR)L"X:\\DoesNotExist.xyz", (psdfi = NULL, &psdfi));
|
|
ok(hr != S_OK, "Must fail parsing\n");
|
|
SafeRelease(psdfi);
|
|
}
|
|
SafeRelease(psdf);
|
|
|
|
hr = CreateFolderFromNameSpace(CSIDL_DESKTOP, &psdf);
|
|
ok_long(hr, S_OK);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = psdf->ParseName((BSTR)L"", (psdfi = NULL, &psdfi));
|
|
ok_long(hr, S_OK);
|
|
SafeRelease(psdfi);
|
|
}
|
|
SafeRelease(psdf);
|
|
|
|
hr = CreateFolderFromNameSpace(L"", &psdf);
|
|
ok(hr == S_OK || hr == S_FALSE, "Empty NS"); // S_FALSE on XP
|
|
SafeRelease(psdf);
|
|
|
|
ok_NameSpaceFolderParseIsPath(CSIDL_DESKTOP, L"", L"::{20D04FE0-3AEA-1069-A2D8-08002B30309D}", false, S_OK); // My Computer
|
|
|
|
SHGetFolderPathW(NULL, CSIDL_PROGRAM_FILES, NULL, SHGFP_TYPE_CURRENT, buf1);
|
|
ok_NameSpaceFolderParseIsPath(CSIDL_DESKTOP, buf1, buf1, true, S_OK);
|
|
|
|
GetShortPathNameW(buf1, buf2, _countof(buf2)); // c:\progra~1
|
|
ok_NameSpaceFolderParseIsPath(CSIDL_DESKTOP, buf2, buf1, true, S_OK); // ParseName+get_Path returns the long path
|
|
}
|
|
|
|
static void TestFolderItem()
|
|
{
|
|
WCHAR buf[MAX_PATH];
|
|
VARIANT v = {};
|
|
Folder *psdf = NULL;
|
|
FolderItem *psdfi = NULL;
|
|
FolderItem2 *psdfi2;
|
|
HRESULT hr = CreateFolderFromNameSpace(CSIDL_DESKTOP, &psdf);
|
|
if (hr == -1)
|
|
{
|
|
skip("Unable to initialize test\n");
|
|
return;
|
|
}
|
|
GetModuleFileName(NULL, buf, _countof(buf));
|
|
hr = psdf->ParseName(buf, &psdfi);
|
|
if ((ok(SUCCEEDED(hr), "ParseName %ls failed\n", buf), SUCCEEDED(hr)))
|
|
{
|
|
hr = psdfi->get_IsFileSystem(&V_BOOL(&v));
|
|
ok(hr == S_OK && V_BOOL(&v), "IsFileSystem");
|
|
|
|
hr = psdfi->get_IsFolder(&V_BOOL(&v));
|
|
ok(hr == S_OK && !V_BOOL(&v), "!IsFolder");
|
|
|
|
hr = psdfi->get_Size(&V_I4(&v));
|
|
ok(hr == S_OK && V_I4(&v) == GetFileSize(buf), "Size");
|
|
|
|
hr = psdfi->QueryInterface(IID_PPV_ARG(FolderItem2, &psdfi2));
|
|
if ((ok(SUCCEEDED(hr), "QI FolderItem2\n", buf), SUCCEEDED(hr)))
|
|
{
|
|
hr = psdfi2->ExtendedProperty((BSTR)L"Size", &v);
|
|
if ((ok(SUCCEEDED(hr), "ExtendedProperty failed\n"), SUCCEEDED(hr)))
|
|
{
|
|
VariantChangeType(&v, &v, 0, VT_I4);
|
|
ok(V_I4(&v) == GetFileSize(buf), "Wrong size from property\n");
|
|
VariantClearAndInvalidate(&v);
|
|
}
|
|
SafeRelease(psdfi2);
|
|
}
|
|
SafeRelease(psdfi);
|
|
}
|
|
SafeRelease(psdf);
|
|
}
|
|
|
|
START_TEST(CShellDispatch)
|
|
{
|
|
CCoInit ComInit;
|
|
|
|
TestNameSpaceFolder();
|
|
TestFolderItem();
|
|
|
|
HRESULT hr;
|
|
CComPtr<IShellDispatch2> pSD2;
|
|
if (FAILED(hr = CoCreateInstance(CLSID_Shell, NULL, CLSCTX_ALL, IID_PPV_ARG(IShellDispatch2, &pSD2))))
|
|
{
|
|
skip("Unable to initialize test\n");
|
|
return;
|
|
}
|
|
|
|
IDispatch *pDisp = NULL;
|
|
hr = pSD2->get_Application(&pDisp);
|
|
ok_long(hr, S_OK);
|
|
ok(!!pDisp, "get_Application\n");
|
|
SafeRelease(pDisp);
|
|
hr = pSD2->get_Application(NULL);
|
|
ok(FAILED(hr), "get_Application NULL\n");
|
|
|
|
LONG lVal;
|
|
hr = pSD2->IsRestricted((BSTR)L"DoesNotExist", (BSTR)L"DoesNotExist", (lVal = 42, &lVal));
|
|
ok_long(hr, S_OK);
|
|
ok(lVal == 0, "IsRestricted\n");
|
|
|
|
VARIANT v = {};
|
|
V_I4(&v) = PROCESSOR_ARCHITECTURE_UNKNOWN;
|
|
hr = pSD2->GetSystemInformation((BSTR)L"ProcessorArchitecture", &v);
|
|
ok_long(hr, S_OK);
|
|
ok(V_I4(&v) != PROCESSOR_ARCHITECTURE_UNKNOWN, "GetSystemInformation ProcessorArchitecture\n");
|
|
VariantClearAndInvalidate(&v);
|
|
|
|
hr = pSD2->IsServiceRunning((BSTR)L"DoesNotExist", &v);
|
|
ok_long(hr, S_OK);
|
|
ok_long(V_VT(&v), VT_BOOL);
|
|
ok_long(V_BOOL(&v), VARIANT_FALSE);
|
|
VariantClearAndInvalidate(&v);
|
|
|
|
CComPtr<IShellDispatch4> pSD4;
|
|
if (FAILED(hr = CoCreateInstance(CLSID_Shell, NULL, CLSCTX_ALL, IID_PPV_ARG(IShellDispatch4, &pSD4))))
|
|
{
|
|
skip("Unable to initialize test\n");
|
|
return;
|
|
}
|
|
hr = pSD4->GetSetting(SSF_NOCONFIRMRECYCLE, &V_BOOL(&v));
|
|
ok_long(hr, S_OK);
|
|
ok(V_BOOL(&v) == VARIANT_FALSE || V_BOOL(&v) == VARIANT_TRUE, "VARIANT_BOOL\n");
|
|
}
|