2 * Copyright 2002 Mike McCormack for CodeWeavers
3 * Copyright 2004-2006 Juan Lang
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.
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.
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
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.
27 #include "wine/port.h"
37 #include "wine/debug.h"
38 #include "wine/list.h"
39 #include "wine/exception.h"
40 #include "crypt32_private.h"
42 WINE_DEFAULT_DEBUG_CHANNEL(crypt);
44 static const WINE_CONTEXT_INTERFACE gCertInterface = {
45 (CreateContextFunc)CertCreateCertificateContext,
46 (AddContextToStoreFunc)CertAddCertificateContextToStore,
47 (AddEncodedContextToStoreFunc)CertAddEncodedCertificateToStore,
48 (DuplicateContextFunc)CertDuplicateCertificateContext,
49 (EnumContextsInStoreFunc)CertEnumCertificatesInStore,
50 (EnumPropertiesFunc)CertEnumCertificateContextProperties,
51 (GetContextPropertyFunc)CertGetCertificateContextProperty,
52 (SetContextPropertyFunc)CertSetCertificateContextProperty,
53 (SerializeElementFunc)CertSerializeCertificateStoreElement,
54 (FreeContextFunc)CertFreeCertificateContext,
55 (DeleteContextFunc)CertDeleteCertificateFromStore,
57 PCWINE_CONTEXT_INTERFACE pCertInterface = &gCertInterface;
59 static const WINE_CONTEXT_INTERFACE gCRLInterface = {
60 (CreateContextFunc)CertCreateCRLContext,
61 (AddContextToStoreFunc)CertAddCRLContextToStore,
62 (AddEncodedContextToStoreFunc)CertAddEncodedCRLToStore,
63 (DuplicateContextFunc)CertDuplicateCRLContext,
64 (EnumContextsInStoreFunc)CertEnumCRLsInStore,
65 (EnumPropertiesFunc)CertEnumCRLContextProperties,
66 (GetContextPropertyFunc)CertGetCRLContextProperty,
67 (SetContextPropertyFunc)CertSetCRLContextProperty,
68 (SerializeElementFunc)CertSerializeCRLStoreElement,
69 (FreeContextFunc)CertFreeCRLContext,
70 (DeleteContextFunc)CertDeleteCRLFromStore,
72 PCWINE_CONTEXT_INTERFACE pCRLInterface = &gCRLInterface;
74 static const WINE_CONTEXT_INTERFACE gCTLInterface = {
75 (CreateContextFunc)CertCreateCTLContext,
76 (AddContextToStoreFunc)CertAddCTLContextToStore,
77 (AddEncodedContextToStoreFunc)CertAddEncodedCTLToStore,
78 (DuplicateContextFunc)CertDuplicateCTLContext,
79 (EnumContextsInStoreFunc)CertEnumCTLsInStore,
80 (EnumPropertiesFunc)CertEnumCTLContextProperties,
81 (GetContextPropertyFunc)CertGetCTLContextProperty,
82 (SetContextPropertyFunc)CertSetCTLContextProperty,
83 (SerializeElementFunc)CertSerializeCTLStoreElement,
84 (FreeContextFunc)CertFreeCTLContext,
85 (DeleteContextFunc)CertDeleteCTLFromStore,
87 PCWINE_CONTEXT_INTERFACE pCTLInterface = &gCTLInterface;
89 typedef struct _WINE_MEMSTORE
91 WINECRYPT_CERTSTORE hdr;
92 struct ContextList *certs;
93 struct ContextList *crls;
94 } WINE_MEMSTORE, *PWINE_MEMSTORE;
96 typedef struct _WINE_MSGSTOREINFO
101 } WINE_MSGSTOREINFO, *PWINE_MSGSTOREINFO;
103 void CRYPT_InitStore(WINECRYPT_CERTSTORE *store, DWORD dwFlags,
107 store->dwMagic = WINE_CRYPTCERTSTORE_MAGIC;
109 store->dwOpenFlags = dwFlags;
110 store->properties = NULL;
113 void CRYPT_FreeStore(PWINECRYPT_CERTSTORE store)
115 if (store->properties)
116 ContextPropertyList_Free(store->properties);
120 static BOOL CRYPT_MemAddCert(PWINECRYPT_CERTSTORE store, void *cert,
121 void *toReplace, const void **ppStoreContext)
123 WINE_MEMSTORE *ms = (WINE_MEMSTORE *)store;
124 PCERT_CONTEXT context;
126 TRACE("(%p, %p, %p, %p)\n", store, cert, toReplace, ppStoreContext);
128 context = (PCERT_CONTEXT)ContextList_Add(ms->certs, cert, toReplace);
131 context->hCertStore = store;
133 *ppStoreContext = CertDuplicateCertificateContext(context);
135 return context ? TRUE : FALSE;
138 static void *CRYPT_MemEnumCert(PWINECRYPT_CERTSTORE store, void *pPrev)
140 WINE_MEMSTORE *ms = (WINE_MEMSTORE *)store;
143 TRACE("(%p, %p)\n", store, pPrev);
145 ret = ContextList_Enum(ms->certs, pPrev);
147 SetLastError(CRYPT_E_NOT_FOUND);
149 TRACE("returning %p\n", ret);
153 static BOOL CRYPT_MemDeleteCert(PWINECRYPT_CERTSTORE store, void *pCertContext)
155 WINE_MEMSTORE *ms = (WINE_MEMSTORE *)store;
157 ContextList_Delete(ms->certs, pCertContext);
161 static BOOL CRYPT_MemAddCrl(PWINECRYPT_CERTSTORE store, void *crl,
162 void *toReplace, const void **ppStoreContext)
164 WINE_MEMSTORE *ms = (WINE_MEMSTORE *)store;
165 PCRL_CONTEXT context;
167 TRACE("(%p, %p, %p, %p)\n", store, crl, toReplace, ppStoreContext);
169 context = (PCRL_CONTEXT)ContextList_Add(ms->crls, crl, toReplace);
172 context->hCertStore = store;
174 *ppStoreContext = CertDuplicateCRLContext(context);
176 return context ? TRUE : FALSE;
179 static void *CRYPT_MemEnumCrl(PWINECRYPT_CERTSTORE store, void *pPrev)
181 WINE_MEMSTORE *ms = (WINE_MEMSTORE *)store;
184 TRACE("(%p, %p)\n", store, pPrev);
186 ret = ContextList_Enum(ms->crls, pPrev);
188 SetLastError(CRYPT_E_NOT_FOUND);
190 TRACE("returning %p\n", ret);
194 static BOOL CRYPT_MemDeleteCrl(PWINECRYPT_CERTSTORE store, void *pCrlContext)
196 WINE_MEMSTORE *ms = (WINE_MEMSTORE *)store;
198 ContextList_Delete(ms->crls, pCrlContext);
202 void CRYPT_EmptyStore(HCERTSTORE store)
208 cert = CertEnumCertificatesInStore(store, NULL);
210 CertDeleteCertificateFromStore(cert);
213 crl = CertEnumCRLsInStore(store, NULL);
215 CertDeleteCRLFromStore(crl);
219 BOOL WINAPI I_CertUpdateStore(HCERTSTORE store1, HCERTSTORE store2, DWORD unk0,
222 static BOOL warned = FALSE;
223 PCCERT_CONTEXT cert = NULL;
224 PCCRL_CONTEXT crl = NULL;
226 TRACE("(%p, %p, %08x, %08x)\n", store1, store2, unk0, unk1);
229 FIXME("semi-stub\n");
233 /* Poor-man's resync: empty first store, then add everything from second
236 CRYPT_EmptyStore(store1);
238 cert = CertEnumCertificatesInStore(store2, cert);
240 CertAddCertificateContextToStore(store1, cert,
241 CERT_STORE_ADD_ALWAYS, NULL);
244 crl = CertEnumCRLsInStore(store2, crl);
246 CertAddCRLContextToStore(store1, crl, CERT_STORE_ADD_ALWAYS, NULL);
251 static void WINAPI CRYPT_MemCloseStore(HCERTSTORE hCertStore, DWORD dwFlags)
253 WINE_MEMSTORE *store = (WINE_MEMSTORE *)hCertStore;
255 TRACE("(%p, %08x)\n", store, dwFlags);
257 FIXME("Unimplemented flags: %08x\n", dwFlags);
259 ContextList_Free(store->certs);
260 ContextList_Free(store->crls);
261 CRYPT_FreeStore((PWINECRYPT_CERTSTORE)store);
264 static WINECRYPT_CERTSTORE *CRYPT_MemOpenStore(HCRYPTPROV hCryptProv,
265 DWORD dwFlags, const void *pvPara)
267 PWINE_MEMSTORE store;
269 TRACE("(%ld, %08x, %p)\n", hCryptProv, dwFlags, pvPara);
271 if (dwFlags & CERT_STORE_DELETE_FLAG)
273 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
278 store = CryptMemAlloc(sizeof(WINE_MEMSTORE));
281 memset(store, 0, sizeof(WINE_MEMSTORE));
282 CRYPT_InitStore(&store->hdr, dwFlags, StoreTypeMem);
283 store->hdr.closeStore = CRYPT_MemCloseStore;
284 store->hdr.certs.addContext = CRYPT_MemAddCert;
285 store->hdr.certs.enumContext = CRYPT_MemEnumCert;
286 store->hdr.certs.deleteContext = CRYPT_MemDeleteCert;
287 store->hdr.crls.addContext = CRYPT_MemAddCrl;
288 store->hdr.crls.enumContext = CRYPT_MemEnumCrl;
289 store->hdr.crls.deleteContext = CRYPT_MemDeleteCrl;
290 store->hdr.control = NULL;
291 store->certs = ContextList_Create(pCertInterface,
292 sizeof(CERT_CONTEXT));
293 store->crls = ContextList_Create(pCRLInterface,
294 sizeof(CRL_CONTEXT));
295 /* Mem store doesn't need crypto provider, so close it */
296 if (hCryptProv && !(dwFlags & CERT_STORE_NO_CRYPT_RELEASE_FLAG))
297 CryptReleaseContext(hCryptProv, 0);
300 return (PWINECRYPT_CERTSTORE)store;
303 static PWINECRYPT_CERTSTORE CRYPT_SysRegOpenStoreW(HCRYPTPROV hCryptProv,
304 DWORD dwFlags, const void *pvPara)
306 static const WCHAR rootW[] = { 'R','o','o','t',0 };
307 static const WCHAR fmt[] = { '%','s','\\','%','s',0 };
308 LPCWSTR storeName = (LPCWSTR)pvPara;
310 PWINECRYPT_CERTSTORE store = NULL;
315 TRACE("(%ld, %08x, %s)\n", hCryptProv, dwFlags,
316 debugstr_w((LPCWSTR)pvPara));
320 SetLastError(E_INVALIDARG);
323 if (!lstrcmpiW(storeName, rootW))
324 return CRYPT_RootOpenStore(hCryptProv, dwFlags);
327 switch (dwFlags & CERT_SYSTEM_STORE_LOCATION_MASK)
329 case CERT_SYSTEM_STORE_LOCAL_MACHINE:
330 root = HKEY_LOCAL_MACHINE;
331 base = CERT_LOCAL_MACHINE_SYSTEM_STORE_REGPATH;
333 case CERT_SYSTEM_STORE_CURRENT_USER:
334 root = HKEY_CURRENT_USER;
335 base = CERT_LOCAL_MACHINE_SYSTEM_STORE_REGPATH;
337 case CERT_SYSTEM_STORE_CURRENT_SERVICE:
338 /* hklm\Software\Microsoft\Cryptography\Services\servicename\
341 FIXME("CERT_SYSTEM_STORE_CURRENT_SERVICE, %s: stub\n",
342 debugstr_w(storeName));
344 case CERT_SYSTEM_STORE_SERVICES:
345 /* hklm\Software\Microsoft\Cryptography\Services\servicename\
348 FIXME("CERT_SYSTEM_STORE_SERVICES, %s: stub\n",
349 debugstr_w(storeName));
351 case CERT_SYSTEM_STORE_USERS:
352 /* hku\user sid\Software\Microsoft\SystemCertificates */
353 FIXME("CERT_SYSTEM_STORE_USERS, %s: stub\n",
354 debugstr_w(storeName));
356 case CERT_SYSTEM_STORE_CURRENT_USER_GROUP_POLICY:
357 root = HKEY_CURRENT_USER;
358 base = CERT_GROUP_POLICY_SYSTEM_STORE_REGPATH;
360 case CERT_SYSTEM_STORE_LOCAL_MACHINE_GROUP_POLICY:
361 root = HKEY_LOCAL_MACHINE;
362 base = CERT_GROUP_POLICY_SYSTEM_STORE_REGPATH;
364 case CERT_SYSTEM_STORE_LOCAL_MACHINE_ENTERPRISE:
365 /* hklm\Software\Microsoft\EnterpriseCertificates */
366 FIXME("CERT_SYSTEM_STORE_LOCAL_MACHINE_ENTERPRISE, %s: stub\n",
367 debugstr_w(storeName));
370 SetLastError(E_INVALIDARG);
374 storePath = CryptMemAlloc((lstrlenW(base) + lstrlenW(storeName) + 2) *
380 REGSAM sam = dwFlags & CERT_STORE_READONLY_FLAG ? KEY_READ :
383 wsprintfW(storePath, fmt, base, storeName);
384 if (dwFlags & CERT_STORE_OPEN_EXISTING_FLAG)
385 rc = RegOpenKeyExW(root, storePath, 0, sam, &key);
390 rc = RegCreateKeyExW(root, storePath, 0, NULL, 0, sam, NULL,
392 if (!rc && dwFlags & CERT_STORE_CREATE_NEW_FLAG &&
393 disp == REG_OPENED_EXISTING_KEY)
396 rc = ERROR_FILE_EXISTS;
401 store = CRYPT_RegOpenStore(hCryptProv, dwFlags, key);
406 CryptMemFree(storePath);
411 static PWINECRYPT_CERTSTORE CRYPT_SysRegOpenStoreA(HCRYPTPROV hCryptProv,
412 DWORD dwFlags, const void *pvPara)
415 PWINECRYPT_CERTSTORE ret = NULL;
417 TRACE("(%ld, %08x, %s)\n", hCryptProv, dwFlags,
418 debugstr_a((LPCSTR)pvPara));
422 SetLastError(ERROR_FILE_NOT_FOUND);
425 len = MultiByteToWideChar(CP_ACP, 0, (LPCSTR)pvPara, -1, NULL, 0);
428 LPWSTR storeName = CryptMemAlloc(len * sizeof(WCHAR));
432 MultiByteToWideChar(CP_ACP, 0, (LPCSTR)pvPara, -1, storeName, len);
433 ret = CRYPT_SysRegOpenStoreW(hCryptProv, dwFlags, storeName);
434 CryptMemFree(storeName);
440 static PWINECRYPT_CERTSTORE CRYPT_SysOpenStoreW(HCRYPTPROV hCryptProv,
441 DWORD dwFlags, const void *pvPara)
443 HCERTSTORE store = 0;
446 TRACE("(%ld, %08x, %s)\n", hCryptProv, dwFlags,
447 debugstr_w((LPCWSTR)pvPara));
451 SetLastError(ERROR_FILE_NOT_FOUND);
454 /* This returns a different error than system registry stores if the
455 * location is invalid.
457 switch (dwFlags & CERT_SYSTEM_STORE_LOCATION_MASK)
459 case CERT_SYSTEM_STORE_LOCAL_MACHINE:
460 case CERT_SYSTEM_STORE_CURRENT_USER:
461 case CERT_SYSTEM_STORE_CURRENT_SERVICE:
462 case CERT_SYSTEM_STORE_SERVICES:
463 case CERT_SYSTEM_STORE_USERS:
464 case CERT_SYSTEM_STORE_CURRENT_USER_GROUP_POLICY:
465 case CERT_SYSTEM_STORE_LOCAL_MACHINE_GROUP_POLICY:
466 case CERT_SYSTEM_STORE_LOCAL_MACHINE_ENTERPRISE:
470 SetLastError(ERROR_FILE_NOT_FOUND);
475 HCERTSTORE regStore = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY_W,
476 0, 0, dwFlags, pvPara);
480 store = CertOpenStore(CERT_STORE_PROV_COLLECTION, 0, 0,
481 CERT_STORE_CREATE_NEW_FLAG, NULL);
482 CertAddStoreToCollection(store, regStore,
483 dwFlags & CERT_STORE_READONLY_FLAG ? 0 :
484 CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
485 CertCloseStore(regStore, 0);
486 /* CERT_SYSTEM_STORE_CURRENT_USER returns both the HKCU and HKLM
489 if ((dwFlags & CERT_SYSTEM_STORE_LOCATION_MASK) ==
490 CERT_SYSTEM_STORE_CURRENT_USER)
492 dwFlags &= ~CERT_SYSTEM_STORE_CURRENT_USER;
493 dwFlags |= CERT_SYSTEM_STORE_LOCAL_MACHINE;
494 regStore = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY_W, 0,
498 CertAddStoreToCollection(store, regStore,
499 dwFlags & CERT_STORE_READONLY_FLAG ? 0 :
500 CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
501 CertCloseStore(regStore, 0);
504 /* System store doesn't need crypto provider, so close it */
505 if (hCryptProv && !(dwFlags & CERT_STORE_NO_CRYPT_RELEASE_FLAG))
506 CryptReleaseContext(hCryptProv, 0);
509 return (PWINECRYPT_CERTSTORE)store;
512 static PWINECRYPT_CERTSTORE CRYPT_SysOpenStoreA(HCRYPTPROV hCryptProv,
513 DWORD dwFlags, const void *pvPara)
516 PWINECRYPT_CERTSTORE ret = NULL;
518 TRACE("(%ld, %08x, %s)\n", hCryptProv, dwFlags,
519 debugstr_a((LPCSTR)pvPara));
523 SetLastError(ERROR_FILE_NOT_FOUND);
526 len = MultiByteToWideChar(CP_ACP, 0, (LPCSTR)pvPara, -1, NULL, 0);
529 LPWSTR storeName = CryptMemAlloc(len * sizeof(WCHAR));
533 MultiByteToWideChar(CP_ACP, 0, (LPCSTR)pvPara, -1, storeName, len);
534 ret = CRYPT_SysOpenStoreW(hCryptProv, dwFlags, storeName);
535 CryptMemFree(storeName);
541 static void WINAPI CRYPT_MsgCloseStore(HCERTSTORE hCertStore, DWORD dwFlags)
543 PWINE_MSGSTOREINFO store = (PWINE_MSGSTOREINFO)hCertStore;
545 TRACE("(%p, %08x)\n", store, dwFlags);
546 CertCloseStore(store->memStore, dwFlags);
547 CryptMsgClose(store->msg);
551 static void *msgProvFuncs[] = {
553 NULL, /* CERT_STORE_PROV_READ_CERT_FUNC */
554 NULL, /* CERT_STORE_PROV_WRITE_CERT_FUNC */
555 NULL, /* CERT_STORE_PROV_DELETE_CERT_FUNC */
556 NULL, /* CERT_STORE_PROV_SET_CERT_PROPERTY_FUNC */
557 NULL, /* CERT_STORE_PROV_READ_CRL_FUNC */
558 NULL, /* CERT_STORE_PROV_WRITE_CRL_FUNC */
559 NULL, /* CERT_STORE_PROV_DELETE_CRL_FUNC */
560 NULL, /* CERT_STORE_PROV_SET_CRL_PROPERTY_FUNC */
561 NULL, /* CERT_STORE_PROV_READ_CTL_FUNC */
562 NULL, /* CERT_STORE_PROV_WRITE_CTL_FUNC */
563 NULL, /* CERT_STORE_PROV_DELETE_CTL_FUNC */
564 NULL, /* CERT_STORE_PROV_SET_CTL_PROPERTY_FUNC */
565 NULL, /* CERT_STORE_PROV_CONTROL_FUNC */
568 static PWINECRYPT_CERTSTORE CRYPT_MsgOpenStore(HCRYPTPROV hCryptProv,
569 DWORD dwFlags, const void *pvPara)
571 PWINECRYPT_CERTSTORE store = NULL;
572 HCRYPTMSG msg = (HCRYPTMSG)pvPara;
573 PWINECRYPT_CERTSTORE memStore;
575 TRACE("(%ld, %08x, %p)\n", hCryptProv, dwFlags, pvPara);
577 memStore = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
578 CERT_STORE_CREATE_NEW_FLAG, NULL);
582 DWORD size, count, i;
584 size = sizeof(count);
585 ret = CryptMsgGetParam(msg, CMSG_CERT_COUNT_PARAM, 0, &count, &size);
586 for (i = 0; ret && i < count; i++)
589 ret = CryptMsgGetParam(msg, CMSG_CERT_PARAM, i, NULL, &size);
592 LPBYTE buf = CryptMemAlloc(size);
596 ret = CryptMsgGetParam(msg, CMSG_CERT_PARAM, i, buf, &size);
598 ret = CertAddEncodedCertificateToStore(memStore,
599 X509_ASN_ENCODING, buf, size, CERT_STORE_ADD_ALWAYS,
605 size = sizeof(count);
606 ret = CryptMsgGetParam(msg, CMSG_CRL_COUNT_PARAM, 0, &count, &size);
607 for (i = 0; ret && i < count; i++)
610 ret = CryptMsgGetParam(msg, CMSG_CRL_PARAM, i, NULL, &size);
613 LPBYTE buf = CryptMemAlloc(size);
617 ret = CryptMsgGetParam(msg, CMSG_CRL_PARAM, i, buf, &size);
619 ret = CertAddEncodedCRLToStore(memStore,
620 X509_ASN_ENCODING, buf, size, CERT_STORE_ADD_ALWAYS,
628 PWINE_MSGSTOREINFO info = CryptMemAlloc(sizeof(WINE_MSGSTOREINFO));
632 CERT_STORE_PROV_INFO provInfo = { 0 };
634 info->dwOpenFlags = dwFlags;
635 info->memStore = memStore;
636 info->msg = CryptMsgDuplicate(msg);
637 provInfo.cbSize = sizeof(provInfo);
638 provInfo.cStoreProvFunc = sizeof(msgProvFuncs) /
639 sizeof(msgProvFuncs[0]);
640 provInfo.rgpvStoreProvFunc = msgProvFuncs;
641 provInfo.hStoreProv = info;
642 store = CRYPT_ProvCreateStore(dwFlags, memStore,
644 /* Msg store doesn't need crypto provider, so close it */
645 if (hCryptProv && !(dwFlags & CERT_STORE_NO_CRYPT_RELEASE_FLAG))
646 CryptReleaseContext(hCryptProv, 0);
649 CertCloseStore(memStore, 0);
652 CertCloseStore(memStore, 0);
654 TRACE("returning %p\n", store);
658 static PWINECRYPT_CERTSTORE CRYPT_PKCSOpenStore(HCRYPTPROV hCryptProv,
659 DWORD dwFlags, const void *pvPara)
662 PWINECRYPT_CERTSTORE store = NULL;
663 const CRYPT_DATA_BLOB *data = (const CRYPT_DATA_BLOB *)pvPara;
665 DWORD msgOpenFlags = dwFlags & CERT_STORE_NO_CRYPT_RELEASE_FLAG ? 0 :
666 CMSG_CRYPT_RELEASE_CONTEXT_FLAG;
668 TRACE("(%ld, %08x, %p)\n", hCryptProv, dwFlags, pvPara);
670 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, msgOpenFlags, CMSG_SIGNED,
671 hCryptProv, NULL, NULL);
672 ret = CryptMsgUpdate(msg, data->pbData, data->cbData, TRUE);
676 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, msgOpenFlags, 0,
677 hCryptProv, NULL, NULL);
678 ret = CryptMsgUpdate(msg, data->pbData, data->cbData, TRUE);
681 DWORD type, size = sizeof(type);
683 /* Only signed messages are allowed, check type */
684 ret = CryptMsgGetParam(msg, CMSG_TYPE_PARAM, 0, &type, &size);
685 if (ret && type != CMSG_SIGNED)
687 SetLastError(CRYPT_E_INVALID_MSG_TYPE);
693 store = CRYPT_MsgOpenStore(0, dwFlags, msg);
695 TRACE("returning %p\n", store);
699 static PWINECRYPT_CERTSTORE CRYPT_PhysOpenStoreW(HCRYPTPROV hCryptProv,
700 DWORD dwFlags, const void *pvPara)
702 if (dwFlags & CERT_SYSTEM_STORE_RELOCATE_FLAG)
703 FIXME("(%ld, %08x, %p): stub\n", hCryptProv, dwFlags, pvPara);
705 FIXME("(%ld, %08x, %s): stub\n", hCryptProv, dwFlags,
706 debugstr_w((LPCWSTR)pvPara));
710 HCERTSTORE WINAPI CertOpenStore(LPCSTR lpszStoreProvider,
711 DWORD dwMsgAndCertEncodingType, HCRYPTPROV_LEGACY hCryptProv, DWORD dwFlags,
714 WINECRYPT_CERTSTORE *hcs;
715 StoreOpenFunc openFunc = NULL;
717 TRACE("(%s, %08x, %08lx, %08x, %p)\n", debugstr_a(lpszStoreProvider),
718 dwMsgAndCertEncodingType, hCryptProv, dwFlags, pvPara);
720 if (!HIWORD(lpszStoreProvider))
722 switch (LOWORD(lpszStoreProvider))
724 case (int)CERT_STORE_PROV_MSG:
725 openFunc = CRYPT_MsgOpenStore;
727 case (int)CERT_STORE_PROV_MEMORY:
728 openFunc = CRYPT_MemOpenStore;
730 case (int)CERT_STORE_PROV_FILE:
731 openFunc = CRYPT_FileOpenStore;
733 case (int)CERT_STORE_PROV_PKCS7:
734 openFunc = CRYPT_PKCSOpenStore;
736 case (int)CERT_STORE_PROV_REG:
737 openFunc = CRYPT_RegOpenStore;
739 case (int)CERT_STORE_PROV_FILENAME_A:
740 openFunc = CRYPT_FileNameOpenStoreA;
742 case (int)CERT_STORE_PROV_FILENAME_W:
743 openFunc = CRYPT_FileNameOpenStoreW;
745 case (int)CERT_STORE_PROV_COLLECTION:
746 openFunc = CRYPT_CollectionOpenStore;
748 case (int)CERT_STORE_PROV_SYSTEM_A:
749 openFunc = CRYPT_SysOpenStoreA;
751 case (int)CERT_STORE_PROV_SYSTEM_W:
752 openFunc = CRYPT_SysOpenStoreW;
754 case (int)CERT_STORE_PROV_SYSTEM_REGISTRY_A:
755 openFunc = CRYPT_SysRegOpenStoreA;
757 case (int)CERT_STORE_PROV_SYSTEM_REGISTRY_W:
758 openFunc = CRYPT_SysRegOpenStoreW;
760 case (int)CERT_STORE_PROV_PHYSICAL_W:
761 openFunc = CRYPT_PhysOpenStoreW;
764 if (LOWORD(lpszStoreProvider))
765 FIXME("unimplemented type %d\n", LOWORD(lpszStoreProvider));
768 else if (!strcasecmp(lpszStoreProvider, sz_CERT_STORE_PROV_MEMORY))
769 openFunc = CRYPT_MemOpenStore;
770 else if (!strcasecmp(lpszStoreProvider, sz_CERT_STORE_PROV_FILENAME_W))
771 openFunc = CRYPT_FileOpenStore;
772 else if (!strcasecmp(lpszStoreProvider, sz_CERT_STORE_PROV_SYSTEM))
773 openFunc = CRYPT_SysOpenStoreW;
774 else if (!strcasecmp(lpszStoreProvider, sz_CERT_STORE_PROV_COLLECTION))
775 openFunc = CRYPT_CollectionOpenStore;
776 else if (!strcasecmp(lpszStoreProvider, sz_CERT_STORE_PROV_SYSTEM_REGISTRY))
777 openFunc = CRYPT_SysRegOpenStoreW;
780 FIXME("unimplemented type %s\n", lpszStoreProvider);
785 hcs = CRYPT_ProvOpenStore(lpszStoreProvider, dwMsgAndCertEncodingType,
786 hCryptProv, dwFlags, pvPara);
788 hcs = openFunc(hCryptProv, dwFlags, pvPara);
789 return (HCERTSTORE)hcs;
792 HCERTSTORE WINAPI CertOpenSystemStoreA(HCRYPTPROV_LEGACY hProv,
793 LPCSTR szSubSystemProtocol)
795 if (!szSubSystemProtocol)
797 SetLastError(E_INVALIDARG);
800 return CertOpenStore(CERT_STORE_PROV_SYSTEM_A, 0, hProv,
801 CERT_SYSTEM_STORE_CURRENT_USER, szSubSystemProtocol);
804 HCERTSTORE WINAPI CertOpenSystemStoreW(HCRYPTPROV_LEGACY hProv,
805 LPCWSTR szSubSystemProtocol)
807 if (!szSubSystemProtocol)
809 SetLastError(E_INVALIDARG);
812 return CertOpenStore(CERT_STORE_PROV_SYSTEM_W, 0, hProv,
813 CERT_SYSTEM_STORE_CURRENT_USER, szSubSystemProtocol);
816 #define CertContext_CopyProperties(to, from) \
817 Context_CopyProperties((to), (from), sizeof(CERT_CONTEXT))
819 BOOL WINAPI CertAddCertificateContextToStore(HCERTSTORE hCertStore,
820 PCCERT_CONTEXT pCertContext, DWORD dwAddDisposition,
821 PCCERT_CONTEXT *ppStoreContext)
823 PWINECRYPT_CERTSTORE store = (PWINECRYPT_CERTSTORE)hCertStore;
825 PCCERT_CONTEXT toAdd = NULL, existing = NULL;
827 TRACE("(%p, %p, %08x, %p)\n", hCertStore, pCertContext,
828 dwAddDisposition, ppStoreContext);
830 /* Weird case to pass a test */
831 if (dwAddDisposition == 0)
833 SetLastError(STATUS_ACCESS_VIOLATION);
836 if (dwAddDisposition != CERT_STORE_ADD_ALWAYS)
839 DWORD size = sizeof(hashToAdd);
841 ret = CertGetCertificateContextProperty(pCertContext, CERT_HASH_PROP_ID,
845 CRYPT_HASH_BLOB blob = { sizeof(hashToAdd), hashToAdd };
847 existing = CertFindCertificateInStore(hCertStore,
848 pCertContext->dwCertEncodingType, 0, CERT_FIND_SHA1_HASH, &blob,
853 switch (dwAddDisposition)
855 case CERT_STORE_ADD_ALWAYS:
856 toAdd = CertDuplicateCertificateContext(pCertContext);
858 case CERT_STORE_ADD_NEW:
861 TRACE("found matching certificate, not adding\n");
862 SetLastError(CRYPT_E_EXISTS);
866 toAdd = CertDuplicateCertificateContext(pCertContext);
868 case CERT_STORE_ADD_REPLACE_EXISTING:
869 toAdd = CertDuplicateCertificateContext(pCertContext);
871 case CERT_STORE_ADD_REPLACE_EXISTING_INHERIT_PROPERTIES:
872 toAdd = CertDuplicateCertificateContext(pCertContext);
874 CertContext_CopyProperties(toAdd, existing);
876 case CERT_STORE_ADD_USE_EXISTING:
879 CertContext_CopyProperties(existing, pCertContext);
880 *ppStoreContext = CertDuplicateCertificateContext(existing);
883 toAdd = CertDuplicateCertificateContext(pCertContext);
886 FIXME("Unimplemented add disposition %d\n", dwAddDisposition);
893 ret = store->certs.addContext(store, (void *)toAdd,
894 (void *)existing, (const void **)ppStoreContext);
895 else if (ppStoreContext)
896 *ppStoreContext = CertDuplicateCertificateContext(toAdd);
897 CertFreeCertificateContext(toAdd);
899 CertFreeCertificateContext(existing);
901 TRACE("returning %d\n", ret);
905 PCCERT_CONTEXT WINAPI CertEnumCertificatesInStore(HCERTSTORE hCertStore,
906 PCCERT_CONTEXT pPrev)
908 WINECRYPT_CERTSTORE *hcs = (WINECRYPT_CERTSTORE *)hCertStore;
911 TRACE("(%p, %p)\n", hCertStore, pPrev);
914 else if (hcs->dwMagic != WINE_CRYPTCERTSTORE_MAGIC)
917 ret = (PCCERT_CONTEXT)hcs->certs.enumContext(hcs, (void *)pPrev);
921 BOOL WINAPI CertDeleteCertificateFromStore(PCCERT_CONTEXT pCertContext)
925 TRACE("(%p)\n", pCertContext);
929 else if (!pCertContext->hCertStore)
932 CertFreeCertificateContext(pCertContext);
936 PWINECRYPT_CERTSTORE hcs =
937 (PWINECRYPT_CERTSTORE)pCertContext->hCertStore;
939 if (hcs->dwMagic != WINE_CRYPTCERTSTORE_MAGIC)
942 ret = hcs->certs.deleteContext(hcs, (void *)pCertContext);
943 CertFreeCertificateContext(pCertContext);
948 #define CrlContext_CopyProperties(to, from) \
949 Context_CopyProperties((to), (from), sizeof(CRL_CONTEXT))
951 BOOL WINAPI CertAddCRLContextToStore(HCERTSTORE hCertStore,
952 PCCRL_CONTEXT pCrlContext, DWORD dwAddDisposition,
953 PCCRL_CONTEXT* ppStoreContext)
955 PWINECRYPT_CERTSTORE store = (PWINECRYPT_CERTSTORE)hCertStore;
957 PCCRL_CONTEXT toAdd = NULL, existing = NULL;
959 TRACE("(%p, %p, %08x, %p)\n", hCertStore, pCrlContext,
960 dwAddDisposition, ppStoreContext);
962 /* Weird case to pass a test */
963 if (dwAddDisposition == 0)
965 SetLastError(STATUS_ACCESS_VIOLATION);
968 if (dwAddDisposition != CERT_STORE_ADD_ALWAYS)
970 existing = CertFindCRLInStore(hCertStore, 0, 0, CRL_FIND_EXISTING,
974 switch (dwAddDisposition)
976 case CERT_STORE_ADD_ALWAYS:
977 toAdd = CertDuplicateCRLContext(pCrlContext);
979 case CERT_STORE_ADD_NEW:
982 TRACE("found matching CRL, not adding\n");
983 SetLastError(CRYPT_E_EXISTS);
987 toAdd = CertDuplicateCRLContext(pCrlContext);
989 case CERT_STORE_ADD_NEWER:
992 LONG newer = CompareFileTime(&existing->pCrlInfo->ThisUpdate,
993 &pCrlContext->pCrlInfo->ThisUpdate);
996 toAdd = CertDuplicateCRLContext(pCrlContext);
999 TRACE("existing CRL is newer, not adding\n");
1000 SetLastError(CRYPT_E_EXISTS);
1005 toAdd = CertDuplicateCRLContext(pCrlContext);
1007 case CERT_STORE_ADD_REPLACE_EXISTING:
1008 toAdd = CertDuplicateCRLContext(pCrlContext);
1010 case CERT_STORE_ADD_REPLACE_EXISTING_INHERIT_PROPERTIES:
1011 toAdd = CertDuplicateCRLContext(pCrlContext);
1013 CrlContext_CopyProperties(toAdd, existing);
1015 case CERT_STORE_ADD_USE_EXISTING:
1017 CrlContext_CopyProperties(existing, pCrlContext);
1020 FIXME("Unimplemented add disposition %d\n", dwAddDisposition);
1027 ret = store->crls.addContext(store, (void *)toAdd,
1028 (void *)existing, (const void **)ppStoreContext);
1029 else if (ppStoreContext)
1030 *ppStoreContext = CertDuplicateCRLContext(toAdd);
1031 CertFreeCRLContext(toAdd);
1033 CertFreeCRLContext(existing);
1035 TRACE("returning %d\n", ret);
1039 BOOL WINAPI CertDeleteCRLFromStore(PCCRL_CONTEXT pCrlContext)
1043 TRACE("(%p)\n", pCrlContext);
1047 else if (!pCrlContext->hCertStore)
1050 CertFreeCRLContext(pCrlContext);
1054 PWINECRYPT_CERTSTORE hcs =
1055 (PWINECRYPT_CERTSTORE)pCrlContext->hCertStore;
1057 if (hcs->dwMagic != WINE_CRYPTCERTSTORE_MAGIC)
1060 ret = hcs->crls.deleteContext(hcs, (void *)pCrlContext);
1061 CertFreeCRLContext(pCrlContext);
1066 PCCRL_CONTEXT WINAPI CertEnumCRLsInStore(HCERTSTORE hCertStore,
1067 PCCRL_CONTEXT pPrev)
1069 WINECRYPT_CERTSTORE *hcs = (WINECRYPT_CERTSTORE *)hCertStore;
1072 TRACE("(%p, %p)\n", hCertStore, pPrev);
1075 else if (hcs->dwMagic != WINE_CRYPTCERTSTORE_MAGIC)
1078 ret = (PCCRL_CONTEXT)hcs->crls.enumContext(hcs, (void *)pPrev);
1082 PCCTL_CONTEXT WINAPI CertCreateCTLContext(DWORD dwCertEncodingType,
1083 const BYTE* pbCtlEncoded, DWORD cbCtlEncoded)
1085 FIXME("(%08x, %p, %08x): stub\n", dwCertEncodingType, pbCtlEncoded,
1090 BOOL WINAPI CertAddEncodedCTLToStore(HCERTSTORE hCertStore,
1091 DWORD dwMsgAndCertEncodingType, const BYTE *pbCtlEncoded, DWORD cbCtlEncoded,
1092 DWORD dwAddDisposition, PCCTL_CONTEXT *ppCtlContext)
1094 FIXME("(%p, %08x, %p, %d, %08x, %p): stub\n", hCertStore,
1095 dwMsgAndCertEncodingType, pbCtlEncoded, cbCtlEncoded, dwAddDisposition,
1100 BOOL WINAPI CertAddCTLContextToStore(HCERTSTORE hCertStore,
1101 PCCTL_CONTEXT pCtlContext, DWORD dwAddDisposition,
1102 PCCTL_CONTEXT* ppStoreContext)
1104 FIXME("(%p, %p, %08x, %p): stub\n", hCertStore, pCtlContext,
1105 dwAddDisposition, ppStoreContext);
1109 PCCTL_CONTEXT WINAPI CertDuplicateCTLContext(PCCTL_CONTEXT pCtlContext)
1111 FIXME("(%p): stub\n", pCtlContext );
1115 BOOL WINAPI CertFreeCTLContext(PCCTL_CONTEXT pCtlContext)
1117 FIXME("(%p): stub\n", pCtlContext );
1121 BOOL WINAPI CertDeleteCTLFromStore(PCCTL_CONTEXT pCtlContext)
1123 FIXME("(%p): stub\n", pCtlContext);
1127 PCCTL_CONTEXT WINAPI CertEnumCTLsInStore(HCERTSTORE hCertStore,
1128 PCCTL_CONTEXT pPrev)
1130 FIXME("(%p, %p): stub\n", hCertStore, pPrev);
1134 HCERTSTORE WINAPI CertDuplicateStore(HCERTSTORE hCertStore)
1136 WINECRYPT_CERTSTORE *hcs = (WINECRYPT_CERTSTORE *)hCertStore;
1138 TRACE("(%p)\n", hCertStore);
1140 if (hcs && hcs->dwMagic == WINE_CRYPTCERTSTORE_MAGIC)
1141 InterlockedIncrement(&hcs->ref);
1145 BOOL WINAPI CertCloseStore(HCERTSTORE hCertStore, DWORD dwFlags)
1147 WINECRYPT_CERTSTORE *hcs = (WINECRYPT_CERTSTORE *) hCertStore;
1149 TRACE("(%p, %08x)\n", hCertStore, dwFlags);
1154 if ( hcs->dwMagic != WINE_CRYPTCERTSTORE_MAGIC )
1157 if (InterlockedDecrement(&hcs->ref) == 0)
1159 TRACE("%p's ref count is 0, freeing\n", hcs);
1161 hcs->closeStore(hcs, dwFlags);
1164 TRACE("%p's ref count is %d\n", hcs, hcs->ref);
1168 BOOL WINAPI CertControlStore(HCERTSTORE hCertStore, DWORD dwFlags,
1169 DWORD dwCtrlType, void const *pvCtrlPara)
1171 WINECRYPT_CERTSTORE *hcs = (WINECRYPT_CERTSTORE *)hCertStore;
1174 TRACE("(%p, %08x, %d, %p)\n", hCertStore, dwFlags, dwCtrlType,
1179 else if (hcs->dwMagic != WINE_CRYPTCERTSTORE_MAGIC)
1184 ret = hcs->control(hCertStore, dwFlags, dwCtrlType, pvCtrlPara);
1191 BOOL WINAPI CertGetStoreProperty(HCERTSTORE hCertStore, DWORD dwPropId,
1192 void *pvData, DWORD *pcbData)
1194 PWINECRYPT_CERTSTORE store = (PWINECRYPT_CERTSTORE)hCertStore;
1197 TRACE("(%p, %d, %p, %p)\n", hCertStore, dwPropId, pvData, pcbData);
1201 case CERT_ACCESS_STATE_PROP_ID:
1204 *pcbData = sizeof(DWORD);
1207 else if (*pcbData < sizeof(DWORD))
1209 SetLastError(ERROR_MORE_DATA);
1210 *pcbData = sizeof(DWORD);
1216 if (store->type != StoreTypeMem &&
1217 !(store->dwOpenFlags & CERT_STORE_READONLY_FLAG))
1218 state |= CERT_ACCESS_STATE_WRITE_PERSIST_FLAG;
1219 *(DWORD *)pvData = state;
1224 if (store->properties)
1226 CRYPT_DATA_BLOB blob;
1228 ret = ContextPropertyList_FindProperty(store->properties, dwPropId,
1233 *pcbData = blob.cbData;
1234 else if (*pcbData < blob.cbData)
1236 SetLastError(ERROR_MORE_DATA);
1237 *pcbData = blob.cbData;
1242 memcpy(pvData, blob.pbData, blob.cbData);
1243 *pcbData = blob.cbData;
1247 SetLastError(CRYPT_E_NOT_FOUND);
1250 SetLastError(CRYPT_E_NOT_FOUND);
1255 BOOL WINAPI CertSetStoreProperty(HCERTSTORE hCertStore, DWORD dwPropId,
1256 DWORD dwFlags, const void *pvData)
1258 PWINECRYPT_CERTSTORE store = (PWINECRYPT_CERTSTORE)hCertStore;
1261 TRACE("(%p, %d, %08x, %p)\n", hCertStore, dwPropId, dwFlags, pvData);
1263 if (!store->properties)
1264 store->properties = ContextPropertyList_Create();
1267 case CERT_ACCESS_STATE_PROP_ID:
1268 SetLastError(E_INVALIDARG);
1273 const CRYPT_DATA_BLOB *blob = (const CRYPT_DATA_BLOB *)pvData;
1275 ret = ContextPropertyList_SetProperty(store->properties, dwPropId,
1276 blob->pbData, blob->cbData);
1280 ContextPropertyList_RemoveProperty(store->properties, dwPropId);
1287 DWORD WINAPI CertEnumCTLContextProperties(PCCTL_CONTEXT pCTLContext,
1290 FIXME("(%p, %d): stub\n", pCTLContext, dwPropId);
1294 BOOL WINAPI CertGetCTLContextProperty(PCCTL_CONTEXT pCTLContext,
1295 DWORD dwPropId, void *pvData, DWORD *pcbData)
1297 FIXME("(%p, %d, %p, %p): stub\n", pCTLContext, dwPropId, pvData, pcbData);
1301 BOOL WINAPI CertSetCTLContextProperty(PCCTL_CONTEXT pCTLContext,
1302 DWORD dwPropId, DWORD dwFlags, const void *pvData)
1304 FIXME("(%p, %d, %08x, %p): stub\n", pCTLContext, dwPropId, dwFlags,
1309 static LONG CRYPT_OpenParentStore(DWORD dwFlags,
1310 void *pvSystemStoreLocationPara, HKEY *key)
1315 TRACE("(%08x, %p)\n", dwFlags, pvSystemStoreLocationPara);
1317 switch (dwFlags & CERT_SYSTEM_STORE_LOCATION_MASK)
1319 case CERT_SYSTEM_STORE_LOCAL_MACHINE:
1320 root = HKEY_LOCAL_MACHINE;
1321 base = CERT_LOCAL_MACHINE_SYSTEM_STORE_REGPATH;
1323 case CERT_SYSTEM_STORE_CURRENT_USER:
1324 root = HKEY_CURRENT_USER;
1325 base = CERT_LOCAL_MACHINE_SYSTEM_STORE_REGPATH;
1327 case CERT_SYSTEM_STORE_CURRENT_SERVICE:
1328 /* hklm\Software\Microsoft\Cryptography\Services\servicename\
1329 * SystemCertificates
1331 FIXME("CERT_SYSTEM_STORE_CURRENT_SERVICE\n");
1332 return ERROR_FILE_NOT_FOUND;
1333 case CERT_SYSTEM_STORE_SERVICES:
1334 /* hklm\Software\Microsoft\Cryptography\Services\servicename\
1335 * SystemCertificates
1337 FIXME("CERT_SYSTEM_STORE_SERVICES\n");
1338 return ERROR_FILE_NOT_FOUND;
1339 case CERT_SYSTEM_STORE_USERS:
1340 /* hku\user sid\Software\Microsoft\SystemCertificates */
1341 FIXME("CERT_SYSTEM_STORE_USERS\n");
1342 return ERROR_FILE_NOT_FOUND;
1343 case CERT_SYSTEM_STORE_CURRENT_USER_GROUP_POLICY:
1344 root = HKEY_CURRENT_USER;
1345 base = CERT_GROUP_POLICY_SYSTEM_STORE_REGPATH;
1347 case CERT_SYSTEM_STORE_LOCAL_MACHINE_GROUP_POLICY:
1348 root = HKEY_LOCAL_MACHINE;
1349 base = CERT_GROUP_POLICY_SYSTEM_STORE_REGPATH;
1351 case CERT_SYSTEM_STORE_LOCAL_MACHINE_ENTERPRISE:
1352 /* hklm\Software\Microsoft\EnterpriseCertificates */
1353 FIXME("CERT_SYSTEM_STORE_LOCAL_MACHINE_ENTERPRISE\n");
1354 return ERROR_FILE_NOT_FOUND;
1356 return ERROR_FILE_NOT_FOUND;
1359 return RegOpenKeyExW(root, base, 0, KEY_READ, key);
1362 BOOL WINAPI CertEnumSystemStore(DWORD dwFlags, void *pvSystemStoreLocationPara,
1363 void *pvArg, PFN_CERT_ENUM_SYSTEM_STORE pfnEnum)
1369 TRACE("(%08x, %p, %p, %p)\n", dwFlags, pvSystemStoreLocationPara, pvArg,
1372 rc = CRYPT_OpenParentStore(dwFlags, pvArg, &key);
1376 CERT_SYSTEM_STORE_INFO info = { sizeof(info) };
1380 WCHAR name[MAX_PATH];
1381 DWORD size = sizeof(name) / sizeof(name[0]);
1383 rc = RegEnumKeyExW(key, index++, name, &size, NULL, NULL, NULL,
1386 ret = pfnEnum(name, 0, &info, NULL, pvArg);
1387 } while (ret && !rc);
1388 if (ret && rc != ERROR_NO_MORE_ITEMS)