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 BOOL WINAPI I_CertUpdateStore(HCERTSTORE store1, HCERTSTORE store2, DWORD unk0,
123 static BOOL warned = FALSE;
124 const WINE_CONTEXT_INTERFACE * const interfaces[] = { pCertInterface,
125 pCRLInterface, pCTLInterface };
128 TRACE("(%p, %p, %08x, %08x)\n", store1, store2, unk0, unk1);
131 FIXME("semi-stub\n");
135 /* Poor-man's resync: empty first store, then add everything from second
138 for (i = 0; i < sizeof(interfaces) / sizeof(interfaces[0]); i++)
143 context = interfaces[i]->enumContextsInStore(store1, NULL);
145 interfaces[i]->deleteFromStore(context);
148 context = interfaces[i]->enumContextsInStore(store2, context);
150 interfaces[i]->addContextToStore(store1, context,
151 CERT_STORE_ADD_ALWAYS, NULL);
157 static BOOL CRYPT_MemAddCert(PWINECRYPT_CERTSTORE store, void *cert,
158 void *toReplace, const void **ppStoreContext)
160 WINE_MEMSTORE *ms = (WINE_MEMSTORE *)store;
161 PCERT_CONTEXT context;
163 TRACE("(%p, %p, %p, %p)\n", store, cert, toReplace, ppStoreContext);
165 context = (PCERT_CONTEXT)ContextList_Add(ms->certs, cert, toReplace);
168 context->hCertStore = store;
170 *ppStoreContext = CertDuplicateCertificateContext(context);
172 return context ? TRUE : FALSE;
175 static void *CRYPT_MemEnumCert(PWINECRYPT_CERTSTORE store, void *pPrev)
177 WINE_MEMSTORE *ms = (WINE_MEMSTORE *)store;
180 TRACE("(%p, %p)\n", store, pPrev);
182 ret = ContextList_Enum(ms->certs, pPrev);
184 SetLastError(CRYPT_E_NOT_FOUND);
186 TRACE("returning %p\n", ret);
190 static BOOL CRYPT_MemDeleteCert(PWINECRYPT_CERTSTORE store, void *pCertContext)
192 WINE_MEMSTORE *ms = (WINE_MEMSTORE *)store;
194 ContextList_Delete(ms->certs, pCertContext);
198 static BOOL CRYPT_MemAddCrl(PWINECRYPT_CERTSTORE store, void *crl,
199 void *toReplace, const void **ppStoreContext)
201 WINE_MEMSTORE *ms = (WINE_MEMSTORE *)store;
202 PCRL_CONTEXT context;
204 TRACE("(%p, %p, %p, %p)\n", store, crl, toReplace, ppStoreContext);
206 context = (PCRL_CONTEXT)ContextList_Add(ms->crls, crl, toReplace);
209 context->hCertStore = store;
211 *ppStoreContext = CertDuplicateCRLContext(context);
213 return context ? TRUE : FALSE;
216 static void *CRYPT_MemEnumCrl(PWINECRYPT_CERTSTORE store, void *pPrev)
218 WINE_MEMSTORE *ms = (WINE_MEMSTORE *)store;
221 TRACE("(%p, %p)\n", store, pPrev);
223 ret = ContextList_Enum(ms->crls, pPrev);
225 SetLastError(CRYPT_E_NOT_FOUND);
227 TRACE("returning %p\n", ret);
231 static BOOL CRYPT_MemDeleteCrl(PWINECRYPT_CERTSTORE store, void *pCrlContext)
233 WINE_MEMSTORE *ms = (WINE_MEMSTORE *)store;
235 ContextList_Delete(ms->crls, pCrlContext);
239 static void WINAPI CRYPT_MemCloseStore(HCERTSTORE hCertStore, DWORD dwFlags)
241 WINE_MEMSTORE *store = (WINE_MEMSTORE *)hCertStore;
243 TRACE("(%p, %08x)\n", store, dwFlags);
245 FIXME("Unimplemented flags: %08x\n", dwFlags);
247 ContextList_Free(store->certs);
248 ContextList_Free(store->crls);
249 CRYPT_FreeStore((PWINECRYPT_CERTSTORE)store);
252 static WINECRYPT_CERTSTORE *CRYPT_MemOpenStore(HCRYPTPROV hCryptProv,
253 DWORD dwFlags, const void *pvPara)
255 PWINE_MEMSTORE store;
257 TRACE("(%ld, %08x, %p)\n", hCryptProv, dwFlags, pvPara);
259 if (dwFlags & CERT_STORE_DELETE_FLAG)
261 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
266 store = CryptMemAlloc(sizeof(WINE_MEMSTORE));
269 memset(store, 0, sizeof(WINE_MEMSTORE));
270 CRYPT_InitStore(&store->hdr, dwFlags, StoreTypeMem);
271 store->hdr.closeStore = CRYPT_MemCloseStore;
272 store->hdr.certs.addContext = CRYPT_MemAddCert;
273 store->hdr.certs.enumContext = CRYPT_MemEnumCert;
274 store->hdr.certs.deleteContext = CRYPT_MemDeleteCert;
275 store->hdr.crls.addContext = CRYPT_MemAddCrl;
276 store->hdr.crls.enumContext = CRYPT_MemEnumCrl;
277 store->hdr.crls.deleteContext = CRYPT_MemDeleteCrl;
278 store->hdr.control = NULL;
279 store->certs = ContextList_Create(pCertInterface,
280 sizeof(CERT_CONTEXT));
281 store->crls = ContextList_Create(pCRLInterface,
282 sizeof(CRL_CONTEXT));
283 /* Mem store doesn't need crypto provider, so close it */
284 if (hCryptProv && !(dwFlags & CERT_STORE_NO_CRYPT_RELEASE_FLAG))
285 CryptReleaseContext(hCryptProv, 0);
288 return (PWINECRYPT_CERTSTORE)store;
291 static PWINECRYPT_CERTSTORE CRYPT_SysRegOpenStoreW(HCRYPTPROV hCryptProv,
292 DWORD dwFlags, const void *pvPara)
294 static const WCHAR rootW[] = { 'R','o','o','t',0 };
295 static const WCHAR fmt[] = { '%','s','\\','%','s',0 };
296 LPCWSTR storeName = (LPCWSTR)pvPara;
298 PWINECRYPT_CERTSTORE store = NULL;
303 TRACE("(%ld, %08x, %s)\n", hCryptProv, dwFlags,
304 debugstr_w((LPCWSTR)pvPara));
308 SetLastError(E_INVALIDARG);
311 if (!lstrcmpiW(storeName, rootW))
312 return CRYPT_RootOpenStore(hCryptProv, dwFlags);
315 switch (dwFlags & CERT_SYSTEM_STORE_LOCATION_MASK)
317 case CERT_SYSTEM_STORE_LOCAL_MACHINE:
318 root = HKEY_LOCAL_MACHINE;
319 base = CERT_LOCAL_MACHINE_SYSTEM_STORE_REGPATH;
321 case CERT_SYSTEM_STORE_CURRENT_USER:
322 root = HKEY_CURRENT_USER;
323 base = CERT_LOCAL_MACHINE_SYSTEM_STORE_REGPATH;
325 case CERT_SYSTEM_STORE_CURRENT_SERVICE:
326 /* hklm\Software\Microsoft\Cryptography\Services\servicename\
329 FIXME("CERT_SYSTEM_STORE_CURRENT_SERVICE, %s: stub\n",
330 debugstr_w(storeName));
332 case CERT_SYSTEM_STORE_SERVICES:
333 /* hklm\Software\Microsoft\Cryptography\Services\servicename\
336 FIXME("CERT_SYSTEM_STORE_SERVICES, %s: stub\n",
337 debugstr_w(storeName));
339 case CERT_SYSTEM_STORE_USERS:
340 /* hku\user sid\Software\Microsoft\SystemCertificates */
341 FIXME("CERT_SYSTEM_STORE_USERS, %s: stub\n",
342 debugstr_w(storeName));
344 case CERT_SYSTEM_STORE_CURRENT_USER_GROUP_POLICY:
345 root = HKEY_CURRENT_USER;
346 base = CERT_GROUP_POLICY_SYSTEM_STORE_REGPATH;
348 case CERT_SYSTEM_STORE_LOCAL_MACHINE_GROUP_POLICY:
349 root = HKEY_LOCAL_MACHINE;
350 base = CERT_GROUP_POLICY_SYSTEM_STORE_REGPATH;
352 case CERT_SYSTEM_STORE_LOCAL_MACHINE_ENTERPRISE:
353 /* hklm\Software\Microsoft\EnterpriseCertificates */
354 FIXME("CERT_SYSTEM_STORE_LOCAL_MACHINE_ENTERPRISE, %s: stub\n",
355 debugstr_w(storeName));
358 SetLastError(E_INVALIDARG);
362 storePath = CryptMemAlloc((lstrlenW(base) + lstrlenW(storeName) + 2) *
368 REGSAM sam = dwFlags & CERT_STORE_READONLY_FLAG ? KEY_READ :
371 wsprintfW(storePath, fmt, base, storeName);
372 if (dwFlags & CERT_STORE_OPEN_EXISTING_FLAG)
373 rc = RegOpenKeyExW(root, storePath, 0, sam, &key);
378 rc = RegCreateKeyExW(root, storePath, 0, NULL, 0, sam, NULL,
380 if (!rc && dwFlags & CERT_STORE_CREATE_NEW_FLAG &&
381 disp == REG_OPENED_EXISTING_KEY)
384 rc = ERROR_FILE_EXISTS;
389 store = CRYPT_RegOpenStore(hCryptProv, dwFlags, key);
394 CryptMemFree(storePath);
399 static PWINECRYPT_CERTSTORE CRYPT_SysRegOpenStoreA(HCRYPTPROV hCryptProv,
400 DWORD dwFlags, const void *pvPara)
403 PWINECRYPT_CERTSTORE ret = NULL;
405 TRACE("(%ld, %08x, %s)\n", hCryptProv, dwFlags,
406 debugstr_a((LPCSTR)pvPara));
410 SetLastError(ERROR_FILE_NOT_FOUND);
413 len = MultiByteToWideChar(CP_ACP, 0, (LPCSTR)pvPara, -1, NULL, 0);
416 LPWSTR storeName = CryptMemAlloc(len * sizeof(WCHAR));
420 MultiByteToWideChar(CP_ACP, 0, (LPCSTR)pvPara, -1, storeName, len);
421 ret = CRYPT_SysRegOpenStoreW(hCryptProv, dwFlags, storeName);
422 CryptMemFree(storeName);
428 static PWINECRYPT_CERTSTORE CRYPT_SysOpenStoreW(HCRYPTPROV hCryptProv,
429 DWORD dwFlags, const void *pvPara)
431 HCERTSTORE store = 0;
434 TRACE("(%ld, %08x, %s)\n", hCryptProv, dwFlags,
435 debugstr_w((LPCWSTR)pvPara));
439 SetLastError(ERROR_FILE_NOT_FOUND);
442 /* This returns a different error than system registry stores if the
443 * location is invalid.
445 switch (dwFlags & CERT_SYSTEM_STORE_LOCATION_MASK)
447 case CERT_SYSTEM_STORE_LOCAL_MACHINE:
448 case CERT_SYSTEM_STORE_CURRENT_USER:
449 case CERT_SYSTEM_STORE_CURRENT_SERVICE:
450 case CERT_SYSTEM_STORE_SERVICES:
451 case CERT_SYSTEM_STORE_USERS:
452 case CERT_SYSTEM_STORE_CURRENT_USER_GROUP_POLICY:
453 case CERT_SYSTEM_STORE_LOCAL_MACHINE_GROUP_POLICY:
454 case CERT_SYSTEM_STORE_LOCAL_MACHINE_ENTERPRISE:
458 SetLastError(ERROR_FILE_NOT_FOUND);
463 HCERTSTORE regStore = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY_W,
464 0, 0, dwFlags, pvPara);
468 store = CertOpenStore(CERT_STORE_PROV_COLLECTION, 0, 0,
469 CERT_STORE_CREATE_NEW_FLAG, NULL);
470 CertAddStoreToCollection(store, regStore,
471 dwFlags & CERT_STORE_READONLY_FLAG ? 0 :
472 CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
473 CertCloseStore(regStore, 0);
474 /* CERT_SYSTEM_STORE_CURRENT_USER returns both the HKCU and HKLM
477 if ((dwFlags & CERT_SYSTEM_STORE_LOCATION_MASK) ==
478 CERT_SYSTEM_STORE_CURRENT_USER)
480 dwFlags &= ~CERT_SYSTEM_STORE_CURRENT_USER;
481 dwFlags |= CERT_SYSTEM_STORE_LOCAL_MACHINE;
482 regStore = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY_W, 0,
486 CertAddStoreToCollection(store, regStore,
487 dwFlags & CERT_STORE_READONLY_FLAG ? 0 :
488 CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
489 CertCloseStore(regStore, 0);
492 /* System store doesn't need crypto provider, so close it */
493 if (hCryptProv && !(dwFlags & CERT_STORE_NO_CRYPT_RELEASE_FLAG))
494 CryptReleaseContext(hCryptProv, 0);
497 return (PWINECRYPT_CERTSTORE)store;
500 static PWINECRYPT_CERTSTORE CRYPT_SysOpenStoreA(HCRYPTPROV hCryptProv,
501 DWORD dwFlags, const void *pvPara)
504 PWINECRYPT_CERTSTORE ret = NULL;
506 TRACE("(%ld, %08x, %s)\n", hCryptProv, dwFlags,
507 debugstr_a((LPCSTR)pvPara));
511 SetLastError(ERROR_FILE_NOT_FOUND);
514 len = MultiByteToWideChar(CP_ACP, 0, (LPCSTR)pvPara, -1, NULL, 0);
517 LPWSTR storeName = CryptMemAlloc(len * sizeof(WCHAR));
521 MultiByteToWideChar(CP_ACP, 0, (LPCSTR)pvPara, -1, storeName, len);
522 ret = CRYPT_SysOpenStoreW(hCryptProv, dwFlags, storeName);
523 CryptMemFree(storeName);
529 static void WINAPI CRYPT_MsgCloseStore(HCERTSTORE hCertStore, DWORD dwFlags)
531 PWINE_MSGSTOREINFO store = (PWINE_MSGSTOREINFO)hCertStore;
533 TRACE("(%p, %08x)\n", store, dwFlags);
534 CertCloseStore(store->memStore, dwFlags);
535 CryptMsgClose(store->msg);
539 static void *msgProvFuncs[] = {
541 NULL, /* CERT_STORE_PROV_READ_CERT_FUNC */
542 NULL, /* CERT_STORE_PROV_WRITE_CERT_FUNC */
543 NULL, /* CERT_STORE_PROV_DELETE_CERT_FUNC */
544 NULL, /* CERT_STORE_PROV_SET_CERT_PROPERTY_FUNC */
545 NULL, /* CERT_STORE_PROV_READ_CRL_FUNC */
546 NULL, /* CERT_STORE_PROV_WRITE_CRL_FUNC */
547 NULL, /* CERT_STORE_PROV_DELETE_CRL_FUNC */
548 NULL, /* CERT_STORE_PROV_SET_CRL_PROPERTY_FUNC */
549 NULL, /* CERT_STORE_PROV_READ_CTL_FUNC */
550 NULL, /* CERT_STORE_PROV_WRITE_CTL_FUNC */
551 NULL, /* CERT_STORE_PROV_DELETE_CTL_FUNC */
552 NULL, /* CERT_STORE_PROV_SET_CTL_PROPERTY_FUNC */
553 NULL, /* CERT_STORE_PROV_CONTROL_FUNC */
556 static PWINECRYPT_CERTSTORE CRYPT_MsgOpenStore(HCRYPTPROV hCryptProv,
557 DWORD dwFlags, const void *pvPara)
559 PWINECRYPT_CERTSTORE store = NULL;
560 HCRYPTMSG msg = (HCRYPTMSG)pvPara;
561 PWINECRYPT_CERTSTORE memStore;
563 TRACE("(%ld, %08x, %p)\n", hCryptProv, dwFlags, pvPara);
565 memStore = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
566 CERT_STORE_CREATE_NEW_FLAG, NULL);
570 DWORD size, count, i;
572 size = sizeof(count);
573 ret = CryptMsgGetParam(msg, CMSG_CERT_COUNT_PARAM, 0, &count, &size);
574 for (i = 0; ret && i < count; i++)
577 ret = CryptMsgGetParam(msg, CMSG_CERT_PARAM, i, NULL, &size);
580 LPBYTE buf = CryptMemAlloc(size);
584 ret = CryptMsgGetParam(msg, CMSG_CERT_PARAM, i, buf, &size);
586 ret = CertAddEncodedCertificateToStore(memStore,
587 X509_ASN_ENCODING, buf, size, CERT_STORE_ADD_ALWAYS,
593 size = sizeof(count);
594 ret = CryptMsgGetParam(msg, CMSG_CRL_COUNT_PARAM, 0, &count, &size);
595 for (i = 0; ret && i < count; i++)
598 ret = CryptMsgGetParam(msg, CMSG_CRL_PARAM, i, NULL, &size);
601 LPBYTE buf = CryptMemAlloc(size);
605 ret = CryptMsgGetParam(msg, CMSG_CRL_PARAM, i, buf, &size);
607 ret = CertAddEncodedCRLToStore(memStore,
608 X509_ASN_ENCODING, buf, size, CERT_STORE_ADD_ALWAYS,
616 PWINE_MSGSTOREINFO info = CryptMemAlloc(sizeof(WINE_MSGSTOREINFO));
620 CERT_STORE_PROV_INFO provInfo = { 0 };
622 info->dwOpenFlags = dwFlags;
623 info->memStore = memStore;
624 info->msg = CryptMsgDuplicate(msg);
625 provInfo.cbSize = sizeof(provInfo);
626 provInfo.cStoreProvFunc = sizeof(msgProvFuncs) /
627 sizeof(msgProvFuncs[0]);
628 provInfo.rgpvStoreProvFunc = msgProvFuncs;
629 provInfo.hStoreProv = info;
630 store = CRYPT_ProvCreateStore(dwFlags, memStore,
632 /* Msg store doesn't need crypto provider, so close it */
633 if (hCryptProv && !(dwFlags & CERT_STORE_NO_CRYPT_RELEASE_FLAG))
634 CryptReleaseContext(hCryptProv, 0);
637 CertCloseStore(memStore, 0);
640 CertCloseStore(memStore, 0);
642 TRACE("returning %p\n", store);
646 static PWINECRYPT_CERTSTORE CRYPT_PKCSOpenStore(HCRYPTPROV hCryptProv,
647 DWORD dwFlags, const void *pvPara)
650 PWINECRYPT_CERTSTORE store = NULL;
651 const CRYPT_DATA_BLOB *data = (const CRYPT_DATA_BLOB *)pvPara;
653 DWORD msgOpenFlags = dwFlags & CERT_STORE_NO_CRYPT_RELEASE_FLAG ? 0 :
654 CMSG_CRYPT_RELEASE_CONTEXT_FLAG;
656 TRACE("(%ld, %08x, %p)\n", hCryptProv, dwFlags, pvPara);
658 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, msgOpenFlags, CMSG_SIGNED,
659 hCryptProv, NULL, NULL);
660 ret = CryptMsgUpdate(msg, data->pbData, data->cbData, TRUE);
664 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, msgOpenFlags, 0,
665 hCryptProv, NULL, NULL);
666 ret = CryptMsgUpdate(msg, data->pbData, data->cbData, TRUE);
669 DWORD type, size = sizeof(type);
671 /* Only signed messages are allowed, check type */
672 ret = CryptMsgGetParam(msg, CMSG_TYPE_PARAM, 0, &type, &size);
673 if (ret && type != CMSG_SIGNED)
675 SetLastError(CRYPT_E_INVALID_MSG_TYPE);
681 store = CRYPT_MsgOpenStore(0, dwFlags, msg);
683 TRACE("returning %p\n", store);
687 static PWINECRYPT_CERTSTORE CRYPT_PhysOpenStoreW(HCRYPTPROV hCryptProv,
688 DWORD dwFlags, const void *pvPara)
690 if (dwFlags & CERT_SYSTEM_STORE_RELOCATE_FLAG)
691 FIXME("(%ld, %08x, %p): stub\n", hCryptProv, dwFlags, pvPara);
693 FIXME("(%ld, %08x, %s): stub\n", hCryptProv, dwFlags,
694 debugstr_w((LPCWSTR)pvPara));
698 HCERTSTORE WINAPI CertOpenStore(LPCSTR lpszStoreProvider,
699 DWORD dwMsgAndCertEncodingType, HCRYPTPROV_LEGACY hCryptProv, DWORD dwFlags,
702 WINECRYPT_CERTSTORE *hcs;
703 StoreOpenFunc openFunc = NULL;
705 TRACE("(%s, %08x, %08lx, %08x, %p)\n", debugstr_a(lpszStoreProvider),
706 dwMsgAndCertEncodingType, hCryptProv, dwFlags, pvPara);
708 if (!HIWORD(lpszStoreProvider))
710 switch (LOWORD(lpszStoreProvider))
712 case (int)CERT_STORE_PROV_MSG:
713 openFunc = CRYPT_MsgOpenStore;
715 case (int)CERT_STORE_PROV_MEMORY:
716 openFunc = CRYPT_MemOpenStore;
718 case (int)CERT_STORE_PROV_FILE:
719 openFunc = CRYPT_FileOpenStore;
721 case (int)CERT_STORE_PROV_PKCS7:
722 openFunc = CRYPT_PKCSOpenStore;
724 case (int)CERT_STORE_PROV_REG:
725 openFunc = CRYPT_RegOpenStore;
727 case (int)CERT_STORE_PROV_FILENAME_A:
728 openFunc = CRYPT_FileNameOpenStoreA;
730 case (int)CERT_STORE_PROV_FILENAME_W:
731 openFunc = CRYPT_FileNameOpenStoreW;
733 case (int)CERT_STORE_PROV_COLLECTION:
734 openFunc = CRYPT_CollectionOpenStore;
736 case (int)CERT_STORE_PROV_SYSTEM_A:
737 openFunc = CRYPT_SysOpenStoreA;
739 case (int)CERT_STORE_PROV_SYSTEM_W:
740 openFunc = CRYPT_SysOpenStoreW;
742 case (int)CERT_STORE_PROV_SYSTEM_REGISTRY_A:
743 openFunc = CRYPT_SysRegOpenStoreA;
745 case (int)CERT_STORE_PROV_SYSTEM_REGISTRY_W:
746 openFunc = CRYPT_SysRegOpenStoreW;
748 case (int)CERT_STORE_PROV_PHYSICAL_W:
749 openFunc = CRYPT_PhysOpenStoreW;
752 if (LOWORD(lpszStoreProvider))
753 FIXME("unimplemented type %d\n", LOWORD(lpszStoreProvider));
756 else if (!strcasecmp(lpszStoreProvider, sz_CERT_STORE_PROV_MEMORY))
757 openFunc = CRYPT_MemOpenStore;
758 else if (!strcasecmp(lpszStoreProvider, sz_CERT_STORE_PROV_FILENAME_W))
759 openFunc = CRYPT_FileOpenStore;
760 else if (!strcasecmp(lpszStoreProvider, sz_CERT_STORE_PROV_SYSTEM))
761 openFunc = CRYPT_SysOpenStoreW;
762 else if (!strcasecmp(lpszStoreProvider, sz_CERT_STORE_PROV_COLLECTION))
763 openFunc = CRYPT_CollectionOpenStore;
764 else if (!strcasecmp(lpszStoreProvider, sz_CERT_STORE_PROV_SYSTEM_REGISTRY))
765 openFunc = CRYPT_SysRegOpenStoreW;
768 FIXME("unimplemented type %s\n", lpszStoreProvider);
773 hcs = CRYPT_ProvOpenStore(lpszStoreProvider, dwMsgAndCertEncodingType,
774 hCryptProv, dwFlags, pvPara);
776 hcs = openFunc(hCryptProv, dwFlags, pvPara);
777 return (HCERTSTORE)hcs;
780 HCERTSTORE WINAPI CertOpenSystemStoreA(HCRYPTPROV_LEGACY hProv,
781 LPCSTR szSubSystemProtocol)
783 if (!szSubSystemProtocol)
785 SetLastError(E_INVALIDARG);
788 return CertOpenStore(CERT_STORE_PROV_SYSTEM_A, 0, hProv,
789 CERT_SYSTEM_STORE_CURRENT_USER, szSubSystemProtocol);
792 HCERTSTORE WINAPI CertOpenSystemStoreW(HCRYPTPROV_LEGACY hProv,
793 LPCWSTR szSubSystemProtocol)
795 if (!szSubSystemProtocol)
797 SetLastError(E_INVALIDARG);
800 return CertOpenStore(CERT_STORE_PROV_SYSTEM_W, 0, hProv,
801 CERT_SYSTEM_STORE_CURRENT_USER, szSubSystemProtocol);
804 #define CertContext_CopyProperties(to, from) \
805 Context_CopyProperties((to), (from), sizeof(CERT_CONTEXT))
807 BOOL WINAPI CertAddCertificateContextToStore(HCERTSTORE hCertStore,
808 PCCERT_CONTEXT pCertContext, DWORD dwAddDisposition,
809 PCCERT_CONTEXT *ppStoreContext)
811 PWINECRYPT_CERTSTORE store = (PWINECRYPT_CERTSTORE)hCertStore;
813 PCCERT_CONTEXT toAdd = NULL, existing = NULL;
815 TRACE("(%p, %p, %08x, %p)\n", hCertStore, pCertContext,
816 dwAddDisposition, ppStoreContext);
818 /* Weird case to pass a test */
819 if (dwAddDisposition == 0)
821 SetLastError(STATUS_ACCESS_VIOLATION);
824 if (dwAddDisposition != CERT_STORE_ADD_ALWAYS)
827 DWORD size = sizeof(hashToAdd);
829 ret = CertGetCertificateContextProperty(pCertContext, CERT_HASH_PROP_ID,
833 CRYPT_HASH_BLOB blob = { sizeof(hashToAdd), hashToAdd };
835 existing = CertFindCertificateInStore(hCertStore,
836 pCertContext->dwCertEncodingType, 0, CERT_FIND_SHA1_HASH, &blob,
841 switch (dwAddDisposition)
843 case CERT_STORE_ADD_ALWAYS:
844 toAdd = CertDuplicateCertificateContext(pCertContext);
846 case CERT_STORE_ADD_NEW:
849 TRACE("found matching certificate, not adding\n");
850 SetLastError(CRYPT_E_EXISTS);
854 toAdd = CertDuplicateCertificateContext(pCertContext);
856 case CERT_STORE_ADD_REPLACE_EXISTING:
857 toAdd = CertDuplicateCertificateContext(pCertContext);
859 case CERT_STORE_ADD_REPLACE_EXISTING_INHERIT_PROPERTIES:
860 toAdd = CertDuplicateCertificateContext(pCertContext);
862 CertContext_CopyProperties(toAdd, existing);
864 case CERT_STORE_ADD_USE_EXISTING:
867 CertContext_CopyProperties(existing, pCertContext);
868 *ppStoreContext = CertDuplicateCertificateContext(existing);
871 toAdd = CertDuplicateCertificateContext(pCertContext);
874 FIXME("Unimplemented add disposition %d\n", dwAddDisposition);
881 ret = store->certs.addContext(store, (void *)toAdd,
882 (void *)existing, (const void **)ppStoreContext);
883 else if (ppStoreContext)
884 *ppStoreContext = CertDuplicateCertificateContext(toAdd);
885 CertFreeCertificateContext(toAdd);
887 CertFreeCertificateContext(existing);
889 TRACE("returning %d\n", ret);
893 PCCERT_CONTEXT WINAPI CertEnumCertificatesInStore(HCERTSTORE hCertStore,
894 PCCERT_CONTEXT pPrev)
896 WINECRYPT_CERTSTORE *hcs = (WINECRYPT_CERTSTORE *)hCertStore;
899 TRACE("(%p, %p)\n", hCertStore, pPrev);
902 else if (hcs->dwMagic != WINE_CRYPTCERTSTORE_MAGIC)
905 ret = (PCCERT_CONTEXT)hcs->certs.enumContext(hcs, (void *)pPrev);
909 BOOL WINAPI CertDeleteCertificateFromStore(PCCERT_CONTEXT pCertContext)
913 TRACE("(%p)\n", pCertContext);
917 else if (!pCertContext->hCertStore)
920 CertFreeCertificateContext(pCertContext);
924 PWINECRYPT_CERTSTORE hcs =
925 (PWINECRYPT_CERTSTORE)pCertContext->hCertStore;
927 if (hcs->dwMagic != WINE_CRYPTCERTSTORE_MAGIC)
930 ret = hcs->certs.deleteContext(hcs, (void *)pCertContext);
931 CertFreeCertificateContext(pCertContext);
936 #define CrlContext_CopyProperties(to, from) \
937 Context_CopyProperties((to), (from), sizeof(CRL_CONTEXT))
939 BOOL WINAPI CertAddCRLContextToStore(HCERTSTORE hCertStore,
940 PCCRL_CONTEXT pCrlContext, DWORD dwAddDisposition,
941 PCCRL_CONTEXT* ppStoreContext)
943 PWINECRYPT_CERTSTORE store = (PWINECRYPT_CERTSTORE)hCertStore;
945 PCCRL_CONTEXT toAdd = NULL, existing = NULL;
947 TRACE("(%p, %p, %08x, %p)\n", hCertStore, pCrlContext,
948 dwAddDisposition, ppStoreContext);
950 /* Weird case to pass a test */
951 if (dwAddDisposition == 0)
953 SetLastError(STATUS_ACCESS_VIOLATION);
956 if (dwAddDisposition != CERT_STORE_ADD_ALWAYS)
958 existing = CertFindCRLInStore(hCertStore, 0, 0, CRL_FIND_EXISTING,
962 switch (dwAddDisposition)
964 case CERT_STORE_ADD_ALWAYS:
965 toAdd = CertDuplicateCRLContext(pCrlContext);
967 case CERT_STORE_ADD_NEW:
970 TRACE("found matching CRL, not adding\n");
971 SetLastError(CRYPT_E_EXISTS);
975 toAdd = CertDuplicateCRLContext(pCrlContext);
977 case CERT_STORE_ADD_NEWER:
980 LONG newer = CompareFileTime(&existing->pCrlInfo->ThisUpdate,
981 &pCrlContext->pCrlInfo->ThisUpdate);
984 toAdd = CertDuplicateCRLContext(pCrlContext);
987 TRACE("existing CRL is newer, not adding\n");
988 SetLastError(CRYPT_E_EXISTS);
993 toAdd = CertDuplicateCRLContext(pCrlContext);
995 case CERT_STORE_ADD_REPLACE_EXISTING:
996 toAdd = CertDuplicateCRLContext(pCrlContext);
998 case CERT_STORE_ADD_REPLACE_EXISTING_INHERIT_PROPERTIES:
999 toAdd = CertDuplicateCRLContext(pCrlContext);
1001 CrlContext_CopyProperties(toAdd, existing);
1003 case CERT_STORE_ADD_USE_EXISTING:
1005 CrlContext_CopyProperties(existing, pCrlContext);
1008 FIXME("Unimplemented add disposition %d\n", dwAddDisposition);
1015 ret = store->crls.addContext(store, (void *)toAdd,
1016 (void *)existing, (const void **)ppStoreContext);
1017 else if (ppStoreContext)
1018 *ppStoreContext = CertDuplicateCRLContext(toAdd);
1019 CertFreeCRLContext(toAdd);
1021 CertFreeCRLContext(existing);
1023 TRACE("returning %d\n", ret);
1027 BOOL WINAPI CertDeleteCRLFromStore(PCCRL_CONTEXT pCrlContext)
1031 TRACE("(%p)\n", pCrlContext);
1035 else if (!pCrlContext->hCertStore)
1038 CertFreeCRLContext(pCrlContext);
1042 PWINECRYPT_CERTSTORE hcs =
1043 (PWINECRYPT_CERTSTORE)pCrlContext->hCertStore;
1045 if (hcs->dwMagic != WINE_CRYPTCERTSTORE_MAGIC)
1048 ret = hcs->crls.deleteContext(hcs, (void *)pCrlContext);
1049 CertFreeCRLContext(pCrlContext);
1054 PCCRL_CONTEXT WINAPI CertEnumCRLsInStore(HCERTSTORE hCertStore,
1055 PCCRL_CONTEXT pPrev)
1057 WINECRYPT_CERTSTORE *hcs = (WINECRYPT_CERTSTORE *)hCertStore;
1060 TRACE("(%p, %p)\n", hCertStore, pPrev);
1063 else if (hcs->dwMagic != WINE_CRYPTCERTSTORE_MAGIC)
1066 ret = (PCCRL_CONTEXT)hcs->crls.enumContext(hcs, (void *)pPrev);
1070 PCCTL_CONTEXT WINAPI CertCreateCTLContext(DWORD dwCertEncodingType,
1071 const BYTE* pbCtlEncoded, DWORD cbCtlEncoded)
1073 FIXME("(%08x, %p, %08x): stub\n", dwCertEncodingType, pbCtlEncoded,
1078 BOOL WINAPI CertAddEncodedCTLToStore(HCERTSTORE hCertStore,
1079 DWORD dwMsgAndCertEncodingType, const BYTE *pbCtlEncoded, DWORD cbCtlEncoded,
1080 DWORD dwAddDisposition, PCCTL_CONTEXT *ppCtlContext)
1082 FIXME("(%p, %08x, %p, %d, %08x, %p): stub\n", hCertStore,
1083 dwMsgAndCertEncodingType, pbCtlEncoded, cbCtlEncoded, dwAddDisposition,
1088 BOOL WINAPI CertAddCTLContextToStore(HCERTSTORE hCertStore,
1089 PCCTL_CONTEXT pCtlContext, DWORD dwAddDisposition,
1090 PCCTL_CONTEXT* ppStoreContext)
1092 FIXME("(%p, %p, %08x, %p): stub\n", hCertStore, pCtlContext,
1093 dwAddDisposition, ppStoreContext);
1097 PCCTL_CONTEXT WINAPI CertDuplicateCTLContext(PCCTL_CONTEXT pCtlContext)
1099 FIXME("(%p): stub\n", pCtlContext );
1103 BOOL WINAPI CertFreeCTLContext(PCCTL_CONTEXT pCtlContext)
1105 FIXME("(%p): stub\n", pCtlContext );
1109 BOOL WINAPI CertDeleteCTLFromStore(PCCTL_CONTEXT pCtlContext)
1111 FIXME("(%p): stub\n", pCtlContext);
1115 PCCTL_CONTEXT WINAPI CertEnumCTLsInStore(HCERTSTORE hCertStore,
1116 PCCTL_CONTEXT pPrev)
1118 FIXME("(%p, %p): stub\n", hCertStore, pPrev);
1122 HCERTSTORE WINAPI CertDuplicateStore(HCERTSTORE hCertStore)
1124 WINECRYPT_CERTSTORE *hcs = (WINECRYPT_CERTSTORE *)hCertStore;
1126 TRACE("(%p)\n", hCertStore);
1128 if (hcs && hcs->dwMagic == WINE_CRYPTCERTSTORE_MAGIC)
1129 InterlockedIncrement(&hcs->ref);
1133 BOOL WINAPI CertCloseStore(HCERTSTORE hCertStore, DWORD dwFlags)
1135 WINECRYPT_CERTSTORE *hcs = (WINECRYPT_CERTSTORE *) hCertStore;
1137 TRACE("(%p, %08x)\n", hCertStore, dwFlags);
1142 if ( hcs->dwMagic != WINE_CRYPTCERTSTORE_MAGIC )
1145 if (InterlockedDecrement(&hcs->ref) == 0)
1147 TRACE("%p's ref count is 0, freeing\n", hcs);
1149 hcs->closeStore(hcs, dwFlags);
1152 TRACE("%p's ref count is %d\n", hcs, hcs->ref);
1156 BOOL WINAPI CertControlStore(HCERTSTORE hCertStore, DWORD dwFlags,
1157 DWORD dwCtrlType, void const *pvCtrlPara)
1159 WINECRYPT_CERTSTORE *hcs = (WINECRYPT_CERTSTORE *)hCertStore;
1162 TRACE("(%p, %08x, %d, %p)\n", hCertStore, dwFlags, dwCtrlType,
1167 else if (hcs->dwMagic != WINE_CRYPTCERTSTORE_MAGIC)
1172 ret = hcs->control(hCertStore, dwFlags, dwCtrlType, pvCtrlPara);
1179 BOOL WINAPI CertGetStoreProperty(HCERTSTORE hCertStore, DWORD dwPropId,
1180 void *pvData, DWORD *pcbData)
1182 PWINECRYPT_CERTSTORE store = (PWINECRYPT_CERTSTORE)hCertStore;
1185 TRACE("(%p, %d, %p, %p)\n", hCertStore, dwPropId, pvData, pcbData);
1189 case CERT_ACCESS_STATE_PROP_ID:
1192 *pcbData = sizeof(DWORD);
1195 else if (*pcbData < sizeof(DWORD))
1197 SetLastError(ERROR_MORE_DATA);
1198 *pcbData = sizeof(DWORD);
1204 if (store->type != StoreTypeMem &&
1205 !(store->dwOpenFlags & CERT_STORE_READONLY_FLAG))
1206 state |= CERT_ACCESS_STATE_WRITE_PERSIST_FLAG;
1207 *(DWORD *)pvData = state;
1212 if (store->properties)
1214 CRYPT_DATA_BLOB blob;
1216 ret = ContextPropertyList_FindProperty(store->properties, dwPropId,
1221 *pcbData = blob.cbData;
1222 else if (*pcbData < blob.cbData)
1224 SetLastError(ERROR_MORE_DATA);
1225 *pcbData = blob.cbData;
1230 memcpy(pvData, blob.pbData, blob.cbData);
1231 *pcbData = blob.cbData;
1235 SetLastError(CRYPT_E_NOT_FOUND);
1238 SetLastError(CRYPT_E_NOT_FOUND);
1243 BOOL WINAPI CertSetStoreProperty(HCERTSTORE hCertStore, DWORD dwPropId,
1244 DWORD dwFlags, const void *pvData)
1246 PWINECRYPT_CERTSTORE store = (PWINECRYPT_CERTSTORE)hCertStore;
1249 TRACE("(%p, %d, %08x, %p)\n", hCertStore, dwPropId, dwFlags, pvData);
1251 if (!store->properties)
1252 store->properties = ContextPropertyList_Create();
1255 case CERT_ACCESS_STATE_PROP_ID:
1256 SetLastError(E_INVALIDARG);
1261 const CRYPT_DATA_BLOB *blob = (const CRYPT_DATA_BLOB *)pvData;
1263 ret = ContextPropertyList_SetProperty(store->properties, dwPropId,
1264 blob->pbData, blob->cbData);
1268 ContextPropertyList_RemoveProperty(store->properties, dwPropId);
1275 DWORD WINAPI CertEnumCTLContextProperties(PCCTL_CONTEXT pCTLContext,
1278 FIXME("(%p, %d): stub\n", pCTLContext, dwPropId);
1282 BOOL WINAPI CertGetCTLContextProperty(PCCTL_CONTEXT pCTLContext,
1283 DWORD dwPropId, void *pvData, DWORD *pcbData)
1285 FIXME("(%p, %d, %p, %p): stub\n", pCTLContext, dwPropId, pvData, pcbData);
1289 BOOL WINAPI CertSetCTLContextProperty(PCCTL_CONTEXT pCTLContext,
1290 DWORD dwPropId, DWORD dwFlags, const void *pvData)
1292 FIXME("(%p, %d, %08x, %p): stub\n", pCTLContext, dwPropId, dwFlags,
1297 static LONG CRYPT_OpenParentStore(DWORD dwFlags,
1298 void *pvSystemStoreLocationPara, HKEY *key)
1303 TRACE("(%08x, %p)\n", dwFlags, pvSystemStoreLocationPara);
1305 switch (dwFlags & CERT_SYSTEM_STORE_LOCATION_MASK)
1307 case CERT_SYSTEM_STORE_LOCAL_MACHINE:
1308 root = HKEY_LOCAL_MACHINE;
1309 base = CERT_LOCAL_MACHINE_SYSTEM_STORE_REGPATH;
1311 case CERT_SYSTEM_STORE_CURRENT_USER:
1312 root = HKEY_CURRENT_USER;
1313 base = CERT_LOCAL_MACHINE_SYSTEM_STORE_REGPATH;
1315 case CERT_SYSTEM_STORE_CURRENT_SERVICE:
1316 /* hklm\Software\Microsoft\Cryptography\Services\servicename\
1317 * SystemCertificates
1319 FIXME("CERT_SYSTEM_STORE_CURRENT_SERVICE\n");
1320 return ERROR_FILE_NOT_FOUND;
1321 case CERT_SYSTEM_STORE_SERVICES:
1322 /* hklm\Software\Microsoft\Cryptography\Services\servicename\
1323 * SystemCertificates
1325 FIXME("CERT_SYSTEM_STORE_SERVICES\n");
1326 return ERROR_FILE_NOT_FOUND;
1327 case CERT_SYSTEM_STORE_USERS:
1328 /* hku\user sid\Software\Microsoft\SystemCertificates */
1329 FIXME("CERT_SYSTEM_STORE_USERS\n");
1330 return ERROR_FILE_NOT_FOUND;
1331 case CERT_SYSTEM_STORE_CURRENT_USER_GROUP_POLICY:
1332 root = HKEY_CURRENT_USER;
1333 base = CERT_GROUP_POLICY_SYSTEM_STORE_REGPATH;
1335 case CERT_SYSTEM_STORE_LOCAL_MACHINE_GROUP_POLICY:
1336 root = HKEY_LOCAL_MACHINE;
1337 base = CERT_GROUP_POLICY_SYSTEM_STORE_REGPATH;
1339 case CERT_SYSTEM_STORE_LOCAL_MACHINE_ENTERPRISE:
1340 /* hklm\Software\Microsoft\EnterpriseCertificates */
1341 FIXME("CERT_SYSTEM_STORE_LOCAL_MACHINE_ENTERPRISE\n");
1342 return ERROR_FILE_NOT_FOUND;
1344 return ERROR_FILE_NOT_FOUND;
1347 return RegOpenKeyExW(root, base, 0, KEY_READ, key);
1350 BOOL WINAPI CertEnumSystemStore(DWORD dwFlags, void *pvSystemStoreLocationPara,
1351 void *pvArg, PFN_CERT_ENUM_SYSTEM_STORE pfnEnum)
1357 TRACE("(%08x, %p, %p, %p)\n", dwFlags, pvSystemStoreLocationPara, pvArg,
1360 rc = CRYPT_OpenParentStore(dwFlags, pvArg, &key);
1364 CERT_SYSTEM_STORE_INFO info = { sizeof(info) };
1368 WCHAR name[MAX_PATH];
1369 DWORD size = sizeof(name) / sizeof(name[0]);
1371 rc = RegEnumKeyExW(key, index++, name, &size, NULL, NULL, NULL,
1374 ret = pfnEnum(name, 0, &info, NULL, pvArg);
1375 } while (ret && !rc);
1376 if (ret && rc != ERROR_NO_MORE_ITEMS)