1 /* 2 * PROJECT: ReactOS api tests 3 * LICENSE: LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later) 4 * PURPOSE: Tests for SHPropertyBag Read/Write 5 * COPYRIGHT: Copyright 2023 Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com> 6 */ 7 8 #include <apitest.h> 9 #include <shlwapi.h> 10 #include <shlobj.h> 11 #include <shlwapi_undoc.h> 12 13 #include <pseh/pseh2.h> 14 15 static LPCWSTR s_pszPropNames[4] = { NULL, NULL, NULL, NULL }; 16 static VARTYPE s_vt; 17 static INT s_cRead = 0; 18 static INT s_cWrite = 0; 19 20 static void ResetTest(VARTYPE vt, 21 LPCWSTR pszName0 = NULL, LPCWSTR pszName1 = NULL, 22 LPCWSTR pszName2 = NULL, LPCWSTR pszName3 = NULL) 23 { 24 s_vt = vt; 25 s_cRead = s_cWrite = 0; 26 s_pszPropNames[0] = pszName0; 27 s_pszPropNames[1] = pszName1; 28 s_pszPropNames[2] = pszName2; 29 s_pszPropNames[3] = pszName3; 30 } 31 32 class CDummyPropertyBag : public IPropertyBag 33 { 34 public: 35 CDummyPropertyBag() 36 { 37 } 38 39 // IUnknown 40 STDMETHODIMP QueryInterface(REFIID riid, void **ppvObject) override 41 { 42 ok_int(0, 1); 43 return S_OK; 44 } 45 STDMETHODIMP_(ULONG) AddRef() override 46 { 47 ok_int(0, 1); 48 return S_OK; 49 } 50 STDMETHODIMP_(ULONG) Release() override 51 { 52 ok_int(0, 1); 53 return S_OK; 54 } 55 56 // IPropertyBag 57 STDMETHODIMP Read(LPCWSTR pszPropName, VARIANT *pvari, IErrorLog *pErrorLog) override 58 { 59 ++s_cRead; 60 ok_int(s_vt, V_VT(pvari)); 61 for (size_t i = 0; i < _countof(s_pszPropNames); ++i) 62 { 63 if (s_pszPropNames[i]) 64 { 65 ok_wstr(pszPropName, s_pszPropNames[i]); 66 s_pszPropNames[i] = NULL; 67 if (lstrcmpiW(pszPropName, L"RECTL2.top") == 0) 68 return E_FAIL; 69 70 goto Skip1; 71 } 72 } 73 ok_int(0, 1); 74 Skip1: 75 return S_OK; 76 } 77 78 STDMETHODIMP Write(LPCWSTR pszPropName, VARIANT *pvari) override 79 { 80 ++s_cWrite; 81 ok_int(s_vt, V_VT(pvari)); 82 for (size_t i = 0; i < _countof(s_pszPropNames); ++i) 83 { 84 if (s_pszPropNames[i]) 85 { 86 ok_wstr(pszPropName, s_pszPropNames[i]); 87 s_pszPropNames[i] = NULL; 88 if (lstrcmpiW(pszPropName, L"RECTL2.bottom") == 0) 89 { 90 s_vt = VT_EMPTY; 91 ZeroMemory(&s_pszPropNames, sizeof(s_pszPropNames)); 92 s_pszPropNames[0] = L"RECTL2.right"; 93 return E_FAIL; 94 } 95 goto Skip2; 96 } 97 } 98 ok_int(0, 1); 99 Skip2: 100 return S_OK; 101 } 102 }; 103 104 static void SHPropertyBag_ReadTest(void) 105 { 106 HRESULT hr; 107 CDummyPropertyBag dummy; 108 BOOL bValue = 0xDEADFACE; 109 SHORT sValue = 0xDEAD; 110 LONG lValue = 0xDEADDEAD; 111 DWORD dwValue = 0xFEEDF00D; 112 BSTR bstr = NULL; 113 POINTL ptl = { 0xEEEE, 0xDDDD }; 114 POINTS pts = { 0x2222, 0x3333 }; 115 RECTL rcl = { 123, 456, 789, 101112 }; 116 117 ResetTest(VT_BOOL, L"BOOL1"); 118 hr = SHPropertyBag_ReadBOOL(&dummy, s_pszPropNames[0], &bValue); 119 ok_long(hr, S_OK); 120 ok_int(s_cRead, 1); 121 ok_int(s_cWrite, 0); 122 123 ResetTest(VT_UI2, L"SHORT1"); 124 hr = SHPropertyBag_ReadSHORT(&dummy, s_pszPropNames[0], &sValue); 125 ok_long(hr, S_OK); 126 ok_int(s_cRead, 1); 127 ok_int(s_cWrite, 0); 128 129 ResetTest(VT_I4, L"LONG1"); 130 hr = SHPropertyBag_ReadLONG(&dummy, s_pszPropNames[0], &lValue); 131 ok_long(hr, S_OK); 132 ok_int(s_cRead, 1); 133 ok_int(s_cWrite, 0); 134 135 ResetTest(VT_UI4, L"DWORD1"); 136 hr = SHPropertyBag_ReadDWORD(&dummy, s_pszPropNames[0], &dwValue); 137 ok_long(hr, S_OK); 138 ok_int(s_cRead, 1); 139 ok_int(s_cWrite, 0); 140 141 ResetTest(VT_BSTR, L"Str1"); 142 hr = SHPropertyBag_ReadBSTR(&dummy, s_pszPropNames[0], &bstr); 143 ok_long(hr, S_OK); 144 ok_int(s_cRead, 1); 145 ok_int(s_cWrite, 0); 146 SysFreeString(bstr); 147 148 ResetTest(VT_I4, L"POINTL1.x", L"POINTL1.y"); 149 hr = SHPropertyBag_ReadPOINTL(&dummy, L"POINTL1", &ptl); 150 ok_long(hr, S_OK); 151 ok_int(s_cRead, 2); 152 ok_int(s_cWrite, 0); 153 154 ResetTest(VT_I4, L"POINTS1.x", L"POINTS1.y"); 155 hr = SHPropertyBag_ReadPOINTS(&dummy, L"POINTS1", &pts); 156 ok_long(hr, S_OK); 157 ok_int(s_cRead, 2); 158 ok_int(s_cWrite, 0); 159 160 ResetTest(VT_I4, L"RECTL1.left", L"RECTL1.top", L"RECTL1.right", L"RECTL1.bottom"); 161 hr = SHPropertyBag_ReadRECTL(&dummy, L"RECTL1", &rcl); 162 ok_long(hr, S_OK); 163 ok_int(s_cRead, 4); 164 ok_int(s_cWrite, 0); 165 166 ResetTest(VT_I4, L"RECTL2.left", L"RECTL2.top", L"RECTL2.right", L"RECTL2.bottom"); 167 hr = SHPropertyBag_ReadRECTL(&dummy, L"RECTL2", &rcl); 168 ok_long(hr, E_FAIL); 169 ok_int(s_cRead, 2); 170 ok_int(s_cWrite, 0); 171 } 172 173 static void SHPropertyBag_WriteTest(void) 174 { 175 HRESULT hr; 176 CDummyPropertyBag dummy; 177 178 ResetTest(VT_EMPTY, L"EMPTY1"); 179 hr = SHPropertyBag_Delete(&dummy, s_pszPropNames[0]); 180 ok_long(hr, S_OK); 181 ok_int(s_cRead, 0); 182 ok_int(s_cWrite, 1); 183 184 ResetTest(VT_BOOL, L"BOOL1"); 185 hr = SHPropertyBag_WriteBOOL(&dummy, s_pszPropNames[0], TRUE); 186 ok_long(hr, S_OK); 187 ok_int(s_cRead, 0); 188 ok_int(s_cWrite, 1); 189 190 ResetTest(VT_UI2, L"SHORT1"); 191 hr = SHPropertyBag_WriteSHORT(&dummy, s_pszPropNames[0], 1); 192 ok_long(hr, S_OK); 193 ok_int(s_cRead, 0); 194 ok_int(s_cWrite, 1); 195 196 ResetTest(VT_I4, L"LONG1"); 197 hr = SHPropertyBag_WriteLONG(&dummy, s_pszPropNames[0], 1); 198 ok_long(hr, S_OK); 199 ok_int(s_cRead, 0); 200 ok_int(s_cWrite, 1); 201 202 ResetTest(VT_UI4, L"DWORD1"); 203 hr = SHPropertyBag_WriteDWORD(&dummy, s_pszPropNames[0], 1); 204 ok_long(hr, S_OK); 205 ok_int(s_cRead, 0); 206 ok_int(s_cWrite, 1); 207 208 ResetTest(VT_BSTR, L"Str1"); 209 hr = SHPropertyBag_WriteStr(&dummy, s_pszPropNames[0], L"1"); 210 ok_long(hr, S_OK); 211 ok_int(s_cRead, 0); 212 ok_int(s_cWrite, 1); 213 214 ResetTest(VT_I4, L"POINTL1.x", L"POINTL1.y"); 215 POINTL ptl = { 0xEEEE, 0xDDDD }; 216 hr = SHPropertyBag_WritePOINTL(&dummy, L"POINTL1", &ptl); 217 ok_long(hr, S_OK); 218 ok_int(s_cRead, 0); 219 ok_int(s_cWrite, 2); 220 221 ResetTest(VT_I4, L"POINTS1.x", L"POINTS1.y"); 222 POINTS pts = { 0x2222, 0x3333 }; 223 hr = SHPropertyBag_WritePOINTS(&dummy, L"POINTS1", &pts); 224 ok_long(hr, S_OK); 225 ok_int(s_cRead, 0); 226 ok_int(s_cWrite, 2); 227 228 ResetTest(VT_I4, L"RECTL1.left", L"RECTL1.top", L"RECTL1.right", L"RECTL1.bottom"); 229 RECTL rcl = { 123, 456, 789, 101112 }; 230 hr = SHPropertyBag_WriteRECTL(&dummy, L"RECTL1", &rcl); 231 ok_long(hr, S_OK); 232 ok_int(s_cRead, 0); 233 ok_int(s_cWrite, 4); 234 235 ResetTest(VT_I4, L"RECTL2.left", L"RECTL2.top", L"RECTL2.right", L"RECTL2.bottom"); 236 hr = SHPropertyBag_WriteRECTL(&dummy, L"RECTL2", &rcl); 237 ok_long(hr, S_OK); 238 ok_int(s_cRead, 0); 239 ok_int(s_cWrite, 5); 240 241 GUID guid; 242 ZeroMemory(&guid, sizeof(guid)); 243 ResetTest(VT_BSTR, L"GUID1"); 244 hr = SHPropertyBag_WriteGUID(&dummy, L"GUID1", &guid); 245 ok_long(hr, S_OK); 246 ok_int(s_cRead, 0); 247 ok_int(s_cWrite, 1); 248 } 249 250 START_TEST(SHPropertyBag) 251 { 252 SHPropertyBag_ReadTest(); 253 SHPropertyBag_WriteTest(); 254 } 255