Implement collection stores.
[wine/gsoc_dplay.git] / dlls / crypt32 / cert.c
bloba166377c42e89c564ee9034b1d8d00773f0f12af
1 /*
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
19 * FIXME:
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
24 * external DLLs.
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.
30 #include <stdarg.h>
31 #include "windef.h"
32 #include "winbase.h"
33 #include "winreg.h"
34 #include "wincrypt.h"
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
56 * it.
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
67 * this.
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 {
78 StoreTypeMem,
79 StoreTypeCollection,
80 StoreTypeReg,
81 StoreTypeDummy,
82 } 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
90 * persistence
92 typedef struct WINE_CRYPTCERTSTORE
94 DWORD dwMagic;
95 LONG ref;
96 DWORD dwOpenFlags;
97 HCRYPTPROV cryptProv;
98 CertStoreType type;
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
118 CERT_CONTEXT cert;
119 LONG ref;
120 CRITICAL_SECTION cs;
121 struct list extendedProperties;
122 } WINE_CERT_CONTEXT, *PWINE_CERT_CONTEXT;
124 typedef struct _WINE_CERT_CONTEXT_REF
126 CERT_CONTEXT cert;
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
131 * header.
133 typedef struct _WINE_CERT_PROP_HEADER
135 DWORD propID;
136 DWORD unknown; /* always 1 */
137 DWORD cb;
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;
144 LPBYTE pbData;
145 struct list entry;
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;
154 struct list entry;
155 } WINE_CERT_LIST_ENTRY, *PWINE_CERT_LIST_ENTRY;
157 typedef struct _WINE_MEMSTORE
159 WINECRYPT_CERTSTORE hdr;
160 CRITICAL_SECTION cs;
161 struct list certs;
162 } WINE_MEMSTORE, *PWINE_MEMSTORE;
164 typedef struct _WINE_STORE_LIST_ENTRY
166 PWINECRYPT_CERTSTORE store;
167 DWORD dwUpdateFlags;
168 DWORD dwPriority;
169 struct list entry;
170 } WINE_STORE_LIST_ENTRY, *PWINE_STORE_LIST_ENTRY;
172 /* Returned by a collection store during enumeration.
173 * Note: relies on the list entry being valid after use, which a number of
174 * conditions might make untrue (reentrancy, closing a collection store before
175 * continuing an enumeration on it, ...). The tests seem to indicate this
176 * sort of unsafety is okay, since Windows isn't well-behaved in these
177 * scenarios either.
179 typedef struct _WINE_COLLECTION_CERT_CONTEXT
181 WINE_CERT_CONTEXT_REF cert;
182 PWINE_STORE_LIST_ENTRY entry;
183 PWINE_CERT_CONTEXT_REF childContext;
184 } WINE_COLLECTION_CERT_CONTEXT, *PWINE_COLLECTION_CERT_CONTEXT;
186 typedef struct _WINE_COLLECTIONSTORE
188 WINECRYPT_CERTSTORE hdr;
189 CRITICAL_SECTION cs;
190 struct list stores;
191 } WINE_COLLECTIONSTORE, *PWINE_COLLECTIONSTORE;
193 /* Like CertGetCertificateContextProperty, but operates directly on the
194 * WINE_CERT_CONTEXT. Doesn't support special-case properties, since they
195 * are handled by CertGetCertificateContextProperty, and are particular to the
196 * store in which the property exists (which is separate from the context.)
198 static BOOL WINAPI CRYPT_GetCertificateContextProperty(
199 PWINE_CERT_CONTEXT context, DWORD dwPropId, void *pvData, DWORD *pcbData);
201 /* Like CertSetCertificateContextProperty, but operates directly on the
202 * WINE_CERT_CONTEXT. Doesn't handle special cases, since they're handled by
203 * CertSetCertificateContextProperty anyway.
205 static BOOL WINAPI CRYPT_SetCertificateContextProperty(
206 PWINE_CERT_CONTEXT context, DWORD dwPropId, DWORD dwFlags, const void *pvData);
208 static void CRYPT_InitStore(WINECRYPT_CERTSTORE *store, HCRYPTPROV hCryptProv,
209 DWORD dwFlags, CertStoreType type)
211 store->ref = 1;
212 store->dwMagic = WINE_CRYPTCERTSTORE_MAGIC;
213 store->type = type;
214 if (!hCryptProv)
216 hCryptProv = CRYPT_GetDefaultProvider();
217 dwFlags |= CERT_STORE_NO_CRYPT_RELEASE_FLAG;
219 store->cryptProv = hCryptProv;
220 store->dwOpenFlags = dwFlags;
223 /* Initializes the reference ref to point to pCertContext, which is assumed to
224 * be a PWINE_CERT_CONTEXT, and increments pCertContext's reference count.
225 * Also sets the hCertStore member of the reference to store.
227 static void CRYPT_InitCertRef(PWINE_CERT_CONTEXT_REF ref,
228 PWINE_CERT_CONTEXT context, HCERTSTORE store)
230 TRACE("(%p, %p)\n", ref, context);
231 memcpy(&ref->cert, context, sizeof(ref->cert));
232 ref->context = context;
233 InterlockedIncrement(&context->ref);
234 ref->cert.hCertStore = store;
237 static PWINE_CERT_CONTEXT_REF CRYPT_CreateCertRef(PWINE_CERT_CONTEXT context,
238 HCERTSTORE store)
240 PWINE_CERT_CONTEXT_REF pCertRef = HeapAlloc(GetProcessHeap(), 0,
241 sizeof(WINE_CERT_CONTEXT_REF));
243 if (pCertRef)
244 CRYPT_InitCertRef(pCertRef, context, store);
245 return pCertRef;
248 static BOOL WINAPI CRYPT_MemAddCert(HCERTSTORE store, PCCERT_CONTEXT pCert,
249 DWORD dwAddDisposition)
251 WINE_MEMSTORE *ms = (WINE_MEMSTORE *)store;
252 BOOL add = FALSE, ret;
254 TRACE("(%p, %p, %ld)\n", store, pCert, dwAddDisposition);
256 switch (dwAddDisposition)
258 case CERT_STORE_ADD_ALWAYS:
259 add = TRUE;
260 break;
261 case CERT_STORE_ADD_NEW:
263 BYTE hashToAdd[20], hash[20];
264 DWORD size = sizeof(hashToAdd);
266 ret = CRYPT_GetCertificateContextProperty((PWINE_CERT_CONTEXT)pCert,
267 CERT_HASH_PROP_ID, hashToAdd, &size);
268 if (ret)
270 PWINE_CERT_LIST_ENTRY cursor;
272 /* Add if no cert with the same hash is found. */
273 add = TRUE;
274 EnterCriticalSection(&ms->cs);
275 LIST_FOR_EACH_ENTRY(cursor, &ms->certs, WINE_CERT_LIST_ENTRY, entry)
277 size = sizeof(hash);
278 ret = CertGetCertificateContextProperty(&cursor->cert.cert,
279 CERT_HASH_PROP_ID, hash, &size);
280 if (ret && !memcmp(hashToAdd, hash, size))
282 TRACE("found matching certificate, not adding\n");
283 SetLastError(CRYPT_E_EXISTS);
284 add = FALSE;
285 break;
288 LeaveCriticalSection(&ms->cs);
290 break;
292 case CERT_STORE_ADD_REPLACE_EXISTING:
294 BYTE hashToAdd[20], hash[20];
295 DWORD size = sizeof(hashToAdd);
297 add = TRUE;
298 ret = CRYPT_GetCertificateContextProperty((PWINE_CERT_CONTEXT)pCert,
299 CERT_HASH_PROP_ID, hashToAdd, &size);
300 if (ret)
302 PWINE_CERT_LIST_ENTRY cursor, next;
304 /* Look for existing cert to delete */
305 EnterCriticalSection(&ms->cs);
306 LIST_FOR_EACH_ENTRY_SAFE(cursor, next, &ms->certs,
307 WINE_CERT_LIST_ENTRY, entry)
309 size = sizeof(hash);
310 ret = CertGetCertificateContextProperty(&cursor->cert.cert,
311 CERT_HASH_PROP_ID, hash, &size);
312 if (ret && !memcmp(hashToAdd, hash, size))
314 TRACE("found matching certificate, replacing\n");
315 list_remove(&cursor->entry);
316 CertFreeCertificateContext((PCCERT_CONTEXT)cursor);
317 break;
320 LeaveCriticalSection(&ms->cs);
322 break;
324 default:
325 FIXME("Unimplemented add disposition %ld\n", dwAddDisposition);
326 add = FALSE;
328 if (add)
330 PWINE_CERT_LIST_ENTRY entry = HeapAlloc(GetProcessHeap(), 0,
331 sizeof(WINE_CERT_LIST_ENTRY));
333 if (entry)
335 TRACE("adding %p\n", entry);
336 CRYPT_InitCertRef(&entry->cert, (PWINE_CERT_CONTEXT)pCert, store);
337 list_init(&entry->entry);
338 EnterCriticalSection(&ms->cs);
339 list_add_tail(&ms->certs, &entry->entry);
340 LeaveCriticalSection(&ms->cs);
341 ret = TRUE;
343 else
344 ret = FALSE;
346 else
347 ret = FALSE;
348 return ret;
351 static PWINE_CERT_CONTEXT_REF CRYPT_MemEnumCert(PWINECRYPT_CERTSTORE store,
352 PWINE_CERT_CONTEXT_REF pPrev)
354 WINE_MEMSTORE *ms = (WINE_MEMSTORE *)store;
355 PWINE_CERT_LIST_ENTRY prevEntry = (PWINE_CERT_LIST_ENTRY)pPrev, ret;
356 struct list *listNext;
358 TRACE("(%p, %p)\n", store, pPrev);
359 EnterCriticalSection(&ms->cs);
360 if (prevEntry)
362 listNext = list_next(&ms->certs, &prevEntry->entry);
363 CertFreeCertificateContext((PCCERT_CONTEXT)pPrev);
365 else
366 listNext = list_next(&ms->certs, &ms->certs);
367 if (listNext)
369 ret = HeapAlloc(GetProcessHeap(), 0, sizeof(WINE_CERT_LIST_ENTRY));
370 memcpy(ret, LIST_ENTRY(listNext, WINE_CERT_LIST_ENTRY, entry),
371 sizeof(WINE_CERT_LIST_ENTRY));
372 InterlockedIncrement(&ret->cert.context->ref);
374 else
376 SetLastError(CRYPT_E_NOT_FOUND);
377 ret = NULL;
379 LeaveCriticalSection(&ms->cs);
381 TRACE("returning %p\n", ret);
382 return (PWINE_CERT_CONTEXT_REF)ret;
385 static BOOL WINAPI CRYPT_MemDeleteCert(HCERTSTORE hCertStore,
386 PCCERT_CONTEXT pCertContext, DWORD dwFlags)
388 WINE_MEMSTORE *store = (WINE_MEMSTORE *)hCertStore;
389 WINE_CERT_CONTEXT_REF *ref = (WINE_CERT_CONTEXT_REF *)pCertContext;
390 PWINE_CERT_LIST_ENTRY cert, next;
391 BOOL ret;
393 /* Find the entry associated with the passed-in context, since the
394 * passed-in context may not be a list entry itself (e.g. if it came from
395 * CertDuplicateCertificateContext.) Pointing to the same context is
396 * a sufficient test of equality.
398 EnterCriticalSection(&store->cs);
399 LIST_FOR_EACH_ENTRY_SAFE(cert, next, &store->certs, WINE_CERT_LIST_ENTRY,
400 entry)
402 if (cert->cert.context == ref->context)
404 TRACE("removing %p\n", cert);
405 /* FIXME: this isn't entirely thread-safe, the entry itself isn't
406 * protected.
408 list_remove(&cert->entry);
409 cert->entry.prev = cert->entry.next = &store->certs;
410 CertFreeCertificateContext((PCCERT_CONTEXT)cert);
411 break;
414 ret = TRUE;
415 LeaveCriticalSection(&store->cs);
416 return ret;
419 static void WINAPI CRYPT_MemCloseStore(HCERTSTORE hCertStore, DWORD dwFlags)
421 WINE_MEMSTORE *store = (WINE_MEMSTORE *)hCertStore;
422 PWINE_CERT_LIST_ENTRY cert, next;
424 TRACE("(%p, %08lx)\n", store, dwFlags);
425 if (dwFlags)
426 FIXME("Unimplemented flags: %08lx\n", dwFlags);
428 /* Note that CertFreeCertificateContext calls HeapFree on the passed-in
429 * pointer if its ref-count reaches zero. That's okay here because there
430 * aren't any allocated data outside of the WINE_CERT_CONTEXT_REF portion
431 * of the CertListEntry.
433 LIST_FOR_EACH_ENTRY_SAFE(cert, next, &store->certs, WINE_CERT_LIST_ENTRY,
434 entry)
436 TRACE("removing %p\n", cert);
437 list_remove(&cert->entry);
438 CertFreeCertificateContext((PCCERT_CONTEXT)cert);
440 DeleteCriticalSection(&store->cs);
441 HeapFree(GetProcessHeap(), 0, store);
444 static WINECRYPT_CERTSTORE *CRYPT_MemOpenStore(HCRYPTPROV hCryptProv,
445 DWORD dwFlags, const void *pvPara)
447 PWINE_MEMSTORE store;
449 TRACE("(%ld, %08lx, %p)\n", hCryptProv, dwFlags, pvPara);
451 if (dwFlags & CERT_STORE_DELETE_FLAG)
453 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
454 store = NULL;
456 else
458 store = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
459 sizeof(WINE_MEMSTORE));
460 if (store)
462 CRYPT_InitStore(&store->hdr, hCryptProv, dwFlags, StoreTypeMem);
463 store->hdr.closeStore = CRYPT_MemCloseStore;
464 store->hdr.addCert = CRYPT_MemAddCert;
465 store->hdr.createCertRef = CRYPT_CreateCertRef;
466 store->hdr.enumCert = CRYPT_MemEnumCert;
467 store->hdr.deleteCert = CRYPT_MemDeleteCert;
468 store->hdr.freeCert = NULL;
469 InitializeCriticalSection(&store->cs);
470 list_init(&store->certs);
473 return (PWINECRYPT_CERTSTORE)store;
476 static BOOL WINAPI CRYPT_CollectionAddCert(HCERTSTORE store,
477 PCCERT_CONTEXT pCert, DWORD dwAddDisposition)
479 PWINE_COLLECTIONSTORE cs = (PWINE_COLLECTIONSTORE)store;
480 PWINE_STORE_LIST_ENTRY entry, next;
481 BOOL ret;
483 TRACE("(%p, %p, %ld)\n", store, pCert, dwAddDisposition);
485 ret = FALSE;
486 EnterCriticalSection(&cs->cs);
487 LIST_FOR_EACH_ENTRY_SAFE(entry, next, &cs->stores, WINE_STORE_LIST_ENTRY,
488 entry)
490 if (entry->dwUpdateFlags & CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG)
492 ret = entry->store->addCert(entry->store, pCert, dwAddDisposition);
493 break;
496 LeaveCriticalSection(&cs->cs);
497 SetLastError(ret ? ERROR_SUCCESS : HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED));
498 return ret;
501 static PWINE_CERT_CONTEXT_REF CRYPT_CollectionCreateCertRef(
502 PWINE_CERT_CONTEXT context, HCERTSTORE store)
504 PWINE_COLLECTION_CERT_CONTEXT ret = HeapAlloc(GetProcessHeap(), 0,
505 sizeof(WINE_COLLECTION_CERT_CONTEXT));
507 if (ret)
509 /* Initialize to empty for now, just make sure the size is right */
510 CRYPT_InitCertRef((PWINE_CERT_CONTEXT_REF)ret, context, store);
511 ret->entry = NULL;
512 ret->childContext = NULL;
514 return (PWINE_CERT_CONTEXT_REF)ret;
517 static void WINAPI CRYPT_CollectionCloseStore(HCERTSTORE store, DWORD dwFlags)
519 PWINE_COLLECTIONSTORE cs = (PWINE_COLLECTIONSTORE)store;
520 PWINE_STORE_LIST_ENTRY entry, next;
522 TRACE("(%p, %08lx)\n", store, dwFlags);
524 LIST_FOR_EACH_ENTRY_SAFE(entry, next, &cs->stores, WINE_STORE_LIST_ENTRY,
525 entry)
527 TRACE("closing %p\n", entry);
528 CertCloseStore((HCERTSTORE)entry->store, dwFlags);
529 HeapFree(GetProcessHeap(), 0, entry);
531 DeleteCriticalSection(&cs->cs);
532 HeapFree(GetProcessHeap(), 0, cs);
535 /* Advances a collection enumeration by one cert, if possible, where advancing
536 * means:
537 * - calling the current store's enumeration function once, and returning
538 * the enumerated cert if one is returned
539 * - moving to the next store if the current store has no more items, and
540 * recursively calling itself to get the next item.
541 * Returns NULL if the collection contains no more items or on error.
542 * Assumes the collection store's lock is held.
544 static PWINE_COLLECTION_CERT_CONTEXT CRYPT_CollectionAdvanceEnum(
545 PWINE_COLLECTIONSTORE store, PWINE_STORE_LIST_ENTRY storeEntry,
546 PWINE_COLLECTION_CERT_CONTEXT pPrev)
548 PWINE_COLLECTION_CERT_CONTEXT ret;
549 PWINE_CERT_CONTEXT_REF child;
551 TRACE("(%p, %p, %p)\n", store, storeEntry, pPrev);
553 if (pPrev)
555 child = storeEntry->store->enumCert((HCERTSTORE)storeEntry->store,
556 pPrev->childContext);
557 if (child)
559 ret = pPrev;
560 memcpy(&ret->cert, child, sizeof(WINE_CERT_CONTEXT_REF));
561 ret->cert.cert.hCertStore = (HCERTSTORE)store;
562 InterlockedIncrement(&ret->cert.context->ref);
563 ret->childContext = child;
565 else
567 struct list *storeNext = list_next(&store->stores,
568 &storeEntry->entry);
570 pPrev->childContext = NULL;
571 CertFreeCertificateContext((PCCERT_CONTEXT)pPrev);
572 if (storeNext)
574 storeEntry = LIST_ENTRY(storeNext, WINE_STORE_LIST_ENTRY,
575 entry);
576 ret = CRYPT_CollectionAdvanceEnum(store, storeEntry, NULL);
578 else
580 SetLastError(CRYPT_E_NOT_FOUND);
581 ret = NULL;
585 else
587 child = storeEntry->store->enumCert((HCERTSTORE)storeEntry->store,
588 NULL);
589 if (child)
591 ret = (PWINE_COLLECTION_CERT_CONTEXT)CRYPT_CollectionCreateCertRef(
592 child->context, store);
593 if (ret)
595 ret->entry = storeEntry;
596 ret->childContext = child;
598 else
599 CertFreeCertificateContext((PCCERT_CONTEXT)child);
601 else
603 struct list *storeNext = list_next(&store->stores,
604 &storeEntry->entry);
606 if (storeNext)
608 storeEntry = LIST_ENTRY(storeNext, WINE_STORE_LIST_ENTRY,
609 entry);
610 ret = CRYPT_CollectionAdvanceEnum(store, storeEntry, NULL);
612 else
614 SetLastError(CRYPT_E_NOT_FOUND);
615 ret = NULL;
619 TRACE("returning %p\n", ret);
620 return ret;
623 static PWINE_CERT_CONTEXT_REF CRYPT_CollectionEnumCert(
624 PWINECRYPT_CERTSTORE store, PWINE_CERT_CONTEXT_REF pPrev)
626 PWINE_COLLECTIONSTORE cs = (PWINE_COLLECTIONSTORE)store;
627 PWINE_COLLECTION_CERT_CONTEXT prevEntry =
628 (PWINE_COLLECTION_CERT_CONTEXT)pPrev, ret;
630 TRACE("(%p, %p)\n", store, pPrev);
632 if (prevEntry)
634 EnterCriticalSection(&cs->cs);
635 ret = CRYPT_CollectionAdvanceEnum(cs, prevEntry->entry, prevEntry);
636 LeaveCriticalSection(&cs->cs);
638 else
640 EnterCriticalSection(&cs->cs);
641 if (!list_empty(&cs->stores))
643 PWINE_STORE_LIST_ENTRY storeEntry;
645 storeEntry = LIST_ENTRY(cs->stores.next, WINE_STORE_LIST_ENTRY,
646 entry);
647 ret = CRYPT_CollectionAdvanceEnum(cs, storeEntry, prevEntry);
649 else
651 SetLastError(CRYPT_E_NOT_FOUND);
652 ret = NULL;
654 LeaveCriticalSection(&cs->cs);
656 TRACE("returning %p\n", ret);
657 return (PWINE_CERT_CONTEXT_REF)ret;
660 static BOOL WINAPI CRYPT_CollectionDeleteCert(HCERTSTORE hCertStore,
661 PCCERT_CONTEXT pCertContext, DWORD dwFlags)
663 PWINE_COLLECTION_CERT_CONTEXT context =
664 (PWINE_COLLECTION_CERT_CONTEXT)pCertContext;
665 BOOL ret;
667 TRACE("(%p, %p, %08lx)\n", hCertStore, pCertContext, dwFlags);
669 ret = CertDeleteCertificateFromStore((PCCERT_CONTEXT)context->childContext);
670 if (ret)
672 context->childContext = NULL;
673 CertFreeCertificateContext((PCCERT_CONTEXT)context);
675 return ret;
678 static void CRYPT_CollectionFreeCert(PWINE_CERT_CONTEXT_REF ref)
680 PWINE_COLLECTION_CERT_CONTEXT context = (PWINE_COLLECTION_CERT_CONTEXT)ref;
682 TRACE("(%p)\n", ref);
684 if (context->childContext)
685 CertFreeCertificateContext((PCCERT_CONTEXT)context->childContext);
688 static WINECRYPT_CERTSTORE *CRYPT_CollectionOpenStore(HCRYPTPROV hCryptProv,
689 DWORD dwFlags, const void *pvPara)
691 PWINE_COLLECTIONSTORE store;
693 if (dwFlags & CERT_STORE_DELETE_FLAG)
695 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
696 store = NULL;
698 else
700 store = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
701 sizeof(WINE_COLLECTIONSTORE));
702 if (store)
704 CRYPT_InitStore(&store->hdr, hCryptProv, dwFlags,
705 StoreTypeCollection);
706 store->hdr.closeStore = CRYPT_CollectionCloseStore;
707 store->hdr.addCert = CRYPT_CollectionAddCert;
708 store->hdr.createCertRef = CRYPT_CollectionCreateCertRef;
709 store->hdr.enumCert = CRYPT_CollectionEnumCert;
710 store->hdr.deleteCert = CRYPT_CollectionDeleteCert;
711 store->hdr.freeCert = CRYPT_CollectionFreeCert;
712 InitializeCriticalSection(&store->cs);
713 list_init(&store->stores);
716 return (PWINECRYPT_CERTSTORE)store;
719 static void WINAPI CRYPT_DummyCloseStore(HCERTSTORE hCertStore, DWORD dwFlags)
721 HeapFree(GetProcessHeap(), 0, (PWINECRYPT_CERTSTORE)hCertStore);
724 static BOOL WINAPI CRYPT_DummyAddCert(HCERTSTORE store, PCCERT_CONTEXT pCert,
725 DWORD dwAddDisposition)
727 return FALSE;
730 static PWINE_CERT_CONTEXT_REF CRYPT_DummyEnumCert(PWINECRYPT_CERTSTORE store,
731 PWINE_CERT_CONTEXT_REF pPrev)
733 return NULL;
736 static BOOL WINAPI CRYPT_DummyDeleteCert(HCERTSTORE hCertStore,
737 PCCERT_CONTEXT pCertContext, DWORD dwFlags)
739 return TRUE;
742 static WINECRYPT_CERTSTORE *CRYPT_DummyOpenStore(HCRYPTPROV hCryptProv,
743 DWORD dwFlags, const void *pvPara)
745 PWINECRYPT_CERTSTORE store;
747 TRACE("(%ld, %08lx, %p)\n", hCryptProv, dwFlags, pvPara);
749 if (dwFlags & CERT_STORE_DELETE_FLAG)
751 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
752 store = NULL;
754 else
756 store = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
757 sizeof(WINECRYPT_CERTSTORE));
758 if (store)
760 CRYPT_InitStore(store, hCryptProv, dwFlags, StoreTypeDummy);
761 store->closeStore = CRYPT_DummyCloseStore;
762 store->addCert = CRYPT_DummyAddCert;
763 store->createCertRef = CRYPT_CreateCertRef;
764 store->enumCert = CRYPT_DummyEnumCert;
765 store->deleteCert = CRYPT_DummyDeleteCert;
766 store->freeCert = NULL;
769 return (PWINECRYPT_CERTSTORE)store;
773 HCERTSTORE WINAPI CertOpenStore(LPCSTR lpszStoreProvider,
774 DWORD dwMsgAndCertEncodingType, HCRYPTPROV hCryptProv, DWORD dwFlags,
775 const void* pvPara)
777 WINECRYPT_CERTSTORE *hcs;
778 StoreOpenFunc openFunc = NULL;
780 TRACE("(%s, %08lx, %08lx, %08lx, %p)\n", debugstr_a(lpszStoreProvider),
781 dwMsgAndCertEncodingType, hCryptProv, dwFlags, pvPara);
783 if (!HIWORD(lpszStoreProvider))
785 switch (LOWORD(lpszStoreProvider))
787 case (int)CERT_STORE_PROV_MEMORY:
788 openFunc = CRYPT_MemOpenStore;
789 break;
790 case (int)CERT_STORE_PROV_COLLECTION:
791 openFunc = CRYPT_CollectionOpenStore;
792 break;
793 case (int)CERT_STORE_PROV_REG:
794 case (int)CERT_STORE_PROV_SYSTEM_A:
795 case (int)CERT_STORE_PROV_SYSTEM_W:
796 openFunc = CRYPT_DummyOpenStore;
797 break;
798 default:
799 if (LOWORD(lpszStoreProvider))
800 FIXME("unimplemented type %d\n", LOWORD(lpszStoreProvider));
803 else if (!strcasecmp(lpszStoreProvider, sz_CERT_STORE_PROV_MEMORY))
804 openFunc = CRYPT_MemOpenStore;
805 else if (!strcasecmp(lpszStoreProvider, sz_CERT_STORE_PROV_SYSTEM))
806 openFunc = CRYPT_DummyOpenStore;
807 else if (!strcasecmp(lpszStoreProvider, sz_CERT_STORE_PROV_COLLECTION))
808 openFunc = CRYPT_CollectionOpenStore;
809 else
811 FIXME("unimplemented type %s\n", lpszStoreProvider);
812 openFunc = NULL;
815 if (!openFunc)
817 /* FIXME: need to look for an installed provider for this type */
818 SetLastError(ERROR_FILE_NOT_FOUND);
819 hcs = NULL;
821 else
822 hcs = openFunc(hCryptProv, dwFlags, pvPara);
823 return (HCERTSTORE)hcs;
826 HCERTSTORE WINAPI CertOpenSystemStoreA(HCRYPTPROV hProv,
827 LPCSTR szSubSystemProtocol)
829 return CertOpenStore( CERT_STORE_PROV_SYSTEM_A, 0, 0,
830 CERT_SYSTEM_STORE_CURRENT_USER | CERT_SYSTEM_STORE_LOCAL_MACHINE |
831 CERT_SYSTEM_STORE_USERS, szSubSystemProtocol );
834 HCERTSTORE WINAPI CertOpenSystemStoreW(HCRYPTPROV hProv,
835 LPCWSTR szSubSystemProtocol)
837 return CertOpenStore( CERT_STORE_PROV_SYSTEM_W, 0, 0,
838 CERT_SYSTEM_STORE_CURRENT_USER | CERT_SYSTEM_STORE_LOCAL_MACHINE |
839 CERT_SYSTEM_STORE_USERS, szSubSystemProtocol );
842 BOOL WINAPI CertSaveStore(HCERTSTORE hCertStore, DWORD dwMsgAndCertEncodingType,
843 DWORD dwSaveAs, DWORD dwSaveTo, void* pvSaveToPara, DWORD dwFlags)
845 FIXME("(%p,%ld,%ld,%ld,%p,%08lx) stub!\n", hCertStore,
846 dwMsgAndCertEncodingType, dwSaveAs, dwSaveTo, pvSaveToPara, dwFlags);
847 return TRUE;
850 PCCRL_CONTEXT WINAPI CertCreateCRLContext( DWORD dwCertEncodingType,
851 const BYTE* pbCrlEncoded, DWORD cbCrlEncoded)
853 PCRL_CONTEXT pcrl;
854 BYTE* data;
856 TRACE("%08lx %p %08lx\n", dwCertEncodingType, pbCrlEncoded, cbCrlEncoded);
858 /* FIXME: semi-stub, need to use CryptDecodeObjectEx to decode the CRL. */
859 pcrl = HeapAlloc( GetProcessHeap(), 0, sizeof (CRL_CONTEXT) );
860 if( !pcrl )
861 return NULL;
863 data = HeapAlloc( GetProcessHeap(), 0, cbCrlEncoded );
864 if( !data )
866 HeapFree( GetProcessHeap(), 0, pcrl );
867 return NULL;
870 pcrl->dwCertEncodingType = dwCertEncodingType;
871 pcrl->pbCrlEncoded = data;
872 pcrl->cbCrlEncoded = cbCrlEncoded;
873 pcrl->pCrlInfo = NULL;
874 pcrl->hCertStore = 0;
876 return pcrl;
879 /* Decodes the encoded certificate and creates the certificate context for it.
880 * The reference count is initially zero, so you must create a reference to it
881 * to avoid leaking memory.
883 static PWINE_CERT_CONTEXT CRYPT_CreateCertificateContext(
884 DWORD dwCertEncodingType, const BYTE *pbCertEncoded, DWORD cbCertEncoded)
886 PWINE_CERT_CONTEXT cert = NULL;
887 BOOL ret;
888 PCERT_INFO certInfo = NULL;
889 DWORD size = 0;
891 TRACE("(%08lx, %p, %ld)\n", dwCertEncodingType, pbCertEncoded,
892 cbCertEncoded);
894 ret = CryptDecodeObjectEx(X509_ASN_ENCODING, X509_CERT_TO_BE_SIGNED,
895 pbCertEncoded, cbCertEncoded,
896 CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_NOCOPY_FLAG, NULL,
897 (BYTE *)&certInfo, &size);
898 if (ret)
900 BYTE *data = NULL;
902 cert = HeapAlloc(GetProcessHeap(), 0, sizeof(WINE_CERT_CONTEXT));
903 if (!cert)
904 goto end;
905 data = HeapAlloc(GetProcessHeap(), 0, cbCertEncoded);
906 if (!data)
908 HeapFree(GetProcessHeap(), 0, cert);
909 cert = NULL;
910 goto end;
912 memcpy(data, pbCertEncoded, cbCertEncoded);
913 cert->cert.dwCertEncodingType = dwCertEncodingType;
914 cert->cert.pbCertEncoded = data;
915 cert->cert.cbCertEncoded = cbCertEncoded;
916 cert->cert.pCertInfo = certInfo;
917 cert->cert.hCertStore = 0;
918 cert->ref = 0;
919 InitializeCriticalSection(&cert->cs);
920 list_init(&cert->extendedProperties);
923 end:
924 return cert;
927 static void CRYPT_FreeCert(PWINE_CERT_CONTEXT context)
929 PWINE_CERT_PROPERTY prop, next;
931 HeapFree(GetProcessHeap(), 0, context->cert.pbCertEncoded);
932 LocalFree(context->cert.pCertInfo);
933 HeapFree(GetProcessHeap(), 0, context);
934 DeleteCriticalSection(&context->cs);
935 LIST_FOR_EACH_ENTRY_SAFE(prop, next, &context->extendedProperties,
936 WINE_CERT_PROPERTY, entry)
938 list_remove(&prop->entry);
939 HeapFree(GetProcessHeap(), 0, prop->pbData);
940 HeapFree(GetProcessHeap(), 0, prop);
944 PCCERT_CONTEXT WINAPI CertCreateCertificateContext(DWORD dwCertEncodingType,
945 const BYTE *pbCertEncoded, DWORD cbCertEncoded)
947 PWINE_CERT_CONTEXT cert;
948 PWINE_CERT_CONTEXT_REF ret = NULL;
950 TRACE("(%08lx, %p, %ld)\n", dwCertEncodingType, pbCertEncoded,
951 cbCertEncoded);
953 cert = CRYPT_CreateCertificateContext(dwCertEncodingType, pbCertEncoded,
954 cbCertEncoded);
955 if (cert)
956 ret = CRYPT_CreateCertRef(cert, 0);
957 return (PCCERT_CONTEXT)ret;
960 /* Since the properties are stored in a list, this is a tad inefficient
961 * (O(n^2)) since I have to find the previous position every time.
963 DWORD WINAPI CertEnumCertificateContextProperties(PCCERT_CONTEXT pCertContext,
964 DWORD dwPropId)
966 PWINE_CERT_CONTEXT_REF ref = (PWINE_CERT_CONTEXT_REF)pCertContext;
967 DWORD ret;
969 TRACE("(%p, %ld)\n", pCertContext, dwPropId);
971 EnterCriticalSection(&ref->context->cs);
972 if (dwPropId)
974 PWINE_CERT_PROPERTY cursor = NULL;
976 LIST_FOR_EACH_ENTRY(cursor, &ref->context->extendedProperties,
977 WINE_CERT_PROPERTY, entry)
979 if (cursor->hdr.propID == dwPropId)
980 break;
982 if (cursor)
984 if (cursor->entry.next != &ref->context->extendedProperties)
985 ret = LIST_ENTRY(cursor->entry.next, WINE_CERT_PROPERTY,
986 entry)->hdr.propID;
987 else
988 ret = 0;
990 else
991 ret = 0;
993 else if (!list_empty(&ref->context->extendedProperties))
994 ret = LIST_ENTRY(ref->context->extendedProperties.next,
995 WINE_CERT_PROPERTY, entry)->hdr.propID;
996 else
997 ret = 0;
998 LeaveCriticalSection(&ref->context->cs);
999 return ret;
1002 static BOOL WINAPI CRYPT_GetCertificateContextProperty(
1003 PWINE_CERT_CONTEXT context, DWORD dwPropId, void *pvData, DWORD *pcbData)
1005 PWINE_CERT_PROPERTY prop;
1006 BOOL ret, found;
1008 TRACE("(%p, %ld, %p, %p)\n", context, dwPropId, pvData, pcbData);
1010 EnterCriticalSection(&context->cs);
1011 ret = FALSE;
1012 found = FALSE;
1013 LIST_FOR_EACH_ENTRY(prop, &context->extendedProperties,
1014 WINE_CERT_PROPERTY, entry)
1016 if (prop->hdr.propID == dwPropId)
1018 if (!pvData)
1020 *pcbData = prop->hdr.cb;
1021 ret = TRUE;
1023 else if (*pcbData < prop->hdr.cb)
1025 SetLastError(ERROR_MORE_DATA);
1026 *pcbData = prop->hdr.cb;
1028 else
1030 memcpy(pvData, prop->pbData, prop->hdr.cb);
1031 *pcbData = prop->hdr.cb;
1032 ret = TRUE;
1034 found = TRUE;
1036 break;
1038 if (!found)
1040 /* Implicit properties */
1041 switch (dwPropId)
1043 case CERT_SHA1_HASH_PROP_ID:
1044 ret = CryptHashCertificate(0, CALG_SHA1, 0,
1045 context->cert.pbCertEncoded, context->cert.cbCertEncoded, pvData,
1046 pcbData);
1047 if (ret)
1049 CRYPT_DATA_BLOB blob = { *pcbData, pvData };
1051 ret = CRYPT_SetCertificateContextProperty(context, dwPropId,
1052 0, &blob);
1054 break;
1055 case CERT_KEY_PROV_INFO_PROP_ID:
1056 case CERT_MD5_HASH_PROP_ID:
1057 case CERT_SIGNATURE_HASH_PROP_ID:
1058 case CERT_KEY_IDENTIFIER_PROP_ID:
1059 case CERT_SUBJECT_PUBLIC_KEY_MD5_HASH_PROP_ID:
1060 case CERT_ISSUER_SERIAL_NUMBER_MD5_HASH_PROP_ID:
1061 case CERT_SUBJECT_NAME_MD5_HASH_PROP_ID:
1062 FIXME("implicit property %ld\n", dwPropId);
1063 break;
1066 LeaveCriticalSection(&context->cs);
1067 TRACE("returning %d\n", ret);
1068 return ret;
1071 BOOL WINAPI CertGetCertificateContextProperty(PCCERT_CONTEXT pCertContext,
1072 DWORD dwPropId, void *pvData, DWORD *pcbData)
1074 PWINE_CERT_CONTEXT_REF ref = (PWINE_CERT_CONTEXT_REF)pCertContext;
1075 BOOL ret;
1077 TRACE("(%p, %ld, %p, %p)\n", pCertContext, dwPropId, pvData, pcbData);
1079 /* Special cases for invalid/special prop IDs.
1081 switch (dwPropId)
1083 case 0:
1084 case CERT_CERT_PROP_ID:
1085 case CERT_CRL_PROP_ID:
1086 case CERT_CTL_PROP_ID:
1087 SetLastError(HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER));
1088 return FALSE;
1089 case CERT_ACCESS_STATE_PROP_ID:
1090 if (!pvData)
1092 *pcbData = sizeof(DWORD);
1093 return TRUE;
1095 else if (*pcbData < sizeof(DWORD))
1097 SetLastError(ERROR_MORE_DATA);
1098 *pcbData = sizeof(DWORD);
1099 return FALSE;
1101 else
1103 DWORD state = 0;
1105 if (pCertContext->hCertStore)
1107 PWINECRYPT_CERTSTORE store =
1108 (PWINECRYPT_CERTSTORE)pCertContext->hCertStore;
1110 /* Take advantage of knowledge of the stores to answer the
1111 * access state question
1113 if (store->type != StoreTypeReg ||
1114 !(store->dwOpenFlags & CERT_STORE_READONLY_FLAG))
1115 state |= CERT_ACCESS_STATE_WRITE_PERSIST_FLAG;
1117 *(DWORD *)pvData = state;
1118 return TRUE;
1122 ret = CRYPT_GetCertificateContextProperty(ref->context, dwPropId,
1123 pvData, pcbData);
1124 TRACE("returning %d\n", ret);
1125 return ret;
1128 /* Copies cbData bytes from pbData to the context's property with ID
1129 * dwPropId.
1131 static BOOL CRYPT_SaveCertificateContextProperty(PWINE_CERT_CONTEXT context,
1132 DWORD dwPropId, const BYTE *pbData, size_t cbData)
1134 BOOL ret = FALSE;
1135 LPBYTE data;
1137 if (cbData)
1139 data = HeapAlloc(GetProcessHeap(), 0, cbData);
1140 if (data)
1141 memcpy(data, pbData, cbData);
1143 else
1144 data = NULL;
1145 if (!cbData || data)
1147 PWINE_CERT_PROPERTY prop;
1149 EnterCriticalSection(&context->cs);
1150 LIST_FOR_EACH_ENTRY(prop, &context->extendedProperties,
1151 WINE_CERT_PROPERTY, entry)
1153 if (prop->hdr.propID == dwPropId)
1154 break;
1156 if (prop && prop->entry.next != &context->extendedProperties)
1158 HeapFree(GetProcessHeap(), 0, prop->pbData);
1159 prop->hdr.cb = cbData;
1160 prop->pbData = cbData ? data : NULL;
1161 ret = TRUE;
1163 else
1165 prop = HeapAlloc(GetProcessHeap(), 0, sizeof(WINE_CERT_PROPERTY));
1166 if (prop)
1168 prop->hdr.propID = dwPropId;
1169 prop->hdr.unknown = 1;
1170 prop->hdr.cb = cbData;
1171 list_init(&prop->entry);
1172 prop->pbData = cbData ? data : NULL;
1173 list_add_tail(&context->extendedProperties, &prop->entry);
1174 ret = TRUE;
1176 else
1177 HeapFree(GetProcessHeap(), 0, data);
1179 LeaveCriticalSection(&context->cs);
1181 return ret;
1184 static BOOL WINAPI CRYPT_SetCertificateContextProperty(
1185 PWINE_CERT_CONTEXT context, DWORD dwPropId, DWORD dwFlags, const void *pvData)
1187 BOOL ret = FALSE;
1189 TRACE("(%p, %ld, %08lx, %p)\n", context, dwPropId, dwFlags, pvData);
1191 if (!pvData)
1193 PWINE_CERT_PROPERTY prop, next;
1195 EnterCriticalSection(&context->cs);
1196 LIST_FOR_EACH_ENTRY_SAFE(prop, next, &context->extendedProperties,
1197 WINE_CERT_PROPERTY, entry)
1199 if (prop->hdr.propID == dwPropId)
1201 list_remove(&prop->entry);
1202 HeapFree(GetProcessHeap(), 0, prop->pbData);
1203 HeapFree(GetProcessHeap(), 0, prop);
1206 LeaveCriticalSection(&context->cs);
1207 ret = TRUE;
1209 else
1211 switch (dwPropId)
1213 case CERT_AUTO_ENROLL_PROP_ID:
1214 case CERT_CTL_USAGE_PROP_ID:
1215 case CERT_DESCRIPTION_PROP_ID:
1216 case CERT_FRIENDLY_NAME_PROP_ID:
1217 case CERT_HASH_PROP_ID:
1218 case CERT_KEY_IDENTIFIER_PROP_ID:
1219 case CERT_MD5_HASH_PROP_ID:
1220 case CERT_NEXT_UPDATE_LOCATION_PROP_ID:
1221 case CERT_PUBKEY_ALG_PARA_PROP_ID:
1222 case CERT_PVK_FILE_PROP_ID:
1223 case CERT_SIGNATURE_HASH_PROP_ID:
1224 case CERT_ISSUER_PUBLIC_KEY_MD5_HASH_PROP_ID:
1225 case CERT_SUBJECT_PUBLIC_KEY_MD5_HASH_PROP_ID:
1226 case CERT_ENROLLMENT_PROP_ID:
1227 case CERT_CROSS_CERT_DIST_POINTS_PROP_ID:
1228 case CERT_RENEWAL_PROP_ID:
1230 PCRYPT_DATA_BLOB blob = (PCRYPT_DATA_BLOB)pvData;
1232 ret = CRYPT_SaveCertificateContextProperty(context, dwPropId,
1233 blob->pbData, blob->cbData);
1234 break;
1236 case CERT_DATE_STAMP_PROP_ID:
1237 ret = CRYPT_SaveCertificateContextProperty(context, dwPropId,
1238 pvData, sizeof(FILETIME));
1239 break;
1240 default:
1241 FIXME("%ld: stub\n", dwPropId);
1244 TRACE("returning %d\n", ret);
1245 return ret;
1248 BOOL WINAPI CertSetCertificateContextProperty(PCCERT_CONTEXT pCertContext,
1249 DWORD dwPropId, DWORD dwFlags, const void *pvData)
1251 PWINE_CERT_CONTEXT_REF ref = (PWINE_CERT_CONTEXT_REF)pCertContext;
1252 BOOL ret;
1254 TRACE("(%p, %ld, %08lx, %p)\n", pCertContext, dwPropId, dwFlags, pvData);
1256 /* Handle special cases for "read-only"/invalid prop IDs. Windows just
1257 * crashes on most of these, I'll be safer.
1259 switch (dwPropId)
1261 case 0:
1262 case CERT_ACCESS_STATE_PROP_ID:
1263 case CERT_CERT_PROP_ID:
1264 case CERT_CRL_PROP_ID:
1265 case CERT_CTL_PROP_ID:
1266 SetLastError(HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER));
1267 return FALSE;
1269 ret = CRYPT_SetCertificateContextProperty(ref->context, dwPropId,
1270 dwFlags, pvData);
1271 TRACE("returning %d\n", ret);
1272 return ret;
1275 /* Only the reference portion of the context is duplicated. The returned
1276 * context has the cert store set to 0, to prevent the store's certificate free
1277 * function from getting called on partial data.
1278 * FIXME: is this okay? Needs a test.
1280 PCCERT_CONTEXT WINAPI CertDuplicateCertificateContext(
1281 PCCERT_CONTEXT pCertContext)
1283 PWINE_CERT_CONTEXT_REF ref = (PWINE_CERT_CONTEXT_REF)pCertContext, ret;
1285 TRACE("(%p)\n", pCertContext);
1286 if (ref)
1288 ret = HeapAlloc(GetProcessHeap(), 0, sizeof(WINE_CERT_CONTEXT_REF));
1289 if (ret)
1291 memcpy(ret, ref, sizeof(*ret));
1292 ret->cert.hCertStore = 0;
1293 InterlockedIncrement(&ret->context->ref);
1296 else
1297 ret = NULL;
1298 return (PCCERT_CONTEXT)ret;
1301 BOOL WINAPI CertAddCertificateContextToStore(HCERTSTORE hCertStore,
1302 PCCERT_CONTEXT pCertContext, DWORD dwAddDisposition,
1303 PCCERT_CONTEXT *ppStoreContext)
1305 PWINECRYPT_CERTSTORE store = (PWINECRYPT_CERTSTORE)hCertStore;
1306 PWINE_CERT_CONTEXT_REF ref = (PWINE_CERT_CONTEXT_REF)pCertContext;
1307 PWINE_CERT_CONTEXT cert;
1308 BOOL ret;
1310 TRACE("(%p, %p, %08lx, %p)\n", hCertStore, pCertContext,
1311 dwAddDisposition, ppStoreContext);
1313 /* FIXME: some tests needed to verify return codes */
1314 if (!store)
1316 SetLastError(ERROR_INVALID_PARAMETER);
1317 return FALSE;
1319 if (store->dwMagic != WINE_CRYPTCERTSTORE_MAGIC)
1321 SetLastError(ERROR_INVALID_PARAMETER);
1322 return FALSE;
1325 cert = CRYPT_CreateCertificateContext(ref->context->cert.dwCertEncodingType,
1326 ref->context->cert.pbCertEncoded, ref->context->cert.cbCertEncoded);
1327 if (cert)
1329 PWINE_CERT_PROPERTY prop;
1331 ret = TRUE;
1332 EnterCriticalSection(&ref->context->cs);
1333 LIST_FOR_EACH_ENTRY(prop, &ref->context->extendedProperties,
1334 WINE_CERT_PROPERTY, entry)
1336 ret = CRYPT_SaveCertificateContextProperty(cert, prop->hdr.propID,
1337 prop->pbData, prop->hdr.cb);
1338 if (!ret)
1339 break;
1341 LeaveCriticalSection(&ref->context->cs);
1342 if (ret)
1344 ret = store->addCert(store, (PCCERT_CONTEXT)cert, dwAddDisposition);
1345 if (ret && ppStoreContext)
1346 *ppStoreContext = (PCCERT_CONTEXT)store->createCertRef(cert,
1347 hCertStore);
1349 if (!ret)
1350 CRYPT_FreeCert(cert);
1352 else
1353 ret = FALSE;
1354 return ret;
1357 BOOL WINAPI CertAddEncodedCertificateToStore(HCERTSTORE hCertStore,
1358 DWORD dwCertEncodingType, const BYTE *pbCertEncoded, DWORD cbCertEncoded,
1359 DWORD dwAddDisposition, PCCERT_CONTEXT *ppCertContext)
1361 WINECRYPT_CERTSTORE *hcs = (WINECRYPT_CERTSTORE *)hCertStore;
1362 BOOL ret;
1364 TRACE("(%p, %08lx, %p, %ld, %08lx, %p)\n", hCertStore, dwCertEncodingType,
1365 pbCertEncoded, cbCertEncoded, dwAddDisposition, ppCertContext);
1367 if (!hcs)
1368 ret = FALSE;
1369 else if (hcs->dwMagic != WINE_CRYPTCERTSTORE_MAGIC)
1370 ret = FALSE;
1371 else
1373 PWINE_CERT_CONTEXT cert = CRYPT_CreateCertificateContext(
1374 dwCertEncodingType, pbCertEncoded, cbCertEncoded);
1376 if (cert)
1378 ret = hcs->addCert(hcs, (PCCERT_CONTEXT)cert, dwAddDisposition);
1379 if (ret && ppCertContext)
1380 *ppCertContext = (PCCERT_CONTEXT)hcs->createCertRef(cert,
1381 hCertStore);
1382 if (!ret)
1383 CRYPT_FreeCert(cert);
1385 else
1386 ret = FALSE;
1388 return ret;
1391 PCCERT_CONTEXT WINAPI CertEnumCertificatesInStore(HCERTSTORE hCertStore,
1392 PCCERT_CONTEXT pPrev)
1394 WINECRYPT_CERTSTORE *hcs = (WINECRYPT_CERTSTORE *)hCertStore;
1395 PWINE_CERT_CONTEXT_REF prev = (PWINE_CERT_CONTEXT_REF)pPrev;
1396 PCCERT_CONTEXT ret;
1398 TRACE("(%p, %p)\n", hCertStore, pPrev);
1399 if (!hCertStore)
1400 ret = NULL;
1401 else if (hcs->dwMagic != WINE_CRYPTCERTSTORE_MAGIC)
1402 ret = NULL;
1403 else
1404 ret = (PCCERT_CONTEXT)hcs->enumCert(hcs, prev);
1405 return ret;
1408 BOOL WINAPI CertDeleteCertificateFromStore(PCCERT_CONTEXT pCertContext)
1410 BOOL ret;
1412 TRACE("(%p)\n", pCertContext);
1414 if (!pCertContext)
1415 ret = TRUE;
1416 else if (!pCertContext->hCertStore)
1417 ret = TRUE;
1418 else
1420 PWINECRYPT_CERTSTORE hcs =
1421 (PWINECRYPT_CERTSTORE)pCertContext->hCertStore;
1423 if (!hcs)
1424 ret = TRUE;
1425 else if (hcs->dwMagic != WINE_CRYPTCERTSTORE_MAGIC)
1426 ret = FALSE;
1427 else
1428 ret = hcs->deleteCert(hcs, pCertContext, 0);
1430 return ret;
1433 BOOL WINAPI CertAddEncodedCRLToStore(HCERTSTORE hCertStore,
1434 DWORD dwCertEncodingType, const BYTE *pbCrlEncoded, DWORD cbCrlEncoded,
1435 DWORD dwAddDisposition, PCCRL_CONTEXT *ppCrlContext)
1437 FIXME("(%p, %08lx, %p, %ld, %08lx, %p): stub\n", hCertStore,
1438 dwCertEncodingType, pbCrlEncoded, cbCrlEncoded, dwAddDisposition,
1439 ppCrlContext);
1440 return FALSE;
1443 BOOL WINAPI CertAddCRLContextToStore( HCERTSTORE hCertStore,
1444 PCCRL_CONTEXT pCrlContext, DWORD dwAddDisposition,
1445 PCCRL_CONTEXT* ppStoreContext )
1447 FIXME("%p %p %08lx %p\n", hCertStore, pCrlContext,
1448 dwAddDisposition, ppStoreContext);
1449 return TRUE;
1452 BOOL WINAPI CertFreeCRLContext( PCCRL_CONTEXT pCrlContext)
1454 FIXME("%p\n", pCrlContext );
1456 return TRUE;
1459 BOOL WINAPI CertDeleteCRLFromStore(PCCRL_CONTEXT pCrlContext)
1461 FIXME("(%p): stub\n", pCrlContext);
1462 return TRUE;
1465 PCCRL_CONTEXT WINAPI CertEnumCRLsInStore(HCERTSTORE hCertStore,
1466 PCCRL_CONTEXT pPrev)
1468 FIXME("(%p, %p): stub\n", hCertStore, pPrev);
1469 return NULL;
1472 PCCTL_CONTEXT WINAPI CertCreateCTLContext(DWORD dwCertEncodingType,
1473 const BYTE* pbCtlEncoded, DWORD cbCtlEncoded)
1475 FIXME("(%08lx, %p, %08lx): stub\n", dwCertEncodingType, pbCtlEncoded,
1476 cbCtlEncoded);
1477 return NULL;
1480 BOOL WINAPI CertAddEncodedCTLToStore(HCERTSTORE hCertStore,
1481 DWORD dwMsgAndCertEncodingType, const BYTE *pbCtlEncoded, DWORD cbCtlEncoded,
1482 DWORD dwAddDisposition, PCCTL_CONTEXT *ppCtlContext)
1484 FIXME("(%p, %08lx, %p, %ld, %08lx, %p): stub\n", hCertStore,
1485 dwMsgAndCertEncodingType, pbCtlEncoded, cbCtlEncoded, dwAddDisposition,
1486 ppCtlContext);
1487 return FALSE;
1490 BOOL WINAPI CertAddCTLContextToStore(HCERTSTORE hCertStore,
1491 PCCTL_CONTEXT pCtlContext, DWORD dwAddDisposition,
1492 PCCTL_CONTEXT* ppStoreContext)
1494 FIXME("(%p, %p, %08lx, %p): stub\n", hCertStore, pCtlContext,
1495 dwAddDisposition, ppStoreContext);
1496 return TRUE;
1499 BOOL WINAPI CertFreeCTLContext(PCCTL_CONTEXT pCtlContext)
1501 FIXME("(%p): stub\n", pCtlContext );
1502 return TRUE;
1505 BOOL WINAPI CertDeleteCTLFromStore(PCCTL_CONTEXT pCtlContext)
1507 FIXME("(%p): stub\n", pCtlContext);
1508 return TRUE;
1511 PCCTL_CONTEXT WINAPI CertEnumCTLsInStore(HCERTSTORE hCertStore,
1512 PCCTL_CONTEXT pPrev)
1514 FIXME("(%p, %p): stub\n", hCertStore, pPrev);
1515 return NULL;
1519 BOOL WINAPI CertCloseStore(HCERTSTORE hCertStore, DWORD dwFlags)
1521 WINECRYPT_CERTSTORE *hcs = (WINECRYPT_CERTSTORE *) hCertStore;
1523 TRACE("(%p, %08lx)\n", hCertStore, dwFlags);
1525 if( ! hCertStore )
1526 return TRUE;
1528 if ( hcs->dwMagic != WINE_CRYPTCERTSTORE_MAGIC )
1529 return FALSE;
1531 if (InterlockedDecrement(&hcs->ref) == 0)
1533 TRACE("freeing %p\n", hcs);
1534 hcs->dwMagic = 0;
1535 if (!(hcs->dwOpenFlags & CERT_STORE_NO_CRYPT_RELEASE_FLAG))
1536 CryptReleaseContext(hcs->cryptProv, 0);
1537 hcs->closeStore(hcs, dwFlags);
1539 else
1540 TRACE("%p's ref count is %ld\n", hcs, hcs->ref);
1541 return TRUE;
1544 BOOL WINAPI CertControlStore(HCERTSTORE hCertStore, DWORD dwFlags,
1545 DWORD dwCtrlType, void const *pvCtrlPara)
1547 FIXME("(%p, %08lx, %ld, %p): stub\n", hCertStore, dwFlags, dwCtrlType,
1548 pvCtrlPara);
1549 return TRUE;
1552 BOOL WINAPI CertGetCRLContextProperty(PCCRL_CONTEXT pCRLContext,
1553 DWORD dwPropId, void *pvData, DWORD *pcbData)
1555 FIXME("(%p, %ld, %p, %p): stub\n", pCRLContext, dwPropId, pvData, pcbData);
1556 return FALSE;
1559 BOOL WINAPI CertSetCRLContextProperty(PCCRL_CONTEXT pCRLContext,
1560 DWORD dwPropId, DWORD dwFlags, const void *pvData)
1562 FIXME("(%p, %ld, %08lx, %p): stub\n", pCRLContext, dwPropId, dwFlags,
1563 pvData);
1564 return FALSE;
1567 BOOL WINAPI CertSerializeCRLStoreElement(PCCRL_CONTEXT pCrlContext,
1568 DWORD dwFlags, BYTE *pbElement, DWORD *pcbElement)
1570 FIXME("(%p, %08lx, %p, %p): stub\n", pCrlContext, dwFlags, pbElement,
1571 pcbElement);
1572 return FALSE;
1575 BOOL WINAPI CertGetCTLContextProperty(PCCTL_CONTEXT pCTLContext,
1576 DWORD dwPropId, void *pvData, DWORD *pcbData)
1578 FIXME("(%p, %ld, %p, %p): stub\n", pCTLContext, dwPropId, pvData, pcbData);
1579 return FALSE;
1582 BOOL WINAPI CertSetCTLContextProperty(PCCTL_CONTEXT pCTLContext,
1583 DWORD dwPropId, DWORD dwFlags, const void *pvData)
1585 FIXME("(%p, %ld, %08lx, %p): stub\n", pCTLContext, dwPropId, dwFlags,
1586 pvData);
1587 return FALSE;
1590 BOOL WINAPI CertSerializeCTLStoreElement(PCCTL_CONTEXT pCtlContext,
1591 DWORD dwFlags, BYTE *pbElement, DWORD *pcbElement)
1593 FIXME("(%p, %08lx, %p, %p): stub\n", pCtlContext, dwFlags, pbElement,
1594 pcbElement);
1595 return FALSE;
1598 BOOL WINAPI CertSerializeCertificateStoreElement(PCCERT_CONTEXT pCertContext,
1599 DWORD dwFlags, BYTE *pbElement, DWORD *pcbElement)
1601 BOOL ret;
1603 TRACE("(%p, %08lx, %p, %p)\n", pCertContext, dwFlags, pbElement,
1604 pcbElement);
1606 if (pCertContext)
1608 PWINE_CERT_CONTEXT_REF ref = (PWINE_CERT_CONTEXT_REF)pCertContext;
1609 DWORD bytesNeeded = sizeof(WINE_CERT_PROP_HEADER) +
1610 pCertContext->cbCertEncoded;
1611 PWINE_CERT_PROPERTY prop;
1613 EnterCriticalSection(&ref->context->cs);
1614 LIST_FOR_EACH_ENTRY(prop, &ref->context->extendedProperties,
1615 WINE_CERT_PROPERTY, entry)
1616 bytesNeeded += sizeof(WINE_CERT_PROP_HEADER) + prop->hdr.cb;
1617 if (!pbElement)
1619 *pcbElement = bytesNeeded;
1620 ret = TRUE;
1622 else if (*pcbElement < bytesNeeded)
1624 *pcbElement = bytesNeeded;
1625 SetLastError(ERROR_MORE_DATA);
1626 ret = FALSE;
1628 else
1630 PWINE_CERT_PROP_HEADER hdr;
1632 LIST_FOR_EACH_ENTRY(prop, &ref->context->extendedProperties,
1633 WINE_CERT_PROPERTY, entry)
1635 memcpy(pbElement, &prop->hdr, sizeof(WINE_CERT_PROP_HEADER));
1636 pbElement += sizeof(WINE_CERT_PROP_HEADER);
1637 if (prop->hdr.cb)
1639 memcpy(pbElement, prop->pbData, prop->hdr.cb);
1640 pbElement += prop->hdr.cb;
1643 hdr = (PWINE_CERT_PROP_HEADER)pbElement;
1644 hdr->propID = CERT_CERT_PROP_ID;
1645 hdr->unknown = 1;
1646 hdr->cb = pCertContext->cbCertEncoded;
1647 memcpy(pbElement + sizeof(WINE_CERT_PROP_HEADER),
1648 pCertContext->pbCertEncoded, pCertContext->cbCertEncoded);
1649 ret = TRUE;
1651 LeaveCriticalSection(&ref->context->cs);
1653 else
1654 ret = FALSE;
1655 return ret;
1658 BOOL WINAPI CertAddSerializedElementToStore(HCERTSTORE hCertStore,
1659 const BYTE *pbElement, DWORD cbElement, DWORD dwAddDisposition, DWORD dwFlags,
1660 DWORD dwContextTypeFlags, DWORD *pdwContentType, const void **ppvContext)
1662 FIXME("(%p, %p, %ld, %08lx, %08lx, %08lx, %p, %p): stub\n", hCertStore,
1663 pbElement, cbElement, dwAddDisposition, dwFlags, dwContextTypeFlags,
1664 pdwContentType, ppvContext);
1665 return FALSE;
1668 BOOL WINAPI CertFreeCertificateContext(PCCERT_CONTEXT pCertContext)
1670 TRACE("(%p)\n", pCertContext);
1672 if (pCertContext)
1674 PWINE_CERT_CONTEXT_REF ref = (PWINE_CERT_CONTEXT_REF)pCertContext;
1675 PWINECRYPT_CERTSTORE store = (PWINECRYPT_CERTSTORE)ref->cert.hCertStore;
1677 if (InterlockedDecrement(&ref->context->ref) == 0)
1679 TRACE("freeing %p\n", ref->context);
1680 CRYPT_FreeCert(ref->context);
1682 else
1683 TRACE("%p's ref count is %ld\n", ref->context,
1684 ref->context->ref);
1685 if (store && store->dwMagic == WINE_CRYPTCERTSTORE_MAGIC &&
1686 store->freeCert)
1687 store->freeCert(ref);
1688 HeapFree(GetProcessHeap(), 0, ref);
1690 return TRUE;
1693 PCCERT_CONTEXT WINAPI CertFindCertificateInStore(HCERTSTORE hCertStore,
1694 DWORD dwCertEncodingType, DWORD dwFlags, DWORD dwType,
1695 const void *pvPara, PCCERT_CONTEXT pPrevCertContext)
1697 FIXME("stub: %p %ld %ld %ld %p %p\n", hCertStore, dwCertEncodingType,
1698 dwFlags, dwType, pvPara, pPrevCertContext);
1699 SetLastError(CRYPT_E_NOT_FOUND);
1700 return NULL;
1703 BOOL WINAPI CertAddStoreToCollection(HCERTSTORE hCollectionStore,
1704 HCERTSTORE hSiblingStore, DWORD dwUpdateFlags, DWORD dwPriority)
1706 PWINE_COLLECTIONSTORE collection = (PWINE_COLLECTIONSTORE)hCollectionStore;
1707 WINECRYPT_CERTSTORE *sibling = (WINECRYPT_CERTSTORE *)hSiblingStore;
1708 PWINE_STORE_LIST_ENTRY entry;
1709 BOOL ret;
1711 TRACE("(%p, %p, %08lx, %ld)\n", hCollectionStore, hSiblingStore,
1712 dwUpdateFlags, dwPriority);
1714 if (!collection || !sibling)
1715 return TRUE;
1716 if (collection->hdr.dwMagic != WINE_CRYPTCERTSTORE_MAGIC)
1718 SetLastError(HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER));
1719 return FALSE;
1721 if (collection->hdr.type != StoreTypeCollection)
1723 SetLastError(HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER));
1724 return FALSE;
1726 if (sibling->dwMagic != WINE_CRYPTCERTSTORE_MAGIC)
1728 SetLastError(HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER));
1729 return FALSE;
1732 entry = HeapAlloc(GetProcessHeap(), 0, sizeof(WINE_STORE_LIST_ENTRY));
1733 if (entry)
1735 InterlockedIncrement(&sibling->ref);
1736 TRACE("sibling %p's ref count is %ld\n", sibling, sibling->ref);
1737 entry->store = sibling;
1738 entry->dwUpdateFlags = dwUpdateFlags;
1739 entry->dwPriority = dwPriority;
1740 list_init(&entry->entry);
1741 TRACE("%p: adding %p, priority %ld\n", collection, entry, dwPriority);
1742 EnterCriticalSection(&collection->cs);
1743 if (dwPriority)
1745 PWINE_STORE_LIST_ENTRY cursor;
1746 BOOL added = FALSE;
1748 LIST_FOR_EACH_ENTRY(cursor, &collection->stores,
1749 WINE_STORE_LIST_ENTRY, entry)
1751 if (cursor->dwPriority < dwPriority)
1753 list_add_before(&cursor->entry, &entry->entry);
1754 added = TRUE;
1755 break;
1758 if (!added)
1759 list_add_tail(&collection->stores, &entry->entry);
1761 else
1762 list_add_tail(&collection->stores, &entry->entry);
1763 LeaveCriticalSection(&collection->cs);
1764 ret = TRUE;
1766 else
1767 ret = FALSE;
1768 return ret;
1771 void WINAPI CertRemoveStoreFromCollection(HCERTSTORE hCollectionStore,
1772 HCERTSTORE hSiblingStore)
1774 PWINE_COLLECTIONSTORE collection = (PWINE_COLLECTIONSTORE)hCollectionStore;
1775 WINECRYPT_CERTSTORE *sibling = (WINECRYPT_CERTSTORE *)hSiblingStore;
1776 PWINE_STORE_LIST_ENTRY store, next;
1778 TRACE("(%p, %p)\n", hCollectionStore, hSiblingStore);
1780 if (!collection || !sibling)
1781 return;
1782 if (collection->hdr.dwMagic != WINE_CRYPTCERTSTORE_MAGIC)
1784 SetLastError(HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER));
1785 return;
1787 if (collection->hdr.type != StoreTypeCollection)
1788 return;
1789 if (sibling->dwMagic != WINE_CRYPTCERTSTORE_MAGIC)
1791 SetLastError(HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER));
1792 return;
1794 EnterCriticalSection(&collection->cs);
1795 LIST_FOR_EACH_ENTRY_SAFE(store, next, &collection->stores,
1796 WINE_STORE_LIST_ENTRY, entry)
1798 if (store->store == sibling)
1800 list_remove(&store->entry);
1801 CertCloseStore(store->store, 0);
1802 HeapFree(GetProcessHeap(), 0, store);
1803 break;
1806 LeaveCriticalSection(&collection->cs);
1809 PCRYPT_ATTRIBUTE WINAPI CertFindAttribute(LPCSTR pszObjId, DWORD cAttr,
1810 CRYPT_ATTRIBUTE rgAttr[])
1812 PCRYPT_ATTRIBUTE ret = NULL;
1813 DWORD i;
1815 TRACE("%s %ld %p\n", debugstr_a(pszObjId), cAttr, rgAttr);
1817 if (!cAttr)
1818 return NULL;
1819 if (!pszObjId)
1821 SetLastError(ERROR_INVALID_PARAMETER);
1822 return NULL;
1825 for (i = 0; !ret && i < cAttr; i++)
1826 if (rgAttr[i].pszObjId && !strcmp(pszObjId, rgAttr[i].pszObjId))
1827 ret = &rgAttr[i];
1828 return ret;
1831 PCERT_EXTENSION WINAPI CertFindExtension(LPCSTR pszObjId, DWORD cExtensions,
1832 CERT_EXTENSION rgExtensions[])
1834 PCERT_EXTENSION ret = NULL;
1835 DWORD i;
1837 TRACE("%s %ld %p\n", debugstr_a(pszObjId), cExtensions, rgExtensions);
1839 if (!cExtensions)
1840 return NULL;
1841 if (!pszObjId)
1843 SetLastError(ERROR_INVALID_PARAMETER);
1844 return NULL;
1847 for (i = 0; !ret && i < cExtensions; i++)
1848 if (rgExtensions[i].pszObjId && !strcmp(pszObjId,
1849 rgExtensions[i].pszObjId))
1850 ret = &rgExtensions[i];
1851 return ret;
1854 PCERT_RDN_ATTR WINAPI CertFindRDNAttr(LPCSTR pszObjId, PCERT_NAME_INFO pName)
1856 PCERT_RDN_ATTR ret = NULL;
1857 DWORD i, j;
1859 TRACE("%s %p\n", debugstr_a(pszObjId), pName);
1861 if (!pszObjId)
1863 SetLastError(ERROR_INVALID_PARAMETER);
1864 return NULL;
1867 for (i = 0; !ret && i < pName->cRDN; i++)
1868 for (j = 0; !ret && j < pName->rgRDN[i].cRDNAttr; j++)
1869 if (pName->rgRDN[i].rgRDNAttr[j].pszObjId && !strcmp(pszObjId,
1870 pName->rgRDN[i].rgRDNAttr[j].pszObjId))
1871 ret = &pName->rgRDN[i].rgRDNAttr[j];
1872 return ret;
1875 LONG WINAPI CertVerifyTimeValidity(LPFILETIME pTimeToVerify,
1876 PCERT_INFO pCertInfo)
1878 FILETIME fileTime;
1879 LONG ret;
1881 if (!pTimeToVerify)
1883 SYSTEMTIME sysTime;
1885 GetSystemTime(&sysTime);
1886 SystemTimeToFileTime(&sysTime, &fileTime);
1887 pTimeToVerify = &fileTime;
1889 if ((ret = CompareFileTime(pTimeToVerify, &pCertInfo->NotBefore)) >= 0)
1891 ret = CompareFileTime(pTimeToVerify, &pCertInfo->NotAfter);
1892 if (ret < 0)
1893 ret = 0;
1895 return ret;
1898 BOOL WINAPI CryptHashCertificate(HCRYPTPROV hCryptProv, ALG_ID Algid,
1899 DWORD dwFlags, const BYTE *pbEncoded, DWORD cbEncoded, BYTE *pbComputedHash,
1900 DWORD *pcbComputedHash)
1902 BOOL ret = TRUE;
1903 HCRYPTHASH hHash = 0;
1905 TRACE("(%ld, %d, %08lx, %p, %ld, %p, %p)\n", hCryptProv, Algid, dwFlags,
1906 pbEncoded, cbEncoded, pbComputedHash, pcbComputedHash);
1908 if (!hCryptProv)
1909 hCryptProv = CRYPT_GetDefaultProvider();
1910 if (!Algid)
1911 Algid = CALG_SHA1;
1912 if (ret)
1914 ret = CryptCreateHash(hCryptProv, Algid, 0, 0, &hHash);
1915 if (ret)
1917 ret = CryptHashData(hHash, pbEncoded, cbEncoded, 0);
1918 if (ret)
1919 ret = CryptGetHashParam(hHash, HP_HASHVAL, pbComputedHash,
1920 pcbComputedHash, 0);
1921 CryptDestroyHash(hHash);
1924 return ret;