ntdll/tests: Added more registry symlink tests.
[wine.git] / dlls / crypt32 / store.c
blobd5d74432e1a64a81e1542f0db13f43dfe35a8f98
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;
427 /* FIXME: In Windows, the root store (even the current user location) is
428 * protected: adding to it or removing from it present a user interface,
429 * and the keys are owned by the system process, not the current user.
430 * Wine's registry doesn't implement access controls, so a similar
431 * mechanism isn't possible yet.
433 if ((dwFlags & CERT_SYSTEM_STORE_LOCATION_MASK) ==
434 CERT_SYSTEM_STORE_LOCAL_MACHINE && !lstrcmpiW(storeName, rootW))
435 return CRYPT_RootOpenStore(hCryptProv, dwFlags);
437 switch (dwFlags & CERT_SYSTEM_STORE_LOCATION_MASK)
439 case CERT_SYSTEM_STORE_LOCAL_MACHINE:
440 root = HKEY_LOCAL_MACHINE;
441 base = CERT_LOCAL_MACHINE_SYSTEM_STORE_REGPATH;
442 break;
443 case CERT_SYSTEM_STORE_CURRENT_USER:
444 root = HKEY_CURRENT_USER;
445 base = CERT_LOCAL_MACHINE_SYSTEM_STORE_REGPATH;
446 break;
447 case CERT_SYSTEM_STORE_CURRENT_SERVICE:
448 /* hklm\Software\Microsoft\Cryptography\Services\servicename\
449 * SystemCertificates
451 FIXME("CERT_SYSTEM_STORE_CURRENT_SERVICE, %s: stub\n",
452 debugstr_w(storeName));
453 return NULL;
454 case CERT_SYSTEM_STORE_SERVICES:
455 /* hklm\Software\Microsoft\Cryptography\Services\servicename\
456 * SystemCertificates
458 FIXME("CERT_SYSTEM_STORE_SERVICES, %s: stub\n",
459 debugstr_w(storeName));
460 return NULL;
461 case CERT_SYSTEM_STORE_USERS:
462 /* hku\user sid\Software\Microsoft\SystemCertificates */
463 FIXME("CERT_SYSTEM_STORE_USERS, %s: stub\n",
464 debugstr_w(storeName));
465 return NULL;
466 case CERT_SYSTEM_STORE_CURRENT_USER_GROUP_POLICY:
467 root = HKEY_CURRENT_USER;
468 base = CERT_GROUP_POLICY_SYSTEM_STORE_REGPATH;
469 break;
470 case CERT_SYSTEM_STORE_LOCAL_MACHINE_GROUP_POLICY:
471 root = HKEY_LOCAL_MACHINE;
472 base = CERT_GROUP_POLICY_SYSTEM_STORE_REGPATH;
473 break;
474 case CERT_SYSTEM_STORE_LOCAL_MACHINE_ENTERPRISE:
475 /* hklm\Software\Microsoft\EnterpriseCertificates */
476 FIXME("CERT_SYSTEM_STORE_LOCAL_MACHINE_ENTERPRISE, %s: stub\n",
477 debugstr_w(storeName));
478 return NULL;
479 default:
480 SetLastError(E_INVALIDARG);
481 return NULL;
484 storePath = CryptMemAlloc((lstrlenW(base) + lstrlenW(storeName) + 2) *
485 sizeof(WCHAR));
486 if (storePath)
488 LONG rc;
489 HKEY key;
490 REGSAM sam = dwFlags & CERT_STORE_READONLY_FLAG ? KEY_READ :
491 KEY_ALL_ACCESS;
493 wsprintfW(storePath, fmt, base, storeName);
494 if (dwFlags & CERT_STORE_OPEN_EXISTING_FLAG)
495 rc = RegOpenKeyExW(root, storePath, 0, sam, &key);
496 else
498 DWORD disp;
500 rc = RegCreateKeyExW(root, storePath, 0, NULL, 0, sam, NULL,
501 &key, &disp);
502 if (!rc && dwFlags & CERT_STORE_CREATE_NEW_FLAG &&
503 disp == REG_OPENED_EXISTING_KEY)
505 RegCloseKey(key);
506 rc = ERROR_FILE_EXISTS;
509 if (!rc)
511 store = CRYPT_RegOpenStore(hCryptProv, dwFlags, key);
512 RegCloseKey(key);
514 else
515 SetLastError(rc);
516 CryptMemFree(storePath);
518 return store;
521 static WINECRYPT_CERTSTORE *CRYPT_SysRegOpenStoreA(HCRYPTPROV hCryptProv,
522 DWORD dwFlags, const void *pvPara)
524 int len;
525 WINECRYPT_CERTSTORE *ret = NULL;
527 TRACE("(%ld, %08x, %s)\n", hCryptProv, dwFlags,
528 debugstr_a(pvPara));
530 if (!pvPara)
532 SetLastError(ERROR_FILE_NOT_FOUND);
533 return NULL;
535 len = MultiByteToWideChar(CP_ACP, 0, pvPara, -1, NULL, 0);
536 if (len)
538 LPWSTR storeName = CryptMemAlloc(len * sizeof(WCHAR));
540 if (storeName)
542 MultiByteToWideChar(CP_ACP, 0, pvPara, -1, storeName, len);
543 ret = CRYPT_SysRegOpenStoreW(hCryptProv, dwFlags, storeName);
544 CryptMemFree(storeName);
547 return ret;
550 static WINECRYPT_CERTSTORE *CRYPT_SysOpenStoreW(HCRYPTPROV hCryptProv,
551 DWORD dwFlags, const void *pvPara)
553 HCERTSTORE store = 0;
554 BOOL ret;
556 TRACE("(%ld, %08x, %s)\n", hCryptProv, dwFlags,
557 debugstr_w(pvPara));
559 if (!pvPara)
561 SetLastError(ERROR_FILE_NOT_FOUND);
562 return NULL;
564 /* This returns a different error than system registry stores if the
565 * location is invalid.
567 switch (dwFlags & CERT_SYSTEM_STORE_LOCATION_MASK)
569 case CERT_SYSTEM_STORE_LOCAL_MACHINE:
570 case CERT_SYSTEM_STORE_CURRENT_USER:
571 case CERT_SYSTEM_STORE_CURRENT_SERVICE:
572 case CERT_SYSTEM_STORE_SERVICES:
573 case CERT_SYSTEM_STORE_USERS:
574 case CERT_SYSTEM_STORE_CURRENT_USER_GROUP_POLICY:
575 case CERT_SYSTEM_STORE_LOCAL_MACHINE_GROUP_POLICY:
576 case CERT_SYSTEM_STORE_LOCAL_MACHINE_ENTERPRISE:
577 ret = TRUE;
578 break;
579 default:
580 SetLastError(ERROR_FILE_NOT_FOUND);
581 ret = FALSE;
583 if (ret)
585 HCERTSTORE regStore = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY_W,
586 0, 0, dwFlags, pvPara);
588 if (regStore)
590 store = CertOpenStore(CERT_STORE_PROV_COLLECTION, 0, 0,
591 CERT_STORE_CREATE_NEW_FLAG, NULL);
592 CertAddStoreToCollection(store, regStore,
593 dwFlags & CERT_STORE_READONLY_FLAG ? 0 :
594 CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
595 CertCloseStore(regStore, 0);
596 /* CERT_SYSTEM_STORE_CURRENT_USER returns both the HKCU and HKLM
597 * stores.
599 if ((dwFlags & CERT_SYSTEM_STORE_LOCATION_MASK) ==
600 CERT_SYSTEM_STORE_CURRENT_USER)
602 dwFlags &= ~CERT_SYSTEM_STORE_CURRENT_USER;
603 dwFlags |= CERT_SYSTEM_STORE_LOCAL_MACHINE;
604 regStore = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY_W, 0,
605 0, dwFlags, pvPara);
606 if (regStore)
608 CertAddStoreToCollection(store, regStore,
609 dwFlags & CERT_STORE_READONLY_FLAG ? 0 :
610 CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
611 CertCloseStore(regStore, 0);
614 /* System store doesn't need crypto provider, so close it */
615 if (hCryptProv && !(dwFlags & CERT_STORE_NO_CRYPT_RELEASE_FLAG))
616 CryptReleaseContext(hCryptProv, 0);
619 return store;
622 static WINECRYPT_CERTSTORE *CRYPT_SysOpenStoreA(HCRYPTPROV hCryptProv,
623 DWORD dwFlags, const void *pvPara)
625 int len;
626 WINECRYPT_CERTSTORE *ret = NULL;
628 TRACE("(%ld, %08x, %s)\n", hCryptProv, dwFlags,
629 debugstr_a(pvPara));
631 if (!pvPara)
633 SetLastError(ERROR_FILE_NOT_FOUND);
634 return NULL;
636 len = MultiByteToWideChar(CP_ACP, 0, pvPara, -1, NULL, 0);
637 if (len)
639 LPWSTR storeName = CryptMemAlloc(len * sizeof(WCHAR));
641 if (storeName)
643 MultiByteToWideChar(CP_ACP, 0, pvPara, -1, storeName, len);
644 ret = CRYPT_SysOpenStoreW(hCryptProv, dwFlags, storeName);
645 CryptMemFree(storeName);
648 return ret;
651 static void WINAPI CRYPT_MsgCloseStore(HCERTSTORE hCertStore, DWORD dwFlags)
653 HCRYPTMSG msg = hCertStore;
655 TRACE("(%p, %08x)\n", msg, dwFlags);
656 CryptMsgClose(msg);
659 static void *msgProvFuncs[] = {
660 CRYPT_MsgCloseStore,
663 static WINECRYPT_CERTSTORE *CRYPT_MsgOpenStore(HCRYPTPROV hCryptProv,
664 DWORD dwFlags, const void *pvPara)
666 WINECRYPT_CERTSTORE *store = NULL;
667 HCRYPTMSG msg = (HCRYPTMSG)pvPara;
668 WINECRYPT_CERTSTORE *memStore;
670 TRACE("(%ld, %08x, %p)\n", hCryptProv, dwFlags, pvPara);
672 memStore = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
673 CERT_STORE_CREATE_NEW_FLAG, NULL);
674 if (memStore)
676 BOOL ret;
677 DWORD size, count, i;
679 size = sizeof(count);
680 ret = CryptMsgGetParam(msg, CMSG_CERT_COUNT_PARAM, 0, &count, &size);
681 for (i = 0; ret && i < count; i++)
683 size = 0;
684 ret = CryptMsgGetParam(msg, CMSG_CERT_PARAM, i, NULL, &size);
685 if (ret)
687 LPBYTE buf = CryptMemAlloc(size);
689 if (buf)
691 ret = CryptMsgGetParam(msg, CMSG_CERT_PARAM, i, buf, &size);
692 if (ret)
693 ret = CertAddEncodedCertificateToStore(memStore,
694 X509_ASN_ENCODING, buf, size, CERT_STORE_ADD_ALWAYS,
695 NULL);
696 CryptMemFree(buf);
700 size = sizeof(count);
701 ret = CryptMsgGetParam(msg, CMSG_CRL_COUNT_PARAM, 0, &count, &size);
702 for (i = 0; ret && i < count; i++)
704 size = 0;
705 ret = CryptMsgGetParam(msg, CMSG_CRL_PARAM, i, NULL, &size);
706 if (ret)
708 LPBYTE buf = CryptMemAlloc(size);
710 if (buf)
712 ret = CryptMsgGetParam(msg, CMSG_CRL_PARAM, i, buf, &size);
713 if (ret)
714 ret = CertAddEncodedCRLToStore(memStore,
715 X509_ASN_ENCODING, buf, size, CERT_STORE_ADD_ALWAYS,
716 NULL);
717 CryptMemFree(buf);
721 if (ret)
723 CERT_STORE_PROV_INFO provInfo = { 0 };
725 provInfo.cbSize = sizeof(provInfo);
726 provInfo.cStoreProvFunc = sizeof(msgProvFuncs) /
727 sizeof(msgProvFuncs[0]);
728 provInfo.rgpvStoreProvFunc = msgProvFuncs;
729 provInfo.hStoreProv = CryptMsgDuplicate(msg);
730 store = CRYPT_ProvCreateStore(dwFlags, memStore, &provInfo);
731 /* Msg store doesn't need crypto provider, so close it */
732 if (hCryptProv && !(dwFlags & CERT_STORE_NO_CRYPT_RELEASE_FLAG))
733 CryptReleaseContext(hCryptProv, 0);
735 else
736 CertCloseStore(memStore, 0);
738 TRACE("returning %p\n", store);
739 return store;
742 static WINECRYPT_CERTSTORE *CRYPT_PKCSOpenStore(HCRYPTPROV hCryptProv,
743 DWORD dwFlags, const void *pvPara)
745 HCRYPTMSG msg;
746 WINECRYPT_CERTSTORE *store = NULL;
747 const CRYPT_DATA_BLOB *data = pvPara;
748 BOOL ret;
749 DWORD msgOpenFlags = dwFlags & CERT_STORE_NO_CRYPT_RELEASE_FLAG ? 0 :
750 CMSG_CRYPT_RELEASE_CONTEXT_FLAG;
752 TRACE("(%ld, %08x, %p)\n", hCryptProv, dwFlags, pvPara);
754 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, msgOpenFlags, CMSG_SIGNED,
755 hCryptProv, NULL, NULL);
756 ret = CryptMsgUpdate(msg, data->pbData, data->cbData, TRUE);
757 if (!ret)
759 CryptMsgClose(msg);
760 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, msgOpenFlags, 0,
761 hCryptProv, NULL, NULL);
762 ret = CryptMsgUpdate(msg, data->pbData, data->cbData, TRUE);
763 if (ret)
765 DWORD type, size = sizeof(type);
767 /* Only signed messages are allowed, check type */
768 ret = CryptMsgGetParam(msg, CMSG_TYPE_PARAM, 0, &type, &size);
769 if (ret && type != CMSG_SIGNED)
771 SetLastError(CRYPT_E_INVALID_MSG_TYPE);
772 ret = FALSE;
776 if (ret)
777 store = CRYPT_MsgOpenStore(0, dwFlags, msg);
778 CryptMsgClose(msg);
779 TRACE("returning %p\n", store);
780 return store;
783 static WINECRYPT_CERTSTORE *CRYPT_SerializedOpenStore(HCRYPTPROV hCryptProv,
784 DWORD dwFlags, const void *pvPara)
786 HCERTSTORE store;
787 const CRYPT_DATA_BLOB *data = pvPara;
789 TRACE("(%ld, %08x, %p)\n", hCryptProv, dwFlags, pvPara);
791 if (dwFlags & CERT_STORE_DELETE_FLAG)
793 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
794 return NULL;
797 store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
798 CERT_STORE_CREATE_NEW_FLAG, NULL);
799 if (store)
801 if (!CRYPT_ReadSerializedStoreFromBlob(data, store))
803 CertCloseStore(store, 0);
804 store = NULL;
807 TRACE("returning %p\n", store);
808 return (WINECRYPT_CERTSTORE*)store;
811 static WINECRYPT_CERTSTORE *CRYPT_PhysOpenStoreW(HCRYPTPROV hCryptProv,
812 DWORD dwFlags, const void *pvPara)
814 if (dwFlags & CERT_SYSTEM_STORE_RELOCATE_FLAG)
815 FIXME("(%ld, %08x, %p): stub\n", hCryptProv, dwFlags, pvPara);
816 else
817 FIXME("(%ld, %08x, %s): stub\n", hCryptProv, dwFlags,
818 debugstr_w(pvPara));
819 return NULL;
822 HCERTSTORE WINAPI CertOpenStore(LPCSTR lpszStoreProvider,
823 DWORD dwMsgAndCertEncodingType, HCRYPTPROV_LEGACY hCryptProv, DWORD dwFlags,
824 const void* pvPara)
826 WINECRYPT_CERTSTORE *hcs;
827 StoreOpenFunc openFunc = NULL;
829 TRACE("(%s, %08x, %08lx, %08x, %p)\n", debugstr_a(lpszStoreProvider),
830 dwMsgAndCertEncodingType, hCryptProv, dwFlags, pvPara);
832 if (IS_INTOID(lpszStoreProvider))
834 switch (LOWORD(lpszStoreProvider))
836 case LOWORD(CERT_STORE_PROV_MSG):
837 openFunc = CRYPT_MsgOpenStore;
838 break;
839 case LOWORD(CERT_STORE_PROV_MEMORY):
840 openFunc = CRYPT_MemOpenStore;
841 break;
842 case LOWORD(CERT_STORE_PROV_FILE):
843 openFunc = CRYPT_FileOpenStore;
844 break;
845 case LOWORD(CERT_STORE_PROV_PKCS7):
846 openFunc = CRYPT_PKCSOpenStore;
847 break;
848 case LOWORD(CERT_STORE_PROV_SERIALIZED):
849 openFunc = CRYPT_SerializedOpenStore;
850 break;
851 case LOWORD(CERT_STORE_PROV_REG):
852 openFunc = CRYPT_RegOpenStore;
853 break;
854 case LOWORD(CERT_STORE_PROV_FILENAME_A):
855 openFunc = CRYPT_FileNameOpenStoreA;
856 break;
857 case LOWORD(CERT_STORE_PROV_FILENAME_W):
858 openFunc = CRYPT_FileNameOpenStoreW;
859 break;
860 case LOWORD(CERT_STORE_PROV_COLLECTION):
861 openFunc = CRYPT_CollectionOpenStore;
862 break;
863 case LOWORD(CERT_STORE_PROV_SYSTEM_A):
864 openFunc = CRYPT_SysOpenStoreA;
865 break;
866 case LOWORD(CERT_STORE_PROV_SYSTEM_W):
867 openFunc = CRYPT_SysOpenStoreW;
868 break;
869 case LOWORD(CERT_STORE_PROV_SYSTEM_REGISTRY_A):
870 openFunc = CRYPT_SysRegOpenStoreA;
871 break;
872 case LOWORD(CERT_STORE_PROV_SYSTEM_REGISTRY_W):
873 openFunc = CRYPT_SysRegOpenStoreW;
874 break;
875 case LOWORD(CERT_STORE_PROV_PHYSICAL_W):
876 openFunc = CRYPT_PhysOpenStoreW;
877 break;
878 default:
879 if (LOWORD(lpszStoreProvider))
880 FIXME("unimplemented type %d\n", LOWORD(lpszStoreProvider));
883 else if (!strcasecmp(lpszStoreProvider, sz_CERT_STORE_PROV_MEMORY))
884 openFunc = CRYPT_MemOpenStore;
885 else if (!strcasecmp(lpszStoreProvider, sz_CERT_STORE_PROV_FILENAME_W))
886 openFunc = CRYPT_FileOpenStore;
887 else if (!strcasecmp(lpszStoreProvider, sz_CERT_STORE_PROV_SYSTEM))
888 openFunc = CRYPT_SysOpenStoreW;
889 else if (!strcasecmp(lpszStoreProvider, sz_CERT_STORE_PROV_PKCS7))
890 openFunc = CRYPT_PKCSOpenStore;
891 else if (!strcasecmp(lpszStoreProvider, sz_CERT_STORE_PROV_SERIALIZED))
892 openFunc = CRYPT_SerializedOpenStore;
893 else if (!strcasecmp(lpszStoreProvider, sz_CERT_STORE_PROV_COLLECTION))
894 openFunc = CRYPT_CollectionOpenStore;
895 else if (!strcasecmp(lpszStoreProvider, sz_CERT_STORE_PROV_SYSTEM_REGISTRY))
896 openFunc = CRYPT_SysRegOpenStoreW;
897 else
899 FIXME("unimplemented type %s\n", lpszStoreProvider);
900 openFunc = NULL;
903 if (!openFunc)
904 hcs = CRYPT_ProvOpenStore(lpszStoreProvider, dwMsgAndCertEncodingType,
905 hCryptProv, dwFlags, pvPara);
906 else
907 hcs = openFunc(hCryptProv, dwFlags, pvPara);
908 return hcs;
911 HCERTSTORE WINAPI CertOpenSystemStoreA(HCRYPTPROV_LEGACY hProv,
912 LPCSTR szSubSystemProtocol)
914 if (!szSubSystemProtocol)
916 SetLastError(E_INVALIDARG);
917 return 0;
919 return CertOpenStore(CERT_STORE_PROV_SYSTEM_A, 0, hProv,
920 CERT_SYSTEM_STORE_CURRENT_USER, szSubSystemProtocol);
923 HCERTSTORE WINAPI CertOpenSystemStoreW(HCRYPTPROV_LEGACY hProv,
924 LPCWSTR szSubSystemProtocol)
926 if (!szSubSystemProtocol)
928 SetLastError(E_INVALIDARG);
929 return 0;
931 return CertOpenStore(CERT_STORE_PROV_SYSTEM_W, 0, hProv,
932 CERT_SYSTEM_STORE_CURRENT_USER, szSubSystemProtocol);
935 PCCERT_CONTEXT WINAPI CertEnumCertificatesInStore(HCERTSTORE hCertStore, PCCERT_CONTEXT pPrev)
937 cert_t *prev = pPrev ? cert_from_ptr(pPrev) : NULL, *ret;
938 WINECRYPT_CERTSTORE *hcs = hCertStore;
940 TRACE("(%p, %p)\n", hCertStore, pPrev);
941 if (!hCertStore)
942 ret = NULL;
943 else if (hcs->dwMagic != WINE_CRYPTCERTSTORE_MAGIC)
944 ret = NULL;
945 else
946 ret = (cert_t*)hcs->vtbl->certs.enumContext(hcs, prev ? &prev->base : NULL);
947 return ret ? &ret->ctx : NULL;
950 BOOL WINAPI CertDeleteCertificateFromStore(PCCERT_CONTEXT pCertContext)
952 WINECRYPT_CERTSTORE *hcs;
954 TRACE("(%p)\n", pCertContext);
956 if (!pCertContext)
957 return TRUE;
959 hcs = pCertContext->hCertStore;
961 if (hcs->dwMagic != WINE_CRYPTCERTSTORE_MAGIC)
962 return FALSE;
964 return hcs->vtbl->certs.delete(hcs, &cert_from_ptr(pCertContext)->base);
967 BOOL WINAPI CertAddCRLContextToStore(HCERTSTORE hCertStore,
968 PCCRL_CONTEXT pCrlContext, DWORD dwAddDisposition,
969 PCCRL_CONTEXT* ppStoreContext)
971 WINECRYPT_CERTSTORE *store = hCertStore;
972 BOOL ret = TRUE;
973 PCCRL_CONTEXT toAdd = NULL, existing = NULL;
975 TRACE("(%p, %p, %08x, %p)\n", hCertStore, pCrlContext,
976 dwAddDisposition, ppStoreContext);
978 /* Weird case to pass a test */
979 if (dwAddDisposition == 0)
981 SetLastError(STATUS_ACCESS_VIOLATION);
982 return FALSE;
984 if (dwAddDisposition != CERT_STORE_ADD_ALWAYS)
986 existing = CertFindCRLInStore(hCertStore, 0, 0, CRL_FIND_EXISTING,
987 pCrlContext, NULL);
990 switch (dwAddDisposition)
992 case CERT_STORE_ADD_ALWAYS:
993 toAdd = CertDuplicateCRLContext(pCrlContext);
994 break;
995 case CERT_STORE_ADD_NEW:
996 if (existing)
998 TRACE("found matching CRL, not adding\n");
999 SetLastError(CRYPT_E_EXISTS);
1000 ret = FALSE;
1002 else
1003 toAdd = CertDuplicateCRLContext(pCrlContext);
1004 break;
1005 case CERT_STORE_ADD_NEWER:
1006 if (existing)
1008 LONG newer = CompareFileTime(&existing->pCrlInfo->ThisUpdate,
1009 &pCrlContext->pCrlInfo->ThisUpdate);
1011 if (newer < 0)
1012 toAdd = CertDuplicateCRLContext(pCrlContext);
1013 else
1015 TRACE("existing CRL is newer, not adding\n");
1016 SetLastError(CRYPT_E_EXISTS);
1017 ret = FALSE;
1020 else
1021 toAdd = CertDuplicateCRLContext(pCrlContext);
1022 break;
1023 case CERT_STORE_ADD_NEWER_INHERIT_PROPERTIES:
1024 if (existing)
1026 LONG newer = CompareFileTime(&existing->pCrlInfo->ThisUpdate,
1027 &pCrlContext->pCrlInfo->ThisUpdate);
1029 if (newer < 0)
1031 toAdd = CertDuplicateCRLContext(pCrlContext);
1032 Context_CopyProperties(toAdd, existing);
1034 else
1036 TRACE("existing CRL is newer, not adding\n");
1037 SetLastError(CRYPT_E_EXISTS);
1038 ret = FALSE;
1041 else
1042 toAdd = CertDuplicateCRLContext(pCrlContext);
1043 break;
1044 case CERT_STORE_ADD_REPLACE_EXISTING:
1045 toAdd = CertDuplicateCRLContext(pCrlContext);
1046 break;
1047 case CERT_STORE_ADD_REPLACE_EXISTING_INHERIT_PROPERTIES:
1048 toAdd = CertDuplicateCRLContext(pCrlContext);
1049 if (existing)
1050 Context_CopyProperties(toAdd, existing);
1051 break;
1052 case CERT_STORE_ADD_USE_EXISTING:
1053 if (existing)
1055 Context_CopyProperties(existing, pCrlContext);
1056 if (ppStoreContext)
1057 *ppStoreContext = CertDuplicateCRLContext(existing);
1059 else
1060 toAdd = CertDuplicateCRLContext(pCrlContext);
1061 break;
1062 default:
1063 FIXME("Unimplemented add disposition %d\n", dwAddDisposition);
1064 ret = FALSE;
1067 if (toAdd)
1069 if (store) {
1070 context_t *ret_context;
1071 ret = store->vtbl->crls.addContext(store, context_from_ptr(toAdd),
1072 existing ? context_from_ptr(existing) : NULL, ppStoreContext ? &ret_context : NULL, FALSE);
1073 if (ret && ppStoreContext)
1074 *ppStoreContext = context_ptr(ret_context);
1075 }else if (ppStoreContext) {
1076 *ppStoreContext = CertDuplicateCRLContext(toAdd);
1078 CertFreeCRLContext(toAdd);
1080 if (existing)
1081 CertFreeCRLContext(existing);
1083 TRACE("returning %d\n", ret);
1084 return ret;
1087 BOOL WINAPI CertDeleteCRLFromStore(PCCRL_CONTEXT pCrlContext)
1089 WINECRYPT_CERTSTORE *hcs;
1090 BOOL ret;
1092 TRACE("(%p)\n", pCrlContext);
1094 if (!pCrlContext)
1095 return TRUE;
1097 hcs = pCrlContext->hCertStore;
1099 if (hcs->dwMagic != WINE_CRYPTCERTSTORE_MAGIC)
1100 return FALSE;
1102 ret = hcs->vtbl->crls.delete(hcs, &crl_from_ptr(pCrlContext)->base);
1103 if (ret)
1104 ret = CertFreeCRLContext(pCrlContext);
1105 return ret;
1108 PCCRL_CONTEXT WINAPI CertEnumCRLsInStore(HCERTSTORE hCertStore, PCCRL_CONTEXT pPrev)
1110 crl_t *ret, *prev = pPrev ? crl_from_ptr(pPrev) : NULL;
1111 WINECRYPT_CERTSTORE *hcs = hCertStore;
1113 TRACE("(%p, %p)\n", hCertStore, pPrev);
1114 if (!hCertStore)
1115 ret = NULL;
1116 else if (hcs->dwMagic != WINE_CRYPTCERTSTORE_MAGIC)
1117 ret = NULL;
1118 else
1119 ret = (crl_t*)hcs->vtbl->crls.enumContext(hcs, prev ? &prev->base : NULL);
1120 return ret ? &ret->ctx : NULL;
1123 HCERTSTORE WINAPI CertDuplicateStore(HCERTSTORE hCertStore)
1125 WINECRYPT_CERTSTORE *hcs = hCertStore;
1127 TRACE("(%p)\n", hCertStore);
1129 if (hcs && hcs->dwMagic == WINE_CRYPTCERTSTORE_MAGIC)
1130 hcs->vtbl->addref(hcs);
1131 return hCertStore;
1134 BOOL WINAPI CertCloseStore(HCERTSTORE hCertStore, DWORD dwFlags)
1136 WINECRYPT_CERTSTORE *hcs = hCertStore;
1137 DWORD res;
1139 TRACE("(%p, %08x)\n", hCertStore, dwFlags);
1141 if( ! hCertStore )
1142 return TRUE;
1144 if ( hcs->dwMagic != WINE_CRYPTCERTSTORE_MAGIC )
1145 return FALSE;
1147 res = hcs->vtbl->release(hcs, dwFlags);
1148 if (res != ERROR_SUCCESS) {
1149 SetLastError(res);
1150 return FALSE;
1153 return TRUE;
1156 BOOL WINAPI CertControlStore(HCERTSTORE hCertStore, DWORD dwFlags,
1157 DWORD dwCtrlType, void const *pvCtrlPara)
1159 WINECRYPT_CERTSTORE *hcs = hCertStore;
1160 BOOL ret;
1162 TRACE("(%p, %08x, %d, %p)\n", hCertStore, dwFlags, dwCtrlType,
1163 pvCtrlPara);
1165 if (!hcs)
1166 ret = FALSE;
1167 else if (hcs->dwMagic != WINE_CRYPTCERTSTORE_MAGIC)
1168 ret = FALSE;
1169 else
1171 if (hcs->vtbl->control)
1172 ret = hcs->vtbl->control(hcs, dwFlags, dwCtrlType, pvCtrlPara);
1173 else
1174 ret = TRUE;
1176 return ret;
1179 BOOL WINAPI CertGetStoreProperty(HCERTSTORE hCertStore, DWORD dwPropId,
1180 void *pvData, DWORD *pcbData)
1182 WINECRYPT_CERTSTORE *store = hCertStore;
1183 BOOL ret = FALSE;
1185 TRACE("(%p, %d, %p, %p)\n", hCertStore, dwPropId, pvData, pcbData);
1187 switch (dwPropId)
1189 case CERT_ACCESS_STATE_PROP_ID:
1190 if (!pvData)
1192 *pcbData = sizeof(DWORD);
1193 ret = TRUE;
1195 else if (*pcbData < sizeof(DWORD))
1197 SetLastError(ERROR_MORE_DATA);
1198 *pcbData = sizeof(DWORD);
1200 else
1202 DWORD state = 0;
1204 if (store->type != StoreTypeMem &&
1205 !(store->dwOpenFlags & CERT_STORE_READONLY_FLAG))
1206 state |= CERT_ACCESS_STATE_WRITE_PERSIST_FLAG;
1207 *(DWORD *)pvData = state;
1208 ret = TRUE;
1210 break;
1211 default:
1212 if (store->properties)
1214 CRYPT_DATA_BLOB blob;
1216 ret = ContextPropertyList_FindProperty(store->properties, dwPropId,
1217 &blob);
1218 if (ret)
1220 if (!pvData)
1221 *pcbData = blob.cbData;
1222 else if (*pcbData < blob.cbData)
1224 SetLastError(ERROR_MORE_DATA);
1225 *pcbData = blob.cbData;
1226 ret = FALSE;
1228 else
1230 memcpy(pvData, blob.pbData, blob.cbData);
1231 *pcbData = blob.cbData;
1234 else
1235 SetLastError(CRYPT_E_NOT_FOUND);
1237 else
1238 SetLastError(CRYPT_E_NOT_FOUND);
1240 return ret;
1243 BOOL WINAPI CertSetStoreProperty(HCERTSTORE hCertStore, DWORD dwPropId,
1244 DWORD dwFlags, const void *pvData)
1246 WINECRYPT_CERTSTORE *store = hCertStore;
1247 BOOL ret = FALSE;
1249 TRACE("(%p, %d, %08x, %p)\n", hCertStore, dwPropId, dwFlags, pvData);
1251 if (!store->properties)
1252 store->properties = ContextPropertyList_Create();
1253 switch (dwPropId)
1255 case CERT_ACCESS_STATE_PROP_ID:
1256 SetLastError(E_INVALIDARG);
1257 break;
1258 default:
1259 if (pvData)
1261 const CRYPT_DATA_BLOB *blob = pvData;
1263 ret = ContextPropertyList_SetProperty(store->properties, dwPropId,
1264 blob->pbData, blob->cbData);
1266 else
1268 ContextPropertyList_RemoveProperty(store->properties, dwPropId);
1269 ret = TRUE;
1272 return ret;
1275 static LONG CRYPT_OpenParentStore(DWORD dwFlags,
1276 void *pvSystemStoreLocationPara, HKEY *key)
1278 HKEY root;
1279 LPCWSTR base;
1281 TRACE("(%08x, %p)\n", dwFlags, pvSystemStoreLocationPara);
1283 switch (dwFlags & CERT_SYSTEM_STORE_LOCATION_MASK)
1285 case CERT_SYSTEM_STORE_LOCAL_MACHINE:
1286 root = HKEY_LOCAL_MACHINE;
1287 base = CERT_LOCAL_MACHINE_SYSTEM_STORE_REGPATH;
1288 break;
1289 case CERT_SYSTEM_STORE_CURRENT_USER:
1290 root = HKEY_CURRENT_USER;
1291 base = CERT_LOCAL_MACHINE_SYSTEM_STORE_REGPATH;
1292 break;
1293 case CERT_SYSTEM_STORE_CURRENT_SERVICE:
1294 /* hklm\Software\Microsoft\Cryptography\Services\servicename\
1295 * SystemCertificates
1297 FIXME("CERT_SYSTEM_STORE_CURRENT_SERVICE\n");
1298 return ERROR_FILE_NOT_FOUND;
1299 case CERT_SYSTEM_STORE_SERVICES:
1300 /* hklm\Software\Microsoft\Cryptography\Services\servicename\
1301 * SystemCertificates
1303 FIXME("CERT_SYSTEM_STORE_SERVICES\n");
1304 return ERROR_FILE_NOT_FOUND;
1305 case CERT_SYSTEM_STORE_USERS:
1306 /* hku\user sid\Software\Microsoft\SystemCertificates */
1307 FIXME("CERT_SYSTEM_STORE_USERS\n");
1308 return ERROR_FILE_NOT_FOUND;
1309 case CERT_SYSTEM_STORE_CURRENT_USER_GROUP_POLICY:
1310 root = HKEY_CURRENT_USER;
1311 base = CERT_GROUP_POLICY_SYSTEM_STORE_REGPATH;
1312 break;
1313 case CERT_SYSTEM_STORE_LOCAL_MACHINE_GROUP_POLICY:
1314 root = HKEY_LOCAL_MACHINE;
1315 base = CERT_GROUP_POLICY_SYSTEM_STORE_REGPATH;
1316 break;
1317 case CERT_SYSTEM_STORE_LOCAL_MACHINE_ENTERPRISE:
1318 /* hklm\Software\Microsoft\EnterpriseCertificates */
1319 FIXME("CERT_SYSTEM_STORE_LOCAL_MACHINE_ENTERPRISE\n");
1320 return ERROR_FILE_NOT_FOUND;
1321 default:
1322 return ERROR_FILE_NOT_FOUND;
1325 return RegOpenKeyExW(root, base, 0, KEY_READ, key);
1328 BOOL WINAPI CertEnumSystemStore(DWORD dwFlags, void *pvSystemStoreLocationPara,
1329 void *pvArg, PFN_CERT_ENUM_SYSTEM_STORE pfnEnum)
1331 BOOL ret = FALSE;
1332 LONG rc;
1333 HKEY key;
1334 CERT_SYSTEM_STORE_INFO info = { sizeof(info) };
1336 TRACE("(%08x, %p, %p, %p)\n", dwFlags, pvSystemStoreLocationPara, pvArg,
1337 pfnEnum);
1339 rc = CRYPT_OpenParentStore(dwFlags, pvArg, &key);
1340 if (!rc)
1342 DWORD index = 0;
1344 ret = TRUE;
1345 do {
1346 WCHAR name[MAX_PATH];
1347 DWORD size = sizeof(name) / sizeof(name[0]);
1349 rc = RegEnumKeyExW(key, index++, name, &size, NULL, NULL, NULL,
1350 NULL);
1351 if (!rc)
1352 ret = pfnEnum(name, dwFlags, &info, NULL, pvArg);
1353 } while (ret && !rc);
1354 if (ret && rc != ERROR_NO_MORE_ITEMS)
1355 SetLastError(rc);
1357 else
1358 SetLastError(rc);
1359 /* Include root store for the local machine location (it isn't in the
1360 * registry)
1362 if (ret && (dwFlags & CERT_SYSTEM_STORE_LOCATION_MASK) ==
1363 CERT_SYSTEM_STORE_LOCAL_MACHINE)
1364 ret = pfnEnum(rootW, dwFlags, &info, NULL, pvArg);
1365 return ret;
1368 BOOL WINAPI CertEnumPhysicalStore(const void *pvSystemStore, DWORD dwFlags,
1369 void *pvArg, PFN_CERT_ENUM_PHYSICAL_STORE pfnEnum)
1371 if (dwFlags & CERT_SYSTEM_STORE_RELOCATE_FLAG)
1372 FIXME("(%p, %08x, %p, %p): stub\n", pvSystemStore, dwFlags, pvArg,
1373 pfnEnum);
1374 else
1375 FIXME("(%s, %08x, %p, %p): stub\n", debugstr_w(pvSystemStore),
1376 dwFlags, pvArg,
1377 pfnEnum);
1378 return FALSE;
1381 BOOL WINAPI CertRegisterPhysicalStore(const void *pvSystemStore, DWORD dwFlags,
1382 LPCWSTR pwszStoreName, PCERT_PHYSICAL_STORE_INFO pStoreInfo, void *pvReserved)
1384 if (dwFlags & CERT_SYSTEM_STORE_RELOCATE_FLAG)
1385 FIXME("(%p, %08x, %s, %p, %p): stub\n", pvSystemStore, dwFlags,
1386 debugstr_w(pwszStoreName), pStoreInfo, pvReserved);
1387 else
1388 FIXME("(%s, %08x, %s, %p, %p): stub\n", debugstr_w(pvSystemStore),
1389 dwFlags, debugstr_w(pwszStoreName), pStoreInfo, pvReserved);
1390 return FALSE;
1393 static void EmptyStore_addref(WINECRYPT_CERTSTORE *store)
1395 TRACE("(%p)\n", store);
1398 static DWORD EmptyStore_release(WINECRYPT_CERTSTORE *store, DWORD flags)
1400 TRACE("(%p)\n", store);
1401 return E_UNEXPECTED;
1404 static void EmptyStore_releaseContext(WINECRYPT_CERTSTORE *store, context_t *context)
1406 Context_Free(context);
1409 static BOOL EmptyStore_add(WINECRYPT_CERTSTORE *store, context_t *context,
1410 context_t *replace, context_t **ret_context, BOOL use_link)
1412 TRACE("(%p, %p, %p, %p)\n", store, context, replace, ret_context);
1414 /* FIXME: We should clone the context */
1415 if(ret_context) {
1416 Context_AddRef(context);
1417 *ret_context = context;
1420 return TRUE;
1423 static context_t *EmptyStore_enum(WINECRYPT_CERTSTORE *store, context_t *prev)
1425 TRACE("(%p, %p)\n", store, prev);
1427 SetLastError(CRYPT_E_NOT_FOUND);
1428 return NULL;
1431 static BOOL EmptyStore_delete(WINECRYPT_CERTSTORE *store, context_t *context)
1433 return TRUE;
1436 static BOOL EmptyStore_control(WINECRYPT_CERTSTORE *store, DWORD flags, DWORD ctrl_type, void const *ctrl_para)
1438 TRACE("()\n");
1440 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1441 return FALSE;
1444 static const store_vtbl_t EmptyStoreVtbl = {
1445 EmptyStore_addref,
1446 EmptyStore_release,
1447 EmptyStore_releaseContext,
1448 EmptyStore_control,
1450 EmptyStore_add,
1451 EmptyStore_enum,
1452 EmptyStore_delete
1453 }, {
1454 EmptyStore_add,
1455 EmptyStore_enum,
1456 EmptyStore_delete
1457 }, {
1458 EmptyStore_add,
1459 EmptyStore_enum,
1460 EmptyStore_delete
1464 WINECRYPT_CERTSTORE empty_store;
1466 void init_empty_store(void)
1468 CRYPT_InitStore(&empty_store, CERT_STORE_READONLY_FLAG, StoreTypeEmpty, &EmptyStoreVtbl);