1 /* 2 * Copyright 2002 Mike McCormack for CodeWeavers 3 * Copyright 2004-2006 Juan Lang 4 * 5 * This library is free software; you can redistribute it and/or 6 * modify it under the terms of the GNU Lesser General Public 7 * License as published by the Free Software Foundation; either 8 * version 2.1 of the License, or (at your option) any later version. 9 * 10 * This library is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 * Lesser General Public License for more details. 14 * 15 * You should have received a copy of the GNU Lesser General Public 16 * License along with this library; if not, write to the Free Software 17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 18 * 19 * FIXME: 20 * - The concept of physical stores and locations isn't implemented. (This 21 * doesn't mean registry stores et al aren't implemented. See the PSDK for 22 * registering and enumerating physical stores and locations.) 23 * - Many flags, options and whatnot are unimplemented. 24 */ 25 26 #include "config.h" 27 #include "wine/port.h" 28 29 #include <assert.h> 30 #include <stdarg.h> 31 #include "windef.h" 32 #include "winbase.h" 33 #include "winnls.h" 34 #include "winreg.h" 35 #include "winuser.h" 36 #include "wincrypt.h" 37 #include "wine/debug.h" 38 #include "wine/exception.h" 39 #include "crypt32_private.h" 40 41 WINE_DEFAULT_DEBUG_CHANNEL(crypt); 42 43 static const WINE_CONTEXT_INTERFACE gCertInterface = { 44 (CreateContextFunc)CertCreateCertificateContext, 45 (AddContextToStoreFunc)CertAddCertificateContextToStore, 46 (AddEncodedContextToStoreFunc)CertAddEncodedCertificateToStore, 47 (EnumContextsInStoreFunc)CertEnumCertificatesInStore, 48 (EnumPropertiesFunc)CertEnumCertificateContextProperties, 49 (GetContextPropertyFunc)CertGetCertificateContextProperty, 50 (SetContextPropertyFunc)CertSetCertificateContextProperty, 51 (SerializeElementFunc)CertSerializeCertificateStoreElement, 52 (DeleteContextFunc)CertDeleteCertificateFromStore, 53 }; 54 const WINE_CONTEXT_INTERFACE *pCertInterface = &gCertInterface; 55 56 static const WINE_CONTEXT_INTERFACE gCRLInterface = { 57 (CreateContextFunc)CertCreateCRLContext, 58 (AddContextToStoreFunc)CertAddCRLContextToStore, 59 (AddEncodedContextToStoreFunc)CertAddEncodedCRLToStore, 60 (EnumContextsInStoreFunc)CertEnumCRLsInStore, 61 (EnumPropertiesFunc)CertEnumCRLContextProperties, 62 (GetContextPropertyFunc)CertGetCRLContextProperty, 63 (SetContextPropertyFunc)CertSetCRLContextProperty, 64 (SerializeElementFunc)CertSerializeCRLStoreElement, 65 (DeleteContextFunc)CertDeleteCRLFromStore, 66 }; 67 const WINE_CONTEXT_INTERFACE *pCRLInterface = &gCRLInterface; 68 69 static const WINE_CONTEXT_INTERFACE gCTLInterface = { 70 (CreateContextFunc)CertCreateCTLContext, 71 (AddContextToStoreFunc)CertAddCTLContextToStore, 72 (AddEncodedContextToStoreFunc)CertAddEncodedCTLToStore, 73 (EnumContextsInStoreFunc)CertEnumCTLsInStore, 74 (EnumPropertiesFunc)CertEnumCTLContextProperties, 75 (GetContextPropertyFunc)CertGetCTLContextProperty, 76 (SetContextPropertyFunc)CertSetCTLContextProperty, 77 (SerializeElementFunc)CertSerializeCTLStoreElement, 78 (DeleteContextFunc)CertDeleteCTLFromStore, 79 }; 80 const WINE_CONTEXT_INTERFACE *pCTLInterface = &gCTLInterface; 81 82 typedef struct _WINE_MEMSTORE 83 { 84 WINECRYPT_CERTSTORE hdr; 85 CRITICAL_SECTION cs; 86 struct list certs; 87 struct list crls; 88 struct list ctls; 89 } WINE_MEMSTORE; 90 91 void CRYPT_InitStore(WINECRYPT_CERTSTORE *store, DWORD dwFlags, CertStoreType type, const store_vtbl_t *vtbl) 92 { 93 store->ref = 1; 94 store->dwMagic = WINE_CRYPTCERTSTORE_MAGIC; 95 store->type = type; 96 store->dwOpenFlags = dwFlags; 97 store->vtbl = vtbl; 98 store->properties = NULL; 99 } 100 101 void CRYPT_FreeStore(WINECRYPT_CERTSTORE *store) 102 { 103 if (store->properties) 104 ContextPropertyList_Free(store->properties); 105 store->dwMagic = 0; 106 CryptMemFree(store); 107 } 108 109 BOOL WINAPI I_CertUpdateStore(HCERTSTORE store1, HCERTSTORE store2, DWORD unk0, 110 DWORD unk1) 111 { 112 static BOOL warned = FALSE; 113 const WINE_CONTEXT_INTERFACE * const interfaces[] = { pCertInterface, 114 pCRLInterface, pCTLInterface }; 115 DWORD i; 116 117 TRACE("(%p, %p, %08x, %08x)\n", store1, store2, unk0, unk1); 118 if (!warned) 119 { 120 FIXME("semi-stub\n"); 121 warned = TRUE; 122 } 123 124 /* Poor-man's resync: empty first store, then add everything from second 125 * store to it. 126 */ 127 for (i = 0; i < ARRAY_SIZE(interfaces); i++) 128 { 129 const void *context; 130 131 do { 132 context = interfaces[i]->enumContextsInStore(store1, NULL); 133 if (context) 134 interfaces[i]->deleteFromStore(context); 135 } while (context); 136 do { 137 context = interfaces[i]->enumContextsInStore(store2, context); 138 if (context) 139 interfaces[i]->addContextToStore(store1, context, 140 CERT_STORE_ADD_ALWAYS, NULL); 141 } while (context); 142 } 143 return TRUE; 144 } 145 146 static BOOL MemStore_addContext(WINE_MEMSTORE *store, struct list *list, context_t *orig_context, 147 context_t *existing, context_t **ret_context, BOOL use_link) 148 { 149 context_t *context; 150 151 context = orig_context->vtbl->clone(orig_context, &store->hdr, use_link); 152 if (!context) 153 return FALSE; 154 155 TRACE("adding %p\n", context); 156 EnterCriticalSection(&store->cs); 157 if (existing) { 158 context->u.entry.prev = existing->u.entry.prev; 159 context->u.entry.next = existing->u.entry.next; 160 context->u.entry.prev->next = &context->u.entry; 161 context->u.entry.next->prev = &context->u.entry; 162 list_init(&existing->u.entry); 163 if(!existing->ref) 164 Context_Release(existing); 165 }else { 166 list_add_head(list, &context->u.entry); 167 } 168 LeaveCriticalSection(&store->cs); 169 170 if(ret_context) 171 *ret_context = context; 172 else 173 Context_Release(context); 174 return TRUE; 175 } 176 177 static context_t *MemStore_enumContext(WINE_MEMSTORE *store, struct list *list, context_t *prev) 178 { 179 struct list *next; 180 context_t *ret; 181 182 EnterCriticalSection(&store->cs); 183 if (prev) { 184 next = list_next(list, &prev->u.entry); 185 Context_Release(prev); 186 }else { 187 next = list_next(list, list); 188 } 189 LeaveCriticalSection(&store->cs); 190 191 if (!next) { 192 SetLastError(CRYPT_E_NOT_FOUND); 193 return NULL; 194 } 195 196 ret = LIST_ENTRY(next, context_t, u.entry); 197 Context_AddRef(ret); 198 return ret; 199 } 200 201 static BOOL MemStore_deleteContext(WINE_MEMSTORE *store, context_t *context) 202 { 203 BOOL in_list = FALSE; 204 205 EnterCriticalSection(&store->cs); 206 if (!list_empty(&context->u.entry)) { 207 list_remove(&context->u.entry); 208 list_init(&context->u.entry); 209 in_list = TRUE; 210 } 211 LeaveCriticalSection(&store->cs); 212 213 if(in_list && !context->ref) 214 Context_Free(context); 215 return TRUE; 216 } 217 218 static void free_contexts(struct list *list) 219 { 220 context_t *context, *next; 221 222 LIST_FOR_EACH_ENTRY_SAFE(context, next, list, context_t, u.entry) 223 { 224 TRACE("freeing %p\n", context); 225 list_remove(&context->u.entry); 226 Context_Free(context); 227 } 228 } 229 230 static void MemStore_releaseContext(WINECRYPT_CERTSTORE *store, context_t *context) 231 { 232 /* Free the context only if it's not in a list. Otherwise it may be reused later. */ 233 if(list_empty(&context->u.entry)) 234 Context_Free(context); 235 } 236 237 static BOOL MemStore_addCert(WINECRYPT_CERTSTORE *store, context_t *cert, 238 context_t *toReplace, context_t **ppStoreContext, BOOL use_link) 239 { 240 WINE_MEMSTORE *ms = (WINE_MEMSTORE *)store; 241 242 TRACE("(%p, %p, %p, %p)\n", store, cert, toReplace, ppStoreContext); 243 return MemStore_addContext(ms, &ms->certs, cert, toReplace, ppStoreContext, use_link); 244 } 245 246 static context_t *MemStore_enumCert(WINECRYPT_CERTSTORE *store, context_t *prev) 247 { 248 WINE_MEMSTORE *ms = (WINE_MEMSTORE *)store; 249 250 TRACE("(%p, %p)\n", store, prev); 251 252 return MemStore_enumContext(ms, &ms->certs, prev); 253 } 254 255 static BOOL MemStore_deleteCert(WINECRYPT_CERTSTORE *store, context_t *context) 256 { 257 WINE_MEMSTORE *ms = (WINE_MEMSTORE *)store; 258 259 TRACE("(%p, %p)\n", store, context); 260 261 return MemStore_deleteContext(ms, context); 262 } 263 264 static BOOL MemStore_addCRL(WINECRYPT_CERTSTORE *store, context_t *crl, 265 context_t *toReplace, context_t **ppStoreContext, BOOL use_link) 266 { 267 WINE_MEMSTORE *ms = (WINE_MEMSTORE *)store; 268 269 TRACE("(%p, %p, %p, %p)\n", store, crl, toReplace, ppStoreContext); 270 271 return MemStore_addContext(ms, &ms->crls, crl, toReplace, ppStoreContext, use_link); 272 } 273 274 static context_t *MemStore_enumCRL(WINECRYPT_CERTSTORE *store, context_t *prev) 275 { 276 WINE_MEMSTORE *ms = (WINE_MEMSTORE *)store; 277 278 TRACE("(%p, %p)\n", store, prev); 279 280 return MemStore_enumContext(ms, &ms->crls, prev); 281 } 282 283 static BOOL MemStore_deleteCRL(WINECRYPT_CERTSTORE *store, context_t *context) 284 { 285 WINE_MEMSTORE *ms = (WINE_MEMSTORE *)store; 286 287 TRACE("(%p, %p)\n", store, context); 288 289 return MemStore_deleteContext(ms, context); 290 } 291 292 static BOOL MemStore_addCTL(WINECRYPT_CERTSTORE *store, context_t *ctl, 293 context_t *toReplace, context_t **ppStoreContext, BOOL use_link) 294 { 295 WINE_MEMSTORE *ms = (WINE_MEMSTORE *)store; 296 297 TRACE("(%p, %p, %p, %p)\n", store, ctl, toReplace, ppStoreContext); 298 299 return MemStore_addContext(ms, &ms->ctls, ctl, toReplace, ppStoreContext, use_link); 300 } 301 302 static context_t *MemStore_enumCTL(WINECRYPT_CERTSTORE *store, context_t *prev) 303 { 304 WINE_MEMSTORE *ms = (WINE_MEMSTORE *)store; 305 306 TRACE("(%p, %p)\n", store, prev); 307 308 return MemStore_enumContext(ms, &ms->ctls, prev); 309 } 310 311 static BOOL MemStore_deleteCTL(WINECRYPT_CERTSTORE *store, context_t *context) 312 { 313 WINE_MEMSTORE *ms = (WINE_MEMSTORE *)store; 314 315 TRACE("(%p, %p)\n", store, context); 316 317 return MemStore_deleteContext(ms, context); 318 } 319 320 static void MemStore_addref(WINECRYPT_CERTSTORE *store) 321 { 322 LONG ref = InterlockedIncrement(&store->ref); 323 TRACE("ref = %d\n", ref); 324 } 325 326 static DWORD MemStore_release(WINECRYPT_CERTSTORE *cert_store, DWORD flags) 327 { 328 WINE_MEMSTORE *store = (WINE_MEMSTORE*)cert_store; 329 LONG ref; 330 331 if(flags & ~CERT_CLOSE_STORE_CHECK_FLAG) 332 FIXME("Unimplemented flags %x\n", flags); 333 334 ref = InterlockedDecrement(&store->hdr.ref); 335 TRACE("(%p) ref=%d\n", store, ref); 336 if(ref) 337 return (flags & CERT_CLOSE_STORE_CHECK_FLAG) ? CRYPT_E_PENDING_CLOSE : ERROR_SUCCESS; 338 339 free_contexts(&store->certs); 340 free_contexts(&store->crls); 341 free_contexts(&store->ctls); 342 store->cs.DebugInfo->Spare[0] = 0; 343 DeleteCriticalSection(&store->cs); 344 CRYPT_FreeStore(&store->hdr); 345 return ERROR_SUCCESS; 346 } 347 348 static BOOL MemStore_control(WINECRYPT_CERTSTORE *store, DWORD dwFlags, 349 DWORD dwCtrlType, void const *pvCtrlPara) 350 { 351 SetLastError(ERROR_CALL_NOT_IMPLEMENTED); 352 return FALSE; 353 } 354 355 static const store_vtbl_t MemStoreVtbl = { 356 MemStore_addref, 357 MemStore_release, 358 MemStore_releaseContext, 359 MemStore_control, 360 { 361 MemStore_addCert, 362 MemStore_enumCert, 363 MemStore_deleteCert 364 }, { 365 MemStore_addCRL, 366 MemStore_enumCRL, 367 MemStore_deleteCRL 368 }, { 369 MemStore_addCTL, 370 MemStore_enumCTL, 371 MemStore_deleteCTL 372 } 373 }; 374 375 static WINECRYPT_CERTSTORE *CRYPT_MemOpenStore(HCRYPTPROV hCryptProv, 376 DWORD dwFlags, const void *pvPara) 377 { 378 WINE_MEMSTORE *store; 379 380 TRACE("(%ld, %08x, %p)\n", hCryptProv, dwFlags, pvPara); 381 382 if (dwFlags & CERT_STORE_DELETE_FLAG) 383 { 384 SetLastError(ERROR_CALL_NOT_IMPLEMENTED); 385 store = NULL; 386 } 387 else 388 { 389 store = CryptMemAlloc(sizeof(WINE_MEMSTORE)); 390 if (store) 391 { 392 memset(store, 0, sizeof(WINE_MEMSTORE)); 393 CRYPT_InitStore(&store->hdr, dwFlags, StoreTypeMem, &MemStoreVtbl); 394 InitializeCriticalSection(&store->cs); 395 store->cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": ContextList.cs"); 396 list_init(&store->certs); 397 list_init(&store->crls); 398 list_init(&store->ctls); 399 /* Mem store doesn't need crypto provider, so close it */ 400 if (hCryptProv && !(dwFlags & CERT_STORE_NO_CRYPT_RELEASE_FLAG)) 401 CryptReleaseContext(hCryptProv, 0); 402 } 403 } 404 return (WINECRYPT_CERTSTORE*)store; 405 } 406 407 static const WCHAR rootW[] = { 'R','o','o','t',0 }; 408 409 static WINECRYPT_CERTSTORE *CRYPT_SysRegOpenStoreW(HCRYPTPROV hCryptProv, 410 DWORD dwFlags, const void *pvPara) 411 { 412 static const WCHAR fmt[] = { '%','s','\\','%','s',0 }; 413 LPCWSTR storeName = pvPara; 414 LPWSTR storePath; 415 WINECRYPT_CERTSTORE *store = NULL; 416 HKEY root; 417 LPCWSTR base; 418 419 TRACE("(%ld, %08x, %s)\n", hCryptProv, dwFlags, 420 debugstr_w(pvPara)); 421 422 if (!pvPara) 423 { 424 SetLastError(E_INVALIDARG); 425 return NULL; 426 } 427 428 switch (dwFlags & CERT_SYSTEM_STORE_LOCATION_MASK) 429 { 430 case CERT_SYSTEM_STORE_LOCAL_MACHINE: 431 root = HKEY_LOCAL_MACHINE; 432 base = CERT_LOCAL_MACHINE_SYSTEM_STORE_REGPATH; 433 /* If the HKLM\Root certs are requested, expressing system certs into the registry */ 434 if (!lstrcmpiW(storeName, rootW)) 435 CRYPT_ImportSystemRootCertsToReg(); 436 break; 437 case CERT_SYSTEM_STORE_CURRENT_USER: 438 root = HKEY_CURRENT_USER; 439 base = CERT_LOCAL_MACHINE_SYSTEM_STORE_REGPATH; 440 break; 441 case CERT_SYSTEM_STORE_CURRENT_SERVICE: 442 /* hklm\Software\Microsoft\Cryptography\Services\servicename\ 443 * SystemCertificates 444 */ 445 FIXME("CERT_SYSTEM_STORE_CURRENT_SERVICE, %s: stub\n", 446 debugstr_w(storeName)); 447 return NULL; 448 case CERT_SYSTEM_STORE_SERVICES: 449 /* hklm\Software\Microsoft\Cryptography\Services\servicename\ 450 * SystemCertificates 451 */ 452 FIXME("CERT_SYSTEM_STORE_SERVICES, %s: stub\n", 453 debugstr_w(storeName)); 454 return NULL; 455 case CERT_SYSTEM_STORE_USERS: 456 /* hku\user sid\Software\Microsoft\SystemCertificates */ 457 FIXME("CERT_SYSTEM_STORE_USERS, %s: stub\n", 458 debugstr_w(storeName)); 459 return NULL; 460 case CERT_SYSTEM_STORE_CURRENT_USER_GROUP_POLICY: 461 root = HKEY_CURRENT_USER; 462 base = CERT_GROUP_POLICY_SYSTEM_STORE_REGPATH; 463 break; 464 case CERT_SYSTEM_STORE_LOCAL_MACHINE_GROUP_POLICY: 465 root = HKEY_LOCAL_MACHINE; 466 base = CERT_GROUP_POLICY_SYSTEM_STORE_REGPATH; 467 break; 468 case CERT_SYSTEM_STORE_LOCAL_MACHINE_ENTERPRISE: 469 /* hklm\Software\Microsoft\EnterpriseCertificates */ 470 FIXME("CERT_SYSTEM_STORE_LOCAL_MACHINE_ENTERPRISE, %s: stub\n", 471 debugstr_w(storeName)); 472 return NULL; 473 default: 474 SetLastError(E_INVALIDARG); 475 return NULL; 476 } 477 478 storePath = CryptMemAlloc((lstrlenW(base) + lstrlenW(storeName) + 2) * 479 sizeof(WCHAR)); 480 if (storePath) 481 { 482 LONG rc; 483 HKEY key; 484 REGSAM sam = dwFlags & CERT_STORE_READONLY_FLAG ? KEY_READ : 485 KEY_ALL_ACCESS; 486 487 wsprintfW(storePath, fmt, base, storeName); 488 if (dwFlags & CERT_STORE_OPEN_EXISTING_FLAG) 489 rc = RegOpenKeyExW(root, storePath, 0, sam, &key); 490 else 491 { 492 DWORD disp; 493 494 rc = RegCreateKeyExW(root, storePath, 0, NULL, 0, sam, NULL, 495 &key, &disp); 496 if (!rc && dwFlags & CERT_STORE_CREATE_NEW_FLAG && 497 disp == REG_OPENED_EXISTING_KEY) 498 { 499 RegCloseKey(key); 500 rc = ERROR_FILE_EXISTS; 501 } 502 } 503 if (!rc) 504 { 505 store = CRYPT_RegOpenStore(hCryptProv, dwFlags, key); 506 RegCloseKey(key); 507 } 508 else 509 SetLastError(rc); 510 CryptMemFree(storePath); 511 } 512 return store; 513 } 514 515 static WINECRYPT_CERTSTORE *CRYPT_SysRegOpenStoreA(HCRYPTPROV hCryptProv, 516 DWORD dwFlags, const void *pvPara) 517 { 518 int len; 519 WINECRYPT_CERTSTORE *ret = NULL; 520 521 TRACE("(%ld, %08x, %s)\n", hCryptProv, dwFlags, 522 debugstr_a(pvPara)); 523 524 if (!pvPara) 525 { 526 SetLastError(ERROR_FILE_NOT_FOUND); 527 return NULL; 528 } 529 len = MultiByteToWideChar(CP_ACP, 0, pvPara, -1, NULL, 0); 530 if (len) 531 { 532 LPWSTR storeName = CryptMemAlloc(len * sizeof(WCHAR)); 533 534 if (storeName) 535 { 536 MultiByteToWideChar(CP_ACP, 0, pvPara, -1, storeName, len); 537 ret = CRYPT_SysRegOpenStoreW(hCryptProv, dwFlags, storeName); 538 CryptMemFree(storeName); 539 } 540 } 541 return ret; 542 } 543 544 static WINECRYPT_CERTSTORE *CRYPT_SysOpenStoreW(HCRYPTPROV hCryptProv, 545 DWORD dwFlags, const void *pvPara) 546 { 547 HCERTSTORE store = 0; 548 BOOL ret; 549 550 TRACE("(%ld, %08x, %s)\n", hCryptProv, dwFlags, 551 debugstr_w(pvPara)); 552 553 if (!pvPara) 554 { 555 SetLastError(ERROR_FILE_NOT_FOUND); 556 return NULL; 557 } 558 /* This returns a different error than system registry stores if the 559 * location is invalid. 560 */ 561 switch (dwFlags & CERT_SYSTEM_STORE_LOCATION_MASK) 562 { 563 case CERT_SYSTEM_STORE_LOCAL_MACHINE: 564 case CERT_SYSTEM_STORE_CURRENT_USER: 565 case CERT_SYSTEM_STORE_CURRENT_SERVICE: 566 case CERT_SYSTEM_STORE_SERVICES: 567 case CERT_SYSTEM_STORE_USERS: 568 case CERT_SYSTEM_STORE_CURRENT_USER_GROUP_POLICY: 569 case CERT_SYSTEM_STORE_LOCAL_MACHINE_GROUP_POLICY: 570 case CERT_SYSTEM_STORE_LOCAL_MACHINE_ENTERPRISE: 571 ret = TRUE; 572 break; 573 default: 574 SetLastError(ERROR_FILE_NOT_FOUND); 575 ret = FALSE; 576 } 577 if (ret) 578 { 579 HCERTSTORE regStore = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY_W, 580 0, 0, dwFlags, pvPara); 581 582 if (regStore) 583 { 584 store = CertOpenStore(CERT_STORE_PROV_COLLECTION, 0, 0, 585 CERT_STORE_CREATE_NEW_FLAG, NULL); 586 CertAddStoreToCollection(store, regStore, 587 dwFlags & CERT_STORE_READONLY_FLAG ? 0 : 588 CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0); 589 CertCloseStore(regStore, 0); 590 /* CERT_SYSTEM_STORE_CURRENT_USER returns both the HKCU and HKLM 591 * stores. 592 */ 593 if ((dwFlags & CERT_SYSTEM_STORE_LOCATION_MASK) == 594 CERT_SYSTEM_STORE_CURRENT_USER) 595 { 596 dwFlags &= ~CERT_SYSTEM_STORE_CURRENT_USER; 597 dwFlags |= CERT_SYSTEM_STORE_LOCAL_MACHINE; 598 regStore = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY_W, 0, 599 0, dwFlags, pvPara); 600 if (regStore) 601 { 602 CertAddStoreToCollection(store, regStore, 603 dwFlags & CERT_STORE_READONLY_FLAG ? 0 : 604 CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0); 605 CertCloseStore(regStore, 0); 606 } 607 } 608 /* System store doesn't need crypto provider, so close it */ 609 if (hCryptProv && !(dwFlags & CERT_STORE_NO_CRYPT_RELEASE_FLAG)) 610 CryptReleaseContext(hCryptProv, 0); 611 } 612 } 613 return store; 614 } 615 616 static WINECRYPT_CERTSTORE *CRYPT_SysOpenStoreA(HCRYPTPROV hCryptProv, 617 DWORD dwFlags, const void *pvPara) 618 { 619 int len; 620 WINECRYPT_CERTSTORE *ret = NULL; 621 622 TRACE("(%ld, %08x, %s)\n", hCryptProv, dwFlags, 623 debugstr_a(pvPara)); 624 625 if (!pvPara) 626 { 627 SetLastError(ERROR_FILE_NOT_FOUND); 628 return NULL; 629 } 630 len = MultiByteToWideChar(CP_ACP, 0, pvPara, -1, NULL, 0); 631 if (len) 632 { 633 LPWSTR storeName = CryptMemAlloc(len * sizeof(WCHAR)); 634 635 if (storeName) 636 { 637 MultiByteToWideChar(CP_ACP, 0, pvPara, -1, storeName, len); 638 ret = CRYPT_SysOpenStoreW(hCryptProv, dwFlags, storeName); 639 CryptMemFree(storeName); 640 } 641 } 642 return ret; 643 } 644 645 static void WINAPI CRYPT_MsgCloseStore(HCERTSTORE hCertStore, DWORD dwFlags) 646 { 647 HCRYPTMSG msg = hCertStore; 648 649 TRACE("(%p, %08x)\n", msg, dwFlags); 650 CryptMsgClose(msg); 651 } 652 653 static void *msgProvFuncs[] = { 654 CRYPT_MsgCloseStore, 655 }; 656 657 static WINECRYPT_CERTSTORE *CRYPT_MsgOpenStore(HCRYPTPROV hCryptProv, 658 DWORD dwFlags, const void *pvPara) 659 { 660 WINECRYPT_CERTSTORE *store = NULL; 661 HCRYPTMSG msg = (HCRYPTMSG)pvPara; 662 WINECRYPT_CERTSTORE *memStore; 663 664 TRACE("(%ld, %08x, %p)\n", hCryptProv, dwFlags, pvPara); 665 666 memStore = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0, 667 CERT_STORE_CREATE_NEW_FLAG, NULL); 668 if (memStore) 669 { 670 BOOL ret; 671 DWORD size, count, i; 672 673 size = sizeof(count); 674 ret = CryptMsgGetParam(msg, CMSG_CERT_COUNT_PARAM, 0, &count, &size); 675 for (i = 0; ret && i < count; i++) 676 { 677 size = 0; 678 ret = CryptMsgGetParam(msg, CMSG_CERT_PARAM, i, NULL, &size); 679 if (ret) 680 { 681 LPBYTE buf = CryptMemAlloc(size); 682 683 if (buf) 684 { 685 ret = CryptMsgGetParam(msg, CMSG_CERT_PARAM, i, buf, &size); 686 if (ret) 687 ret = CertAddEncodedCertificateToStore(memStore, 688 X509_ASN_ENCODING, buf, size, CERT_STORE_ADD_ALWAYS, 689 NULL); 690 CryptMemFree(buf); 691 } 692 } 693 } 694 size = sizeof(count); 695 ret = CryptMsgGetParam(msg, CMSG_CRL_COUNT_PARAM, 0, &count, &size); 696 for (i = 0; ret && i < count; i++) 697 { 698 size = 0; 699 ret = CryptMsgGetParam(msg, CMSG_CRL_PARAM, i, NULL, &size); 700 if (ret) 701 { 702 LPBYTE buf = CryptMemAlloc(size); 703 704 if (buf) 705 { 706 ret = CryptMsgGetParam(msg, CMSG_CRL_PARAM, i, buf, &size); 707 if (ret) 708 ret = CertAddEncodedCRLToStore(memStore, 709 X509_ASN_ENCODING, buf, size, CERT_STORE_ADD_ALWAYS, 710 NULL); 711 CryptMemFree(buf); 712 } 713 } 714 } 715 if (ret) 716 { 717 CERT_STORE_PROV_INFO provInfo = { 0 }; 718 719 provInfo.cbSize = sizeof(provInfo); 720 provInfo.cStoreProvFunc = ARRAY_SIZE(msgProvFuncs); 721 provInfo.rgpvStoreProvFunc = msgProvFuncs; 722 provInfo.hStoreProv = CryptMsgDuplicate(msg); 723 store = CRYPT_ProvCreateStore(dwFlags, memStore, &provInfo); 724 /* Msg store doesn't need crypto provider, so close it */ 725 if (hCryptProv && !(dwFlags & CERT_STORE_NO_CRYPT_RELEASE_FLAG)) 726 CryptReleaseContext(hCryptProv, 0); 727 } 728 else 729 CertCloseStore(memStore, 0); 730 } 731 TRACE("returning %p\n", store); 732 return store; 733 } 734 735 static WINECRYPT_CERTSTORE *CRYPT_PKCSOpenStore(HCRYPTPROV hCryptProv, 736 DWORD dwFlags, const void *pvPara) 737 { 738 HCRYPTMSG msg; 739 WINECRYPT_CERTSTORE *store = NULL; 740 const CRYPT_DATA_BLOB *data = pvPara; 741 BOOL ret; 742 DWORD msgOpenFlags = dwFlags & CERT_STORE_NO_CRYPT_RELEASE_FLAG ? 0 : 743 CMSG_CRYPT_RELEASE_CONTEXT_FLAG; 744 745 TRACE("(%ld, %08x, %p)\n", hCryptProv, dwFlags, pvPara); 746 747 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, msgOpenFlags, CMSG_SIGNED, 748 hCryptProv, NULL, NULL); 749 ret = CryptMsgUpdate(msg, data->pbData, data->cbData, TRUE); 750 if (!ret) 751 { 752 CryptMsgClose(msg); 753 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, msgOpenFlags, 0, 754 hCryptProv, NULL, NULL); 755 ret = CryptMsgUpdate(msg, data->pbData, data->cbData, TRUE); 756 if (ret) 757 { 758 DWORD type, size = sizeof(type); 759 760 /* Only signed messages are allowed, check type */ 761 ret = CryptMsgGetParam(msg, CMSG_TYPE_PARAM, 0, &type, &size); 762 if (ret && type != CMSG_SIGNED) 763 { 764 SetLastError(CRYPT_E_INVALID_MSG_TYPE); 765 ret = FALSE; 766 } 767 } 768 } 769 if (ret) 770 store = CRYPT_MsgOpenStore(0, dwFlags, msg); 771 CryptMsgClose(msg); 772 TRACE("returning %p\n", store); 773 return store; 774 } 775 776 static WINECRYPT_CERTSTORE *CRYPT_SerializedOpenStore(HCRYPTPROV hCryptProv, 777 DWORD dwFlags, const void *pvPara) 778 { 779 HCERTSTORE store; 780 const CRYPT_DATA_BLOB *data = pvPara; 781 782 TRACE("(%ld, %08x, %p)\n", hCryptProv, dwFlags, pvPara); 783 784 if (dwFlags & CERT_STORE_DELETE_FLAG) 785 { 786 SetLastError(ERROR_CALL_NOT_IMPLEMENTED); 787 return NULL; 788 } 789 790 store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0, 791 CERT_STORE_CREATE_NEW_FLAG, NULL); 792 if (store) 793 { 794 if (!CRYPT_ReadSerializedStoreFromBlob(data, store)) 795 { 796 CertCloseStore(store, 0); 797 store = NULL; 798 } 799 } 800 TRACE("returning %p\n", store); 801 return (WINECRYPT_CERTSTORE*)store; 802 } 803 804 static WINECRYPT_CERTSTORE *CRYPT_PhysOpenStoreW(HCRYPTPROV hCryptProv, 805 DWORD dwFlags, const void *pvPara) 806 { 807 if (dwFlags & CERT_SYSTEM_STORE_RELOCATE_FLAG) 808 FIXME("(%ld, %08x, %p): stub\n", hCryptProv, dwFlags, pvPara); 809 else 810 FIXME("(%ld, %08x, %s): stub\n", hCryptProv, dwFlags, 811 debugstr_w(pvPara)); 812 return NULL; 813 } 814 815 HCERTSTORE WINAPI CertOpenStore(LPCSTR lpszStoreProvider, 816 DWORD dwMsgAndCertEncodingType, HCRYPTPROV_LEGACY hCryptProv, DWORD dwFlags, 817 const void* pvPara) 818 { 819 WINECRYPT_CERTSTORE *hcs; 820 StoreOpenFunc openFunc = NULL; 821 822 TRACE("(%s, %08x, %08lx, %08x, %p)\n", debugstr_a(lpszStoreProvider), 823 dwMsgAndCertEncodingType, hCryptProv, dwFlags, pvPara); 824 825 if (IS_INTOID(lpszStoreProvider)) 826 { 827 switch (LOWORD(lpszStoreProvider)) 828 { 829 case LOWORD(CERT_STORE_PROV_MSG): 830 openFunc = CRYPT_MsgOpenStore; 831 break; 832 case LOWORD(CERT_STORE_PROV_MEMORY): 833 openFunc = CRYPT_MemOpenStore; 834 break; 835 case LOWORD(CERT_STORE_PROV_FILE): 836 openFunc = CRYPT_FileOpenStore; 837 break; 838 case LOWORD(CERT_STORE_PROV_PKCS7): 839 openFunc = CRYPT_PKCSOpenStore; 840 break; 841 case LOWORD(CERT_STORE_PROV_SERIALIZED): 842 openFunc = CRYPT_SerializedOpenStore; 843 break; 844 case LOWORD(CERT_STORE_PROV_REG): 845 openFunc = CRYPT_RegOpenStore; 846 break; 847 case LOWORD(CERT_STORE_PROV_FILENAME_A): 848 openFunc = CRYPT_FileNameOpenStoreA; 849 break; 850 case LOWORD(CERT_STORE_PROV_FILENAME_W): 851 openFunc = CRYPT_FileNameOpenStoreW; 852 break; 853 case LOWORD(CERT_STORE_PROV_COLLECTION): 854 openFunc = CRYPT_CollectionOpenStore; 855 break; 856 case LOWORD(CERT_STORE_PROV_SYSTEM_A): 857 openFunc = CRYPT_SysOpenStoreA; 858 break; 859 case LOWORD(CERT_STORE_PROV_SYSTEM_W): 860 openFunc = CRYPT_SysOpenStoreW; 861 break; 862 case LOWORD(CERT_STORE_PROV_SYSTEM_REGISTRY_A): 863 openFunc = CRYPT_SysRegOpenStoreA; 864 break; 865 case LOWORD(CERT_STORE_PROV_SYSTEM_REGISTRY_W): 866 openFunc = CRYPT_SysRegOpenStoreW; 867 break; 868 case LOWORD(CERT_STORE_PROV_PHYSICAL_W): 869 openFunc = CRYPT_PhysOpenStoreW; 870 break; 871 default: 872 if (LOWORD(lpszStoreProvider)) 873 FIXME("unimplemented type %d\n", LOWORD(lpszStoreProvider)); 874 } 875 } 876 else if (!strcasecmp(lpszStoreProvider, sz_CERT_STORE_PROV_MEMORY)) 877 openFunc = CRYPT_MemOpenStore; 878 else if (!strcasecmp(lpszStoreProvider, sz_CERT_STORE_PROV_FILENAME_W)) 879 openFunc = CRYPT_FileOpenStore; 880 else if (!strcasecmp(lpszStoreProvider, sz_CERT_STORE_PROV_SYSTEM)) 881 openFunc = CRYPT_SysOpenStoreW; 882 else if (!strcasecmp(lpszStoreProvider, sz_CERT_STORE_PROV_PKCS7)) 883 openFunc = CRYPT_PKCSOpenStore; 884 else if (!strcasecmp(lpszStoreProvider, sz_CERT_STORE_PROV_SERIALIZED)) 885 openFunc = CRYPT_SerializedOpenStore; 886 else if (!strcasecmp(lpszStoreProvider, sz_CERT_STORE_PROV_COLLECTION)) 887 openFunc = CRYPT_CollectionOpenStore; 888 else if (!strcasecmp(lpszStoreProvider, sz_CERT_STORE_PROV_SYSTEM_REGISTRY)) 889 openFunc = CRYPT_SysRegOpenStoreW; 890 else 891 { 892 FIXME("unimplemented type %s\n", lpszStoreProvider); 893 openFunc = NULL; 894 } 895 896 if (!openFunc) 897 hcs = CRYPT_ProvOpenStore(lpszStoreProvider, dwMsgAndCertEncodingType, 898 hCryptProv, dwFlags, pvPara); 899 else 900 hcs = openFunc(hCryptProv, dwFlags, pvPara); 901 return hcs; 902 } 903 904 HCERTSTORE WINAPI CertOpenSystemStoreA(HCRYPTPROV_LEGACY hProv, 905 LPCSTR szSubSystemProtocol) 906 { 907 if (!szSubSystemProtocol) 908 { 909 SetLastError(E_INVALIDARG); 910 return 0; 911 } 912 return CertOpenStore(CERT_STORE_PROV_SYSTEM_A, 0, hProv, 913 CERT_SYSTEM_STORE_CURRENT_USER, szSubSystemProtocol); 914 } 915 916 HCERTSTORE WINAPI CertOpenSystemStoreW(HCRYPTPROV_LEGACY hProv, 917 LPCWSTR szSubSystemProtocol) 918 { 919 if (!szSubSystemProtocol) 920 { 921 SetLastError(E_INVALIDARG); 922 return 0; 923 } 924 return CertOpenStore(CERT_STORE_PROV_SYSTEM_W, 0, hProv, 925 CERT_SYSTEM_STORE_CURRENT_USER, szSubSystemProtocol); 926 } 927 928 PCCERT_CONTEXT WINAPI CertEnumCertificatesInStore(HCERTSTORE hCertStore, PCCERT_CONTEXT pPrev) 929 { 930 cert_t *prev = pPrev ? cert_from_ptr(pPrev) : NULL, *ret; 931 WINECRYPT_CERTSTORE *hcs = hCertStore; 932 933 TRACE("(%p, %p)\n", hCertStore, pPrev); 934 if (!hCertStore) 935 ret = NULL; 936 else if (hcs->dwMagic != WINE_CRYPTCERTSTORE_MAGIC) 937 ret = NULL; 938 else 939 ret = (cert_t*)hcs->vtbl->certs.enumContext(hcs, prev ? &prev->base : NULL); 940 return ret ? &ret->ctx : NULL; 941 } 942 943 BOOL WINAPI CertDeleteCertificateFromStore(PCCERT_CONTEXT pCertContext) 944 { 945 WINECRYPT_CERTSTORE *hcs; 946 947 TRACE("(%p)\n", pCertContext); 948 949 if (!pCertContext) 950 return TRUE; 951 952 hcs = pCertContext->hCertStore; 953 954 if (hcs->dwMagic != WINE_CRYPTCERTSTORE_MAGIC) 955 return FALSE; 956 957 return hcs->vtbl->certs.delete(hcs, &cert_from_ptr(pCertContext)->base); 958 } 959 960 BOOL WINAPI CertAddCRLContextToStore(HCERTSTORE hCertStore, 961 PCCRL_CONTEXT pCrlContext, DWORD dwAddDisposition, 962 PCCRL_CONTEXT* ppStoreContext) 963 { 964 WINECRYPT_CERTSTORE *store = hCertStore; 965 BOOL ret = TRUE; 966 PCCRL_CONTEXT toAdd = NULL, existing = NULL; 967 968 TRACE("(%p, %p, %08x, %p)\n", hCertStore, pCrlContext, 969 dwAddDisposition, ppStoreContext); 970 971 /* Weird case to pass a test */ 972 if (dwAddDisposition == 0) 973 { 974 SetLastError(STATUS_ACCESS_VIOLATION); 975 return FALSE; 976 } 977 if (dwAddDisposition != CERT_STORE_ADD_ALWAYS) 978 { 979 existing = CertFindCRLInStore(hCertStore, 0, 0, CRL_FIND_EXISTING, 980 pCrlContext, NULL); 981 } 982 983 switch (dwAddDisposition) 984 { 985 case CERT_STORE_ADD_ALWAYS: 986 toAdd = CertDuplicateCRLContext(pCrlContext); 987 break; 988 case CERT_STORE_ADD_NEW: 989 if (existing) 990 { 991 TRACE("found matching CRL, not adding\n"); 992 SetLastError(CRYPT_E_EXISTS); 993 ret = FALSE; 994 } 995 else 996 toAdd = CertDuplicateCRLContext(pCrlContext); 997 break; 998 case CERT_STORE_ADD_NEWER: 999 if (existing) 1000 { 1001 LONG newer = CompareFileTime(&existing->pCrlInfo->ThisUpdate, 1002 &pCrlContext->pCrlInfo->ThisUpdate); 1003 1004 if (newer < 0) 1005 toAdd = CertDuplicateCRLContext(pCrlContext); 1006 else 1007 { 1008 TRACE("existing CRL is newer, not adding\n"); 1009 SetLastError(CRYPT_E_EXISTS); 1010 ret = FALSE; 1011 } 1012 } 1013 else 1014 toAdd = CertDuplicateCRLContext(pCrlContext); 1015 break; 1016 case CERT_STORE_ADD_NEWER_INHERIT_PROPERTIES: 1017 if (existing) 1018 { 1019 LONG newer = CompareFileTime(&existing->pCrlInfo->ThisUpdate, 1020 &pCrlContext->pCrlInfo->ThisUpdate); 1021 1022 if (newer < 0) 1023 { 1024 toAdd = CertDuplicateCRLContext(pCrlContext); 1025 Context_CopyProperties(toAdd, existing); 1026 } 1027 else 1028 { 1029 TRACE("existing CRL is newer, not adding\n"); 1030 SetLastError(CRYPT_E_EXISTS); 1031 ret = FALSE; 1032 } 1033 } 1034 else 1035 toAdd = CertDuplicateCRLContext(pCrlContext); 1036 break; 1037 case CERT_STORE_ADD_REPLACE_EXISTING: 1038 toAdd = CertDuplicateCRLContext(pCrlContext); 1039 break; 1040 case CERT_STORE_ADD_REPLACE_EXISTING_INHERIT_PROPERTIES: 1041 toAdd = CertDuplicateCRLContext(pCrlContext); 1042 if (existing) 1043 Context_CopyProperties(toAdd, existing); 1044 break; 1045 case CERT_STORE_ADD_USE_EXISTING: 1046 if (existing) 1047 { 1048 Context_CopyProperties(existing, pCrlContext); 1049 if (ppStoreContext) 1050 *ppStoreContext = CertDuplicateCRLContext(existing); 1051 } 1052 else 1053 toAdd = CertDuplicateCRLContext(pCrlContext); 1054 break; 1055 default: 1056 FIXME("Unimplemented add disposition %d\n", dwAddDisposition); 1057 ret = FALSE; 1058 } 1059 1060 if (toAdd) 1061 { 1062 if (store) { 1063 context_t *ret_context; 1064 ret = store->vtbl->crls.addContext(store, context_from_ptr(toAdd), 1065 existing ? context_from_ptr(existing) : NULL, ppStoreContext ? &ret_context : NULL, FALSE); 1066 if (ret && ppStoreContext) 1067 *ppStoreContext = context_ptr(ret_context); 1068 }else if (ppStoreContext) { 1069 *ppStoreContext = CertDuplicateCRLContext(toAdd); 1070 } 1071 CertFreeCRLContext(toAdd); 1072 } 1073 if (existing) 1074 CertFreeCRLContext(existing); 1075 1076 TRACE("returning %d\n", ret); 1077 return ret; 1078 } 1079 1080 BOOL WINAPI CertDeleteCRLFromStore(PCCRL_CONTEXT pCrlContext) 1081 { 1082 WINECRYPT_CERTSTORE *hcs; 1083 BOOL ret; 1084 1085 TRACE("(%p)\n", pCrlContext); 1086 1087 if (!pCrlContext) 1088 return TRUE; 1089 1090 hcs = pCrlContext->hCertStore; 1091 1092 if (hcs->dwMagic != WINE_CRYPTCERTSTORE_MAGIC) 1093 return FALSE; 1094 1095 ret = hcs->vtbl->crls.delete(hcs, &crl_from_ptr(pCrlContext)->base); 1096 if (ret) 1097 ret = CertFreeCRLContext(pCrlContext); 1098 return ret; 1099 } 1100 1101 PCCRL_CONTEXT WINAPI CertEnumCRLsInStore(HCERTSTORE hCertStore, PCCRL_CONTEXT pPrev) 1102 { 1103 crl_t *ret, *prev = pPrev ? crl_from_ptr(pPrev) : NULL; 1104 WINECRYPT_CERTSTORE *hcs = hCertStore; 1105 1106 TRACE("(%p, %p)\n", hCertStore, pPrev); 1107 if (!hCertStore) 1108 ret = NULL; 1109 else if (hcs->dwMagic != WINE_CRYPTCERTSTORE_MAGIC) 1110 ret = NULL; 1111 else 1112 ret = (crl_t*)hcs->vtbl->crls.enumContext(hcs, prev ? &prev->base : NULL); 1113 return ret ? &ret->ctx : NULL; 1114 } 1115 1116 HCERTSTORE WINAPI CertDuplicateStore(HCERTSTORE hCertStore) 1117 { 1118 WINECRYPT_CERTSTORE *hcs = hCertStore; 1119 1120 TRACE("(%p)\n", hCertStore); 1121 1122 if (hcs && hcs->dwMagic == WINE_CRYPTCERTSTORE_MAGIC) 1123 hcs->vtbl->addref(hcs); 1124 return hCertStore; 1125 } 1126 1127 BOOL WINAPI CertCloseStore(HCERTSTORE hCertStore, DWORD dwFlags) 1128 { 1129 WINECRYPT_CERTSTORE *hcs = hCertStore; 1130 DWORD res; 1131 1132 TRACE("(%p, %08x)\n", hCertStore, dwFlags); 1133 1134 if( ! hCertStore ) 1135 return TRUE; 1136 1137 if ( hcs->dwMagic != WINE_CRYPTCERTSTORE_MAGIC ) 1138 return FALSE; 1139 1140 res = hcs->vtbl->release(hcs, dwFlags); 1141 if (res != ERROR_SUCCESS) { 1142 SetLastError(res); 1143 return FALSE; 1144 } 1145 1146 return TRUE; 1147 } 1148 1149 BOOL WINAPI CertControlStore(HCERTSTORE hCertStore, DWORD dwFlags, 1150 DWORD dwCtrlType, void const *pvCtrlPara) 1151 { 1152 WINECRYPT_CERTSTORE *hcs = hCertStore; 1153 BOOL ret; 1154 1155 TRACE("(%p, %08x, %d, %p)\n", hCertStore, dwFlags, dwCtrlType, 1156 pvCtrlPara); 1157 1158 if (!hcs) 1159 ret = FALSE; 1160 else if (hcs->dwMagic != WINE_CRYPTCERTSTORE_MAGIC) 1161 ret = FALSE; 1162 else 1163 { 1164 if (hcs->vtbl->control) 1165 ret = hcs->vtbl->control(hcs, dwFlags, dwCtrlType, pvCtrlPara); 1166 else 1167 ret = TRUE; 1168 } 1169 return ret; 1170 } 1171 1172 BOOL WINAPI CertGetStoreProperty(HCERTSTORE hCertStore, DWORD dwPropId, 1173 void *pvData, DWORD *pcbData) 1174 { 1175 WINECRYPT_CERTSTORE *store = hCertStore; 1176 BOOL ret = FALSE; 1177 1178 TRACE("(%p, %d, %p, %p)\n", hCertStore, dwPropId, pvData, pcbData); 1179 1180 switch (dwPropId) 1181 { 1182 case CERT_ACCESS_STATE_PROP_ID: 1183 if (!pvData) 1184 { 1185 *pcbData = sizeof(DWORD); 1186 ret = TRUE; 1187 } 1188 else if (*pcbData < sizeof(DWORD)) 1189 { 1190 SetLastError(ERROR_MORE_DATA); 1191 *pcbData = sizeof(DWORD); 1192 } 1193 else 1194 { 1195 DWORD state = 0; 1196 1197 if (store->type != StoreTypeMem && 1198 !(store->dwOpenFlags & CERT_STORE_READONLY_FLAG)) 1199 state |= CERT_ACCESS_STATE_WRITE_PERSIST_FLAG; 1200 *(DWORD *)pvData = state; 1201 ret = TRUE; 1202 } 1203 break; 1204 default: 1205 if (store->properties) 1206 { 1207 CRYPT_DATA_BLOB blob; 1208 1209 ret = ContextPropertyList_FindProperty(store->properties, dwPropId, 1210 &blob); 1211 if (ret) 1212 { 1213 if (!pvData) 1214 *pcbData = blob.cbData; 1215 else if (*pcbData < blob.cbData) 1216 { 1217 SetLastError(ERROR_MORE_DATA); 1218 *pcbData = blob.cbData; 1219 ret = FALSE; 1220 } 1221 else 1222 { 1223 memcpy(pvData, blob.pbData, blob.cbData); 1224 *pcbData = blob.cbData; 1225 } 1226 } 1227 else 1228 SetLastError(CRYPT_E_NOT_FOUND); 1229 } 1230 else 1231 SetLastError(CRYPT_E_NOT_FOUND); 1232 } 1233 return ret; 1234 } 1235 1236 BOOL WINAPI CertSetStoreProperty(HCERTSTORE hCertStore, DWORD dwPropId, 1237 DWORD dwFlags, const void *pvData) 1238 { 1239 WINECRYPT_CERTSTORE *store = hCertStore; 1240 BOOL ret = FALSE; 1241 1242 TRACE("(%p, %d, %08x, %p)\n", hCertStore, dwPropId, dwFlags, pvData); 1243 1244 if (!store->properties) 1245 store->properties = ContextPropertyList_Create(); 1246 switch (dwPropId) 1247 { 1248 case CERT_ACCESS_STATE_PROP_ID: 1249 SetLastError(E_INVALIDARG); 1250 break; 1251 default: 1252 if (pvData) 1253 { 1254 const CRYPT_DATA_BLOB *blob = pvData; 1255 1256 ret = ContextPropertyList_SetProperty(store->properties, dwPropId, 1257 blob->pbData, blob->cbData); 1258 } 1259 else 1260 { 1261 ContextPropertyList_RemoveProperty(store->properties, dwPropId); 1262 ret = TRUE; 1263 } 1264 } 1265 return ret; 1266 } 1267 1268 static LONG CRYPT_OpenParentStore(DWORD dwFlags, 1269 void *pvSystemStoreLocationPara, HKEY *key) 1270 { 1271 HKEY root; 1272 LPCWSTR base; 1273 1274 TRACE("(%08x, %p)\n", dwFlags, pvSystemStoreLocationPara); 1275 1276 switch (dwFlags & CERT_SYSTEM_STORE_LOCATION_MASK) 1277 { 1278 case CERT_SYSTEM_STORE_LOCAL_MACHINE: 1279 root = HKEY_LOCAL_MACHINE; 1280 base = CERT_LOCAL_MACHINE_SYSTEM_STORE_REGPATH; 1281 break; 1282 case CERT_SYSTEM_STORE_CURRENT_USER: 1283 root = HKEY_CURRENT_USER; 1284 base = CERT_LOCAL_MACHINE_SYSTEM_STORE_REGPATH; 1285 break; 1286 case CERT_SYSTEM_STORE_CURRENT_SERVICE: 1287 /* hklm\Software\Microsoft\Cryptography\Services\servicename\ 1288 * SystemCertificates 1289 */ 1290 FIXME("CERT_SYSTEM_STORE_CURRENT_SERVICE\n"); 1291 return ERROR_FILE_NOT_FOUND; 1292 case CERT_SYSTEM_STORE_SERVICES: 1293 /* hklm\Software\Microsoft\Cryptography\Services\servicename\ 1294 * SystemCertificates 1295 */ 1296 FIXME("CERT_SYSTEM_STORE_SERVICES\n"); 1297 return ERROR_FILE_NOT_FOUND; 1298 case CERT_SYSTEM_STORE_USERS: 1299 /* hku\user sid\Software\Microsoft\SystemCertificates */ 1300 FIXME("CERT_SYSTEM_STORE_USERS\n"); 1301 return ERROR_FILE_NOT_FOUND; 1302 case CERT_SYSTEM_STORE_CURRENT_USER_GROUP_POLICY: 1303 root = HKEY_CURRENT_USER; 1304 base = CERT_GROUP_POLICY_SYSTEM_STORE_REGPATH; 1305 break; 1306 case CERT_SYSTEM_STORE_LOCAL_MACHINE_GROUP_POLICY: 1307 root = HKEY_LOCAL_MACHINE; 1308 base = CERT_GROUP_POLICY_SYSTEM_STORE_REGPATH; 1309 break; 1310 case CERT_SYSTEM_STORE_LOCAL_MACHINE_ENTERPRISE: 1311 /* hklm\Software\Microsoft\EnterpriseCertificates */ 1312 FIXME("CERT_SYSTEM_STORE_LOCAL_MACHINE_ENTERPRISE\n"); 1313 return ERROR_FILE_NOT_FOUND; 1314 default: 1315 return ERROR_FILE_NOT_FOUND; 1316 } 1317 1318 return RegOpenKeyExW(root, base, 0, KEY_READ, key); 1319 } 1320 1321 BOOL WINAPI CertEnumSystemStore(DWORD dwFlags, void *pvSystemStoreLocationPara, 1322 void *pvArg, PFN_CERT_ENUM_SYSTEM_STORE pfnEnum) 1323 { 1324 BOOL ret = FALSE; 1325 LONG rc; 1326 HKEY key; 1327 CERT_SYSTEM_STORE_INFO info = { sizeof(info) }; 1328 1329 TRACE("(%08x, %p, %p, %p)\n", dwFlags, pvSystemStoreLocationPara, pvArg, 1330 pfnEnum); 1331 1332 rc = CRYPT_OpenParentStore(dwFlags, pvArg, &key); 1333 if (!rc) 1334 { 1335 DWORD index = 0; 1336 1337 ret = TRUE; 1338 do { 1339 WCHAR name[MAX_PATH]; 1340 DWORD size = ARRAY_SIZE(name); 1341 1342 rc = RegEnumKeyExW(key, index++, name, &size, NULL, NULL, NULL, 1343 NULL); 1344 if (!rc) 1345 ret = pfnEnum(name, dwFlags, &info, NULL, pvArg); 1346 } while (ret && !rc); 1347 if (ret && rc != ERROR_NO_MORE_ITEMS) 1348 SetLastError(rc); 1349 } 1350 else 1351 SetLastError(rc); 1352 /* Include root store for the local machine location (it isn't in the 1353 * registry) 1354 */ 1355 if (ret && (dwFlags & CERT_SYSTEM_STORE_LOCATION_MASK) == 1356 CERT_SYSTEM_STORE_LOCAL_MACHINE) 1357 ret = pfnEnum(rootW, dwFlags, &info, NULL, pvArg); 1358 return ret; 1359 } 1360 1361 BOOL WINAPI CertEnumPhysicalStore(const void *pvSystemStore, DWORD dwFlags, 1362 void *pvArg, PFN_CERT_ENUM_PHYSICAL_STORE pfnEnum) 1363 { 1364 if (dwFlags & CERT_SYSTEM_STORE_RELOCATE_FLAG) 1365 FIXME("(%p, %08x, %p, %p): stub\n", pvSystemStore, dwFlags, pvArg, 1366 pfnEnum); 1367 else 1368 FIXME("(%s, %08x, %p, %p): stub\n", debugstr_w(pvSystemStore), 1369 dwFlags, pvArg, 1370 pfnEnum); 1371 return FALSE; 1372 } 1373 1374 BOOL WINAPI CertRegisterPhysicalStore(const void *pvSystemStore, DWORD dwFlags, 1375 LPCWSTR pwszStoreName, PCERT_PHYSICAL_STORE_INFO pStoreInfo, void *pvReserved) 1376 { 1377 if (dwFlags & CERT_SYSTEM_STORE_RELOCATE_FLAG) 1378 FIXME("(%p, %08x, %s, %p, %p): stub\n", pvSystemStore, dwFlags, 1379 debugstr_w(pwszStoreName), pStoreInfo, pvReserved); 1380 else 1381 FIXME("(%s, %08x, %s, %p, %p): stub\n", debugstr_w(pvSystemStore), 1382 dwFlags, debugstr_w(pwszStoreName), pStoreInfo, pvReserved); 1383 return FALSE; 1384 } 1385 1386 BOOL WINAPI CertUnregisterPhysicalStore(const void *pvSystemStore, DWORD dwFlags, 1387 LPCWSTR pwszStoreName) 1388 { 1389 FIXME("(%p, %08x, %s): stub\n", pvSystemStore, dwFlags, debugstr_w(pwszStoreName)); 1390 return TRUE; 1391 } 1392 1393 BOOL WINAPI CertRegisterSystemStore(const void *pvSystemStore, DWORD dwFlags, 1394 PCERT_SYSTEM_STORE_INFO pStoreInfo, void *pvReserved) 1395 { 1396 HCERTSTORE hstore; 1397 1398 if (dwFlags & CERT_SYSTEM_STORE_RELOCATE_FLAG ) 1399 { 1400 FIXME("(%p, %08x, %p, %p): flag not supported\n", pvSystemStore, dwFlags, pStoreInfo, pvReserved); 1401 return FALSE; 1402 } 1403 1404 TRACE("(%s, %08x, %p, %p)\n", debugstr_w(pvSystemStore), dwFlags, pStoreInfo, pvReserved); 1405 1406 hstore = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY_W, 0, 0, dwFlags, pvSystemStore); 1407 if (hstore) 1408 { 1409 CertCloseStore(hstore, 0); 1410 return TRUE; 1411 } 1412 1413 return FALSE; 1414 } 1415 1416 BOOL WINAPI CertUnregisterSystemStore(const void *pvSystemStore, DWORD dwFlags) 1417 { 1418 HCERTSTORE hstore; 1419 1420 if (dwFlags & CERT_SYSTEM_STORE_RELOCATE_FLAG) 1421 { 1422 FIXME("(%p, %08x): flag not supported\n", pvSystemStore, dwFlags); 1423 return FALSE; 1424 } 1425 TRACE("(%s, %08x)\n", debugstr_w(pvSystemStore), dwFlags); 1426 1427 hstore = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY_W, 0, 0, dwFlags | CERT_STORE_OPEN_EXISTING_FLAG, pvSystemStore); 1428 if (hstore == NULL) 1429 return FALSE; 1430 1431 hstore = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY_W, 0, 0, dwFlags | CERT_STORE_DELETE_FLAG, pvSystemStore); 1432 if (hstore == NULL && GetLastError() == 0) 1433 return TRUE; 1434 1435 return FALSE; 1436 } 1437 1438 static void EmptyStore_addref(WINECRYPT_CERTSTORE *store) 1439 { 1440 TRACE("(%p)\n", store); 1441 } 1442 1443 static DWORD EmptyStore_release(WINECRYPT_CERTSTORE *store, DWORD flags) 1444 { 1445 TRACE("(%p)\n", store); 1446 return E_UNEXPECTED; 1447 } 1448 1449 static void EmptyStore_releaseContext(WINECRYPT_CERTSTORE *store, context_t *context) 1450 { 1451 Context_Free(context); 1452 } 1453 1454 static BOOL EmptyStore_add(WINECRYPT_CERTSTORE *store, context_t *context, 1455 context_t *replace, context_t **ret_context, BOOL use_link) 1456 { 1457 TRACE("(%p, %p, %p, %p)\n", store, context, replace, ret_context); 1458 1459 /* FIXME: We should clone the context */ 1460 if(ret_context) { 1461 Context_AddRef(context); 1462 *ret_context = context; 1463 } 1464 1465 return TRUE; 1466 } 1467 1468 static context_t *EmptyStore_enum(WINECRYPT_CERTSTORE *store, context_t *prev) 1469 { 1470 TRACE("(%p, %p)\n", store, prev); 1471 1472 SetLastError(CRYPT_E_NOT_FOUND); 1473 return NULL; 1474 } 1475 1476 static BOOL EmptyStore_delete(WINECRYPT_CERTSTORE *store, context_t *context) 1477 { 1478 return TRUE; 1479 } 1480 1481 static BOOL EmptyStore_control(WINECRYPT_CERTSTORE *store, DWORD flags, DWORD ctrl_type, void const *ctrl_para) 1482 { 1483 TRACE("()\n"); 1484 1485 SetLastError(ERROR_CALL_NOT_IMPLEMENTED); 1486 return FALSE; 1487 } 1488 1489 static const store_vtbl_t EmptyStoreVtbl = { 1490 EmptyStore_addref, 1491 EmptyStore_release, 1492 EmptyStore_releaseContext, 1493 EmptyStore_control, 1494 { 1495 EmptyStore_add, 1496 EmptyStore_enum, 1497 EmptyStore_delete 1498 }, { 1499 EmptyStore_add, 1500 EmptyStore_enum, 1501 EmptyStore_delete 1502 }, { 1503 EmptyStore_add, 1504 EmptyStore_enum, 1505 EmptyStore_delete 1506 } 1507 }; 1508 1509 WINECRYPT_CERTSTORE empty_store; 1510 1511 void init_empty_store(void) 1512 { 1513 CRYPT_InitStore(&empty_store, CERT_STORE_READONLY_FLAG, StoreTypeEmpty, &EmptyStoreVtbl); 1514 } 1515