mf/session: Forward more events to the application.
[wine/zf.git] / dlls / crypt32 / store.c
blob599a4dd4936bf44875b8400a96585a4bc908549a
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 <assert.h>
27 #include <stdarg.h>
28 #include "windef.h"
29 #include "winbase.h"
30 #include "winnls.h"
31 #include "winreg.h"
32 #include "winternl.h"
33 #include "winuser.h"
34 #include "wincrypt.h"
35 #include "wine/debug.h"
36 #include "wine/exception.h"
37 #include "crypt32_private.h"
39 WINE_DEFAULT_DEBUG_CHANNEL(crypt);
41 static const WINE_CONTEXT_INTERFACE gCertInterface = {
42 (CreateContextFunc)CertCreateCertificateContext,
43 (AddContextToStoreFunc)CertAddCertificateContextToStore,
44 (AddEncodedContextToStoreFunc)CertAddEncodedCertificateToStore,
45 (EnumContextsInStoreFunc)CertEnumCertificatesInStore,
46 (EnumPropertiesFunc)CertEnumCertificateContextProperties,
47 (GetContextPropertyFunc)CertGetCertificateContextProperty,
48 (SetContextPropertyFunc)CertSetCertificateContextProperty,
49 (SerializeElementFunc)CertSerializeCertificateStoreElement,
50 (DeleteContextFunc)CertDeleteCertificateFromStore,
52 const WINE_CONTEXT_INTERFACE *pCertInterface = &gCertInterface;
54 static const WINE_CONTEXT_INTERFACE gCRLInterface = {
55 (CreateContextFunc)CertCreateCRLContext,
56 (AddContextToStoreFunc)CertAddCRLContextToStore,
57 (AddEncodedContextToStoreFunc)CertAddEncodedCRLToStore,
58 (EnumContextsInStoreFunc)CertEnumCRLsInStore,
59 (EnumPropertiesFunc)CertEnumCRLContextProperties,
60 (GetContextPropertyFunc)CertGetCRLContextProperty,
61 (SetContextPropertyFunc)CertSetCRLContextProperty,
62 (SerializeElementFunc)CertSerializeCRLStoreElement,
63 (DeleteContextFunc)CertDeleteCRLFromStore,
65 const WINE_CONTEXT_INTERFACE *pCRLInterface = &gCRLInterface;
67 static const WINE_CONTEXT_INTERFACE gCTLInterface = {
68 (CreateContextFunc)CertCreateCTLContext,
69 (AddContextToStoreFunc)CertAddCTLContextToStore,
70 (AddEncodedContextToStoreFunc)CertAddEncodedCTLToStore,
71 (EnumContextsInStoreFunc)CertEnumCTLsInStore,
72 (EnumPropertiesFunc)CertEnumCTLContextProperties,
73 (GetContextPropertyFunc)CertGetCTLContextProperty,
74 (SetContextPropertyFunc)CertSetCTLContextProperty,
75 (SerializeElementFunc)CertSerializeCTLStoreElement,
76 (DeleteContextFunc)CertDeleteCTLFromStore,
78 const WINE_CONTEXT_INTERFACE *pCTLInterface = &gCTLInterface;
80 typedef struct _WINE_MEMSTORE
82 WINECRYPT_CERTSTORE hdr;
83 CRITICAL_SECTION cs;
84 struct list certs;
85 struct list crls;
86 struct list ctls;
87 } WINE_MEMSTORE;
89 void CRYPT_InitStore(WINECRYPT_CERTSTORE *store, DWORD dwFlags, CertStoreType type, const store_vtbl_t *vtbl)
91 store->ref = 1;
92 store->dwMagic = WINE_CRYPTCERTSTORE_MAGIC;
93 store->type = type;
94 store->dwOpenFlags = dwFlags;
95 store->vtbl = vtbl;
96 store->properties = NULL;
99 void CRYPT_FreeStore(WINECRYPT_CERTSTORE *store)
101 if (store->properties)
102 ContextPropertyList_Free(store->properties);
103 store->dwMagic = 0;
104 CryptMemFree(store);
107 BOOL WINAPI I_CertUpdateStore(HCERTSTORE store1, HCERTSTORE store2, DWORD unk0,
108 DWORD unk1)
110 static BOOL warned = FALSE;
111 const WINE_CONTEXT_INTERFACE * const interfaces[] = { pCertInterface,
112 pCRLInterface, pCTLInterface };
113 DWORD i;
115 TRACE("(%p, %p, %08x, %08x)\n", store1, store2, unk0, unk1);
116 if (!warned)
118 FIXME("semi-stub\n");
119 warned = TRUE;
122 /* Poor-man's resync: empty first store, then add everything from second
123 * store to it.
125 for (i = 0; i < ARRAY_SIZE(interfaces); i++)
127 const void *context;
129 do {
130 context = interfaces[i]->enumContextsInStore(store1, NULL);
131 if (context)
132 interfaces[i]->deleteFromStore(context);
133 } while (context);
134 do {
135 context = interfaces[i]->enumContextsInStore(store2, context);
136 if (context)
137 interfaces[i]->addContextToStore(store1, context,
138 CERT_STORE_ADD_ALWAYS, NULL);
139 } while (context);
141 return TRUE;
144 static BOOL MemStore_addContext(WINE_MEMSTORE *store, struct list *list, context_t *orig_context,
145 context_t *existing, context_t **ret_context, BOOL use_link)
147 context_t *context;
149 context = orig_context->vtbl->clone(orig_context, &store->hdr, use_link);
150 if (!context)
151 return FALSE;
153 TRACE("adding %p\n", context);
154 EnterCriticalSection(&store->cs);
155 if (existing) {
156 context->u.entry.prev = existing->u.entry.prev;
157 context->u.entry.next = existing->u.entry.next;
158 context->u.entry.prev->next = &context->u.entry;
159 context->u.entry.next->prev = &context->u.entry;
160 list_init(&existing->u.entry);
161 if(!existing->ref)
162 Context_Release(existing);
163 }else {
164 list_add_head(list, &context->u.entry);
166 LeaveCriticalSection(&store->cs);
168 if(ret_context)
169 *ret_context = context;
170 else
171 Context_Release(context);
172 return TRUE;
175 static context_t *MemStore_enumContext(WINE_MEMSTORE *store, struct list *list, context_t *prev)
177 struct list *next;
178 context_t *ret;
180 EnterCriticalSection(&store->cs);
181 if (prev) {
182 next = list_next(list, &prev->u.entry);
183 Context_Release(prev);
184 }else {
185 next = list_next(list, list);
187 LeaveCriticalSection(&store->cs);
189 if (!next) {
190 SetLastError(CRYPT_E_NOT_FOUND);
191 return NULL;
194 ret = LIST_ENTRY(next, context_t, u.entry);
195 Context_AddRef(ret);
196 return ret;
199 static BOOL MemStore_deleteContext(WINE_MEMSTORE *store, context_t *context)
201 BOOL in_list = FALSE;
203 EnterCriticalSection(&store->cs);
204 if (!list_empty(&context->u.entry)) {
205 list_remove(&context->u.entry);
206 list_init(&context->u.entry);
207 in_list = TRUE;
209 LeaveCriticalSection(&store->cs);
211 if(in_list && !context->ref)
212 Context_Free(context);
213 return TRUE;
216 static void free_contexts(struct list *list)
218 context_t *context, *next;
220 LIST_FOR_EACH_ENTRY_SAFE(context, next, list, context_t, u.entry)
222 TRACE("freeing %p\n", context);
223 list_remove(&context->u.entry);
224 Context_Free(context);
228 static void MemStore_releaseContext(WINECRYPT_CERTSTORE *store, context_t *context)
230 /* Free the context only if it's not in a list. Otherwise it may be reused later. */
231 if(list_empty(&context->u.entry))
232 Context_Free(context);
235 static BOOL MemStore_addCert(WINECRYPT_CERTSTORE *store, context_t *cert,
236 context_t *toReplace, context_t **ppStoreContext, BOOL use_link)
238 WINE_MEMSTORE *ms = (WINE_MEMSTORE *)store;
240 TRACE("(%p, %p, %p, %p)\n", store, cert, toReplace, ppStoreContext);
241 return MemStore_addContext(ms, &ms->certs, cert, toReplace, ppStoreContext, use_link);
244 static context_t *MemStore_enumCert(WINECRYPT_CERTSTORE *store, context_t *prev)
246 WINE_MEMSTORE *ms = (WINE_MEMSTORE *)store;
248 TRACE("(%p, %p)\n", store, prev);
250 return MemStore_enumContext(ms, &ms->certs, prev);
253 static BOOL MemStore_deleteCert(WINECRYPT_CERTSTORE *store, context_t *context)
255 WINE_MEMSTORE *ms = (WINE_MEMSTORE *)store;
257 TRACE("(%p, %p)\n", store, context);
259 return MemStore_deleteContext(ms, context);
262 static BOOL MemStore_addCRL(WINECRYPT_CERTSTORE *store, context_t *crl,
263 context_t *toReplace, context_t **ppStoreContext, BOOL use_link)
265 WINE_MEMSTORE *ms = (WINE_MEMSTORE *)store;
267 TRACE("(%p, %p, %p, %p)\n", store, crl, toReplace, ppStoreContext);
269 return MemStore_addContext(ms, &ms->crls, crl, toReplace, ppStoreContext, use_link);
272 static context_t *MemStore_enumCRL(WINECRYPT_CERTSTORE *store, context_t *prev)
274 WINE_MEMSTORE *ms = (WINE_MEMSTORE *)store;
276 TRACE("(%p, %p)\n", store, prev);
278 return MemStore_enumContext(ms, &ms->crls, prev);
281 static BOOL MemStore_deleteCRL(WINECRYPT_CERTSTORE *store, context_t *context)
283 WINE_MEMSTORE *ms = (WINE_MEMSTORE *)store;
285 TRACE("(%p, %p)\n", store, context);
287 return MemStore_deleteContext(ms, context);
290 static BOOL MemStore_addCTL(WINECRYPT_CERTSTORE *store, context_t *ctl,
291 context_t *toReplace, context_t **ppStoreContext, BOOL use_link)
293 WINE_MEMSTORE *ms = (WINE_MEMSTORE *)store;
295 TRACE("(%p, %p, %p, %p)\n", store, ctl, toReplace, ppStoreContext);
297 return MemStore_addContext(ms, &ms->ctls, ctl, toReplace, ppStoreContext, use_link);
300 static context_t *MemStore_enumCTL(WINECRYPT_CERTSTORE *store, context_t *prev)
302 WINE_MEMSTORE *ms = (WINE_MEMSTORE *)store;
304 TRACE("(%p, %p)\n", store, prev);
306 return MemStore_enumContext(ms, &ms->ctls, prev);
309 static BOOL MemStore_deleteCTL(WINECRYPT_CERTSTORE *store, context_t *context)
311 WINE_MEMSTORE *ms = (WINE_MEMSTORE *)store;
313 TRACE("(%p, %p)\n", store, context);
315 return MemStore_deleteContext(ms, context);
318 static void MemStore_addref(WINECRYPT_CERTSTORE *store)
320 LONG ref = InterlockedIncrement(&store->ref);
321 TRACE("ref = %d\n", ref);
324 static DWORD MemStore_release(WINECRYPT_CERTSTORE *cert_store, DWORD flags)
326 WINE_MEMSTORE *store = (WINE_MEMSTORE*)cert_store;
327 LONG ref;
329 if(flags & ~CERT_CLOSE_STORE_CHECK_FLAG)
330 FIXME("Unimplemented flags %x\n", flags);
332 ref = InterlockedDecrement(&store->hdr.ref);
333 TRACE("(%p) ref=%d\n", store, ref);
334 if(ref)
335 return (flags & CERT_CLOSE_STORE_CHECK_FLAG) ? CRYPT_E_PENDING_CLOSE : ERROR_SUCCESS;
337 free_contexts(&store->certs);
338 free_contexts(&store->crls);
339 free_contexts(&store->ctls);
340 store->cs.DebugInfo->Spare[0] = 0;
341 DeleteCriticalSection(&store->cs);
342 CRYPT_FreeStore(&store->hdr);
343 return ERROR_SUCCESS;
346 static BOOL MemStore_control(WINECRYPT_CERTSTORE *store, DWORD dwFlags,
347 DWORD dwCtrlType, void const *pvCtrlPara)
349 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
350 return FALSE;
353 static const store_vtbl_t MemStoreVtbl = {
354 MemStore_addref,
355 MemStore_release,
356 MemStore_releaseContext,
357 MemStore_control,
359 MemStore_addCert,
360 MemStore_enumCert,
361 MemStore_deleteCert
362 }, {
363 MemStore_addCRL,
364 MemStore_enumCRL,
365 MemStore_deleteCRL
366 }, {
367 MemStore_addCTL,
368 MemStore_enumCTL,
369 MemStore_deleteCTL
373 static WINECRYPT_CERTSTORE *CRYPT_MemOpenStore(HCRYPTPROV hCryptProv,
374 DWORD dwFlags, const void *pvPara)
376 WINE_MEMSTORE *store;
378 TRACE("(%ld, %08x, %p)\n", hCryptProv, dwFlags, pvPara);
380 if (dwFlags & CERT_STORE_DELETE_FLAG)
382 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
383 store = NULL;
385 else
387 store = CryptMemAlloc(sizeof(WINE_MEMSTORE));
388 if (store)
390 memset(store, 0, sizeof(WINE_MEMSTORE));
391 CRYPT_InitStore(&store->hdr, dwFlags, StoreTypeMem, &MemStoreVtbl);
392 InitializeCriticalSection(&store->cs);
393 store->cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": ContextList.cs");
394 list_init(&store->certs);
395 list_init(&store->crls);
396 list_init(&store->ctls);
397 /* Mem store doesn't need crypto provider, so close it */
398 if (hCryptProv && !(dwFlags & CERT_STORE_NO_CRYPT_RELEASE_FLAG))
399 CryptReleaseContext(hCryptProv, 0);
402 return (WINECRYPT_CERTSTORE*)store;
405 static WINECRYPT_CERTSTORE *CRYPT_SysRegOpenStoreW(HCRYPTPROV hCryptProv,
406 DWORD dwFlags, const void *pvPara)
408 LPCWSTR storeName = pvPara;
409 LPWSTR storePath;
410 WINECRYPT_CERTSTORE *store = NULL;
411 HKEY root;
412 LPCWSTR base;
414 TRACE("(%ld, %08x, %s)\n", hCryptProv, dwFlags,
415 debugstr_w(pvPara));
417 if (!pvPara)
419 SetLastError(E_INVALIDARG);
420 return NULL;
423 switch (dwFlags & CERT_SYSTEM_STORE_LOCATION_MASK)
425 case CERT_SYSTEM_STORE_LOCAL_MACHINE:
426 root = HKEY_LOCAL_MACHINE;
427 base = CERT_LOCAL_MACHINE_SYSTEM_STORE_REGPATH;
428 /* If the HKLM\Root certs are requested, expressing system certs into the registry */
429 if (!lstrcmpiW(storeName, L"Root"))
430 CRYPT_ImportSystemRootCertsToReg();
431 break;
432 case CERT_SYSTEM_STORE_CURRENT_USER:
433 root = HKEY_CURRENT_USER;
434 base = CERT_LOCAL_MACHINE_SYSTEM_STORE_REGPATH;
435 break;
436 case CERT_SYSTEM_STORE_CURRENT_SERVICE:
437 /* hklm\Software\Microsoft\Cryptography\Services\servicename\
438 * SystemCertificates
440 FIXME("CERT_SYSTEM_STORE_CURRENT_SERVICE, %s: stub\n",
441 debugstr_w(storeName));
442 return NULL;
443 case CERT_SYSTEM_STORE_SERVICES:
444 /* hklm\Software\Microsoft\Cryptography\Services\servicename\
445 * SystemCertificates
447 FIXME("CERT_SYSTEM_STORE_SERVICES, %s: stub\n",
448 debugstr_w(storeName));
449 return NULL;
450 case CERT_SYSTEM_STORE_USERS:
451 /* hku\user sid\Software\Microsoft\SystemCertificates */
452 FIXME("CERT_SYSTEM_STORE_USERS, %s: stub\n",
453 debugstr_w(storeName));
454 return NULL;
455 case CERT_SYSTEM_STORE_CURRENT_USER_GROUP_POLICY:
456 root = HKEY_CURRENT_USER;
457 base = CERT_GROUP_POLICY_SYSTEM_STORE_REGPATH;
458 break;
459 case CERT_SYSTEM_STORE_LOCAL_MACHINE_GROUP_POLICY:
460 root = HKEY_LOCAL_MACHINE;
461 base = CERT_GROUP_POLICY_SYSTEM_STORE_REGPATH;
462 break;
463 case CERT_SYSTEM_STORE_LOCAL_MACHINE_ENTERPRISE:
464 /* hklm\Software\Microsoft\EnterpriseCertificates */
465 FIXME("CERT_SYSTEM_STORE_LOCAL_MACHINE_ENTERPRISE, %s: stub\n",
466 debugstr_w(storeName));
467 return NULL;
468 default:
469 SetLastError(E_INVALIDARG);
470 return NULL;
473 storePath = CryptMemAlloc((lstrlenW(base) + lstrlenW(storeName) + 2) *
474 sizeof(WCHAR));
475 if (storePath)
477 LONG rc;
478 HKEY key;
479 REGSAM sam = dwFlags & CERT_STORE_READONLY_FLAG ? KEY_READ :
480 KEY_ALL_ACCESS;
482 wsprintfW(storePath, L"%s\\%s", base, storeName);
483 if (dwFlags & CERT_STORE_OPEN_EXISTING_FLAG)
484 rc = RegOpenKeyExW(root, storePath, 0, sam, &key);
485 else
487 DWORD disp;
489 rc = RegCreateKeyExW(root, storePath, 0, NULL, 0, sam, NULL,
490 &key, &disp);
491 if (!rc && dwFlags & CERT_STORE_CREATE_NEW_FLAG &&
492 disp == REG_OPENED_EXISTING_KEY)
494 RegCloseKey(key);
495 rc = ERROR_FILE_EXISTS;
498 if (!rc)
500 store = CRYPT_RegOpenStore(hCryptProv, dwFlags, key);
501 RegCloseKey(key);
503 else
504 SetLastError(rc);
505 CryptMemFree(storePath);
507 return store;
510 static WINECRYPT_CERTSTORE *CRYPT_SysRegOpenStoreA(HCRYPTPROV hCryptProv,
511 DWORD dwFlags, const void *pvPara)
513 int len;
514 WINECRYPT_CERTSTORE *ret = NULL;
516 TRACE("(%ld, %08x, %s)\n", hCryptProv, dwFlags,
517 debugstr_a(pvPara));
519 if (!pvPara)
521 SetLastError(ERROR_FILE_NOT_FOUND);
522 return NULL;
524 len = MultiByteToWideChar(CP_ACP, 0, pvPara, -1, NULL, 0);
525 if (len)
527 LPWSTR storeName = CryptMemAlloc(len * sizeof(WCHAR));
529 if (storeName)
531 MultiByteToWideChar(CP_ACP, 0, pvPara, -1, storeName, len);
532 ret = CRYPT_SysRegOpenStoreW(hCryptProv, dwFlags, storeName);
533 CryptMemFree(storeName);
536 return ret;
539 static WINECRYPT_CERTSTORE *CRYPT_SysOpenStoreW(HCRYPTPROV hCryptProv,
540 DWORD dwFlags, const void *pvPara)
542 HCERTSTORE store = 0;
543 BOOL ret;
545 TRACE("(%ld, %08x, %s)\n", hCryptProv, dwFlags,
546 debugstr_w(pvPara));
548 if (!pvPara)
550 SetLastError(ERROR_FILE_NOT_FOUND);
551 return NULL;
553 /* This returns a different error than system registry stores if the
554 * location is invalid.
556 switch (dwFlags & CERT_SYSTEM_STORE_LOCATION_MASK)
558 case CERT_SYSTEM_STORE_LOCAL_MACHINE:
559 case CERT_SYSTEM_STORE_CURRENT_USER:
560 case CERT_SYSTEM_STORE_CURRENT_SERVICE:
561 case CERT_SYSTEM_STORE_SERVICES:
562 case CERT_SYSTEM_STORE_USERS:
563 case CERT_SYSTEM_STORE_CURRENT_USER_GROUP_POLICY:
564 case CERT_SYSTEM_STORE_LOCAL_MACHINE_GROUP_POLICY:
565 case CERT_SYSTEM_STORE_LOCAL_MACHINE_ENTERPRISE:
566 ret = TRUE;
567 break;
568 default:
569 SetLastError(ERROR_FILE_NOT_FOUND);
570 ret = FALSE;
572 if (ret)
574 HCERTSTORE regStore = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY_W,
575 0, 0, dwFlags, pvPara);
577 if (regStore)
579 store = CertOpenStore(CERT_STORE_PROV_COLLECTION, 0, 0,
580 CERT_STORE_CREATE_NEW_FLAG, NULL);
581 CertAddStoreToCollection(store, regStore,
582 dwFlags & CERT_STORE_READONLY_FLAG ? 0 :
583 CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
584 CertCloseStore(regStore, 0);
585 /* CERT_SYSTEM_STORE_CURRENT_USER returns both the HKCU and HKLM
586 * stores.
588 if ((dwFlags & CERT_SYSTEM_STORE_LOCATION_MASK) ==
589 CERT_SYSTEM_STORE_CURRENT_USER)
591 dwFlags &= ~CERT_SYSTEM_STORE_CURRENT_USER;
592 dwFlags |= CERT_SYSTEM_STORE_LOCAL_MACHINE;
593 regStore = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY_W, 0,
594 0, dwFlags, pvPara);
595 if (regStore)
597 CertAddStoreToCollection(store, regStore,
598 dwFlags & CERT_STORE_READONLY_FLAG ? 0 :
599 CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
600 CertCloseStore(regStore, 0);
603 /* System store doesn't need crypto provider, so close it */
604 if (hCryptProv && !(dwFlags & CERT_STORE_NO_CRYPT_RELEASE_FLAG))
605 CryptReleaseContext(hCryptProv, 0);
608 return store;
611 static WINECRYPT_CERTSTORE *CRYPT_SysOpenStoreA(HCRYPTPROV hCryptProv,
612 DWORD dwFlags, const void *pvPara)
614 int len;
615 WINECRYPT_CERTSTORE *ret = NULL;
617 TRACE("(%ld, %08x, %s)\n", hCryptProv, dwFlags,
618 debugstr_a(pvPara));
620 if (!pvPara)
622 SetLastError(ERROR_FILE_NOT_FOUND);
623 return NULL;
625 len = MultiByteToWideChar(CP_ACP, 0, pvPara, -1, NULL, 0);
626 if (len)
628 LPWSTR storeName = CryptMemAlloc(len * sizeof(WCHAR));
630 if (storeName)
632 MultiByteToWideChar(CP_ACP, 0, pvPara, -1, storeName, len);
633 ret = CRYPT_SysOpenStoreW(hCryptProv, dwFlags, storeName);
634 CryptMemFree(storeName);
637 return ret;
640 static void WINAPI CRYPT_MsgCloseStore(HCERTSTORE hCertStore, DWORD dwFlags)
642 HCRYPTMSG msg = hCertStore;
644 TRACE("(%p, %08x)\n", msg, dwFlags);
645 CryptMsgClose(msg);
648 static void *msgProvFuncs[] = {
649 CRYPT_MsgCloseStore,
652 static WINECRYPT_CERTSTORE *CRYPT_MsgOpenStore(HCRYPTPROV hCryptProv,
653 DWORD dwFlags, const void *pvPara)
655 WINECRYPT_CERTSTORE *store = NULL;
656 HCRYPTMSG msg = (HCRYPTMSG)pvPara;
657 WINECRYPT_CERTSTORE *memStore;
659 TRACE("(%ld, %08x, %p)\n", hCryptProv, dwFlags, pvPara);
661 memStore = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
662 CERT_STORE_CREATE_NEW_FLAG, NULL);
663 if (memStore)
665 BOOL ret;
666 DWORD size, count, i;
668 size = sizeof(count);
669 ret = CryptMsgGetParam(msg, CMSG_CERT_COUNT_PARAM, 0, &count, &size);
670 for (i = 0; ret && i < count; i++)
672 size = 0;
673 ret = CryptMsgGetParam(msg, CMSG_CERT_PARAM, i, NULL, &size);
674 if (ret)
676 LPBYTE buf = CryptMemAlloc(size);
678 if (buf)
680 ret = CryptMsgGetParam(msg, CMSG_CERT_PARAM, i, buf, &size);
681 if (ret)
682 ret = CertAddEncodedCertificateToStore(memStore,
683 X509_ASN_ENCODING, buf, size, CERT_STORE_ADD_ALWAYS,
684 NULL);
685 CryptMemFree(buf);
689 size = sizeof(count);
690 ret = CryptMsgGetParam(msg, CMSG_CRL_COUNT_PARAM, 0, &count, &size);
691 for (i = 0; ret && i < count; i++)
693 size = 0;
694 ret = CryptMsgGetParam(msg, CMSG_CRL_PARAM, i, NULL, &size);
695 if (ret)
697 LPBYTE buf = CryptMemAlloc(size);
699 if (buf)
701 ret = CryptMsgGetParam(msg, CMSG_CRL_PARAM, i, buf, &size);
702 if (ret)
703 ret = CertAddEncodedCRLToStore(memStore,
704 X509_ASN_ENCODING, buf, size, CERT_STORE_ADD_ALWAYS,
705 NULL);
706 CryptMemFree(buf);
710 if (ret)
712 CERT_STORE_PROV_INFO provInfo = { 0 };
714 provInfo.cbSize = sizeof(provInfo);
715 provInfo.cStoreProvFunc = ARRAY_SIZE(msgProvFuncs);
716 provInfo.rgpvStoreProvFunc = msgProvFuncs;
717 provInfo.hStoreProv = CryptMsgDuplicate(msg);
718 store = CRYPT_ProvCreateStore(dwFlags, memStore, &provInfo);
719 /* Msg store doesn't need crypto provider, so close it */
720 if (hCryptProv && !(dwFlags & CERT_STORE_NO_CRYPT_RELEASE_FLAG))
721 CryptReleaseContext(hCryptProv, 0);
723 else
724 CertCloseStore(memStore, 0);
726 TRACE("returning %p\n", store);
727 return store;
730 static WINECRYPT_CERTSTORE *CRYPT_PKCSOpenStore(HCRYPTPROV hCryptProv,
731 DWORD dwFlags, const void *pvPara)
733 HCRYPTMSG msg;
734 WINECRYPT_CERTSTORE *store = NULL;
735 const CRYPT_DATA_BLOB *data = pvPara;
736 BOOL ret;
737 DWORD msgOpenFlags = dwFlags & CERT_STORE_NO_CRYPT_RELEASE_FLAG ? 0 :
738 CMSG_CRYPT_RELEASE_CONTEXT_FLAG;
740 TRACE("(%ld, %08x, %p)\n", hCryptProv, dwFlags, pvPara);
742 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, msgOpenFlags, CMSG_SIGNED,
743 hCryptProv, NULL, NULL);
744 ret = CryptMsgUpdate(msg, data->pbData, data->cbData, TRUE);
745 if (!ret)
747 CryptMsgClose(msg);
748 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, msgOpenFlags, 0,
749 hCryptProv, NULL, NULL);
750 ret = CryptMsgUpdate(msg, data->pbData, data->cbData, TRUE);
751 if (ret)
753 DWORD type, size = sizeof(type);
755 /* Only signed messages are allowed, check type */
756 ret = CryptMsgGetParam(msg, CMSG_TYPE_PARAM, 0, &type, &size);
757 if (ret && type != CMSG_SIGNED)
759 SetLastError(CRYPT_E_INVALID_MSG_TYPE);
760 ret = FALSE;
764 if (ret)
765 store = CRYPT_MsgOpenStore(0, dwFlags, msg);
766 CryptMsgClose(msg);
767 TRACE("returning %p\n", store);
768 return store;
771 static WINECRYPT_CERTSTORE *CRYPT_SerializedOpenStore(HCRYPTPROV hCryptProv,
772 DWORD dwFlags, const void *pvPara)
774 HCERTSTORE store;
775 const CRYPT_DATA_BLOB *data = pvPara;
777 TRACE("(%ld, %08x, %p)\n", hCryptProv, dwFlags, pvPara);
779 if (dwFlags & CERT_STORE_DELETE_FLAG)
781 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
782 return NULL;
785 store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
786 CERT_STORE_CREATE_NEW_FLAG, NULL);
787 if (store)
789 if (!CRYPT_ReadSerializedStoreFromBlob(data, store))
791 CertCloseStore(store, 0);
792 store = NULL;
795 TRACE("returning %p\n", store);
796 return (WINECRYPT_CERTSTORE*)store;
799 static WINECRYPT_CERTSTORE *CRYPT_PhysOpenStoreW(HCRYPTPROV hCryptProv,
800 DWORD dwFlags, const void *pvPara)
802 if (dwFlags & CERT_SYSTEM_STORE_RELOCATE_FLAG)
803 FIXME("(%ld, %08x, %p): stub\n", hCryptProv, dwFlags, pvPara);
804 else
805 FIXME("(%ld, %08x, %s): stub\n", hCryptProv, dwFlags,
806 debugstr_w(pvPara));
807 return NULL;
810 HCERTSTORE WINAPI CertOpenStore(LPCSTR lpszStoreProvider,
811 DWORD dwMsgAndCertEncodingType, HCRYPTPROV_LEGACY hCryptProv, DWORD dwFlags,
812 const void* pvPara)
814 WINECRYPT_CERTSTORE *hcs;
815 StoreOpenFunc openFunc = NULL;
817 TRACE("(%s, %08x, %08lx, %08x, %p)\n", debugstr_a(lpszStoreProvider),
818 dwMsgAndCertEncodingType, hCryptProv, dwFlags, pvPara);
820 if (IS_INTOID(lpszStoreProvider))
822 switch (LOWORD(lpszStoreProvider))
824 case LOWORD(CERT_STORE_PROV_MSG):
825 openFunc = CRYPT_MsgOpenStore;
826 break;
827 case LOWORD(CERT_STORE_PROV_MEMORY):
828 openFunc = CRYPT_MemOpenStore;
829 break;
830 case LOWORD(CERT_STORE_PROV_FILE):
831 openFunc = CRYPT_FileOpenStore;
832 break;
833 case LOWORD(CERT_STORE_PROV_PKCS7):
834 openFunc = CRYPT_PKCSOpenStore;
835 break;
836 case LOWORD(CERT_STORE_PROV_SERIALIZED):
837 openFunc = CRYPT_SerializedOpenStore;
838 break;
839 case LOWORD(CERT_STORE_PROV_REG):
840 openFunc = CRYPT_RegOpenStore;
841 break;
842 case LOWORD(CERT_STORE_PROV_FILENAME_A):
843 openFunc = CRYPT_FileNameOpenStoreA;
844 break;
845 case LOWORD(CERT_STORE_PROV_FILENAME_W):
846 openFunc = CRYPT_FileNameOpenStoreW;
847 break;
848 case LOWORD(CERT_STORE_PROV_COLLECTION):
849 openFunc = CRYPT_CollectionOpenStore;
850 break;
851 case LOWORD(CERT_STORE_PROV_SYSTEM_A):
852 openFunc = CRYPT_SysOpenStoreA;
853 break;
854 case LOWORD(CERT_STORE_PROV_SYSTEM_W):
855 openFunc = CRYPT_SysOpenStoreW;
856 break;
857 case LOWORD(CERT_STORE_PROV_SYSTEM_REGISTRY_A):
858 openFunc = CRYPT_SysRegOpenStoreA;
859 break;
860 case LOWORD(CERT_STORE_PROV_SYSTEM_REGISTRY_W):
861 openFunc = CRYPT_SysRegOpenStoreW;
862 break;
863 case LOWORD(CERT_STORE_PROV_PHYSICAL_W):
864 openFunc = CRYPT_PhysOpenStoreW;
865 break;
866 default:
867 if (LOWORD(lpszStoreProvider))
868 FIXME("unimplemented type %d\n", LOWORD(lpszStoreProvider));
871 else if (!stricmp(lpszStoreProvider, sz_CERT_STORE_PROV_MEMORY))
872 openFunc = CRYPT_MemOpenStore;
873 else if (!stricmp(lpszStoreProvider, sz_CERT_STORE_PROV_FILENAME_W))
874 openFunc = CRYPT_FileOpenStore;
875 else if (!stricmp(lpszStoreProvider, sz_CERT_STORE_PROV_SYSTEM))
876 openFunc = CRYPT_SysOpenStoreW;
877 else if (!stricmp(lpszStoreProvider, sz_CERT_STORE_PROV_PKCS7))
878 openFunc = CRYPT_PKCSOpenStore;
879 else if (!stricmp(lpszStoreProvider, sz_CERT_STORE_PROV_SERIALIZED))
880 openFunc = CRYPT_SerializedOpenStore;
881 else if (!stricmp(lpszStoreProvider, sz_CERT_STORE_PROV_COLLECTION))
882 openFunc = CRYPT_CollectionOpenStore;
883 else if (!stricmp(lpszStoreProvider, sz_CERT_STORE_PROV_SYSTEM_REGISTRY))
884 openFunc = CRYPT_SysRegOpenStoreW;
885 else
887 FIXME("unimplemented type %s\n", lpszStoreProvider);
888 openFunc = NULL;
891 if (!openFunc)
892 hcs = CRYPT_ProvOpenStore(lpszStoreProvider, dwMsgAndCertEncodingType,
893 hCryptProv, dwFlags, pvPara);
894 else
895 hcs = openFunc(hCryptProv, dwFlags, pvPara);
896 return hcs;
899 HCERTSTORE WINAPI CertOpenSystemStoreA(HCRYPTPROV_LEGACY hProv,
900 LPCSTR szSubSystemProtocol)
902 if (!szSubSystemProtocol)
904 SetLastError(E_INVALIDARG);
905 return 0;
907 return CertOpenStore(CERT_STORE_PROV_SYSTEM_A, 0, hProv,
908 CERT_SYSTEM_STORE_CURRENT_USER, szSubSystemProtocol);
911 HCERTSTORE WINAPI CertOpenSystemStoreW(HCRYPTPROV_LEGACY hProv,
912 LPCWSTR szSubSystemProtocol)
914 if (!szSubSystemProtocol)
916 SetLastError(E_INVALIDARG);
917 return 0;
919 return CertOpenStore(CERT_STORE_PROV_SYSTEM_W, 0, hProv,
920 CERT_SYSTEM_STORE_CURRENT_USER, szSubSystemProtocol);
923 PCCERT_CONTEXT WINAPI CertEnumCertificatesInStore(HCERTSTORE hCertStore, PCCERT_CONTEXT pPrev)
925 cert_t *prev = pPrev ? cert_from_ptr(pPrev) : NULL, *ret;
926 WINECRYPT_CERTSTORE *hcs = hCertStore;
928 TRACE("(%p, %p)\n", hCertStore, pPrev);
929 if (!hCertStore)
930 ret = NULL;
931 else if (hcs->dwMagic != WINE_CRYPTCERTSTORE_MAGIC)
932 ret = NULL;
933 else
934 ret = (cert_t*)hcs->vtbl->certs.enumContext(hcs, prev ? &prev->base : NULL);
935 return ret ? &ret->ctx : NULL;
938 BOOL WINAPI CertDeleteCertificateFromStore(PCCERT_CONTEXT pCertContext)
940 WINECRYPT_CERTSTORE *hcs;
942 TRACE("(%p)\n", pCertContext);
944 if (!pCertContext)
945 return TRUE;
947 hcs = pCertContext->hCertStore;
949 if (hcs->dwMagic != WINE_CRYPTCERTSTORE_MAGIC)
950 return FALSE;
952 return hcs->vtbl->certs.delete(hcs, &cert_from_ptr(pCertContext)->base);
955 BOOL WINAPI CertAddCRLContextToStore(HCERTSTORE hCertStore,
956 PCCRL_CONTEXT pCrlContext, DWORD dwAddDisposition,
957 PCCRL_CONTEXT* ppStoreContext)
959 WINECRYPT_CERTSTORE *store = hCertStore;
960 BOOL ret = TRUE;
961 PCCRL_CONTEXT toAdd = NULL, existing = NULL;
963 TRACE("(%p, %p, %08x, %p)\n", hCertStore, pCrlContext,
964 dwAddDisposition, ppStoreContext);
966 /* Weird case to pass a test */
967 if (dwAddDisposition == 0)
969 SetLastError(STATUS_ACCESS_VIOLATION);
970 return FALSE;
972 if (dwAddDisposition != CERT_STORE_ADD_ALWAYS)
974 existing = CertFindCRLInStore(hCertStore, 0, 0, CRL_FIND_EXISTING,
975 pCrlContext, NULL);
978 switch (dwAddDisposition)
980 case CERT_STORE_ADD_ALWAYS:
981 toAdd = CertDuplicateCRLContext(pCrlContext);
982 break;
983 case CERT_STORE_ADD_NEW:
984 if (existing)
986 TRACE("found matching CRL, not adding\n");
987 SetLastError(CRYPT_E_EXISTS);
988 ret = FALSE;
990 else
991 toAdd = CertDuplicateCRLContext(pCrlContext);
992 break;
993 case CERT_STORE_ADD_NEWER:
994 if (existing)
996 LONG newer = CompareFileTime(&existing->pCrlInfo->ThisUpdate,
997 &pCrlContext->pCrlInfo->ThisUpdate);
999 if (newer < 0)
1000 toAdd = CertDuplicateCRLContext(pCrlContext);
1001 else
1003 TRACE("existing CRL is newer, not adding\n");
1004 SetLastError(CRYPT_E_EXISTS);
1005 ret = FALSE;
1008 else
1009 toAdd = CertDuplicateCRLContext(pCrlContext);
1010 break;
1011 case CERT_STORE_ADD_NEWER_INHERIT_PROPERTIES:
1012 if (existing)
1014 LONG newer = CompareFileTime(&existing->pCrlInfo->ThisUpdate,
1015 &pCrlContext->pCrlInfo->ThisUpdate);
1017 if (newer < 0)
1019 toAdd = CertDuplicateCRLContext(pCrlContext);
1020 Context_CopyProperties(toAdd, existing);
1022 else
1024 TRACE("existing CRL is newer, not adding\n");
1025 SetLastError(CRYPT_E_EXISTS);
1026 ret = FALSE;
1029 else
1030 toAdd = CertDuplicateCRLContext(pCrlContext);
1031 break;
1032 case CERT_STORE_ADD_REPLACE_EXISTING:
1033 toAdd = CertDuplicateCRLContext(pCrlContext);
1034 break;
1035 case CERT_STORE_ADD_REPLACE_EXISTING_INHERIT_PROPERTIES:
1036 toAdd = CertDuplicateCRLContext(pCrlContext);
1037 if (existing)
1038 Context_CopyProperties(toAdd, existing);
1039 break;
1040 case CERT_STORE_ADD_USE_EXISTING:
1041 if (existing)
1043 Context_CopyProperties(existing, pCrlContext);
1044 if (ppStoreContext)
1045 *ppStoreContext = CertDuplicateCRLContext(existing);
1047 else
1048 toAdd = CertDuplicateCRLContext(pCrlContext);
1049 break;
1050 default:
1051 FIXME("Unimplemented add disposition %d\n", dwAddDisposition);
1052 ret = FALSE;
1055 if (toAdd)
1057 if (store) {
1058 context_t *ret_context;
1059 ret = store->vtbl->crls.addContext(store, context_from_ptr(toAdd),
1060 existing ? context_from_ptr(existing) : NULL, ppStoreContext ? &ret_context : NULL, FALSE);
1061 if (ret && ppStoreContext)
1062 *ppStoreContext = context_ptr(ret_context);
1063 }else if (ppStoreContext) {
1064 *ppStoreContext = CertDuplicateCRLContext(toAdd);
1066 CertFreeCRLContext(toAdd);
1068 if (existing)
1069 CertFreeCRLContext(existing);
1071 TRACE("returning %d\n", ret);
1072 return ret;
1075 BOOL WINAPI CertDeleteCRLFromStore(PCCRL_CONTEXT pCrlContext)
1077 WINECRYPT_CERTSTORE *hcs;
1078 BOOL ret;
1080 TRACE("(%p)\n", pCrlContext);
1082 if (!pCrlContext)
1083 return TRUE;
1085 hcs = pCrlContext->hCertStore;
1087 if (hcs->dwMagic != WINE_CRYPTCERTSTORE_MAGIC)
1088 return FALSE;
1090 ret = hcs->vtbl->crls.delete(hcs, &crl_from_ptr(pCrlContext)->base);
1091 if (ret)
1092 ret = CertFreeCRLContext(pCrlContext);
1093 return ret;
1096 PCCRL_CONTEXT WINAPI CertEnumCRLsInStore(HCERTSTORE hCertStore, PCCRL_CONTEXT pPrev)
1098 crl_t *ret, *prev = pPrev ? crl_from_ptr(pPrev) : NULL;
1099 WINECRYPT_CERTSTORE *hcs = hCertStore;
1101 TRACE("(%p, %p)\n", hCertStore, pPrev);
1102 if (!hCertStore)
1103 ret = NULL;
1104 else if (hcs->dwMagic != WINE_CRYPTCERTSTORE_MAGIC)
1105 ret = NULL;
1106 else
1107 ret = (crl_t*)hcs->vtbl->crls.enumContext(hcs, prev ? &prev->base : NULL);
1108 return ret ? &ret->ctx : NULL;
1111 HCERTSTORE WINAPI CertDuplicateStore(HCERTSTORE hCertStore)
1113 WINECRYPT_CERTSTORE *hcs = hCertStore;
1115 TRACE("(%p)\n", hCertStore);
1117 if (hcs && hcs->dwMagic == WINE_CRYPTCERTSTORE_MAGIC)
1118 hcs->vtbl->addref(hcs);
1119 return hCertStore;
1122 BOOL WINAPI CertCloseStore(HCERTSTORE hCertStore, DWORD dwFlags)
1124 WINECRYPT_CERTSTORE *hcs = hCertStore;
1125 DWORD res;
1127 TRACE("(%p, %08x)\n", hCertStore, dwFlags);
1129 if( ! hCertStore )
1130 return TRUE;
1132 if ( hcs->dwMagic != WINE_CRYPTCERTSTORE_MAGIC )
1133 return FALSE;
1135 res = hcs->vtbl->release(hcs, dwFlags);
1136 if (res != ERROR_SUCCESS) {
1137 SetLastError(res);
1138 return FALSE;
1141 return TRUE;
1144 BOOL WINAPI CertControlStore(HCERTSTORE hCertStore, DWORD dwFlags,
1145 DWORD dwCtrlType, void const *pvCtrlPara)
1147 WINECRYPT_CERTSTORE *hcs = hCertStore;
1148 BOOL ret;
1150 TRACE("(%p, %08x, %d, %p)\n", hCertStore, dwFlags, dwCtrlType,
1151 pvCtrlPara);
1153 if (!hcs)
1154 ret = FALSE;
1155 else if (hcs->dwMagic != WINE_CRYPTCERTSTORE_MAGIC)
1156 ret = FALSE;
1157 else
1159 if (hcs->vtbl->control)
1160 ret = hcs->vtbl->control(hcs, dwFlags, dwCtrlType, pvCtrlPara);
1161 else
1162 ret = TRUE;
1164 return ret;
1167 BOOL WINAPI CertGetStoreProperty(HCERTSTORE hCertStore, DWORD dwPropId,
1168 void *pvData, DWORD *pcbData)
1170 WINECRYPT_CERTSTORE *store = hCertStore;
1171 BOOL ret = FALSE;
1173 TRACE("(%p, %d, %p, %p)\n", hCertStore, dwPropId, pvData, pcbData);
1175 switch (dwPropId)
1177 case CERT_ACCESS_STATE_PROP_ID:
1178 if (!pvData)
1180 *pcbData = sizeof(DWORD);
1181 ret = TRUE;
1183 else if (*pcbData < sizeof(DWORD))
1185 SetLastError(ERROR_MORE_DATA);
1186 *pcbData = sizeof(DWORD);
1188 else
1190 DWORD state = 0;
1192 if (store->type != StoreTypeMem &&
1193 !(store->dwOpenFlags & CERT_STORE_READONLY_FLAG))
1194 state |= CERT_ACCESS_STATE_WRITE_PERSIST_FLAG;
1195 *(DWORD *)pvData = state;
1196 ret = TRUE;
1198 break;
1199 default:
1200 if (store->properties)
1202 CRYPT_DATA_BLOB blob;
1204 ret = ContextPropertyList_FindProperty(store->properties, dwPropId,
1205 &blob);
1206 if (ret)
1208 if (!pvData)
1209 *pcbData = blob.cbData;
1210 else if (*pcbData < blob.cbData)
1212 SetLastError(ERROR_MORE_DATA);
1213 *pcbData = blob.cbData;
1214 ret = FALSE;
1216 else
1218 memcpy(pvData, blob.pbData, blob.cbData);
1219 *pcbData = blob.cbData;
1222 else
1223 SetLastError(CRYPT_E_NOT_FOUND);
1225 else
1226 SetLastError(CRYPT_E_NOT_FOUND);
1228 return ret;
1231 BOOL WINAPI CertSetStoreProperty(HCERTSTORE hCertStore, DWORD dwPropId,
1232 DWORD dwFlags, const void *pvData)
1234 WINECRYPT_CERTSTORE *store = hCertStore;
1235 BOOL ret = FALSE;
1237 TRACE("(%p, %d, %08x, %p)\n", hCertStore, dwPropId, dwFlags, pvData);
1239 if (!store->properties)
1240 store->properties = ContextPropertyList_Create();
1241 switch (dwPropId)
1243 case CERT_ACCESS_STATE_PROP_ID:
1244 SetLastError(E_INVALIDARG);
1245 break;
1246 default:
1247 if (pvData)
1249 const CRYPT_DATA_BLOB *blob = pvData;
1251 ret = ContextPropertyList_SetProperty(store->properties, dwPropId,
1252 blob->pbData, blob->cbData);
1254 else
1256 ContextPropertyList_RemoveProperty(store->properties, dwPropId);
1257 ret = TRUE;
1260 return ret;
1263 static LONG CRYPT_OpenParentStore(DWORD dwFlags,
1264 void *pvSystemStoreLocationPara, HKEY *key)
1266 HKEY root;
1267 LPCWSTR base;
1269 TRACE("(%08x, %p)\n", dwFlags, pvSystemStoreLocationPara);
1271 switch (dwFlags & CERT_SYSTEM_STORE_LOCATION_MASK)
1273 case CERT_SYSTEM_STORE_LOCAL_MACHINE:
1274 root = HKEY_LOCAL_MACHINE;
1275 base = CERT_LOCAL_MACHINE_SYSTEM_STORE_REGPATH;
1276 break;
1277 case CERT_SYSTEM_STORE_CURRENT_USER:
1278 root = HKEY_CURRENT_USER;
1279 base = CERT_LOCAL_MACHINE_SYSTEM_STORE_REGPATH;
1280 break;
1281 case CERT_SYSTEM_STORE_CURRENT_SERVICE:
1282 /* hklm\Software\Microsoft\Cryptography\Services\servicename\
1283 * SystemCertificates
1285 FIXME("CERT_SYSTEM_STORE_CURRENT_SERVICE\n");
1286 return ERROR_FILE_NOT_FOUND;
1287 case CERT_SYSTEM_STORE_SERVICES:
1288 /* hklm\Software\Microsoft\Cryptography\Services\servicename\
1289 * SystemCertificates
1291 FIXME("CERT_SYSTEM_STORE_SERVICES\n");
1292 return ERROR_FILE_NOT_FOUND;
1293 case CERT_SYSTEM_STORE_USERS:
1294 /* hku\user sid\Software\Microsoft\SystemCertificates */
1295 FIXME("CERT_SYSTEM_STORE_USERS\n");
1296 return ERROR_FILE_NOT_FOUND;
1297 case CERT_SYSTEM_STORE_CURRENT_USER_GROUP_POLICY:
1298 root = HKEY_CURRENT_USER;
1299 base = CERT_GROUP_POLICY_SYSTEM_STORE_REGPATH;
1300 break;
1301 case CERT_SYSTEM_STORE_LOCAL_MACHINE_GROUP_POLICY:
1302 root = HKEY_LOCAL_MACHINE;
1303 base = CERT_GROUP_POLICY_SYSTEM_STORE_REGPATH;
1304 break;
1305 case CERT_SYSTEM_STORE_LOCAL_MACHINE_ENTERPRISE:
1306 /* hklm\Software\Microsoft\EnterpriseCertificates */
1307 FIXME("CERT_SYSTEM_STORE_LOCAL_MACHINE_ENTERPRISE\n");
1308 return ERROR_FILE_NOT_FOUND;
1309 default:
1310 return ERROR_FILE_NOT_FOUND;
1313 return RegOpenKeyExW(root, base, 0, KEY_READ, key);
1316 BOOL WINAPI CertEnumSystemStore(DWORD dwFlags, void *pvSystemStoreLocationPara,
1317 void *pvArg, PFN_CERT_ENUM_SYSTEM_STORE pfnEnum)
1319 BOOL ret = FALSE;
1320 LONG rc;
1321 HKEY key;
1322 CERT_SYSTEM_STORE_INFO info = { sizeof(info) };
1324 TRACE("(%08x, %p, %p, %p)\n", dwFlags, pvSystemStoreLocationPara, pvArg,
1325 pfnEnum);
1327 rc = CRYPT_OpenParentStore(dwFlags, pvArg, &key);
1328 if (!rc)
1330 DWORD index = 0;
1332 ret = TRUE;
1333 do {
1334 WCHAR name[MAX_PATH];
1335 DWORD size = ARRAY_SIZE(name);
1337 rc = RegEnumKeyExW(key, index++, name, &size, NULL, NULL, NULL,
1338 NULL);
1339 if (!rc)
1340 ret = pfnEnum(name, dwFlags, &info, NULL, pvArg);
1341 } while (ret && !rc);
1342 if (ret && rc != ERROR_NO_MORE_ITEMS)
1343 SetLastError(rc);
1345 else
1346 SetLastError(rc);
1347 /* Include root store for the local machine location (it isn't in the
1348 * registry)
1350 if (ret && (dwFlags & CERT_SYSTEM_STORE_LOCATION_MASK) ==
1351 CERT_SYSTEM_STORE_LOCAL_MACHINE)
1352 ret = pfnEnum(L"Root", dwFlags, &info, NULL, pvArg);
1353 return ret;
1356 BOOL WINAPI CertEnumPhysicalStore(const void *pvSystemStore, DWORD dwFlags,
1357 void *pvArg, PFN_CERT_ENUM_PHYSICAL_STORE pfnEnum)
1359 if (dwFlags & CERT_SYSTEM_STORE_RELOCATE_FLAG)
1360 FIXME("(%p, %08x, %p, %p): stub\n", pvSystemStore, dwFlags, pvArg,
1361 pfnEnum);
1362 else
1363 FIXME("(%s, %08x, %p, %p): stub\n", debugstr_w(pvSystemStore),
1364 dwFlags, pvArg,
1365 pfnEnum);
1366 return FALSE;
1369 BOOL WINAPI CertRegisterPhysicalStore(const void *pvSystemStore, DWORD dwFlags,
1370 LPCWSTR pwszStoreName, PCERT_PHYSICAL_STORE_INFO pStoreInfo, void *pvReserved)
1372 if (dwFlags & CERT_SYSTEM_STORE_RELOCATE_FLAG)
1373 FIXME("(%p, %08x, %s, %p, %p): stub\n", pvSystemStore, dwFlags,
1374 debugstr_w(pwszStoreName), pStoreInfo, pvReserved);
1375 else
1376 FIXME("(%s, %08x, %s, %p, %p): stub\n", debugstr_w(pvSystemStore),
1377 dwFlags, debugstr_w(pwszStoreName), pStoreInfo, pvReserved);
1378 return FALSE;
1381 BOOL WINAPI CertUnregisterPhysicalStore(const void *pvSystemStore, DWORD dwFlags,
1382 LPCWSTR pwszStoreName)
1384 FIXME("(%p, %08x, %s): stub\n", pvSystemStore, dwFlags, debugstr_w(pwszStoreName));
1385 return TRUE;
1388 BOOL WINAPI CertRegisterSystemStore(const void *pvSystemStore, DWORD dwFlags,
1389 PCERT_SYSTEM_STORE_INFO pStoreInfo, void *pvReserved)
1391 HCERTSTORE hstore;
1393 if (dwFlags & CERT_SYSTEM_STORE_RELOCATE_FLAG )
1395 FIXME("(%p, %08x, %p, %p): flag not supported\n", pvSystemStore, dwFlags, pStoreInfo, pvReserved);
1396 return FALSE;
1399 TRACE("(%s, %08x, %p, %p)\n", debugstr_w(pvSystemStore), dwFlags, pStoreInfo, pvReserved);
1401 hstore = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY_W, 0, 0, dwFlags, pvSystemStore);
1402 if (hstore)
1404 CertCloseStore(hstore, 0);
1405 return TRUE;
1408 return FALSE;
1411 BOOL WINAPI CertUnregisterSystemStore(const void *pvSystemStore, DWORD dwFlags)
1413 HCERTSTORE hstore;
1415 if (dwFlags & CERT_SYSTEM_STORE_RELOCATE_FLAG)
1417 FIXME("(%p, %08x): flag not supported\n", pvSystemStore, dwFlags);
1418 return FALSE;
1420 TRACE("(%s, %08x)\n", debugstr_w(pvSystemStore), dwFlags);
1422 hstore = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY_W, 0, 0, dwFlags | CERT_STORE_OPEN_EXISTING_FLAG, pvSystemStore);
1423 if (hstore == NULL)
1424 return FALSE;
1426 hstore = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY_W, 0, 0, dwFlags | CERT_STORE_DELETE_FLAG, pvSystemStore);
1427 if (hstore == NULL && GetLastError() == 0)
1428 return TRUE;
1430 return FALSE;
1433 static void EmptyStore_addref(WINECRYPT_CERTSTORE *store)
1435 TRACE("(%p)\n", store);
1438 static DWORD EmptyStore_release(WINECRYPT_CERTSTORE *store, DWORD flags)
1440 TRACE("(%p)\n", store);
1441 return E_UNEXPECTED;
1444 static void EmptyStore_releaseContext(WINECRYPT_CERTSTORE *store, context_t *context)
1446 Context_Free(context);
1449 static BOOL EmptyStore_add(WINECRYPT_CERTSTORE *store, context_t *context,
1450 context_t *replace, context_t **ret_context, BOOL use_link)
1452 TRACE("(%p, %p, %p, %p)\n", store, context, replace, ret_context);
1454 /* FIXME: We should clone the context */
1455 if(ret_context) {
1456 Context_AddRef(context);
1457 *ret_context = context;
1460 return TRUE;
1463 static context_t *EmptyStore_enum(WINECRYPT_CERTSTORE *store, context_t *prev)
1465 TRACE("(%p, %p)\n", store, prev);
1467 SetLastError(CRYPT_E_NOT_FOUND);
1468 return NULL;
1471 static BOOL EmptyStore_delete(WINECRYPT_CERTSTORE *store, context_t *context)
1473 return TRUE;
1476 static BOOL EmptyStore_control(WINECRYPT_CERTSTORE *store, DWORD flags, DWORD ctrl_type, void const *ctrl_para)
1478 TRACE("()\n");
1480 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1481 return FALSE;
1484 static const store_vtbl_t EmptyStoreVtbl = {
1485 EmptyStore_addref,
1486 EmptyStore_release,
1487 EmptyStore_releaseContext,
1488 EmptyStore_control,
1490 EmptyStore_add,
1491 EmptyStore_enum,
1492 EmptyStore_delete
1493 }, {
1494 EmptyStore_add,
1495 EmptyStore_enum,
1496 EmptyStore_delete
1497 }, {
1498 EmptyStore_add,
1499 EmptyStore_enum,
1500 EmptyStore_delete
1504 WINECRYPT_CERTSTORE empty_store;
1506 void init_empty_store(void)
1508 CRYPT_InitStore(&empty_store, CERT_STORE_READONLY_FLAG, StoreTypeEmpty, &EmptyStoreVtbl);