Skip to content

Commit

Permalink
[SHLWAPI][SHLWAPI_APITEST][SDK] Implement SHPropertyBag_ReadGUID etc. (
Browse files Browse the repository at this point in the history
…reactos#5491)

- Implement SHPropertyBag_ReadGUID and SHPropertyBag_ReadStream functions.
- Modify shlwapi.spec and shlwapi_undoc.h.
 CORE-9283
  • Loading branch information
katahiromz authored Aug 2, 2023
1 parent 53b30e3 commit 6299340
Show file tree
Hide file tree
Showing 5 changed files with 187 additions and 10 deletions.
98 changes: 98 additions & 0 deletions dll/win32/shlwapi/ordinal.c
Original file line number Diff line number Diff line change
Expand Up @@ -5350,6 +5350,36 @@ HRESULT VariantChangeTypeForRead(_Inout_ VARIANTARG *pvarg, _In_ VARTYPE vt)
return hr;
}

BOOL
VariantArrayToBuffer(
_In_ const VARIANT *pvarIn,
_Out_writes_(cbSize) LPVOID pvDest,
_In_ SIZE_T cbSize)
{
LPVOID pvData;
LONG LowerBound, UpperBound;
LPSAFEARRAY pArray;

/* Only supports byte array */
if (!pvarIn || V_VT(pvarIn) != (VT_UI1 | VT_ARRAY))
return FALSE;

/* Boundary check and access */
pArray = V_ARRAY(pvarIn);
if (SafeArrayGetDim(pArray) == 1 &&
SUCCEEDED(SafeArrayGetLBound(pArray, 1, &LowerBound)) &&
SUCCEEDED(SafeArrayGetUBound(pArray, 1, &UpperBound)) &&
((LONG)cbSize <= UpperBound - LowerBound + 1) &&
SUCCEEDED(SafeArrayAccessData(pArray, &pvData)))
{
CopyMemory(pvDest, pvData, cbSize);
SafeArrayUnaccessData(pArray);
return TRUE; /* Success */
}

return FALSE; /* Failure */
}

/**************************************************************************
* SHPropertyBag_ReadType (SHLWAPI.493)
*/
Expand Down Expand Up @@ -5670,6 +5700,74 @@ HRESULT WINAPI SHPropertyBag_ReadRECTL(IPropertyBag *ppb, LPCWSTR pszPropName, R
return SHPropertyBag_ReadLONG(ppb, szBuff, &prcl->bottom);
}

/**************************************************************************
* SHPropertyBag_ReadGUID (SHLWAPI.505)
*/
HRESULT WINAPI SHPropertyBag_ReadGUID(IPropertyBag *ppb, LPCWSTR pszPropName, GUID *pguid)
{
HRESULT hr;
BOOL bRet;
VARIANT vari;

TRACE("%p %s %p\n", ppb, debugstr_w(pszPropName), pguid);

if (!ppb || !pszPropName || !pguid)
{
ERR("%p %s %p\n", ppb, debugstr_w(pszPropName), pguid);
return E_INVALIDARG;
}

hr = SHPropertyBag_ReadType(ppb, pszPropName, &vari, VT_EMPTY);
if (FAILED(hr))
{
ERR("%p %s %p\n", ppb, debugstr_w(pszPropName), pguid);
return hr;
}

if (V_VT(&vari) == (VT_UI1 | VT_ARRAY)) /* Byte Array */
bRet = VariantArrayToBuffer(&vari, pguid, sizeof(*pguid));
else if (V_VT(&vari) == VT_BSTR)
bRet = GUIDFromStringW(V_BSTR(&vari), pguid);
else
#if (_WIN32_WINNT >= _WIN32_WINNT_VISTA)
bRet = FALSE;
#else
bRet = TRUE; /* This is by design in WinXP/Win2k3. */
#endif

if (!bRet)
ERR("%p %s %p\n", ppb, debugstr_w(pszPropName), pguid);

VariantClear(&vari);
return (bRet ? S_OK : E_FAIL);
}

/**************************************************************************
* SHPropertyBag_ReadStream (SHLWAPI.531)
*/
HRESULT WINAPI SHPropertyBag_ReadStream(IPropertyBag *ppb, LPCWSTR pszPropName, IStream **ppStream)
{
HRESULT hr;
VARIANT vari;

TRACE("%p %s %p\n", ppb, debugstr_w(pszPropName), ppStream);

if (!ppb || !pszPropName || !ppStream)
{
ERR("%p %s %p\n", ppb, debugstr_w(pszPropName), ppStream);
return E_INVALIDARG;
}

hr = SHPropertyBag_ReadType(ppb, pszPropName, &vari, VT_UNKNOWN);
if (FAILED(hr))
return hr;

hr = IUnknown_QueryInterface(V_UNKNOWN(&vari), &IID_IStream, (void **)ppStream);
IUnknown_Release(V_UNKNOWN(&vari));

return hr;
}

