winhttp: Get rid of send_request_t.
[wine.git] / dlls / crypt32 / store.c
blob2b8ea1d5d82aab48dc587a254af6f61661d25143
1 /*
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
19 * FIXME:
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.
26 #include "config.h"
27 #include "wine/port.h"
29 #include <assert.h>
30 #include <stdarg.h>
31 #include "windef.h"
32 #include "winbase.h"
33 #include "winnls.h"
34 #include "winreg.h"
35 #include "winuser.h"
36 #include "wincrypt.h"
37 #include "wine/debug.h"
38 #include "wine/exception.h"
39 #include "crypt32_private.h"
41 WINE_DEFAULT_DEBUG_CHANNEL(crypt);
43 static const WINE_CONTEXT_INTERFACE gCertInterface = {
44 (CreateContextFunc)CertCreateCertificateContext,
45 (AddContextToStoreFunc)CertAddCertificateContextToStore,
46 (AddEncodedContextToStoreFunc)CertAddEncodedCertificateToStore,
47 (EnumContextsInStoreFunc)CertEnumCertificatesInStore,
48 (EnumPropertiesFunc)CertEnumCertificateContextProperties,
49 (GetContextPropertyFunc)CertGetCertificateContextProperty,
50 (SetContextPropertyFunc)CertSetCertificateContextProperty,
51 (SerializeElementFunc)CertSerializeCertificateStoreElement,
52 (DeleteContextFunc)CertDeleteCertificateFromStore,
54 const WINE_CONTEXT_INTERFACE *pCertInterface = &gCertInterface;
56 static const WINE_CONTEXT_INTERFACE gCRLInterface = {
57 (CreateContextFunc)CertCreateCRLContext,
58 (AddContextToStoreFunc)CertAddCRLContextToStore,
59 (AddEncodedContextToStoreFunc)CertAddEncodedCRLToStore,
60 (EnumContextsInStoreFunc)CertEnumCRLsInStore,
61 (EnumPropertiesFunc)CertEnumCRLContextProperties,
62 (GetContextPropertyFunc)CertGetCRLContextProperty,
63 (SetContextPropertyFunc)CertSetCRLContextProperty,
64 (SerializeElementFunc)CertSerializeCRLStoreElement,
65 (DeleteContextFunc)CertDeleteCRLFromStore,
67 const WINE_CONTEXT_INTERFACE *pCRLInterface = &gCRLInterface;
69 static const WINE_CONTEXT_INTERFACE gCTLInterface = {
70 (CreateContextFunc)CertCreateCTLContext,
71 (AddContextToStoreFunc)CertAddCTLContextToStore,
72 (AddEncodedContextToStoreFunc)CertAddEncodedCTLToStore,
73 (EnumContextsInStoreFunc)CertEnumCTLsInStore,
74 (EnumPropertiesFunc)CertEnumCTLContextProperties,
75 (GetContextPropertyFunc)CertGetCTLContextProperty,
76 (SetContextPropertyFunc)CertSetCTLContextProperty,
77 (SerializeElementFunc)CertSerializeCTLStoreElement,
78 (DeleteContextFunc)CertDeleteCTLFromStore,
80 const WINE_CONTEXT_INTERFACE *pCTLInterface = &gCTLInterface;
82 typedef struct _WINE_MEMSTORE
84 WINECRYPT_CERTSTORE hdr;
85 CRITICAL_SECTION cs;
86 struct list certs;
87 struct list crls;
88 struct list ctls;
89 } WINE_MEMSTORE;
91 void CRYPT_InitStore(WINECRYPT_CERTSTORE *store, DWORD dwFlags, CertStoreType type, const store_vtbl_t *vtbl)
93 store->ref = 1;
94 store->dwMagic = WINE_CRYPTCERTSTORE_MAGIC;
95 store->type = type;
96 store->dwOpenFlags = dwFlags;
97 store->vtbl = vtbl;
98 store->properties = NULL;
101 void CRYPT_FreeStore(WINECRYPT_CERTSTORE *store)
103 if (store->properties)
104 ContextPropertyList_Free(store->properties);
105 store->dwMagic = 0;
106 CryptMemFree(store);
109 BOOL WINAPI I_CertUpdateStore(HCERTSTORE store1, HCERTSTORE store2, DWORD unk0,
110 DWORD unk1)
112 static BOOL warned = FALSE;
113 const WINE_CONTEXT_INTERFACE * const interfaces[] = { pCertInterface,
114 pCRLInterface, pCTLInterface };
115 DWORD i;
117 TRACE("(%p, %p, %08x, %08x)\n", store1, store2, unk0, unk1);
118 if (!warned)
120 FIXME("semi-stub\n");
121 warned = TRUE;
124 /* Poor-man's resync: empty first store, then add everything from second
125 * store to it.
127 for (i = 0; i < ARRAY_SIZE(interfaces); i++)
129 const void *context;
131 do {
132 context = interfaces[i]->enumContextsInStore(store1, NULL);
133 if (context)
134 interfaces[i]->deleteFromStore(context);
135 } while (context);
136 do {
137 context = interfaces[i]->enumContextsInStore(store2, context);
138 if (context)
139 interfaces[i]->addContextToStore(store1, context,
140 CERT_STORE_ADD_ALWAYS, NULL);
141 } while (context);
143 return TRUE;
146 static BOOL MemStore_addContext(WINE_MEMSTORE *store, struct list *list, context_t *orig_context,
147 context_t *existing, context_t **ret_context, BOOL use_link)
149 context_t *context;
151 context = orig_context->vtbl->clone(orig_context, &store->hdr, use_link);
152 if (!context)
153 return FALSE;
155 TRACE("adding %p\n", context);
156 EnterCriticalSection(&store->cs);
157 if (existing) {
158 context->u.entry.prev = existing->u.entry.prev;
159 context->u.entry.next = existing->u.entry.next;
160 context->u.entry.prev->next = &context->u.entry;
161 context->u.entry.next->prev = &context->u.entry;
162 list_init(&existing->u.entry);
163 if(!existing->ref)
164 Context_Release(existing);
165 }else {
166 list_add_head(list, &context->u.entry);
168 LeaveCriticalSection(&store->cs);
170 if(ret_context)
171 *ret_context = context;
172 else
173 Context_Release(context);
174 return TRUE;
177 static context_t *MemStore_enumContext(WINE_MEMSTORE *store, struct list *list, context_t *prev)
179 struct list *next;
180 context_t *ret;
182 EnterCriticalSection(&store->cs);
183 if (prev) {
184 next = list_next(list, &prev->u.entry);
185 Context_Release(prev);
186 }else {
187 next = list_next(list, list);
189 LeaveCriticalSection(&store->cs);
191 if (!next) {
192 SetLastError(CRYPT_E_NOT_FOUND);
193 return NULL;
196 ret = LIST_ENTRY(next, context_t, u.entry);
197 Context_AddRef(ret);
198 return ret;
201 static BOOL MemStore_deleteContext(WINE_MEMSTORE *store, context_t *context)
203 BOOL in_list = FALSE;
205 EnterCriticalSection(&store->cs);
206 if (!list_empty(&context->u.entry)) {
207 list_remove(&context->u.entry);
208 list_init(&context->u.entry);
209 in_list = TRUE;
211 LeaveCriticalSection(&store->cs);
213 if(in_list && !context->ref)
214 Context_Free(context);
215 return TRUE;
218 static void free_contexts(struct list *list)
220 context_t *context, *next;
222 LIST_FOR_EACH_ENTRY_SAFE(context, next, list, context_t, u.entry)
224 TRACE("freeing %p\n", context);
225 list_remove(&context->u.entry);
226 Context_Free(context);
230 static void MemStore_releaseContext(WINECRYPT_CERTSTORE *store, context_t *context)
232 /* Free the context only if it's not in a list. Otherwise it may be reused later. */
233 if(list_empty(&context->u.entry))
234 Context_Free(context);
237 static BOOL MemStore_addCert(WINECRYPT_CERTSTORE *store, context_t *cert,
238 context_t *toReplace, context_t **ppStoreContext, BOOL use_link)
240 WINE_MEMSTORE *ms = (WINE_MEMSTORE *)store;
242 TRACE("(%p, %p, %p, %p)\n", store, cert, toReplace, ppStoreContext);
243 return MemStore_addContext(ms, &ms->certs, cert, toReplace, ppStoreContext, use_link);
246 static context_t *MemStore_enumCert(WINECRYPT_CERTSTORE *store, context_t *prev)
248 WINE_MEMSTORE *ms = (WINE_MEMSTORE *)store;
250 TRACE("(%p, %p)\n", store, prev);
252 return MemStore_enumContext(ms, &ms->certs, prev);
255 static BOOL MemStore_deleteCert(WINECRYPT_CERTSTORE *store, context_t *context)
257 WINE_MEMSTORE *ms = (WINE_MEMSTORE *)store;
259 TRACE("(%p, %p)\n", store, context);
261 return MemStore_deleteContext(ms, context);
264 static BOOL MemStore_addCRL(WINECRYPT_CERTSTORE *store, context_t *crl,
265 context_t *toReplace, context_t **ppStoreContext, BOOL use_link)
267 WINE_MEMSTORE *ms = (WINE_MEMSTORE *)store;
269 TRACE("(%p, %p, %p, %p)\n", store, crl, toReplace, ppStoreContext);
271 return MemStore_addContext(ms, &ms->crls, crl, toReplace, ppStoreContext, use_link);
274 static context_t *MemStore_enumCRL(WINECRYPT_CERTSTORE *store, context_t *prev)
276 WINE_MEMSTORE *ms = (WINE_MEMSTORE *)store;
278 TRACE("(%p, %p)\n", store, prev);
280 return MemStore_enumContext(ms, &ms->crls, prev);
283 static BOOL MemStore_deleteCRL(WINECRYPT_CERTSTORE *store, context_t *context)
285 WINE_MEMSTORE *ms = (WINE_MEMSTORE *)store;
287 TRACE("(%p, %p)\n", store, context);
289 return MemStore_deleteContext(ms, context);
292 static BOOL MemStore_addCTL(WINECRYPT_CERTSTORE *store, context_t *ctl,
293 context_t *toReplace, context_t **ppStoreContext, BOOL use_link)
295 WINE_MEMSTORE *ms = (WINE_MEMSTORE *)store;
297 TRACE("(%p, %p, %p, %p)\n", store, ctl, toReplace, ppStoreContext);
299 return MemStore_addContext(ms, &ms->ctls, ctl, toReplace, ppStoreContext, use_link);
302 static context_t *MemStore_enumCTL(WINECRYPT_CERTSTORE *store, context_t *prev)
304 WINE_MEMSTORE *ms = (WINE_MEMSTORE *)store;
306 TRACE("(%p, %p)\n", store, prev);
308 return MemStore_enumContext(ms, &ms->ctls, prev);
311 static BOOL MemStore_deleteCTL(WINECRYPT_CERTSTORE *store, context_t *context)
313 WINE_MEMSTORE *ms = (WINE_MEMSTORE *)store;
315 TRACE("(%p, %p)\n", store, context);
317 return MemStore_deleteContext(ms, context);
320 static void MemStore_addref(WINECRYPT_CERTSTORE *store)
322 LONG ref = InterlockedIncrement(&store->ref);
323 TRACE("ref = %d\n", ref);
326 static DWORD MemStore_release(WINECRYPT_CERTSTORE *cert_store, DWORD flags)
328 WINE_MEMSTORE *store = (WINE_MEMSTORE*)cert_store;
329 LONG ref;
331 if(flags & ~CERT_CLOSE_STORE_CHECK_FLAG)
332 FIXME("Unimplemented flags %x\n", flags);
334 ref = InterlockedDecrement(&store->hdr.ref);
335 TRACE("(%p) ref=%d\n", store, ref);
336 if(ref)
337 return (flags & CERT_CLOSE_STORE_CHECK_FLAG) ? CRYPT_E_PENDING_CLOSE : ERROR_SUCCESS;
339 free_contexts(&store->certs);
340 free_contexts(&store->crls);
341 free_contexts(&store->ctls);
342 store->cs.DebugInfo->Spare[0] = 0;
343 DeleteCriticalSection(&store->cs);
344 CRYPT_FreeStore(&store->hdr);
345 return ERROR_SUCCESS;
348 static BOOL MemStore_control(WINECRYPT_CERTSTORE *store, DWORD dwFlags,
349 DWORD dwCtrlType, void const *pvCtrlPara)
351 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
352 return FALSE;
355 static const store_vtbl_t MemStoreVtbl = {
356 MemStore_addref,
357 MemStore_release,
358 MemStore_releaseContext,
359 MemStore_control,
361 MemStore_addCert,
362 MemStore_enumCert,
363 MemStore_deleteCert
364 }, {
365 MemStore_addCRL,
366 MemStore_enumCRL,
367 MemStore_deleteCRL
368 }, {
369 MemStore_addCTL,
370 MemStore_enumCTL,
371 MemStore_deleteCTL
375 static WINECRYPT_CERTSTORE *CRYPT_MemOpenStore(HCRYPTPROV hCryptProv,
376 DWORD dwFlags, const void *pvPara)
378 WINE_MEMSTORE *store;
380 TRACE("(%ld, %08x, %p)\n", hCryptProv, dwFlags, pvPara);
382 if (dwFlags & CERT_STORE_DELETE_FLAG)
384 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
385 store = NULL;
387 else
389 store = CryptMemAlloc(sizeof(WINE_MEMSTORE));
390 if (store)
392 memset(store, 0, sizeof(WINE_MEMSTORE));
393 CRYPT_InitStore(&store->hdr, dwFlags, StoreTypeMem, &MemStoreVtbl);
394 InitializeCriticalSection(&store->cs);
395 store->cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": ContextList.cs");
396 list_init(&store->certs);
397 list_init(&store->crls);
398 list_init(&store->ctls);
399 /* Mem store doesn't need crypto provider, so close it */
400 if (hCryptProv && !(dwFlags & CERT_STORE_NO_CRYPT_RELEASE_FLAG))
401 CryptReleaseContext(hCryptProv, 0);
404 return (WINECRYPT_CERTSTORE*)store;
407 static const WCHAR rootW[] = { 'R','o','o','t',0 };
409 static WINECRYPT_CERTSTORE *CRYPT_SysRegOpenStoreW(HCRYPTPROV hCryptProv,
410 DWORD dwFlags, const void *pvPara)
412 static const WCHAR fmt[] = { '%','s','\\','%','s',0 };
413 LPCWSTR storeName = pvPara;
414 LPWSTR storePath;
415 WINECRYPT_CERTSTORE *store = NULL;
416 HKEY root;
417 LPCWSTR base;
419 TRACE("(%ld, %08x, %s)\n", hCryptProv, dwFlags,
420 debugstr_w(pvPara));
422 if (!pvPara)
424 SetLastError(E_INVALIDARG);
425 return NULL;
428 switch (dwFlags & CERT_SYSTEM_STORE_LOCATION_MASK)
430 case CERT_SYSTEM_STORE_LOCAL_MACHINE:
431 root = HKEY_LOCAL_MACHINE;
432 base = CERT_LOCAL_MACHINE_SYSTEM_STORE_REGPATH;
433 /* If the HKLM\Root certs are requested, expressing system certs into the registry */
434 if (!lstrcmpiW(storeName, rootW))
435 CRYPT_ImportSystemRootCertsToReg();
436 break;
437 case CERT_SYSTEM_STORE_CURRENT_USER:
438 root = HKEY_CURRENT_USER;
439 base = CERT_LOCAL_MACHINE_SYSTEM_STORE_REGPATH;
440 break;
441 case CERT_SYSTEM_STORE_CURRENT_SERVICE:
442 /* hklm\Software\Microsoft\Cryptography\Services\servicename\
443 * SystemCertificates
445 FIXME("CERT_SYSTEM_STORE_CURRENT_SERVICE, %s: stub\n",
446 debugstr_w(storeName));
447 return NULL;
448 case CERT_SYSTEM_STORE_SERVICES:
449 /* hklm\Software\Microsoft\Cryptography\Services\servicename\
450 * SystemCertificates
452 FIXME("CERT_SYSTEM_STORE_SERVICES, %s: stub\n",
453 debugstr_w(storeName));
454 return NULL;
455 case CERT_SYSTEM_STORE_USERS:
456 /* hku\user sid\Software\Microsoft\SystemCertificates */
457 FIXME("CERT_SYSTEM_STORE_USERS, %s: stub\n",
458 debugstr_w(storeName));
459 return NULL;
460 case CERT_SYSTEM_STORE_CURRENT_USER_GROUP_POLICY:
461 root = HKEY_CURRENT_USER;
462 base = CERT_GROUP_POLICY_SYSTEM_STORE_REGPATH;
463 break;
464 case CERT_SYSTEM_STORE_LOCAL_MACHINE_GROUP_POLICY:
465 root = HKEY_LOCAL_MACHINE;
466 base = CERT_GROUP_POLICY_SYSTEM_STORE_REGPATH;
467 break;
468 case CERT_SYSTEM_STORE_LOCAL_MACHINE_ENTERPRISE:
469 /* hklm\Software\Microsoft\EnterpriseCertificates */
470 FIXME("CERT_SYSTEM_STORE_LOCAL_MACHINE_ENTERPRISE, %s: stub\n",
471 debugstr_w(storeName));
472 return NULL;
473 default:
474 SetLastError(E_INVALIDARG);
475 return NULL;
478 storePath = CryptMemAlloc((lstrlenW(base) + lstrlenW(storeName) + 2) *
479 sizeof(WCHAR));
480 if (storePath)
482 LONG rc;
483 HKEY key;
484 REGSAM sam = dwFlags & CERT_STORE_READONLY_FLAG ? KEY_READ :
485 KEY_ALL_ACCESS;
487 wsprintfW(storePath, fmt, base, storeName);
488 if (dwFlags & CERT_STORE_OPEN_EXISTING_FLAG)
489 rc = RegOpenKeyExW(root, storePath, 0, sam, &key);
490 else
492 DWORD disp;
494 rc = RegCreateKeyExW(root, storePath, 0, NULL, 0, sam, NULL,
495 &key, &disp);
496 if (!rc && dwFlags & CERT_STORE_CREATE_NEW_FLAG &&
497 disp == REG_OPENED_EXISTING_KEY)
499 RegCloseKey(key);
500 rc = ERROR_FILE_EXISTS;
503 if (!rc)
505 store = CRYPT_RegOpenStore(hCryptProv, dwFlags, key);
506 RegCloseKey(key);
508 else
509 SetLastError(rc);
510 CryptMemFree(storePath);
512 return store;
515 static WINECRYPT_CERTSTORE *CRYPT_SysRegOpenStoreA(HCRYPTPROV hCryptProv,
516 DWORD dwFlags, const void *pvPara)
518 int len;
519 WINECRYPT_CERTSTORE *ret = NULL;
521 TRACE("(%ld, %08x, %s)\n", hCryptProv, dwFlags,
522 debugstr_a(pvPara));
524 if (!pvPara)
526 SetLastError(ERROR_FILE_NOT_FOUND);
527 return NULL;
529 len = MultiByteToWideChar(CP_ACP, 0, pvPara, -1, NULL, 0);
530 if (len)
532 LPWSTR storeName = CryptMemAlloc(len * sizeof(WCHAR));
534 if (storeName)
536 MultiByteToWideChar(CP_ACP, 0, pvPara, -1, storeName, len);
537 ret = CRYPT_SysRegOpenStoreW(hCryptProv, dwFlags, storeName);
538 CryptMemFree(storeName);
541 return ret;
544 static WINECRYPT_CERTSTORE *CRYPT_SysOpenStoreW(HCRYPTPROV hCryptProv,
545 DWORD dwFlags, const void *pvPara)
547 HCERTSTORE store = 0;
548 BOOL ret;
550 TRACE("(%ld, %08x, %s)\n", hCryptProv, dwFlags,
551 debugstr_w(pvPara));
553 if (!pvPara)
555 SetLastError(ERROR_FILE_NOT_FOUND);
556 return NULL;
558 /* This returns a different error than system registry stores if the
559 * location is invalid.
561 switch (dwFlags & CERT_SYSTEM_STORE_LOCATION_MASK)
563 case CERT_SYSTEM_STORE_LOCAL_MACHINE:
564 case CERT_SYSTEM_STORE_CURRENT_USER:
565 case CERT_SYSTEM_STORE_CURRENT_SERVICE:
566 case CERT_SYSTEM_STORE_SERVICES:
567 case CERT_SYSTEM_STORE_USERS:
568 case CERT_SYSTEM_STORE_CURRENT_USER_GROUP_POLICY:
569 case CERT_SYSTEM_STORE_LOCAL_MACHINE_GROUP_POLICY:
570 case CERT_SYSTEM_STORE_LOCAL_MACHINE_ENTERPRISE:
571 ret = TRUE;
572 break;
573 default:
574 SetLastError(ERROR_FILE_NOT_FOUND);
575 ret = FALSE;
577 if (ret)
579 HCERTSTORE regStore = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY_W,
580 0, 0, dwFlags, pvPara);
582 if (regStore)
584 store = CertOpenStore(CERT_STORE_PROV_COLLECTION, 0, 0,
585 CERT_STORE_CREATE_NEW_FLAG, NULL);
586 CertAddStoreToCollection(store, regStore,
587 dwFlags & CERT_STORE_READONLY_FLAG ? 0 :
588 CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
589 CertCloseStore(regStore, 0);
590 /* CERT_SYSTEM_STORE_CURRENT_USER returns both the HKCU and HKLM
591 * stores.
593 if ((dwFlags & CERT_SYSTEM_STORE_LOCATION_MASK) ==
594 CERT_SYSTEM_STORE_CURRENT_USER)
596 dwFlags &= ~CERT_SYSTEM_STORE_CURRENT_USER;
597 dwFlags |= CERT_SYSTEM_STORE_LOCAL_MACHINE;
598 regStore = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY_W, 0,
599 0, dwFlags, pvPara);
600 if (regStore)
602 CertAddStoreToCollection(store, regStore,
603 dwFlags & CERT_STORE_READONLY_FLAG ? 0 :
604 CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
605 CertCloseStore(regStore, 0);
608 /* System store doesn't need crypto provider, so close it */
609 if (hCryptProv && !(dwFlags & CERT_STORE_NO_CRYPT_RELEASE_FLAG))
610 CryptReleaseContext(hCryptProv, 0);
613 return store;
616 static WINECRYPT_CERTSTORE *CRYPT_SysOpenStoreA(HCRYPTPROV hCryptProv,
617 DWORD dwFlags, const void *pvPara)
619 int len;
620 WINECRYPT_CERTSTORE *ret = NULL;
622 TRACE("(%ld, %08x, %s)\n", hCryptProv, dwFlags,
623 debugstr_a(pvPara));
625 if (!pvPara)
627 SetLastError(ERROR_FILE_NOT_FOUND);
628 return NULL;
630 len = MultiByteToWideChar(CP_ACP, 0, pvPara, -1, NULL, 0);
631 if (len)
633 LPWSTR storeName = CryptMemAlloc(len * sizeof(WCHAR));
635 if (storeName)
637 MultiByteToWideChar(CP_ACP, 0, pvPara, -1, storeName, len);
638 ret = CRYPT_SysOpenStoreW(hCryptProv, dwFlags, storeName);
639 CryptMemFree(storeName);
642 return ret;
645 static void WINAPI CRYPT_MsgCloseStore(HCERTSTORE hCertStore, DWORD dwFlags)
647 HCRYPTMSG msg = hCertStore;
649 TRACE("(%p, %08x)\n", msg, dwFlags);
650 CryptMsgClose(msg);
653 static void *msgProvFuncs[] = {
654 CRYPT_MsgCloseStore,
657 static WINECRYPT_CERTSTORE *CRYPT_MsgOpenStore(HCRYPTPROV hCryptProv,
658 DWORD dwFlags, const void *pvPara)
660 WINECRYPT_CERTSTORE *store = NULL;
661 HCRYPTMSG msg = (HCRYPTMSG)pvPara;
662 WINECRYPT_CERTSTORE *memStore;
664 TRACE("(%ld, %08x, %p)\n", hCryptProv, dwFlags, pvPara);
666 memStore = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
667 CERT_STORE_CREATE_NEW_FLAG, NULL);
668 if (memStore)
670 BOOL ret;
671 DWORD size, count, i;
673 size = sizeof(count);
674 ret = CryptMsgGetParam(msg, CMSG_CERT_COUNT_PARAM, 0, &count, &size);
675 for (i = 0; ret && i < count; i++)
677 size = 0;
678 ret = CryptMsgGetParam(msg, CMSG_CERT_PARAM, i, NULL, &size);
679 if (ret)
681 LPBYTE buf = CryptMemAlloc(size);
683 if (buf)
685 ret = CryptMsgGetParam(msg, CMSG_CERT_PARAM, i, buf, &size);
686 if (ret)
687 ret = CertAddEncodedCertificateToStore(memStore,
688 X509_ASN_ENCODING, buf, size, CERT_STORE_ADD_ALWAYS,
689 NULL);
690 CryptMemFree(buf);
694 size = sizeof(count);
695 ret = CryptMsgGetParam(msg, CMSG_CRL_COUNT_PARAM, 0, &count, &size);
696 for (i = 0; ret && i < count; i++)
698 size = 0;
699 ret = CryptMsgGetParam(msg, CMSG_CRL_PARAM, i, NULL, &size);
700 if (ret)
702 LPBYTE buf = CryptMemAlloc(size);
704 if (buf)
706 ret = CryptMsgGetParam(msg, CMSG_CRL_PARAM, i, buf, &size);
707 if (ret)
708 ret = CertAddEncodedCRLToStore(memStore,
709 X509_ASN_ENCODING, buf, size, CERT_STORE_ADD_ALWAYS,
710 NULL);
711 CryptMemFree(buf);
715 if (ret)
717 CERT_STORE_PROV_INFO provInfo = { 0 };
719 provInfo.cbSize = sizeof(provInfo);
720 provInfo.cStoreProvFunc = ARRAY_SIZE(msgProvFuncs);
721 provInfo.rgpvStoreProvFunc = msgProvFuncs;
722 provInfo.hStoreProv = CryptMsgDuplicate(msg);
723 store = CRYPT_ProvCreateStore(dwFlags, memStore, &provInfo);
724 /* Msg store doesn't need crypto provider, so close it */
725 if (hCryptProv && !(dwFlags & CERT_STORE_NO_CRYPT_RELEASE_FLAG))
726 CryptReleaseContext(hCryptProv, 0);
728 else
729 CertCloseStore(memStore, 0);
731 TRACE("returning %p\n", store);
732 return store;
735 static WINECRYPT_CERTSTORE *CRYPT_PKCSOpenStore(HCRYPTPROV hCryptProv,
736 DWORD dwFlags, const void *pvPara)
738 HCRYPTMSG msg;
739 WINECRYPT_CERTSTORE *store = NULL;
740 const CRYPT_DATA_BLOB *data = pvPara;
741 BOOL ret;
742 DWORD msgOpenFlags = dwFlags & CERT_STORE_NO_CRYPT_RELEASE_FLAG ? 0 :
743 CMSG_CRYPT_RELEASE_CONTEXT_FLAG;
745 TRACE("(%ld, %08x, %p)\n", hCryptProv, dwFlags, pvPara);
747 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, msgOpenFlags, CMSG_SIGNED,
748 hCryptProv, NULL, NULL);
749 ret = CryptMsgUpdate(msg, data->pbData, data->cbData, TRUE);
750 if (!ret)
752 CryptMsgClose(msg);
753 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, msgOpenFlags, 0,
754 hCryptProv, NULL, NULL);
755 ret = CryptMsgUpdate(msg, data->pbData, data->cbData, TRUE);
756 if (ret)
758 DWORD type, size = sizeof(type);
760 /* Only signed messages are allowed, check type */
761 ret = CryptMsgGetParam(msg, CMSG_TYPE_PARAM, 0, &type, &size);
762 if (ret && type != CMSG_SIGNED)
764 SetLastError(CRYPT_E_INVALID_MSG_TYPE);
765 ret = FALSE;
769 if (ret)
770 store = CRYPT_MsgOpenStore(0, dwFlags, msg);
771 CryptMsgClose(msg);
772 TRACE("returning %p\n", store);
773 return store;
776 static WINECRYPT_CERTSTORE *CRYPT_SerializedOpenStore(HCRYPTPROV hCryptProv,
777 DWORD dwFlags, const void *pvPara)
779 HCERTSTORE store;
780 const CRYPT_DATA_BLOB *data = pvPara;
782 TRACE("(%ld, %08x, %p)\n", hCryptProv, dwFlags, pvPara);
784 if (dwFlags & CERT_STORE_DELETE_FLAG)
786 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
787 return NULL;
790 store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
791 CERT_STORE_CREATE_NEW_FLAG, NULL);
792 if (store)
794 if (!CRYPT_ReadSerializedStoreFromBlob(data, store))
796 CertCloseStore(store, 0);
797 store = NULL;
800 TRACE("returning %p\n", store);
801 return (WINECRYPT_CERTSTORE*)store;
804 static WINECRYPT_CERTSTORE *CRYPT_PhysOpenStoreW(HCRYPTPROV hCryptProv,
805 DWORD dwFlags, const void *pvPara)
807 if (dwFlags & CERT_SYSTEM_STORE_RELOCATE_FLAG)
808 FIXME("(%ld, %08x, %p): stub\n", hCryptProv, dwFlags, pvPara);
809 else
810 FIXME("(%ld, %08x, %s): stub\n", hCryptProv, dwFlags,
811 debugstr_w(pvPara));
812 return NULL;
815 HCERTSTORE WINAPI CertOpenStore(LPCSTR lpszStoreProvider,
816 DWORD dwMsgAndCertEncodingType, HCRYPTPROV_LEGACY hCryptProv, DWORD dwFlags,
817 const void* pvPara)
819 WINECRYPT_CERTSTORE *hcs;
820 StoreOpenFunc openFunc = NULL;
822 TRACE("(%s, %08x, %08lx, %08x, %p)\n", debugstr_a(lpszStoreProvider),
823 dwMsgAndCertEncodingType, hCryptProv, dwFlags, pvPara);
825 if (IS_INTOID(lpszStoreProvider))
827 switch (LOWORD(lpszStoreProvider))
829 case LOWORD(CERT_STORE_PROV_MSG):
830 openFunc = CRYPT_MsgOpenStore;
831 break;
832 case LOWORD(CERT_STORE_PROV_MEMORY):
833 openFunc = CRYPT_MemOpenStore;
834 break;
835 case LOWORD(CERT_STORE_PROV_FILE):
836 openFunc = CRYPT_FileOpenStore;
837 break;
838 case LOWORD(CERT_STORE_PROV_PKCS7):
839 openFunc = CRYPT_PKCSOpenStore;
840 break;
841 case LOWORD(CERT_STORE_PROV_SERIALIZED):
842 openFunc = CRYPT_SerializedOpenStore;
843 break;
844 case LOWORD(CERT_STORE_PROV_REG):
845 openFunc = CRYPT_RegOpenStore;
846 break;
847 case LOWORD(CERT_STORE_PROV_FILENAME_A):
848 openFunc = CRYPT_FileNameOpenStoreA;
849 break;
850 case LOWORD(CERT_STORE_PROV_FILENAME_W):
851 openFunc = CRYPT_FileNameOpenStoreW;
852 break;
853 case LOWORD(CERT_STORE_PROV_COLLECTION):
854 openFunc = CRYPT_CollectionOpenStore;
855 break;
856 case LOWORD(CERT_STORE_PROV_SYSTEM_A):
857 openFunc = CRYPT_SysOpenStoreA;
858 break;
859 case LOWORD(CERT_STORE_PROV_SYSTEM_W):
860 openFunc = CRYPT_SysOpenStoreW;
861 break;
862 case LOWORD(CERT_STORE_PROV_SYSTEM_REGISTRY_A):
863 openFunc = CRYPT_SysRegOpenStoreA;
864 break;
865 case LOWORD(CERT_STORE_PROV_SYSTEM_REGISTRY_W):
866 openFunc = CRYPT_SysRegOpenStoreW;
867 break;
868 case LOWORD(CERT_STORE_PROV_PHYSICAL_W):
869 openFunc = CRYPT_PhysOpenStoreW;
870 break;
871 default:
872 if (LOWORD(lpszStoreProvider))
873 FIXME("unimplemented type %d\n", LOWORD(lpszStoreProvider));
876 else if (!strcasecmp(lpszStoreProvider, sz_CERT_STORE_PROV_MEMORY))
877 openFunc = CRYPT_MemOpenStore;
878 else if (!strcasecmp(lpszStoreProvider, sz_CERT_STORE_PROV_FILENAME_W))
879 openFunc = CRYPT_FileOpenStore;
880 else if (!strcasecmp(lpszStoreProvider, sz_CERT_STORE_PROV_SYSTEM))
881 openFunc = CRYPT_SysOpenStoreW;
882 else if (!strcasecmp(lpszStoreProvider, sz_CERT_STORE_PROV_PKCS7))
883 openFunc = CRYPT_PKCSOpenStore;
884 else if (!strcasecmp(lpszStoreProvider, sz_CERT_STORE_PROV_SERIALIZED))
885 openFunc = CRYPT_SerializedOpenStore;
886 else if (!strcasecmp(lpszStoreProvider, sz_CERT_STORE_PROV_COLLECTION))
887 openFunc = CRYPT_CollectionOpenStore;
888 else if (!strcasecmp(lpszStoreProvider, sz_CERT_STORE_PROV_SYSTEM_REGISTRY))
889 openFunc = CRYPT_SysRegOpenStoreW;
890 else
892 FIXME("unimplemented type %s\n", lpszStoreProvider);
893 openFunc = NULL;
896 if (!openFunc)
897 hcs = CRYPT_ProvOpenStore(lpszStoreProvider, dwMsgAndCertEncodingType,
898 hCryptProv, dwFlags, pvPara);
899 else
900 hcs = openFunc(hCryptProv, dwFlags, pvPara);
901 return hcs;
904 HCERTSTORE WINAPI CertOpenSystemStoreA(HCRYPTPROV_LEGACY hProv,
905 LPCSTR szSubSystemProtocol)
907 if (!szSubSystemProtocol)
909 SetLastError(E_INVALIDARG);
910 return 0;
912 return CertOpenStore(CERT_STORE_PROV_SYSTEM_A, 0, hProv,
913 CERT_SYSTEM_STORE_CURRENT_USER, szSubSystemProtocol);
916 HCERTSTORE WINAPI CertOpenSystemStoreW(HCRYPTPROV_LEGACY hProv,
917 LPCWSTR szSubSystemProtocol)
919 if (!szSubSystemProtocol)
921 SetLastError(E_INVALIDARG);
922 return 0;
924 return CertOpenStore(CERT_STORE_PROV_SYSTEM_W, 0, hProv,
925 CERT_SYSTEM_STORE_CURRENT_USER, szSubSystemProtocol);
928 PCCERT_CONTEXT WINAPI CertEnumCertificatesInStore(HCERTSTORE hCertStore, PCCERT_CONTEXT pPrev)
930 cert_t *prev = pPrev ? cert_from_ptr(pPrev) : NULL, *ret;
931 WINECRYPT_CERTSTORE *hcs = hCertStore;
933 TRACE("(%p, %p)\n", hCertStore, pPrev);
934 if (!hCertStore)
935 ret = NULL;
936 else if (hcs->dwMagic != WINE_CRYPTCERTSTORE_MAGIC)
937 ret = NULL;
938 else
939 ret = (cert_t*)hcs->vtbl->certs.enumContext(hcs, prev ? &prev->base : NULL);
940 return ret ? &ret->ctx : NULL;
943 BOOL WINAPI CertDeleteCertificateFromStore(PCCERT_CONTEXT pCertContext)
945 WINECRYPT_CERTSTORE *hcs;
947 TRACE("(%p)\n", pCertContext);
949 if (!pCertContext)
950 return TRUE;
952 hcs = pCertContext->hCertStore;
954 if (hcs->dwMagic != WINE_CRYPTCERTSTORE_MAGIC)
955 return FALSE;
957 return hcs->vtbl->certs.delete(hcs, &cert_from_ptr(pCertContext)->base);
960 BOOL WINAPI CertAddCRLContextToStore(HCERTSTORE hCertStore,
961 PCCRL_CONTEXT pCrlContext, DWORD dwAddDisposition,
962 PCCRL_CONTEXT* ppStoreContext)
964 WINECRYPT_CERTSTORE *store = hCertStore;
965 BOOL ret = TRUE;
966 PCCRL_CONTEXT toAdd = NULL, existing = NULL;
968 TRACE("(%p, %p, %08x, %p)\n", hCertStore, pCrlContext,
969 dwAddDisposition, ppStoreContext);
971 /* Weird case to pass a test */
972 if (dwAddDisposition == 0)
974 SetLastError(STATUS_ACCESS_VIOLATION);
975 return FALSE;
977 if (dwAddDisposition != CERT_STORE_ADD_ALWAYS)
979 existing = CertFindCRLInStore(hCertStore, 0, 0, CRL_FIND_EXISTING,
980 pCrlContext, NULL);
983 switch (dwAddDisposition)
985 case CERT_STORE_ADD_ALWAYS:
986 toAdd = CertDuplicateCRLContext(pCrlContext);
987 break;
988 case CERT_STORE_ADD_NEW:
989 if (existing)
991 TRACE("found matching CRL, not adding\n");
992 SetLastError(CRYPT_E_EXISTS);
993 ret = FALSE;
995 else
996 toAdd = CertDuplicateCRLContext(pCrlContext);
997 break;
998 case CERT_STORE_ADD_NEWER:
999 if (existing)
1001 LONG newer = CompareFileTime(&existing->pCrlInfo->ThisUpdate,
1002 &pCrlContext->pCrlInfo->ThisUpdate);
1004 if (newer < 0)
1005 toAdd = CertDuplicateCRLContext(pCrlContext);
1006 else
1008 TRACE("existing CRL is newer, not adding\n");
1009 SetLastError(CRYPT_E_EXISTS);
1010 ret = FALSE;
1013 else
1014 toAdd = CertDuplicateCRLContext(pCrlContext);
1015 break;
1016 case CERT_STORE_ADD_NEWER_INHERIT_PROPERTIES:
1017 if (existing)
1019 LONG newer = CompareFileTime(&existing->pCrlInfo->ThisUpdate,
1020 &pCrlContext->pCrlInfo->ThisUpdate);
1022 if (newer < 0)
1024 toAdd = CertDuplicateCRLContext(pCrlContext);
1025 Context_CopyProperties(toAdd, existing);
1027 else
1029 TRACE("existing CRL is newer, not adding\n");
1030 SetLastError(CRYPT_E_EXISTS);
1031 ret = FALSE;
1034 else
1035 toAdd = CertDuplicateCRLContext(pCrlContext);
1036 break;
1037 case CERT_STORE_ADD_REPLACE_EXISTING:
1038 toAdd = CertDuplicateCRLContext(pCrlContext);
1039 break;
1040 case CERT_STORE_ADD_REPLACE_EXISTING_INHERIT_PROPERTIES:
1041 toAdd = CertDuplicateCRLContext(pCrlContext);
1042 if (existing)
1043 Context_CopyProperties(toAdd, existing);
1044 break;
1045 case CERT_STORE_ADD_USE_EXISTING:
1046 if (existing)
1048 Context_CopyProperties(existing, pCrlContext);
1049 if (ppStoreContext)
1050 *ppStoreContext = CertDuplicateCRLContext(existing);
1052 else
1053 toAdd = CertDuplicateCRLContext(pCrlContext);
1054 break;
1055 default:
1056 FIXME("Unimplemented add disposition %d\n", dwAddDisposition);
1057 ret = FALSE;
1060 if (toAdd)
1062 if (store) {
1063 context_t *ret_context;
1064 ret = store->vtbl->crls.addContext(store, context_from_ptr(toAdd),
1065 existing ? context_from_ptr(existing) : NULL, ppStoreContext ? &ret_context : NULL, FALSE);
1066 if (ret && ppStoreContext)
1067 *ppStoreContext = context_ptr(ret_context);
1068 }else if (ppStoreContext) {
1069 *ppStoreContext = CertDuplicateCRLContext(toAdd);
1071 CertFreeCRLContext(toAdd);
1073 if (existing)
1074 CertFreeCRLContext(existing);
1076 TRACE("returning %d\n", ret);
1077 return ret;
1080 BOOL WINAPI CertDeleteCRLFromStore(PCCRL_CONTEXT pCrlContext)
1082 WINECRYPT_CERTSTORE *hcs;
1083 BOOL ret;
1085 TRACE("(%p)\n", pCrlContext);
1087 if (!pCrlContext)
1088 return TRUE;
1090 hcs = pCrlContext->hCertStore;
1092 if (hcs->dwMagic != WINE_CRYPTCERTSTORE_MAGIC)
1093 return FALSE;
1095 ret = hcs->vtbl->crls.delete(hcs, &crl_from_ptr(pCrlContext)->base);
1096 if (ret)
1097 ret = CertFreeCRLContext(pCrlContext);
1098 return ret;
1101 PCCRL_CONTEXT WINAPI CertEnumCRLsInStore(HCERTSTORE hCertStore, PCCRL_CONTEXT pPrev)
1103 crl_t *ret, *prev = pPrev ? crl_from_ptr(pPrev) : NULL;
1104 WINECRYPT_CERTSTORE *hcs = hCertStore;
1106 TRACE("(%p, %p)\n", hCertStore, pPrev);
1107 if (!hCertStore)
1108 ret = NULL;
1109 else if (hcs->dwMagic != WINE_CRYPTCERTSTORE_MAGIC)
1110 ret = NULL;
1111 else
1112 ret = (crl_t*)hcs->vtbl->crls.enumContext(hcs, prev ? &prev->base : NULL);
1113 return ret ? &ret->ctx : NULL;
1116 HCERTSTORE WINAPI CertDuplicateStore(HCERTSTORE hCertStore)
1118 WINECRYPT_CERTSTORE *hcs = hCertStore;
1120 TRACE("(%p)\n", hCertStore);
1122 if (hcs && hcs->dwMagic == WINE_CRYPTCERTSTORE_MAGIC)
1123 hcs->vtbl->addref(hcs);
1124 return hCertStore;
1127 BOOL WINAPI CertCloseStore(HCERTSTORE hCertStore, DWORD dwFlags)
1129 WINECRYPT_CERTSTORE *hcs = hCertStore;
1130 DWORD res;
1132 TRACE("(%p, %08x)\n", hCertStore, dwFlags);
1134 if( ! hCertStore )
1135 return TRUE;
1137 if ( hcs->dwMagic != WINE_CRYPTCERTSTORE_MAGIC )
1138 return FALSE;
1140 res = hcs->vtbl->release(hcs, dwFlags);
1141 if (res != ERROR_SUCCESS) {
1142 SetLastError(res);
1143 return FALSE;
1146 return TRUE;
1149 BOOL WINAPI CertControlStore(HCERTSTORE hCertStore, DWORD dwFlags,
1150 DWORD dwCtrlType, void const *pvCtrlPara)
1152 WINECRYPT_CERTSTORE *hcs = hCertStore;
1153 BOOL ret;
1155 TRACE("(%p, %08x, %d, %p)\n", hCertStore, dwFlags, dwCtrlType,
1156 pvCtrlPara);
1158 if (!hcs)
1159 ret = FALSE;
1160 else if (hcs->dwMagic != WINE_CRYPTCERTSTORE_MAGIC)
1161 ret = FALSE;
1162 else
1164 if (hcs->vtbl->control)
1165 ret = hcs->vtbl->control(hcs, dwFlags, dwCtrlType, pvCtrlPara);
1166 else
1167 ret = TRUE;
1169 return ret;
1172 BOOL WINAPI CertGetStoreProperty(HCERTSTORE hCertStore, DWORD dwPropId,
1173 void *pvData, DWORD *pcbData)
1175 WINECRYPT_CERTSTORE *store = hCertStore;
1176 BOOL ret = FALSE;
1178 TRACE("(%p, %d, %p, %p)\n", hCertStore, dwPropId, pvData, pcbData);
1180 switch (dwPropId)
1182 case CERT_ACCESS_STATE_PROP_ID:
1183 if (!pvData)
1185 *pcbData = sizeof(DWORD);
1186 ret = TRUE;
1188 else if (*pcbData < sizeof(DWORD))
1190 SetLastError(ERROR_MORE_DATA);
1191 *pcbData = sizeof(DWORD);
1193 else
1195 DWORD state = 0;
1197 if (store->type != StoreTypeMem &&
1198 !(store->dwOpenFlags & CERT_STORE_READONLY_FLAG))
1199 state |= CERT_ACCESS_STATE_WRITE_PERSIST_FLAG;
1200 *(DWORD *)pvData = state;
1201 ret = TRUE;
1203 break;
1204 default:
1205 if (store->properties)
1207 CRYPT_DATA_BLOB blob;
1209 ret = ContextPropertyList_FindProperty(store->properties, dwPropId,
1210 &blob);
1211 if (ret)
1213 if (!pvData)
1214 *pcbData = blob.cbData;
1215 else if (*pcbData < blob.cbData)
1217 SetLastError(ERROR_MORE_DATA);
1218 *pcbData = blob.cbData;
1219 ret = FALSE;
1221 else
1223 memcpy(pvData, blob.pbData, blob.cbData);
1224 *pcbData = blob.cbData;
1227 else
1228 SetLastError(CRYPT_E_NOT_FOUND);
1230 else
1231 SetLastError(CRYPT_E_NOT_FOUND);
1233 return ret;
1236 BOOL WINAPI CertSetStoreProperty(HCERTSTORE hCertStore, DWORD dwPropId,
1237 DWORD dwFlags, const void *pvData)
1239 WINECRYPT_CERTSTORE *store = hCertStore;
1240 BOOL ret = FALSE;
1242 TRACE("(%p, %d, %08x, %p)\n", hCertStore, dwPropId, dwFlags, pvData);
1244 if (!store->properties)
1245 store->properties = ContextPropertyList_Create();
1246 switch (dwPropId)
1248 case CERT_ACCESS_STATE_PROP_ID:
1249 SetLastError(E_INVALIDARG);
1250 break;
1251 default:
1252 if (pvData)
1254 const CRYPT_DATA_BLOB *blob = pvData;
1256 ret = ContextPropertyList_SetProperty(store->properties, dwPropId,
1257 blob->pbData, blob->cbData);
1259 else
1261 ContextPropertyList_RemoveProperty(store->properties, dwPropId);
1262 ret = TRUE;
1265 return ret;
1268 static LONG CRYPT_OpenParentStore(DWORD dwFlags,
1269 void *pvSystemStoreLocationPara, HKEY *key)
1271 HKEY root;
1272 LPCWSTR base;
1274 TRACE("(%08x, %p)\n", dwFlags, pvSystemStoreLocationPara);
1276 switch (dwFlags & CERT_SYSTEM_STORE_LOCATION_MASK)
1278 case CERT_SYSTEM_STORE_LOCAL_MACHINE:
1279 root = HKEY_LOCAL_MACHINE;
1280 base = CERT_LOCAL_MACHINE_SYSTEM_STORE_REGPATH;
1281 break;
1282 case CERT_SYSTEM_STORE_CURRENT_USER:
1283 root = HKEY_CURRENT_USER;
1284 base = CERT_LOCAL_MACHINE_SYSTEM_STORE_REGPATH;
1285 break;
1286 case CERT_SYSTEM_STORE_CURRENT_SERVICE:
1287 /* hklm\Software\Microsoft\Cryptography\Services\servicename\
1288 * SystemCertificates
1290 FIXME("CERT_SYSTEM_STORE_CURRENT_SERVICE\n");
1291 return ERROR_FILE_NOT_FOUND;
1292 case CERT_SYSTEM_STORE_SERVICES:
1293 /* hklm\Software\Microsoft\Cryptography\Services\servicename\
1294 * SystemCertificates
1296 FIXME("CERT_SYSTEM_STORE_SERVICES\n");
1297 return ERROR_FILE_NOT_FOUND;
1298 case CERT_SYSTEM_STORE_USERS:
1299 /* hku\user sid\Software\Microsoft\SystemCertificates */
1300 FIXME("CERT_SYSTEM_STORE_USERS\n");
1301 return ERROR_FILE_NOT_FOUND;
1302 case CERT_SYSTEM_STORE_CURRENT_USER_GROUP_POLICY:
1303 root = HKEY_CURRENT_USER;
1304 base = CERT_GROUP_POLICY_SYSTEM_STORE_REGPATH;
1305 break;
1306 case CERT_SYSTEM_STORE_LOCAL_MACHINE_GROUP_POLICY:
1307 root = HKEY_LOCAL_MACHINE;
1308 base = CERT_GROUP_POLICY_SYSTEM_STORE_REGPATH;
1309 break;
1310 case CERT_SYSTEM_STORE_LOCAL_MACHINE_ENTERPRISE:
1311 /* hklm\Software\Microsoft\EnterpriseCertificates */
1312 FIXME("CERT_SYSTEM_STORE_LOCAL_MACHINE_ENTERPRISE\n");
1313 return ERROR_FILE_NOT_FOUND;
1314 default:
1315 return ERROR_FILE_NOT_FOUND;
1318 return RegOpenKeyExW(root, base, 0, KEY_READ, key);
1321 BOOL WINAPI CertEnumSystemStore(DWORD dwFlags, void *pvSystemStoreLocationPara,
1322 void *pvArg, PFN_CERT_ENUM_SYSTEM_STORE pfnEnum)
1324 BOOL ret = FALSE;
1325 LONG rc;
1326 HKEY key;
1327 CERT_SYSTEM_STORE_INFO info = { sizeof(info) };
1329 TRACE("(%08x, %p, %p, %p)\n", dwFlags, pvSystemStoreLocationPara, pvArg,
1330 pfnEnum);
1332 rc = CRYPT_OpenParentStore(dwFlags, pvArg, &key);
1333 if (!rc)
1335 DWORD index = 0;
1337 ret = TRUE;
1338 do {
1339 WCHAR name[MAX_PATH];
1340 DWORD size = ARRAY_SIZE(name);
1342 rc = RegEnumKeyExW(key, index++, name, &size, NULL, NULL, NULL,
1343 NULL);
1344 if (!rc)
1345 ret = pfnEnum(name, dwFlags, &info, NULL, pvArg);
1346 } while (ret && !rc);
1347 if (ret && rc != ERROR_NO_MORE_ITEMS)
1348 SetLastError(rc);
1350 else
1351 SetLastError(rc);
1352 /* Include root store for the local machine location (it isn't in the
1353 * registry)
1355 if (ret && (dwFlags & CERT_SYSTEM_STORE_LOCATION_MASK) ==
1356 CERT_SYSTEM_STORE_LOCAL_MACHINE)
1357 ret = pfnEnum(rootW, dwFlags, &info, NULL, pvArg);
1358 return ret;
1361 BOOL WINAPI CertEnumPhysicalStore(const void *pvSystemStore, DWORD dwFlags,
1362 void *pvArg, PFN_CERT_ENUM_PHYSICAL_STORE pfnEnum)
1364 if (dwFlags & CERT_SYSTEM_STORE_RELOCATE_FLAG)
1365 FIXME("(%p, %08x, %p, %p): stub\n", pvSystemStore, dwFlags, pvArg,
1366 pfnEnum);
1367 else
1368 FIXME("(%s, %08x, %p, %p): stub\n", debugstr_w(pvSystemStore),
1369 dwFlags, pvArg,
1370 pfnEnum);
1371 return FALSE;
1374 BOOL WINAPI CertRegisterPhysicalStore(const void *pvSystemStore, DWORD dwFlags,
1375 LPCWSTR pwszStoreName, PCERT_PHYSICAL_STORE_INFO pStoreInfo, void *pvReserved)
1377 if (dwFlags & CERT_SYSTEM_STORE_RELOCATE_FLAG)
1378 FIXME("(%p, %08x, %s, %p, %p): stub\n", pvSystemStore, dwFlags,
1379 debugstr_w(pwszStoreName), pStoreInfo, pvReserved);
1380 else
1381 FIXME("(%s, %08x, %s, %p, %p): stub\n", debugstr_w(pvSystemStore),
1382 dwFlags, debugstr_w(pwszStoreName), pStoreInfo, pvReserved);
1383 return FALSE;
1386 BOOL WINAPI CertUnregisterPhysicalStore(const void *pvSystemStore, DWORD dwFlags,
1387 LPCWSTR pwszStoreName)
1389 FIXME("(%p, %08x, %s): stub\n", pvSystemStore, dwFlags, debugstr_w(pwszStoreName));
1390 return TRUE;
1393 BOOL WINAPI CertRegisterSystemStore(const void *pvSystemStore, DWORD dwFlags,
1394 PCERT_SYSTEM_STORE_INFO pStoreInfo, void *pvReserved)
1396 HCERTSTORE hstore;
1398 if (dwFlags & CERT_SYSTEM_STORE_RELOCATE_FLAG )
1400 FIXME("(%p, %08x, %p, %p): flag not supported\n", pvSystemStore, dwFlags, pStoreInfo, pvReserved);
1401 return FALSE;
1404 TRACE("(%s, %08x, %p, %p)\n", debugstr_w(pvSystemStore), dwFlags, pStoreInfo, pvReserved);
1406 hstore = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY_W, 0, 0, dwFlags, pvSystemStore);
1407 if (hstore)
1409 CertCloseStore(hstore, 0);
1410 return TRUE;
1413 return FALSE;
1416 BOOL WINAPI CertUnregisterSystemStore(const void *pvSystemStore, DWORD dwFlags)
1418 HCERTSTORE hstore;
1420 if (dwFlags & CERT_SYSTEM_STORE_RELOCATE_FLAG)
1422 FIXME("(%p, %08x): flag not supported\n", pvSystemStore, dwFlags);
1423 return FALSE;
1425 TRACE("(%s, %08x)\n", debugstr_w(pvSystemStore), dwFlags);
1427 hstore = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY_W, 0, 0, dwFlags | CERT_STORE_OPEN_EXISTING_FLAG, pvSystemStore);
1428 if (hstore == NULL)
1429 return FALSE;
1431 hstore = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY_W, 0, 0, dwFlags | CERT_STORE_DELETE_FLAG, pvSystemStore);
1432 if (hstore == NULL && GetLastError() == 0)
1433 return TRUE;
1435 return FALSE;
1438 static void EmptyStore_addref(WINECRYPT_CERTSTORE *store)
1440 TRACE("(%p)\n", store);
1443 static DWORD EmptyStore_release(WINECRYPT_CERTSTORE *store, DWORD flags)
1445 TRACE("(%p)\n", store);
1446 return E_UNEXPECTED;
1449 static void EmptyStore_releaseContext(WINECRYPT_CERTSTORE *store, context_t *context)
1451 Context_Free(context);
1454 static BOOL EmptyStore_add(WINECRYPT_CERTSTORE *store, context_t *context,
1455 context_t *replace, context_t **ret_context, BOOL use_link)
1457 TRACE("(%p, %p, %p, %p)\n", store, context, replace, ret_context);
1459 /* FIXME: We should clone the context */
1460 if(ret_context) {
1461 Context_AddRef(context);
1462 *ret_context = context;
1465 return TRUE;
1468 static context_t *EmptyStore_enum(WINECRYPT_CERTSTORE *store, context_t *prev)
1470 TRACE("(%p, %p)\n", store, prev);
1472 SetLastError(CRYPT_E_NOT_FOUND);
1473 return NULL;
1476 static BOOL EmptyStore_delete(WINECRYPT_CERTSTORE *store, context_t *context)
1478 return TRUE;
1481 static BOOL EmptyStore_control(WINECRYPT_CERTSTORE *store, DWORD flags, DWORD ctrl_type, void const *ctrl_para)
1483 TRACE("()\n");
1485 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1486 return FALSE;
1489 static const store_vtbl_t EmptyStoreVtbl = {
1490 EmptyStore_addref,
1491 EmptyStore_release,
1492 EmptyStore_releaseContext,
1493 EmptyStore_control,
1495 EmptyStore_add,
1496 EmptyStore_enum,
1497 EmptyStore_delete
1498 }, {
1499 EmptyStore_add,
1500 EmptyStore_enum,
1501 EmptyStore_delete
1502 }, {
1503 EmptyStore_add,
1504 EmptyStore_enum,
1505 EmptyStore_delete
1509 WINECRYPT_CERTSTORE empty_store;
1511 void init_empty_store(void)
1513 CRYPT_InitStore(&empty_store, CERT_STORE_READONLY_FLAG, StoreTypeEmpty, &EmptyStoreVtbl);