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, HCRYPTPROV hCryptProv,
104 DWORD dwFlags, CertStoreType type)
107 store->dwMagic = WINE_CRYPTCERTSTORE_MAGIC;
111 hCryptProv = CRYPT_GetDefaultProvider();
112 dwFlags |= CERT_STORE_NO_CRYPT_RELEASE_FLAG;
114 store->cryptProv = hCryptProv;
115 store->dwOpenFlags = dwFlags;
116 store->properties = NULL;
119 void CRYPT_FreeStore(PWINECRYPT_CERTSTORE store)
121 if (store->properties)
122 ContextPropertyList_Free(store->properties);
126 static BOOL CRYPT_MemAddCert(PWINECRYPT_CERTSTORE store, void *cert,
127 void *toReplace, const void **ppStoreContext)
129 WINE_MEMSTORE *ms = (WINE_MEMSTORE *)store;
130 PCERT_CONTEXT context;
132 TRACE("(%p, %p, %p, %p)\n", store, cert, toReplace, ppStoreContext);
134 context = (PCERT_CONTEXT)ContextList_Add(ms->certs, cert, toReplace);
137 context->hCertStore = store;
139 *ppStoreContext = CertDuplicateCertificateContext(context);
141 return context ? TRUE : FALSE;
144 static void *CRYPT_MemEnumCert(PWINECRYPT_CERTSTORE store, void *pPrev)
146 WINE_MEMSTORE *ms = (WINE_MEMSTORE *)store;
149 TRACE("(%p, %p)\n", store, pPrev);
151 ret = ContextList_Enum(ms->certs, pPrev);
153 SetLastError(CRYPT_E_NOT_FOUND);
155 TRACE("returning %p\n", ret);
159 static BOOL CRYPT_MemDeleteCert(PWINECRYPT_CERTSTORE store, void *pCertContext)
161 WINE_MEMSTORE *ms = (WINE_MEMSTORE *)store;
163 ContextList_Delete(ms->certs, pCertContext);
167 static BOOL CRYPT_MemAddCrl(PWINECRYPT_CERTSTORE store, void *crl,
168 void *toReplace, const void **ppStoreContext)
170 WINE_MEMSTORE *ms = (WINE_MEMSTORE *)store;
171 PCRL_CONTEXT context;
173 TRACE("(%p, %p, %p, %p)\n", store, crl, toReplace, ppStoreContext);
175 context = (PCRL_CONTEXT)ContextList_Add(ms->crls, crl, toReplace);
178 context->hCertStore = store;
180 *ppStoreContext = CertDuplicateCRLContext(context);
182 return context ? TRUE : FALSE;
185 static void *CRYPT_MemEnumCrl(PWINECRYPT_CERTSTORE store, void *pPrev)
187 WINE_MEMSTORE *ms = (WINE_MEMSTORE *)store;
190 TRACE("(%p, %p)\n", store, pPrev);
192 ret = ContextList_Enum(ms->crls, pPrev);
194 SetLastError(CRYPT_E_NOT_FOUND);
196 TRACE("returning %p\n", ret);
200 static BOOL CRYPT_MemDeleteCrl(PWINECRYPT_CERTSTORE store, void *pCrlContext)
202 WINE_MEMSTORE *ms = (WINE_MEMSTORE *)store;
204 ContextList_Delete(ms->crls, pCrlContext);
208 void CRYPT_EmptyStore(HCERTSTORE store)
214 cert = CertEnumCertificatesInStore(store, NULL);
216 CertDeleteCertificateFromStore(cert);
219 crl = CertEnumCRLsInStore(store, NULL);
221 CertDeleteCRLFromStore(crl);
225 static void WINAPI CRYPT_MemCloseStore(HCERTSTORE hCertStore, DWORD dwFlags)
227 WINE_MEMSTORE *store = (WINE_MEMSTORE *)hCertStore;
229 TRACE("(%p, %08x)\n", store, dwFlags);
231 FIXME("Unimplemented flags: %08x\n", dwFlags);
233 ContextList_Free(store->certs);
234 ContextList_Free(store->crls);
235 CRYPT_FreeStore((PWINECRYPT_CERTSTORE)store);
238 static WINECRYPT_CERTSTORE *CRYPT_MemOpenStore(HCRYPTPROV hCryptProv,
239 DWORD dwFlags, const void *pvPara)
241 PWINE_MEMSTORE store;
243 TRACE("(%ld, %08x, %p)\n", hCryptProv, dwFlags, pvPara);
245 if (dwFlags & CERT_STORE_DELETE_FLAG)
247 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
252 store = CryptMemAlloc(sizeof(WINE_MEMSTORE));
255 memset(store, 0, sizeof(WINE_MEMSTORE));
256 CRYPT_InitStore(&store->hdr, hCryptProv, dwFlags, StoreTypeMem);
257 store->hdr.closeStore = CRYPT_MemCloseStore;
258 store->hdr.certs.addContext = CRYPT_MemAddCert;
259 store->hdr.certs.enumContext = CRYPT_MemEnumCert;
260 store->hdr.certs.deleteContext = CRYPT_MemDeleteCert;
261 store->hdr.crls.addContext = CRYPT_MemAddCrl;
262 store->hdr.crls.enumContext = CRYPT_MemEnumCrl;
263 store->hdr.crls.deleteContext = CRYPT_MemDeleteCrl;
264 store->hdr.control = NULL;
265 store->certs = ContextList_Create(pCertInterface,
266 sizeof(CERT_CONTEXT));
267 store->crls = ContextList_Create(pCRLInterface,
268 sizeof(CRL_CONTEXT));
271 return (PWINECRYPT_CERTSTORE)store;
274 /* FIXME: this isn't complete for the Root store, in which the top-level
275 * self-signed CA certs reside. Adding a cert to the Root store should present
276 * the user with a dialog indicating the consequences of doing so, and asking
277 * the user to confirm whether the cert should be added.
279 static PWINECRYPT_CERTSTORE CRYPT_SysRegOpenStoreW(HCRYPTPROV hCryptProv,
280 DWORD dwFlags, const void *pvPara)
282 static const WCHAR fmt[] = { '%','s','\\','%','s',0 };
283 LPCWSTR storeName = (LPCWSTR)pvPara;
285 PWINECRYPT_CERTSTORE store = NULL;
290 TRACE("(%ld, %08x, %s)\n", hCryptProv, dwFlags,
291 debugstr_w((LPCWSTR)pvPara));
295 SetLastError(E_INVALIDARG);
300 switch (dwFlags & CERT_SYSTEM_STORE_LOCATION_MASK)
302 case CERT_SYSTEM_STORE_LOCAL_MACHINE:
303 root = HKEY_LOCAL_MACHINE;
304 base = CERT_LOCAL_MACHINE_SYSTEM_STORE_REGPATH;
306 case CERT_SYSTEM_STORE_CURRENT_USER:
307 root = HKEY_CURRENT_USER;
308 base = CERT_LOCAL_MACHINE_SYSTEM_STORE_REGPATH;
310 case CERT_SYSTEM_STORE_CURRENT_SERVICE:
311 /* hklm\Software\Microsoft\Cryptography\Services\servicename\
314 FIXME("CERT_SYSTEM_STORE_CURRENT_SERVICE, %s: stub\n",
315 debugstr_w(storeName));
317 case CERT_SYSTEM_STORE_SERVICES:
318 /* hklm\Software\Microsoft\Cryptography\Services\servicename\
321 FIXME("CERT_SYSTEM_STORE_SERVICES, %s: stub\n",
322 debugstr_w(storeName));
324 case CERT_SYSTEM_STORE_USERS:
325 /* hku\user sid\Software\Microsoft\SystemCertificates */
326 FIXME("CERT_SYSTEM_STORE_USERS, %s: stub\n",
327 debugstr_w(storeName));
329 case CERT_SYSTEM_STORE_CURRENT_USER_GROUP_POLICY:
330 root = HKEY_CURRENT_USER;
331 base = CERT_GROUP_POLICY_SYSTEM_STORE_REGPATH;
333 case CERT_SYSTEM_STORE_LOCAL_MACHINE_GROUP_POLICY:
334 root = HKEY_LOCAL_MACHINE;
335 base = CERT_GROUP_POLICY_SYSTEM_STORE_REGPATH;
337 case CERT_SYSTEM_STORE_LOCAL_MACHINE_ENTERPRISE:
338 /* hklm\Software\Microsoft\EnterpriseCertificates */
339 FIXME("CERT_SYSTEM_STORE_LOCAL_MACHINE_ENTERPRISE, %s: stub\n",
340 debugstr_w(storeName));
343 SetLastError(E_INVALIDARG);
347 storePath = CryptMemAlloc((lstrlenW(base) + lstrlenW(storeName) + 2) *
353 REGSAM sam = dwFlags & CERT_STORE_READONLY_FLAG ? KEY_READ :
356 wsprintfW(storePath, fmt, base, storeName);
357 if (dwFlags & CERT_STORE_OPEN_EXISTING_FLAG)
358 rc = RegOpenKeyExW(root, storePath, 0, sam, &key);
363 rc = RegCreateKeyExW(root, storePath, 0, NULL, 0, sam, NULL,
365 if (!rc && dwFlags & CERT_STORE_CREATE_NEW_FLAG &&
366 disp == REG_OPENED_EXISTING_KEY)
369 rc = ERROR_FILE_EXISTS;
374 store = CRYPT_RegOpenStore(hCryptProv, dwFlags, key);
379 CryptMemFree(storePath);
384 static PWINECRYPT_CERTSTORE CRYPT_SysRegOpenStoreA(HCRYPTPROV hCryptProv,
385 DWORD dwFlags, const void *pvPara)
388 PWINECRYPT_CERTSTORE ret = NULL;
390 TRACE("(%ld, %08x, %s)\n", hCryptProv, dwFlags,
391 debugstr_a((LPCSTR)pvPara));
395 SetLastError(ERROR_FILE_NOT_FOUND);
398 len = MultiByteToWideChar(CP_ACP, 0, (LPCSTR)pvPara, -1, NULL, 0);
401 LPWSTR storeName = CryptMemAlloc(len * sizeof(WCHAR));
405 MultiByteToWideChar(CP_ACP, 0, (LPCSTR)pvPara, -1, storeName, len);
406 ret = CRYPT_SysRegOpenStoreW(hCryptProv, dwFlags, storeName);
407 CryptMemFree(storeName);
413 static PWINECRYPT_CERTSTORE CRYPT_SysOpenStoreW(HCRYPTPROV hCryptProv,
414 DWORD dwFlags, const void *pvPara)
416 HCERTSTORE store = 0;
419 TRACE("(%ld, %08x, %s)\n", hCryptProv, dwFlags,
420 debugstr_w((LPCWSTR)pvPara));
424 SetLastError(ERROR_FILE_NOT_FOUND);
427 /* This returns a different error than system registry stores if the
428 * location is invalid.
430 switch (dwFlags & CERT_SYSTEM_STORE_LOCATION_MASK)
432 case CERT_SYSTEM_STORE_LOCAL_MACHINE:
433 case CERT_SYSTEM_STORE_CURRENT_USER:
434 case CERT_SYSTEM_STORE_CURRENT_SERVICE:
435 case CERT_SYSTEM_STORE_SERVICES:
436 case CERT_SYSTEM_STORE_USERS:
437 case CERT_SYSTEM_STORE_CURRENT_USER_GROUP_POLICY:
438 case CERT_SYSTEM_STORE_LOCAL_MACHINE_GROUP_POLICY:
439 case CERT_SYSTEM_STORE_LOCAL_MACHINE_ENTERPRISE:
443 SetLastError(ERROR_FILE_NOT_FOUND);
448 HCERTSTORE regStore = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY_W,
449 0, hCryptProv, dwFlags, pvPara);
453 store = CertOpenStore(CERT_STORE_PROV_COLLECTION, 0, 0,
454 CERT_STORE_CREATE_NEW_FLAG, NULL);
455 CertAddStoreToCollection(store, regStore,
456 dwFlags & CERT_STORE_READONLY_FLAG ? 0 :
457 CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
458 CertCloseStore(regStore, 0);
459 /* CERT_SYSTEM_STORE_CURRENT_USER returns both the HKCU and HKLM
462 if ((dwFlags & CERT_SYSTEM_STORE_LOCATION_MASK) ==
463 CERT_SYSTEM_STORE_CURRENT_USER)
465 dwFlags &= ~CERT_SYSTEM_STORE_CURRENT_USER;
466 dwFlags |= CERT_SYSTEM_STORE_LOCAL_MACHINE;
467 regStore = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY_W, 0,
468 hCryptProv, dwFlags, pvPara);
471 CertAddStoreToCollection(store, regStore,
472 dwFlags & CERT_STORE_READONLY_FLAG ? 0 :
473 CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
474 CertCloseStore(regStore, 0);
479 return (PWINECRYPT_CERTSTORE)store;
482 static PWINECRYPT_CERTSTORE CRYPT_SysOpenStoreA(HCRYPTPROV hCryptProv,
483 DWORD dwFlags, const void *pvPara)
486 PWINECRYPT_CERTSTORE ret = NULL;
488 TRACE("(%ld, %08x, %s)\n", hCryptProv, dwFlags,
489 debugstr_a((LPCSTR)pvPara));
493 SetLastError(ERROR_FILE_NOT_FOUND);
496 len = MultiByteToWideChar(CP_ACP, 0, (LPCSTR)pvPara, -1, NULL, 0);
499 LPWSTR storeName = CryptMemAlloc(len * sizeof(WCHAR));
503 MultiByteToWideChar(CP_ACP, 0, (LPCSTR)pvPara, -1, storeName, len);
504 ret = CRYPT_SysOpenStoreW(hCryptProv, dwFlags, storeName);
505 CryptMemFree(storeName);
511 static void WINAPI CRYPT_MsgCloseStore(HCERTSTORE hCertStore, DWORD dwFlags)
513 PWINE_MSGSTOREINFO store = (PWINE_MSGSTOREINFO)hCertStore;
515 TRACE("(%p, %08x)\n", store, dwFlags);
516 CertCloseStore(store->memStore, dwFlags);
517 CryptMsgClose(store->msg);
521 static void *msgProvFuncs[] = {
523 NULL, /* CERT_STORE_PROV_READ_CERT_FUNC */
524 NULL, /* CERT_STORE_PROV_WRITE_CERT_FUNC */
525 NULL, /* CERT_STORE_PROV_DELETE_CERT_FUNC */
526 NULL, /* CERT_STORE_PROV_SET_CERT_PROPERTY_FUNC */
527 NULL, /* CERT_STORE_PROV_READ_CRL_FUNC */
528 NULL, /* CERT_STORE_PROV_WRITE_CRL_FUNC */
529 NULL, /* CERT_STORE_PROV_DELETE_CRL_FUNC */
530 NULL, /* CERT_STORE_PROV_SET_CRL_PROPERTY_FUNC */
531 NULL, /* CERT_STORE_PROV_READ_CTL_FUNC */
532 NULL, /* CERT_STORE_PROV_WRITE_CTL_FUNC */
533 NULL, /* CERT_STORE_PROV_DELETE_CTL_FUNC */
534 NULL, /* CERT_STORE_PROV_SET_CTL_PROPERTY_FUNC */
535 NULL, /* CERT_STORE_PROV_CONTROL_FUNC */
538 static PWINECRYPT_CERTSTORE CRYPT_MsgOpenStore(HCRYPTPROV hCryptProv,
539 DWORD dwFlags, const void *pvPara)
541 PWINECRYPT_CERTSTORE store = NULL;
542 HCRYPTMSG msg = (HCRYPTMSG)pvPara;
543 PWINECRYPT_CERTSTORE memStore;
545 TRACE("(%ld, %08x, %p)\n", hCryptProv, dwFlags, pvPara);
547 memStore = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, hCryptProv,
548 CERT_STORE_CREATE_NEW_FLAG, NULL);
552 DWORD size, count, i;
554 size = sizeof(count);
555 ret = CryptMsgGetParam(msg, CMSG_CERT_COUNT_PARAM, 0, &count, &size);
556 for (i = 0; ret && i < count; i++)
559 ret = CryptMsgGetParam(msg, CMSG_CERT_PARAM, i, NULL, &size);
562 LPBYTE buf = CryptMemAlloc(size);
566 ret = CryptMsgGetParam(msg, CMSG_CERT_PARAM, i, buf, &size);
568 ret = CertAddEncodedCertificateToStore(memStore,
569 X509_ASN_ENCODING, buf, size, CERT_STORE_ADD_ALWAYS,
575 size = sizeof(count);
576 ret = CryptMsgGetParam(msg, CMSG_CRL_COUNT_PARAM, 0, &count, &size);
577 for (i = 0; ret && i < count; i++)
580 ret = CryptMsgGetParam(msg, CMSG_CRL_PARAM, i, NULL, &size);
583 LPBYTE buf = CryptMemAlloc(size);
587 ret = CryptMsgGetParam(msg, CMSG_CRL_PARAM, i, buf, &size);
589 ret = CertAddEncodedCRLToStore(memStore,
590 X509_ASN_ENCODING, buf, size, CERT_STORE_ADD_ALWAYS,
598 PWINE_MSGSTOREINFO info = CryptMemAlloc(sizeof(WINE_MSGSTOREINFO));
602 CERT_STORE_PROV_INFO provInfo = { 0 };
604 info->dwOpenFlags = dwFlags;
605 info->memStore = memStore;
606 info->msg = CryptMsgDuplicate(msg);
607 provInfo.cbSize = sizeof(provInfo);
608 provInfo.cStoreProvFunc = sizeof(msgProvFuncs) /
609 sizeof(msgProvFuncs[0]);
610 provInfo.rgpvStoreProvFunc = msgProvFuncs;
611 provInfo.hStoreProv = info;
612 store = CRYPT_ProvCreateStore(hCryptProv, dwFlags, memStore,
616 CertCloseStore(memStore, 0);
619 CertCloseStore(memStore, 0);
621 TRACE("returning %p\n", store);
625 static PWINECRYPT_CERTSTORE CRYPT_PKCSOpenStore(HCRYPTPROV hCryptProv,
626 DWORD dwFlags, const void *pvPara)
629 PWINECRYPT_CERTSTORE store = NULL;
630 const CRYPT_DATA_BLOB *data = (const CRYPT_DATA_BLOB *)pvPara;
632 DWORD msgOpenFlags = dwFlags & CERT_STORE_NO_CRYPT_RELEASE_FLAG ? 0 :
633 CMSG_CRYPT_RELEASE_CONTEXT_FLAG;
635 TRACE("(%ld, %08x, %p)\n", hCryptProv, dwFlags, pvPara);
637 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, msgOpenFlags, CMSG_SIGNED,
638 hCryptProv, NULL, NULL);
639 ret = CryptMsgUpdate(msg, data->pbData, data->cbData, TRUE);
643 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, msgOpenFlags, 0,
644 hCryptProv, NULL, NULL);
645 ret = CryptMsgUpdate(msg, data->pbData, data->cbData, TRUE);
648 DWORD type, size = sizeof(type);
650 /* Only signed messages are allowed, check type */
651 ret = CryptMsgGetParam(msg, CMSG_TYPE_PARAM, 0, &type, &size);
652 if (ret && type != CMSG_SIGNED)
654 SetLastError(CRYPT_E_INVALID_MSG_TYPE);
660 store = CRYPT_MsgOpenStore(hCryptProv, dwFlags, msg);
662 TRACE("returning %p\n", store);
666 static PWINECRYPT_CERTSTORE CRYPT_PhysOpenStoreW(HCRYPTPROV hCryptProv,
667 DWORD dwFlags, const void *pvPara)
669 if (dwFlags & CERT_SYSTEM_STORE_RELOCATE_FLAG)
670 FIXME("(%ld, %08x, %p): stub\n", hCryptProv, dwFlags, pvPara);
672 FIXME("(%ld, %08x, %s): stub\n", hCryptProv, dwFlags,
673 debugstr_w((LPCWSTR)pvPara));
677 HCERTSTORE WINAPI CertOpenStore(LPCSTR lpszStoreProvider,
678 DWORD dwMsgAndCertEncodingType, HCRYPTPROV_LEGACY hCryptProv, DWORD dwFlags,
681 WINECRYPT_CERTSTORE *hcs;
682 StoreOpenFunc openFunc = NULL;
684 TRACE("(%s, %08x, %08lx, %08x, %p)\n", debugstr_a(lpszStoreProvider),
685 dwMsgAndCertEncodingType, hCryptProv, dwFlags, pvPara);
687 if (!HIWORD(lpszStoreProvider))
689 switch (LOWORD(lpszStoreProvider))
691 case (int)CERT_STORE_PROV_MSG:
692 openFunc = CRYPT_MsgOpenStore;
694 case (int)CERT_STORE_PROV_MEMORY:
695 openFunc = CRYPT_MemOpenStore;
697 case (int)CERT_STORE_PROV_FILE:
698 openFunc = CRYPT_FileOpenStore;
700 case (int)CERT_STORE_PROV_PKCS7:
701 openFunc = CRYPT_PKCSOpenStore;
703 case (int)CERT_STORE_PROV_REG:
704 openFunc = CRYPT_RegOpenStore;
706 case (int)CERT_STORE_PROV_FILENAME_A:
707 openFunc = CRYPT_FileNameOpenStoreA;
709 case (int)CERT_STORE_PROV_FILENAME_W:
710 openFunc = CRYPT_FileNameOpenStoreW;
712 case (int)CERT_STORE_PROV_COLLECTION:
713 openFunc = CRYPT_CollectionOpenStore;
715 case (int)CERT_STORE_PROV_SYSTEM_A:
716 openFunc = CRYPT_SysOpenStoreA;
718 case (int)CERT_STORE_PROV_SYSTEM_W:
719 openFunc = CRYPT_SysOpenStoreW;
721 case (int)CERT_STORE_PROV_SYSTEM_REGISTRY_A:
722 openFunc = CRYPT_SysRegOpenStoreA;
724 case (int)CERT_STORE_PROV_SYSTEM_REGISTRY_W:
725 openFunc = CRYPT_SysRegOpenStoreW;
727 case (int)CERT_STORE_PROV_PHYSICAL_W:
728 openFunc = CRYPT_PhysOpenStoreW;
731 if (LOWORD(lpszStoreProvider))
732 FIXME("unimplemented type %d\n", LOWORD(lpszStoreProvider));
735 else if (!strcasecmp(lpszStoreProvider, sz_CERT_STORE_PROV_MEMORY))
736 openFunc = CRYPT_MemOpenStore;
737 else if (!strcasecmp(lpszStoreProvider, sz_CERT_STORE_PROV_FILENAME_W))
738 openFunc = CRYPT_FileOpenStore;
739 else if (!strcasecmp(lpszStoreProvider, sz_CERT_STORE_PROV_SYSTEM))
740 openFunc = CRYPT_SysOpenStoreW;
741 else if (!strcasecmp(lpszStoreProvider, sz_CERT_STORE_PROV_COLLECTION))
742 openFunc = CRYPT_CollectionOpenStore;
743 else if (!strcasecmp(lpszStoreProvider, sz_CERT_STORE_PROV_SYSTEM_REGISTRY))
744 openFunc = CRYPT_SysRegOpenStoreW;
747 FIXME("unimplemented type %s\n", lpszStoreProvider);
752 hcs = CRYPT_ProvOpenStore(lpszStoreProvider, dwMsgAndCertEncodingType,
753 hCryptProv, dwFlags, pvPara);
755 hcs = openFunc(hCryptProv, dwFlags, pvPara);
756 return (HCERTSTORE)hcs;
759 HCERTSTORE WINAPI CertOpenSystemStoreA(HCRYPTPROV_LEGACY hProv,
760 LPCSTR szSubSystemProtocol)
762 if (!szSubSystemProtocol)
764 SetLastError(E_INVALIDARG);
767 return CertOpenStore(CERT_STORE_PROV_SYSTEM_A, 0, hProv,
768 CERT_SYSTEM_STORE_CURRENT_USER, szSubSystemProtocol);
771 HCERTSTORE WINAPI CertOpenSystemStoreW(HCRYPTPROV_LEGACY hProv,
772 LPCWSTR szSubSystemProtocol)
774 if (!szSubSystemProtocol)
776 SetLastError(E_INVALIDARG);
779 return CertOpenStore(CERT_STORE_PROV_SYSTEM_W, 0, hProv,
780 CERT_SYSTEM_STORE_CURRENT_USER, szSubSystemProtocol);
783 BOOL WINAPI CertSaveStore(HCERTSTORE hCertStore, DWORD dwMsgAndCertEncodingType,
784 DWORD dwSaveAs, DWORD dwSaveTo, void* pvSaveToPara, DWORD dwFlags)
786 FIXME("(%p,%d,%d,%d,%p,%08x) stub!\n", hCertStore,
787 dwMsgAndCertEncodingType, dwSaveAs, dwSaveTo, pvSaveToPara, dwFlags);
791 #define CertContext_CopyProperties(to, from) \
792 Context_CopyProperties((to), (from), sizeof(CERT_CONTEXT))
794 BOOL WINAPI CertAddCertificateContextToStore(HCERTSTORE hCertStore,
795 PCCERT_CONTEXT pCertContext, DWORD dwAddDisposition,
796 PCCERT_CONTEXT *ppStoreContext)
798 PWINECRYPT_CERTSTORE store = (PWINECRYPT_CERTSTORE)hCertStore;
800 PCCERT_CONTEXT toAdd = NULL, existing = NULL;
802 TRACE("(%p, %p, %08x, %p)\n", hCertStore, pCertContext,
803 dwAddDisposition, ppStoreContext);
805 /* Weird case to pass a test */
806 if (dwAddDisposition == 0)
808 SetLastError(STATUS_ACCESS_VIOLATION);
811 if (dwAddDisposition != CERT_STORE_ADD_ALWAYS)
814 DWORD size = sizeof(hashToAdd);
816 ret = CertGetCertificateContextProperty(pCertContext, CERT_HASH_PROP_ID,
820 CRYPT_HASH_BLOB blob = { sizeof(hashToAdd), hashToAdd };
822 existing = CertFindCertificateInStore(hCertStore,
823 pCertContext->dwCertEncodingType, 0, CERT_FIND_SHA1_HASH, &blob,
828 switch (dwAddDisposition)
830 case CERT_STORE_ADD_ALWAYS:
831 toAdd = CertDuplicateCertificateContext(pCertContext);
833 case CERT_STORE_ADD_NEW:
836 TRACE("found matching certificate, not adding\n");
837 SetLastError(CRYPT_E_EXISTS);
841 toAdd = CertDuplicateCertificateContext(pCertContext);
843 case CERT_STORE_ADD_REPLACE_EXISTING:
844 toAdd = CertDuplicateCertificateContext(pCertContext);
846 case CERT_STORE_ADD_REPLACE_EXISTING_INHERIT_PROPERTIES:
847 toAdd = CertDuplicateCertificateContext(pCertContext);
849 CertContext_CopyProperties(toAdd, existing);
851 case CERT_STORE_ADD_USE_EXISTING:
854 CertContext_CopyProperties(existing, pCertContext);
855 *ppStoreContext = CertDuplicateCertificateContext(existing);
858 toAdd = CertDuplicateCertificateContext(pCertContext);
861 FIXME("Unimplemented add disposition %d\n", dwAddDisposition);
868 ret = store->certs.addContext(store, (void *)toAdd,
869 (void *)existing, (const void **)ppStoreContext);
870 else if (ppStoreContext)
871 *ppStoreContext = CertDuplicateCertificateContext(toAdd);
872 CertFreeCertificateContext(toAdd);
874 CertFreeCertificateContext(existing);
876 TRACE("returning %d\n", ret);
880 PCCERT_CONTEXT WINAPI CertEnumCertificatesInStore(HCERTSTORE hCertStore,
881 PCCERT_CONTEXT pPrev)
883 WINECRYPT_CERTSTORE *hcs = (WINECRYPT_CERTSTORE *)hCertStore;
886 TRACE("(%p, %p)\n", hCertStore, pPrev);
889 else if (hcs->dwMagic != WINE_CRYPTCERTSTORE_MAGIC)
892 ret = (PCCERT_CONTEXT)hcs->certs.enumContext(hcs, (void *)pPrev);
896 BOOL WINAPI CertDeleteCertificateFromStore(PCCERT_CONTEXT pCertContext)
900 TRACE("(%p)\n", pCertContext);
904 else if (!pCertContext->hCertStore)
907 CertFreeCertificateContext(pCertContext);
911 PWINECRYPT_CERTSTORE hcs =
912 (PWINECRYPT_CERTSTORE)pCertContext->hCertStore;
914 if (hcs->dwMagic != WINE_CRYPTCERTSTORE_MAGIC)
917 ret = hcs->certs.deleteContext(hcs, (void *)pCertContext);
918 CertFreeCertificateContext(pCertContext);
923 #define CrlContext_CopyProperties(to, from) \
924 Context_CopyProperties((to), (from), sizeof(CRL_CONTEXT))
926 BOOL WINAPI CertAddCRLContextToStore(HCERTSTORE hCertStore,
927 PCCRL_CONTEXT pCrlContext, DWORD dwAddDisposition,
928 PCCRL_CONTEXT* ppStoreContext)
930 PWINECRYPT_CERTSTORE store = (PWINECRYPT_CERTSTORE)hCertStore;
932 PCCRL_CONTEXT toAdd = NULL, existing = NULL;
934 TRACE("(%p, %p, %08x, %p)\n", hCertStore, pCrlContext,
935 dwAddDisposition, ppStoreContext);
937 /* Weird case to pass a test */
938 if (dwAddDisposition == 0)
940 SetLastError(STATUS_ACCESS_VIOLATION);
943 if (dwAddDisposition != CERT_STORE_ADD_ALWAYS)
945 existing = CertFindCRLInStore(hCertStore, 0, 0, CRL_FIND_EXISTING,
949 switch (dwAddDisposition)
951 case CERT_STORE_ADD_ALWAYS:
952 toAdd = CertDuplicateCRLContext(pCrlContext);
954 case CERT_STORE_ADD_NEW:
957 TRACE("found matching CRL, not adding\n");
958 SetLastError(CRYPT_E_EXISTS);
962 toAdd = CertDuplicateCRLContext(pCrlContext);
964 case CERT_STORE_ADD_NEWER:
967 LONG newer = CompareFileTime(&existing->pCrlInfo->ThisUpdate,
968 &pCrlContext->pCrlInfo->ThisUpdate);
971 toAdd = CertDuplicateCRLContext(pCrlContext);
974 TRACE("existing CRL is newer, not adding\n");
975 SetLastError(CRYPT_E_EXISTS);
980 toAdd = CertDuplicateCRLContext(pCrlContext);
982 case CERT_STORE_ADD_REPLACE_EXISTING:
983 toAdd = CertDuplicateCRLContext(pCrlContext);
985 case CERT_STORE_ADD_REPLACE_EXISTING_INHERIT_PROPERTIES:
986 toAdd = CertDuplicateCRLContext(pCrlContext);
988 CrlContext_CopyProperties(toAdd, existing);
990 case CERT_STORE_ADD_USE_EXISTING:
992 CrlContext_CopyProperties(existing, pCrlContext);
995 FIXME("Unimplemented add disposition %d\n", dwAddDisposition);
1002 ret = store->crls.addContext(store, (void *)toAdd,
1003 (void *)existing, (const void **)ppStoreContext);
1004 else if (ppStoreContext)
1005 *ppStoreContext = CertDuplicateCRLContext(toAdd);
1006 CertFreeCRLContext(toAdd);
1008 CertFreeCRLContext(existing);
1010 TRACE("returning %d\n", ret);
1014 BOOL WINAPI CertDeleteCRLFromStore(PCCRL_CONTEXT pCrlContext)
1018 TRACE("(%p)\n", pCrlContext);
1022 else if (!pCrlContext->hCertStore)
1025 CertFreeCRLContext(pCrlContext);
1029 PWINECRYPT_CERTSTORE hcs =
1030 (PWINECRYPT_CERTSTORE)pCrlContext->hCertStore;
1032 if (hcs->dwMagic != WINE_CRYPTCERTSTORE_MAGIC)
1035 ret = hcs->crls.deleteContext(hcs, (void *)pCrlContext);
1036 CertFreeCRLContext(pCrlContext);
1041 PCCRL_CONTEXT WINAPI CertEnumCRLsInStore(HCERTSTORE hCertStore,
1042 PCCRL_CONTEXT pPrev)
1044 WINECRYPT_CERTSTORE *hcs = (WINECRYPT_CERTSTORE *)hCertStore;
1047 TRACE("(%p, %p)\n", hCertStore, pPrev);
1050 else if (hcs->dwMagic != WINE_CRYPTCERTSTORE_MAGIC)
1053 ret = (PCCRL_CONTEXT)hcs->crls.enumContext(hcs, (void *)pPrev);
1057 PCCTL_CONTEXT WINAPI CertCreateCTLContext(DWORD dwCertEncodingType,
1058 const BYTE* pbCtlEncoded, DWORD cbCtlEncoded)
1060 FIXME("(%08x, %p, %08x): stub\n", dwCertEncodingType, pbCtlEncoded,
1065 BOOL WINAPI CertAddEncodedCTLToStore(HCERTSTORE hCertStore,
1066 DWORD dwMsgAndCertEncodingType, const BYTE *pbCtlEncoded, DWORD cbCtlEncoded,
1067 DWORD dwAddDisposition, PCCTL_CONTEXT *ppCtlContext)
1069 FIXME("(%p, %08x, %p, %d, %08x, %p): stub\n", hCertStore,
1070 dwMsgAndCertEncodingType, pbCtlEncoded, cbCtlEncoded, dwAddDisposition,
1075 BOOL WINAPI CertAddCTLContextToStore(HCERTSTORE hCertStore,
1076 PCCTL_CONTEXT pCtlContext, DWORD dwAddDisposition,
1077 PCCTL_CONTEXT* ppStoreContext)
1079 FIXME("(%p, %p, %08x, %p): stub\n", hCertStore, pCtlContext,
1080 dwAddDisposition, ppStoreContext);
1084 PCCTL_CONTEXT WINAPI CertDuplicateCTLContext(PCCTL_CONTEXT pCtlContext)
1086 FIXME("(%p): stub\n", pCtlContext );
1090 BOOL WINAPI CertFreeCTLContext(PCCTL_CONTEXT pCtlContext)
1092 FIXME("(%p): stub\n", pCtlContext );
1096 BOOL WINAPI CertDeleteCTLFromStore(PCCTL_CONTEXT pCtlContext)
1098 FIXME("(%p): stub\n", pCtlContext);
1102 PCCTL_CONTEXT WINAPI CertEnumCTLsInStore(HCERTSTORE hCertStore,
1103 PCCTL_CONTEXT pPrev)
1105 FIXME("(%p, %p): stub\n", hCertStore, pPrev);
1109 HCERTSTORE WINAPI CertDuplicateStore(HCERTSTORE hCertStore)
1111 WINECRYPT_CERTSTORE *hcs = (WINECRYPT_CERTSTORE *)hCertStore;
1113 TRACE("(%p)\n", hCertStore);
1115 if (hcs && hcs->dwMagic == WINE_CRYPTCERTSTORE_MAGIC)
1116 InterlockedIncrement(&hcs->ref);
1120 BOOL WINAPI CertCloseStore(HCERTSTORE hCertStore, DWORD dwFlags)
1122 WINECRYPT_CERTSTORE *hcs = (WINECRYPT_CERTSTORE *) hCertStore;
1124 TRACE("(%p, %08x)\n", hCertStore, dwFlags);
1129 if ( hcs->dwMagic != WINE_CRYPTCERTSTORE_MAGIC )
1132 if (InterlockedDecrement(&hcs->ref) == 0)
1134 TRACE("%p's ref count is 0, freeing\n", hcs);
1136 if (!(hcs->dwOpenFlags & CERT_STORE_NO_CRYPT_RELEASE_FLAG))
1137 CryptReleaseContext(hcs->cryptProv, 0);
1138 hcs->closeStore(hcs, dwFlags);
1141 TRACE("%p's ref count is %d\n", hcs, hcs->ref);
1145 BOOL WINAPI CertControlStore(HCERTSTORE hCertStore, DWORD dwFlags,
1146 DWORD dwCtrlType, void const *pvCtrlPara)
1148 WINECRYPT_CERTSTORE *hcs = (WINECRYPT_CERTSTORE *)hCertStore;
1151 TRACE("(%p, %08x, %d, %p)\n", hCertStore, dwFlags, dwCtrlType,
1156 else if (hcs->dwMagic != WINE_CRYPTCERTSTORE_MAGIC)
1161 ret = hcs->control(hCertStore, dwFlags, dwCtrlType, pvCtrlPara);
1168 BOOL WINAPI CertGetStoreProperty(HCERTSTORE hCertStore, DWORD dwPropId,
1169 void *pvData, DWORD *pcbData)
1171 PWINECRYPT_CERTSTORE store = (PWINECRYPT_CERTSTORE)hCertStore;
1174 TRACE("(%p, %d, %p, %p)\n", hCertStore, dwPropId, pvData, pcbData);
1178 case CERT_ACCESS_STATE_PROP_ID:
1181 *pcbData = sizeof(DWORD);
1184 else if (*pcbData < sizeof(DWORD))
1186 SetLastError(ERROR_MORE_DATA);
1187 *pcbData = sizeof(DWORD);
1193 if (store->type != StoreTypeMem &&
1194 !(store->dwOpenFlags & CERT_STORE_READONLY_FLAG))
1195 state |= CERT_ACCESS_STATE_WRITE_PERSIST_FLAG;
1196 *(DWORD *)pvData = state;
1201 if (store->properties)
1203 CRYPT_DATA_BLOB blob;
1205 ret = ContextPropertyList_FindProperty(store->properties, dwPropId,
1210 *pcbData = blob.cbData;
1211 else if (*pcbData < blob.cbData)
1213 SetLastError(ERROR_MORE_DATA);
1214 *pcbData = blob.cbData;
1219 memcpy(pvData, blob.pbData, blob.cbData);
1220 *pcbData = blob.cbData;
1224 SetLastError(CRYPT_E_NOT_FOUND);
1227 SetLastError(CRYPT_E_NOT_FOUND);
1232 BOOL WINAPI CertSetStoreProperty(HCERTSTORE hCertStore, DWORD dwPropId,
1233 DWORD dwFlags, const void *pvData)
1235 PWINECRYPT_CERTSTORE store = (PWINECRYPT_CERTSTORE)hCertStore;
1238 TRACE("(%p, %d, %08x, %p)\n", hCertStore, dwPropId, dwFlags, pvData);
1240 if (!store->properties)
1241 store->properties = ContextPropertyList_Create();
1244 case CERT_ACCESS_STATE_PROP_ID:
1245 SetLastError(E_INVALIDARG);
1250 const CRYPT_DATA_BLOB *blob = (const CRYPT_DATA_BLOB *)pvData;
1252 ret = ContextPropertyList_SetProperty(store->properties, dwPropId,
1253 blob->pbData, blob->cbData);
1257 ContextPropertyList_RemoveProperty(store->properties, dwPropId);
1264 DWORD WINAPI CertEnumCTLContextProperties(PCCTL_CONTEXT pCTLContext,
1267 FIXME("(%p, %d): stub\n", pCTLContext, dwPropId);
1271 BOOL WINAPI CertGetCTLContextProperty(PCCTL_CONTEXT pCTLContext,
1272 DWORD dwPropId, void *pvData, DWORD *pcbData)
1274 FIXME("(%p, %d, %p, %p): stub\n", pCTLContext, dwPropId, pvData, pcbData);
1278 BOOL WINAPI CertSetCTLContextProperty(PCCTL_CONTEXT pCTLContext,
1279 DWORD dwPropId, DWORD dwFlags, const void *pvData)
1281 FIXME("(%p, %d, %08x, %p): stub\n", pCTLContext, dwPropId, dwFlags,
1286 static LONG CRYPT_OpenParentStore(DWORD dwFlags,
1287 void *pvSystemStoreLocationPara, HKEY *key)
1292 TRACE("(%08x, %p)\n", dwFlags, pvSystemStoreLocationPara);
1294 switch (dwFlags & CERT_SYSTEM_STORE_LOCATION_MASK)
1296 case CERT_SYSTEM_STORE_LOCAL_MACHINE:
1297 root = HKEY_LOCAL_MACHINE;
1298 base = CERT_LOCAL_MACHINE_SYSTEM_STORE_REGPATH;
1300 case CERT_SYSTEM_STORE_CURRENT_USER:
1301 root = HKEY_CURRENT_USER;
1302 base = CERT_LOCAL_MACHINE_SYSTEM_STORE_REGPATH;
1304 case CERT_SYSTEM_STORE_CURRENT_SERVICE:
1305 /* hklm\Software\Microsoft\Cryptography\Services\servicename\
1306 * SystemCertificates
1308 FIXME("CERT_SYSTEM_STORE_CURRENT_SERVICE\n");
1309 return ERROR_FILE_NOT_FOUND;
1310 case CERT_SYSTEM_STORE_SERVICES:
1311 /* hklm\Software\Microsoft\Cryptography\Services\servicename\
1312 * SystemCertificates
1314 FIXME("CERT_SYSTEM_STORE_SERVICES\n");
1315 return ERROR_FILE_NOT_FOUND;
1316 case CERT_SYSTEM_STORE_USERS:
1317 /* hku\user sid\Software\Microsoft\SystemCertificates */
1318 FIXME("CERT_SYSTEM_STORE_USERS\n");
1319 return ERROR_FILE_NOT_FOUND;
1320 case CERT_SYSTEM_STORE_CURRENT_USER_GROUP_POLICY:
1321 root = HKEY_CURRENT_USER;
1322 base = CERT_GROUP_POLICY_SYSTEM_STORE_REGPATH;
1324 case CERT_SYSTEM_STORE_LOCAL_MACHINE_GROUP_POLICY:
1325 root = HKEY_LOCAL_MACHINE;
1326 base = CERT_GROUP_POLICY_SYSTEM_STORE_REGPATH;
1328 case CERT_SYSTEM_STORE_LOCAL_MACHINE_ENTERPRISE:
1329 /* hklm\Software\Microsoft\EnterpriseCertificates */
1330 FIXME("CERT_SYSTEM_STORE_LOCAL_MACHINE_ENTERPRISE\n");
1331 return ERROR_FILE_NOT_FOUND;
1333 return ERROR_FILE_NOT_FOUND;
1336 return RegOpenKeyExW(root, base, 0, KEY_READ, key);
1339 BOOL WINAPI CertEnumSystemStore(DWORD dwFlags, void *pvSystemStoreLocationPara,
1340 void *pvArg, PFN_CERT_ENUM_SYSTEM_STORE pfnEnum)
1346 TRACE("(%08x, %p, %p, %p)\n", dwFlags, pvSystemStoreLocationPara, pvArg,
1349 rc = CRYPT_OpenParentStore(dwFlags, pvArg, &key);
1353 CERT_SYSTEM_STORE_INFO info = { sizeof(info) };
1357 WCHAR name[MAX_PATH];
1358 DWORD size = sizeof(name) / sizeof(name[0]);
1360 rc = RegEnumKeyExW(key, index++, name, &size, NULL, NULL, NULL,
1363 ret = pfnEnum(name, 0, &info, NULL, pvArg);
1364 } while (ret && !rc);
1365 if (ret && rc != ERROR_NO_MORE_ITEMS)