/**************************************************************************
* SHPropertyBag_Delete (SHLWAPI.535)
*/
Expand Down
4 changes: 2 additions & 2 deletions dll/win32/shlwapi/shlwapi.spec
Original file line number Diff line number Diff line change
Expand Up @@ -502,7 +502,7 @@
502 stdcall AssocQueryKeyA(long long str str ptr)
503 stdcall AssocQueryKeyW(long long wstr wstr ptr)
504 stdcall AssocQueryStringA(long long str str ptr ptr)
505 stub -noname SHPropertyBag_ReadGUID
505 stdcall -noname SHPropertyBag_ReadGUID(ptr wstr ptr)
506 stdcall -noname SHPropertyBag_WriteGUID(ptr wstr ptr)
507 stdcall -noname SHPropertyBag_ReadDWORD(ptr wstr ptr)
508 stdcall -noname SHPropertyBag_WriteDWORD(ptr wstr long)
Expand All @@ -528,7 +528,7 @@
528 stdcall -noname SHPropertyBag_WriteSHORT(ptr wstr long)
529 stdcall -noname SHPropertyBag_ReadInt(ptr wstr ptr) SHPropertyBag_ReadLONG
530 stdcall -noname SHPropertyBag_WriteInt(ptr wstr long) SHPropertyBag_WriteLONG
531 stub -noname SHPropertyBag_ReadStream
531 stdcall -noname SHPropertyBag_ReadStream(ptr wstr ptr)
532 stdcall -noname SHPropertyBag_WriteStream(ptr wstr ptr)
533 stub -noname SHGetPerScreenResName
534 stdcall -noname SHPropertyBag_ReadBOOL(ptr wstr ptr)
Expand Down
4 changes: 2 additions & 2 deletions modules/rostests/apitests/shlwapi/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ add_rc_deps(testdata.rc ${CMAKE_CURRENT_BINARY_DIR}/shlwapi_resource_dll/shlwapi

add_executable(shlwapi_apitest ${SOURCE})
set_module_type(shlwapi_apitest win32cui)
target_link_libraries(shlwapi_apitest ${PSEH_LIB})
add_importlibs(shlwapi_apitest shlwapi oleaut32 user32 advapi32 msvcrt kernel32)
target_link_libraries(shlwapi_apitest ${PSEH_LIB} uuid)
add_importlibs(shlwapi_apitest shlwapi oleaut32 ole32 user32 advapi32 msvcrt kernel32)
add_dependencies(shlwapi_apitest shlwapi_resource_dll)
add_rostests_file(TARGET shlwapi_apitest)
88 changes: 83 additions & 5 deletions modules/rostests/apitests/shlwapi/SHPropertyBag.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include <shlwapi.h>
#include <shlobj.h>
#include <shlwapi_undoc.h>
#include <versionhelpers.h>

#include <pseh/pseh2.h>

Expand All @@ -29,6 +30,30 @@ static void ResetTest(VARTYPE vt,
s_pszPropNames[3] = pszName3;
}

static SAFEARRAY* CreateByteArray(LPCVOID pvSrc, DWORD cbSize)
{
SAFEARRAYBOUND Bound;
Bound.lLbound = 0;
Bound.cElements = cbSize;

SAFEARRAY* pArray = SafeArrayCreate(VT_UI1, 1, &Bound);
if (!pArray)
return NULL;

void HUGEP *pvData;
HRESULT hr = SafeArrayAccessData(pArray, &pvData);
if (FAILED(hr))
{
SafeArrayDestroy(pArray);
return NULL;
}

CopyMemory(pvData, pvSrc, cbSize);
SafeArrayUnaccessData(pArray);

return pArray;
}

class CDummyPropertyBag : public IPropertyBag
{
public:
Expand All @@ -39,17 +64,17 @@ class CDummyPropertyBag : public IPropertyBag
// IUnknown
STDMETHODIMP QueryInterface(REFIID riid, void **ppvObject) override
{
ok_int(0, 1);
ok(FALSE, "Unexpected call\n");
return S_OK;
}
STDMETHODIMP_(ULONG) AddRef() override
{
ok_int(0, 1);
ok(FALSE, "Unexpected call\n");
return S_OK;
}
STDMETHODIMP_(ULONG) Release() override
{
ok_int(0, 1);
ok(FALSE, "Unexpected call\n");
return S_OK;
}

Expand All @@ -64,13 +89,38 @@ class CDummyPropertyBag : public IPropertyBag
{
ok_wstr(pszPropName, s_pszPropNames[i]);
s_pszPropNames[i] = NULL;

if (lstrcmpiW(pszPropName, L"RECTL2.top") == 0)
return E_FAIL;

if (lstrcmpiW(pszPropName, L"GUID1") == 0)
{
V_VT(pvari) = (VT_UI1 | VT_ARRAY);
V_ARRAY(pvari) = CreateByteArray(&IID_IShellLink, sizeof(IID));
return S_OK;
}

if (lstrcmpiW(pszPropName, L"GUID2") == 0)
{
WCHAR szText[50];
StringFromGUID2(IID_IUnknown, szText, _countof(szText));

V_VT(pvari) = VT_BSTR;
V_BSTR(pvari) = SysAllocString(szText);
return S_OK;
}

if (lstrcmpiW(pszPropName, L"GUID3") == 0)
{
V_VT(pvari) = VT_EMPTY;
V_UI4(pvari) = 0xDEADFACE;
return S_OK;
}

goto Skip1;
}
}
ok_int(0, 1);
ok(FALSE, "Unexpected call\n");
Skip1:
return S_OK;
}
Expand All @@ -95,7 +145,7 @@ class CDummyPropertyBag : public IPropertyBag
goto Skip2;
}
}
ok_int(0, 1);
ok(FALSE, "Unexpected call\n");
Skip2:
return S_OK;
}
Expand All @@ -113,6 +163,7 @@ static void SHPropertyBag_ReadTest(void)
POINTL ptl = { 0xEEEE, 0xDDDD };
POINTS pts = { 0x2222, 0x3333 };
RECTL rcl = { 123, 456, 789, 101112 };
GUID guid = { 0 };

