From fe440f7514a6eb59f63e368ee4776164ac797d68 Mon Sep 17 00:00:00 2001 From: Katayama Hirofumi MZ Date: Wed, 26 Jul 2023 08:21:47 +0900 Subject: [PATCH] [SHLWAPI][SHLWAPI_APITEST][SDK] Implement SHPropertyBag_ReadDWORD etc. (#5479) - Add VariantChangeTypeForRead helper function. - Implement SHPropertyBag_ReadType, SHPropertyBag_ReadBOOL, SHPropertyBag_ReadBOOLOld, SHPropertyBag_ReadSHORT, SHPropertyBag_ReadLONG, and SHPropertyBag_ReadDWORD functions. - SHPropertyBag_ReadInt is an alias to SHPropertyBag_ReadLONG. CORE-9283 --- dll/win32/shlwapi/ordinal.c | 187 ++++++++++++++++++ dll/win32/shlwapi/shlwapi.spec | 12 +- .../apitests/shlwapi/SHPropertyBag.cpp | 71 ++++++- sdk/include/reactos/shlwapi_undoc.h | 6 + 4 files changed, 265 insertions(+), 11 deletions(-) diff --git a/dll/win32/shlwapi/ordinal.c b/dll/win32/shlwapi/ordinal.c index c7ba39c5cee..d8aaf6a7678 100644 --- a/dll/win32/shlwapi/ordinal.c +++ b/dll/win32/shlwapi/ordinal.c @@ -5289,6 +5289,153 @@ HRESULT WINAPI IUnknown_QueryServiceForWebBrowserApp(IUnknown* lpUnknown, return IUnknown_QueryService(lpUnknown,&IID_IWebBrowserApp,riid,lppOut); } +#ifdef __REACTOS__ +HRESULT VariantChangeTypeForRead(_Inout_ VARIANTARG *pvarg, _In_ VARTYPE vt) +{ + HRESULT hr; + VARIANTARG vargTemp; + VARIANT variTemp; + + if (V_VT(pvarg) == vt || vt == VT_EMPTY) + return S_OK; + + vargTemp = *pvarg; + + if (V_VT(&vargTemp) != VT_BSTR || vt <= VT_NULL) + goto DoDefault; + + if (vt == VT_I1 || vt == VT_I2 || vt == VT_I4) + { + if (!StrToIntExW(V_BSTR(&vargTemp), STIF_SUPPORT_HEX, &V_I4(&variTemp))) + goto DoDefault; + + V_VT(&variTemp) = VT_INT; + VariantInit(pvarg); + hr = VariantChangeType(pvarg, &variTemp, 0, vt); + VariantClear(&vargTemp); + return hr; + } + + if (vt <= VT_DECIMAL) + goto DoDefault; + + if (vt == VT_UI1 || vt == VT_UI2 || vt == VT_UI4) + { + if (!StrToIntExW(V_BSTR(&vargTemp), STIF_SUPPORT_HEX, (LPINT)&V_UI4(&variTemp))) + goto DoDefault; + + V_VT(&variTemp) = VT_UINT; + VariantInit(pvarg); + hr = VariantChangeType(pvarg, &variTemp, 0, vt); + VariantClear(&vargTemp); + return hr; + } + + if (vt == VT_INT || vt == VT_UINT) + { + if (!StrToIntExW(V_BSTR(&vargTemp), STIF_SUPPORT_HEX, &V_INT(&variTemp))) + goto DoDefault; + + V_VT(&variTemp) = VT_UINT; + VariantInit(pvarg); + hr = VariantChangeType(pvarg, &variTemp, 0, vt); + VariantClear(&vargTemp); + return hr; + } + +DoDefault: + VariantInit(pvarg); + hr = VariantChangeType(pvarg, &vargTemp, 0, vt); + VariantClear(&vargTemp); + return hr; +} + +/************************************************************************** + * SHPropertyBag_ReadType (SHLWAPI.493) + */ +HRESULT WINAPI +SHPropertyBag_ReadType(IPropertyBag *ppb, LPCWSTR pszPropName, VARIANTARG *pvarg, VARTYPE vt) +{ + HRESULT hr; + + VariantInit(pvarg); + V_VT(pvarg) = vt; + + hr = IPropertyBag_Read(ppb, pszPropName, pvarg, NULL); + if (FAILED(hr)) + { + ERR("%p %s\n", ppb, debugstr_w(pszPropName)); + VariantInit(pvarg); + return hr; + } + + return VariantChangeTypeForRead(pvarg, vt); +} + +/************************************************************************** + * SHPropertyBag_ReadBOOL (SHLWAPI.534) + */ +HRESULT WINAPI SHPropertyBag_ReadBOOL(IPropertyBag *ppb, LPCWSTR pszPropName, BOOL *pbValue) +{ + HRESULT hr; + VARIANTARG varg; + + TRACE("%p %s %p\n", ppb, debugstr_w(pszPropName), pbValue); + + if (!ppb || !pszPropName || !pbValue) + { + ERR("%p %s %p\n", ppb, debugstr_w(pszPropName), pbValue); + return E_INVALIDARG; + } + + hr = SHPropertyBag_ReadType(ppb, pszPropName, &varg, VT_BOOL); + if (SUCCEEDED(hr)) + *pbValue = (V_BOOL(&varg) == VARIANT_TRUE); + + return hr; +} + +/************************************************************************** + * SHPropertyBag_ReadBOOLOld (SHLWAPI.498) + */ +BOOL WINAPI SHPropertyBag_ReadBOOLOld(IPropertyBag *ppb, LPCWSTR pszPropName, BOOL bDefValue) +{ + VARIANTARG varg; + HRESULT hr; + + TRACE("%p %s %d\n", ppb, debugstr_w(pszPropName), bDefValue); + + hr = SHPropertyBag_ReadType(ppb, pszPropName, &varg, VT_BOOL); + if (FAILED(hr)) + return bDefValue; + + return V_BOOL(&varg) == VARIANT_TRUE; +} + +/************************************************************************** + * SHPropertyBag_ReadSHORT (SHLWAPI.527) + */ +HRESULT WINAPI SHPropertyBag_ReadSHORT(IPropertyBag *ppb, LPCWSTR pszPropName, SHORT *psValue) +{ + HRESULT hr; + VARIANTARG varg; + + TRACE("%p %s %p\n", ppb, debugstr_w(pszPropName), psValue); + + if (!ppb || !pszPropName || !psValue) + { + ERR("%p %s %p\n", ppb, debugstr_w(pszPropName), psValue); + return E_INVALIDARG; + } + + hr = SHPropertyBag_ReadType(ppb, pszPropName, &varg, VT_UI2); + if (SUCCEEDED(hr)) + *psValue = V_UI2(&varg); + + return hr; +} +#endif + /************************************************************************** * SHPropertyBag_ReadLONG (SHLWAPI.496) * @@ -5304,6 +5451,22 @@ HRESULT WINAPI IUnknown_QueryServiceForWebBrowserApp(IUnknown* lpUnknown, */ HRESULT WINAPI SHPropertyBag_ReadLONG(IPropertyBag *ppb, LPCWSTR pszPropName, LPLONG pValue) { +#ifdef __REACTOS__ + HRESULT hr; + VARIANTARG varg; + + TRACE("%p %s %p\n", ppb, debugstr_w(pszPropName), pValue); + + if (!ppb || !pszPropName || !pValue) + { + ERR("%p %s %p\n", ppb, debugstr_w(pszPropName), pValue); + return E_INVALIDARG; + } + + hr = SHPropertyBag_ReadType(ppb, pszPropName, &varg, VT_I4); + if (SUCCEEDED(hr)) + *pValue = V_I4(&varg); +#else VARIANT var; HRESULT hr; TRACE("%p %s %p\n", ppb,debugstr_w(pszPropName),pValue); @@ -5318,10 +5481,34 @@ HRESULT WINAPI SHPropertyBag_ReadLONG(IPropertyBag *ppb, LPCWSTR pszPropName, LP else hr = DISP_E_BADVARTYPE; } +#endif return hr; } #ifdef __REACTOS__ +/************************************************************************** + * SHPropertyBag_ReadDWORD (SHLWAPI.507) + */ +HRESULT WINAPI SHPropertyBag_ReadDWORD(IPropertyBag *ppb, LPCWSTR pszPropName, DWORD *pdwValue) +{ + HRESULT hr; + VARIANTARG varg; + + TRACE("%p %s %p\n", ppb, debugstr_w(pszPropName), pdwValue); + + if (!ppb || !pszPropName || !pdwValue) + { + ERR("%p %s %p\n", ppb, debugstr_w(pszPropName), pdwValue); + return E_INVALIDARG; + } + + hr = SHPropertyBag_ReadType(ppb, pszPropName, &varg, VT_UI4); + if (SUCCEEDED(hr)) + *pdwValue = V_UI4(&varg); + + return hr; +} + /************************************************************************** * SHPropertyBag_Delete (SHLWAPI.535) */ diff --git a/dll/win32/shlwapi/shlwapi.spec b/dll/win32/shlwapi/shlwapi.spec index 0833bd8f20a..7251262161e 100644 --- a/dll/win32/shlwapi/shlwapi.spec +++ b/dll/win32/shlwapi/shlwapi.spec @@ -490,12 +490,12 @@ 490 stdcall -noname GlobalFindAtomWrapW(wstr) kernel32.GlobalFindAtomW 491 stdcall -noname SHGetShellKey(long long long) 492 stub -noname PrettifyFileDescriptionW -493 stub -noname SHPropertyBag_ReadType +493 stdcall -noname SHPropertyBag_ReadType(ptr wstr ptr long) 494 stub -noname SHPropertyBag_ReadStr 495 stdcall -noname SHPropertyBag_WriteStr(ptr wstr wstr) 496 stdcall -noname SHPropertyBag_ReadLONG(ptr wstr ptr) 497 stdcall -noname SHPropertyBag_WriteLONG(ptr wstr long) -498 stub -noname SHPropertyBag_ReadBOOLOld +498 stdcall -noname SHPropertyBag_ReadBOOLOld(ptr wstr long) 499 stdcall -noname SHPropertyBag_WriteBOOL(ptr wstr long) 500 stdcall AssocGetPerceivedType(wstr ptr ptr ptr) 501 stdcall AssocIsDangerous(wstr) @@ -504,7 +504,7 @@ 504 stdcall AssocQueryStringA(long long str str ptr ptr) 505 stub -noname SHPropertyBag_ReadGUID 506 stdcall -noname SHPropertyBag_WriteGUID(ptr wstr ptr) -507 stdcall -stub -noname SHPropertyBag_ReadDWORD(ptr ptr ptr) +507 stdcall -noname SHPropertyBag_ReadDWORD(ptr wstr ptr) 508 stdcall -noname SHPropertyBag_WriteDWORD(ptr wstr long) 509 stdcall -noname IUnknown_OnFocusChangeIS(ptr ptr long) 510 stdcall -noname SHLockSharedEx(ptr long long) @@ -524,14 +524,14 @@ 524 stdcall -noname SHPropertyBag_WriteRECTL(ptr wstr ptr) 525 stub -noname SHPropertyBag_ReadPOINTS 526 stdcall -noname SHPropertyBag_WritePOINTS(ptr wstr ptr) -527 stub -noname SHPropertyBag_ReadSHORT +527 stdcall -noname SHPropertyBag_ReadSHORT(ptr wstr ptr) 528 stdcall -noname SHPropertyBag_WriteSHORT(ptr wstr long) -529 stub -noname SHPropertyBag_ReadInt +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 532 stdcall -noname SHPropertyBag_WriteStream(ptr wstr ptr) 533 stub -noname SHGetPerScreenResName -534 stub -noname SHPropertyBag_ReadBOOL +534 stdcall -noname SHPropertyBag_ReadBOOL(ptr wstr ptr) 535 stdcall -noname SHPropertyBag_Delete(ptr wstr) 536 stdcall -stub -noname IUnknown_QueryServicePropertyBag(ptr long ptr ptr) 537 stub -noname SHBoolSystemParametersInfo diff --git a/modules/rostests/apitests/shlwapi/SHPropertyBag.cpp b/modules/rostests/apitests/shlwapi/SHPropertyBag.cpp index 6291f25d17e..224d66fb43d 100644 --- a/modules/rostests/apitests/shlwapi/SHPropertyBag.cpp +++ b/modules/rostests/apitests/shlwapi/SHPropertyBag.cpp @@ -14,6 +14,7 @@ static LPCWSTR s_pszPropNames[4] = { NULL, NULL, NULL, NULL }; static VARTYPE s_vt; +static INT s_cRead = 0; static INT s_cWrite = 0; static void ResetTest(VARTYPE vt, @@ -21,17 +22,17 @@ static void ResetTest(VARTYPE vt, LPCWSTR pszName2 = NULL, LPCWSTR pszName3 = NULL) { s_vt = vt; - s_cWrite = 0; + s_cRead = s_cWrite = 0; s_pszPropNames[0] = pszName0; s_pszPropNames[1] = pszName1; s_pszPropNames[2] = pszName2; s_pszPropNames[3] = pszName3; } -class CDummyWritePropertyBag : public IPropertyBag +class CDummyPropertyBag : public IPropertyBag { public: - CDummyWritePropertyBag() + CDummyPropertyBag() { } @@ -55,7 +56,19 @@ public: // IPropertyBag STDMETHODIMP Read(LPCWSTR pszPropName, VARIANT *pvari, IErrorLog *pErrorLog) override { + ++s_cRead; + ok_int(s_vt, V_VT(pvari)); + for (size_t i = 0; i < _countof(s_pszPropNames); ++i) + { + if (s_pszPropNames[i]) + { + ok_wstr(pszPropName, s_pszPropNames[i]); + s_pszPropNames[i] = NULL; + goto Skip1; + } + } ok_int(0, 1); +Skip1: return S_OK; } @@ -76,69 +89,115 @@ public: s_pszPropNames[0] = L"RECTL2.right"; return E_FAIL; } - break; + goto Skip2; } } + ok_int(0, 1); +Skip2: return S_OK; } }; +static void SHPropertyBag_ReadTest(void) +{ + HRESULT hr; + CDummyPropertyBag dummy; + BOOL bValue = 0xDEADFACE; + SHORT sValue = 0xDEAD; + LONG lValue = 0xDEADDEAD; + DWORD dwValue = 0xFEEDF00D; + + ResetTest(VT_BOOL, L"BOOL1"); + hr = SHPropertyBag_ReadBOOL(&dummy, s_pszPropNames[0], &bValue); + ok_long(hr, S_OK); + ok_int(s_cRead, 1); + ok_int(s_cWrite, 0); + + ResetTest(VT_UI2, L"SHORT1"); + hr = SHPropertyBag_ReadSHORT(&dummy, s_pszPropNames[0], &sValue); + ok_long(hr, S_OK); + ok_int(s_cRead, 1); + ok_int(s_cWrite, 0); + + ResetTest(VT_I4, L"LONG1"); + hr = SHPropertyBag_ReadLONG(&dummy, s_pszPropNames[0], &lValue); + ok_long(hr, S_OK); + ok_int(s_cRead, 1); + ok_int(s_cWrite, 0); + + ResetTest(VT_UI4, L"DWORD1"); + hr = SHPropertyBag_ReadDWORD(&dummy, s_pszPropNames[0], &dwValue); + ok_long(hr, S_OK); + ok_int(s_cRead, 1); + ok_int(s_cWrite, 0); +} + static void SHPropertyBag_WriteTest(void) { HRESULT hr; - CDummyWritePropertyBag dummy; + CDummyPropertyBag dummy; ResetTest(VT_EMPTY, L"EMPTY1"); hr = SHPropertyBag_Delete(&dummy, s_pszPropNames[0]); ok_long(hr, S_OK); + ok_int(s_cRead, 0); ok_int(s_cWrite, 1); ResetTest(VT_BOOL, L"BOOL1"); hr = SHPropertyBag_WriteBOOL(&dummy, s_pszPropNames[0], TRUE); ok_long(hr, S_OK); + ok_int(s_cRead, 0); ok_int(s_cWrite, 1); ResetTest(VT_UI2, L"SHORT1"); hr = SHPropertyBag_WriteSHORT(&dummy, s_pszPropNames[0], 1); ok_long(hr, S_OK); + ok_int(s_cRead, 0); ok_int(s_cWrite, 1); ResetTest(VT_I4, L"LONG1"); hr = SHPropertyBag_WriteLONG(&dummy, s_pszPropNames[0], 1); ok_long(hr, S_OK); + ok_int(s_cRead, 0); ok_int(s_cWrite, 1); ResetTest(VT_UI4, L"DWORD1"); hr = SHPropertyBag_WriteDWORD(&dummy, s_pszPropNames[0], 1); ok_long(hr, S_OK); + ok_int(s_cRead, 0); ok_int(s_cWrite, 1); ResetTest(VT_BSTR, L"Str1"); hr = SHPropertyBag_WriteStr(&dummy, s_pszPropNames[0], L"1"); ok_long(hr, S_OK); + ok_int(s_cRead, 0); ok_int(s_cWrite, 1); ResetTest(VT_I4, L"POINTL1.x", L"POINTL1.y"); POINTL ptl = { 0xEEEE, 0xDDDD }; hr = SHPropertyBag_WritePOINTL(&dummy, L"POINTL1", &ptl); ok_long(hr, S_OK); + ok_int(s_cRead, 0); ok_int(s_cWrite, 2); ResetTest(VT_I4, L"POINTS1.x", L"POINTS1.y"); POINTS pts = { 0x2222, 0x3333 }; hr = SHPropertyBag_WritePOINTS(&dummy, L"POINTS1", &pts); ok_long(hr, S_OK); + ok_int(s_cRead, 0); ok_int(s_cWrite, 2); ResetTest(VT_I4, L"RECTL1.left", L"RECTL1.top", L"RECTL1.right", L"RECTL1.bottom"); RECTL rcl = { 123, 456, 789, 101112 }; hr = SHPropertyBag_WriteRECTL(&dummy, L"RECTL1", &rcl); ok_long(hr, S_OK); + ok_int(s_cRead, 0); ok_int(s_cWrite, 4); ResetTest(VT_I4, L"RECTL2.left", L"RECTL2.top", L"RECTL2.right", L"RECTL2.bottom"); hr = SHPropertyBag_WriteRECTL(&dummy, L"RECTL2", &rcl); ok_long(hr, S_OK); + ok_int(s_cRead, 0); ok_int(s_cWrite, 5); GUID guid; @@ -146,10 +205,12 @@ static void SHPropertyBag_WriteTest(void) ResetTest(VT_BSTR, L"GUID1"); hr = SHPropertyBag_WriteGUID(&dummy, L"GUID1", &guid); ok_long(hr, S_OK); + ok_int(s_cRead, 0); ok_int(s_cWrite, 1); } START_TEST(SHPropertyBag) { + SHPropertyBag_ReadTest(); SHPropertyBag_WriteTest(); } diff --git a/sdk/include/reactos/shlwapi_undoc.h b/sdk/include/reactos/shlwapi_undoc.h index d584b57df2d..87f7d62d289 100644 --- a/sdk/include/reactos/shlwapi_undoc.h +++ b/sdk/include/reactos/shlwapi_undoc.h @@ -92,6 +92,12 @@ BOOL WINAPI SHExpandEnvironmentStringsForUserW(HANDLE, LPCWSTR, LPWSTR, DWORD); BOOL WINAPI SHIsEmptyStream(IStream*); HRESULT WINAPI SHInvokeDefaultCommand(HWND,IShellFolder*,LPCITEMIDLIST); +HRESULT WINAPI SHPropertyBag_ReadType(IPropertyBag *ppb, LPCWSTR pszPropName, VARIANTARG *pvarg, VARTYPE vt); +HRESULT WINAPI SHPropertyBag_ReadBOOL(IPropertyBag *ppb, LPCWSTR pszPropName, BOOL *pbValue); +BOOL WINAPI SHPropertyBag_ReadBOOLOld(IPropertyBag *ppb, LPCWSTR pszPropName, BOOL bDefValue); +HRESULT WINAPI SHPropertyBag_ReadSHORT(IPropertyBag *ppb, LPCWSTR pszPropName, SHORT *psValue); +HRESULT WINAPI SHPropertyBag_ReadLONG(IPropertyBag *ppb, LPCWSTR pszPropName, LPLONG pValue); +HRESULT WINAPI SHPropertyBag_ReadDWORD(IPropertyBag *ppb, LPCWSTR pszPropName, DWORD *pdwValue); HRESULT WINAPI SHPropertyBag_ReadPOINTL(IPropertyBag*,LPCWSTR,POINTL*); HRESULT WINAPI SHGetPerScreenResName(OUT LPWSTR lpResName,