2 * Copyright 2002 Mike McCormack for CodeWeavers
3 * Copyright 2004,2005 Juan Lang
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 * - As you can see in the stubs below, support for CRLs and CTLs is missing.
21 * Mostly this should be copy-paste work, and some code (e.g. extended
22 * properties) could be shared between them.
23 * - Opening a cert store provider should be morphed to support loading
25 * - The concept of physical stores and locations isn't implemented. (This
26 * doesn't mean registry stores et al aren't implemented. See the PSDK for
27 * registering and enumerating physical stores and locations.)
28 * - Many flags, options and whatnot are unimplemented.
38 #include "wine/debug.h"
39 #include "wine/list.h"
41 #include "wine/exception.h"
42 #include "crypt32_private.h"
44 WINE_DEFAULT_DEBUG_CHANNEL(crypt
);
46 #define WINE_CRYPTCERTSTORE_MAGIC 0x74726563
47 /* The following aren't defined in wincrypt.h, as they're "reserved" */
48 #define CERT_CERT_PROP_ID 32
49 #define CERT_CRL_PROP_ID 33
50 #define CERT_CTL_PROP_ID 34
52 /* Some typedefs that make it easier to abstract which type of context we're
55 typedef const void *(WINAPI
*CreateContextFunc
)(DWORD dwCertEncodingType
,
56 const BYTE
*pbCertEncoded
, DWORD cbCertEncoded
);
57 typedef BOOL (WINAPI
*AddContextToStoreFunc
)(HCERTSTORE hCertStore
,
58 const void *context
, DWORD dwAddDisposition
, const void **ppStoreContext
);
59 typedef BOOL (WINAPI
*AddEncodedContextToStoreFunc
)(HCERTSTORE hCertStore
,
60 DWORD dwCertEncodingType
, const BYTE
*pbEncoded
, DWORD cbEncoded
,
61 DWORD dwAddDisposition
, const void **ppContext
);
62 typedef const void *(WINAPI
*EnumContextsInStoreFunc
)(HCERTSTORE hCertStore
,
63 const void *pPrevContext
);
64 typedef BOOL (WINAPI
*GetContextPropertyFunc
)(const void *context
,
65 DWORD dwPropID
, void *pvData
, DWORD
*pcbData
);
66 typedef BOOL (WINAPI
*SetContextPropertyFunc
)(const void *context
,
67 DWORD dwPropID
, DWORD dwFlags
, const void *pvData
);
68 typedef BOOL (WINAPI
*SerializeElementFunc
)(const void *context
, DWORD dwFlags
,
69 BYTE
*pbElement
, DWORD
*pcbElement
);
70 typedef BOOL (WINAPI
*FreeContextFunc
)(const void *context
);
71 typedef BOOL (WINAPI
*DeleteContextFunc
)(const void *context
);
73 /* An abstract context (certificate, CRL, or CTL) interface */
74 typedef struct _WINE_CONTEXT_INTERFACE
76 CreateContextFunc create
;
77 AddContextToStoreFunc addContextToStore
;
78 AddEncodedContextToStoreFunc addEncodedToStore
;
79 EnumContextsInStoreFunc enumContextsInStore
;
80 GetContextPropertyFunc getProp
;
81 SetContextPropertyFunc setProp
;
82 SerializeElementFunc serialize
;
84 DeleteContextFunc deleteFromStore
;
85 } WINE_CONTEXT_INTERFACE
, *PWINE_CONTEXT_INTERFACE
;
87 static const WINE_CONTEXT_INTERFACE gCertInterface
= {
88 (CreateContextFunc
)CertCreateCertificateContext
,
89 (AddContextToStoreFunc
)CertAddCertificateContextToStore
,
90 (AddEncodedContextToStoreFunc
)CertAddEncodedCertificateToStore
,
91 (EnumContextsInStoreFunc
)CertEnumCertificatesInStore
,
92 (GetContextPropertyFunc
)CertGetCertificateContextProperty
,
93 (SetContextPropertyFunc
)CertSetCertificateContextProperty
,
94 (SerializeElementFunc
)CertSerializeCertificateStoreElement
,
95 (FreeContextFunc
)CertFreeCertificateContext
,
96 (DeleteContextFunc
)CertDeleteCertificateFromStore
,
99 static const WINE_CONTEXT_INTERFACE gCRLInterface
= {
100 (CreateContextFunc
)CertCreateCRLContext
,
101 (AddContextToStoreFunc
)CertAddCRLContextToStore
,
102 (AddEncodedContextToStoreFunc
)CertAddEncodedCRLToStore
,
103 (EnumContextsInStoreFunc
)CertEnumCRLsInStore
,
104 (GetContextPropertyFunc
)CertGetCRLContextProperty
,
105 (SetContextPropertyFunc
)CertSetCRLContextProperty
,
106 (SerializeElementFunc
)CertSerializeCRLStoreElement
,
107 (FreeContextFunc
)CertFreeCRLContext
,
108 (DeleteContextFunc
)CertDeleteCRLFromStore
,
111 static const WINE_CONTEXT_INTERFACE gCTLInterface
= {
112 (CreateContextFunc
)CertCreateCTLContext
,
113 (AddContextToStoreFunc
)CertAddCTLContextToStore
,
114 (AddEncodedContextToStoreFunc
)CertAddEncodedCTLToStore
,
115 (EnumContextsInStoreFunc
)CertEnumCTLsInStore
,
116 (GetContextPropertyFunc
)CertGetCTLContextProperty
,
117 (SetContextPropertyFunc
)CertSetCTLContextProperty
,
118 (SerializeElementFunc
)CertSerializeCTLStoreElement
,
119 (FreeContextFunc
)CertFreeCTLContext
,
120 (DeleteContextFunc
)CertDeleteCTLFromStore
,
123 struct WINE_CRYPTCERTSTORE
;
125 typedef struct WINE_CRYPTCERTSTORE
* (*StoreOpenFunc
)(HCRYPTPROV hCryptProv
,
126 DWORD dwFlags
, const void *pvPara
);
128 struct _WINE_CERT_CONTEXT_REF
;
130 /* Called to enumerate the next certificate in a store. The returned pointer
131 * must be newly allocated (via HeapAlloc): CertFreeCertificateContext frees
134 typedef struct _WINE_CERT_CONTEXT_REF
* (*EnumCertFunc
)
135 (struct WINE_CRYPTCERTSTORE
*store
, struct _WINE_CERT_CONTEXT_REF
*pPrev
);
137 struct _WINE_CERT_CONTEXT
;
139 /* Called to create a new reference to an existing cert context. Should call
140 * CRYPT_InitCertRef to make sure the reference count is properly updated.
141 * If the store does not provide any additional allocated data (that is, does
142 * not need to implement a FreeCertFunc), it may use CRYPT_CreateCertRef for
145 typedef struct _WINE_CERT_CONTEXT_REF
* (*CreateRefFunc
)
146 (struct _WINE_CERT_CONTEXT
*context
, HCERTSTORE store
);
148 /* Optional, called when a cert context reference is being freed. Don't free
149 * the ref pointer itself, CertFreeCertificateContext does that.
151 typedef void (*FreeCertFunc
)(struct _WINE_CERT_CONTEXT_REF
*ref
);
153 typedef enum _CertStoreType
{
160 /* A cert store is polymorphic through the use of function pointers. A type
161 * is still needed to distinguish collection stores from other types.
162 * On the function pointers:
163 * - closeStore is called when the store's ref count becomes 0
164 * - addCert is called with a PWINE_CERT_CONTEXT as the second parameter
165 * - control is optional, but should be implemented by any store that supports
168 typedef struct WINE_CRYPTCERTSTORE
173 HCRYPTPROV cryptProv
;
175 PFN_CERT_STORE_PROV_CLOSE closeStore
;
176 PFN_CERT_STORE_PROV_WRITE_CERT addCert
;
177 CreateRefFunc createCertRef
;
178 EnumCertFunc enumCert
;
179 PFN_CERT_STORE_PROV_DELETE_CERT deleteCert
;
180 FreeCertFunc freeCert
; /* optional */
181 PFN_CERT_STORE_PROV_CONTROL control
; /* optional */
182 } WINECRYPT_CERTSTORE
, *PWINECRYPT_CERTSTORE
;
184 /* A certificate context has pointers to data that are owned by this module,
185 * so rather than duplicate the data every time a certificate context is
186 * copied, I keep a reference count to the data. Thus I have two data
187 * structures, the "true" certificate context (that has the reference count)
188 * and a reference certificate context, that has a pointer to the true context.
189 * Each one can be cast to a PCERT_CONTEXT, though you'll usually be dealing
190 * with the reference version.
192 typedef struct _WINE_CERT_CONTEXT
197 struct list extendedProperties
;
198 } WINE_CERT_CONTEXT
, *PWINE_CERT_CONTEXT
;
200 typedef struct _WINE_CERT_CONTEXT_REF
203 WINE_CERT_CONTEXT
*context
;
204 } WINE_CERT_CONTEXT_REF
, *PWINE_CERT_CONTEXT_REF
;
206 /* An extended certificate property in serialized form is prefixed by this
209 typedef struct _WINE_CERT_PROP_HEADER
212 DWORD unknown
; /* always 1 */
214 } WINE_CERT_PROP_HEADER
, *PWINE_CERT_PROP_HEADER
;
216 /* Stores an extended property in a cert. */
217 typedef struct _WINE_CERT_PROPERTY
219 WINE_CERT_PROP_HEADER hdr
;
222 } WINE_CERT_PROPERTY
, *PWINE_CERT_PROPERTY
;
224 /* A mem store has a list of these. They're also returned by the mem store
225 * during enumeration.
227 typedef struct _WINE_CERT_LIST_ENTRY
229 WINE_CERT_CONTEXT_REF cert
;
231 } WINE_CERT_LIST_ENTRY
, *PWINE_CERT_LIST_ENTRY
;
233 typedef struct _WINE_MEMSTORE
235 WINECRYPT_CERTSTORE hdr
;
238 } WINE_MEMSTORE
, *PWINE_MEMSTORE
;
240 typedef struct _WINE_HASH_TO_DELETE
244 } WINE_HASH_TO_DELETE
, *PWINE_HASH_TO_DELETE
;
246 /* Returned by a reg store during enumeration. */
247 typedef struct _WINE_REG_CERT_CONTEXT
249 WINE_CERT_CONTEXT_REF cert
;
250 PWINE_CERT_CONTEXT_REF childContext
;
251 } WINE_REG_CERT_CONTEXT
, *PWINE_REG_CERT_CONTEXT
;
253 typedef struct _WINE_REGSTORE
255 WINECRYPT_CERTSTORE hdr
;
256 PWINECRYPT_CERTSTORE memStore
;
260 struct list certsToDelete
;
261 } WINE_REGSTORE
, *PWINE_REGSTORE
;
263 typedef struct _WINE_STORE_LIST_ENTRY
265 PWINECRYPT_CERTSTORE store
;
269 } WINE_STORE_LIST_ENTRY
, *PWINE_STORE_LIST_ENTRY
;
271 /* Returned by a collection store during enumeration.
272 * Note: relies on the list entry being valid after use, which a number of
273 * conditions might make untrue (reentrancy, closing a collection store before
274 * continuing an enumeration on it, ...). The tests seem to indicate this
275 * sort of unsafety is okay, since Windows isn't well-behaved in these
278 typedef struct _WINE_COLLECTION_CERT_CONTEXT
280 WINE_CERT_CONTEXT_REF cert
;
281 PWINE_STORE_LIST_ENTRY entry
;
282 PWINE_CERT_CONTEXT_REF childContext
;
283 } WINE_COLLECTION_CERT_CONTEXT
, *PWINE_COLLECTION_CERT_CONTEXT
;
285 typedef struct _WINE_COLLECTIONSTORE
287 WINECRYPT_CERTSTORE hdr
;
290 } WINE_COLLECTIONSTORE
, *PWINE_COLLECTIONSTORE
;
292 /* Like CertGetCertificateContextProperty, but operates directly on the
293 * WINE_CERT_CONTEXT. Doesn't support special-case properties, since they
294 * are handled by CertGetCertificateContextProperty, and are particular to the
295 * store in which the property exists (which is separate from the context.)
297 static BOOL WINAPI
CRYPT_GetCertificateContextProperty(
298 PWINE_CERT_CONTEXT context
, DWORD dwPropId
, void *pvData
, DWORD
*pcbData
);
300 /* Like CertSetCertificateContextProperty, but operates directly on the
301 * WINE_CERT_CONTEXT. Doesn't handle special cases, since they're handled by
302 * CertSetCertificateContextProperty anyway.
304 static BOOL WINAPI
CRYPT_SetCertificateContextProperty(
305 PWINE_CERT_CONTEXT context
, DWORD dwPropId
, DWORD dwFlags
, const void *pvData
);
307 /* Helper function for store reading functions and
308 * CertAddSerializedElementToStore. Returns a context of the appropriate type
309 * if it can, or NULL otherwise. Doesn't validate any of the properties in
310 * the serialized context (for example, bad hashes are retained.)
311 * *pdwContentType is set to the type of the returned context.
313 static const void * WINAPI
CRYPT_ReadSerializedElement(const BYTE
*pbElement
,
314 DWORD cbElement
, DWORD dwContextTypeFlags
, DWORD
*pdwContentType
);
316 /* filter for page-fault exceptions */
317 static WINE_EXCEPTION_FILTER(page_fault
)
319 if (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION
)
320 return EXCEPTION_EXECUTE_HANDLER
;
321 return EXCEPTION_CONTINUE_SEARCH
;
324 static void CRYPT_InitStore(WINECRYPT_CERTSTORE
*store
, HCRYPTPROV hCryptProv
,
325 DWORD dwFlags
, CertStoreType type
)
328 store
->dwMagic
= WINE_CRYPTCERTSTORE_MAGIC
;
332 hCryptProv
= CRYPT_GetDefaultProvider();
333 dwFlags
|= CERT_STORE_NO_CRYPT_RELEASE_FLAG
;
335 store
->cryptProv
= hCryptProv
;
336 store
->dwOpenFlags
= dwFlags
;
339 /* Initializes the reference ref to point to pCertContext, which is assumed to
340 * be a PWINE_CERT_CONTEXT, and increments pCertContext's reference count.
341 * Also sets the hCertStore member of the reference to store.
343 static void CRYPT_InitCertRef(PWINE_CERT_CONTEXT_REF ref
,
344 PWINE_CERT_CONTEXT context
, HCERTSTORE store
)
346 TRACE("(%p, %p)\n", ref
, context
);
347 memcpy(&ref
->cert
, context
, sizeof(ref
->cert
));
348 ref
->context
= context
;
349 InterlockedIncrement(&context
->ref
);
350 ref
->cert
.hCertStore
= store
;
353 static PWINE_CERT_CONTEXT_REF
CRYPT_CreateCertRef(PWINE_CERT_CONTEXT context
,
356 PWINE_CERT_CONTEXT_REF pCertRef
= HeapAlloc(GetProcessHeap(), 0,
357 sizeof(WINE_CERT_CONTEXT_REF
));
360 CRYPT_InitCertRef(pCertRef
, context
, store
);
364 static BOOL WINAPI
CRYPT_MemAddCert(HCERTSTORE store
, PCCERT_CONTEXT pCert
,
365 DWORD dwAddDisposition
)
367 WINE_MEMSTORE
*ms
= (WINE_MEMSTORE
*)store
;
368 BOOL add
= FALSE
, ret
;
370 TRACE("(%p, %p, %ld)\n", store
, pCert
, dwAddDisposition
);
372 switch (dwAddDisposition
)
374 case CERT_STORE_ADD_ALWAYS
:
377 case CERT_STORE_ADD_NEW
:
379 BYTE hashToAdd
[20], hash
[20];
380 DWORD size
= sizeof(hashToAdd
);
382 ret
= CRYPT_GetCertificateContextProperty((PWINE_CERT_CONTEXT
)pCert
,
383 CERT_HASH_PROP_ID
, hashToAdd
, &size
);
386 PWINE_CERT_LIST_ENTRY cursor
;
388 /* Add if no cert with the same hash is found. */
390 EnterCriticalSection(&ms
->cs
);
391 LIST_FOR_EACH_ENTRY(cursor
, &ms
->certs
, WINE_CERT_LIST_ENTRY
, entry
)
394 ret
= CertGetCertificateContextProperty(&cursor
->cert
.cert
,
395 CERT_HASH_PROP_ID
, hash
, &size
);
396 if (ret
&& !memcmp(hashToAdd
, hash
, size
))
398 TRACE("found matching certificate, not adding\n");
399 SetLastError(CRYPT_E_EXISTS
);
404 LeaveCriticalSection(&ms
->cs
);
408 case CERT_STORE_ADD_REPLACE_EXISTING
:
410 BYTE hashToAdd
[20], hash
[20];
411 DWORD size
= sizeof(hashToAdd
);
414 ret
= CRYPT_GetCertificateContextProperty((PWINE_CERT_CONTEXT
)pCert
,
415 CERT_HASH_PROP_ID
, hashToAdd
, &size
);
418 PWINE_CERT_LIST_ENTRY cursor
, next
;
420 /* Look for existing cert to delete */
421 EnterCriticalSection(&ms
->cs
);
422 LIST_FOR_EACH_ENTRY_SAFE(cursor
, next
, &ms
->certs
,
423 WINE_CERT_LIST_ENTRY
, entry
)
426 ret
= CertGetCertificateContextProperty(&cursor
->cert
.cert
,
427 CERT_HASH_PROP_ID
, hash
, &size
);
428 if (ret
&& !memcmp(hashToAdd
, hash
, size
))
430 TRACE("found matching certificate, replacing\n");
431 list_remove(&cursor
->entry
);
432 CertFreeCertificateContext((PCCERT_CONTEXT
)cursor
);
436 LeaveCriticalSection(&ms
->cs
);
441 FIXME("Unimplemented add disposition %ld\n", dwAddDisposition
);
446 PWINE_CERT_LIST_ENTRY entry
= HeapAlloc(GetProcessHeap(), 0,
447 sizeof(WINE_CERT_LIST_ENTRY
));
451 TRACE("adding %p\n", entry
);
452 CRYPT_InitCertRef(&entry
->cert
, (PWINE_CERT_CONTEXT
)pCert
, store
);
453 list_init(&entry
->entry
);
454 EnterCriticalSection(&ms
->cs
);
455 list_add_tail(&ms
->certs
, &entry
->entry
);
456 LeaveCriticalSection(&ms
->cs
);
467 static PWINE_CERT_CONTEXT_REF
CRYPT_MemEnumCert(PWINECRYPT_CERTSTORE store
,
468 PWINE_CERT_CONTEXT_REF pPrev
)
470 WINE_MEMSTORE
*ms
= (WINE_MEMSTORE
*)store
;
471 PWINE_CERT_LIST_ENTRY prevEntry
= (PWINE_CERT_LIST_ENTRY
)pPrev
, ret
;
472 struct list
*listNext
;
474 TRACE("(%p, %p)\n", store
, pPrev
);
475 EnterCriticalSection(&ms
->cs
);
478 listNext
= list_next(&ms
->certs
, &prevEntry
->entry
);
479 CertFreeCertificateContext((PCCERT_CONTEXT
)pPrev
);
482 listNext
= list_next(&ms
->certs
, &ms
->certs
);
485 ret
= HeapAlloc(GetProcessHeap(), 0, sizeof(WINE_CERT_LIST_ENTRY
));
486 memcpy(ret
, LIST_ENTRY(listNext
, WINE_CERT_LIST_ENTRY
, entry
),
487 sizeof(WINE_CERT_LIST_ENTRY
));
488 InterlockedIncrement(&ret
->cert
.context
->ref
);
492 SetLastError(CRYPT_E_NOT_FOUND
);
495 LeaveCriticalSection(&ms
->cs
);
497 TRACE("returning %p\n", ret
);
498 return (PWINE_CERT_CONTEXT_REF
)ret
;
501 static BOOL WINAPI
CRYPT_MemDeleteCert(HCERTSTORE hCertStore
,
502 PCCERT_CONTEXT pCertContext
, DWORD dwFlags
)
504 WINE_MEMSTORE
*store
= (WINE_MEMSTORE
*)hCertStore
;
505 WINE_CERT_CONTEXT_REF
*ref
= (WINE_CERT_CONTEXT_REF
*)pCertContext
;
506 PWINE_CERT_LIST_ENTRY cert
, next
;
509 /* Find the entry associated with the passed-in context, since the
510 * passed-in context may not be a list entry itself (e.g. if it came from
511 * CertDuplicateCertificateContext.) Pointing to the same context is
512 * a sufficient test of equality.
514 EnterCriticalSection(&store
->cs
);
515 LIST_FOR_EACH_ENTRY_SAFE(cert
, next
, &store
->certs
, WINE_CERT_LIST_ENTRY
,
518 if (cert
->cert
.context
== ref
->context
)
520 TRACE("removing %p\n", cert
);
521 /* FIXME: this isn't entirely thread-safe, the entry itself isn't
524 list_remove(&cert
->entry
);
525 cert
->entry
.prev
= cert
->entry
.next
= &store
->certs
;
526 CertFreeCertificateContext((PCCERT_CONTEXT
)cert
);
531 LeaveCriticalSection(&store
->cs
);
535 static void WINAPI
CRYPT_MemCloseStore(HCERTSTORE hCertStore
, DWORD dwFlags
)
537 WINE_MEMSTORE
*store
= (WINE_MEMSTORE
*)hCertStore
;
538 PWINE_CERT_LIST_ENTRY cert
, next
;
540 TRACE("(%p, %08lx)\n", store
, dwFlags
);
542 FIXME("Unimplemented flags: %08lx\n", dwFlags
);
544 /* Note that CertFreeCertificateContext calls HeapFree on the passed-in
545 * pointer if its ref-count reaches zero. That's okay here because there
546 * aren't any allocated data outside of the WINE_CERT_CONTEXT_REF portion
547 * of the CertListEntry.
549 LIST_FOR_EACH_ENTRY_SAFE(cert
, next
, &store
->certs
, WINE_CERT_LIST_ENTRY
,
552 TRACE("removing %p\n", cert
);
553 list_remove(&cert
->entry
);
554 CertFreeCertificateContext((PCCERT_CONTEXT
)cert
);
556 DeleteCriticalSection(&store
->cs
);
557 HeapFree(GetProcessHeap(), 0, store
);
560 static WINECRYPT_CERTSTORE
*CRYPT_MemOpenStore(HCRYPTPROV hCryptProv
,
561 DWORD dwFlags
, const void *pvPara
)
563 PWINE_MEMSTORE store
;
565 TRACE("(%ld, %08lx, %p)\n", hCryptProv
, dwFlags
, pvPara
);
567 if (dwFlags
& CERT_STORE_DELETE_FLAG
)
569 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
574 store
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
575 sizeof(WINE_MEMSTORE
));
578 CRYPT_InitStore(&store
->hdr
, hCryptProv
, dwFlags
, StoreTypeMem
);
579 store
->hdr
.closeStore
= CRYPT_MemCloseStore
;
580 store
->hdr
.addCert
= CRYPT_MemAddCert
;
581 store
->hdr
.createCertRef
= CRYPT_CreateCertRef
;
582 store
->hdr
.enumCert
= CRYPT_MemEnumCert
;
583 store
->hdr
.deleteCert
= CRYPT_MemDeleteCert
;
584 store
->hdr
.freeCert
= NULL
;
585 InitializeCriticalSection(&store
->cs
);
586 list_init(&store
->certs
);
589 return (PWINECRYPT_CERTSTORE
)store
;
592 static BOOL WINAPI
CRYPT_CollectionAddCert(HCERTSTORE store
,
593 PCCERT_CONTEXT pCert
, DWORD dwAddDisposition
)
595 PWINE_COLLECTIONSTORE cs
= (PWINE_COLLECTIONSTORE
)store
;
596 PWINE_STORE_LIST_ENTRY entry
, next
;
599 TRACE("(%p, %p, %ld)\n", store
, pCert
, dwAddDisposition
);
602 EnterCriticalSection(&cs
->cs
);
603 LIST_FOR_EACH_ENTRY_SAFE(entry
, next
, &cs
->stores
, WINE_STORE_LIST_ENTRY
,
606 if (entry
->dwUpdateFlags
& CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG
)
608 ret
= entry
->store
->addCert(entry
->store
, pCert
, dwAddDisposition
);
612 LeaveCriticalSection(&cs
->cs
);
613 SetLastError(ret
? ERROR_SUCCESS
: HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED
));
617 static PWINE_CERT_CONTEXT_REF
CRYPT_CollectionCreateCertRef(
618 PWINE_CERT_CONTEXT context
, HCERTSTORE store
)
620 PWINE_COLLECTION_CERT_CONTEXT ret
= HeapAlloc(GetProcessHeap(), 0,
621 sizeof(WINE_COLLECTION_CERT_CONTEXT
));
625 /* Initialize to empty for now, just make sure the size is right */
626 CRYPT_InitCertRef((PWINE_CERT_CONTEXT_REF
)ret
, context
, store
);
628 ret
->childContext
= NULL
;
630 return (PWINE_CERT_CONTEXT_REF
)ret
;
633 static void WINAPI
CRYPT_CollectionCloseStore(HCERTSTORE store
, DWORD dwFlags
)
635 PWINE_COLLECTIONSTORE cs
= (PWINE_COLLECTIONSTORE
)store
;
636 PWINE_STORE_LIST_ENTRY entry
, next
;
638 TRACE("(%p, %08lx)\n", store
, dwFlags
);
640 LIST_FOR_EACH_ENTRY_SAFE(entry
, next
, &cs
->stores
, WINE_STORE_LIST_ENTRY
,
643 TRACE("closing %p\n", entry
);
644 CertCloseStore((HCERTSTORE
)entry
->store
, dwFlags
);
645 HeapFree(GetProcessHeap(), 0, entry
);
647 DeleteCriticalSection(&cs
->cs
);
648 HeapFree(GetProcessHeap(), 0, cs
);
651 /* Advances a collection enumeration by one cert, if possible, where advancing
653 * - calling the current store's enumeration function once, and returning
654 * the enumerated cert if one is returned
655 * - moving to the next store if the current store has no more items, and
656 * recursively calling itself to get the next item.
657 * Returns NULL if the collection contains no more items or on error.
658 * Assumes the collection store's lock is held.
660 static PWINE_COLLECTION_CERT_CONTEXT
CRYPT_CollectionAdvanceEnum(
661 PWINE_COLLECTIONSTORE store
, PWINE_STORE_LIST_ENTRY storeEntry
,
662 PWINE_COLLECTION_CERT_CONTEXT pPrev
)
664 PWINE_COLLECTION_CERT_CONTEXT ret
;
665 PWINE_CERT_CONTEXT_REF child
;
667 TRACE("(%p, %p, %p)\n", store
, storeEntry
, pPrev
);
671 child
= storeEntry
->store
->enumCert((HCERTSTORE
)storeEntry
->store
,
672 pPrev
->childContext
);
676 memcpy(&ret
->cert
, child
, sizeof(WINE_CERT_CONTEXT_REF
));
677 ret
->cert
.cert
.hCertStore
= (HCERTSTORE
)store
;
678 InterlockedIncrement(&ret
->cert
.context
->ref
);
679 ret
->childContext
= child
;
683 struct list
*storeNext
= list_next(&store
->stores
,
686 pPrev
->childContext
= NULL
;
687 CertFreeCertificateContext((PCCERT_CONTEXT
)pPrev
);
690 storeEntry
= LIST_ENTRY(storeNext
, WINE_STORE_LIST_ENTRY
,
692 ret
= CRYPT_CollectionAdvanceEnum(store
, storeEntry
, NULL
);
696 SetLastError(CRYPT_E_NOT_FOUND
);
703 child
= storeEntry
->store
->enumCert((HCERTSTORE
)storeEntry
->store
,
707 ret
= (PWINE_COLLECTION_CERT_CONTEXT
)CRYPT_CollectionCreateCertRef(
708 child
->context
, store
);
711 ret
->entry
= storeEntry
;
712 ret
->childContext
= child
;
715 CertFreeCertificateContext((PCCERT_CONTEXT
)child
);
719 struct list
*storeNext
= list_next(&store
->stores
,
724 storeEntry
= LIST_ENTRY(storeNext
, WINE_STORE_LIST_ENTRY
,
726 ret
= CRYPT_CollectionAdvanceEnum(store
, storeEntry
, NULL
);
730 SetLastError(CRYPT_E_NOT_FOUND
);
735 TRACE("returning %p\n", ret
);
739 static PWINE_CERT_CONTEXT_REF
CRYPT_CollectionEnumCert(
740 PWINECRYPT_CERTSTORE store
, PWINE_CERT_CONTEXT_REF pPrev
)
742 PWINE_COLLECTIONSTORE cs
= (PWINE_COLLECTIONSTORE
)store
;
743 PWINE_COLLECTION_CERT_CONTEXT prevEntry
=
744 (PWINE_COLLECTION_CERT_CONTEXT
)pPrev
, ret
;
746 TRACE("(%p, %p)\n", store
, pPrev
);
750 EnterCriticalSection(&cs
->cs
);
751 ret
= CRYPT_CollectionAdvanceEnum(cs
, prevEntry
->entry
, prevEntry
);
752 LeaveCriticalSection(&cs
->cs
);
756 EnterCriticalSection(&cs
->cs
);
757 if (!list_empty(&cs
->stores
))
759 PWINE_STORE_LIST_ENTRY storeEntry
;
761 storeEntry
= LIST_ENTRY(cs
->stores
.next
, WINE_STORE_LIST_ENTRY
,
763 ret
= CRYPT_CollectionAdvanceEnum(cs
, storeEntry
, prevEntry
);
767 SetLastError(CRYPT_E_NOT_FOUND
);
770 LeaveCriticalSection(&cs
->cs
);
772 TRACE("returning %p\n", ret
);
773 return (PWINE_CERT_CONTEXT_REF
)ret
;
776 static BOOL WINAPI
CRYPT_CollectionDeleteCert(HCERTSTORE hCertStore
,
777 PCCERT_CONTEXT pCertContext
, DWORD dwFlags
)
779 PWINE_COLLECTION_CERT_CONTEXT context
=
780 (PWINE_COLLECTION_CERT_CONTEXT
)pCertContext
;
783 TRACE("(%p, %p, %08lx)\n", hCertStore
, pCertContext
, dwFlags
);
785 ret
= CertDeleteCertificateFromStore((PCCERT_CONTEXT
)context
->childContext
);
788 context
->childContext
= NULL
;
789 CertFreeCertificateContext((PCCERT_CONTEXT
)context
);
794 static void CRYPT_CollectionFreeCert(PWINE_CERT_CONTEXT_REF ref
)
796 PWINE_COLLECTION_CERT_CONTEXT context
= (PWINE_COLLECTION_CERT_CONTEXT
)ref
;
798 TRACE("(%p)\n", ref
);
800 if (context
->childContext
)
801 CertFreeCertificateContext((PCCERT_CONTEXT
)context
->childContext
);
804 static WINECRYPT_CERTSTORE
*CRYPT_CollectionOpenStore(HCRYPTPROV hCryptProv
,
805 DWORD dwFlags
, const void *pvPara
)
807 PWINE_COLLECTIONSTORE store
;
809 if (dwFlags
& CERT_STORE_DELETE_FLAG
)
811 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
816 store
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
817 sizeof(WINE_COLLECTIONSTORE
));
820 CRYPT_InitStore(&store
->hdr
, hCryptProv
, dwFlags
,
821 StoreTypeCollection
);
822 store
->hdr
.closeStore
= CRYPT_CollectionCloseStore
;
823 store
->hdr
.addCert
= CRYPT_CollectionAddCert
;
824 store
->hdr
.createCertRef
= CRYPT_CollectionCreateCertRef
;
825 store
->hdr
.enumCert
= CRYPT_CollectionEnumCert
;
826 store
->hdr
.deleteCert
= CRYPT_CollectionDeleteCert
;
827 store
->hdr
.freeCert
= CRYPT_CollectionFreeCert
;
828 InitializeCriticalSection(&store
->cs
);
829 list_init(&store
->stores
);
832 return (PWINECRYPT_CERTSTORE
)store
;
835 static void CRYPT_HashToStr(LPBYTE hash
, LPWSTR asciiHash
)
837 static const WCHAR fmt
[] = { '%','0','2','X',0 };
843 for (i
= 0; i
< 20; i
++)
844 wsprintfW(asciiHash
+ i
* 2, fmt
, hash
[i
]);
847 static const WCHAR CertsW
[] = { 'C','e','r','t','i','f','i','c','a','t','e','s',
849 static const WCHAR CRLsW
[] = { 'C','R','L','s',0 };
850 static const WCHAR CTLsW
[] = { 'C','T','L','s',0 };
851 static const WCHAR BlobW
[] = { 'B','l','o','b',0 };
853 static void CRYPT_RegReadSerializedFromReg(PWINE_REGSTORE store
, HKEY key
,
858 WCHAR subKeyName
[MAX_PATH
];
861 DWORD size
= sizeof(subKeyName
) / sizeof(WCHAR
);
863 rc
= RegEnumKeyExW(key
, index
++, subKeyName
, &size
, NULL
, NULL
, NULL
,
869 rc
= RegOpenKeyExW(key
, subKeyName
, 0, KEY_READ
, &subKey
);
875 rc
= RegQueryValueExW(subKey
, BlobW
, NULL
, NULL
, NULL
, &size
);
877 buf
= HeapAlloc(GetProcessHeap(), 0, size
);
880 rc
= RegQueryValueExW(subKey
, BlobW
, NULL
, NULL
, buf
,
887 TRACE("Adding cert with hash %s\n",
888 debugstr_w(subKeyName
));
889 context
= CRYPT_ReadSerializedElement(buf
, size
,
890 contextType
, &addedType
);
893 const WINE_CONTEXT_INTERFACE
*contextInterface
;
898 case CERT_STORE_CERTIFICATE_CONTEXT
:
899 contextInterface
= &gCertInterface
;
901 case CERT_STORE_CRL_CONTEXT
:
902 contextInterface
= &gCRLInterface
;
904 case CERT_STORE_CTL_CONTEXT
:
905 contextInterface
= &gCTLInterface
;
908 contextInterface
= NULL
;
910 if (contextInterface
)
913 if (contextInterface
->getProp(context
,
914 CERT_HASH_PROP_ID
, hash
, &size
))
916 WCHAR asciiHash
[20 * 2 + 1];
918 CRYPT_HashToStr(hash
, asciiHash
);
919 TRACE("comparing %s\n",
920 debugstr_w(asciiHash
));
921 TRACE("with %s\n", debugstr_w(subKeyName
));
922 if (!lstrcmpW(asciiHash
, subKeyName
))
924 TRACE("hash matches, adding\n");
925 contextInterface
->addContextToStore(
927 CERT_STORE_ADD_REPLACE_EXISTING
, NULL
);
931 TRACE("hash doesn't match, ignoring\n");
932 contextInterface
->free(context
);
938 HeapFree(GetProcessHeap(), 0, buf
);
942 /* Ignore intermediate errors, continue enumerating */
948 static void CRYPT_RegReadFromReg(PWINE_REGSTORE store
)
950 static const WCHAR
*subKeys
[] = { CertsW
, CRLsW
, CTLsW
};
951 static const DWORD contextFlags
[] = { CERT_STORE_CERTIFICATE_CONTEXT_FLAG
,
952 CERT_STORE_CRL_CONTEXT_FLAG
, CERT_STORE_CTL_CONTEXT_FLAG
};
955 for (i
= 0; i
< sizeof(subKeys
) / sizeof(subKeys
[0]); i
++)
960 rc
= RegCreateKeyExW(store
->key
, subKeys
[i
], 0, NULL
, 0, KEY_READ
, NULL
,
964 CRYPT_RegReadSerializedFromReg(store
, key
, contextFlags
[i
]);
970 /* Hash is assumed to be 20 bytes in length (a SHA-1 hash) */
971 static BOOL
CRYPT_WriteSerializedToReg(HKEY key
, LPBYTE hash
, LPBYTE buf
,
974 WCHAR asciiHash
[20 * 2 + 1];
979 CRYPT_HashToStr(hash
, asciiHash
);
980 rc
= RegCreateKeyExW(key
, asciiHash
, 0, NULL
, 0, KEY_ALL_ACCESS
, NULL
,
984 rc
= RegSetValueExW(subKey
, BlobW
, 0, REG_BINARY
, buf
, len
);
997 static BOOL
CRYPT_SerializeContextsToReg(HKEY key
,
998 const WINE_CONTEXT_INTERFACE
*contextInterface
, HCERTSTORE memStore
)
1000 const void *context
= NULL
;
1004 context
= contextInterface
->enumContextsInStore(memStore
, context
);
1008 DWORD hashSize
= sizeof(hash
);
1010 ret
= contextInterface
->getProp(context
, CERT_HASH_PROP_ID
, hash
,
1017 ret
= contextInterface
->serialize(context
, 0, NULL
, &size
);
1019 buf
= HeapAlloc(GetProcessHeap(), 0, size
);
1022 ret
= contextInterface
->serialize(context
, 0, buf
, &size
);
1024 ret
= CRYPT_WriteSerializedToReg(key
, hash
, buf
, size
);
1026 HeapFree(GetProcessHeap(), 0, buf
);
1031 } while (ret
&& context
!= NULL
);
1033 contextInterface
->free(context
);
1037 static BOOL
CRYPT_RegWriteToReg(PWINE_REGSTORE store
)
1039 static const WCHAR
*subKeys
[] = { CertsW
, CRLsW
, CTLsW
};
1040 static const WINE_CONTEXT_INTERFACE
*interfaces
[] = { &gCertInterface
,
1041 &gCRLInterface
, &gCTLInterface
};
1042 struct list
*listToDelete
[] = { &store
->certsToDelete
, NULL
, NULL
};
1046 for (i
= 0; ret
&& i
< sizeof(subKeys
) / sizeof(subKeys
[0]); i
++)
1049 LONG rc
= RegCreateKeyExW(store
->key
, subKeys
[i
], 0, NULL
, 0,
1050 KEY_ALL_ACCESS
, NULL
, &key
, NULL
);
1054 if (listToDelete
[i
])
1056 PWINE_HASH_TO_DELETE toDelete
, next
;
1057 WCHAR asciiHash
[20 * 2 + 1];
1059 EnterCriticalSection(&store
->cs
);
1060 LIST_FOR_EACH_ENTRY_SAFE(toDelete
, next
, listToDelete
[i
],
1061 WINE_HASH_TO_DELETE
, entry
)
1065 CRYPT_HashToStr(toDelete
->hash
, asciiHash
);
1066 TRACE("Removing %s\n", debugstr_w(asciiHash
));
1067 rc
= RegDeleteKeyW(key
, asciiHash
);
1068 if (rc
!= ERROR_SUCCESS
&& rc
!= ERROR_FILE_NOT_FOUND
)
1073 list_remove(&toDelete
->entry
);
1074 HeapFree(GetProcessHeap(), 0, toDelete
);
1076 LeaveCriticalSection(&store
->cs
);
1078 ret
= CRYPT_SerializeContextsToReg(key
, interfaces
[i
],
1091 /* If force is true or the registry store is dirty, writes the contents of the
1092 * store to the registry.
1094 static BOOL
CRYPT_RegFlushStore(PWINE_REGSTORE store
, BOOL force
)
1098 if (store
->dirty
|| force
)
1099 ret
= CRYPT_RegWriteToReg(store
);
1105 static void WINAPI
CRYPT_RegCloseStore(HCERTSTORE hCertStore
, DWORD dwFlags
)
1107 PWINE_REGSTORE store
= (PWINE_REGSTORE
)hCertStore
;
1109 TRACE("(%p, %08lx)\n", store
, dwFlags
);
1111 FIXME("Unimplemented flags: %08lx\n", dwFlags
);
1113 CRYPT_RegFlushStore(store
, FALSE
);
1114 /* certsToDelete should already be cleared by this point */
1115 store
->memStore
->closeStore(store
->memStore
, 0);
1116 RegCloseKey(store
->key
);
1117 DeleteCriticalSection(&store
->cs
);
1118 HeapFree(GetProcessHeap(), 0, store
);
1121 static BOOL WINAPI
CRYPT_RegAddCert(HCERTSTORE hCertStore
, PCCERT_CONTEXT cert
,
1122 DWORD dwAddDisposition
)
1124 PWINE_REGSTORE store
= (PWINE_REGSTORE
)hCertStore
;
1127 TRACE("(%p, %p, %ld)\n", hCertStore
, cert
, dwAddDisposition
);
1129 if (store
->hdr
.dwOpenFlags
& CERT_STORE_READONLY_FLAG
)
1131 SetLastError(ERROR_ACCESS_DENIED
);
1136 ret
= store
->memStore
->addCert(store
->memStore
, cert
, dwAddDisposition
);
1138 store
->dirty
= TRUE
;
1143 static PWINE_CERT_CONTEXT_REF
CRYPT_RegCreateCertRef(
1144 PWINE_CERT_CONTEXT context
, HCERTSTORE store
)
1146 PWINE_REG_CERT_CONTEXT ret
= HeapAlloc(GetProcessHeap(), 0,
1147 sizeof(WINE_REG_CERT_CONTEXT
));
1151 CRYPT_InitCertRef((PWINE_CERT_CONTEXT_REF
)ret
, context
, store
);
1152 ret
->childContext
= NULL
;
1154 return (PWINE_CERT_CONTEXT_REF
)ret
;
1157 static PWINE_CERT_CONTEXT_REF
CRYPT_RegEnumCert(PWINECRYPT_CERTSTORE store
,
1158 PWINE_CERT_CONTEXT_REF pPrev
)
1160 PWINE_REGSTORE rs
= (PWINE_REGSTORE
)store
;
1161 PWINE_CERT_CONTEXT_REF child
;
1162 PWINE_REG_CERT_CONTEXT prev
= (PWINE_REG_CERT_CONTEXT
)pPrev
, ret
= NULL
;
1164 TRACE("(%p, %p)\n", store
, pPrev
);
1168 child
= rs
->memStore
->enumCert(rs
->memStore
, prev
->childContext
);
1171 ret
= (PWINE_REG_CERT_CONTEXT
)pPrev
;
1172 memcpy(&ret
->cert
, child
, sizeof(WINE_CERT_CONTEXT_REF
));
1173 ret
->cert
.cert
.hCertStore
= (HCERTSTORE
)store
;
1174 InterlockedIncrement(&ret
->cert
.context
->ref
);
1175 ret
->childContext
= child
;
1180 child
= rs
->memStore
->enumCert(rs
->memStore
, NULL
);
1183 ret
= HeapAlloc(GetProcessHeap(), 0, sizeof(WINE_REG_CERT_CONTEXT
));
1187 memcpy(&ret
->cert
, child
, sizeof(WINE_CERT_CONTEXT_REF
));
1188 ret
->cert
.cert
.hCertStore
= (HCERTSTORE
)store
;
1189 InterlockedIncrement(&ret
->cert
.context
->ref
);
1190 ret
->childContext
= child
;
1193 CertFreeCertificateContext((PCCERT_CONTEXT
)child
);
1196 return (PWINE_CERT_CONTEXT_REF
)ret
;
1199 static BOOL WINAPI
CRYPT_RegDeleteCert(HCERTSTORE hCertStore
,
1200 PCCERT_CONTEXT pCertContext
, DWORD dwFlags
)
1202 PWINE_REGSTORE store
= (PWINE_REGSTORE
)hCertStore
;
1205 TRACE("(%p, %p, %08lx)\n", store
, pCertContext
, dwFlags
);
1207 if (store
->hdr
.dwOpenFlags
& CERT_STORE_READONLY_FLAG
)
1209 SetLastError(ERROR_ACCESS_DENIED
);
1214 PWINE_HASH_TO_DELETE toDelete
=
1215 HeapAlloc(GetProcessHeap(), 0, sizeof(WINE_HASH_TO_DELETE
));
1219 DWORD size
= sizeof(toDelete
->hash
);
1221 ret
= CertGetCertificateContextProperty(pCertContext
,
1222 CERT_HASH_PROP_ID
, toDelete
->hash
, &size
);
1225 list_init(&toDelete
->entry
);
1226 EnterCriticalSection(&store
->cs
);
1227 list_add_tail(&store
->certsToDelete
, &toDelete
->entry
);
1228 LeaveCriticalSection(&store
->cs
);
1229 ret
= store
->memStore
->deleteCert(store
->memStore
, pCertContext
,
1233 HeapFree(GetProcessHeap(), 0, toDelete
);
1238 store
->dirty
= TRUE
;
1243 static void CRYPT_RegFreeCert(PWINE_CERT_CONTEXT_REF ref
)
1245 PWINE_REG_CERT_CONTEXT context
= (PWINE_REG_CERT_CONTEXT
)ref
;
1247 TRACE("(%p)\n", ref
);
1249 if (context
->childContext
)
1250 CertFreeCertificateContext((PCCERT_CONTEXT
)context
->childContext
);
1253 static BOOL WINAPI
CRYPT_RegControl(HCERTSTORE hCertStore
, DWORD dwFlags
,
1254 DWORD dwCtrlType
, void const *pvCtrlPara
)
1256 PWINE_REGSTORE store
= (PWINE_REGSTORE
)hCertStore
;
1261 case CERT_STORE_CTRL_RESYNC
:
1262 CRYPT_RegFlushStore(store
, FALSE
);
1263 store
->memStore
->closeStore(store
->memStore
, 0);
1264 store
->memStore
= CRYPT_MemOpenStore(store
->hdr
.cryptProv
,
1265 store
->hdr
.dwOpenFlags
, NULL
);
1266 if (store
->memStore
)
1268 CRYPT_RegReadFromReg(store
);
1274 case CERT_STORE_CTRL_COMMIT
:
1275 ret
= CRYPT_RegFlushStore(store
,
1276 dwFlags
& CERT_STORE_CTRL_COMMIT_FORCE_FLAG
);
1279 FIXME("%ld: stub\n", dwCtrlType
);
1285 /* Copied from shlwapi's SHDeleteKeyW, and reformatted to match this file. */
1286 static DWORD
CRYPT_RecurseDeleteKey(HKEY hKey
, LPCWSTR lpszSubKey
)
1288 DWORD dwRet
, dwKeyCount
= 0, dwMaxSubkeyLen
= 0, dwSize
, i
;
1289 WCHAR szNameBuf
[MAX_PATH
], *lpszName
= szNameBuf
;
1292 TRACE("(hkey=%p,%s)\n", hKey
, debugstr_w(lpszSubKey
));
1294 dwRet
= RegOpenKeyExW(hKey
, lpszSubKey
, 0, KEY_READ
, &hSubKey
);
1297 /* Find how many subkeys there are */
1298 dwRet
= RegQueryInfoKeyW(hSubKey
, NULL
, NULL
, NULL
, &dwKeyCount
,
1299 &dwMaxSubkeyLen
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
1303 if (dwMaxSubkeyLen
> sizeof(szNameBuf
)/sizeof(WCHAR
))
1305 /* Name too big: alloc a buffer for it */
1306 lpszName
= HeapAlloc(GetProcessHeap(), 0,
1307 dwMaxSubkeyLen
*sizeof(WCHAR
));
1311 dwRet
= ERROR_NOT_ENOUGH_MEMORY
;
1314 /* Recursively delete all the subkeys */
1315 for (i
= 0; i
< dwKeyCount
&& !dwRet
; i
++)
1317 dwSize
= dwMaxSubkeyLen
;
1318 dwRet
= RegEnumKeyExW(hSubKey
, i
, lpszName
, &dwSize
, NULL
,
1321 dwRet
= CRYPT_RecurseDeleteKey(hSubKey
, lpszName
);
1324 if (lpszName
!= szNameBuf
)
1326 /* Free buffer if allocated */
1327 HeapFree(GetProcessHeap(), 0, lpszName
);
1332 RegCloseKey(hSubKey
);
1334 dwRet
= RegDeleteKeyW(hKey
, lpszSubKey
);
1339 static WINECRYPT_CERTSTORE
*CRYPT_RegOpenStore(HCRYPTPROV hCryptProv
,
1340 DWORD dwFlags
, const void *pvPara
)
1342 PWINE_REGSTORE store
= NULL
;
1344 TRACE("(%ld, %08lx, %p)\n", hCryptProv
, dwFlags
, pvPara
);
1346 if (dwFlags
& CERT_STORE_DELETE_FLAG
)
1348 DWORD rc
= CRYPT_RecurseDeleteKey((HKEY
)pvPara
, CertsW
);
1350 if (rc
== ERROR_SUCCESS
|| rc
== ERROR_NO_MORE_ITEMS
)
1351 rc
= CRYPT_RecurseDeleteKey((HKEY
)pvPara
, CRLsW
);
1352 if (rc
== ERROR_SUCCESS
|| rc
== ERROR_NO_MORE_ITEMS
)
1353 rc
= CRYPT_RecurseDeleteKey((HKEY
)pvPara
, CTLsW
);
1354 if (rc
== ERROR_NO_MORE_ITEMS
)
1362 if (DuplicateHandle(GetCurrentProcess(), (HANDLE
)pvPara
,
1363 GetCurrentProcess(), (LPHANDLE
)&key
,
1364 dwFlags
& CERT_STORE_READONLY_FLAG
? KEY_READ
: KEY_ALL_ACCESS
,
1367 PWINECRYPT_CERTSTORE memStore
;
1369 memStore
= CRYPT_MemOpenStore(hCryptProv
, dwFlags
, NULL
);
1372 store
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
1373 sizeof(WINE_REGSTORE
));
1376 CRYPT_InitStore(&store
->hdr
, hCryptProv
, dwFlags
,
1378 store
->hdr
.closeStore
= CRYPT_RegCloseStore
;
1379 store
->hdr
.addCert
= CRYPT_RegAddCert
;
1380 store
->hdr
.createCertRef
= CRYPT_RegCreateCertRef
;
1381 store
->hdr
.enumCert
= CRYPT_RegEnumCert
;
1382 store
->hdr
.deleteCert
= CRYPT_RegDeleteCert
;
1383 store
->hdr
.freeCert
= CRYPT_RegFreeCert
;
1384 store
->hdr
.control
= CRYPT_RegControl
;
1385 store
->memStore
= memStore
;
1387 InitializeCriticalSection(&store
->cs
);
1388 list_init(&store
->certsToDelete
);
1389 CRYPT_RegReadFromReg(store
);
1390 store
->dirty
= FALSE
;
1395 TRACE("returning %p\n", store
);
1396 return (WINECRYPT_CERTSTORE
*)store
;
1399 /* FIXME: this isn't complete for the Root store, in which the top-level
1400 * self-signed CA certs reside. Adding a cert to the Root store should present
1401 * the user with a dialog indicating the consequences of doing so, and asking
1402 * the user to confirm whether the cert should be added.
1404 static PWINECRYPT_CERTSTORE
CRYPT_SysRegOpenStoreW(HCRYPTPROV hCryptProv
,
1405 DWORD dwFlags
, const void *pvPara
)
1407 static const WCHAR fmt
[] = { '%','s','\\','%','s',0 };
1408 LPCWSTR storeName
= (LPCWSTR
)pvPara
;
1410 PWINECRYPT_CERTSTORE store
= NULL
;
1415 TRACE("(%ld, %08lx, %s)\n", hCryptProv
, dwFlags
,
1416 debugstr_w((LPCWSTR
)pvPara
));
1420 SetLastError(HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER
));
1425 switch (dwFlags
& CERT_SYSTEM_STORE_LOCATION_MASK
)
1427 case CERT_SYSTEM_STORE_LOCAL_MACHINE
:
1428 root
= HKEY_LOCAL_MACHINE
;
1429 base
= CERT_LOCAL_MACHINE_SYSTEM_STORE_REGPATH
;
1431 case CERT_SYSTEM_STORE_CURRENT_USER
:
1432 root
= HKEY_CURRENT_USER
;
1433 base
= CERT_LOCAL_MACHINE_SYSTEM_STORE_REGPATH
;
1435 case CERT_SYSTEM_STORE_CURRENT_SERVICE
:
1436 /* hklm\Software\Microsoft\Cryptography\Services\servicename\
1437 * SystemCertificates
1439 FIXME("CERT_SYSTEM_STORE_CURRENT_SERVICE, %s: stub\n",
1440 debugstr_w(storeName
));
1442 case CERT_SYSTEM_STORE_SERVICES
:
1443 /* hklm\Software\Microsoft\Cryptography\Services\servicename\
1444 * SystemCertificates
1446 FIXME("CERT_SYSTEM_STORE_SERVICES, %s: stub\n",
1447 debugstr_w(storeName
));
1449 case CERT_SYSTEM_STORE_USERS
:
1450 /* hku\user sid\Software\Microsoft\SystemCertificates */
1451 FIXME("CERT_SYSTEM_STORE_USERS, %s: stub\n",
1452 debugstr_w(storeName
));
1454 case CERT_SYSTEM_STORE_CURRENT_USER_GROUP_POLICY
:
1455 root
= HKEY_CURRENT_USER
;
1456 base
= CERT_GROUP_POLICY_SYSTEM_STORE_REGPATH
;
1458 case CERT_SYSTEM_STORE_LOCAL_MACHINE_GROUP_POLICY
:
1459 root
= HKEY_LOCAL_MACHINE
;
1460 base
= CERT_GROUP_POLICY_SYSTEM_STORE_REGPATH
;
1462 case CERT_SYSTEM_STORE_LOCAL_MACHINE_ENTERPRISE
:
1463 /* hklm\Software\Microsoft\EnterpriseCertificates */
1464 FIXME("CERT_SYSTEM_STORE_LOCAL_MACHINE_ENTERPRISE, %s: stub\n",
1465 debugstr_w(storeName
));
1468 SetLastError(HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER
));
1472 storePath
= HeapAlloc(GetProcessHeap(), 0, (lstrlenW(base
) +
1473 lstrlenW(storeName
) + 2) * sizeof(WCHAR
));
1478 REGSAM sam
= dwFlags
& CERT_STORE_READONLY_FLAG
? KEY_READ
:
1481 wsprintfW(storePath
, fmt
, base
, storeName
);
1482 if (dwFlags
& CERT_STORE_OPEN_EXISTING_FLAG
)
1483 rc
= RegOpenKeyExW(root
, storePath
, 0, sam
, &key
);
1488 rc
= RegCreateKeyExW(root
, storePath
, 0, NULL
, 0, sam
, NULL
,
1490 if (!rc
&& dwFlags
& CERT_STORE_CREATE_NEW_FLAG
&&
1491 disp
== REG_OPENED_EXISTING_KEY
)
1494 rc
= ERROR_FILE_EXISTS
;
1499 store
= CRYPT_RegOpenStore(hCryptProv
, dwFlags
, key
);
1504 HeapFree(GetProcessHeap(), 0, storePath
);
1509 static PWINECRYPT_CERTSTORE
CRYPT_SysRegOpenStoreA(HCRYPTPROV hCryptProv
,
1510 DWORD dwFlags
, const void *pvPara
)
1513 PWINECRYPT_CERTSTORE ret
= NULL
;
1515 TRACE("(%ld, %08lx, %s)\n", hCryptProv
, dwFlags
,
1516 debugstr_a((LPCSTR
)pvPara
));
1520 SetLastError(ERROR_FILE_NOT_FOUND
);
1523 len
= MultiByteToWideChar(CP_ACP
, 0, (LPCSTR
)pvPara
, -1, NULL
, 0);
1526 LPWSTR storeName
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
1530 MultiByteToWideChar(CP_ACP
, 0, (LPCSTR
)pvPara
, -1, storeName
, len
);
1531 ret
= CRYPT_SysRegOpenStoreW(hCryptProv
, dwFlags
, storeName
);
1532 HeapFree(GetProcessHeap(), 0, storeName
);
1538 static PWINECRYPT_CERTSTORE
CRYPT_SysOpenStoreW(HCRYPTPROV hCryptProv
,
1539 DWORD dwFlags
, const void *pvPara
)
1541 HCERTSTORE store
= 0;
1544 TRACE("(%ld, %08lx, %s)\n", hCryptProv
, dwFlags
,
1545 debugstr_w((LPCWSTR
)pvPara
));
1549 SetLastError(ERROR_FILE_NOT_FOUND
);
1552 /* This returns a different error than system registry stores if the
1553 * location is invalid.
1555 switch (dwFlags
& CERT_SYSTEM_STORE_LOCATION_MASK
)
1557 case CERT_SYSTEM_STORE_LOCAL_MACHINE
:
1558 case CERT_SYSTEM_STORE_CURRENT_USER
:
1559 case CERT_SYSTEM_STORE_CURRENT_SERVICE
:
1560 case CERT_SYSTEM_STORE_SERVICES
:
1561 case CERT_SYSTEM_STORE_USERS
:
1562 case CERT_SYSTEM_STORE_CURRENT_USER_GROUP_POLICY
:
1563 case CERT_SYSTEM_STORE_LOCAL_MACHINE_GROUP_POLICY
:
1564 case CERT_SYSTEM_STORE_LOCAL_MACHINE_ENTERPRISE
:
1568 SetLastError(ERROR_FILE_NOT_FOUND
);
1573 HCERTSTORE regStore
= CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY_W
,
1574 0, hCryptProv
, dwFlags
, pvPara
);
1578 store
= CertOpenStore(CERT_STORE_PROV_COLLECTION
, 0, 0,
1579 CERT_STORE_CREATE_NEW_FLAG
, NULL
);
1582 CertAddStoreToCollection(store
, regStore
,
1583 dwFlags
& CERT_STORE_READONLY_FLAG
? 0 :
1584 CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG
, 0);
1585 CertCloseStore(regStore
, 0);
1589 return (PWINECRYPT_CERTSTORE
)store
;
1592 static PWINECRYPT_CERTSTORE
CRYPT_SysOpenStoreA(HCRYPTPROV hCryptProv
,
1593 DWORD dwFlags
, const void *pvPara
)
1596 PWINECRYPT_CERTSTORE ret
= NULL
;
1598 TRACE("(%ld, %08lx, %s)\n", hCryptProv
, dwFlags
,
1599 debugstr_a((LPCSTR
)pvPara
));
1603 SetLastError(ERROR_FILE_NOT_FOUND
);
1606 len
= MultiByteToWideChar(CP_ACP
, 0, (LPCSTR
)pvPara
, -1, NULL
, 0);
1609 LPWSTR storeName
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
1613 MultiByteToWideChar(CP_ACP
, 0, (LPCSTR
)pvPara
, -1, storeName
, len
);
1614 ret
= CRYPT_SysOpenStoreW(hCryptProv
, dwFlags
, storeName
);
1615 HeapFree(GetProcessHeap(), 0, storeName
);
1621 HCERTSTORE WINAPI
CertOpenStore(LPCSTR lpszStoreProvider
,
1622 DWORD dwMsgAndCertEncodingType
, HCRYPTPROV hCryptProv
, DWORD dwFlags
,
1625 WINECRYPT_CERTSTORE
*hcs
;
1626 StoreOpenFunc openFunc
= NULL
;
1628 TRACE("(%s, %08lx, %08lx, %08lx, %p)\n", debugstr_a(lpszStoreProvider
),
1629 dwMsgAndCertEncodingType
, hCryptProv
, dwFlags
, pvPara
);
1631 if (!HIWORD(lpszStoreProvider
))
1633 switch (LOWORD(lpszStoreProvider
))
1635 case (int)CERT_STORE_PROV_MEMORY
:
1636 openFunc
= CRYPT_MemOpenStore
;
1638 case (int)CERT_STORE_PROV_REG
:
1639 openFunc
= CRYPT_RegOpenStore
;
1641 case (int)CERT_STORE_PROV_COLLECTION
:
1642 openFunc
= CRYPT_CollectionOpenStore
;
1644 case (int)CERT_STORE_PROV_SYSTEM_A
:
1645 openFunc
= CRYPT_SysOpenStoreA
;
1647 case (int)CERT_STORE_PROV_SYSTEM_W
:
1648 openFunc
= CRYPT_SysOpenStoreW
;
1650 case (int)CERT_STORE_PROV_SYSTEM_REGISTRY_A
:
1651 openFunc
= CRYPT_SysRegOpenStoreA
;
1653 case (int)CERT_STORE_PROV_SYSTEM_REGISTRY_W
:
1654 openFunc
= CRYPT_SysRegOpenStoreW
;
1657 if (LOWORD(lpszStoreProvider
))
1658 FIXME("unimplemented type %d\n", LOWORD(lpszStoreProvider
));
1661 else if (!strcasecmp(lpszStoreProvider
, sz_CERT_STORE_PROV_MEMORY
))
1662 openFunc
= CRYPT_MemOpenStore
;
1663 else if (!strcasecmp(lpszStoreProvider
, sz_CERT_STORE_PROV_SYSTEM
))
1664 openFunc
= CRYPT_SysOpenStoreW
;
1665 else if (!strcasecmp(lpszStoreProvider
, sz_CERT_STORE_PROV_COLLECTION
))
1666 openFunc
= CRYPT_CollectionOpenStore
;
1667 else if (!strcasecmp(lpszStoreProvider
, sz_CERT_STORE_PROV_SYSTEM_REGISTRY
))
1668 openFunc
= CRYPT_SysRegOpenStoreW
;
1671 FIXME("unimplemented type %s\n", lpszStoreProvider
);
1677 /* FIXME: need to look for an installed provider for this type */
1678 SetLastError(ERROR_FILE_NOT_FOUND
);
1682 hcs
= openFunc(hCryptProv
, dwFlags
, pvPara
);
1683 return (HCERTSTORE
)hcs
;
1686 HCERTSTORE WINAPI
CertOpenSystemStoreA(HCRYPTPROV hProv
,
1687 LPCSTR szSubSystemProtocol
)
1691 if (szSubSystemProtocol
)
1693 int len
= MultiByteToWideChar(CP_ACP
, 0, szSubSystemProtocol
, -1, NULL
,
1695 LPWSTR param
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
1699 MultiByteToWideChar(CP_ACP
, 0, szSubSystemProtocol
, -1, param
, len
);
1700 ret
= CertOpenSystemStoreW(hProv
, param
);
1701 HeapFree(GetProcessHeap(), 0, param
);
1705 SetLastError(HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER
));
1709 HCERTSTORE WINAPI
CertOpenSystemStoreW(HCRYPTPROV hProv
,
1710 LPCWSTR szSubSystemProtocol
)
1714 if (!szSubSystemProtocol
)
1716 SetLastError(HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER
));
1720 /* FIXME: needs some tests. It seems to open both HKEY_LOCAL_MACHINE and
1721 * HKEY_CURRENT_USER stores, but I'm not sure under what conditions, if any,
1724 ret
= CertOpenStore(CERT_STORE_PROV_COLLECTION
, 0, hProv
,
1725 CERT_STORE_CREATE_NEW_FLAG
, NULL
);
1728 HCERTSTORE store
= CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY_W
,
1729 0, hProv
, CERT_SYSTEM_STORE_LOCAL_MACHINE
, szSubSystemProtocol
);
1733 CertAddStoreToCollection(ret
, store
,
1734 CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG
, 0);
1735 CertCloseStore(store
, 0);
1737 store
= CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY_W
,
1738 0, hProv
, CERT_SYSTEM_STORE_CURRENT_USER
, szSubSystemProtocol
);
1741 CertAddStoreToCollection(ret
, store
,
1742 CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG
, 0);
1743 CertCloseStore(store
, 0);
1749 BOOL WINAPI
CertSaveStore(HCERTSTORE hCertStore
, DWORD dwMsgAndCertEncodingType
,
1750 DWORD dwSaveAs
, DWORD dwSaveTo
, void* pvSaveToPara
, DWORD dwFlags
)
1752 FIXME("(%p,%ld,%ld,%ld,%p,%08lx) stub!\n", hCertStore
,
1753 dwMsgAndCertEncodingType
, dwSaveAs
, dwSaveTo
, pvSaveToPara
, dwFlags
);
1757 PCCRL_CONTEXT WINAPI
CertCreateCRLContext( DWORD dwCertEncodingType
,
1758 const BYTE
* pbCrlEncoded
, DWORD cbCrlEncoded
)
1763 TRACE("%08lx %p %08lx\n", dwCertEncodingType
, pbCrlEncoded
, cbCrlEncoded
);
1765 /* FIXME: semi-stub, need to use CryptDecodeObjectEx to decode the CRL. */
1766 pcrl
= HeapAlloc( GetProcessHeap(), 0, sizeof (CRL_CONTEXT
) );
1770 data
= HeapAlloc( GetProcessHeap(), 0, cbCrlEncoded
);
1773 HeapFree( GetProcessHeap(), 0, pcrl
);
1777 pcrl
->dwCertEncodingType
= dwCertEncodingType
;
1778 pcrl
->pbCrlEncoded
= data
;
1779 pcrl
->cbCrlEncoded
= cbCrlEncoded
;
1780 pcrl
->pCrlInfo
= NULL
;
1781 pcrl
->hCertStore
= 0;
1786 /* Decodes the encoded certificate and creates the certificate context for it.
1787 * The reference count is initially zero, so you must create a reference to it
1788 * to avoid leaking memory.
1790 static PWINE_CERT_CONTEXT
CRYPT_CreateCertificateContext(
1791 DWORD dwCertEncodingType
, const BYTE
*pbCertEncoded
, DWORD cbCertEncoded
)
1793 PWINE_CERT_CONTEXT cert
= NULL
;
1795 PCERT_INFO certInfo
= NULL
;
1798 TRACE("(%08lx, %p, %ld)\n", dwCertEncodingType
, pbCertEncoded
,
1801 /* First try to decode it as a signed cert. */
1802 ret
= CryptDecodeObjectEx(X509_ASN_ENCODING
, X509_CERT
, pbCertEncoded
,
1803 cbCertEncoded
, CRYPT_DECODE_ALLOC_FLAG
| CRYPT_DECODE_NOCOPY_FLAG
, NULL
,
1804 (BYTE
*)&certInfo
, &size
);
1805 /* Failing that, try it as an unsigned cert */
1807 ret
= CryptDecodeObjectEx(X509_ASN_ENCODING
, X509_CERT_TO_BE_SIGNED
,
1808 pbCertEncoded
, cbCertEncoded
,
1809 CRYPT_DECODE_ALLOC_FLAG
| CRYPT_DECODE_NOCOPY_FLAG
, NULL
,
1810 (BYTE
*)&certInfo
, &size
);
1815 cert
= HeapAlloc(GetProcessHeap(), 0, sizeof(WINE_CERT_CONTEXT
));
1818 data
= HeapAlloc(GetProcessHeap(), 0, cbCertEncoded
);
1821 HeapFree(GetProcessHeap(), 0, cert
);
1825 memcpy(data
, pbCertEncoded
, cbCertEncoded
);
1826 cert
->cert
.dwCertEncodingType
= dwCertEncodingType
;
1827 cert
->cert
.pbCertEncoded
= data
;
1828 cert
->cert
.cbCertEncoded
= cbCertEncoded
;
1829 cert
->cert
.pCertInfo
= certInfo
;
1830 cert
->cert
.hCertStore
= 0;
1832 InitializeCriticalSection(&cert
->cs
);
1833 list_init(&cert
->extendedProperties
);
1840 static void CRYPT_FreeCert(PWINE_CERT_CONTEXT context
)
1842 PWINE_CERT_PROPERTY prop
, next
;
1844 HeapFree(GetProcessHeap(), 0, context
->cert
.pbCertEncoded
);
1845 LocalFree(context
->cert
.pCertInfo
);
1846 DeleteCriticalSection(&context
->cs
);
1847 LIST_FOR_EACH_ENTRY_SAFE(prop
, next
, &context
->extendedProperties
,
1848 WINE_CERT_PROPERTY
, entry
)
1850 list_remove(&prop
->entry
);
1851 HeapFree(GetProcessHeap(), 0, prop
->pbData
);
1852 HeapFree(GetProcessHeap(), 0, prop
);
1854 HeapFree(GetProcessHeap(), 0, context
);
1857 PCCERT_CONTEXT WINAPI
CertCreateCertificateContext(DWORD dwCertEncodingType
,
1858 const BYTE
*pbCertEncoded
, DWORD cbCertEncoded
)
1860 PWINE_CERT_CONTEXT cert
;
1861 PWINE_CERT_CONTEXT_REF ret
= NULL
;
1863 TRACE("(%08lx, %p, %ld)\n", dwCertEncodingType
, pbCertEncoded
,
1866 cert
= CRYPT_CreateCertificateContext(dwCertEncodingType
, pbCertEncoded
,
1869 ret
= CRYPT_CreateCertRef(cert
, 0);
1870 return (PCCERT_CONTEXT
)ret
;
1873 /* Since the properties are stored in a list, this is a tad inefficient
1874 * (O(n^2)) since I have to find the previous position every time.
1876 DWORD WINAPI
CertEnumCertificateContextProperties(PCCERT_CONTEXT pCertContext
,
1879 PWINE_CERT_CONTEXT_REF ref
= (PWINE_CERT_CONTEXT_REF
)pCertContext
;
1882 TRACE("(%p, %ld)\n", pCertContext
, dwPropId
);
1884 EnterCriticalSection(&ref
->context
->cs
);
1887 PWINE_CERT_PROPERTY cursor
= NULL
;
1889 LIST_FOR_EACH_ENTRY(cursor
, &ref
->context
->extendedProperties
,
1890 WINE_CERT_PROPERTY
, entry
)
1892 if (cursor
->hdr
.propID
== dwPropId
)
1897 if (cursor
->entry
.next
!= &ref
->context
->extendedProperties
)
1898 ret
= LIST_ENTRY(cursor
->entry
.next
, WINE_CERT_PROPERTY
,
1906 else if (!list_empty(&ref
->context
->extendedProperties
))
1907 ret
= LIST_ENTRY(ref
->context
->extendedProperties
.next
,
1908 WINE_CERT_PROPERTY
, entry
)->hdr
.propID
;
1911 LeaveCriticalSection(&ref
->context
->cs
);
1915 static BOOL WINAPI
CRYPT_GetCertificateContextProperty(
1916 PWINE_CERT_CONTEXT context
, DWORD dwPropId
, void *pvData
, DWORD
*pcbData
)
1918 PWINE_CERT_PROPERTY prop
;
1921 TRACE("(%p, %ld, %p, %p)\n", context
, dwPropId
, pvData
, pcbData
);
1923 EnterCriticalSection(&context
->cs
);
1926 LIST_FOR_EACH_ENTRY(prop
, &context
->extendedProperties
,
1927 WINE_CERT_PROPERTY
, entry
)
1929 if (prop
->hdr
.propID
== dwPropId
)
1933 *pcbData
= prop
->hdr
.cb
;
1936 else if (*pcbData
< prop
->hdr
.cb
)
1938 SetLastError(ERROR_MORE_DATA
);
1939 *pcbData
= prop
->hdr
.cb
;
1943 memcpy(pvData
, prop
->pbData
, prop
->hdr
.cb
);
1944 *pcbData
= prop
->hdr
.cb
;
1953 /* Implicit properties */
1956 case CERT_SHA1_HASH_PROP_ID
:
1957 ret
= CryptHashCertificate(0, CALG_SHA1
, 0,
1958 context
->cert
.pbCertEncoded
, context
->cert
.cbCertEncoded
, pvData
,
1962 CRYPT_DATA_BLOB blob
= { *pcbData
, pvData
};
1964 ret
= CRYPT_SetCertificateContextProperty(context
, dwPropId
,
1968 case CERT_KEY_PROV_INFO_PROP_ID
:
1969 case CERT_MD5_HASH_PROP_ID
:
1970 case CERT_SIGNATURE_HASH_PROP_ID
:
1971 case CERT_KEY_IDENTIFIER_PROP_ID
:
1972 case CERT_SUBJECT_PUBLIC_KEY_MD5_HASH_PROP_ID
:
1973 case CERT_ISSUER_SERIAL_NUMBER_MD5_HASH_PROP_ID
:
1974 case CERT_SUBJECT_NAME_MD5_HASH_PROP_ID
:
1975 FIXME("implicit property %ld\n", dwPropId
);
1979 LeaveCriticalSection(&context
->cs
);
1980 TRACE("returning %d\n", ret
);
1984 BOOL WINAPI
CertGetCertificateContextProperty(PCCERT_CONTEXT pCertContext
,
1985 DWORD dwPropId
, void *pvData
, DWORD
*pcbData
)
1987 PWINE_CERT_CONTEXT_REF ref
= (PWINE_CERT_CONTEXT_REF
)pCertContext
;
1990 TRACE("(%p, %ld, %p, %p)\n", pCertContext
, dwPropId
, pvData
, pcbData
);
1992 /* Special cases for invalid/special prop IDs.
1997 case CERT_CERT_PROP_ID
:
1998 case CERT_CRL_PROP_ID
:
1999 case CERT_CTL_PROP_ID
:
2000 SetLastError(HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER
));
2002 case CERT_ACCESS_STATE_PROP_ID
:
2005 *pcbData
= sizeof(DWORD
);
2008 else if (*pcbData
< sizeof(DWORD
))
2010 SetLastError(ERROR_MORE_DATA
);
2011 *pcbData
= sizeof(DWORD
);
2018 if (pCertContext
->hCertStore
)
2020 PWINECRYPT_CERTSTORE store
=
2021 (PWINECRYPT_CERTSTORE
)pCertContext
->hCertStore
;
2023 /* Take advantage of knowledge of the stores to answer the
2024 * access state question
2026 if (store
->type
!= StoreTypeReg
||
2027 !(store
->dwOpenFlags
& CERT_STORE_READONLY_FLAG
))
2028 state
|= CERT_ACCESS_STATE_WRITE_PERSIST_FLAG
;
2030 *(DWORD
*)pvData
= state
;
2035 ret
= CRYPT_GetCertificateContextProperty(ref
->context
, dwPropId
,
2037 TRACE("returning %d\n", ret
);
2041 /* Copies cbData bytes from pbData to the context's property with ID
2044 static BOOL
CRYPT_SaveCertificateContextProperty(PWINE_CERT_CONTEXT context
,
2045 DWORD dwPropId
, const BYTE
*pbData
, size_t cbData
)
2052 data
= HeapAlloc(GetProcessHeap(), 0, cbData
);
2054 memcpy(data
, pbData
, cbData
);
2058 if (!cbData
|| data
)
2060 PWINE_CERT_PROPERTY prop
;
2062 EnterCriticalSection(&context
->cs
);
2063 LIST_FOR_EACH_ENTRY(prop
, &context
->extendedProperties
,
2064 WINE_CERT_PROPERTY
, entry
)
2066 if (prop
->hdr
.propID
== dwPropId
)
2069 if (prop
&& prop
->entry
.next
!= &context
->extendedProperties
)
2071 HeapFree(GetProcessHeap(), 0, prop
->pbData
);
2072 prop
->hdr
.cb
= cbData
;
2073 prop
->pbData
= cbData
? data
: NULL
;
2078 prop
= HeapAlloc(GetProcessHeap(), 0, sizeof(WINE_CERT_PROPERTY
));
2081 prop
->hdr
.propID
= dwPropId
;
2082 prop
->hdr
.unknown
= 1;
2083 prop
->hdr
.cb
= cbData
;
2084 list_init(&prop
->entry
);
2085 prop
->pbData
= cbData
? data
: NULL
;
2086 list_add_tail(&context
->extendedProperties
, &prop
->entry
);
2090 HeapFree(GetProcessHeap(), 0, data
);
2092 LeaveCriticalSection(&context
->cs
);
2097 static BOOL WINAPI
CRYPT_SetCertificateContextProperty(
2098 PWINE_CERT_CONTEXT context
, DWORD dwPropId
, DWORD dwFlags
, const void *pvData
)
2102 TRACE("(%p, %ld, %08lx, %p)\n", context
, dwPropId
, dwFlags
, pvData
);
2106 PWINE_CERT_PROPERTY prop
, next
;
2108 EnterCriticalSection(&context
->cs
);
2109 LIST_FOR_EACH_ENTRY_SAFE(prop
, next
, &context
->extendedProperties
,
2110 WINE_CERT_PROPERTY
, entry
)
2112 if (prop
->hdr
.propID
== dwPropId
)
2114 list_remove(&prop
->entry
);
2115 HeapFree(GetProcessHeap(), 0, prop
->pbData
);
2116 HeapFree(GetProcessHeap(), 0, prop
);
2119 LeaveCriticalSection(&context
->cs
);
2126 case CERT_AUTO_ENROLL_PROP_ID
:
2127 case CERT_CTL_USAGE_PROP_ID
:
2128 case CERT_DESCRIPTION_PROP_ID
:
2129 case CERT_FRIENDLY_NAME_PROP_ID
:
2130 case CERT_HASH_PROP_ID
:
2131 case CERT_KEY_IDENTIFIER_PROP_ID
:
2132 case CERT_MD5_HASH_PROP_ID
:
2133 case CERT_NEXT_UPDATE_LOCATION_PROP_ID
:
2134 case CERT_PUBKEY_ALG_PARA_PROP_ID
:
2135 case CERT_PVK_FILE_PROP_ID
:
2136 case CERT_SIGNATURE_HASH_PROP_ID
:
2137 case CERT_ISSUER_PUBLIC_KEY_MD5_HASH_PROP_ID
:
2138 case CERT_SUBJECT_PUBLIC_KEY_MD5_HASH_PROP_ID
:
2139 case CERT_ENROLLMENT_PROP_ID
:
2140 case CERT_CROSS_CERT_DIST_POINTS_PROP_ID
:
2141 case CERT_RENEWAL_PROP_ID
:
2143 PCRYPT_DATA_BLOB blob
= (PCRYPT_DATA_BLOB
)pvData
;
2145 ret
= CRYPT_SaveCertificateContextProperty(context
, dwPropId
,
2146 blob
->pbData
, blob
->cbData
);
2149 case CERT_DATE_STAMP_PROP_ID
:
2150 ret
= CRYPT_SaveCertificateContextProperty(context
, dwPropId
,
2151 pvData
, sizeof(FILETIME
));
2154 FIXME("%ld: stub\n", dwPropId
);
2157 TRACE("returning %d\n", ret
);
2161 BOOL WINAPI
CertSetCertificateContextProperty(PCCERT_CONTEXT pCertContext
,
2162 DWORD dwPropId
, DWORD dwFlags
, const void *pvData
)
2164 PWINE_CERT_CONTEXT_REF ref
= (PWINE_CERT_CONTEXT_REF
)pCertContext
;
2167 TRACE("(%p, %ld, %08lx, %p)\n", pCertContext
, dwPropId
, dwFlags
, pvData
);
2169 /* Handle special cases for "read-only"/invalid prop IDs. Windows just
2170 * crashes on most of these, I'll be safer.
2175 case CERT_ACCESS_STATE_PROP_ID
:
2176 case CERT_CERT_PROP_ID
:
2177 case CERT_CRL_PROP_ID
:
2178 case CERT_CTL_PROP_ID
:
2179 SetLastError(HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER
));
2182 ret
= CRYPT_SetCertificateContextProperty(ref
->context
, dwPropId
,
2184 TRACE("returning %d\n", ret
);
2188 /* Only the reference portion of the context is duplicated. The returned
2189 * context has the cert store set to 0, to prevent the store's certificate free
2190 * function from getting called on partial data.
2191 * FIXME: is this okay? Needs a test.
2193 PCCERT_CONTEXT WINAPI
CertDuplicateCertificateContext(
2194 PCCERT_CONTEXT pCertContext
)
2196 PWINE_CERT_CONTEXT_REF ref
= (PWINE_CERT_CONTEXT_REF
)pCertContext
, ret
;
2198 TRACE("(%p)\n", pCertContext
);
2201 ret
= HeapAlloc(GetProcessHeap(), 0, sizeof(WINE_CERT_CONTEXT_REF
));
2204 memcpy(ret
, ref
, sizeof(*ret
));
2205 ret
->cert
.hCertStore
= 0;
2206 InterlockedIncrement(&ret
->context
->ref
);
2211 return (PCCERT_CONTEXT
)ret
;
2214 BOOL WINAPI
CertAddCertificateContextToStore(HCERTSTORE hCertStore
,
2215 PCCERT_CONTEXT pCertContext
, DWORD dwAddDisposition
,
2216 PCCERT_CONTEXT
*ppStoreContext
)
2218 PWINECRYPT_CERTSTORE store
= (PWINECRYPT_CERTSTORE
)hCertStore
;
2219 PWINE_CERT_CONTEXT_REF ref
= (PWINE_CERT_CONTEXT_REF
)pCertContext
;
2220 PWINE_CERT_CONTEXT cert
;
2223 TRACE("(%p, %p, %08lx, %p)\n", hCertStore
, pCertContext
,
2224 dwAddDisposition
, ppStoreContext
);
2226 /* FIXME: some tests needed to verify return codes */
2229 SetLastError(ERROR_INVALID_PARAMETER
);
2232 if (store
->dwMagic
!= WINE_CRYPTCERTSTORE_MAGIC
)
2234 SetLastError(ERROR_INVALID_PARAMETER
);
2238 cert
= CRYPT_CreateCertificateContext(ref
->context
->cert
.dwCertEncodingType
,
2239 ref
->context
->cert
.pbCertEncoded
, ref
->context
->cert
.cbCertEncoded
);
2242 PWINE_CERT_PROPERTY prop
;
2245 EnterCriticalSection(&ref
->context
->cs
);
2246 LIST_FOR_EACH_ENTRY(prop
, &ref
->context
->extendedProperties
,
2247 WINE_CERT_PROPERTY
, entry
)
2249 ret
= CRYPT_SaveCertificateContextProperty(cert
, prop
->hdr
.propID
,
2250 prop
->pbData
, prop
->hdr
.cb
);
2254 LeaveCriticalSection(&ref
->context
->cs
);
2257 ret
= store
->addCert(store
, (PCCERT_CONTEXT
)cert
, dwAddDisposition
);
2258 if (ret
&& ppStoreContext
)
2259 *ppStoreContext
= (PCCERT_CONTEXT
)store
->createCertRef(cert
,
2263 CRYPT_FreeCert(cert
);
2270 BOOL WINAPI
CertAddEncodedCertificateToStore(HCERTSTORE hCertStore
,
2271 DWORD dwCertEncodingType
, const BYTE
*pbCertEncoded
, DWORD cbCertEncoded
,
2272 DWORD dwAddDisposition
, PCCERT_CONTEXT
*ppCertContext
)
2274 WINECRYPT_CERTSTORE
*hcs
= (WINECRYPT_CERTSTORE
*)hCertStore
;
2277 TRACE("(%p, %08lx, %p, %ld, %08lx, %p)\n", hCertStore
, dwCertEncodingType
,
2278 pbCertEncoded
, cbCertEncoded
, dwAddDisposition
, ppCertContext
);
2282 else if (hcs
->dwMagic
!= WINE_CRYPTCERTSTORE_MAGIC
)
2286 PWINE_CERT_CONTEXT cert
= CRYPT_CreateCertificateContext(
2287 dwCertEncodingType
, pbCertEncoded
, cbCertEncoded
);
2291 ret
= hcs
->addCert(hcs
, (PCCERT_CONTEXT
)cert
, dwAddDisposition
);
2292 if (ret
&& ppCertContext
)
2293 *ppCertContext
= (PCCERT_CONTEXT
)hcs
->createCertRef(cert
,
2296 CRYPT_FreeCert(cert
);
2304 PCCERT_CONTEXT WINAPI
CertEnumCertificatesInStore(HCERTSTORE hCertStore
,
2305 PCCERT_CONTEXT pPrev
)
2307 WINECRYPT_CERTSTORE
*hcs
= (WINECRYPT_CERTSTORE
*)hCertStore
;
2308 PWINE_CERT_CONTEXT_REF prev
= (PWINE_CERT_CONTEXT_REF
)pPrev
;
2311 TRACE("(%p, %p)\n", hCertStore
, pPrev
);
2314 else if (hcs
->dwMagic
!= WINE_CRYPTCERTSTORE_MAGIC
)
2317 ret
= (PCCERT_CONTEXT
)hcs
->enumCert(hcs
, prev
);
2321 BOOL WINAPI
CertDeleteCertificateFromStore(PCCERT_CONTEXT pCertContext
)
2325 TRACE("(%p)\n", pCertContext
);
2329 else if (!pCertContext
->hCertStore
)
2333 PWINECRYPT_CERTSTORE hcs
=
2334 (PWINECRYPT_CERTSTORE
)pCertContext
->hCertStore
;
2338 else if (hcs
->dwMagic
!= WINE_CRYPTCERTSTORE_MAGIC
)
2341 ret
= hcs
->deleteCert(hcs
, pCertContext
, 0);
2346 BOOL WINAPI
CertAddEncodedCRLToStore(HCERTSTORE hCertStore
,
2347 DWORD dwCertEncodingType
, const BYTE
*pbCrlEncoded
, DWORD cbCrlEncoded
,
2348 DWORD dwAddDisposition
, PCCRL_CONTEXT
*ppCrlContext
)
2350 FIXME("(%p, %08lx, %p, %ld, %08lx, %p): stub\n", hCertStore
,
2351 dwCertEncodingType
, pbCrlEncoded
, cbCrlEncoded
, dwAddDisposition
,
2356 BOOL WINAPI
CertAddCRLContextToStore( HCERTSTORE hCertStore
,
2357 PCCRL_CONTEXT pCrlContext
, DWORD dwAddDisposition
,
2358 PCCRL_CONTEXT
* ppStoreContext
)
2360 FIXME("%p %p %08lx %p\n", hCertStore
, pCrlContext
,
2361 dwAddDisposition
, ppStoreContext
);
2365 BOOL WINAPI
CertFreeCRLContext( PCCRL_CONTEXT pCrlContext
)
2367 FIXME("%p\n", pCrlContext
);
2372 BOOL WINAPI
CertDeleteCRLFromStore(PCCRL_CONTEXT pCrlContext
)
2374 FIXME("(%p): stub\n", pCrlContext
);
2378 PCCRL_CONTEXT WINAPI
CertEnumCRLsInStore(HCERTSTORE hCertStore
,
2379 PCCRL_CONTEXT pPrev
)
2381 FIXME("(%p, %p): stub\n", hCertStore
, pPrev
);
2385 PCCTL_CONTEXT WINAPI
CertCreateCTLContext(DWORD dwCertEncodingType
,
2386 const BYTE
* pbCtlEncoded
, DWORD cbCtlEncoded
)
2388 FIXME("(%08lx, %p, %08lx): stub\n", dwCertEncodingType
, pbCtlEncoded
,
2393 BOOL WINAPI
CertAddEncodedCTLToStore(HCERTSTORE hCertStore
,
2394 DWORD dwMsgAndCertEncodingType
, const BYTE
*pbCtlEncoded
, DWORD cbCtlEncoded
,
2395 DWORD dwAddDisposition
, PCCTL_CONTEXT
*ppCtlContext
)
2397 FIXME("(%p, %08lx, %p, %ld, %08lx, %p): stub\n", hCertStore
,
2398 dwMsgAndCertEncodingType
, pbCtlEncoded
, cbCtlEncoded
, dwAddDisposition
,
2403 BOOL WINAPI
CertAddCTLContextToStore(HCERTSTORE hCertStore
,
2404 PCCTL_CONTEXT pCtlContext
, DWORD dwAddDisposition
,
2405 PCCTL_CONTEXT
* ppStoreContext
)
2407 FIXME("(%p, %p, %08lx, %p): stub\n", hCertStore
, pCtlContext
,
2408 dwAddDisposition
, ppStoreContext
);
2412 BOOL WINAPI
CertFreeCTLContext(PCCTL_CONTEXT pCtlContext
)
2414 FIXME("(%p): stub\n", pCtlContext
);
2418 BOOL WINAPI
CertDeleteCTLFromStore(PCCTL_CONTEXT pCtlContext
)
2420 FIXME("(%p): stub\n", pCtlContext
);
2424 PCCTL_CONTEXT WINAPI
CertEnumCTLsInStore(HCERTSTORE hCertStore
,
2425 PCCTL_CONTEXT pPrev
)
2427 FIXME("(%p, %p): stub\n", hCertStore
, pPrev
);
2432 BOOL WINAPI
CertCloseStore(HCERTSTORE hCertStore
, DWORD dwFlags
)
2434 WINECRYPT_CERTSTORE
*hcs
= (WINECRYPT_CERTSTORE
*) hCertStore
;
2436 TRACE("(%p, %08lx)\n", hCertStore
, dwFlags
);
2441 if ( hcs
->dwMagic
!= WINE_CRYPTCERTSTORE_MAGIC
)
2444 if (InterlockedDecrement(&hcs
->ref
) == 0)
2446 TRACE("freeing %p\n", hcs
);
2448 if (!(hcs
->dwOpenFlags
& CERT_STORE_NO_CRYPT_RELEASE_FLAG
))
2449 CryptReleaseContext(hcs
->cryptProv
, 0);
2450 hcs
->closeStore(hcs
, dwFlags
);
2453 TRACE("%p's ref count is %ld\n", hcs
, hcs
->ref
);
2457 BOOL WINAPI
CertControlStore(HCERTSTORE hCertStore
, DWORD dwFlags
,
2458 DWORD dwCtrlType
, void const *pvCtrlPara
)
2460 WINECRYPT_CERTSTORE
*hcs
= (WINECRYPT_CERTSTORE
*)hCertStore
;
2463 TRACE("(%p, %08lx, %ld, %p)\n", hCertStore
, dwFlags
, dwCtrlType
,
2468 else if (hcs
->dwMagic
!= WINE_CRYPTCERTSTORE_MAGIC
)
2473 ret
= hcs
->control(hCertStore
, dwFlags
, dwCtrlType
, pvCtrlPara
);
2480 BOOL WINAPI
CertGetCRLContextProperty(PCCRL_CONTEXT pCRLContext
,
2481 DWORD dwPropId
, void *pvData
, DWORD
*pcbData
)
2483 FIXME("(%p, %ld, %p, %p): stub\n", pCRLContext
, dwPropId
, pvData
, pcbData
);
2487 BOOL WINAPI
CertSetCRLContextProperty(PCCRL_CONTEXT pCRLContext
,
2488 DWORD dwPropId
, DWORD dwFlags
, const void *pvData
)
2490 FIXME("(%p, %ld, %08lx, %p): stub\n", pCRLContext
, dwPropId
, dwFlags
,
2495 BOOL WINAPI
CertSerializeCRLStoreElement(PCCRL_CONTEXT pCrlContext
,
2496 DWORD dwFlags
, BYTE
*pbElement
, DWORD
*pcbElement
)
2498 FIXME("(%p, %08lx, %p, %p): stub\n", pCrlContext
, dwFlags
, pbElement
,
2503 BOOL WINAPI
CertGetCTLContextProperty(PCCTL_CONTEXT pCTLContext
,
2504 DWORD dwPropId
, void *pvData
, DWORD
*pcbData
)
2506 FIXME("(%p, %ld, %p, %p): stub\n", pCTLContext
, dwPropId
, pvData
, pcbData
);
2510 BOOL WINAPI
CertSetCTLContextProperty(PCCTL_CONTEXT pCTLContext
,
2511 DWORD dwPropId
, DWORD dwFlags
, const void *pvData
)
2513 FIXME("(%p, %ld, %08lx, %p): stub\n", pCTLContext
, dwPropId
, dwFlags
,
2518 BOOL WINAPI
CertSerializeCTLStoreElement(PCCTL_CONTEXT pCtlContext
,
2519 DWORD dwFlags
, BYTE
*pbElement
, DWORD
*pcbElement
)
2521 FIXME("(%p, %08lx, %p, %p): stub\n", pCtlContext
, dwFlags
, pbElement
,
2526 BOOL WINAPI
CertSerializeCertificateStoreElement(PCCERT_CONTEXT pCertContext
,
2527 DWORD dwFlags
, BYTE
*pbElement
, DWORD
*pcbElement
)
2531 TRACE("(%p, %08lx, %p, %p)\n", pCertContext
, dwFlags
, pbElement
,
2536 PWINE_CERT_CONTEXT_REF ref
= (PWINE_CERT_CONTEXT_REF
)pCertContext
;
2537 DWORD bytesNeeded
= sizeof(WINE_CERT_PROP_HEADER
) +
2538 pCertContext
->cbCertEncoded
;
2539 PWINE_CERT_PROPERTY prop
;
2541 EnterCriticalSection(&ref
->context
->cs
);
2542 LIST_FOR_EACH_ENTRY(prop
, &ref
->context
->extendedProperties
,
2543 WINE_CERT_PROPERTY
, entry
)
2544 bytesNeeded
+= sizeof(WINE_CERT_PROP_HEADER
) + prop
->hdr
.cb
;
2547 *pcbElement
= bytesNeeded
;
2550 else if (*pcbElement
< bytesNeeded
)
2552 *pcbElement
= bytesNeeded
;
2553 SetLastError(ERROR_MORE_DATA
);
2558 PWINE_CERT_PROP_HEADER hdr
;
2560 LIST_FOR_EACH_ENTRY(prop
, &ref
->context
->extendedProperties
,
2561 WINE_CERT_PROPERTY
, entry
)
2563 memcpy(pbElement
, &prop
->hdr
, sizeof(WINE_CERT_PROP_HEADER
));
2564 pbElement
+= sizeof(WINE_CERT_PROP_HEADER
);
2567 memcpy(pbElement
, prop
->pbData
, prop
->hdr
.cb
);
2568 pbElement
+= prop
->hdr
.cb
;
2571 hdr
= (PWINE_CERT_PROP_HEADER
)pbElement
;
2572 hdr
->propID
= CERT_CERT_PROP_ID
;
2574 hdr
->cb
= pCertContext
->cbCertEncoded
;
2575 memcpy(pbElement
+ sizeof(WINE_CERT_PROP_HEADER
),
2576 pCertContext
->pbCertEncoded
, pCertContext
->cbCertEncoded
);
2579 LeaveCriticalSection(&ref
->context
->cs
);
2586 /* Looks for the property with ID propID in the buffer buf. Returns a pointer
2587 * to its header if a valid header is found, NULL if not. Valid means the
2588 * length of thte property won't overrun buf, and the unknown field is 1.
2590 static const WINE_CERT_PROP_HEADER
*CRYPT_findPropID(const BYTE
*buf
,
2591 DWORD size
, DWORD propID
)
2593 const WINE_CERT_PROP_HEADER
*ret
= NULL
;
2596 while (size
&& !ret
&& !done
)
2598 if (size
< sizeof(WINE_CERT_PROP_HEADER
))
2600 SetLastError(CRYPT_E_FILE_ERROR
);
2605 const WINE_CERT_PROP_HEADER
*hdr
=
2606 (const WINE_CERT_PROP_HEADER
*)buf
;
2608 size
-= sizeof(WINE_CERT_PROP_HEADER
);
2609 buf
+= sizeof(WINE_CERT_PROP_HEADER
);
2612 SetLastError(HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER
));
2615 else if (!hdr
->propID
)
2617 /* assume a zero prop ID means the data are uninitialized, so
2622 else if (hdr
->unknown
!= 1)
2624 SetLastError(ERROR_FILE_NOT_FOUND
);
2627 else if (hdr
->propID
== propID
)
2639 static const void * WINAPI
CRYPT_ReadSerializedElement(const BYTE
*pbElement
,
2640 DWORD cbElement
, DWORD dwContextTypeFlags
, DWORD
*pdwContentType
)
2642 const void *context
;
2644 TRACE("(%p, %ld, %08lx, %p)\n", pbElement
, cbElement
, dwContextTypeFlags
,
2649 SetLastError(ERROR_END_OF_MEDIA
);
2655 const WINE_CONTEXT_INTERFACE
*contextInterface
= NULL
;
2656 const WINE_CERT_PROP_HEADER
*hdr
= NULL
;
2662 if (dwContextTypeFlags
== CERT_STORE_ALL_CONTEXT_FLAG
)
2664 hdr
= CRYPT_findPropID(pbElement
, cbElement
, CERT_CERT_PROP_ID
);
2666 type
= CERT_STORE_CERTIFICATE_CONTEXT
;
2669 hdr
= CRYPT_findPropID(pbElement
, cbElement
, CERT_CRL_PROP_ID
);
2671 type
= CERT_STORE_CRL_CONTEXT
;
2674 hdr
= CRYPT_findPropID(pbElement
, cbElement
,
2677 type
= CERT_STORE_CTL_CONTEXT
;
2681 else if (dwContextTypeFlags
& CERT_STORE_CERTIFICATE_CONTEXT_FLAG
)
2683 hdr
= CRYPT_findPropID(pbElement
, cbElement
, CERT_CERT_PROP_ID
);
2684 type
= CERT_STORE_CERTIFICATE_CONTEXT
;
2686 else if (dwContextTypeFlags
& CERT_STORE_CRL_CONTEXT_FLAG
)
2688 hdr
= CRYPT_findPropID(pbElement
, cbElement
, CERT_CRL_PROP_ID
);
2689 type
= CERT_STORE_CRL_CONTEXT
;
2691 else if (dwContextTypeFlags
& CERT_STORE_CTL_CONTEXT_FLAG
)
2693 hdr
= CRYPT_findPropID(pbElement
, cbElement
, CERT_CTL_PROP_ID
);
2694 type
= CERT_STORE_CTL_CONTEXT
;
2699 case CERT_STORE_CERTIFICATE_CONTEXT
:
2700 contextInterface
= &gCertInterface
;
2702 case CERT_STORE_CRL_CONTEXT
:
2703 contextInterface
= &gCRLInterface
;
2705 case CERT_STORE_CTL_CONTEXT
:
2706 contextInterface
= &gCTLInterface
;
2709 SetLastError(HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER
));
2716 context
= contextInterface
->create(X509_ASN_ENCODING
,
2717 (BYTE
*)hdr
+ sizeof(WINE_CERT_PROP_HEADER
), hdr
->cb
);
2720 BOOL noMoreProps
= FALSE
;
2722 while (!noMoreProps
&& ret
)
2724 if (cbElement
< sizeof(WINE_CERT_PROP_HEADER
))
2728 const WINE_CERT_PROP_HEADER
*hdr
=
2729 (const WINE_CERT_PROP_HEADER
*)pbElement
;
2731 TRACE("prop is %ld\n", hdr
->propID
);
2732 cbElement
-= sizeof(WINE_CERT_PROP_HEADER
);
2733 pbElement
+= sizeof(WINE_CERT_PROP_HEADER
);
2734 if (cbElement
< hdr
->cb
)
2736 SetLastError(HRESULT_FROM_WIN32(
2737 ERROR_INVALID_PARAMETER
));
2740 else if (!hdr
->propID
)
2742 /* Like in CRYPT_findPropID, stop if the propID is zero
2746 else if (hdr
->unknown
!= 1)
2748 SetLastError(ERROR_FILE_NOT_FOUND
);
2751 else if (hdr
->propID
!= CERT_CERT_PROP_ID
&&
2752 hdr
->propID
!= CERT_CRL_PROP_ID
&& hdr
->propID
!=
2755 /* Have to create a blob for most types, but not
2758 switch (hdr
->propID
)
2760 case CERT_AUTO_ENROLL_PROP_ID
:
2761 case CERT_CTL_USAGE_PROP_ID
:
2762 case CERT_DESCRIPTION_PROP_ID
:
2763 case CERT_FRIENDLY_NAME_PROP_ID
:
2764 case CERT_HASH_PROP_ID
:
2765 case CERT_KEY_IDENTIFIER_PROP_ID
:
2766 case CERT_MD5_HASH_PROP_ID
:
2767 case CERT_NEXT_UPDATE_LOCATION_PROP_ID
:
2768 case CERT_PUBKEY_ALG_PARA_PROP_ID
:
2769 case CERT_PVK_FILE_PROP_ID
:
2770 case CERT_SIGNATURE_HASH_PROP_ID
:
2771 case CERT_ISSUER_PUBLIC_KEY_MD5_HASH_PROP_ID
:
2772 case CERT_SUBJECT_PUBLIC_KEY_MD5_HASH_PROP_ID
:
2773 case CERT_ENROLLMENT_PROP_ID
:
2774 case CERT_CROSS_CERT_DIST_POINTS_PROP_ID
:
2775 case CERT_RENEWAL_PROP_ID
:
2777 CRYPT_DATA_BLOB blob
= { hdr
->cb
,
2778 (LPBYTE
)pbElement
};
2780 ret
= contextInterface
->setProp(context
,
2781 hdr
->propID
, 0, &blob
);
2784 case CERT_DATE_STAMP_PROP_ID
:
2785 ret
= contextInterface
->setProp(context
,
2786 hdr
->propID
, 0, pbElement
);
2789 FIXME("prop ID %ld: stub\n", hdr
->propID
);
2792 pbElement
+= hdr
->cb
;
2793 cbElement
-= hdr
->cb
;
2801 *pdwContentType
= type
;
2805 contextInterface
->free(context
);
2810 __EXCEPT(page_fault
)
2812 SetLastError(STATUS_ACCESS_VIOLATION
);
2819 BOOL WINAPI
CertAddSerializedElementToStore(HCERTSTORE hCertStore
,
2820 const BYTE
*pbElement
, DWORD cbElement
, DWORD dwAddDisposition
, DWORD dwFlags
,
2821 DWORD dwContextTypeFlags
, DWORD
*pdwContentType
, const void **ppvContext
)
2823 const void *context
;
2827 TRACE("(%p, %p, %ld, %08lx, %08lx, %08lx, %p, %p)\n", hCertStore
,
2828 pbElement
, cbElement
, dwAddDisposition
, dwFlags
, dwContextTypeFlags
,
2829 pdwContentType
, ppvContext
);
2831 /* Call the internal function, then delete the hashes. Tests show this
2832 * function uses real hash values, not whatever's stored in the hash
2835 context
= CRYPT_ReadSerializedElement(pbElement
, cbElement
,
2836 dwContextTypeFlags
, &type
);
2839 const WINE_CONTEXT_INTERFACE
*contextInterface
= NULL
;
2843 case CERT_STORE_CERTIFICATE_CONTEXT
:
2844 contextInterface
= &gCertInterface
;
2846 case CERT_STORE_CRL_CONTEXT
:
2847 contextInterface
= &gCRLInterface
;
2849 case CERT_STORE_CTL_CONTEXT
:
2850 contextInterface
= &gCTLInterface
;
2853 SetLastError(HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER
));
2855 if (contextInterface
)
2857 contextInterface
->setProp(context
, CERT_HASH_PROP_ID
, 0, NULL
);
2858 contextInterface
->setProp(context
, CERT_MD5_HASH_PROP_ID
, 0, NULL
);
2859 contextInterface
->setProp(context
, CERT_SIGNATURE_HASH_PROP_ID
, 0,
2862 *pdwContentType
= type
;
2863 ret
= contextInterface
->addContextToStore(hCertStore
, context
,
2864 dwAddDisposition
, ppvContext
);
2865 contextInterface
->free(context
);
2875 BOOL WINAPI
CertFreeCertificateContext(PCCERT_CONTEXT pCertContext
)
2877 TRACE("(%p)\n", pCertContext
);
2881 PWINE_CERT_CONTEXT_REF ref
= (PWINE_CERT_CONTEXT_REF
)pCertContext
;
2882 PWINECRYPT_CERTSTORE store
= (PWINECRYPT_CERTSTORE
)ref
->cert
.hCertStore
;
2884 if (InterlockedDecrement(&ref
->context
->ref
) == 0)
2886 TRACE("freeing %p\n", ref
->context
);
2887 CRYPT_FreeCert(ref
->context
);
2890 TRACE("%p's ref count is %ld\n", ref
->context
,
2892 if (store
&& store
->dwMagic
== WINE_CRYPTCERTSTORE_MAGIC
&&
2894 store
->freeCert(ref
);
2895 HeapFree(GetProcessHeap(), 0, ref
);
2900 PCCERT_CONTEXT WINAPI
CertFindCertificateInStore(HCERTSTORE hCertStore
,
2901 DWORD dwCertEncodingType
, DWORD dwFlags
, DWORD dwType
,
2902 const void *pvPara
, PCCERT_CONTEXT pPrevCertContext
)
2904 FIXME("stub: %p %ld %ld %ld %p %p\n", hCertStore
, dwCertEncodingType
,
2905 dwFlags
, dwType
, pvPara
, pPrevCertContext
);
2906 SetLastError(CRYPT_E_NOT_FOUND
);
2910 BOOL WINAPI
CertAddStoreToCollection(HCERTSTORE hCollectionStore
,
2911 HCERTSTORE hSiblingStore
, DWORD dwUpdateFlags
, DWORD dwPriority
)
2913 PWINE_COLLECTIONSTORE collection
= (PWINE_COLLECTIONSTORE
)hCollectionStore
;
2914 WINECRYPT_CERTSTORE
*sibling
= (WINECRYPT_CERTSTORE
*)hSiblingStore
;
2915 PWINE_STORE_LIST_ENTRY entry
;
2918 TRACE("(%p, %p, %08lx, %ld)\n", hCollectionStore
, hSiblingStore
,
2919 dwUpdateFlags
, dwPriority
);
2921 if (!collection
|| !sibling
)
2923 if (collection
->hdr
.dwMagic
!= WINE_CRYPTCERTSTORE_MAGIC
)
2925 SetLastError(HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER
));
2928 if (collection
->hdr
.type
!= StoreTypeCollection
)
2930 SetLastError(HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER
));
2933 if (sibling
->dwMagic
!= WINE_CRYPTCERTSTORE_MAGIC
)
2935 SetLastError(HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER
));
2939 entry
= HeapAlloc(GetProcessHeap(), 0, sizeof(WINE_STORE_LIST_ENTRY
));
2942 InterlockedIncrement(&sibling
->ref
);
2943 TRACE("sibling %p's ref count is %ld\n", sibling
, sibling
->ref
);
2944 entry
->store
= sibling
;
2945 entry
->dwUpdateFlags
= dwUpdateFlags
;
2946 entry
->dwPriority
= dwPriority
;
2947 list_init(&entry
->entry
);
2948 TRACE("%p: adding %p, priority %ld\n", collection
, entry
, dwPriority
);
2949 EnterCriticalSection(&collection
->cs
);
2952 PWINE_STORE_LIST_ENTRY cursor
;
2955 LIST_FOR_EACH_ENTRY(cursor
, &collection
->stores
,
2956 WINE_STORE_LIST_ENTRY
, entry
)
2958 if (cursor
->dwPriority
< dwPriority
)
2960 list_add_before(&cursor
->entry
, &entry
->entry
);
2966 list_add_tail(&collection
->stores
, &entry
->entry
);
2969 list_add_tail(&collection
->stores
, &entry
->entry
);
2970 LeaveCriticalSection(&collection
->cs
);
2978 void WINAPI
CertRemoveStoreFromCollection(HCERTSTORE hCollectionStore
,
2979 HCERTSTORE hSiblingStore
)
2981 PWINE_COLLECTIONSTORE collection
= (PWINE_COLLECTIONSTORE
)hCollectionStore
;
2982 WINECRYPT_CERTSTORE
*sibling
= (WINECRYPT_CERTSTORE
*)hSiblingStore
;
2983 PWINE_STORE_LIST_ENTRY store
, next
;
2985 TRACE("(%p, %p)\n", hCollectionStore
, hSiblingStore
);
2987 if (!collection
|| !sibling
)
2989 if (collection
->hdr
.dwMagic
!= WINE_CRYPTCERTSTORE_MAGIC
)
2991 SetLastError(HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER
));
2994 if (collection
->hdr
.type
!= StoreTypeCollection
)
2996 if (sibling
->dwMagic
!= WINE_CRYPTCERTSTORE_MAGIC
)
2998 SetLastError(HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER
));
3001 EnterCriticalSection(&collection
->cs
);
3002 LIST_FOR_EACH_ENTRY_SAFE(store
, next
, &collection
->stores
,
3003 WINE_STORE_LIST_ENTRY
, entry
)
3005 if (store
->store
== sibling
)
3007 list_remove(&store
->entry
);
3008 CertCloseStore(store
->store
, 0);
3009 HeapFree(GetProcessHeap(), 0, store
);
3013 LeaveCriticalSection(&collection
->cs
);
3016 PCRYPT_ATTRIBUTE WINAPI
CertFindAttribute(LPCSTR pszObjId
, DWORD cAttr
,
3017 CRYPT_ATTRIBUTE rgAttr
[])
3019 PCRYPT_ATTRIBUTE ret
= NULL
;
3022 TRACE("%s %ld %p\n", debugstr_a(pszObjId
), cAttr
, rgAttr
);
3028 SetLastError(ERROR_INVALID_PARAMETER
);
3032 for (i
= 0; !ret
&& i
< cAttr
; i
++)
3033 if (rgAttr
[i
].pszObjId
&& !strcmp(pszObjId
, rgAttr
[i
].pszObjId
))
3038 PCERT_EXTENSION WINAPI
CertFindExtension(LPCSTR pszObjId
, DWORD cExtensions
,
3039 CERT_EXTENSION rgExtensions
[])
3041 PCERT_EXTENSION ret
= NULL
;
3044 TRACE("%s %ld %p\n", debugstr_a(pszObjId
), cExtensions
, rgExtensions
);
3050 SetLastError(ERROR_INVALID_PARAMETER
);
3054 for (i
= 0; !ret
&& i
< cExtensions
; i
++)
3055 if (rgExtensions
[i
].pszObjId
&& !strcmp(pszObjId
,
3056 rgExtensions
[i
].pszObjId
))
3057 ret
= &rgExtensions
[i
];
3061 PCERT_RDN_ATTR WINAPI
CertFindRDNAttr(LPCSTR pszObjId
, PCERT_NAME_INFO pName
)
3063 PCERT_RDN_ATTR ret
= NULL
;
3066 TRACE("%s %p\n", debugstr_a(pszObjId
), pName
);
3070 SetLastError(ERROR_INVALID_PARAMETER
);
3074 for (i
= 0; !ret
&& i
< pName
->cRDN
; i
++)
3075 for (j
= 0; !ret
&& j
< pName
->rgRDN
[i
].cRDNAttr
; j
++)
3076 if (pName
->rgRDN
[i
].rgRDNAttr
[j
].pszObjId
&& !strcmp(pszObjId
,
3077 pName
->rgRDN
[i
].rgRDNAttr
[j
].pszObjId
))
3078 ret
= &pName
->rgRDN
[i
].rgRDNAttr
[j
];
3082 LONG WINAPI
CertVerifyTimeValidity(LPFILETIME pTimeToVerify
,
3083 PCERT_INFO pCertInfo
)
3092 GetSystemTime(&sysTime
);
3093 SystemTimeToFileTime(&sysTime
, &fileTime
);
3094 pTimeToVerify
= &fileTime
;
3096 if ((ret
= CompareFileTime(pTimeToVerify
, &pCertInfo
->NotBefore
)) >= 0)
3098 ret
= CompareFileTime(pTimeToVerify
, &pCertInfo
->NotAfter
);
3105 BOOL WINAPI
CryptHashCertificate(HCRYPTPROV hCryptProv
, ALG_ID Algid
,
3106 DWORD dwFlags
, const BYTE
*pbEncoded
, DWORD cbEncoded
, BYTE
*pbComputedHash
,
3107 DWORD
*pcbComputedHash
)
3110 HCRYPTHASH hHash
= 0;
3112 TRACE("(%ld, %d, %08lx, %p, %ld, %p, %p)\n", hCryptProv
, Algid
, dwFlags
,
3113 pbEncoded
, cbEncoded
, pbComputedHash
, pcbComputedHash
);
3116 hCryptProv
= CRYPT_GetDefaultProvider();
3121 ret
= CryptCreateHash(hCryptProv
, Algid
, 0, 0, &hHash
);
3124 ret
= CryptHashData(hHash
, pbEncoded
, cbEncoded
, 0);
3126 ret
= CryptGetHashParam(hHash
, HP_HASHVAL
, pbComputedHash
,
3127 pcbComputedHash
, 0);
3128 CryptDestroyHash(hHash
);