ResetTest(VT_BOOL, L"BOOL1");
hr = SHPropertyBag_ReadBOOL(&dummy, s_pszPropNames[0], &bValue);
Expand Down Expand Up @@ -168,6 +219,33 @@ static void SHPropertyBag_ReadTest(void)
ok_long(hr, E_FAIL);
ok_int(s_cRead, 2);
ok_int(s_cWrite, 0);

ResetTest(VT_EMPTY, L"GUID1");
hr = SHPropertyBag_ReadGUID(&dummy, L"GUID1", &guid);
ok_long(hr, S_OK);
ok_int(s_cRead, 1);
ok_int(s_cWrite, 0);
ok_int(IsEqualGUID(guid, IID_IShellLink), TRUE);

ResetTest(VT_EMPTY, L"GUID2");
hr = SHPropertyBag_ReadGUID(&dummy, L"GUID2", &guid);
ok_long(hr, S_OK);
ok_int(s_cRead, 1);
ok_int(s_cWrite, 0);
ok_int(IsEqualGUID(guid, IID_IUnknown), TRUE);

ResetTest(VT_EMPTY, L"GUID3");
guid = IID_IExtractIcon;
hr = SHPropertyBag_ReadGUID(&dummy, L"GUID3", &guid);

if (IsWindowsVistaOrGreater())
ok_long(hr, E_INVALIDARG);
else
ok_long(hr, S_OK);

ok_int(s_cRead, 1);
ok_int(s_cWrite, 0);
ok_int(IsEqualGUID(guid, IID_IExtractIcon), TRUE);
}

static void SHPropertyBag_WriteTest(void)
Expand Down
3 changes: 2 additions & 1 deletion sdk/include/reactos/shlwapi_undoc.h
Original file line number Diff line number Diff line change
Expand Up @@ -103,12 +103,13 @@ HRESULT WINAPI SHPropertyBag_ReadStr(IPropertyBag *ppb, LPCWSTR pszPropName, LPW
HRESULT WINAPI SHPropertyBag_ReadPOINTL(IPropertyBag *ppb, LPCWSTR pszPropName, POINTL *pptl);
HRESULT WINAPI SHPropertyBag_ReadPOINTS(IPropertyBag *ppb, LPCWSTR pszPropName, POINTS *ppts);
HRESULT WINAPI SHPropertyBag_ReadRECTL(IPropertyBag *ppb, LPCWSTR pszPropName, RECTL *prcl);
HRESULT WINAPI SHPropertyBag_ReadGUID(IPropertyBag *ppb, LPCWSTR pszPropName, GUID *pguid);
HRESULT WINAPI SHPropertyBag_ReadStream(IPropertyBag *ppb, LPCWSTR pszPropName, IStream **ppStream);

HRESULT WINAPI SHGetPerScreenResName(OUT LPWSTR lpResName,
IN INT cchResName,
IN DWORD dwReserved);

HRESULT WINAPI SHPropertyBag_ReadStream(IPropertyBag*,LPCWSTR,IStream**);
HRESULT WINAPI SHPropertyBag_Delete(IPropertyBag *ppb, LPCWSTR pszPropName);
HRESULT WINAPI SHPropertyBag_WriteBOOL(IPropertyBag *ppb, LPCWSTR pszPropName, BOOL bValue);
HRESULT WINAPI SHPropertyBag_WriteSHORT(IPropertyBag *ppb, LPCWSTR pszPropName, SHORT sValue);
Expand Down

0 comments on commit 6299340

Please sign in to comment.