wined3d: Fix a trailing new-line in an ERR() message.
[wine.git] / dlls / crypt32 / store.c
blob19eca22be2d6fe57c8c7f6eab5f652403ae4b35a
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 < sizeof(interfaces) / sizeof(interfaces[0]); 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 = sizeof(msgProvFuncs) /
721 sizeof(msgProvFuncs[0]);
722 provInfo.rgpvStoreProvFunc = msgProvFuncs;
723 provInfo.hStoreProv = CryptMsgDuplicate(msg);
724 store = CRYPT_ProvCreateStore(dwFlags, memStore, &provInfo);
725 /* Msg store doesn't need crypto provider, so close it */
726 if (hCryptProv && !(dwFlags & CERT_STORE_NO_CRYPT_RELEASE_FLAG))
727 CryptReleaseContext(hCryptProv, 0);
729 else
730 CertCloseStore(memStore, 0);
732 TRACE("returning %p\n", store);
733 return store;
736 static WINECRYPT_CERTSTORE *CRYPT_PKCSOpenStore(HCRYPTPROV hCryptProv,
737 DWORD dwFlags, const void *pvPara)
739 HCRYPTMSG msg;
740 WINECRYPT_CERTSTORE *store = NULL;
741 const CRYPT_DATA_BLOB *data = pvPara;
742 BOOL ret;
743 DWORD msgOpenFlags = dwFlags & CERT_STORE_NO_CRYPT_RELEASE_FLAG ? 0 :
744 CMSG_CRYPT_RELEASE_CONTEXT_FLAG;
746 TRACE("(%ld, %08x, %p)\n", hCryptProv, dwFlags, pvPara);
748 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, msgOpenFlags, CMSG_SIGNED,
749 hCryptProv, NULL, NULL);
750 ret = CryptMsgUpdate(msg, data->pbData, data->cbData, TRUE);
751 if (!ret)
753 CryptMsgClose(msg);
754 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, msgOpenFlags, 0,
755 hCryptProv, NULL, NULL);
756 ret = CryptMsgUpdate(msg, data->pbData, data->cbData, TRUE);
757 if (ret)
759 DWORD type, size = sizeof(type);
761 /* Only signed messages are allowed, check type */
762 ret = CryptMsgGetParam(msg, CMSG_TYPE_PARAM, 0, &type, &size);
763 if (ret && type != CMSG_SIGNED)
765 SetLastError(CRYPT_E_INVALID_MSG_TYPE);
766 ret = FALSE;
770 if (ret)
771 store = CRYPT_MsgOpenStore(0, dwFlags, msg);
772 CryptMsgClose(msg);
773 TRACE("returning %p\n", store);
774 return store;
777 static WINECRYPT_CERTSTORE *CRYPT_SerializedOpenStore(HCRYPTPROV hCryptProv,
778 DWORD dwFlags, const void *pvPara)
780 HCERTSTORE store;
781 const CRYPT_DATA_BLOB *data = pvPara;
783 TRACE("(%ld, %08x, %p)\n", hCryptProv, dwFlags, pvPara);
785 if (dwFlags & CERT_STORE_DELETE_FLAG)
787 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
788 return NULL;
791 store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
792 CERT_STORE_CREATE_NEW_FLAG, NULL);
793 if (store)
795 if (!CRYPT_ReadSerializedStoreFromBlob(data, store))
797 CertCloseStore(store, 0);
798 store = NULL;
801 TRACE("returning %p\n", store);
802 return (WINECRYPT_CERTSTORE*)store;
805 static WINECRYPT_CERTSTORE *CRYPT_PhysOpenStoreW(HCRYPTPROV hCryptProv,
806 DWORD dwFlags, const void *pvPara)
808 if (dwFlags & CERT_SYSTEM_STORE_RELOCATE_FLAG)
809 FIXME("(%ld, %08x, %p): stub\n", hCryptProv, dwFlags, pvPara);
810 else
811 FIXME("(%ld, %08x, %s): stub\n", hCryptProv, dwFlags,
812 debugstr_w(pvPara));
813 return NULL;
816 HCERTSTORE WINAPI CertOpenStore(LPCSTR lpszStoreProvider,
817 DWORD dwMsgAndCertEncodingType, HCRYPTPROV_LEGACY hCryptProv, DWORD dwFlags,
818 const void* pvPara)
820 WINECRYPT_CERTSTORE *hcs;
821 StoreOpenFunc openFunc = NULL;
823 TRACE("(%s, %08x, %08lx, %08x, %p)\n", debugstr_a(lpszStoreProvider),
824 dwMsgAndCertEncodingType, hCryptProv, dwFlags, pvPara);
826 if (IS_INTOID(lpszStoreProvider))
828 switch (LOWORD(lpszStoreProvider))
830 case LOWORD(CERT_STORE_PROV_MSG):
831 openFunc = CRYPT_MsgOpenStore;
832 break;
833 case LOWORD(CERT_STORE_PROV_MEMORY):
834 openFunc = CRYPT_MemOpenStore;
835 break;
836 case LOWORD(CERT_STORE_PROV_FILE):
837 openFunc = CRYPT_FileOpenStore;
838 break;
839 case LOWORD(CERT_STORE_PROV_PKCS7):
840 openFunc = CRYPT_PKCSOpenStore;
841 break;
842 case LOWORD(CERT_STORE_PROV_SERIALIZED):
843 openFunc = CRYPT_SerializedOpenStore;
844 break;
845 case LOWORD(CERT_STORE_PROV_REG):
846 openFunc = CRYPT_RegOpenStore;
847 break;
848 case LOWORD(CERT_STORE_PROV_FILENAME_A):
849 openFunc = CRYPT_FileNameOpenStoreA;
850 break;
851 case LOWORD(CERT_STORE_PROV_FILENAME_W):
852 openFunc = CRYPT_FileNameOpenStoreW;
853 break;
854 case LOWORD(CERT_STORE_PROV_COLLECTION):
855 openFunc = CRYPT_CollectionOpenStore;
856 break;
857 case LOWORD(CERT_STORE_PROV_SYSTEM_A):
858 openFunc = CRYPT_SysOpenStoreA;
859 break;
860 case LOWORD(CERT_STORE_PROV_SYSTEM_W):
861 openFunc = CRYPT_SysOpenStoreW;
862 break;
863 case LOWORD(CERT_STORE_PROV_SYSTEM_REGISTRY_A):
864 openFunc = CRYPT_SysRegOpenStoreA;
865 break;
866 case LOWORD(CERT_STORE_PROV_SYSTEM_REGISTRY_W):
867 openFunc = CRYPT_SysRegOpenStoreW;
868 break;
869 case LOWORD(CERT_STORE_PROV_PHYSICAL_W):
870 openFunc = CRYPT_PhysOpenStoreW;
871 break;
872 default:
873 if (LOWORD(lpszStoreProvider))
874 FIXME("unimplemented type %d\n", LOWORD(lpszStoreProvider));
877 else if (!strcasecmp(lpszStoreProvider, sz_CERT_STORE_PROV_MEMORY))
878 openFunc = CRYPT_MemOpenStore;
879 else if (!strcasecmp(lpszStoreProvider, sz_CERT_STORE_PROV_FILENAME_W))
880 openFunc = CRYPT_FileOpenStore;
881 else if (!strcasecmp(lpszStoreProvider, sz_CERT_STORE_PROV_SYSTEM))
882 openFunc = CRYPT_SysOpenStoreW;
883 else if (!strcasecmp(lpszStoreProvider, sz_CERT_STORE_PROV_PKCS7))
884 openFunc = CRYPT_PKCSOpenStore;
885 else if (!strcasecmp(lpszStoreProvider, sz_CERT_STORE_PROV_SERIALIZED))
886 openFunc = CRYPT_SerializedOpenStore;
887 else if (!strcasecmp(lpszStoreProvider, sz_CERT_STORE_PROV_COLLECTION))
888 openFunc = CRYPT_CollectionOpenStore;
889 else if (!strcasecmp(lpszStoreProvider, sz_CERT_STORE_PROV_SYSTEM_REGISTRY))
890 openFunc = CRYPT_SysRegOpenStoreW;
891 else
893 FIXME("unimplemented type %s\n", lpszStoreProvider);
894 openFunc = NULL;
897 if (!openFunc)
898 hcs = CRYPT_ProvOpenStore(lpszStoreProvider, dwMsgAndCertEncodingType,
899 hCryptProv, dwFlags, pvPara);
900 else
901 hcs = openFunc(hCryptProv, dwFlags, pvPara);
902 return hcs;
905 HCERTSTORE WINAPI CertOpenSystemStoreA(HCRYPTPROV_LEGACY hProv,
906 LPCSTR szSubSystemProtocol)
908 if (!szSubSystemProtocol)
910 SetLastError(E_INVALIDARG);
911 return 0;
913 return CertOpenStore(CERT_STORE_PROV_SYSTEM_A, 0, hProv,
914 CERT_SYSTEM_STORE_CURRENT_USER, szSubSystemProtocol);
917 HCERTSTORE WINAPI CertOpenSystemStoreW(HCRYPTPROV_LEGACY hProv,
918 LPCWSTR szSubSystemProtocol)
920 if (!szSubSystemProtocol)
922 SetLastError(E_INVALIDARG);
923 return 0;
925 return CertOpenStore(CERT_STORE_PROV_SYSTEM_W, 0, hProv,
926 CERT_SYSTEM_STORE_CURRENT_USER, szSubSystemProtocol);
929 PCCERT_CONTEXT WINAPI CertEnumCertificatesInStore(HCERTSTORE hCertStore, PCCERT_CONTEXT pPrev)
931 cert_t *prev = pPrev ? cert_from_ptr(pPrev) : NULL, *ret;
932 WINECRYPT_CERTSTORE *hcs = hCertStore;
934 TRACE("(%p, %p)\n", hCertStore, pPrev);
935 if (!hCertStore)
936 ret = NULL;
937 else if (hcs->dwMagic != WINE_CRYPTCERTSTORE_MAGIC)
938 ret = NULL;
939 else
940 ret = (cert_t*)hcs->vtbl->certs.enumContext(hcs, prev ? &prev->base : NULL);
941 return ret ? &ret->ctx : NULL;
944 BOOL WINAPI CertDeleteCertificateFromStore(PCCERT_CONTEXT pCertContext)
946 WINECRYPT_CERTSTORE *hcs;
948 TRACE("(%p)\n", pCertContext);
950 if (!pCertContext)
951 return TRUE;
953 hcs = pCertContext->hCertStore;
955 if (hcs->dwMagic != WINE_CRYPTCERTSTORE_MAGIC)
956 return FALSE;
958 return hcs->vtbl->certs.delete(hcs, &cert_from_ptr(pCertContext)->base);
961 BOOL WINAPI CertAddCRLContextToStore(HCERTSTORE hCertStore,
962 PCCRL_CONTEXT pCrlContext, DWORD dwAddDisposition,
963 PCCRL_CONTEXT* ppStoreContext)
965 WINECRYPT_CERTSTORE *store = hCertStore;
966 BOOL ret = TRUE;
967 PCCRL_CONTEXT toAdd = NULL, existing = NULL;
969 TRACE("(%p, %p, %08x, %p)\n", hCertStore, pCrlContext,
970 dwAddDisposition, ppStoreContext);
972 /* Weird case to pass a test */
973 if (dwAddDisposition == 0)
975 SetLastError(STATUS_ACCESS_VIOLATION);
976 return FALSE;
978 if (dwAddDisposition != CERT_STORE_ADD_ALWAYS)
980 existing = CertFindCRLInStore(hCertStore, 0, 0, CRL_FIND_EXISTING,
981 pCrlContext, NULL);
984 switch (dwAddDisposition)
986 case CERT_STORE_ADD_ALWAYS:
987 toAdd = CertDuplicateCRLContext(pCrlContext);
988 break;
989 case CERT_STORE_ADD_NEW:
990 if (existing)
992 TRACE("found matching CRL, not adding\n");
993 SetLastError(CRYPT_E_EXISTS);
994 ret = FALSE;
996 else
997 toAdd = CertDuplicateCRLContext(pCrlContext);
998 break;
999 case CERT_STORE_ADD_NEWER:
1000 if (existing)
1002 LONG newer = CompareFileTime(&existing->pCrlInfo->ThisUpdate,
1003 &pCrlContext->pCrlInfo->ThisUpdate);
1005 if (newer < 0)
1006 toAdd = CertDuplicateCRLContext(pCrlContext);
1007 else
1009 TRACE("existing CRL is newer, not adding\n");
1010 SetLastError(CRYPT_E_EXISTS);
1011 ret = FALSE;
1014 else
1015 toAdd = CertDuplicateCRLContext(pCrlContext);
1016 break;
1017 case CERT_STORE_ADD_NEWER_INHERIT_PROPERTIES:
1018 if (existing)
1020 LONG newer = CompareFileTime(&existing->pCrlInfo->ThisUpdate,
1021 &pCrlContext->pCrlInfo->ThisUpdate);
1023 if (newer < 0)
1025 toAdd = CertDuplicateCRLContext(pCrlContext);
1026 Context_CopyProperties(toAdd, existing);
1028 else
1030 TRACE("existing CRL is newer, not adding\n");
1031 SetLastError(CRYPT_E_EXISTS);
1032 ret = FALSE;
1035 else
1036 toAdd = CertDuplicateCRLContext(pCrlContext);
1037 break;
1038 case CERT_STORE_ADD_REPLACE_EXISTING:
1039 toAdd = CertDuplicateCRLContext(pCrlContext);
1040 break;
1041 case CERT_STORE_ADD_REPLACE_EXISTING_INHERIT_PROPERTIES:
1042 toAdd = CertDuplicateCRLContext(pCrlContext);
1043 if (existing)
1044 Context_CopyProperties(toAdd, existing);
1045 break;
1046 case CERT_STORE_ADD_USE_EXISTING:
1047 if (existing)
1049 Context_CopyProperties(existing, pCrlContext);
1050 if (ppStoreContext)
1051 *ppStoreContext = CertDuplicateCRLContext(existing);
1053 else
1054 toAdd = CertDuplicateCRLContext(pCrlContext);
1055 break;
1056 default:
1057 FIXME("Unimplemented add disposition %d\n", dwAddDisposition);
1058 ret = FALSE;
1061 if (toAdd)
1063 if (store) {
1064 context_t *ret_context;
1065 ret = store->vtbl->crls.addContext(store, context_from_ptr(toAdd),
1066 existing ? context_from_ptr(existing) : NULL, ppStoreContext ? &ret_context : NULL, FALSE);
1067 if (ret && ppStoreContext)
1068 *ppStoreContext = context_ptr(ret_context);
1069 }else if (ppStoreContext) {
1070 *ppStoreContext = CertDuplicateCRLContext(toAdd);
1072 CertFreeCRLContext(toAdd);
1074 if (existing)
1075 CertFreeCRLContext(existing);
1077 TRACE("returning %d\n", ret);
1078 return ret;
1081 BOOL WINAPI CertDeleteCRLFromStore(PCCRL_CONTEXT pCrlContext)
1083 WINECRYPT_CERTSTORE *hcs;
1084 BOOL ret;
1086 TRACE("(%p)\n", pCrlContext);
1088 if (!pCrlContext)
1089 return TRUE;
1091 hcs = pCrlContext->hCertStore;
1093 if (hcs->dwMagic != WINE_CRYPTCERTSTORE_MAGIC)
1094 return FALSE;
1096 ret = hcs->vtbl->crls.delete(hcs, &crl_from_ptr(pCrlContext)->base);
1097 if (ret)
1098 ret = CertFreeCRLContext(pCrlContext);
1099 return ret;
1102 PCCRL_CONTEXT WINAPI CertEnumCRLsInStore(HCERTSTORE hCertStore, PCCRL_CONTEXT pPrev)
1104 crl_t *ret, *prev = pPrev ? crl_from_ptr(pPrev) : NULL;
1105 WINECRYPT_CERTSTORE *hcs = hCertStore;
1107 TRACE("(%p, %p)\n", hCertStore, pPrev);
1108 if (!hCertStore)
1109 ret = NULL;
1110 else if (hcs->dwMagic != WINE_CRYPTCERTSTORE_MAGIC)
1111 ret = NULL;
1112 else
1113 ret = (crl_t*)hcs->vtbl->crls.enumContext(hcs, prev ? &prev->base : NULL);
1114 return ret ? &ret->ctx : NULL;
1117 HCERTSTORE WINAPI CertDuplicateStore(HCERTSTORE hCertStore)
1119 WINECRYPT_CERTSTORE *hcs = hCertStore;
1121 TRACE("(%p)\n", hCertStore);
1123 if (hcs && hcs->dwMagic == WINE_CRYPTCERTSTORE_MAGIC)
1124 hcs->vtbl->addref(hcs);
1125 return hCertStore;
1128 BOOL WINAPI CertCloseStore(HCERTSTORE hCertStore, DWORD dwFlags)
1130 WINECRYPT_CERTSTORE *hcs = hCertStore;
1131 DWORD res;
1133 TRACE("(%p, %08x)\n", hCertStore, dwFlags);
1135 if( ! hCertStore )
1136 return TRUE;
1138 if ( hcs->dwMagic != WINE_CRYPTCERTSTORE_MAGIC )
1139 return FALSE;
1141 res = hcs->vtbl->release(hcs, dwFlags);
1142 if (res != ERROR_SUCCESS) {
1143 SetLastError(res);
1144 return FALSE;
1147 return TRUE;
1150 BOOL WINAPI CertControlStore(HCERTSTORE hCertStore, DWORD dwFlags,
1151 DWORD dwCtrlType, void const *pvCtrlPara)
1153 WINECRYPT_CERTSTORE *hcs = hCertStore;
1154 BOOL ret;
1156 TRACE("(%p, %08x, %d, %p)\n", hCertStore, dwFlags, dwCtrlType,
1157 pvCtrlPara);
1159 if (!hcs)
1160 ret = FALSE;
1161 else if (hcs->dwMagic != WINE_CRYPTCERTSTORE_MAGIC)
1162 ret = FALSE;
1163 else
1165 if (hcs->vtbl->control)
1166 ret = hcs->vtbl->control(hcs, dwFlags, dwCtrlType, pvCtrlPara);
1167 else
1168 ret = TRUE;
1170 return ret;
1173 BOOL WINAPI CertGetStoreProperty(HCERTSTORE hCertStore, DWORD dwPropId,
1174 void *pvData, DWORD *pcbData)
1176 WINECRYPT_CERTSTORE *store = hCertStore;
1177 BOOL ret = FALSE;
1179 TRACE("(%p, %d, %p, %p)\n", hCertStore, dwPropId, pvData, pcbData);
1181 switch (dwPropId)
1183 case CERT_ACCESS_STATE_PROP_ID:
1184 if (!pvData)
1186 *pcbData = sizeof(DWORD);
1187 ret = TRUE;
1189 else if (*pcbData < sizeof(DWORD))
1191 SetLastError(ERROR_MORE_DATA);
1192 *pcbData = sizeof(DWORD);
1194 else
1196 DWORD state = 0;
1198 if (store->type != StoreTypeMem &&
1199 !(store->dwOpenFlags & CERT_STORE_READONLY_FLAG))
1200 state |= CERT_ACCESS_STATE_WRITE_PERSIST_FLAG;
1201 *(DWORD *)pvData = state;
1202 ret = TRUE;
1204 break;
1205 default:
1206 if (store->properties)
1208 CRYPT_DATA_BLOB blob;
1210 ret = ContextPropertyList_FindProperty(store->properties, dwPropId,
1211 &blob);
1212 if (ret)
1214 if (!pvData)
1215 *pcbData = blob.cbData;
1216 else if (*pcbData < blob.cbData)
1218 SetLastError(ERROR_MORE_DATA);
1219 *pcbData = blob.cbData;
1220 ret = FALSE;
1222 else
1224 memcpy(pvData, blob.pbData, blob.cbData);
1225 *pcbData = blob.cbData;
1228 else
1229 SetLastError(CRYPT_E_NOT_FOUND);
1231 else
1232 SetLastError(CRYPT_E_NOT_FOUND);
1234 return ret;
1237 BOOL WINAPI CertSetStoreProperty(HCERTSTORE hCertStore, DWORD dwPropId,
1238 DWORD dwFlags, const void *pvData)
1240 WINECRYPT_CERTSTORE *store = hCertStore;
1241 BOOL ret = FALSE;
1243 TRACE("(%p, %d, %08x, %p)\n", hCertStore, dwPropId, dwFlags, pvData);
1245 if (!store->properties)
1246 store->properties = ContextPropertyList_Create();
1247 switch (dwPropId)
1249 case CERT_ACCESS_STATE_PROP_ID:
1250 SetLastError(E_INVALIDARG);
1251 break;
1252 default:
1253 if (pvData)
1255 const CRYPT_DATA_BLOB *blob = pvData;
1257 ret = ContextPropertyList_SetProperty(store->properties, dwPropId,
1258 blob->pbData, blob->cbData);
1260 else
1262 ContextPropertyList_RemoveProperty(store->properties, dwPropId);
1263 ret = TRUE;
1266 return ret;
1269 static LONG CRYPT_OpenParentStore(DWORD dwFlags,
1270 void *pvSystemStoreLocationPara, HKEY *key)
1272 HKEY root;
1273 LPCWSTR base;
1275 TRACE("(%08x, %p)\n", dwFlags, pvSystemStoreLocationPara);
1277 switch (dwFlags & CERT_SYSTEM_STORE_LOCATION_MASK)
1279 case CERT_SYSTEM_STORE_LOCAL_MACHINE:
1280 root = HKEY_LOCAL_MACHINE;
1281 base = CERT_LOCAL_MACHINE_SYSTEM_STORE_REGPATH;
1282 break;
1283 case CERT_SYSTEM_STORE_CURRENT_USER:
1284 root = HKEY_CURRENT_USER;
1285 base = CERT_LOCAL_MACHINE_SYSTEM_STORE_REGPATH;
1286 break;
1287 case CERT_SYSTEM_STORE_CURRENT_SERVICE:
1288 /* hklm\Software\Microsoft\Cryptography\Services\servicename\
1289 * SystemCertificates
1291 FIXME("CERT_SYSTEM_STORE_CURRENT_SERVICE\n");
1292 return ERROR_FILE_NOT_FOUND;
1293 case CERT_SYSTEM_STORE_SERVICES:
1294 /* hklm\Software\Microsoft\Cryptography\Services\servicename\
1295 * SystemCertificates
1297 FIXME("CERT_SYSTEM_STORE_SERVICES\n");
1298 return ERROR_FILE_NOT_FOUND;
1299 case CERT_SYSTEM_STORE_USERS:
1300 /* hku\user sid\Software\Microsoft\SystemCertificates */
1301 FIXME("CERT_SYSTEM_STORE_USERS\n");
1302 return ERROR_FILE_NOT_FOUND;
1303 case CERT_SYSTEM_STORE_CURRENT_USER_GROUP_POLICY:
1304 root = HKEY_CURRENT_USER;
1305 base = CERT_GROUP_POLICY_SYSTEM_STORE_REGPATH;
1306 break;
1307 case CERT_SYSTEM_STORE_LOCAL_MACHINE_GROUP_POLICY:
1308 root = HKEY_LOCAL_MACHINE;
1309 base = CERT_GROUP_POLICY_SYSTEM_STORE_REGPATH;
1310 break;
1311 case CERT_SYSTEM_STORE_LOCAL_MACHINE_ENTERPRISE:
1312 /* hklm\Software\Microsoft\EnterpriseCertificates */
1313 FIXME("CERT_SYSTEM_STORE_LOCAL_MACHINE_ENTERPRISE\n");
1314 return ERROR_FILE_NOT_FOUND;
1315 default:
1316 return ERROR_FILE_NOT_FOUND;
1319 return RegOpenKeyExW(root, base, 0, KEY_READ, key);
1322 BOOL WINAPI CertEnumSystemStore(DWORD dwFlags, void *pvSystemStoreLocationPara,
1323 void *pvArg, PFN_CERT_ENUM_SYSTEM_STORE pfnEnum)
1325 BOOL ret = FALSE;
1326 LONG rc;
1327 HKEY key;
1328 CERT_SYSTEM_STORE_INFO info = { sizeof(info) };
1330 TRACE("(%08x, %p, %p, %p)\n", dwFlags, pvSystemStoreLocationPara, pvArg,
1331 pfnEnum);
1333 rc = CRYPT_OpenParentStore(dwFlags, pvArg, &key);
1334 if (!rc)
1336 DWORD index = 0;
1338 ret = TRUE;
1339 do {
1340 WCHAR name[MAX_PATH];
1341 DWORD size = sizeof(name) / sizeof(name[0]);
1343 rc = RegEnumKeyExW(key, index++, name, &size, NULL, NULL, NULL,
1344 NULL);
1345 if (!rc)
1346 ret = pfnEnum(name, dwFlags, &info, NULL, pvArg);
1347 } while (ret && !rc);
1348 if (ret && rc != ERROR_NO_MORE_ITEMS)
1349 SetLastError(rc);
1351 else
1352 SetLastError(rc);
1353 /* Include root store for the local machine location (it isn't in the
1354 * registry)
1356 if (ret && (dwFlags & CERT_SYSTEM_STORE_LOCATION_MASK) ==
1357 CERT_SYSTEM_STORE_LOCAL_MACHINE)
1358 ret = pfnEnum(rootW, dwFlags, &info, NULL, pvArg);
1359 return ret;
1362 BOOL WINAPI CertEnumPhysicalStore(const void *pvSystemStore, DWORD dwFlags,
1363 void *pvArg, PFN_CERT_ENUM_PHYSICAL_STORE pfnEnum)
1365 if (dwFlags & CERT_SYSTEM_STORE_RELOCATE_FLAG)
1366 FIXME("(%p, %08x, %p, %p): stub\n", pvSystemStore, dwFlags, pvArg,
1367 pfnEnum);
1368 else
1369 FIXME("(%s, %08x, %p, %p): stub\n", debugstr_w(pvSystemStore),
1370 dwFlags, pvArg,
1371 pfnEnum);
1372 return FALSE;
1375 BOOL WINAPI CertRegisterPhysicalStore(const void *pvSystemStore, DWORD dwFlags,
1376 LPCWSTR pwszStoreName, PCERT_PHYSICAL_STORE_INFO pStoreInfo, void *pvReserved)
1378 if (dwFlags & CERT_SYSTEM_STORE_RELOCATE_FLAG)
1379 FIXME("(%p, %08x, %s, %p, %p): stub\n", pvSystemStore, dwFlags,
1380 debugstr_w(pwszStoreName), pStoreInfo, pvReserved);
1381 else
1382 FIXME("(%s, %08x, %s, %p, %p): stub\n", debugstr_w(pvSystemStore),
1383 dwFlags, debugstr_w(pwszStoreName), pStoreInfo, pvReserved);
1384 return FALSE;
1387 BOOL WINAPI CertRegisterSystemStore(const void *pvSystemStore, DWORD dwFlags,
1388 PCERT_SYSTEM_STORE_INFO pStoreInfo, void *pvReserved)
1390 HCERTSTORE hstore;
1392 if (dwFlags & CERT_SYSTEM_STORE_RELOCATE_FLAG )
1394 FIXME("(%p, %08x, %p, %p): flag not supported\n", pvSystemStore, dwFlags, pStoreInfo, pvReserved);
1395 return FALSE;
1398 TRACE("(%s, %08x, %p, %p)\n", debugstr_w(pvSystemStore), dwFlags, pStoreInfo, pvReserved);
1400 hstore = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY_W, 0, 0, dwFlags, pvSystemStore);
1401 if (hstore)
1403 CertCloseStore(hstore, 0);
1404 return TRUE;
1407 return FALSE;
1410 BOOL WINAPI CertUnregisterSystemStore(void *pvSystemStore, DWORD dwFlags)
1412 HCERTSTORE hstore;
1414 if (dwFlags & CERT_SYSTEM_STORE_RELOCATE_FLAG)
1416 FIXME("(%p, %08x): flag not supported\n", pvSystemStore, dwFlags);
1417 return FALSE;
1419 TRACE("(%s, %08x)\n", debugstr_w(pvSystemStore), dwFlags);
1421 hstore = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY_W, 0, 0, dwFlags | CERT_STORE_OPEN_EXISTING_FLAG, pvSystemStore);
1422 if (hstore == NULL)
1423 return FALSE;
1425 hstore = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY_W, 0, 0, dwFlags | CERT_STORE_DELETE_FLAG, pvSystemStore);
1426 if (hstore == NULL && GetLastError() == 0)
1427 return TRUE;
1429 return FALSE;
1432 static void EmptyStore_addref(WINECRYPT_CERTSTORE *store)
1434 TRACE("(%p)\n", store);
1437 static DWORD EmptyStore_release(WINECRYPT_CERTSTORE *store, DWORD flags)
1439 TRACE("(%p)\n", store);
1440 return E_UNEXPECTED;
1443 static void EmptyStore_releaseContext(WINECRYPT_CERTSTORE *store, context_t *context)
1445 Context_Free(context);
1448 static BOOL EmptyStore_add(WINECRYPT_CERTSTORE *store, context_t *context,
1449 context_t *replace, context_t **ret_context, BOOL use_link)
1451 TRACE("(%p, %p, %p, %p)\n", store, context, replace, ret_context);
1453 /* FIXME: We should clone the context */
1454 if(ret_context) {
1455 Context_AddRef(context);
1456 *ret_context = context;
1459 return TRUE;
1462 static context_t *EmptyStore_enum(WINECRYPT_CERTSTORE *store, context_t *prev)
1464 TRACE("(%p, %p)\n", store, prev);
1466 SetLastError(CRYPT_E_NOT_FOUND);
1467 return NULL;
1470 static BOOL EmptyStore_delete(WINECRYPT_CERTSTORE *store, context_t *context)
1472 return TRUE;
1475 static BOOL EmptyStore_control(WINECRYPT_CERTSTORE *store, DWORD flags, DWORD ctrl_type, void const *ctrl_para)
1477 TRACE("()\n");
1479 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1480 return FALSE;
1483 static const store_vtbl_t EmptyStoreVtbl = {
1484 EmptyStore_addref,
1485 EmptyStore_release,
1486 EmptyStore_releaseContext,
1487 EmptyStore_control,
1489 EmptyStore_add,
1490 EmptyStore_enum,
1491 EmptyStore_delete
1492 }, {
1493 EmptyStore_add,
1494 EmptyStore_enum,
1495 EmptyStore_delete
1496 }, {
1497 EmptyStore_add,
1498 EmptyStore_enum,
1499 EmptyStore_delete
1503 WINECRYPT_CERTSTORE empty_store;
1505 void init_empty_store(void)
1507 CRYPT_InitStore(&empty_store, CERT_STORE_READONLY_FLAG, StoreTypeEmpty, &EmptyStoreVtbl);