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 #include <versionhelpers.h> 13 14 #include <pseh/pseh2.h> 15 16 static LPCWSTR s_pszPropNames[4] = { NULL, NULL, NULL, NULL }; 17 static VARTYPE s_vt; 18 static INT s_cRead = 0; 19 static INT s_cWrite = 0; 20 21 static void ResetTest(VARTYPE vt, 22 LPCWSTR pszName0 = NULL, LPCWSTR pszName1 = NULL, 23 LPCWSTR pszName2 = NULL, LPCWSTR pszName3 = NULL) 24 { 25 s_vt = vt; 26 s_cRead = s_cWrite = 0; 27 s_pszPropNames[0] = pszName0; 28 s_pszPropNames[1] = pszName1; 29 s_pszPropNames[2] = pszName2; 30 s_pszPropNames[3] = pszName3; 31 } 32 33 static SAFEARRAY* CreateByteArray(LPCVOID pvSrc, DWORD cbSize) 34 { 35 SAFEARRAYBOUND Bound; 36 Bound.lLbound = 0; 37 Bound.cElements = cbSize; 38 39 SAFEARRAY* pArray = SafeArrayCreate(VT_UI1, 1, &Bound); 40 if (!pArray) 41 return NULL; 42 43 void HUGEP *pvData; 44 HRESULT hr = SafeArrayAccessData(pArray, &pvData); 45 if (FAILED(hr)) 46 { 47 SafeArrayDestroy(pArray); 48 return NULL; 49 } 50 51 CopyMemory(pvData, pvSrc, cbSize); 52 SafeArrayUnaccessData(pArray); 53 54 return pArray; 55 } 56 57 class CDummyPropertyBag : public IPropertyBag 58 { 59 public: 60 CDummyPropertyBag() 61 { 62 } 63 64 // IUnknown 65 STDMETHODIMP QueryInterface(REFIID riid, void **ppvObject) override 66 { 67 ok(FALSE, "Unexpected call\n"); 68 return S_OK; 69 } 70 STDMETHODIMP_(ULONG) AddRef() override 71 { 72 ok(FALSE, "Unexpected call\n"); 73 return S_OK; 74 } 75 STDMETHODIMP_(ULONG) Release() override 76 { 77 ok(FALSE, "Unexpected call\n"); 78 return S_OK; 79 } 80 81 // IPropertyBag 82 STDMETHODIMP Read(LPCWSTR pszPropName, VARIANT *pvari, IErrorLog *pErrorLog) override 83 { 84 ++s_cRead; 85 ok_int(s_vt, V_VT(pvari)); 86 for (size_t i = 0; i < _countof(s_pszPropNames); ++i) 87 { 88 if (s_pszPropNames[i]) 89 { 90 ok_wstr(pszPropName, s_pszPropNames[i]); 91 s_pszPropNames[i] = NULL; 92 93 if (lstrcmpiW(pszPropName, L"RECTL2.top") == 0) 94 return E_FAIL; 95 96 if (lstrcmpiW(pszPropName, L"GUID1") == 0) 97 { 98 V_VT(pvari) = (VT_UI1 | VT_ARRAY); 99 V_ARRAY(pvari) = CreateByteArray(&IID_IShellLinkW, sizeof(IID)); 100 return S_OK; 101 } 102 103 if (lstrcmpiW(pszPropName, L"GUID2") == 0) 104 { 105 WCHAR szText[50]; 106 StringFromGUID2(IID_IUnknown, szText, _countof(szText)); 107 108 V_VT(pvari) = VT_BSTR; 109 V_BSTR(pvari) = SysAllocString(szText); 110 return S_OK; 111 } 112 113 if (lstrcmpiW(pszPropName, L"GUID3") == 0) 114 { 115 V_VT(pvari) = VT_EMPTY; 116 V_UI4(pvari) = 0xDEADFACE; 117 return S_OK; 118 } 119 120 goto Skip1; 121 } 122 } 123 ok(FALSE, "Unexpected call\n"); 124 Skip1: 125 return S_OK; 126 } 127 128 STDMETHODIMP Write(LPCWSTR pszPropName, VARIANT *pvari) override 129 { 130 ++s_cWrite; 131 ok_int(s_vt, V_VT(pvari)); 132 for (size_t i = 0; i < _countof(s_pszPropNames); ++i) 133 { 134 if (s_pszPropNames[i]) 135 { 136 ok_wstr(pszPropName, s_pszPropNames[i]); 137 s_pszPropNames[i] = NULL; 138 if (lstrcmpiW(pszPropName, L"RECTL2.bottom") == 0) 139 { 140 s_vt = VT_EMPTY; 141 ZeroMemory(&s_pszPropNames, sizeof(s_pszPropNames)); 142 s_pszPropNames[0] = L"RECTL2.right"; 143 return E_FAIL; 144 } 145 goto Skip2; 146 } 147 } 148 ok(FALSE, "Unexpected call\n"); 149 Skip2: 150 return S_OK; 151 } 152 }; 153 154 static void SHPropertyBag_ReadTest(void) 155 { 156 HRESULT hr; 157 CDummyPropertyBag dummy; 158 BOOL bValue = 0xDEADFACE; 159 SHORT sValue = 0xDEAD; 160 LONG lValue = 0xDEADDEAD; 161 DWORD dwValue = 0xFEEDF00D; 162 BSTR bstr = NULL; 163 POINTL ptl = { 0xEEEE, 0xDDDD }; 164 POINTS pts = { 0x2222, 0x3333 }; 165 RECTL rcl = { 123, 456, 789, 101112 }; 166 GUID guid = { 0 }; 167 168 ResetTest(VT_BOOL, L"BOOL1"); 169 hr = SHPropertyBag_ReadBOOL(&dummy, s_pszPropNames[0], &bValue); 170 ok_long(hr, S_OK); 171 ok_int(s_cRead, 1); 172 ok_int(s_cWrite, 0); 173 174 ResetTest(VT_UI2, L"SHORT1"); 175 hr = SHPropertyBag_ReadSHORT(&dummy, s_pszPropNames[0], &sValue); 176 ok_long(hr, S_OK); 177 ok_int(s_cRead, 1); 178 ok_int(s_cWrite, 0); 179 180 ResetTest(VT_I4, L"LONG1"); 181 hr = SHPropertyBag_ReadLONG(&dummy, s_pszPropNames[0], &lValue); 182 ok_long(hr, S_OK); 183 ok_int(s_cRead, 1); 184 ok_int(s_cWrite, 0); 185 186 ResetTest(VT_UI4, L"DWORD1"); 187 hr = SHPropertyBag_ReadDWORD(&dummy, s_pszPropNames[0], &dwValue); 188 ok_long(hr, S_OK); 189 ok_int(s_cRead, 1); 190 ok_int(s_cWrite, 0); 191 192 ResetTest(VT_BSTR, L"Str1"); 193 hr = SHPropertyBag_ReadBSTR(&dummy, s_pszPropNames[0], &bstr); 194 ok_long(hr, S_OK); 195 ok_int(s_cRead, 1); 196 ok_int(s_cWrite, 0); 197 SysFreeString(bstr); 198 199 ResetTest(VT_I4, L"POINTL1.x", L"POINTL1.y"); 200 hr = SHPropertyBag_ReadPOINTL(&dummy, L"POINTL1", &ptl); 201 ok_long(hr, S_OK); 202 ok_int(s_cRead, 2); 203 ok_int(s_cWrite, 0); 204 205 ResetTest(VT_I4, L"POINTS1.x", L"POINTS1.y"); 206 hr = SHPropertyBag_ReadPOINTS(&dummy, L"POINTS1", &pts); 207 ok_long(hr, S_OK); 208 ok_int(s_cRead, 2); 209 ok_int(s_cWrite, 0); 210 211 ResetTest(VT_I4, L"RECTL1.left", L"RECTL1.top", L"RECTL1.right", L"RECTL1.bottom"); 212 hr = SHPropertyBag_ReadRECTL(&dummy, L"RECTL1", &rcl); 213 ok_long(hr, S_OK); 214 ok_int(s_cRead, 4); 215 ok_int(s_cWrite, 0); 216 217 ResetTest(VT_I4, L"RECTL2.left", L"RECTL2.top", L"RECTL2.right", L"RECTL2.bottom"); 218 hr = SHPropertyBag_ReadRECTL(&dummy, L"RECTL2", &rcl); 219 ok_long(hr, E_FAIL); 220 ok_int(s_cRead, 2); 221 ok_int(s_cWrite, 0); 222 223 ResetTest(VT_EMPTY, L"GUID1"); 224 hr = SHPropertyBag_ReadGUID(&dummy, L"GUID1", &guid); 225 ok_long(hr, S_OK); 226 ok_int(s_cRead, 1); 227 ok_int(s_cWrite, 0); 228 ok_int(IsEqualGUID(guid, IID_IShellLinkW), TRUE); 229 230 ResetTest(VT_EMPTY, L"GUID2"); 231 hr = SHPropertyBag_ReadGUID(&dummy, L"GUID2", &guid); 232 ok_long(hr, S_OK); 233 ok_int(s_cRead, 1); 234 ok_int(s_cWrite, 0); 235 ok_int(IsEqualGUID(guid, IID_IUnknown), TRUE); 236 237 ResetTest(VT_EMPTY, L"GUID3"); 238 guid = IID_IExtractIcon; 239 hr = SHPropertyBag_ReadGUID(&dummy, L"GUID3", &guid); 240 241 if (IsWindowsVistaOrGreater()) 242 ok_long(hr, E_INVALIDARG); 243 else 244 ok_long(hr, S_OK); 245 246 ok_int(s_cRead, 1); 247 ok_int(s_cWrite, 0); 248 ok_int(IsEqualGUID(guid, IID_IExtractIcon), TRUE); 249 } 250 251 static void SHPropertyBag_WriteTest(void) 252 { 253 HRESULT hr; 254 CDummyPropertyBag dummy; 255 256 ResetTest(VT_EMPTY, L"EMPTY1"); 257 hr = SHPropertyBag_Delete(&dummy, s_pszPropNames[0]); 258 ok_long(hr, S_OK); 259 ok_int(s_cRead, 0); 260 ok_int(s_cWrite, 1); 261 262 ResetTest(VT_BOOL, L"BOOL1"); 263 hr = SHPropertyBag_WriteBOOL(&dummy, s_pszPropNames[0], TRUE); 264 ok_long(hr, S_OK); 265 ok_int(s_cRead, 0); 266 ok_int(s_cWrite, 1); 267 268 ResetTest(VT_UI2, L"SHORT1"); 269 hr = SHPropertyBag_WriteSHORT(&dummy, s_pszPropNames[0], 1); 270 ok_long(hr, S_OK); 271 ok_int(s_cRead, 0); 272 ok_int(s_cWrite, 1); 273 274 ResetTest(VT_I4, L"LONG1"); 275 hr = SHPropertyBag_WriteLONG(&dummy, s_pszPropNames[0], 1); 276 ok_long(hr, S_OK); 277 ok_int(s_cRead, 0); 278 ok_int(s_cWrite, 1); 279 280 ResetTest(VT_UI4, L"DWORD1"); 281 hr = SHPropertyBag_WriteDWORD(&dummy, s_pszPropNames[0], 1); 282 ok_long(hr, S_OK); 283 ok_int(s_cRead, 0); 284 ok_int(s_cWrite, 1); 285 286 ResetTest(VT_BSTR, L"Str1"); 287 hr = SHPropertyBag_WriteStr(&dummy, s_pszPropNames[0], L"1"); 288 ok_long(hr, S_OK); 289 ok_int(s_cRead, 0); 290 ok_int(s_cWrite, 1); 291 292 ResetTest(VT_I4, L"POINTL1.x", L"POINTL1.y"); 293 POINTL ptl = { 0xEEEE, 0xDDDD }; 294 hr = SHPropertyBag_WritePOINTL(&dummy, L"POINTL1", &ptl); 295 ok_long(hr, S_OK); 296 ok_int(s_cRead, 0); 297 ok_int(s_cWrite, 2); 298 299 ResetTest(VT_I4, L"POINTS1.x", L"POINTS1.y"); 300 POINTS pts = { 0x2222, 0x3333 }; 301 hr = SHPropertyBag_WritePOINTS(&dummy, L"POINTS1", &pts); 302 ok_long(hr, S_OK); 303 ok_int(s_cRead, 0); 304 ok_int(s_cWrite, 2); 305 306 ResetTest(VT_I4, L"RECTL1.left", L"RECTL1.top", L"RECTL1.right", L"RECTL1.bottom"); 307 RECTL rcl = { 123, 456, 789, 101112 }; 308 hr = SHPropertyBag_WriteRECTL(&dummy, L"RECTL1", &rcl); 309 ok_long(hr, S_OK); 310 ok_int(s_cRead, 0); 311 ok_int(s_cWrite, 4); 312 313 ResetTest(VT_I4, L"RECTL2.left", L"RECTL2.top", L"RECTL2.right", L"RECTL2.bottom"); 314 hr = SHPropertyBag_WriteRECTL(&dummy, L"RECTL2", &rcl); 315 ok_long(hr, S_OK); 316 ok_int(s_cRead, 0); 317 ok_int(s_cWrite, 5); 318 319 GUID guid; 320 ZeroMemory(&guid, sizeof(guid)); 321 ResetTest(VT_BSTR, L"GUID1"); 322 hr = SHPropertyBag_WriteGUID(&dummy, L"GUID1", &guid); 323 ok_long(hr, S_OK); 324 ok_int(s_cRead, 0); 325 ok_int(s_cWrite, 1); 326 } 327 328 static void SHPropertyBag_OnMemory(void) 329 { 330 HRESULT hr; 331 VARIANT vari; 332 333 IPropertyBag *pPropBag = NULL; 334 hr = SHCreatePropertyBagOnMemory(STGM_READWRITE, IID_IPropertyBag, (void**)&pPropBag); 335 ok_long(hr, S_OK); 336 if (pPropBag == NULL) 337 { 338 skip("pPropBag was NULL\n"); 339 return; 340 } 341 342 VariantInit(&vari); 343 hr = pPropBag->Read(L"InvalidName", &vari, NULL); 344 ok_long(hr, E_FAIL); 345 VariantClear(&vari); 346 347 VariantInit(&vari); 348 V_VT(&vari) = VT_UI4; 349 V_UI4(&vari) = 0xDEADFACE; 350 hr = pPropBag->Write(L"Name1", &vari); 351 ok_long(hr, S_OK); 352 VariantClear(&vari); 353 354 VariantInit(&vari); 355 hr = pPropBag->Read(L"Name1", &vari, NULL); 356 ok_long(hr, S_OK); 357 ok_long(V_VT(&vari), VT_UI4); 358 ok_long(V_UI4(&vari), 0xDEADFACE); 359 VariantClear(&vari); 360 361 pPropBag->Release(); 362 pPropBag = NULL; 363 364 hr = SHCreatePropertyBagOnMemory(STGM_READ, IID_IPropertyBag, (void**)&pPropBag); 365 ok_long(hr, S_OK); 366 367 VariantInit(&vari); 368 V_VT(&vari) = VT_UI4; 369 V_UI4(&vari) = 0xDEADFACE; 370 hr = pPropBag->Write(L"Name1", &vari); 371 ok_long(hr, (IsWindowsVistaOrGreater() ? S_OK : E_ACCESSDENIED)); 372 VariantClear(&vari); 373 374 VariantInit(&vari); 375 V_VT(&vari) = VT_UI4; 376 V_UI4(&vari) = 0xFEEDF00D; 377 hr = pPropBag->Read(L"Name1", &vari, NULL); 378 if (IsWindowsVistaOrGreater()) 379 { 380 ok_long(hr, S_OK); 381 ok_int(V_VT(&vari), VT_UI4); 382 ok_long(V_UI4(&vari), 0xDEADFACE); 383 } 384 else 385 { 386 ok_long(hr, E_FAIL); 387 ok_int(V_VT(&vari), VT_EMPTY); 388 ok_long(V_UI4(&vari), 0xFEEDF00D); 389 } 390 VariantClear(&vari); 391 392 pPropBag->Release(); 393 pPropBag = NULL; 394 395 hr = SHCreatePropertyBagOnMemory(STGM_WRITE, IID_IPropertyBag, (void**)&pPropBag); 396 ok_long(hr, S_OK); 397 398 VariantInit(&vari); 399 V_VT(&vari) = VT_UI4; 400 V_UI4(&vari) = 0xDEADFACE; 401 hr = pPropBag->Write(L"Name1", &vari); 402 ok_long(hr, S_OK); 403 VariantClear(&vari); 404 405 VariantInit(&vari); 406 V_VT(&vari) = VT_UI4; 407 V_UI4(&vari) = 0xFEEDF00D; 408 hr = pPropBag->Read(L"Name1", &vari, NULL); 409 if (IsWindowsVistaOrGreater()) 410 { 411 ok_long(hr, S_OK); 412 ok_int(V_VT(&vari), VT_UI4); 413 ok_long(V_UI4(&vari), 0xDEADFACE); 414 } 415 else 416 { 417 ok_long(hr, E_ACCESSDENIED); 418 ok_int(V_VT(&vari), VT_EMPTY); 419 ok_long(V_UI4(&vari), 0xFEEDF00D); 420 } 421 VariantClear(&vari); 422 423 pPropBag->Release(); 424 425 hr = SHCreatePropertyBagOnMemory(STGM_READWRITE, IID_IPropertyBag2, (void**)&pPropBag); 426 if (IsWindowsVistaOrGreater()) 427 { 428 ok_long(hr, E_NOINTERFACE); 429 } 430 else 431 { 432 ok_long(hr, S_OK); 433 pPropBag->Release(); 434 } 435 436 hr = SHCreatePropertyBagOnMemory(STGM_READ, IID_IPropertyBag2, (void**)&pPropBag); 437 if (IsWindowsVistaOrGreater()) 438 { 439 ok_long(hr, E_NOINTERFACE); 440 } 441 else 442 { 443 ok_long(hr, S_OK); 444 pPropBag->Release(); 445 } 446 447 hr = SHCreatePropertyBagOnMemory(STGM_WRITE, IID_IPropertyBag2, (void**)&pPropBag); 448 if (IsWindowsVistaOrGreater()) 449 { 450 ok_long(hr, E_NOINTERFACE); 451 } 452 else 453 { 454 ok_long(hr, S_OK); 455 pPropBag->Release(); 456 } 457 } 458 459 static void SHPropertyBag_OnRegKey(void) 460 { 461 HKEY hKey, hSubKey; 462 LONG error; 463 VARIANT vari; 464 WCHAR szText[MAX_PATH]; 465 IStream *pStream; 466 GUID guid; 467 BYTE guid_and_extra[sizeof(GUID) + sizeof(GUID)]; 468 469 // Create HKCU\Software\ReactOS registry key 470 error = RegCreateKeyW(HKEY_CURRENT_USER, L"Software\\ReactOS", &hKey); 471 if (error) 472 { 473 skip("FAILED to create HKCU\\Software\\ReactOS\n"); 474 return; 475 } 476 477 IPropertyBag *pPropBag; 478 HRESULT hr; 479 480 // Try to create new registry key 481 RegDeleteKeyW(hKey, L"PropBagTest"); 482 hr = SHCreatePropertyBagOnRegKey(hKey, L"PropBagTest", 0, 483 IID_IPropertyBag, (void **)&pPropBag); 484 ok_long(hr, HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)); 485 486 // Try to create new registry key 487 RegDeleteKeyW(hKey, L"PropBagTest"); 488 hr = SHCreatePropertyBagOnRegKey(hKey, L"PropBagTest", STGM_READWRITE, 489 IID_IPropertyBag, (void **)&pPropBag); 490 ok_long(hr, HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)); 491 492 // Create new registry key 493 RegDeleteKeyW(hKey, L"PropBagTest"); 494 hr = SHCreatePropertyBagOnRegKey(hKey, L"PropBagTest", STGM_CREATE | STGM_READWRITE, 495 IID_IPropertyBag, (void **)&pPropBag); 496 if (FAILED(hr)) 497 { 498 skip("SHCreatePropertyBagOnRegKey FAILED\n"); 499 RegCloseKey(hKey); 500 return; 501 } 502 503 // Write UI4 504 VariantInit(&vari); 505 V_VT(&vari) = VT_UI4; 506 V_UI4(&vari) = 0xDEADFACE; 507 hr = pPropBag->Write(L"Name1", &vari); 508 ok_long(hr, S_OK); 509 VariantClear(&vari); 510 511 // Read UI4 512 VariantInit(&vari); 513 hr = pPropBag->Read(L"Name1", &vari, NULL); 514 ok_long(hr, S_OK); 515 ok_long(V_VT(&vari), VT_UI4); 516 ok_long(V_UI4(&vari), 0xDEADFACE); 517 VariantClear(&vari); 518 519 // Write BSTR 520 VariantInit(&vari); 521 V_VT(&vari) = VT_BSTR; 522 V_BSTR(&vari) = SysAllocString(L"StrValue"); 523 hr = pPropBag->Write(L"Name2", &vari); 524 ok_long(hr, S_OK); 525 VariantClear(&vari); 526 527 // Read BSTR 528 VariantInit(&vari); 529 V_VT(&vari) = VT_BSTR; 530 hr = pPropBag->Read(L"Name2", &vari, NULL); 531 ok_long(hr, S_OK); 532 ok_long(V_VT(&vari), VT_BSTR); 533 ok_wstr(V_BSTR(&vari), L"StrValue"); 534 VariantClear(&vari); 535 536 // Write GUID 537 VariantInit(&vari); 538 V_VT(&vari) = VT_UNKNOWN; 539 V_UNKNOWN(&vari) = SHCreateMemStream((BYTE*)&IID_IShellLinkW, sizeof(IID_IShellLinkW)); 540 hr = pPropBag->Write(L"Name4", &vari); 541 ok_long(hr, S_OK); 542 VariantClear(&vari); 543 544 // Read GUID 545 VariantInit(&vari); 546 V_VT(&vari) = VT_EMPTY; 547 hr = pPropBag->Read(L"Name4", &vari, NULL); 548 if (IsWindowsVistaOrGreater()) 549 { 550 ok_long(hr, S_OK); 551 ok_long(V_VT(&vari), VT_UNKNOWN); 552 pStream = (IStream*)V_UNKNOWN(&vari); 553 FillMemory(&guid, sizeof(guid), 0xEE); 554 hr = pStream->Read(&guid, sizeof(guid), NULL); 555 ok_long(hr, S_OK); 556 ok_int(::IsEqualGUID(guid, IID_IShellLinkW), TRUE); 557 } 558 else // XP/2k3 Read is buggy 559 { 560 ok_long(hr, E_FAIL); 561 ok_long(V_VT(&vari), VT_EMPTY); 562 } 563 VariantClear(&vari); 564 565 pPropBag->Release(); 566 567 // Check registry 568 error = RegOpenKeyExW(hKey, L"PropBagTest", 0, KEY_READ, &hSubKey); 569 ok_long(error, ERROR_SUCCESS); 570 DWORD dwType, dwValue, cbValue = sizeof(dwValue); 571 error = RegQueryValueExW(hSubKey, L"Name1", NULL, &dwType, (BYTE*)&dwValue, &cbValue); 572 ok_long(error, ERROR_SUCCESS); 573 ok_long(dwType, REG_DWORD); 574 ok_long(dwValue, 0xDEADFACE); 575 ok_long(cbValue, sizeof(DWORD)); 576 cbValue = sizeof(szText); 577 error = RegQueryValueExW(hSubKey, L"Name2", NULL, &dwType, (BYTE*)szText, &cbValue); 578 ok_long(error, ERROR_SUCCESS); 579 ok_long(dwType, REG_SZ); 580 ok_wstr(szText, L"StrValue"); 581 cbValue = sizeof(guid_and_extra); 582 error = RegQueryValueExW(hSubKey, L"Name4", NULL, &dwType, (BYTE*)&guid_and_extra, &cbValue); 583 ok_long(error, ERROR_SUCCESS); 584 ok_long(dwType, REG_BINARY); 585 ok_int(memcmp(&guid_and_extra, &GUID_NULL, sizeof(GUID)), 0); 586 ok_int(memcmp(&guid_and_extra[sizeof(GUID)], &IID_IShellLinkW, sizeof(GUID)), 0); 587 RegCloseKey(hSubKey); 588 589 // Create as read-only 590 hr = SHCreatePropertyBagOnRegKey(hKey, L"PropBagTest", STGM_READ, 591 IID_IPropertyBag, (void **)&pPropBag); 592 ok_long(hr, S_OK); 593 594 // Read UI4 595 VariantInit(&vari); 596 hr = pPropBag->Read(L"Name1", &vari, NULL); 597 ok_long(hr, S_OK); 598 ok_long(V_VT(&vari), VT_UI4); 599 ok_long(V_UI4(&vari), 0xDEADFACE); 600 VariantClear(&vari); 601 602 // Write UI4 603 VariantInit(&vari); 604 V_VT(&vari) = VT_UI4; 605 V_UI4(&vari) = 0xDEADFACE; 606 hr = pPropBag->Write(L"Name1", &vari); 607 ok_long(hr, E_ACCESSDENIED); 608 VariantClear(&vari); 609 610 pPropBag->Release(); 611 612 // Create as write-only IPropertyBag2 613 hr = SHCreatePropertyBagOnRegKey(hKey, L"PropBagTest", STGM_WRITE, 614 IID_IPropertyBag2, (void **)&pPropBag); 615 ok_long(hr, S_OK); 616 617 // Write UI4 618 VariantInit(&vari); 619 V_VT(&vari) = VT_UI4; 620 V_UI4(&vari) = 0xDEADFACE; 621 hr = pPropBag->Write(L"Name3", &vari); 622 ok_long(hr, E_NOTIMPL); 623 VariantClear(&vari); 624 625 // Read UI4 626 VariantInit(&vari); 627 V_UI4(&vari) = 0xFEEDF00D; 628 hr = pPropBag->Read(L"Name3", &vari, NULL); 629 ok_long(hr, E_NOTIMPL); 630 ok_int(V_VT(&vari), VT_EMPTY); 631 ok_long(V_UI4(&vari), 0xFEEDF00D); 632 VariantClear(&vari); 633 634 pPropBag->Release(); 635 636 // Clean up 637 RegDeleteKeyW(hKey, L"PropBagTest"); 638 RegCloseKey(hKey); 639 } 640 641 static void SHPropertyBag_SHSetIniStringW(void) 642 { 643 WCHAR szIniFile[MAX_PATH]; 644 WCHAR szValue[MAX_PATH]; 645 BOOL bRet; 646 DWORD dwRet; 647 648 ExpandEnvironmentStringsW(L"%TEMP%\\SHSetIniString.ini", szIniFile, _countof(szIniFile)); 649 650 DeleteFileW(szIniFile); 651 652 trace("%ls\n", szIniFile); 653 654 bRet = SHSetIniStringW(L"TestSection", L"Key", L"Value", szIniFile); 655 ok_int(bRet, TRUE); 656 657 WritePrivateProfileStringW(NULL, NULL, NULL, szIniFile); 658 659 dwRet = SHGetIniStringW(L"TestSection", L"Key", szValue, _countof(szValue), szIniFile); 660 ok_long(dwRet, 5); 661 ok_wstr(szValue, L"Value"); 662 663 bRet = SHSetIniStringW(L"TestSection", L"Key", NULL, szIniFile); 664 ok_int(bRet, TRUE); 665 666 WritePrivateProfileStringW(NULL, NULL, NULL, szIniFile); 667 668 dwRet = SHGetIniStringW(L"TestSection", L"Key", szValue, _countof(szValue), szIniFile); 669 ok_long(dwRet, 0); 670 ok_wstr(szValue, L""); 671 672 bRet = SHSetIniStringW(L"TestSection", L"Key", L"ABC\x3042\x3044\x3046\x2665", szIniFile); 673 ok_int(bRet, TRUE); 674 675 WritePrivateProfileStringW(NULL, NULL, NULL, szIniFile); 676 677 dwRet = SHGetIniStringW(L"TestSection", L"Key", szValue, _countof(szValue), szIniFile); 678 ok_long(dwRet, 7); 679 ok_wstr(szValue, L"ABC\x3042\x3044\x3046\x2665"); 680 681 szValue[0] = 0x3000; 682 szValue[1] = UNICODE_NULL; 683 dwRet = SHGetIniStringW(L"TestSection", L"NotExistentKey", szValue, _countof(szValue), szIniFile); 684 ok_long(dwRet, 0); 685 ok_wstr(szValue, L""); 686 687 DeleteFileW(szIniFile); 688 } 689 690 START_TEST(SHPropertyBag) 691 { 692 SHPropertyBag_ReadTest(); 693 SHPropertyBag_WriteTest(); 694 SHPropertyBag_OnMemory(); 695 SHPropertyBag_OnRegKey(); 696 SHPropertyBag_SHSetIniStringW(); 697 } 698