2 * Copyright 2002 Mike McCormack for CodeWeavers
3 * Copyright 2004-2006 Juan Lang
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 * - The concept of physical stores and locations isn't implemented. (This
21 * doesn't mean registry stores et al aren't implemented. See the PSDK for
22 * registering and enumerating physical stores and locations.)
23 * - Many flags, options and whatnot are unimplemented.
34 #include "wine/debug.h"
35 #include "wine/list.h"
37 #include "wine/exception.h"
38 #include "crypt32_private.h"
40 WINE_DEFAULT_DEBUG_CHANNEL(crypt
);
42 #define WINE_CRYPTCERTSTORE_MAGIC 0x74726563
44 static const WINE_CONTEXT_INTERFACE gCertInterface
= {
45 (CreateContextFunc
)CertCreateCertificateContext
,
46 (AddContextToStoreFunc
)CertAddCertificateContextToStore
,
47 (AddEncodedContextToStoreFunc
)CertAddEncodedCertificateToStore
,
48 (DuplicateContextFunc
)CertDuplicateCertificateContext
,
49 (EnumContextsInStoreFunc
)CertEnumCertificatesInStore
,
50 (EnumPropertiesFunc
)CertEnumCertificateContextProperties
,
51 (GetContextPropertyFunc
)CertGetCertificateContextProperty
,
52 (SetContextPropertyFunc
)CertSetCertificateContextProperty
,
53 (SerializeElementFunc
)CertSerializeCertificateStoreElement
,
54 (FreeContextFunc
)CertFreeCertificateContext
,
55 (DeleteContextFunc
)CertDeleteCertificateFromStore
,
57 PCWINE_CONTEXT_INTERFACE pCertInterface
= &gCertInterface
;
59 static const WINE_CONTEXT_INTERFACE gCRLInterface
= {
60 (CreateContextFunc
)CertCreateCRLContext
,
61 (AddContextToStoreFunc
)CertAddCRLContextToStore
,
62 (AddEncodedContextToStoreFunc
)CertAddEncodedCRLToStore
,
63 (DuplicateContextFunc
)CertDuplicateCRLContext
,
64 (EnumContextsInStoreFunc
)CertEnumCRLsInStore
,
65 (EnumPropertiesFunc
)CertEnumCRLContextProperties
,
66 (GetContextPropertyFunc
)CertGetCRLContextProperty
,
67 (SetContextPropertyFunc
)CertSetCRLContextProperty
,
68 (SerializeElementFunc
)CertSerializeCRLStoreElement
,
69 (FreeContextFunc
)CertFreeCRLContext
,
70 (DeleteContextFunc
)CertDeleteCRLFromStore
,
72 PCWINE_CONTEXT_INTERFACE pCRLInterface
= &gCRLInterface
;
74 static const WINE_CONTEXT_INTERFACE gCTLInterface
= {
75 (CreateContextFunc
)CertCreateCTLContext
,
76 (AddContextToStoreFunc
)CertAddCTLContextToStore
,
77 (AddEncodedContextToStoreFunc
)CertAddEncodedCTLToStore
,
78 (DuplicateContextFunc
)CertDuplicateCTLContext
,
79 (EnumContextsInStoreFunc
)CertEnumCTLsInStore
,
80 (EnumPropertiesFunc
)CertEnumCTLContextProperties
,
81 (GetContextPropertyFunc
)CertGetCTLContextProperty
,
82 (SetContextPropertyFunc
)CertSetCTLContextProperty
,
83 (SerializeElementFunc
)CertSerializeCTLStoreElement
,
84 (FreeContextFunc
)CertFreeCTLContext
,
85 (DeleteContextFunc
)CertDeleteCTLFromStore
,
87 PCWINE_CONTEXT_INTERFACE pCTLInterface
= &gCTLInterface
;
89 struct WINE_CRYPTCERTSTORE
;
91 typedef struct WINE_CRYPTCERTSTORE
* (*StoreOpenFunc
)(HCRYPTPROV hCryptProv
,
92 DWORD dwFlags
, const void *pvPara
);
94 /* Called to enumerate the next context in a store. */
95 typedef void * (*EnumFunc
)(struct WINE_CRYPTCERTSTORE
*store
, void *pPrev
);
97 /* Called to add a context to a store. If toReplace is not NULL,
98 * context replaces toReplace in the store, and access checks should not be
99 * performed. Otherwise context is a new context, and it should only be
100 * added if the store allows it. If ppStoreContext is not NULL, the added
101 * context should be returned in *ppStoreContext.
103 typedef BOOL (*AddFunc
)(struct WINE_CRYPTCERTSTORE
*store
, void *context
,
104 void *toReplace
, const void **ppStoreContext
);
106 typedef BOOL (*DeleteFunc
)(struct WINE_CRYPTCERTSTORE
*store
, void *context
);
108 typedef struct _CONTEXT_STORE
111 EnumFunc enumContext
;
112 DeleteFunc deleteContext
;
113 } CONTEXT_STORE
, *PCONTEXT_STORE
;
115 typedef enum _CertStoreType
{
121 /* A cert store is polymorphic through the use of function pointers. A type
122 * is still needed to distinguish collection stores from other types.
123 * On the function pointers:
124 * - closeStore is called when the store's ref count becomes 0
125 * - control is optional, but should be implemented by any store that supports
128 typedef struct WINE_CRYPTCERTSTORE
133 HCRYPTPROV cryptProv
;
135 PFN_CERT_STORE_PROV_CLOSE closeStore
;
138 PFN_CERT_STORE_PROV_CONTROL control
; /* optional */
139 } WINECRYPT_CERTSTORE
, *PWINECRYPT_CERTSTORE
;
141 typedef struct _WINE_MEMSTORE
143 WINECRYPT_CERTSTORE hdr
;
144 struct ContextList
*certs
;
145 struct ContextList
*crls
;
146 } WINE_MEMSTORE
, *PWINE_MEMSTORE
;
148 typedef struct _WINE_HASH_TO_DELETE
152 } WINE_HASH_TO_DELETE
, *PWINE_HASH_TO_DELETE
;
154 typedef struct _WINE_REGSTOREINFO
157 HCRYPTPROV cryptProv
;
158 PWINECRYPT_CERTSTORE memStore
;
162 struct list certsToDelete
;
163 struct list crlsToDelete
;
164 } WINE_REGSTOREINFO
, *PWINE_REGSTOREINFO
;
166 typedef struct _WINE_FILESTOREINFO
169 HCRYPTPROV cryptProv
;
170 PWINECRYPT_CERTSTORE memStore
;
173 } WINE_FILESTOREINFO
, *PWINE_FILESTOREINFO
;
175 typedef struct _WINE_STORE_LIST_ENTRY
177 PWINECRYPT_CERTSTORE store
;
181 } WINE_STORE_LIST_ENTRY
, *PWINE_STORE_LIST_ENTRY
;
183 typedef struct _WINE_COLLECTIONSTORE
185 WINECRYPT_CERTSTORE hdr
;
188 } WINE_COLLECTIONSTORE
, *PWINE_COLLECTIONSTORE
;
190 typedef struct _WINE_PROVIDERSTORE
192 WINECRYPT_CERTSTORE hdr
;
193 DWORD dwStoreProvFlags
;
194 PWINECRYPT_CERTSTORE memStore
;
195 HCERTSTOREPROV hStoreProv
;
196 PFN_CERT_STORE_PROV_CLOSE provCloseStore
;
197 PFN_CERT_STORE_PROV_WRITE_CERT provWriteCert
;
198 PFN_CERT_STORE_PROV_DELETE_CERT provDeleteCert
;
199 PFN_CERT_STORE_PROV_WRITE_CRL provWriteCrl
;
200 PFN_CERT_STORE_PROV_DELETE_CRL provDeleteCrl
;
201 PFN_CERT_STORE_PROV_CONTROL provControl
;
202 } WINE_PROVIDERSTORE
, *PWINE_PROVIDERSTORE
;
204 static void CRYPT_InitStore(WINECRYPT_CERTSTORE
*store
, HCRYPTPROV hCryptProv
,
205 DWORD dwFlags
, CertStoreType type
)
208 store
->dwMagic
= WINE_CRYPTCERTSTORE_MAGIC
;
212 hCryptProv
= CRYPT_GetDefaultProvider();
213 dwFlags
|= CERT_STORE_NO_CRYPT_RELEASE_FLAG
;
215 store
->cryptProv
= hCryptProv
;
216 store
->dwOpenFlags
= dwFlags
;
219 static BOOL
CRYPT_MemAddCert(PWINECRYPT_CERTSTORE store
, void *cert
,
220 void *toReplace
, const void **ppStoreContext
)
222 WINE_MEMSTORE
*ms
= (WINE_MEMSTORE
*)store
;
223 PCERT_CONTEXT context
;
225 TRACE("(%p, %p, %p, %p)\n", store
, cert
, toReplace
, ppStoreContext
);
227 context
= (PCERT_CONTEXT
)ContextList_Add(ms
->certs
, cert
, toReplace
);
230 context
->hCertStore
= store
;
232 *ppStoreContext
= CertDuplicateCertificateContext(context
);
234 return context
? TRUE
: FALSE
;
237 static void *CRYPT_MemEnumCert(PWINECRYPT_CERTSTORE store
, void *pPrev
)
239 WINE_MEMSTORE
*ms
= (WINE_MEMSTORE
*)store
;
242 TRACE("(%p, %p)\n", store
, pPrev
);
244 ret
= ContextList_Enum(ms
->certs
, pPrev
);
246 SetLastError(CRYPT_E_NOT_FOUND
);
248 TRACE("returning %p\n", ret
);
252 static BOOL
CRYPT_MemDeleteCert(PWINECRYPT_CERTSTORE store
, void *pCertContext
)
254 WINE_MEMSTORE
*ms
= (WINE_MEMSTORE
*)store
;
256 ContextList_Delete(ms
->certs
, pCertContext
);
260 static BOOL
CRYPT_MemAddCrl(PWINECRYPT_CERTSTORE store
, void *crl
,
261 void *toReplace
, const void **ppStoreContext
)
263 WINE_MEMSTORE
*ms
= (WINE_MEMSTORE
*)store
;
264 PCRL_CONTEXT context
;
266 TRACE("(%p, %p, %p, %p)\n", store
, crl
, toReplace
, ppStoreContext
);
268 context
= (PCRL_CONTEXT
)ContextList_Add(ms
->crls
, crl
, toReplace
);
271 context
->hCertStore
= store
;
273 *ppStoreContext
= CertDuplicateCRLContext(context
);
275 return context
? TRUE
: FALSE
;
278 static void *CRYPT_MemEnumCrl(PWINECRYPT_CERTSTORE store
, void *pPrev
)
280 WINE_MEMSTORE
*ms
= (WINE_MEMSTORE
*)store
;
283 TRACE("(%p, %p)\n", store
, pPrev
);
285 ret
= ContextList_Enum(ms
->crls
, pPrev
);
287 SetLastError(CRYPT_E_NOT_FOUND
);
289 TRACE("returning %p\n", ret
);
293 static BOOL
CRYPT_MemDeleteCrl(PWINECRYPT_CERTSTORE store
, void *pCrlContext
)
295 WINE_MEMSTORE
*ms
= (WINE_MEMSTORE
*)store
;
297 ContextList_Delete(ms
->crls
, pCrlContext
);
301 static void CRYPT_MemEmptyStore(PWINE_MEMSTORE store
)
303 ContextList_Empty(store
->certs
);
304 ContextList_Empty(store
->crls
);
307 static void WINAPI
CRYPT_MemCloseStore(HCERTSTORE hCertStore
, DWORD dwFlags
)
309 WINE_MEMSTORE
*store
= (WINE_MEMSTORE
*)hCertStore
;
311 TRACE("(%p, %08lx)\n", store
, dwFlags
);
313 FIXME("Unimplemented flags: %08lx\n", dwFlags
);
315 ContextList_Free(store
->certs
);
316 ContextList_Free(store
->crls
);
320 static WINECRYPT_CERTSTORE
*CRYPT_MemOpenStore(HCRYPTPROV hCryptProv
,
321 DWORD dwFlags
, const void *pvPara
)
323 PWINE_MEMSTORE store
;
325 TRACE("(%ld, %08lx, %p)\n", hCryptProv
, dwFlags
, pvPara
);
327 if (dwFlags
& CERT_STORE_DELETE_FLAG
)
329 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
334 store
= CryptMemAlloc(sizeof(WINE_MEMSTORE
));
337 memset(store
, 0, sizeof(WINE_MEMSTORE
));
338 CRYPT_InitStore(&store
->hdr
, hCryptProv
, dwFlags
, StoreTypeMem
);
339 store
->hdr
.closeStore
= CRYPT_MemCloseStore
;
340 store
->hdr
.certs
.addContext
= CRYPT_MemAddCert
;
341 store
->hdr
.certs
.enumContext
= CRYPT_MemEnumCert
;
342 store
->hdr
.certs
.deleteContext
= CRYPT_MemDeleteCert
;
343 store
->hdr
.crls
.addContext
= CRYPT_MemAddCrl
;
344 store
->hdr
.crls
.enumContext
= CRYPT_MemEnumCrl
;
345 store
->hdr
.crls
.deleteContext
= CRYPT_MemDeleteCrl
;
346 store
->hdr
.control
= NULL
;
347 store
->certs
= ContextList_Create(pCertInterface
,
348 sizeof(CERT_CONTEXT
));
349 store
->crls
= ContextList_Create(pCRLInterface
,
350 sizeof(CRL_CONTEXT
));
353 return (PWINECRYPT_CERTSTORE
)store
;
356 static void WINAPI
CRYPT_CollectionCloseStore(HCERTSTORE store
, DWORD dwFlags
)
358 PWINE_COLLECTIONSTORE cs
= (PWINE_COLLECTIONSTORE
)store
;
359 PWINE_STORE_LIST_ENTRY entry
, next
;
361 TRACE("(%p, %08lx)\n", store
, dwFlags
);
363 LIST_FOR_EACH_ENTRY_SAFE(entry
, next
, &cs
->stores
, WINE_STORE_LIST_ENTRY
,
366 TRACE("closing %p\n", entry
);
367 CertCloseStore((HCERTSTORE
)entry
->store
, dwFlags
);
370 DeleteCriticalSection(&cs
->cs
);
374 static void *CRYPT_CollectionCreateContextFromChild(PWINE_COLLECTIONSTORE store
,
375 PWINE_STORE_LIST_ENTRY storeEntry
, void *child
, size_t contextSize
,
378 void *ret
= Context_CreateLinkContext(contextSize
, child
,
379 sizeof(PWINE_STORE_LIST_ENTRY
), addRef
);
382 *(PWINE_STORE_LIST_ENTRY
*)Context_GetExtra(ret
, contextSize
)
388 static BOOL
CRYPT_CollectionAddContext(PWINE_COLLECTIONSTORE store
,
389 unsigned int contextStoreOffset
, void *context
, void *toReplace
, unsigned int contextSize
,
390 void **pChildContext
)
393 void *childContext
= NULL
;
394 PWINE_STORE_LIST_ENTRY storeEntry
= NULL
;
396 TRACE("(%p, %d, %p, %p, %d)\n", store
, contextStoreOffset
, context
,
397 toReplace
, contextSize
);
402 void *existingLinked
= Context_GetLinkedContext(toReplace
, contextSize
);
403 PCONTEXT_STORE contextStore
;
405 storeEntry
= *(PWINE_STORE_LIST_ENTRY
*)Context_GetExtra(toReplace
,
407 contextStore
= (PCONTEXT_STORE
)((LPBYTE
)storeEntry
->store
+
409 ret
= contextStore
->addContext(storeEntry
->store
, context
,
410 existingLinked
, (const void **)&childContext
);
414 PWINE_STORE_LIST_ENTRY entry
, next
;
416 EnterCriticalSection(&store
->cs
);
417 LIST_FOR_EACH_ENTRY_SAFE(entry
, next
, &store
->stores
,
418 WINE_STORE_LIST_ENTRY
, entry
)
420 if (entry
->dwUpdateFlags
& CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG
)
422 PCONTEXT_STORE contextStore
= (PCONTEXT_STORE
)(
423 (LPBYTE
)entry
->store
+ contextStoreOffset
);
426 ret
= contextStore
->addContext(entry
->store
, context
, NULL
,
427 (const void **)&childContext
);
431 LeaveCriticalSection(&store
->cs
);
433 SetLastError(E_ACCESSDENIED
);
435 *pChildContext
= childContext
;
439 /* Advances a collection enumeration by one context, if possible, where
441 * - calling the current store's enumeration function once, and returning
442 * the enumerated context if one is returned
443 * - moving to the next store if the current store has no more items, and
444 * recursively calling itself to get the next item.
445 * Returns NULL if the collection contains no more items or on error.
446 * Assumes the collection store's lock is held.
448 static void *CRYPT_CollectionAdvanceEnum(PWINE_COLLECTIONSTORE store
,
449 PWINE_STORE_LIST_ENTRY storeEntry
, size_t contextStoreOffset
,
450 PCWINE_CONTEXT_INTERFACE contextInterface
, void *pPrev
, size_t contextSize
)
453 struct list
*storeNext
= list_next(&store
->stores
, &storeEntry
->entry
);
454 PCONTEXT_STORE contextStore
= (PCONTEXT_STORE
)((LPBYTE
)storeEntry
->store
+
457 TRACE("(%p, %p, %p)\n", store
, storeEntry
, pPrev
);
461 /* Ref-counting funny business: "duplicate" (addref) the child, because
462 * the free(pPrev) below can cause the ref count to become negative.
464 child
= Context_GetLinkedContext(pPrev
, contextSize
);
465 contextInterface
->duplicate(child
);
466 child
= contextStore
->enumContext(storeEntry
->store
, child
);
467 contextInterface
->free(pPrev
);
471 child
= storeEntry
->store
->certs
.enumContext(storeEntry
->store
, NULL
);
473 ret
= CRYPT_CollectionCreateContextFromChild(store
, storeEntry
, child
,
478 ret
= CRYPT_CollectionAdvanceEnum(store
, LIST_ENTRY(storeNext
,
479 WINE_STORE_LIST_ENTRY
, entry
), contextStoreOffset
,
480 contextInterface
, NULL
, contextSize
);
483 SetLastError(CRYPT_E_NOT_FOUND
);
487 TRACE("returning %p\n", ret
);
491 static BOOL
CRYPT_CollectionAddCert(PWINECRYPT_CERTSTORE store
, void *cert
,
492 void *toReplace
, const void **ppStoreContext
)
495 void *childContext
= NULL
;
496 PWINE_COLLECTIONSTORE cs
= (PWINE_COLLECTIONSTORE
)store
;
498 ret
= CRYPT_CollectionAddContext(cs
, offsetof(WINECRYPT_CERTSTORE
, certs
),
499 cert
, toReplace
, sizeof(CERT_CONTEXT
), &childContext
);
500 if (ppStoreContext
&& childContext
)
502 PWINE_STORE_LIST_ENTRY storeEntry
= *(PWINE_STORE_LIST_ENTRY
*)
503 Context_GetExtra(childContext
, sizeof(CERT_CONTEXT
));
504 PCERT_CONTEXT context
=
505 CRYPT_CollectionCreateContextFromChild(cs
, storeEntry
, childContext
,
506 sizeof(CERT_CONTEXT
), TRUE
);
509 context
->hCertStore
= store
;
510 *ppStoreContext
= context
;
512 CertFreeCertificateContext((PCCERT_CONTEXT
)childContext
);
516 static void *CRYPT_CollectionEnumCert(PWINECRYPT_CERTSTORE store
, void *pPrev
)
518 PWINE_COLLECTIONSTORE cs
= (PWINE_COLLECTIONSTORE
)store
;
521 TRACE("(%p, %p)\n", store
, pPrev
);
523 EnterCriticalSection(&cs
->cs
);
526 PWINE_STORE_LIST_ENTRY storeEntry
=
527 *(PWINE_STORE_LIST_ENTRY
*)Context_GetExtra(pPrev
,
528 sizeof(CERT_CONTEXT
));
530 ret
= CRYPT_CollectionAdvanceEnum(cs
, storeEntry
,
531 offsetof(WINECRYPT_CERTSTORE
, certs
), pCertInterface
, pPrev
,
532 sizeof(CERT_CONTEXT
));
536 if (!list_empty(&cs
->stores
))
538 PWINE_STORE_LIST_ENTRY storeEntry
= LIST_ENTRY(cs
->stores
.next
,
539 WINE_STORE_LIST_ENTRY
, entry
);
541 ret
= CRYPT_CollectionAdvanceEnum(cs
, storeEntry
,
542 offsetof(WINECRYPT_CERTSTORE
, certs
), pCertInterface
, NULL
,
543 sizeof(CERT_CONTEXT
));
547 SetLastError(CRYPT_E_NOT_FOUND
);
551 LeaveCriticalSection(&cs
->cs
);
553 ((PCERT_CONTEXT
)ret
)->hCertStore
= store
;
554 TRACE("returning %p\n", ret
);
558 static BOOL
CRYPT_CollectionDeleteCert(PWINECRYPT_CERTSTORE store
,
563 TRACE("(%p, %p)\n", store
, pCertContext
);
565 ret
= CertDeleteCertificateFromStore((PCCERT_CONTEXT
)
566 Context_GetLinkedContext(pCertContext
, sizeof(CERT_CONTEXT
)));
570 static BOOL
CRYPT_CollectionAddCRL(PWINECRYPT_CERTSTORE store
, void *crl
,
571 void *toReplace
, const void **ppStoreContext
)
574 void *childContext
= NULL
;
575 PWINE_COLLECTIONSTORE cs
= (PWINE_COLLECTIONSTORE
)store
;
577 ret
= CRYPT_CollectionAddContext(cs
, offsetof(WINECRYPT_CERTSTORE
, crls
),
578 crl
, toReplace
, sizeof(CRL_CONTEXT
), &childContext
);
579 if (ppStoreContext
&& childContext
)
581 PWINE_STORE_LIST_ENTRY storeEntry
= *(PWINE_STORE_LIST_ENTRY
*)
582 Context_GetExtra(childContext
, sizeof(CRL_CONTEXT
));
583 PCRL_CONTEXT context
=
584 CRYPT_CollectionCreateContextFromChild(cs
, storeEntry
, childContext
,
585 sizeof(CRL_CONTEXT
), TRUE
);
588 context
->hCertStore
= store
;
589 *ppStoreContext
= context
;
591 CertFreeCRLContext((PCCRL_CONTEXT
)childContext
);
595 static void *CRYPT_CollectionEnumCRL(PWINECRYPT_CERTSTORE store
, void *pPrev
)
597 PWINE_COLLECTIONSTORE cs
= (PWINE_COLLECTIONSTORE
)store
;
600 TRACE("(%p, %p)\n", store
, pPrev
);
602 EnterCriticalSection(&cs
->cs
);
605 PWINE_STORE_LIST_ENTRY storeEntry
=
606 *(PWINE_STORE_LIST_ENTRY
*)Context_GetExtra(pPrev
,
607 sizeof(CRL_CONTEXT
));
609 ret
= CRYPT_CollectionAdvanceEnum(cs
, storeEntry
,
610 offsetof(WINECRYPT_CERTSTORE
, crls
), pCRLInterface
, pPrev
,
611 sizeof(CRL_CONTEXT
));
615 if (!list_empty(&cs
->stores
))
617 PWINE_STORE_LIST_ENTRY storeEntry
= LIST_ENTRY(cs
->stores
.next
,
618 WINE_STORE_LIST_ENTRY
, entry
);
620 ret
= CRYPT_CollectionAdvanceEnum(cs
, storeEntry
,
621 offsetof(WINECRYPT_CERTSTORE
, crls
), pCRLInterface
, NULL
,
622 sizeof(CRL_CONTEXT
));
626 SetLastError(CRYPT_E_NOT_FOUND
);
630 LeaveCriticalSection(&cs
->cs
);
632 ((PCRL_CONTEXT
)ret
)->hCertStore
= store
;
633 TRACE("returning %p\n", ret
);
637 static BOOL
CRYPT_CollectionDeleteCRL(PWINECRYPT_CERTSTORE store
,
642 TRACE("(%p, %p)\n", store
, pCrlContext
);
644 ret
= CertDeleteCRLFromStore((PCCRL_CONTEXT
)
645 Context_GetLinkedContext(pCrlContext
, sizeof(CRL_CONTEXT
)));
649 static WINECRYPT_CERTSTORE
*CRYPT_CollectionOpenStore(HCRYPTPROV hCryptProv
,
650 DWORD dwFlags
, const void *pvPara
)
652 PWINE_COLLECTIONSTORE store
;
654 if (dwFlags
& CERT_STORE_DELETE_FLAG
)
656 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
661 store
= CryptMemAlloc(sizeof(WINE_COLLECTIONSTORE
));
664 memset(store
, 0, sizeof(WINE_COLLECTIONSTORE
));
665 CRYPT_InitStore(&store
->hdr
, hCryptProv
, dwFlags
,
666 StoreTypeCollection
);
667 store
->hdr
.closeStore
= CRYPT_CollectionCloseStore
;
668 store
->hdr
.certs
.addContext
= CRYPT_CollectionAddCert
;
669 store
->hdr
.certs
.enumContext
= CRYPT_CollectionEnumCert
;
670 store
->hdr
.certs
.deleteContext
= CRYPT_CollectionDeleteCert
;
671 store
->hdr
.crls
.addContext
= CRYPT_CollectionAddCRL
;
672 store
->hdr
.crls
.enumContext
= CRYPT_CollectionEnumCRL
;
673 store
->hdr
.crls
.deleteContext
= CRYPT_CollectionDeleteCRL
;
674 InitializeCriticalSection(&store
->cs
);
675 list_init(&store
->stores
);
678 return (PWINECRYPT_CERTSTORE
)store
;
681 static void WINAPI
CRYPT_ProvCloseStore(HCERTSTORE hCertStore
, DWORD dwFlags
)
683 PWINE_PROVIDERSTORE store
= (PWINE_PROVIDERSTORE
)hCertStore
;
685 TRACE("(%p, %08lx)\n", store
, dwFlags
);
687 if (store
->provCloseStore
)
688 store
->provCloseStore(store
->hStoreProv
, dwFlags
);
689 if (!(store
->dwStoreProvFlags
& CERT_STORE_PROV_EXTERNAL_FLAG
))
690 CertCloseStore(store
->memStore
, dwFlags
);
694 static BOOL
CRYPT_ProvAddCert(PWINECRYPT_CERTSTORE store
, void *cert
,
695 void *toReplace
, const void **ppStoreContext
)
697 PWINE_PROVIDERSTORE ps
= (PWINE_PROVIDERSTORE
)store
;
700 TRACE("(%p, %p, %p, %p)\n", store
, cert
, toReplace
, ppStoreContext
);
703 ret
= ps
->memStore
->certs
.addContext(ps
->memStore
, cert
, toReplace
,
704 (const void **)ppStoreContext
);
708 if (ps
->provWriteCert
)
709 ret
= ps
->provWriteCert(ps
->hStoreProv
, (PCCERT_CONTEXT
)cert
,
710 CERT_STORE_PROV_WRITE_ADD_FLAG
);
712 ret
= ps
->memStore
->certs
.addContext(ps
->memStore
, cert
, NULL
,
713 (const void **)ppStoreContext
);
715 /* dirty trick: replace the returned context's hCertStore with
719 (*(PCERT_CONTEXT
*)ppStoreContext
)->hCertStore
= store
;
723 static void *CRYPT_ProvEnumCert(PWINECRYPT_CERTSTORE store
, void *pPrev
)
725 PWINE_PROVIDERSTORE ps
= (PWINE_PROVIDERSTORE
)store
;
728 ret
= ps
->memStore
->certs
.enumContext(ps
->memStore
, pPrev
);
731 /* same dirty trick: replace the returned context's hCertStore with
734 ((PCERT_CONTEXT
)ret
)->hCertStore
= store
;
739 static BOOL
CRYPT_ProvDeleteCert(PWINECRYPT_CERTSTORE store
, void *cert
)
741 PWINE_PROVIDERSTORE ps
= (PWINE_PROVIDERSTORE
)store
;
744 TRACE("(%p, %p)\n", store
, cert
);
746 if (ps
->provDeleteCert
)
747 ret
= ps
->provDeleteCert(ps
->hStoreProv
, cert
, 0);
749 ret
= ps
->memStore
->certs
.deleteContext(ps
->memStore
, cert
);
753 static BOOL
CRYPT_ProvAddCRL(PWINECRYPT_CERTSTORE store
, void *crl
,
754 void *toReplace
, const void **ppStoreContext
)
756 PWINE_PROVIDERSTORE ps
= (PWINE_PROVIDERSTORE
)store
;
759 TRACE("(%p, %p, %p, %p)\n", store
, crl
, toReplace
, ppStoreContext
);
762 ret
= ps
->memStore
->crls
.addContext(ps
->memStore
, crl
, toReplace
,
763 (const void **)ppStoreContext
);
766 if (ps
->hdr
.dwOpenFlags
& CERT_STORE_READONLY_FLAG
)
768 SetLastError(ERROR_ACCESS_DENIED
);
774 if (ps
->provWriteCrl
)
775 ret
= ps
->provWriteCrl(ps
->hStoreProv
, (PCCRL_CONTEXT
)crl
,
776 CERT_STORE_PROV_WRITE_ADD_FLAG
);
778 ret
= ps
->memStore
->crls
.addContext(ps
->memStore
, crl
, NULL
,
779 (const void **)ppStoreContext
);
782 /* dirty trick: replace the returned context's hCertStore with
786 (*(PCRL_CONTEXT
*)ppStoreContext
)->hCertStore
= store
;
790 static void *CRYPT_ProvEnumCRL(PWINECRYPT_CERTSTORE store
, void *pPrev
)
792 PWINE_PROVIDERSTORE ps
= (PWINE_PROVIDERSTORE
)store
;
795 ret
= ps
->memStore
->crls
.enumContext(ps
->memStore
, pPrev
);
798 /* same dirty trick: replace the returned context's hCertStore with
801 ((PCERT_CONTEXT
)ret
)->hCertStore
= store
;
806 static BOOL
CRYPT_ProvDeleteCRL(PWINECRYPT_CERTSTORE store
, void *crl
)
808 PWINE_PROVIDERSTORE ps
= (PWINE_PROVIDERSTORE
)store
;
811 TRACE("(%p, %p)\n", store
, crl
);
813 if (ps
->provDeleteCrl
)
814 ret
= ps
->provDeleteCrl(ps
->hStoreProv
, crl
, 0);
816 ret
= ps
->memStore
->crls
.deleteContext(ps
->memStore
, crl
);
820 static BOOL WINAPI
CRYPT_ProvControl(HCERTSTORE hCertStore
, DWORD dwFlags
,
821 DWORD dwCtrlType
, void const *pvCtrlPara
)
823 PWINE_PROVIDERSTORE store
= (PWINE_PROVIDERSTORE
)hCertStore
;
826 TRACE("(%p, %08lx, %ld, %p)\n", hCertStore
, dwFlags
, dwCtrlType
,
829 if (store
->provControl
)
830 ret
= store
->provControl(store
->hStoreProv
, dwFlags
, dwCtrlType
,
835 static PWINECRYPT_CERTSTORE
CRYPT_ProvCreateStore(HCRYPTPROV hCryptProv
,
836 DWORD dwFlags
, PWINECRYPT_CERTSTORE memStore
, PCERT_STORE_PROV_INFO pProvInfo
)
838 PWINE_PROVIDERSTORE ret
= (PWINE_PROVIDERSTORE
)CryptMemAlloc(
839 sizeof(WINE_PROVIDERSTORE
));
843 CRYPT_InitStore(&ret
->hdr
, hCryptProv
, dwFlags
,
845 ret
->dwStoreProvFlags
= pProvInfo
->dwStoreProvFlags
;
846 if (ret
->dwStoreProvFlags
& CERT_STORE_PROV_EXTERNAL_FLAG
)
848 CertCloseStore(memStore
, 0);
849 ret
->memStore
= NULL
;
852 ret
->memStore
= memStore
;
853 ret
->hStoreProv
= pProvInfo
->hStoreProv
;
854 ret
->hdr
.closeStore
= CRYPT_ProvCloseStore
;
855 ret
->hdr
.certs
.addContext
= CRYPT_ProvAddCert
;
856 ret
->hdr
.certs
.enumContext
= CRYPT_ProvEnumCert
;
857 ret
->hdr
.certs
.deleteContext
= CRYPT_ProvDeleteCert
;
858 ret
->hdr
.crls
.addContext
= CRYPT_ProvAddCRL
;
859 ret
->hdr
.crls
.enumContext
= CRYPT_ProvEnumCRL
;
860 ret
->hdr
.crls
.deleteContext
= CRYPT_ProvDeleteCRL
;
861 ret
->hdr
.control
= CRYPT_ProvControl
;
862 if (pProvInfo
->cStoreProvFunc
> CERT_STORE_PROV_CLOSE_FUNC
)
863 ret
->provCloseStore
=
864 pProvInfo
->rgpvStoreProvFunc
[CERT_STORE_PROV_CLOSE_FUNC
];
866 ret
->provCloseStore
= NULL
;
867 if (pProvInfo
->cStoreProvFunc
>
868 CERT_STORE_PROV_WRITE_CERT_FUNC
)
869 ret
->provWriteCert
= pProvInfo
->rgpvStoreProvFunc
[
870 CERT_STORE_PROV_WRITE_CERT_FUNC
];
872 ret
->provWriteCert
= NULL
;
873 if (pProvInfo
->cStoreProvFunc
>
874 CERT_STORE_PROV_DELETE_CERT_FUNC
)
875 ret
->provDeleteCert
= pProvInfo
->rgpvStoreProvFunc
[
876 CERT_STORE_PROV_DELETE_CERT_FUNC
];
878 ret
->provDeleteCert
= NULL
;
879 if (pProvInfo
->cStoreProvFunc
>
880 CERT_STORE_PROV_WRITE_CRL_FUNC
)
881 ret
->provWriteCrl
= pProvInfo
->rgpvStoreProvFunc
[
882 CERT_STORE_PROV_WRITE_CRL_FUNC
];
884 ret
->provWriteCert
= NULL
;
885 if (pProvInfo
->cStoreProvFunc
>
886 CERT_STORE_PROV_DELETE_CRL_FUNC
)
887 ret
->provDeleteCrl
= pProvInfo
->rgpvStoreProvFunc
[
888 CERT_STORE_PROV_DELETE_CRL_FUNC
];
890 ret
->provDeleteCert
= NULL
;
891 if (pProvInfo
->cStoreProvFunc
>
892 CERT_STORE_PROV_CONTROL_FUNC
)
893 ret
->provControl
= pProvInfo
->rgpvStoreProvFunc
[
894 CERT_STORE_PROV_CONTROL_FUNC
];
896 ret
->provControl
= NULL
;
898 return (PWINECRYPT_CERTSTORE
)ret
;
901 static PWINECRYPT_CERTSTORE
CRYPT_ProvOpenStore(LPCSTR lpszStoreProvider
,
902 DWORD dwEncodingType
, HCRYPTPROV hCryptProv
, DWORD dwFlags
, const void *pvPara
)
904 static HCRYPTOIDFUNCSET set
= NULL
;
905 PFN_CERT_DLL_OPEN_STORE_PROV_FUNC provOpenFunc
;
906 HCRYPTOIDFUNCADDR hFunc
;
907 PWINECRYPT_CERTSTORE ret
= NULL
;
910 set
= CryptInitOIDFunctionSet(CRYPT_OID_OPEN_STORE_PROV_FUNC
, 0);
911 CryptGetOIDFunctionAddress(set
, dwEncodingType
, lpszStoreProvider
, 0,
912 (void **)&provOpenFunc
, &hFunc
);
915 CERT_STORE_PROV_INFO provInfo
= { 0 };
917 provInfo
.cbSize
= sizeof(provInfo
);
918 if (dwFlags
& CERT_STORE_DELETE_FLAG
)
919 provOpenFunc(lpszStoreProvider
, dwEncodingType
, hCryptProv
,
920 dwFlags
, pvPara
, NULL
, &provInfo
);
925 memStore
= CertOpenStore(CERT_STORE_PROV_MEMORY
, 0, 0,
926 CERT_STORE_CREATE_NEW_FLAG
, NULL
);
929 if (provOpenFunc(lpszStoreProvider
, dwEncodingType
, hCryptProv
,
930 dwFlags
, pvPara
, memStore
, &provInfo
))
931 ret
= CRYPT_ProvCreateStore(hCryptProv
, dwFlags
, memStore
,
934 CertCloseStore(memStore
, 0);
937 CryptFreeOIDFunctionAddress(hFunc
, 0);
940 SetLastError(ERROR_FILE_NOT_FOUND
);
944 static void CRYPT_HashToStr(LPBYTE hash
, LPWSTR asciiHash
)
946 static const WCHAR fmt
[] = { '%','0','2','X',0 };
952 for (i
= 0; i
< 20; i
++)
953 wsprintfW(asciiHash
+ i
* 2, fmt
, hash
[i
]);
956 static const WCHAR CertsW
[] = { 'C','e','r','t','i','f','i','c','a','t','e','s',
958 static const WCHAR CRLsW
[] = { 'C','R','L','s',0 };
959 static const WCHAR CTLsW
[] = { 'C','T','L','s',0 };
960 static const WCHAR BlobW
[] = { 'B','l','o','b',0 };
962 static void CRYPT_RegReadSerializedFromReg(PWINE_REGSTOREINFO store
, HKEY key
,
967 WCHAR subKeyName
[MAX_PATH
];
970 DWORD size
= sizeof(subKeyName
) / sizeof(WCHAR
);
972 rc
= RegEnumKeyExW(key
, index
++, subKeyName
, &size
, NULL
, NULL
, NULL
,
978 rc
= RegOpenKeyExW(key
, subKeyName
, 0, KEY_READ
, &subKey
);
984 rc
= RegQueryValueExW(subKey
, BlobW
, NULL
, NULL
, NULL
, &size
);
986 buf
= CryptMemAlloc(size
);
989 rc
= RegQueryValueExW(subKey
, BlobW
, NULL
, NULL
, buf
,
996 TRACE("Adding cert with hash %s\n",
997 debugstr_w(subKeyName
));
998 context
= CRYPT_ReadSerializedElement(buf
, size
,
999 contextType
, &addedType
);
1002 const WINE_CONTEXT_INTERFACE
*contextInterface
;
1007 case CERT_STORE_CERTIFICATE_CONTEXT
:
1008 contextInterface
= &gCertInterface
;
1010 case CERT_STORE_CRL_CONTEXT
:
1011 contextInterface
= &gCRLInterface
;
1013 case CERT_STORE_CTL_CONTEXT
:
1014 contextInterface
= &gCTLInterface
;
1017 contextInterface
= NULL
;
1019 if (contextInterface
)
1021 size
= sizeof(hash
);
1022 if (contextInterface
->getProp(context
,
1023 CERT_HASH_PROP_ID
, hash
, &size
))
1025 WCHAR asciiHash
[20 * 2 + 1];
1027 CRYPT_HashToStr(hash
, asciiHash
);
1028 TRACE("comparing %s\n",
1029 debugstr_w(asciiHash
));
1030 TRACE("with %s\n", debugstr_w(subKeyName
));
1031 if (!lstrcmpW(asciiHash
, subKeyName
))
1033 TRACE("hash matches, adding\n");
1034 contextInterface
->addContextToStore(
1035 store
->memStore
, context
,
1036 CERT_STORE_ADD_REPLACE_EXISTING
, NULL
);
1039 TRACE("hash doesn't match, ignoring\n");
1041 contextInterface
->free(context
);
1047 RegCloseKey(subKey
);
1049 /* Ignore intermediate errors, continue enumerating */
1055 static void CRYPT_RegReadFromReg(PWINE_REGSTOREINFO store
)
1057 static const WCHAR
*subKeys
[] = { CertsW
, CRLsW
, CTLsW
};
1058 static const DWORD contextFlags
[] = { CERT_STORE_CERTIFICATE_CONTEXT_FLAG
,
1059 CERT_STORE_CRL_CONTEXT_FLAG
, CERT_STORE_CTL_CONTEXT_FLAG
};
1062 for (i
= 0; i
< sizeof(subKeys
) / sizeof(subKeys
[0]); i
++)
1067 rc
= RegCreateKeyExW(store
->key
, subKeys
[i
], 0, NULL
, 0, KEY_READ
, NULL
,
1071 CRYPT_RegReadSerializedFromReg(store
, key
, contextFlags
[i
]);
1077 /* Hash is assumed to be 20 bytes in length (a SHA-1 hash) */
1078 static BOOL
CRYPT_WriteSerializedToReg(HKEY key
, LPBYTE hash
, LPBYTE buf
,
1081 WCHAR asciiHash
[20 * 2 + 1];
1086 CRYPT_HashToStr(hash
, asciiHash
);
1087 rc
= RegCreateKeyExW(key
, asciiHash
, 0, NULL
, 0, KEY_ALL_ACCESS
, NULL
,
1091 rc
= RegSetValueExW(subKey
, BlobW
, 0, REG_BINARY
, buf
, len
);
1092 RegCloseKey(subKey
);
1104 static BOOL
CRYPT_SerializeContextsToReg(HKEY key
,
1105 const WINE_CONTEXT_INTERFACE
*contextInterface
, HCERTSTORE memStore
)
1107 const void *context
= NULL
;
1111 context
= contextInterface
->enumContextsInStore(memStore
, context
);
1115 DWORD hashSize
= sizeof(hash
);
1117 ret
= contextInterface
->getProp(context
, CERT_HASH_PROP_ID
, hash
,
1124 ret
= contextInterface
->serialize(context
, 0, NULL
, &size
);
1126 buf
= CryptMemAlloc(size
);
1129 ret
= contextInterface
->serialize(context
, 0, buf
, &size
);
1131 ret
= CRYPT_WriteSerializedToReg(key
, hash
, buf
, size
);
1138 } while (ret
&& context
!= NULL
);
1140 contextInterface
->free(context
);
1144 static BOOL
CRYPT_RegWriteToReg(PWINE_REGSTOREINFO store
)
1146 static const WCHAR
*subKeys
[] = { CertsW
, CRLsW
, CTLsW
};
1147 static const WINE_CONTEXT_INTERFACE
*interfaces
[] = { &gCertInterface
,
1148 &gCRLInterface
, &gCTLInterface
};
1149 struct list
*listToDelete
[] = { &store
->certsToDelete
, &store
->crlsToDelete
,
1154 for (i
= 0; ret
&& i
< sizeof(subKeys
) / sizeof(subKeys
[0]); i
++)
1157 LONG rc
= RegCreateKeyExW(store
->key
, subKeys
[i
], 0, NULL
, 0,
1158 KEY_ALL_ACCESS
, NULL
, &key
, NULL
);
1162 if (listToDelete
[i
])
1164 PWINE_HASH_TO_DELETE toDelete
, next
;
1165 WCHAR asciiHash
[20 * 2 + 1];
1167 EnterCriticalSection(&store
->cs
);
1168 LIST_FOR_EACH_ENTRY_SAFE(toDelete
, next
, listToDelete
[i
],
1169 WINE_HASH_TO_DELETE
, entry
)
1173 CRYPT_HashToStr(toDelete
->hash
, asciiHash
);
1174 TRACE("Removing %s\n", debugstr_w(asciiHash
));
1175 rc
= RegDeleteKeyW(key
, asciiHash
);
1176 if (rc
!= ERROR_SUCCESS
&& rc
!= ERROR_FILE_NOT_FOUND
)
1181 list_remove(&toDelete
->entry
);
1182 CryptMemFree(toDelete
);
1184 LeaveCriticalSection(&store
->cs
);
1186 ret
= CRYPT_SerializeContextsToReg(key
, interfaces
[i
],
1199 /* If force is true or the registry store is dirty, writes the contents of the
1200 * store to the registry.
1202 static BOOL
CRYPT_RegFlushStore(PWINE_REGSTOREINFO store
, BOOL force
)
1206 TRACE("(%p, %d)\n", store
, force
);
1208 if (store
->dirty
|| force
)
1209 ret
= CRYPT_RegWriteToReg(store
);
1215 static void WINAPI
CRYPT_RegCloseStore(HCERTSTORE hCertStore
, DWORD dwFlags
)
1217 PWINE_REGSTOREINFO store
= (PWINE_REGSTOREINFO
)hCertStore
;
1219 TRACE("(%p, %08lx)\n", store
, dwFlags
);
1221 FIXME("Unimplemented flags: %08lx\n", dwFlags
);
1223 CRYPT_RegFlushStore(store
, FALSE
);
1224 RegCloseKey(store
->key
);
1225 DeleteCriticalSection(&store
->cs
);
1226 CryptMemFree(store
);
1229 static BOOL WINAPI
CRYPT_RegWriteContext(PWINE_REGSTOREINFO store
,
1230 const void *context
, DWORD dwFlags
)
1234 if (dwFlags
& CERT_STORE_PROV_WRITE_ADD_FLAG
)
1236 store
->dirty
= TRUE
;
1244 static BOOL
CRYPT_RegDeleteContext(PWINE_REGSTOREINFO store
,
1245 struct list
*deleteList
, const void *context
,
1246 PCWINE_CONTEXT_INTERFACE contextInterface
)
1250 if (store
->dwOpenFlags
& CERT_STORE_READONLY_FLAG
)
1252 SetLastError(ERROR_ACCESS_DENIED
);
1257 PWINE_HASH_TO_DELETE toDelete
=
1258 CryptMemAlloc(sizeof(WINE_HASH_TO_DELETE
));
1262 DWORD size
= sizeof(toDelete
->hash
);
1264 ret
= contextInterface
->getProp(context
, CERT_HASH_PROP_ID
,
1265 toDelete
->hash
, &size
);
1268 EnterCriticalSection(&store
->cs
);
1269 list_add_tail(deleteList
, &toDelete
->entry
);
1270 LeaveCriticalSection(&store
->cs
);
1274 CryptMemFree(toDelete
);
1281 store
->dirty
= TRUE
;
1286 static BOOL WINAPI
CRYPT_RegWriteCert(HCERTSTORE hCertStore
,
1287 PCCERT_CONTEXT cert
, DWORD dwFlags
)
1289 PWINE_REGSTOREINFO store
= (PWINE_REGSTOREINFO
)hCertStore
;
1291 TRACE("(%p, %p, %ld)\n", hCertStore
, cert
, dwFlags
);
1293 return CRYPT_RegWriteContext(store
, cert
, dwFlags
);
1296 static BOOL WINAPI
CRYPT_RegDeleteCert(HCERTSTORE hCertStore
,
1297 PCCERT_CONTEXT pCertContext
, DWORD dwFlags
)
1299 PWINE_REGSTOREINFO store
= (PWINE_REGSTOREINFO
)hCertStore
;
1301 TRACE("(%p, %p, %08lx)\n", store
, pCertContext
, dwFlags
);
1303 return CRYPT_RegDeleteContext(store
, &store
->certsToDelete
, pCertContext
,
1307 static BOOL WINAPI
CRYPT_RegWriteCRL(HCERTSTORE hCertStore
,
1308 PCCRL_CONTEXT crl
, DWORD dwFlags
)
1310 PWINE_REGSTOREINFO store
= (PWINE_REGSTOREINFO
)hCertStore
;
1312 TRACE("(%p, %p, %ld)\n", hCertStore
, crl
, dwFlags
);
1314 return CRYPT_RegWriteContext(store
, crl
, dwFlags
);
1317 static BOOL WINAPI
CRYPT_RegDeleteCRL(HCERTSTORE hCertStore
,
1318 PCCRL_CONTEXT pCrlContext
, DWORD dwFlags
)
1320 PWINE_REGSTOREINFO store
= (PWINE_REGSTOREINFO
)hCertStore
;
1322 TRACE("(%p, %p, %08lx)\n", store
, pCrlContext
, dwFlags
);
1324 return CRYPT_RegDeleteContext(store
, &store
->crlsToDelete
, pCrlContext
,
1328 static BOOL WINAPI
CRYPT_RegControl(HCERTSTORE hCertStore
, DWORD dwFlags
,
1329 DWORD dwCtrlType
, void const *pvCtrlPara
)
1331 PWINE_REGSTOREINFO store
= (PWINE_REGSTOREINFO
)hCertStore
;
1334 TRACE("(%p, %08lx, %ld, %p)\n", hCertStore
, dwFlags
, dwCtrlType
,
1339 case CERT_STORE_CTRL_RESYNC
:
1340 CRYPT_RegFlushStore(store
, FALSE
);
1341 CRYPT_MemEmptyStore((PWINE_MEMSTORE
)store
->memStore
);
1342 CRYPT_RegReadFromReg(store
);
1345 case CERT_STORE_CTRL_COMMIT
:
1346 ret
= CRYPT_RegFlushStore(store
,
1347 dwFlags
& CERT_STORE_CTRL_COMMIT_FORCE_FLAG
);
1350 FIXME("%ld: stub\n", dwCtrlType
);
1356 /* Copied from shlwapi's SHDeleteKeyW, and reformatted to match this file. */
1357 static DWORD
CRYPT_RecurseDeleteKey(HKEY hKey
, LPCWSTR lpszSubKey
)
1359 DWORD dwRet
, dwKeyCount
= 0, dwMaxSubkeyLen
= 0, dwSize
, i
;
1360 WCHAR szNameBuf
[MAX_PATH
], *lpszName
= szNameBuf
;
1363 TRACE("(hkey=%p,%s)\n", hKey
, debugstr_w(lpszSubKey
));
1365 dwRet
= RegOpenKeyExW(hKey
, lpszSubKey
, 0, KEY_READ
, &hSubKey
);
1368 /* Find how many subkeys there are */
1369 dwRet
= RegQueryInfoKeyW(hSubKey
, NULL
, NULL
, NULL
, &dwKeyCount
,
1370 &dwMaxSubkeyLen
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
1374 if (dwMaxSubkeyLen
> sizeof(szNameBuf
)/sizeof(WCHAR
))
1376 /* Name too big: alloc a buffer for it */
1377 lpszName
= CryptMemAlloc(dwMaxSubkeyLen
*sizeof(WCHAR
));
1381 dwRet
= ERROR_NOT_ENOUGH_MEMORY
;
1384 /* Recursively delete all the subkeys */
1385 for (i
= 0; i
< dwKeyCount
&& !dwRet
; i
++)
1387 dwSize
= dwMaxSubkeyLen
;
1388 dwRet
= RegEnumKeyExW(hSubKey
, i
, lpszName
, &dwSize
, NULL
,
1391 dwRet
= CRYPT_RecurseDeleteKey(hSubKey
, lpszName
);
1394 if (lpszName
!= szNameBuf
)
1396 /* Free buffer if allocated */
1397 CryptMemFree(lpszName
);
1402 RegCloseKey(hSubKey
);
1404 dwRet
= RegDeleteKeyW(hKey
, lpszSubKey
);
1409 static void *regProvFuncs
[] = {
1410 CRYPT_RegCloseStore
,
1411 NULL
, /* CERT_STORE_PROV_READ_CERT_FUNC */
1413 CRYPT_RegDeleteCert
,
1414 NULL
, /* CERT_STORE_PROV_SET_CERT_PROPERTY_FUNC */
1415 NULL
, /* CERT_STORE_PROV_READ_CRL_FUNC */
1418 NULL
, /* CERT_STORE_PROV_SET_CRL_PROPERTY_FUNC */
1419 NULL
, /* CERT_STORE_PROV_READ_CTL_FUNC */
1420 NULL
, /* CERT_STORE_PROV_WRITE_CTL_FUNC */
1421 NULL
, /* CERT_STORE_PROV_DELETE_CTL_FUNC */
1422 NULL
, /* CERT_STORE_PROV_SET_CTL_PROPERTY_FUNC */
1426 static WINECRYPT_CERTSTORE
*CRYPT_RegOpenStore(HCRYPTPROV hCryptProv
,
1427 DWORD dwFlags
, const void *pvPara
)
1429 PWINECRYPT_CERTSTORE store
= NULL
;
1431 TRACE("(%ld, %08lx, %p)\n", hCryptProv
, dwFlags
, pvPara
);
1433 if (dwFlags
& CERT_STORE_DELETE_FLAG
)
1435 DWORD rc
= CRYPT_RecurseDeleteKey((HKEY
)pvPara
, CertsW
);
1437 if (rc
== ERROR_SUCCESS
|| rc
== ERROR_NO_MORE_ITEMS
)
1438 rc
= CRYPT_RecurseDeleteKey((HKEY
)pvPara
, CRLsW
);
1439 if (rc
== ERROR_SUCCESS
|| rc
== ERROR_NO_MORE_ITEMS
)
1440 rc
= CRYPT_RecurseDeleteKey((HKEY
)pvPara
, CTLsW
);
1441 if (rc
== ERROR_NO_MORE_ITEMS
)
1449 if (DuplicateHandle(GetCurrentProcess(), (HANDLE
)pvPara
,
1450 GetCurrentProcess(), (LPHANDLE
)&key
,
1451 dwFlags
& CERT_STORE_READONLY_FLAG
? KEY_READ
: KEY_ALL_ACCESS
,
1454 PWINECRYPT_CERTSTORE memStore
;
1456 memStore
= CRYPT_MemOpenStore(hCryptProv
, dwFlags
, NULL
);
1459 PWINE_REGSTOREINFO regInfo
= CryptMemAlloc(
1460 sizeof(WINE_REGSTOREINFO
));
1464 CERT_STORE_PROV_INFO provInfo
= { 0 };
1466 regInfo
->dwOpenFlags
= dwFlags
;
1467 regInfo
->cryptProv
= hCryptProv
;
1468 regInfo
->memStore
= memStore
;
1470 InitializeCriticalSection(®Info
->cs
);
1471 list_init(®Info
->certsToDelete
);
1472 list_init(®Info
->crlsToDelete
);
1473 CRYPT_RegReadFromReg(regInfo
);
1474 regInfo
->dirty
= FALSE
;
1475 provInfo
.cbSize
= sizeof(provInfo
);
1476 provInfo
.cStoreProvFunc
= sizeof(regProvFuncs
) /
1477 sizeof(regProvFuncs
[0]);
1478 provInfo
.rgpvStoreProvFunc
= regProvFuncs
;
1479 provInfo
.hStoreProv
= regInfo
;
1480 store
= CRYPT_ProvCreateStore(hCryptProv
, dwFlags
, memStore
,
1486 TRACE("returning %p\n", store
);
1490 /* FIXME: this isn't complete for the Root store, in which the top-level
1491 * self-signed CA certs reside. Adding a cert to the Root store should present
1492 * the user with a dialog indicating the consequences of doing so, and asking
1493 * the user to confirm whether the cert should be added.
1495 static PWINECRYPT_CERTSTORE
CRYPT_SysRegOpenStoreW(HCRYPTPROV hCryptProv
,
1496 DWORD dwFlags
, const void *pvPara
)
1498 static const WCHAR fmt
[] = { '%','s','\\','%','s',0 };
1499 LPCWSTR storeName
= (LPCWSTR
)pvPara
;
1501 PWINECRYPT_CERTSTORE store
= NULL
;
1506 TRACE("(%ld, %08lx, %s)\n", hCryptProv
, dwFlags
,
1507 debugstr_w((LPCWSTR
)pvPara
));
1511 SetLastError(E_INVALIDARG
);
1516 switch (dwFlags
& CERT_SYSTEM_STORE_LOCATION_MASK
)
1518 case CERT_SYSTEM_STORE_LOCAL_MACHINE
:
1519 root
= HKEY_LOCAL_MACHINE
;
1520 base
= CERT_LOCAL_MACHINE_SYSTEM_STORE_REGPATH
;
1522 case CERT_SYSTEM_STORE_CURRENT_USER
:
1523 root
= HKEY_CURRENT_USER
;
1524 base
= CERT_LOCAL_MACHINE_SYSTEM_STORE_REGPATH
;
1526 case CERT_SYSTEM_STORE_CURRENT_SERVICE
:
1527 /* hklm\Software\Microsoft\Cryptography\Services\servicename\
1528 * SystemCertificates
1530 FIXME("CERT_SYSTEM_STORE_CURRENT_SERVICE, %s: stub\n",
1531 debugstr_w(storeName
));
1533 case CERT_SYSTEM_STORE_SERVICES
:
1534 /* hklm\Software\Microsoft\Cryptography\Services\servicename\
1535 * SystemCertificates
1537 FIXME("CERT_SYSTEM_STORE_SERVICES, %s: stub\n",
1538 debugstr_w(storeName
));
1540 case CERT_SYSTEM_STORE_USERS
:
1541 /* hku\user sid\Software\Microsoft\SystemCertificates */
1542 FIXME("CERT_SYSTEM_STORE_USERS, %s: stub\n",
1543 debugstr_w(storeName
));
1545 case CERT_SYSTEM_STORE_CURRENT_USER_GROUP_POLICY
:
1546 root
= HKEY_CURRENT_USER
;
1547 base
= CERT_GROUP_POLICY_SYSTEM_STORE_REGPATH
;
1549 case CERT_SYSTEM_STORE_LOCAL_MACHINE_GROUP_POLICY
:
1550 root
= HKEY_LOCAL_MACHINE
;
1551 base
= CERT_GROUP_POLICY_SYSTEM_STORE_REGPATH
;
1553 case CERT_SYSTEM_STORE_LOCAL_MACHINE_ENTERPRISE
:
1554 /* hklm\Software\Microsoft\EnterpriseCertificates */
1555 FIXME("CERT_SYSTEM_STORE_LOCAL_MACHINE_ENTERPRISE, %s: stub\n",
1556 debugstr_w(storeName
));
1559 SetLastError(E_INVALIDARG
);
1563 storePath
= CryptMemAlloc((lstrlenW(base
) + lstrlenW(storeName
) + 2) *
1569 REGSAM sam
= dwFlags
& CERT_STORE_READONLY_FLAG
? KEY_READ
:
1572 wsprintfW(storePath
, fmt
, base
, storeName
);
1573 if (dwFlags
& CERT_STORE_OPEN_EXISTING_FLAG
)
1574 rc
= RegOpenKeyExW(root
, storePath
, 0, sam
, &key
);
1579 rc
= RegCreateKeyExW(root
, storePath
, 0, NULL
, 0, sam
, NULL
,
1581 if (!rc
&& dwFlags
& CERT_STORE_CREATE_NEW_FLAG
&&
1582 disp
== REG_OPENED_EXISTING_KEY
)
1585 rc
= ERROR_FILE_EXISTS
;
1590 store
= CRYPT_RegOpenStore(hCryptProv
, dwFlags
, key
);
1595 CryptMemFree(storePath
);
1600 static PWINECRYPT_CERTSTORE
CRYPT_SysRegOpenStoreA(HCRYPTPROV hCryptProv
,
1601 DWORD dwFlags
, const void *pvPara
)
1604 PWINECRYPT_CERTSTORE ret
= NULL
;
1606 TRACE("(%ld, %08lx, %s)\n", hCryptProv
, dwFlags
,
1607 debugstr_a((LPCSTR
)pvPara
));
1611 SetLastError(ERROR_FILE_NOT_FOUND
);
1614 len
= MultiByteToWideChar(CP_ACP
, 0, (LPCSTR
)pvPara
, -1, NULL
, 0);
1617 LPWSTR storeName
= CryptMemAlloc(len
* sizeof(WCHAR
));
1621 MultiByteToWideChar(CP_ACP
, 0, (LPCSTR
)pvPara
, -1, storeName
, len
);
1622 ret
= CRYPT_SysRegOpenStoreW(hCryptProv
, dwFlags
, storeName
);
1623 CryptMemFree(storeName
);
1629 static PWINECRYPT_CERTSTORE
CRYPT_SysOpenStoreW(HCRYPTPROV hCryptProv
,
1630 DWORD dwFlags
, const void *pvPara
)
1632 HCERTSTORE store
= 0;
1635 TRACE("(%ld, %08lx, %s)\n", hCryptProv
, dwFlags
,
1636 debugstr_w((LPCWSTR
)pvPara
));
1640 SetLastError(ERROR_FILE_NOT_FOUND
);
1643 /* This returns a different error than system registry stores if the
1644 * location is invalid.
1646 switch (dwFlags
& CERT_SYSTEM_STORE_LOCATION_MASK
)
1648 case CERT_SYSTEM_STORE_LOCAL_MACHINE
:
1649 case CERT_SYSTEM_STORE_CURRENT_USER
:
1650 case CERT_SYSTEM_STORE_CURRENT_SERVICE
:
1651 case CERT_SYSTEM_STORE_SERVICES
:
1652 case CERT_SYSTEM_STORE_USERS
:
1653 case CERT_SYSTEM_STORE_CURRENT_USER_GROUP_POLICY
:
1654 case CERT_SYSTEM_STORE_LOCAL_MACHINE_GROUP_POLICY
:
1655 case CERT_SYSTEM_STORE_LOCAL_MACHINE_ENTERPRISE
:
1659 SetLastError(ERROR_FILE_NOT_FOUND
);
1664 HCERTSTORE regStore
= CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY_W
,
1665 0, hCryptProv
, dwFlags
, pvPara
);
1669 store
= CertOpenStore(CERT_STORE_PROV_COLLECTION
, 0, 0,
1670 CERT_STORE_CREATE_NEW_FLAG
, NULL
);
1671 CertAddStoreToCollection(store
, regStore
,
1672 dwFlags
& CERT_STORE_READONLY_FLAG
? 0 :
1673 CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG
, 0);
1674 CertCloseStore(regStore
, 0);
1675 /* CERT_SYSTEM_STORE_CURRENT_USER returns both the HKCU and HKLM
1678 if ((dwFlags
& CERT_SYSTEM_STORE_LOCATION_MASK
) ==
1679 CERT_SYSTEM_STORE_CURRENT_USER
)
1681 dwFlags
&= ~CERT_SYSTEM_STORE_CURRENT_USER
;
1682 dwFlags
|= CERT_SYSTEM_STORE_LOCAL_MACHINE
;
1683 regStore
= CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY_W
, 0,
1684 hCryptProv
, dwFlags
, pvPara
);
1687 CertAddStoreToCollection(store
, regStore
,
1688 dwFlags
& CERT_STORE_READONLY_FLAG
? 0 :
1689 CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG
, 0);
1690 CertCloseStore(regStore
, 0);
1695 return (PWINECRYPT_CERTSTORE
)store
;
1698 static PWINECRYPT_CERTSTORE
CRYPT_SysOpenStoreA(HCRYPTPROV hCryptProv
,
1699 DWORD dwFlags
, const void *pvPara
)
1702 PWINECRYPT_CERTSTORE ret
= NULL
;
1704 TRACE("(%ld, %08lx, %s)\n", hCryptProv
, dwFlags
,
1705 debugstr_a((LPCSTR
)pvPara
));
1709 SetLastError(ERROR_FILE_NOT_FOUND
);
1712 len
= MultiByteToWideChar(CP_ACP
, 0, (LPCSTR
)pvPara
, -1, NULL
, 0);
1715 LPWSTR storeName
= CryptMemAlloc(len
* sizeof(WCHAR
));
1719 MultiByteToWideChar(CP_ACP
, 0, (LPCSTR
)pvPara
, -1, storeName
, len
);
1720 ret
= CRYPT_SysOpenStoreW(hCryptProv
, dwFlags
, storeName
);
1721 CryptMemFree(storeName
);
1727 static void WINAPI
CRYPT_FileCloseStore(HCERTSTORE hCertStore
, DWORD dwFlags
)
1729 PWINE_FILESTOREINFO store
= (PWINE_FILESTOREINFO
)hCertStore
;
1731 TRACE("(%p, %08lx)\n", store
, dwFlags
);
1733 CRYPT_WriteSerializedFile(store
->file
, store
->memStore
);
1734 CertCloseStore(store
->memStore
, dwFlags
);
1735 CloseHandle(store
->file
);
1736 CryptMemFree(store
);
1739 static BOOL WINAPI
CRYPT_FileWriteCert(HCERTSTORE hCertStore
,
1740 PCCERT_CONTEXT cert
, DWORD dwFlags
)
1742 PWINE_FILESTOREINFO store
= (PWINE_FILESTOREINFO
)hCertStore
;
1744 TRACE("(%p, %p, %ld)\n", hCertStore
, cert
, dwFlags
);
1745 store
->dirty
= TRUE
;
1749 static BOOL WINAPI
CRYPT_FileDeleteCert(HCERTSTORE hCertStore
,
1750 PCCERT_CONTEXT pCertContext
, DWORD dwFlags
)
1752 PWINE_FILESTOREINFO store
= (PWINE_FILESTOREINFO
)hCertStore
;
1754 TRACE("(%p, %p, %08lx)\n", hCertStore
, pCertContext
, dwFlags
);
1755 store
->dirty
= TRUE
;
1759 static BOOL WINAPI
CRYPT_FileWriteCRL(HCERTSTORE hCertStore
,
1760 PCCRL_CONTEXT crl
, DWORD dwFlags
)
1762 PWINE_FILESTOREINFO store
= (PWINE_FILESTOREINFO
)hCertStore
;
1764 TRACE("(%p, %p, %ld)\n", hCertStore
, crl
, dwFlags
);
1765 store
->dirty
= TRUE
;
1769 static BOOL WINAPI
CRYPT_FileDeleteCRL(HCERTSTORE hCertStore
,
1770 PCCRL_CONTEXT pCrlContext
, DWORD dwFlags
)
1772 PWINE_FILESTOREINFO store
= (PWINE_FILESTOREINFO
)hCertStore
;
1774 TRACE("(%p, %p, %08lx)\n", hCertStore
, pCrlContext
, dwFlags
);
1775 store
->dirty
= TRUE
;
1779 static BOOL WINAPI
CRYPT_FileControl(HCERTSTORE hCertStore
, DWORD dwFlags
,
1780 DWORD dwCtrlType
, void const *pvCtrlPara
)
1782 PWINE_FILESTOREINFO store
= (PWINE_FILESTOREINFO
)hCertStore
;
1785 TRACE("(%p, %08lx, %ld, %p)\n", hCertStore
, dwFlags
, dwCtrlType
,
1790 case CERT_STORE_CTRL_RESYNC
:
1791 CRYPT_MemEmptyStore((PWINE_MEMSTORE
)store
->memStore
);
1792 CRYPT_ReadSerializedFile(store
->file
, store
);
1795 case CERT_STORE_CTRL_COMMIT
:
1796 if (!(store
->dwOpenFlags
& CERT_FILE_STORE_COMMIT_ENABLE_FLAG
))
1798 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
1801 else if (store
->dirty
)
1802 ret
= CRYPT_WriteSerializedFile(store
->file
, store
->memStore
);
1807 FIXME("%ld: stub\n", dwCtrlType
);
1813 static void *fileProvFuncs
[] = {
1814 CRYPT_FileCloseStore
,
1815 NULL
, /* CERT_STORE_PROV_READ_CERT_FUNC */
1816 CRYPT_FileWriteCert
,
1817 CRYPT_FileDeleteCert
,
1818 NULL
, /* CERT_STORE_PROV_SET_CERT_PROPERTY_FUNC */
1819 NULL
, /* CERT_STORE_PROV_READ_CRL_FUNC */
1821 CRYPT_FileDeleteCRL
,
1822 NULL
, /* CERT_STORE_PROV_SET_CRL_PROPERTY_FUNC */
1823 NULL
, /* CERT_STORE_PROV_READ_CTL_FUNC */
1824 NULL
, /* CERT_STORE_PROV_WRITE_CTL_FUNC */
1825 NULL
, /* CERT_STORE_PROV_DELETE_CTL_FUNC */
1826 NULL
, /* CERT_STORE_PROV_SET_CTL_PROPERTY_FUNC */
1830 static PWINECRYPT_CERTSTORE
CRYPT_FileOpenStore(HCRYPTPROV hCryptProv
,
1831 DWORD dwFlags
, const void *pvPara
)
1833 PWINECRYPT_CERTSTORE store
= NULL
;
1834 HANDLE file
= (HANDLE
)pvPara
;
1836 TRACE("(%ld, %08lx, %p)\n", hCryptProv
, dwFlags
, pvPara
);
1840 SetLastError(ERROR_INVALID_HANDLE
);
1843 if (dwFlags
& CERT_STORE_DELETE_FLAG
)
1845 SetLastError(E_INVALIDARG
);
1848 if ((dwFlags
& CERT_STORE_READONLY_FLAG
) &&
1849 (dwFlags
& CERT_FILE_STORE_COMMIT_ENABLE_FLAG
))
1851 SetLastError(E_INVALIDARG
);
1855 if (DuplicateHandle(GetCurrentProcess(), (HANDLE
)pvPara
,
1856 GetCurrentProcess(), &file
, dwFlags
& CERT_STORE_READONLY_FLAG
?
1857 GENERIC_READ
: GENERIC_READ
| GENERIC_WRITE
, TRUE
, 0))
1859 PWINECRYPT_CERTSTORE memStore
;
1861 memStore
= CRYPT_MemOpenStore(hCryptProv
, dwFlags
, NULL
);
1864 if (CRYPT_ReadSerializedFile(file
, memStore
))
1866 PWINE_FILESTOREINFO info
= CryptMemAlloc(
1867 sizeof(WINE_FILESTOREINFO
));
1871 CERT_STORE_PROV_INFO provInfo
= { 0 };
1873 info
->dwOpenFlags
= dwFlags
;
1874 info
->cryptProv
= hCryptProv
;
1875 info
->memStore
= memStore
;
1877 info
->dirty
= FALSE
;
1878 provInfo
.cbSize
= sizeof(provInfo
);
1879 provInfo
.cStoreProvFunc
= sizeof(fileProvFuncs
) /
1880 sizeof(fileProvFuncs
[0]);
1881 provInfo
.rgpvStoreProvFunc
= fileProvFuncs
;
1882 provInfo
.hStoreProv
= info
;
1883 store
= CRYPT_ProvCreateStore(hCryptProv
, dwFlags
, memStore
,
1889 TRACE("returning %p\n", store
);
1893 static PWINECRYPT_CERTSTORE
CRYPT_FileNameOpenStoreW(HCRYPTPROV hCryptProv
,
1894 DWORD dwFlags
, const void *pvPara
)
1896 HCERTSTORE store
= 0;
1897 LPCWSTR fileName
= (LPCWSTR
)pvPara
;
1898 DWORD access
, create
;
1901 TRACE("(%ld, %08lx, %s)\n", hCryptProv
, dwFlags
, debugstr_w(fileName
));
1905 SetLastError(ERROR_PATH_NOT_FOUND
);
1908 if (!(dwFlags
& (CERT_FILE_STORE_COMMIT_ENABLE_FLAG
|
1909 CERT_STORE_READONLY_FLAG
)))
1911 SetLastError(ERROR_FILE_NOT_FOUND
);
1915 access
= GENERIC_READ
;
1916 if (dwFlags
& CERT_FILE_STORE_COMMIT_ENABLE_FLAG
)
1917 access
|= GENERIC_WRITE
;
1918 if (dwFlags
& CERT_STORE_CREATE_NEW_FLAG
)
1919 create
= CREATE_NEW
;
1920 else if (dwFlags
& CERT_STORE_OPEN_EXISTING_FLAG
)
1921 create
= OPEN_EXISTING
;
1923 create
= OPEN_ALWAYS
;
1924 file
= CreateFileW(fileName
, access
, FILE_SHARE_READ
, NULL
, create
,
1925 FILE_ATTRIBUTE_NORMAL
, NULL
);
1926 if (file
!= INVALID_HANDLE_VALUE
)
1928 /* FIXME: need to check whether it's a serialized store; if not, fall
1929 * back to a PKCS#7 signed message, then to a single serialized cert.
1931 store
= CertOpenStore(CERT_STORE_PROV_FILE
, 0, hCryptProv
, dwFlags
,
1935 return (PWINECRYPT_CERTSTORE
)store
;
1938 static PWINECRYPT_CERTSTORE
CRYPT_FileNameOpenStoreA(HCRYPTPROV hCryptProv
,
1939 DWORD dwFlags
, const void *pvPara
)
1942 PWINECRYPT_CERTSTORE ret
= NULL
;
1944 TRACE("(%ld, %08lx, %s)\n", hCryptProv
, dwFlags
,
1945 debugstr_a((LPCSTR
)pvPara
));
1949 SetLastError(ERROR_FILE_NOT_FOUND
);
1952 len
= MultiByteToWideChar(CP_ACP
, 0, (LPCSTR
)pvPara
, -1, NULL
, 0);
1955 LPWSTR storeName
= CryptMemAlloc(len
* sizeof(WCHAR
));
1959 MultiByteToWideChar(CP_ACP
, 0, (LPCSTR
)pvPara
, -1, storeName
, len
);
1960 ret
= CRYPT_FileNameOpenStoreW(hCryptProv
, dwFlags
, storeName
);
1961 CryptMemFree(storeName
);
1967 static PWINECRYPT_CERTSTORE
CRYPT_PhysOpenStoreW(HCRYPTPROV hCryptProv
,
1968 DWORD dwFlags
, const void *pvPara
)
1970 if (dwFlags
& CERT_SYSTEM_STORE_RELOCATE_FLAG
)
1971 FIXME("(%ld, %08lx, %p): stub\n", hCryptProv
, dwFlags
, pvPara
);
1973 FIXME("(%ld, %08lx, %s): stub\n", hCryptProv
, dwFlags
,
1974 debugstr_w((LPCWSTR
)pvPara
));
1978 HCERTSTORE WINAPI
CertOpenStore(LPCSTR lpszStoreProvider
,
1979 DWORD dwMsgAndCertEncodingType
, HCRYPTPROV hCryptProv
, DWORD dwFlags
,
1982 WINECRYPT_CERTSTORE
*hcs
;
1983 StoreOpenFunc openFunc
= NULL
;
1985 TRACE("(%s, %08lx, %08lx, %08lx, %p)\n", debugstr_a(lpszStoreProvider
),
1986 dwMsgAndCertEncodingType
, hCryptProv
, dwFlags
, pvPara
);
1988 if (!HIWORD(lpszStoreProvider
))
1990 switch (LOWORD(lpszStoreProvider
))
1992 case (int)CERT_STORE_PROV_MEMORY
:
1993 openFunc
= CRYPT_MemOpenStore
;
1995 case (int)CERT_STORE_PROV_FILE
:
1996 openFunc
= CRYPT_FileOpenStore
;
1998 case (int)CERT_STORE_PROV_REG
:
1999 openFunc
= CRYPT_RegOpenStore
;
2001 case (int)CERT_STORE_PROV_FILENAME_A
:
2002 openFunc
= CRYPT_FileNameOpenStoreA
;
2004 case (int)CERT_STORE_PROV_FILENAME_W
:
2005 openFunc
= CRYPT_FileNameOpenStoreW
;
2007 case (int)CERT_STORE_PROV_COLLECTION
:
2008 openFunc
= CRYPT_CollectionOpenStore
;
2010 case (int)CERT_STORE_PROV_SYSTEM_A
:
2011 openFunc
= CRYPT_SysOpenStoreA
;
2013 case (int)CERT_STORE_PROV_SYSTEM_W
:
2014 openFunc
= CRYPT_SysOpenStoreW
;
2016 case (int)CERT_STORE_PROV_SYSTEM_REGISTRY_A
:
2017 openFunc
= CRYPT_SysRegOpenStoreA
;
2019 case (int)CERT_STORE_PROV_SYSTEM_REGISTRY_W
:
2020 openFunc
= CRYPT_SysRegOpenStoreW
;
2022 case (int)CERT_STORE_PROV_PHYSICAL_W
:
2023 openFunc
= CRYPT_PhysOpenStoreW
;
2026 if (LOWORD(lpszStoreProvider
))
2027 FIXME("unimplemented type %d\n", LOWORD(lpszStoreProvider
));
2030 else if (!strcasecmp(lpszStoreProvider
, sz_CERT_STORE_PROV_MEMORY
))
2031 openFunc
= CRYPT_MemOpenStore
;
2032 else if (!strcasecmp(lpszStoreProvider
, sz_CERT_STORE_PROV_FILENAME_W
))
2033 openFunc
= CRYPT_FileOpenStore
;
2034 else if (!strcasecmp(lpszStoreProvider
, sz_CERT_STORE_PROV_SYSTEM
))
2035 openFunc
= CRYPT_SysOpenStoreW
;
2036 else if (!strcasecmp(lpszStoreProvider
, sz_CERT_STORE_PROV_COLLECTION
))
2037 openFunc
= CRYPT_CollectionOpenStore
;
2038 else if (!strcasecmp(lpszStoreProvider
, sz_CERT_STORE_PROV_SYSTEM_REGISTRY
))
2039 openFunc
= CRYPT_SysRegOpenStoreW
;
2042 FIXME("unimplemented type %s\n", lpszStoreProvider
);
2047 hcs
= CRYPT_ProvOpenStore(lpszStoreProvider
, dwMsgAndCertEncodingType
,
2048 hCryptProv
, dwFlags
, pvPara
);
2050 hcs
= openFunc(hCryptProv
, dwFlags
, pvPara
);
2051 return (HCERTSTORE
)hcs
;
2054 HCERTSTORE WINAPI
CertOpenSystemStoreA(HCRYPTPROV hProv
,
2055 LPCSTR szSubSystemProtocol
)
2057 if (!szSubSystemProtocol
)
2059 SetLastError(E_INVALIDARG
);
2062 return CertOpenStore(CERT_STORE_PROV_SYSTEM_A
, 0, hProv
,
2063 CERT_SYSTEM_STORE_CURRENT_USER
, szSubSystemProtocol
);
2066 HCERTSTORE WINAPI
CertOpenSystemStoreW(HCRYPTPROV hProv
,
2067 LPCWSTR szSubSystemProtocol
)
2069 if (!szSubSystemProtocol
)
2071 SetLastError(E_INVALIDARG
);
2074 return CertOpenStore(CERT_STORE_PROV_SYSTEM_W
, 0, hProv
,
2075 CERT_SYSTEM_STORE_CURRENT_USER
, szSubSystemProtocol
);
2078 BOOL WINAPI
CertSaveStore(HCERTSTORE hCertStore
, DWORD dwMsgAndCertEncodingType
,
2079 DWORD dwSaveAs
, DWORD dwSaveTo
, void* pvSaveToPara
, DWORD dwFlags
)
2081 FIXME("(%p,%ld,%ld,%ld,%p,%08lx) stub!\n", hCertStore
,
2082 dwMsgAndCertEncodingType
, dwSaveAs
, dwSaveTo
, pvSaveToPara
, dwFlags
);
2086 DWORD
CertStore_GetAccessState(HCERTSTORE hCertStore
)
2092 PWINECRYPT_CERTSTORE store
= (PWINECRYPT_CERTSTORE
)hCertStore
;
2094 if (store
->type
!= StoreTypeMem
&&
2095 !(store
->dwOpenFlags
& CERT_STORE_READONLY_FLAG
))
2096 state
|= CERT_ACCESS_STATE_WRITE_PERSIST_FLAG
;
2101 #define CertContext_CopyProperties(to, from) \
2102 Context_CopyProperties((to), (from), sizeof(CERT_CONTEXT))
2104 BOOL WINAPI
CertAddCertificateContextToStore(HCERTSTORE hCertStore
,
2105 PCCERT_CONTEXT pCertContext
, DWORD dwAddDisposition
,
2106 PCCERT_CONTEXT
*ppStoreContext
)
2108 PWINECRYPT_CERTSTORE store
= (PWINECRYPT_CERTSTORE
)hCertStore
;
2110 PCCERT_CONTEXT toAdd
= NULL
, existing
= NULL
;
2112 TRACE("(%p, %p, %08lx, %p)\n", hCertStore
, pCertContext
,
2113 dwAddDisposition
, ppStoreContext
);
2115 /* Weird case to pass a test */
2116 if (dwAddDisposition
== 0)
2118 SetLastError(STATUS_ACCESS_VIOLATION
);
2121 if (dwAddDisposition
!= CERT_STORE_ADD_ALWAYS
)
2124 DWORD size
= sizeof(hashToAdd
);
2126 ret
= CertGetCertificateContextProperty(pCertContext
, CERT_HASH_PROP_ID
,
2130 CRYPT_HASH_BLOB blob
= { sizeof(hashToAdd
), hashToAdd
};
2132 existing
= CertFindCertificateInStore(hCertStore
,
2133 pCertContext
->dwCertEncodingType
, 0, CERT_FIND_SHA1_HASH
, &blob
,
2138 switch (dwAddDisposition
)
2140 case CERT_STORE_ADD_ALWAYS
:
2141 toAdd
= CertDuplicateCertificateContext(pCertContext
);
2143 case CERT_STORE_ADD_NEW
:
2146 TRACE("found matching certificate, not adding\n");
2147 SetLastError(CRYPT_E_EXISTS
);
2151 toAdd
= CertDuplicateCertificateContext(pCertContext
);
2153 case CERT_STORE_ADD_REPLACE_EXISTING
:
2154 toAdd
= CertDuplicateCertificateContext(pCertContext
);
2156 case CERT_STORE_ADD_REPLACE_EXISTING_INHERIT_PROPERTIES
:
2157 toAdd
= CertDuplicateCertificateContext(pCertContext
);
2159 CertContext_CopyProperties(toAdd
, existing
);
2161 case CERT_STORE_ADD_USE_EXISTING
:
2163 CertContext_CopyProperties(existing
, pCertContext
);
2166 FIXME("Unimplemented add disposition %ld\n", dwAddDisposition
);
2173 ret
= store
->certs
.addContext(store
, (void *)toAdd
,
2174 (void *)existing
, (const void **)ppStoreContext
);
2175 else if (ppStoreContext
)
2176 *ppStoreContext
= CertDuplicateCertificateContext(toAdd
);
2177 CertFreeCertificateContext(toAdd
);
2179 CertFreeCertificateContext(existing
);
2181 TRACE("returning %d\n", ret
);
2185 PCCERT_CONTEXT WINAPI
CertEnumCertificatesInStore(HCERTSTORE hCertStore
,
2186 PCCERT_CONTEXT pPrev
)
2188 WINECRYPT_CERTSTORE
*hcs
= (WINECRYPT_CERTSTORE
*)hCertStore
;
2191 TRACE("(%p, %p)\n", hCertStore
, pPrev
);
2194 else if (hcs
->dwMagic
!= WINE_CRYPTCERTSTORE_MAGIC
)
2197 ret
= (PCCERT_CONTEXT
)hcs
->certs
.enumContext(hcs
, (void *)pPrev
);
2201 BOOL WINAPI
CertDeleteCertificateFromStore(PCCERT_CONTEXT pCertContext
)
2205 TRACE("(%p)\n", pCertContext
);
2209 else if (!pCertContext
->hCertStore
)
2212 CertFreeCertificateContext(pCertContext
);
2216 PWINECRYPT_CERTSTORE hcs
=
2217 (PWINECRYPT_CERTSTORE
)pCertContext
->hCertStore
;
2219 if (hcs
->dwMagic
!= WINE_CRYPTCERTSTORE_MAGIC
)
2222 ret
= hcs
->certs
.deleteContext(hcs
, (void *)pCertContext
);
2223 CertFreeCertificateContext(pCertContext
);
2228 #define CrlContext_CopyProperties(to, from) \
2229 Context_CopyProperties((to), (from), sizeof(CRL_CONTEXT))
2231 BOOL WINAPI
CertAddCRLContextToStore(HCERTSTORE hCertStore
,
2232 PCCRL_CONTEXT pCrlContext
, DWORD dwAddDisposition
,
2233 PCCRL_CONTEXT
* ppStoreContext
)
2235 PWINECRYPT_CERTSTORE store
= (PWINECRYPT_CERTSTORE
)hCertStore
;
2237 PCCRL_CONTEXT toAdd
= NULL
, existing
= NULL
;
2239 TRACE("(%p, %p, %08lx, %p)\n", hCertStore
, pCrlContext
,
2240 dwAddDisposition
, ppStoreContext
);
2242 /* Weird case to pass a test */
2243 if (dwAddDisposition
== 0)
2245 SetLastError(STATUS_ACCESS_VIOLATION
);
2248 if (dwAddDisposition
!= CERT_STORE_ADD_ALWAYS
)
2250 existing
= CertFindCRLInStore(hCertStore
, 0, 0, CRL_FIND_EXISTING
,
2254 switch (dwAddDisposition
)
2256 case CERT_STORE_ADD_ALWAYS
:
2257 toAdd
= CertDuplicateCRLContext(pCrlContext
);
2259 case CERT_STORE_ADD_NEW
:
2262 TRACE("found matching CRL, not adding\n");
2263 SetLastError(CRYPT_E_EXISTS
);
2267 toAdd
= CertDuplicateCRLContext(pCrlContext
);
2269 case CERT_STORE_ADD_NEWER
:
2272 LONG newer
= CompareFileTime(&existing
->pCrlInfo
->ThisUpdate
,
2273 &pCrlContext
->pCrlInfo
->ThisUpdate
);
2276 toAdd
= CertDuplicateCRLContext(pCrlContext
);
2279 TRACE("existing CRL is newer, not adding\n");
2280 SetLastError(CRYPT_E_EXISTS
);
2285 toAdd
= CertDuplicateCRLContext(pCrlContext
);
2287 case CERT_STORE_ADD_REPLACE_EXISTING
:
2288 toAdd
= CertDuplicateCRLContext(pCrlContext
);
2290 case CERT_STORE_ADD_REPLACE_EXISTING_INHERIT_PROPERTIES
:
2291 toAdd
= CertDuplicateCRLContext(pCrlContext
);
2293 CrlContext_CopyProperties(toAdd
, existing
);
2295 case CERT_STORE_ADD_USE_EXISTING
:
2297 CrlContext_CopyProperties(existing
, pCrlContext
);
2300 FIXME("Unimplemented add disposition %ld\n", dwAddDisposition
);
2307 ret
= store
->crls
.addContext(store
, (void *)toAdd
,
2308 (void *)existing
, (const void **)ppStoreContext
);
2309 else if (ppStoreContext
)
2310 *ppStoreContext
= CertDuplicateCRLContext(toAdd
);
2311 CertFreeCRLContext(toAdd
);
2313 CertFreeCRLContext(existing
);
2315 TRACE("returning %d\n", ret
);
2319 BOOL WINAPI
CertDeleteCRLFromStore(PCCRL_CONTEXT pCrlContext
)
2323 TRACE("(%p)\n", pCrlContext
);
2327 else if (!pCrlContext
->hCertStore
)
2330 CertFreeCRLContext(pCrlContext
);
2334 PWINECRYPT_CERTSTORE hcs
=
2335 (PWINECRYPT_CERTSTORE
)pCrlContext
->hCertStore
;
2337 if (hcs
->dwMagic
!= WINE_CRYPTCERTSTORE_MAGIC
)
2340 ret
= hcs
->crls
.deleteContext(hcs
, (void *)pCrlContext
);
2341 CertFreeCRLContext(pCrlContext
);
2346 PCCRL_CONTEXT WINAPI
CertEnumCRLsInStore(HCERTSTORE hCertStore
,
2347 PCCRL_CONTEXT pPrev
)
2349 WINECRYPT_CERTSTORE
*hcs
= (WINECRYPT_CERTSTORE
*)hCertStore
;
2352 TRACE("(%p, %p)\n", hCertStore
, pPrev
);
2355 else if (hcs
->dwMagic
!= WINE_CRYPTCERTSTORE_MAGIC
)
2358 ret
= (PCCRL_CONTEXT
)hcs
->crls
.enumContext(hcs
, (void *)pPrev
);
2362 PCCTL_CONTEXT WINAPI
CertCreateCTLContext(DWORD dwCertEncodingType
,
2363 const BYTE
* pbCtlEncoded
, DWORD cbCtlEncoded
)
2365 FIXME("(%08lx, %p, %08lx): stub\n", dwCertEncodingType
, pbCtlEncoded
,
2370 BOOL WINAPI
CertAddEncodedCTLToStore(HCERTSTORE hCertStore
,
2371 DWORD dwMsgAndCertEncodingType
, const BYTE
*pbCtlEncoded
, DWORD cbCtlEncoded
,
2372 DWORD dwAddDisposition
, PCCTL_CONTEXT
*ppCtlContext
)
2374 FIXME("(%p, %08lx, %p, %ld, %08lx, %p): stub\n", hCertStore
,
2375 dwMsgAndCertEncodingType
, pbCtlEncoded
, cbCtlEncoded
, dwAddDisposition
,
2380 BOOL WINAPI
CertAddCTLContextToStore(HCERTSTORE hCertStore
,
2381 PCCTL_CONTEXT pCtlContext
, DWORD dwAddDisposition
,
2382 PCCTL_CONTEXT
* ppStoreContext
)
2384 FIXME("(%p, %p, %08lx, %p): stub\n", hCertStore
, pCtlContext
,
2385 dwAddDisposition
, ppStoreContext
);
2389 PCCTL_CONTEXT WINAPI
CertDuplicateCTLContext(PCCTL_CONTEXT pCtlContext
)
2391 FIXME("(%p): stub\n", pCtlContext
);
2395 BOOL WINAPI
CertFreeCTLContext(PCCTL_CONTEXT pCtlContext
)
2397 FIXME("(%p): stub\n", pCtlContext
);
2401 BOOL WINAPI
CertDeleteCTLFromStore(PCCTL_CONTEXT pCtlContext
)
2403 FIXME("(%p): stub\n", pCtlContext
);
2407 PCCTL_CONTEXT WINAPI
CertEnumCTLsInStore(HCERTSTORE hCertStore
,
2408 PCCTL_CONTEXT pPrev
)
2410 FIXME("(%p, %p): stub\n", hCertStore
, pPrev
);
2414 HCERTSTORE WINAPI
CertDuplicateStore(HCERTSTORE hCertStore
)
2416 WINECRYPT_CERTSTORE
*hcs
= (WINECRYPT_CERTSTORE
*)hCertStore
;
2418 TRACE("(%p)\n", hCertStore
);
2420 if (hcs
&& hcs
->dwMagic
== WINE_CRYPTCERTSTORE_MAGIC
)
2421 InterlockedIncrement(&hcs
->ref
);
2425 BOOL WINAPI
CertCloseStore(HCERTSTORE hCertStore
, DWORD dwFlags
)
2427 WINECRYPT_CERTSTORE
*hcs
= (WINECRYPT_CERTSTORE
*) hCertStore
;
2429 TRACE("(%p, %08lx)\n", hCertStore
, dwFlags
);
2434 if ( hcs
->dwMagic
!= WINE_CRYPTCERTSTORE_MAGIC
)
2437 if (InterlockedDecrement(&hcs
->ref
) == 0)
2439 TRACE("%p's ref count is 0, freeing\n", hcs
);
2441 if (!(hcs
->dwOpenFlags
& CERT_STORE_NO_CRYPT_RELEASE_FLAG
))
2442 CryptReleaseContext(hcs
->cryptProv
, 0);
2443 hcs
->closeStore(hcs
, dwFlags
);
2446 TRACE("%p's ref count is %ld\n", hcs
, hcs
->ref
);
2450 BOOL WINAPI
CertControlStore(HCERTSTORE hCertStore
, DWORD dwFlags
,
2451 DWORD dwCtrlType
, void const *pvCtrlPara
)
2453 WINECRYPT_CERTSTORE
*hcs
= (WINECRYPT_CERTSTORE
*)hCertStore
;
2456 TRACE("(%p, %08lx, %ld, %p)\n", hCertStore
, dwFlags
, dwCtrlType
,
2461 else if (hcs
->dwMagic
!= WINE_CRYPTCERTSTORE_MAGIC
)
2466 ret
= hcs
->control(hCertStore
, dwFlags
, dwCtrlType
, pvCtrlPara
);
2473 DWORD WINAPI
CertEnumCTLContextProperties(PCCTL_CONTEXT pCTLContext
,
2476 FIXME("(%p, %ld): stub\n", pCTLContext
, dwPropId
);
2480 BOOL WINAPI
CertGetCTLContextProperty(PCCTL_CONTEXT pCTLContext
,
2481 DWORD dwPropId
, void *pvData
, DWORD
*pcbData
)
2483 FIXME("(%p, %ld, %p, %p): stub\n", pCTLContext
, dwPropId
, pvData
, pcbData
);
2487 BOOL WINAPI
CertSetCTLContextProperty(PCCTL_CONTEXT pCTLContext
,
2488 DWORD dwPropId
, DWORD dwFlags
, const void *pvData
)
2490 FIXME("(%p, %ld, %08lx, %p): stub\n", pCTLContext
, dwPropId
, dwFlags
,
2495 BOOL WINAPI
CertAddStoreToCollection(HCERTSTORE hCollectionStore
,
2496 HCERTSTORE hSiblingStore
, DWORD dwUpdateFlags
, DWORD dwPriority
)
2498 PWINE_COLLECTIONSTORE collection
= (PWINE_COLLECTIONSTORE
)hCollectionStore
;
2499 WINECRYPT_CERTSTORE
*sibling
= (WINECRYPT_CERTSTORE
*)hSiblingStore
;
2500 PWINE_STORE_LIST_ENTRY entry
;
2503 TRACE("(%p, %p, %08lx, %ld)\n", hCollectionStore
, hSiblingStore
,
2504 dwUpdateFlags
, dwPriority
);
2506 if (!collection
|| !sibling
)
2508 if (collection
->hdr
.dwMagic
!= WINE_CRYPTCERTSTORE_MAGIC
)
2510 SetLastError(E_INVALIDARG
);
2513 if (collection
->hdr
.type
!= StoreTypeCollection
)
2515 SetLastError(E_INVALIDARG
);
2518 if (sibling
->dwMagic
!= WINE_CRYPTCERTSTORE_MAGIC
)
2520 SetLastError(E_INVALIDARG
);
2524 entry
= CryptMemAlloc(sizeof(WINE_STORE_LIST_ENTRY
));
2527 InterlockedIncrement(&sibling
->ref
);
2528 TRACE("sibling %p's ref count is %ld\n", sibling
, sibling
->ref
);
2529 entry
->store
= sibling
;
2530 entry
->dwUpdateFlags
= dwUpdateFlags
;
2531 entry
->dwPriority
= dwPriority
;
2532 list_init(&entry
->entry
);
2533 TRACE("%p: adding %p, priority %ld\n", collection
, entry
, dwPriority
);
2534 EnterCriticalSection(&collection
->cs
);
2537 PWINE_STORE_LIST_ENTRY cursor
;
2540 LIST_FOR_EACH_ENTRY(cursor
, &collection
->stores
,
2541 WINE_STORE_LIST_ENTRY
, entry
)
2543 if (cursor
->dwPriority
< dwPriority
)
2545 list_add_before(&cursor
->entry
, &entry
->entry
);
2551 list_add_tail(&collection
->stores
, &entry
->entry
);
2554 list_add_tail(&collection
->stores
, &entry
->entry
);
2555 LeaveCriticalSection(&collection
->cs
);
2563 void WINAPI
CertRemoveStoreFromCollection(HCERTSTORE hCollectionStore
,
2564 HCERTSTORE hSiblingStore
)
2566 PWINE_COLLECTIONSTORE collection
= (PWINE_COLLECTIONSTORE
)hCollectionStore
;
2567 WINECRYPT_CERTSTORE
*sibling
= (WINECRYPT_CERTSTORE
*)hSiblingStore
;
2568 PWINE_STORE_LIST_ENTRY store
, next
;
2570 TRACE("(%p, %p)\n", hCollectionStore
, hSiblingStore
);
2572 if (!collection
|| !sibling
)
2574 if (collection
->hdr
.dwMagic
!= WINE_CRYPTCERTSTORE_MAGIC
)
2576 SetLastError(E_INVALIDARG
);
2579 if (collection
->hdr
.type
!= StoreTypeCollection
)
2581 if (sibling
->dwMagic
!= WINE_CRYPTCERTSTORE_MAGIC
)
2583 SetLastError(E_INVALIDARG
);
2586 EnterCriticalSection(&collection
->cs
);
2587 LIST_FOR_EACH_ENTRY_SAFE(store
, next
, &collection
->stores
,
2588 WINE_STORE_LIST_ENTRY
, entry
)
2590 if (store
->store
== sibling
)
2592 list_remove(&store
->entry
);
2593 CertCloseStore(store
->store
, 0);
2594 CryptMemFree(store
);
2598 LeaveCriticalSection(&collection
->cs
);