2 * Copyright 2002 Mike McCormack for CodeWeavers
3 * Copyright 2004,2005 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 * - As you can see in the stubs below, support for CRLs and CTLs is missing.
21 * Mostly this should be copy-paste work, and some code (e.g. extended
22 * properties) could be shared between them.
23 * - Opening a cert store provider should be morphed to support loading
25 * - The concept of physical stores and locations isn't implemented. (This
26 * doesn't mean registry stores et al aren't implemented. See the PSDK for
27 * registering and enumerating physical stores and locations.)
28 * - Many flags, options and whatnot are unimplemented.
35 #include "wine/debug.h"
36 #include "wine/list.h"
37 #include "crypt32_private.h"
39 WINE_DEFAULT_DEBUG_CHANNEL(crypt);
41 #define WINE_CRYPTCERTSTORE_MAGIC 0x74726563
42 /* The following aren't defined in wincrypt.h, as they're "reserved" */
43 #define CERT_CERT_PROP_ID 32
44 #define CERT_CRL_PROP_ID 33
45 #define CERT_CTL_PROP_ID 34
47 struct WINE_CRYPTCERTSTORE;
49 typedef struct WINE_CRYPTCERTSTORE * (*StoreOpenFunc)(HCRYPTPROV hCryptProv,
50 DWORD dwFlags, const void *pvPara);
52 struct _WINE_CERT_CONTEXT_REF;
54 /* Called to enumerate the next certificate in a store. The returned pointer
55 * must be newly allocated (via HeapAlloc): CertFreeCertificateContext frees
58 typedef struct _WINE_CERT_CONTEXT_REF * (*EnumCertFunc)
59 (struct WINE_CRYPTCERTSTORE *store, struct _WINE_CERT_CONTEXT_REF *pPrev);
61 struct _WINE_CERT_CONTEXT;
63 /* Called to create a new reference to an existing cert context. Should call
64 * CRYPT_InitCertRef to make sure the reference count is properly updated.
65 * If the store does not provide any additional allocated data (that is, does
66 * not need to implement a FreeCertFunc), it may use CRYPT_CreateCertRef for
69 typedef struct _WINE_CERT_CONTEXT_REF * (*CreateRefFunc)
70 (struct _WINE_CERT_CONTEXT *context, HCERTSTORE store);
72 /* Optional, called when a cert context reference is being freed. Don't free
73 * the ref pointer itself, CertFreeCertificateContext does that.
75 typedef void (*FreeCertFunc)(struct _WINE_CERT_CONTEXT_REF *ref);
77 typedef enum _CertStoreType {
84 /* A cert store is polymorphic through the use of function pointers. A type
85 * is still needed to distinguish collection stores from other types.
86 * On the function pointers:
87 * - closeStore is called when the store's ref count becomes 0
88 * - addCert is called with a PWINE_CERT_CONTEXT as the second parameter
89 * - control is optional, but should be implemented by any store that supports
92 typedef struct WINE_CRYPTCERTSTORE
99 PFN_CERT_STORE_PROV_CLOSE closeStore;
100 PFN_CERT_STORE_PROV_WRITE_CERT addCert;
101 CreateRefFunc createCertRef;
102 EnumCertFunc enumCert;
103 PFN_CERT_STORE_PROV_DELETE_CERT deleteCert;
104 FreeCertFunc freeCert; /* optional */
105 PFN_CERT_STORE_PROV_CONTROL control; /* optional */
106 } WINECRYPT_CERTSTORE, *PWINECRYPT_CERTSTORE;
108 /* A certificate context has pointers to data that are owned by this module,
109 * so rather than duplicate the data every time a certificate context is
110 * copied, I keep a reference count to the data. Thus I have two data
111 * structures, the "true" certificate context (that has the reference count)
112 * and a reference certificate context, that has a pointer to the true context.
113 * Each one can be cast to a PCERT_CONTEXT, though you'll usually be dealing
114 * with the reference version.
116 typedef struct _WINE_CERT_CONTEXT
121 struct list extendedProperties;
122 } WINE_CERT_CONTEXT, *PWINE_CERT_CONTEXT;
124 typedef struct _WINE_CERT_CONTEXT_REF
127 WINE_CERT_CONTEXT *context;
128 } WINE_CERT_CONTEXT_REF, *PWINE_CERT_CONTEXT_REF;
130 /* An extended certificate property in serialized form is prefixed by this
133 typedef struct _WINE_CERT_PROP_HEADER
136 DWORD unknown; /* always 1 */
138 } WINE_CERT_PROP_HEADER, *PWINE_CERT_PROP_HEADER;
140 /* Stores an extended property in a cert. */
141 typedef struct _WINE_CERT_PROPERTY
143 WINE_CERT_PROP_HEADER hdr;
146 } WINE_CERT_PROPERTY, *PWINE_CERT_PROPERTY;
148 /* A mem store has a list of these. They're also returned by the mem store
149 * during enumeration.
151 typedef struct _WINE_CERT_LIST_ENTRY
153 WINE_CERT_CONTEXT_REF cert;
155 } WINE_CERT_LIST_ENTRY, *PWINE_CERT_LIST_ENTRY;
157 typedef struct _WINE_MEMSTORE
159 WINECRYPT_CERTSTORE hdr;
162 } WINE_MEMSTORE, *PWINE_MEMSTORE;
164 /* Like CertGetCertificateContextProperty, but operates directly on the
165 * WINE_CERT_CONTEXT. Doesn't support special-case properties, since they
166 * are handled by CertGetCertificateContextProperty, and are particular to the
167 * store in which the property exists (which is separate from the context.)
169 static BOOL WINAPI CRYPT_GetCertificateContextProperty(
170 PWINE_CERT_CONTEXT context, DWORD dwPropId, void *pvData, DWORD *pcbData);
172 /* Like CertSetCertificateContextProperty, but operates directly on the
173 * WINE_CERT_CONTEXT. Doesn't handle special cases, since they're handled by
174 * CertSetCertificateContextProperty anyway.
176 static BOOL WINAPI CRYPT_SetCertificateContextProperty(
177 PWINE_CERT_CONTEXT context, DWORD dwPropId, DWORD dwFlags, const void *pvData);
179 static void CRYPT_InitStore(WINECRYPT_CERTSTORE *store, HCRYPTPROV hCryptProv,
180 DWORD dwFlags, CertStoreType type)
183 store->dwMagic = WINE_CRYPTCERTSTORE_MAGIC;
187 hCryptProv = CRYPT_GetDefaultProvider();
188 dwFlags |= CERT_STORE_NO_CRYPT_RELEASE_FLAG;
190 store->cryptProv = hCryptProv;
191 store->dwOpenFlags = dwFlags;
194 /* Initializes the reference ref to point to pCertContext, which is assumed to
195 * be a PWINE_CERT_CONTEXT, and increments pCertContext's reference count.
196 * Also sets the hCertStore member of the reference to store.
198 static void CRYPT_InitCertRef(PWINE_CERT_CONTEXT_REF ref,
199 PWINE_CERT_CONTEXT context, HCERTSTORE store)
201 TRACE("(%p, %p)\n", ref, context);
202 memcpy(&ref->cert, context, sizeof(ref->cert));
203 ref->context = context;
204 InterlockedIncrement(&context->ref);
205 ref->cert.hCertStore = store;
208 static PWINE_CERT_CONTEXT_REF CRYPT_CreateCertRef(PWINE_CERT_CONTEXT context,
211 PWINE_CERT_CONTEXT_REF pCertRef = HeapAlloc(GetProcessHeap(), 0,
212 sizeof(WINE_CERT_CONTEXT_REF));
215 CRYPT_InitCertRef(pCertRef, context, store);
219 static BOOL WINAPI CRYPT_MemAddCert(HCERTSTORE store, PCCERT_CONTEXT pCert,
220 DWORD dwAddDisposition)
222 WINE_MEMSTORE *ms = (WINE_MEMSTORE *)store;
223 BOOL add = FALSE, ret;
225 TRACE("(%p, %p, %ld)\n", store, pCert, dwAddDisposition);
227 switch (dwAddDisposition)
229 case CERT_STORE_ADD_ALWAYS:
232 case CERT_STORE_ADD_NEW:
234 BYTE hashToAdd[20], hash[20];
235 DWORD size = sizeof(hashToAdd);
237 ret = CRYPT_GetCertificateContextProperty((PWINE_CERT_CONTEXT)pCert,
238 CERT_HASH_PROP_ID, hashToAdd, &size);
241 PWINE_CERT_LIST_ENTRY cursor;
243 /* Add if no cert with the same hash is found. */
245 EnterCriticalSection(&ms->cs);
246 LIST_FOR_EACH_ENTRY(cursor, &ms->certs, WINE_CERT_LIST_ENTRY, entry)
249 ret = CertGetCertificateContextProperty(&cursor->cert.cert,
250 CERT_HASH_PROP_ID, hash, &size);
251 if (ret && !memcmp(hashToAdd, hash, size))
253 TRACE("found matching certificate, not adding\n");
254 SetLastError(CRYPT_E_EXISTS);
259 LeaveCriticalSection(&ms->cs);
263 case CERT_STORE_ADD_REPLACE_EXISTING:
265 BYTE hashToAdd[20], hash[20];
266 DWORD size = sizeof(hashToAdd);
269 ret = CRYPT_GetCertificateContextProperty((PWINE_CERT_CONTEXT)pCert,
270 CERT_HASH_PROP_ID, hashToAdd, &size);
273 PWINE_CERT_LIST_ENTRY cursor, next;
275 /* Look for existing cert to delete */
276 EnterCriticalSection(&ms->cs);
277 LIST_FOR_EACH_ENTRY_SAFE(cursor, next, &ms->certs,
278 WINE_CERT_LIST_ENTRY, entry)
281 ret = CertGetCertificateContextProperty(&cursor->cert.cert,
282 CERT_HASH_PROP_ID, hash, &size);
283 if (ret && !memcmp(hashToAdd, hash, size))
285 TRACE("found matching certificate, replacing\n");
286 list_remove(&cursor->entry);
287 CertFreeCertificateContext((PCCERT_CONTEXT)cursor);
291 LeaveCriticalSection(&ms->cs);
296 FIXME("Unimplemented add disposition %ld\n", dwAddDisposition);
301 PWINE_CERT_LIST_ENTRY entry = HeapAlloc(GetProcessHeap(), 0,
302 sizeof(WINE_CERT_LIST_ENTRY));
306 TRACE("adding %p\n", entry);
307 CRYPT_InitCertRef(&entry->cert, (PWINE_CERT_CONTEXT)pCert, store);
308 list_init(&entry->entry);
309 EnterCriticalSection(&ms->cs);
310 list_add_tail(&ms->certs, &entry->entry);
311 LeaveCriticalSection(&ms->cs);
322 static PWINE_CERT_CONTEXT_REF CRYPT_MemEnumCert(PWINECRYPT_CERTSTORE store,
323 PWINE_CERT_CONTEXT_REF pPrev)
325 WINE_MEMSTORE *ms = (WINE_MEMSTORE *)store;
326 PWINE_CERT_LIST_ENTRY prevEntry = (PWINE_CERT_LIST_ENTRY)pPrev, ret;
327 struct list *listNext;
329 TRACE("(%p, %p)\n", store, pPrev);
330 EnterCriticalSection(&ms->cs);
333 listNext = list_next(&ms->certs, &prevEntry->entry);
334 CertFreeCertificateContext((PCCERT_CONTEXT)pPrev);
337 listNext = list_next(&ms->certs, &ms->certs);
340 ret = HeapAlloc(GetProcessHeap(), 0, sizeof(WINE_CERT_LIST_ENTRY));
341 memcpy(ret, LIST_ENTRY(listNext, WINE_CERT_LIST_ENTRY, entry),
342 sizeof(WINE_CERT_LIST_ENTRY));
343 InterlockedIncrement(&ret->cert.context->ref);
347 SetLastError(CRYPT_E_NOT_FOUND);
350 LeaveCriticalSection(&ms->cs);
352 TRACE("returning %p\n", ret);
353 return (PWINE_CERT_CONTEXT_REF)ret;
356 static BOOL WINAPI CRYPT_MemDeleteCert(HCERTSTORE hCertStore,
357 PCCERT_CONTEXT pCertContext, DWORD dwFlags)
359 WINE_MEMSTORE *store = (WINE_MEMSTORE *)hCertStore;
360 WINE_CERT_CONTEXT_REF *ref = (WINE_CERT_CONTEXT_REF *)pCertContext;
361 PWINE_CERT_LIST_ENTRY cert, next;
364 /* Find the entry associated with the passed-in context, since the
365 * passed-in context may not be a list entry itself (e.g. if it came from
366 * CertDuplicateCertificateContext.) Pointing to the same context is
367 * a sufficient test of equality.
369 EnterCriticalSection(&store->cs);
370 LIST_FOR_EACH_ENTRY_SAFE(cert, next, &store->certs, WINE_CERT_LIST_ENTRY,
373 if (cert->cert.context == ref->context)
375 TRACE("removing %p\n", cert);
376 /* FIXME: this isn't entirely thread-safe, the entry itself isn't
379 list_remove(&cert->entry);
380 cert->entry.prev = cert->entry.next = &store->certs;
381 CertFreeCertificateContext((PCCERT_CONTEXT)cert);
386 LeaveCriticalSection(&store->cs);
390 static void WINAPI CRYPT_MemCloseStore(HCERTSTORE hCertStore, DWORD dwFlags)
392 WINE_MEMSTORE *store = (WINE_MEMSTORE *)hCertStore;
393 PWINE_CERT_LIST_ENTRY cert, next;
395 TRACE("(%p, %08lx)\n", store, dwFlags);
397 FIXME("Unimplemented flags: %08lx\n", dwFlags);
399 /* Note that CertFreeCertificateContext calls HeapFree on the passed-in
400 * pointer if its ref-count reaches zero. That's okay here because there
401 * aren't any allocated data outside of the WINE_CERT_CONTEXT_REF portion
402 * of the CertListEntry.
404 LIST_FOR_EACH_ENTRY_SAFE(cert, next, &store->certs, WINE_CERT_LIST_ENTRY,
407 TRACE("removing %p\n", cert);
408 list_remove(&cert->entry);
409 CertFreeCertificateContext((PCCERT_CONTEXT)cert);
411 DeleteCriticalSection(&store->cs);
412 HeapFree(GetProcessHeap(), 0, store);
415 static WINECRYPT_CERTSTORE *CRYPT_MemOpenStore(HCRYPTPROV hCryptProv,
416 DWORD dwFlags, const void *pvPara)
418 PWINE_MEMSTORE store;
420 TRACE("(%ld, %08lx, %p)\n", hCryptProv, dwFlags, pvPara);
422 if (dwFlags & CERT_STORE_DELETE_FLAG)
424 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
429 store = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
430 sizeof(WINE_MEMSTORE));
433 CRYPT_InitStore(&store->hdr, hCryptProv, dwFlags, StoreTypeMem);
434 store->hdr.closeStore = CRYPT_MemCloseStore;
435 store->hdr.addCert = CRYPT_MemAddCert;
436 store->hdr.createCertRef = CRYPT_CreateCertRef;
437 store->hdr.enumCert = CRYPT_MemEnumCert;
438 store->hdr.deleteCert = CRYPT_MemDeleteCert;
439 store->hdr.freeCert = NULL;
440 InitializeCriticalSection(&store->cs);
441 list_init(&store->certs);
444 return (PWINECRYPT_CERTSTORE)store;
447 static void WINAPI CRYPT_DummyCloseStore(HCERTSTORE hCertStore, DWORD dwFlags)
449 HeapFree(GetProcessHeap(), 0, (PWINECRYPT_CERTSTORE)hCertStore);
452 static BOOL WINAPI CRYPT_DummyAddCert(HCERTSTORE store, PCCERT_CONTEXT pCert,
453 DWORD dwAddDisposition)
458 static PWINE_CERT_CONTEXT_REF CRYPT_DummyEnumCert(PWINECRYPT_CERTSTORE store,
459 PWINE_CERT_CONTEXT_REF pPrev)
464 static BOOL WINAPI CRYPT_DummyDeleteCert(HCERTSTORE hCertStore,
465 PCCERT_CONTEXT pCertContext, DWORD dwFlags)
470 static WINECRYPT_CERTSTORE *CRYPT_DummyOpenStore(HCRYPTPROV hCryptProv,
471 DWORD dwFlags, const void *pvPara)
473 PWINECRYPT_CERTSTORE store;
475 TRACE("(%ld, %08lx, %p)\n", hCryptProv, dwFlags, pvPara);
477 if (dwFlags & CERT_STORE_DELETE_FLAG)
479 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
484 store = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
485 sizeof(WINECRYPT_CERTSTORE));
488 CRYPT_InitStore(store, hCryptProv, dwFlags, StoreTypeDummy);
489 store->closeStore = CRYPT_DummyCloseStore;
490 store->addCert = CRYPT_DummyAddCert;
491 store->createCertRef = CRYPT_CreateCertRef;
492 store->enumCert = CRYPT_DummyEnumCert;
493 store->deleteCert = CRYPT_DummyDeleteCert;
494 store->freeCert = NULL;
497 return (PWINECRYPT_CERTSTORE)store;
501 HCERTSTORE WINAPI CertOpenStore(LPCSTR lpszStoreProvider,
502 DWORD dwMsgAndCertEncodingType, HCRYPTPROV hCryptProv, DWORD dwFlags,
505 WINECRYPT_CERTSTORE *hcs;
506 StoreOpenFunc openFunc = NULL;
508 TRACE("(%s, %08lx, %08lx, %08lx, %p)\n", debugstr_a(lpszStoreProvider),
509 dwMsgAndCertEncodingType, hCryptProv, dwFlags, pvPara);
511 if (!HIWORD(lpszStoreProvider))
513 switch (LOWORD(lpszStoreProvider))
515 case (int)CERT_STORE_PROV_MEMORY:
516 openFunc = CRYPT_MemOpenStore;
518 case (int)CERT_STORE_PROV_REG:
519 case (int)CERT_STORE_PROV_SYSTEM_A:
520 case (int)CERT_STORE_PROV_SYSTEM_W:
521 case (int)CERT_STORE_PROV_COLLECTION:
522 openFunc = CRYPT_DummyOpenStore;
525 if (LOWORD(lpszStoreProvider))
526 FIXME("unimplemented type %d\n", LOWORD(lpszStoreProvider));
529 else if (!strcasecmp(lpszStoreProvider, sz_CERT_STORE_PROV_MEMORY))
530 openFunc = CRYPT_MemOpenStore;
531 else if (!strcasecmp(lpszStoreProvider, sz_CERT_STORE_PROV_SYSTEM))
532 openFunc = CRYPT_DummyOpenStore;
533 else if (!strcasecmp(lpszStoreProvider, sz_CERT_STORE_PROV_COLLECTION))
534 openFunc = CRYPT_DummyOpenStore;
537 FIXME("unimplemented type %s\n", lpszStoreProvider);
543 /* FIXME: need to look for an installed provider for this type */
544 SetLastError(ERROR_FILE_NOT_FOUND);
548 hcs = openFunc(hCryptProv, dwFlags, pvPara);
549 return (HCERTSTORE)hcs;
552 HCERTSTORE WINAPI CertOpenSystemStoreA(HCRYPTPROV hProv,
553 LPCSTR szSubSystemProtocol)
555 return CertOpenStore( CERT_STORE_PROV_SYSTEM_A, 0, 0,
556 CERT_SYSTEM_STORE_CURRENT_USER | CERT_SYSTEM_STORE_LOCAL_MACHINE |
557 CERT_SYSTEM_STORE_USERS, szSubSystemProtocol );
560 HCERTSTORE WINAPI CertOpenSystemStoreW(HCRYPTPROV hProv,
561 LPCWSTR szSubSystemProtocol)
563 return CertOpenStore( CERT_STORE_PROV_SYSTEM_W, 0, 0,
564 CERT_SYSTEM_STORE_CURRENT_USER | CERT_SYSTEM_STORE_LOCAL_MACHINE |
565 CERT_SYSTEM_STORE_USERS, szSubSystemProtocol );
568 BOOL WINAPI CertSaveStore(HCERTSTORE hCertStore, DWORD dwMsgAndCertEncodingType,
569 DWORD dwSaveAs, DWORD dwSaveTo, void* pvSaveToPara, DWORD dwFlags)
571 FIXME("(%p,%ld,%ld,%ld,%p,%08lx) stub!\n", hCertStore,
572 dwMsgAndCertEncodingType, dwSaveAs, dwSaveTo, pvSaveToPara, dwFlags);
576 PCCRL_CONTEXT WINAPI CertCreateCRLContext( DWORD dwCertEncodingType,
577 const BYTE* pbCrlEncoded, DWORD cbCrlEncoded)
582 TRACE("%08lx %p %08lx\n", dwCertEncodingType, pbCrlEncoded, cbCrlEncoded);
584 /* FIXME: semi-stub, need to use CryptDecodeObjectEx to decode the CRL. */
585 pcrl = HeapAlloc( GetProcessHeap(), 0, sizeof (CRL_CONTEXT) );
589 data = HeapAlloc( GetProcessHeap(), 0, cbCrlEncoded );
592 HeapFree( GetProcessHeap(), 0, pcrl );
596 pcrl->dwCertEncodingType = dwCertEncodingType;
597 pcrl->pbCrlEncoded = data;
598 pcrl->cbCrlEncoded = cbCrlEncoded;
599 pcrl->pCrlInfo = NULL;
600 pcrl->hCertStore = 0;
605 /* Decodes the encoded certificate and creates the certificate context for it.
606 * The reference count is initially zero, so you must create a reference to it
607 * to avoid leaking memory.
609 static PWINE_CERT_CONTEXT CRYPT_CreateCertificateContext(
610 DWORD dwCertEncodingType, const BYTE *pbCertEncoded, DWORD cbCertEncoded)
612 PWINE_CERT_CONTEXT cert = NULL;
614 PCERT_INFO certInfo = NULL;
617 TRACE("(%08lx, %p, %ld)\n", dwCertEncodingType, pbCertEncoded,
620 ret = CryptDecodeObjectEx(X509_ASN_ENCODING, X509_CERT_TO_BE_SIGNED,
621 pbCertEncoded, cbCertEncoded,
622 CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_NOCOPY_FLAG, NULL,
623 (BYTE *)&certInfo, &size);
628 cert = HeapAlloc(GetProcessHeap(), 0, sizeof(WINE_CERT_CONTEXT));
631 data = HeapAlloc(GetProcessHeap(), 0, cbCertEncoded);
634 HeapFree(GetProcessHeap(), 0, cert);
638 memcpy(data, pbCertEncoded, cbCertEncoded);
639 cert->cert.dwCertEncodingType = dwCertEncodingType;
640 cert->cert.pbCertEncoded = data;
641 cert->cert.cbCertEncoded = cbCertEncoded;
642 cert->cert.pCertInfo = certInfo;
643 cert->cert.hCertStore = 0;
645 InitializeCriticalSection(&cert->cs);
646 list_init(&cert->extendedProperties);
653 static void CRYPT_FreeCert(PWINE_CERT_CONTEXT context)
655 PWINE_CERT_PROPERTY prop, next;
657 HeapFree(GetProcessHeap(), 0, context->cert.pbCertEncoded);
658 LocalFree(context->cert.pCertInfo);
659 HeapFree(GetProcessHeap(), 0, context);
660 DeleteCriticalSection(&context->cs);
661 LIST_FOR_EACH_ENTRY_SAFE(prop, next, &context->extendedProperties,
662 WINE_CERT_PROPERTY, entry)
664 list_remove(&prop->entry);
665 HeapFree(GetProcessHeap(), 0, prop->pbData);
666 HeapFree(GetProcessHeap(), 0, prop);
670 PCCERT_CONTEXT WINAPI CertCreateCertificateContext(DWORD dwCertEncodingType,
671 const BYTE *pbCertEncoded, DWORD cbCertEncoded)
673 PWINE_CERT_CONTEXT cert;
674 PWINE_CERT_CONTEXT_REF ret = NULL;
676 TRACE("(%08lx, %p, %ld)\n", dwCertEncodingType, pbCertEncoded,
679 cert = CRYPT_CreateCertificateContext(dwCertEncodingType, pbCertEncoded,
682 ret = CRYPT_CreateCertRef(cert, 0);
683 return (PCCERT_CONTEXT)ret;
686 /* Since the properties are stored in a list, this is a tad inefficient
687 * (O(n^2)) since I have to find the previous position every time.
689 DWORD WINAPI CertEnumCertificateContextProperties(PCCERT_CONTEXT pCertContext,
692 PWINE_CERT_CONTEXT_REF ref = (PWINE_CERT_CONTEXT_REF)pCertContext;
695 TRACE("(%p, %ld)\n", pCertContext, dwPropId);
697 EnterCriticalSection(&ref->context->cs);
700 PWINE_CERT_PROPERTY cursor = NULL;
702 LIST_FOR_EACH_ENTRY(cursor, &ref->context->extendedProperties,
703 WINE_CERT_PROPERTY, entry)
705 if (cursor->hdr.propID == dwPropId)
710 if (cursor->entry.next != &ref->context->extendedProperties)
711 ret = LIST_ENTRY(cursor->entry.next, WINE_CERT_PROPERTY,
719 else if (!list_empty(&ref->context->extendedProperties))
720 ret = LIST_ENTRY(ref->context->extendedProperties.next,
721 WINE_CERT_PROPERTY, entry)->hdr.propID;
724 LeaveCriticalSection(&ref->context->cs);
728 static BOOL WINAPI CRYPT_GetCertificateContextProperty(
729 PWINE_CERT_CONTEXT context, DWORD dwPropId, void *pvData, DWORD *pcbData)
731 PWINE_CERT_PROPERTY prop;
734 TRACE("(%p, %ld, %p, %p)\n", context, dwPropId, pvData, pcbData);
736 EnterCriticalSection(&context->cs);
739 LIST_FOR_EACH_ENTRY(prop, &context->extendedProperties,
740 WINE_CERT_PROPERTY, entry)
742 if (prop->hdr.propID == dwPropId)
746 *pcbData = prop->hdr.cb;
749 else if (*pcbData < prop->hdr.cb)
751 SetLastError(ERROR_MORE_DATA);
752 *pcbData = prop->hdr.cb;
756 memcpy(pvData, prop->pbData, prop->hdr.cb);
757 *pcbData = prop->hdr.cb;
766 /* Implicit properties */
769 case CERT_SHA1_HASH_PROP_ID:
770 ret = CryptHashCertificate(0, CALG_SHA1, 0,
771 context->cert.pbCertEncoded, context->cert.cbCertEncoded, pvData,
775 CRYPT_DATA_BLOB blob = { *pcbData, pvData };
777 ret = CRYPT_SetCertificateContextProperty(context, dwPropId,
781 case CERT_KEY_PROV_INFO_PROP_ID:
782 case CERT_MD5_HASH_PROP_ID:
783 case CERT_SIGNATURE_HASH_PROP_ID:
784 case CERT_KEY_IDENTIFIER_PROP_ID:
785 case CERT_SUBJECT_PUBLIC_KEY_MD5_HASH_PROP_ID:
786 case CERT_ISSUER_SERIAL_NUMBER_MD5_HASH_PROP_ID:
787 case CERT_SUBJECT_NAME_MD5_HASH_PROP_ID:
788 FIXME("implicit property %ld\n", dwPropId);
792 LeaveCriticalSection(&context->cs);
793 TRACE("returning %d\n", ret);
797 BOOL WINAPI CertGetCertificateContextProperty(PCCERT_CONTEXT pCertContext,
798 DWORD dwPropId, void *pvData, DWORD *pcbData)
800 PWINE_CERT_CONTEXT_REF ref = (PWINE_CERT_CONTEXT_REF)pCertContext;
803 TRACE("(%p, %ld, %p, %p)\n", pCertContext, dwPropId, pvData, pcbData);
805 /* Special cases for invalid/special prop IDs.
810 case CERT_CERT_PROP_ID:
811 case CERT_CRL_PROP_ID:
812 case CERT_CTL_PROP_ID:
813 SetLastError(HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER));
815 case CERT_ACCESS_STATE_PROP_ID:
818 *pcbData = sizeof(DWORD);
821 else if (*pcbData < sizeof(DWORD))
823 SetLastError(ERROR_MORE_DATA);
824 *pcbData = sizeof(DWORD);
831 if (pCertContext->hCertStore)
833 PWINECRYPT_CERTSTORE store =
834 (PWINECRYPT_CERTSTORE)pCertContext->hCertStore;
836 /* Take advantage of knowledge of the stores to answer the
837 * access state question
839 if (store->type != StoreTypeReg ||
840 !(store->dwOpenFlags & CERT_STORE_READONLY_FLAG))
841 state |= CERT_ACCESS_STATE_WRITE_PERSIST_FLAG;
843 *(DWORD *)pvData = state;
848 ret = CRYPT_GetCertificateContextProperty(ref->context, dwPropId,
850 TRACE("returning %d\n", ret);
854 /* Copies cbData bytes from pbData to the context's property with ID
857 static BOOL CRYPT_SaveCertificateContextProperty(PWINE_CERT_CONTEXT context,
858 DWORD dwPropId, const BYTE *pbData, size_t cbData)
865 data = HeapAlloc(GetProcessHeap(), 0, cbData);
867 memcpy(data, pbData, cbData);
873 PWINE_CERT_PROPERTY prop;
875 EnterCriticalSection(&context->cs);
876 LIST_FOR_EACH_ENTRY(prop, &context->extendedProperties,
877 WINE_CERT_PROPERTY, entry)
879 if (prop->hdr.propID == dwPropId)
882 if (prop && prop->entry.next != &context->extendedProperties)
884 HeapFree(GetProcessHeap(), 0, prop->pbData);
885 prop->hdr.cb = cbData;
886 prop->pbData = cbData ? data : NULL;
891 prop = HeapAlloc(GetProcessHeap(), 0, sizeof(WINE_CERT_PROPERTY));
894 prop->hdr.propID = dwPropId;
895 prop->hdr.unknown = 1;
896 prop->hdr.cb = cbData;
897 list_init(&prop->entry);
898 prop->pbData = cbData ? data : NULL;
899 list_add_tail(&context->extendedProperties, &prop->entry);
903 HeapFree(GetProcessHeap(), 0, data);
905 LeaveCriticalSection(&context->cs);
910 static BOOL WINAPI CRYPT_SetCertificateContextProperty(
911 PWINE_CERT_CONTEXT context, DWORD dwPropId, DWORD dwFlags, const void *pvData)
915 TRACE("(%p, %ld, %08lx, %p)\n", context, dwPropId, dwFlags, pvData);
919 PWINE_CERT_PROPERTY prop, next;
921 EnterCriticalSection(&context->cs);
922 LIST_FOR_EACH_ENTRY_SAFE(prop, next, &context->extendedProperties,
923 WINE_CERT_PROPERTY, entry)
925 if (prop->hdr.propID == dwPropId)
927 list_remove(&prop->entry);
928 HeapFree(GetProcessHeap(), 0, prop->pbData);
929 HeapFree(GetProcessHeap(), 0, prop);
932 LeaveCriticalSection(&context->cs);
939 case CERT_AUTO_ENROLL_PROP_ID:
940 case CERT_CTL_USAGE_PROP_ID:
941 case CERT_DESCRIPTION_PROP_ID:
942 case CERT_FRIENDLY_NAME_PROP_ID:
943 case CERT_HASH_PROP_ID:
944 case CERT_KEY_IDENTIFIER_PROP_ID:
945 case CERT_MD5_HASH_PROP_ID:
946 case CERT_NEXT_UPDATE_LOCATION_PROP_ID:
947 case CERT_PUBKEY_ALG_PARA_PROP_ID:
948 case CERT_PVK_FILE_PROP_ID:
949 case CERT_SIGNATURE_HASH_PROP_ID:
950 case CERT_ISSUER_PUBLIC_KEY_MD5_HASH_PROP_ID:
951 case CERT_SUBJECT_PUBLIC_KEY_MD5_HASH_PROP_ID:
952 case CERT_ENROLLMENT_PROP_ID:
953 case CERT_CROSS_CERT_DIST_POINTS_PROP_ID:
954 case CERT_RENEWAL_PROP_ID:
956 PCRYPT_DATA_BLOB blob = (PCRYPT_DATA_BLOB)pvData;
958 ret = CRYPT_SaveCertificateContextProperty(context, dwPropId,
959 blob->pbData, blob->cbData);
962 case CERT_DATE_STAMP_PROP_ID:
963 ret = CRYPT_SaveCertificateContextProperty(context, dwPropId,
964 pvData, sizeof(FILETIME));
967 FIXME("%ld: stub\n", dwPropId);
970 TRACE("returning %d\n", ret);
974 BOOL WINAPI CertSetCertificateContextProperty(PCCERT_CONTEXT pCertContext,
975 DWORD dwPropId, DWORD dwFlags, const void *pvData)
977 PWINE_CERT_CONTEXT_REF ref = (PWINE_CERT_CONTEXT_REF)pCertContext;
980 TRACE("(%p, %ld, %08lx, %p)\n", pCertContext, dwPropId, dwFlags, pvData);
982 /* Handle special cases for "read-only"/invalid prop IDs. Windows just
983 * crashes on most of these, I'll be safer.
988 case CERT_ACCESS_STATE_PROP_ID:
989 case CERT_CERT_PROP_ID:
990 case CERT_CRL_PROP_ID:
991 case CERT_CTL_PROP_ID:
992 SetLastError(HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER));
995 ret = CRYPT_SetCertificateContextProperty(ref->context, dwPropId,
997 TRACE("returning %d\n", ret);
1001 /* Only the reference portion of the context is duplicated. The returned
1002 * context has the cert store set to 0, to prevent the store's certificate free
1003 * function from getting called on partial data.
1004 * FIXME: is this okay? Needs a test.
1006 PCCERT_CONTEXT WINAPI CertDuplicateCertificateContext(
1007 PCCERT_CONTEXT pCertContext)
1009 PWINE_CERT_CONTEXT_REF ref = (PWINE_CERT_CONTEXT_REF)pCertContext, ret;
1011 TRACE("(%p)\n", pCertContext);
1014 ret = HeapAlloc(GetProcessHeap(), 0, sizeof(WINE_CERT_CONTEXT_REF));
1017 memcpy(ret, ref, sizeof(*ret));
1018 ret->cert.hCertStore = 0;
1019 InterlockedIncrement(&ret->context->ref);
1024 return (PCCERT_CONTEXT)ret;
1027 BOOL WINAPI CertAddCertificateContextToStore(HCERTSTORE hCertStore,
1028 PCCERT_CONTEXT pCertContext, DWORD dwAddDisposition,
1029 PCCERT_CONTEXT *ppStoreContext)
1031 PWINECRYPT_CERTSTORE store = (PWINECRYPT_CERTSTORE)hCertStore;
1032 PWINE_CERT_CONTEXT_REF ref = (PWINE_CERT_CONTEXT_REF)pCertContext;
1033 PWINE_CERT_CONTEXT cert;
1036 TRACE("(%p, %p, %08lx, %p)\n", hCertStore, pCertContext,
1037 dwAddDisposition, ppStoreContext);
1039 /* FIXME: some tests needed to verify return codes */
1042 SetLastError(ERROR_INVALID_PARAMETER);
1045 if (store->dwMagic != WINE_CRYPTCERTSTORE_MAGIC)
1047 SetLastError(ERROR_INVALID_PARAMETER);
1051 cert = CRYPT_CreateCertificateContext(ref->context->cert.dwCertEncodingType,
1052 ref->context->cert.pbCertEncoded, ref->context->cert.cbCertEncoded);
1055 PWINE_CERT_PROPERTY prop;
1058 EnterCriticalSection(&ref->context->cs);
1059 LIST_FOR_EACH_ENTRY(prop, &ref->context->extendedProperties,
1060 WINE_CERT_PROPERTY, entry)
1062 ret = CRYPT_SaveCertificateContextProperty(cert, prop->hdr.propID,
1063 prop->pbData, prop->hdr.cb);
1067 LeaveCriticalSection(&ref->context->cs);
1070 ret = store->addCert(store, (PCCERT_CONTEXT)cert, dwAddDisposition);
1071 if (ret && ppStoreContext)
1072 *ppStoreContext = (PCCERT_CONTEXT)store->createCertRef(cert,
1076 CRYPT_FreeCert(cert);
1083 BOOL WINAPI CertAddEncodedCertificateToStore(HCERTSTORE hCertStore,
1084 DWORD dwCertEncodingType, const BYTE *pbCertEncoded, DWORD cbCertEncoded,
1085 DWORD dwAddDisposition, PCCERT_CONTEXT *ppCertContext)
1087 WINECRYPT_CERTSTORE *hcs = (WINECRYPT_CERTSTORE *)hCertStore;
1090 TRACE("(%p, %08lx, %p, %ld, %08lx, %p)\n", hCertStore, dwCertEncodingType,
1091 pbCertEncoded, cbCertEncoded, dwAddDisposition, ppCertContext);
1095 else if (hcs->dwMagic != WINE_CRYPTCERTSTORE_MAGIC)
1099 PWINE_CERT_CONTEXT cert = CRYPT_CreateCertificateContext(
1100 dwCertEncodingType, pbCertEncoded, cbCertEncoded);
1104 ret = hcs->addCert(hcs, (PCCERT_CONTEXT)cert, dwAddDisposition);
1105 if (ret && ppCertContext)
1106 *ppCertContext = (PCCERT_CONTEXT)hcs->createCertRef(cert,
1109 CRYPT_FreeCert(cert);
1117 PCCERT_CONTEXT WINAPI CertEnumCertificatesInStore(HCERTSTORE hCertStore,
1118 PCCERT_CONTEXT pPrev)
1120 WINECRYPT_CERTSTORE *hcs = (WINECRYPT_CERTSTORE *)hCertStore;
1121 PWINE_CERT_CONTEXT_REF prev = (PWINE_CERT_CONTEXT_REF)pPrev;
1124 TRACE("(%p, %p)\n", hCertStore, pPrev);
1127 else if (hcs->dwMagic != WINE_CRYPTCERTSTORE_MAGIC)
1130 ret = (PCCERT_CONTEXT)hcs->enumCert(hcs, prev);
1134 BOOL WINAPI CertDeleteCertificateFromStore(PCCERT_CONTEXT pCertContext)
1138 TRACE("(%p)\n", pCertContext);
1142 else if (!pCertContext->hCertStore)
1146 PWINECRYPT_CERTSTORE hcs =
1147 (PWINECRYPT_CERTSTORE)pCertContext->hCertStore;
1151 else if (hcs->dwMagic != WINE_CRYPTCERTSTORE_MAGIC)
1154 ret = hcs->deleteCert(hcs, pCertContext, 0);
1159 BOOL WINAPI CertAddEncodedCRLToStore(HCERTSTORE hCertStore,
1160 DWORD dwCertEncodingType, const BYTE *pbCrlEncoded, DWORD cbCrlEncoded,
1161 DWORD dwAddDisposition, PCCRL_CONTEXT *ppCrlContext)
1163 FIXME("(%p, %08lx, %p, %ld, %08lx, %p): stub\n", hCertStore,
1164 dwCertEncodingType, pbCrlEncoded, cbCrlEncoded, dwAddDisposition,
1169 BOOL WINAPI CertAddCRLContextToStore( HCERTSTORE hCertStore,
1170 PCCRL_CONTEXT pCrlContext, DWORD dwAddDisposition,
1171 PCCRL_CONTEXT* ppStoreContext )
1173 FIXME("%p %p %08lx %p\n", hCertStore, pCrlContext,
1174 dwAddDisposition, ppStoreContext);
1178 BOOL WINAPI CertFreeCRLContext( PCCRL_CONTEXT pCrlContext)
1180 FIXME("%p\n", pCrlContext );
1185 BOOL WINAPI CertDeleteCRLFromStore(PCCRL_CONTEXT pCrlContext)
1187 FIXME("(%p): stub\n", pCrlContext);
1191 PCCRL_CONTEXT WINAPI CertEnumCRLsInStore(HCERTSTORE hCertStore,
1192 PCCRL_CONTEXT pPrev)
1194 FIXME("(%p, %p): stub\n", hCertStore, pPrev);
1198 PCCTL_CONTEXT WINAPI CertCreateCTLContext(DWORD dwCertEncodingType,
1199 const BYTE* pbCtlEncoded, DWORD cbCtlEncoded)
1201 FIXME("(%08lx, %p, %08lx): stub\n", dwCertEncodingType, pbCtlEncoded,
1206 BOOL WINAPI CertAddEncodedCTLToStore(HCERTSTORE hCertStore,
1207 DWORD dwMsgAndCertEncodingType, const BYTE *pbCtlEncoded, DWORD cbCtlEncoded,
1208 DWORD dwAddDisposition, PCCTL_CONTEXT *ppCtlContext)
1210 FIXME("(%p, %08lx, %p, %ld, %08lx, %p): stub\n", hCertStore,
1211 dwMsgAndCertEncodingType, pbCtlEncoded, cbCtlEncoded, dwAddDisposition,
1216 BOOL WINAPI CertAddCTLContextToStore(HCERTSTORE hCertStore,
1217 PCCTL_CONTEXT pCtlContext, DWORD dwAddDisposition,
1218 PCCTL_CONTEXT* ppStoreContext)
1220 FIXME("(%p, %p, %08lx, %p): stub\n", hCertStore, pCtlContext,
1221 dwAddDisposition, ppStoreContext);
1225 BOOL WINAPI CertFreeCTLContext(PCCTL_CONTEXT pCtlContext)
1227 FIXME("(%p): stub\n", pCtlContext );
1231 BOOL WINAPI CertDeleteCTLFromStore(PCCTL_CONTEXT pCtlContext)
1233 FIXME("(%p): stub\n", pCtlContext);
1237 PCCTL_CONTEXT WINAPI CertEnumCTLsInStore(HCERTSTORE hCertStore,
1238 PCCTL_CONTEXT pPrev)
1240 FIXME("(%p, %p): stub\n", hCertStore, pPrev);
1245 BOOL WINAPI CertCloseStore(HCERTSTORE hCertStore, DWORD dwFlags)
1247 WINECRYPT_CERTSTORE *hcs = (WINECRYPT_CERTSTORE *) hCertStore;
1249 TRACE("(%p, %08lx)\n", hCertStore, dwFlags);
1254 if ( hcs->dwMagic != WINE_CRYPTCERTSTORE_MAGIC )
1257 if (InterlockedDecrement(&hcs->ref) == 0)
1259 TRACE("freeing %p\n", hcs);
1261 if (!(hcs->dwOpenFlags & CERT_STORE_NO_CRYPT_RELEASE_FLAG))
1262 CryptReleaseContext(hcs->cryptProv, 0);
1263 hcs->closeStore(hcs, dwFlags);
1266 TRACE("%p's ref count is %ld\n", hcs, hcs->ref);
1270 BOOL WINAPI CertControlStore(HCERTSTORE hCertStore, DWORD dwFlags,
1271 DWORD dwCtrlType, void const *pvCtrlPara)
1273 FIXME("(%p, %08lx, %ld, %p): stub\n", hCertStore, dwFlags, dwCtrlType,
1278 BOOL WINAPI CertGetCRLContextProperty(PCCRL_CONTEXT pCRLContext,
1279 DWORD dwPropId, void *pvData, DWORD *pcbData)
1281 FIXME("(%p, %ld, %p, %p): stub\n", pCRLContext, dwPropId, pvData, pcbData);
1285 BOOL WINAPI CertSetCRLContextProperty(PCCRL_CONTEXT pCRLContext,
1286 DWORD dwPropId, DWORD dwFlags, const void *pvData)
1288 FIXME("(%p, %ld, %08lx, %p): stub\n", pCRLContext, dwPropId, dwFlags,
1293 BOOL WINAPI CertSerializeCRLStoreElement(PCCRL_CONTEXT pCrlContext,
1294 DWORD dwFlags, BYTE *pbElement, DWORD *pcbElement)
1296 FIXME("(%p, %08lx, %p, %p): stub\n", pCrlContext, dwFlags, pbElement,
1301 BOOL WINAPI CertGetCTLContextProperty(PCCTL_CONTEXT pCTLContext,
1302 DWORD dwPropId, void *pvData, DWORD *pcbData)
1304 FIXME("(%p, %ld, %p, %p): stub\n", pCTLContext, dwPropId, pvData, pcbData);
1308 BOOL WINAPI CertSetCTLContextProperty(PCCTL_CONTEXT pCTLContext,
1309 DWORD dwPropId, DWORD dwFlags, const void *pvData)
1311 FIXME("(%p, %ld, %08lx, %p): stub\n", pCTLContext, dwPropId, dwFlags,
1316 BOOL WINAPI CertSerializeCTLStoreElement(PCCTL_CONTEXT pCtlContext,
1317 DWORD dwFlags, BYTE *pbElement, DWORD *pcbElement)
1319 FIXME("(%p, %08lx, %p, %p): stub\n", pCtlContext, dwFlags, pbElement,
1324 BOOL WINAPI CertSerializeCertificateStoreElement(PCCERT_CONTEXT pCertContext,
1325 DWORD dwFlags, BYTE *pbElement, DWORD *pcbElement)
1329 TRACE("(%p, %08lx, %p, %p)\n", pCertContext, dwFlags, pbElement,
1334 PWINE_CERT_CONTEXT_REF ref = (PWINE_CERT_CONTEXT_REF)pCertContext;
1335 DWORD bytesNeeded = sizeof(WINE_CERT_PROP_HEADER) +
1336 pCertContext->cbCertEncoded;
1337 PWINE_CERT_PROPERTY prop;
1339 EnterCriticalSection(&ref->context->cs);
1340 LIST_FOR_EACH_ENTRY(prop, &ref->context->extendedProperties,
1341 WINE_CERT_PROPERTY, entry)
1342 bytesNeeded += sizeof(WINE_CERT_PROP_HEADER) + prop->hdr.cb;
1345 *pcbElement = bytesNeeded;
1348 else if (*pcbElement < bytesNeeded)
1350 *pcbElement = bytesNeeded;
1351 SetLastError(ERROR_MORE_DATA);
1356 PWINE_CERT_PROP_HEADER hdr;
1358 LIST_FOR_EACH_ENTRY(prop, &ref->context->extendedProperties,
1359 WINE_CERT_PROPERTY, entry)
1361 memcpy(pbElement, &prop->hdr, sizeof(WINE_CERT_PROP_HEADER));
1362 pbElement += sizeof(WINE_CERT_PROP_HEADER);
1365 memcpy(pbElement, prop->pbData, prop->hdr.cb);
1366 pbElement += prop->hdr.cb;
1369 hdr = (PWINE_CERT_PROP_HEADER)pbElement;
1370 hdr->propID = CERT_CERT_PROP_ID;
1372 hdr->cb = pCertContext->cbCertEncoded;
1373 memcpy(pbElement + sizeof(WINE_CERT_PROP_HEADER),
1374 pCertContext->pbCertEncoded, pCertContext->cbCertEncoded);
1377 LeaveCriticalSection(&ref->context->cs);
1384 BOOL WINAPI CertAddSerializedElementToStore(HCERTSTORE hCertStore,
1385 const BYTE *pbElement, DWORD cbElement, DWORD dwAddDisposition, DWORD dwFlags,
1386 DWORD dwContextTypeFlags, DWORD *pdwContentType, const void **ppvContext)
1388 FIXME("(%p, %p, %ld, %08lx, %08lx, %08lx, %p, %p): stub\n", hCertStore,
1389 pbElement, cbElement, dwAddDisposition, dwFlags, dwContextTypeFlags,
1390 pdwContentType, ppvContext);
1394 BOOL WINAPI CertFreeCertificateContext(PCCERT_CONTEXT pCertContext)
1396 TRACE("(%p)\n", pCertContext);
1400 PWINE_CERT_CONTEXT_REF ref = (PWINE_CERT_CONTEXT_REF)pCertContext;
1401 PWINECRYPT_CERTSTORE store = (PWINECRYPT_CERTSTORE)ref->cert.hCertStore;
1403 if (InterlockedDecrement(&ref->context->ref) == 0)
1405 TRACE("freeing %p\n", ref->context);
1406 CRYPT_FreeCert(ref->context);
1409 TRACE("%p's ref count is %ld\n", ref->context,
1411 if (store && store->dwMagic == WINE_CRYPTCERTSTORE_MAGIC &&
1413 store->freeCert(ref);
1414 HeapFree(GetProcessHeap(), 0, ref);
1419 PCCERT_CONTEXT WINAPI CertFindCertificateInStore(HCERTSTORE hCertStore,
1420 DWORD dwCertEncodingType, DWORD dwFlags, DWORD dwType,
1421 const void *pvPara, PCCERT_CONTEXT pPrevCertContext)
1423 FIXME("stub: %p %ld %ld %ld %p %p\n", hCertStore, dwCertEncodingType,
1424 dwFlags, dwType, pvPara, pPrevCertContext);
1425 SetLastError(CRYPT_E_NOT_FOUND);
1429 BOOL WINAPI CertAddStoreToCollection(HCERTSTORE hCollectionStore,
1430 HCERTSTORE hSiblingStore, DWORD dwUpdateFlags, DWORD dwPriority)
1432 FIXME("(%p, %p, %08lx, %ld): stub\n", hCollectionStore, hSiblingStore,
1433 dwUpdateFlags, dwPriority);
1437 void WINAPI CertRemoveStoreFromCollection(HCERTSTORE hCollectionStore,
1438 HCERTSTORE hSiblingStore)
1440 FIXME("(%p, %p): stub\n", hCollectionStore, hSiblingStore);
1443 PCRYPT_ATTRIBUTE WINAPI CertFindAttribute(LPCSTR pszObjId, DWORD cAttr,
1444 CRYPT_ATTRIBUTE rgAttr[])
1446 PCRYPT_ATTRIBUTE ret = NULL;
1449 TRACE("%s %ld %p\n", debugstr_a(pszObjId), cAttr, rgAttr);
1455 SetLastError(ERROR_INVALID_PARAMETER);
1459 for (i = 0; !ret && i < cAttr; i++)
1460 if (rgAttr[i].pszObjId && !strcmp(pszObjId, rgAttr[i].pszObjId))
1465 PCERT_EXTENSION WINAPI CertFindExtension(LPCSTR pszObjId, DWORD cExtensions,
1466 CERT_EXTENSION rgExtensions[])
1468 PCERT_EXTENSION ret = NULL;
1471 TRACE("%s %ld %p\n", debugstr_a(pszObjId), cExtensions, rgExtensions);
1477 SetLastError(ERROR_INVALID_PARAMETER);
1481 for (i = 0; !ret && i < cExtensions; i++)
1482 if (rgExtensions[i].pszObjId && !strcmp(pszObjId,
1483 rgExtensions[i].pszObjId))
1484 ret = &rgExtensions[i];
1488 PCERT_RDN_ATTR WINAPI CertFindRDNAttr(LPCSTR pszObjId, PCERT_NAME_INFO pName)
1490 PCERT_RDN_ATTR ret = NULL;
1493 TRACE("%s %p\n", debugstr_a(pszObjId), pName);
1497 SetLastError(ERROR_INVALID_PARAMETER);
1501 for (i = 0; !ret && i < pName->cRDN; i++)
1502 for (j = 0; !ret && j < pName->rgRDN[i].cRDNAttr; j++)
1503 if (pName->rgRDN[i].rgRDNAttr[j].pszObjId && !strcmp(pszObjId,
1504 pName->rgRDN[i].rgRDNAttr[j].pszObjId))
1505 ret = &pName->rgRDN[i].rgRDNAttr[j];
1509 LONG WINAPI CertVerifyTimeValidity(LPFILETIME pTimeToVerify,
1510 PCERT_INFO pCertInfo)
1519 GetSystemTime(&sysTime);
1520 SystemTimeToFileTime(&sysTime, &fileTime);
1521 pTimeToVerify = &fileTime;
1523 if ((ret = CompareFileTime(pTimeToVerify, &pCertInfo->NotBefore)) >= 0)
1525 ret = CompareFileTime(pTimeToVerify, &pCertInfo->NotAfter);
1532 BOOL WINAPI CryptHashCertificate(HCRYPTPROV hCryptProv, ALG_ID Algid,
1533 DWORD dwFlags, const BYTE *pbEncoded, DWORD cbEncoded, BYTE *pbComputedHash,
1534 DWORD *pcbComputedHash)
1537 HCRYPTHASH hHash = 0;
1539 TRACE("(%ld, %d, %08lx, %p, %ld, %p, %p)\n", hCryptProv, Algid, dwFlags,
1540 pbEncoded, cbEncoded, pbComputedHash, pcbComputedHash);
1543 hCryptProv = CRYPT_GetDefaultProvider();
1548 ret = CryptCreateHash(hCryptProv, Algid, 0, 0, &hHash);
1551 ret = CryptHashData(hHash, pbEncoded, cbEncoded, 0);
1553 ret = CryptGetHashParam(hHash, HP_HASHVAL, pbComputedHash,
1554 pcbComputedHash, 0);
1555 CryptDestroyHash(hHash);