crypt32: Moved store functions to vtbl.
[wine/multimedia.git] / dlls / crypt32 / store.c
blob0042d92de9bbf3c824c1658de7b0aee533444894
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/list.h"
39 #include "wine/exception.h"
40 #include "crypt32_private.h"
42 WINE_DEFAULT_DEBUG_CHANNEL(crypt);
44 static const WINE_CONTEXT_INTERFACE gCertInterface = {
45 (CreateContextFunc)CertCreateCertificateContext,
46 (AddContextToStoreFunc)CertAddCertificateContextToStore,
47 (AddEncodedContextToStoreFunc)CertAddEncodedCertificateToStore,
48 (DuplicateContextFunc)CertDuplicateCertificateContext,
49 (EnumContextsInStoreFunc)CertEnumCertificatesInStore,
50 (EnumPropertiesFunc)CertEnumCertificateContextProperties,
51 (GetContextPropertyFunc)CertGetCertificateContextProperty,
52 (SetContextPropertyFunc)CertSetCertificateContextProperty,
53 (SerializeElementFunc)CertSerializeCertificateStoreElement,
54 (FreeContextFunc)CertFreeCertificateContext,
55 (DeleteContextFunc)CertDeleteCertificateFromStore,
57 const WINE_CONTEXT_INTERFACE *pCertInterface = &gCertInterface;
59 static const WINE_CONTEXT_INTERFACE gCRLInterface = {
60 (CreateContextFunc)CertCreateCRLContext,
61 (AddContextToStoreFunc)CertAddCRLContextToStore,
62 (AddEncodedContextToStoreFunc)CertAddEncodedCRLToStore,
63 (DuplicateContextFunc)CertDuplicateCRLContext,
64 (EnumContextsInStoreFunc)CertEnumCRLsInStore,
65 (EnumPropertiesFunc)CertEnumCRLContextProperties,
66 (GetContextPropertyFunc)CertGetCRLContextProperty,
67 (SetContextPropertyFunc)CertSetCRLContextProperty,
68 (SerializeElementFunc)CertSerializeCRLStoreElement,
69 (FreeContextFunc)CertFreeCRLContext,
70 (DeleteContextFunc)CertDeleteCRLFromStore,
72 const WINE_CONTEXT_INTERFACE *pCRLInterface = &gCRLInterface;
74 static const WINE_CONTEXT_INTERFACE gCTLInterface = {
75 (CreateContextFunc)CertCreateCTLContext,
76 (AddContextToStoreFunc)CertAddCTLContextToStore,
77 (AddEncodedContextToStoreFunc)CertAddEncodedCTLToStore,
78 (DuplicateContextFunc)CertDuplicateCTLContext,
79 (EnumContextsInStoreFunc)CertEnumCTLsInStore,
80 (EnumPropertiesFunc)CertEnumCTLContextProperties,
81 (GetContextPropertyFunc)CertGetCTLContextProperty,
82 (SetContextPropertyFunc)CertSetCTLContextProperty,
83 (SerializeElementFunc)CertSerializeCTLStoreElement,
84 (FreeContextFunc)CertFreeCTLContext,
85 (DeleteContextFunc)CertDeleteCTLFromStore,
87 const WINE_CONTEXT_INTERFACE *pCTLInterface = &gCTLInterface;
89 typedef struct _WINE_MEMSTORE
91 WINECRYPT_CERTSTORE hdr;
92 struct ContextList *certs;
93 struct ContextList *crls;
94 struct ContextList *ctls;
95 } WINE_MEMSTORE;
97 void CRYPT_InitStore(WINECRYPT_CERTSTORE *store, DWORD dwFlags, CertStoreType type, const store_vtbl_t *vtbl)
99 store->ref = 1;
100 store->dwMagic = WINE_CRYPTCERTSTORE_MAGIC;
101 store->type = type;
102 store->dwOpenFlags = dwFlags;
103 store->vtbl = vtbl;
104 store->properties = NULL;
107 void CRYPT_FreeStore(WINECRYPT_CERTSTORE *store)
109 if (store->properties)
110 ContextPropertyList_Free(store->properties);
111 CryptMemFree(store);
114 BOOL WINAPI I_CertUpdateStore(HCERTSTORE store1, HCERTSTORE store2, DWORD unk0,
115 DWORD unk1)
117 static BOOL warned = FALSE;
118 const WINE_CONTEXT_INTERFACE * const interfaces[] = { pCertInterface,
119 pCRLInterface, pCTLInterface };
120 DWORD i;
122 TRACE("(%p, %p, %08x, %08x)\n", store1, store2, unk0, unk1);
123 if (!warned)
125 FIXME("semi-stub\n");
126 warned = TRUE;
129 /* Poor-man's resync: empty first store, then add everything from second
130 * store to it.
132 for (i = 0; i < sizeof(interfaces) / sizeof(interfaces[0]); i++)
134 const void *context;
136 do {
137 context = interfaces[i]->enumContextsInStore(store1, NULL);
138 if (context)
139 interfaces[i]->deleteFromStore(context);
140 } while (context);
141 do {
142 context = interfaces[i]->enumContextsInStore(store2, context);
143 if (context)
144 interfaces[i]->addContextToStore(store1, context,
145 CERT_STORE_ADD_ALWAYS, NULL);
146 } while (context);
148 return TRUE;
151 static BOOL CRYPT_MemAddCert(WINECRYPT_CERTSTORE *store, void *cert,
152 void *toReplace, const void **ppStoreContext)
154 WINE_MEMSTORE *ms = (WINE_MEMSTORE *)store;
155 PCERT_CONTEXT context;
157 TRACE("(%p, %p, %p, %p)\n", store, cert, toReplace, ppStoreContext);
159 context = ContextList_Add(ms->certs, cert, toReplace);
160 if (context)
162 context->hCertStore = store;
163 if (ppStoreContext) {
164 *ppStoreContext = CertDuplicateCertificateContext(context);
167 return context != 0;
170 static void *CRYPT_MemEnumCert(WINECRYPT_CERTSTORE *store, void *pPrev)
172 WINE_MEMSTORE *ms = (WINE_MEMSTORE *)store;
173 void *ret;
175 TRACE("(%p, %p)\n", store, pPrev);
177 ret = ContextList_Enum(ms->certs, pPrev);
178 if (!ret)
179 SetLastError(CRYPT_E_NOT_FOUND);
181 TRACE("returning %p\n", ret);
182 return ret;
185 static BOOL CRYPT_MemDeleteCert(WINECRYPT_CERTSTORE *store, void *pCertContext)
187 WINE_MEMSTORE *ms = (WINE_MEMSTORE *)store;
188 BOOL ret;
190 if (ContextList_Remove(ms->certs, pCertContext))
191 ret = CertFreeCertificateContext(pCertContext);
192 else
193 ret = TRUE;
194 return ret;
197 static BOOL CRYPT_MemAddCrl(WINECRYPT_CERTSTORE *store, void *crl,
198 void *toReplace, const void **ppStoreContext)
200 WINE_MEMSTORE *ms = (WINE_MEMSTORE *)store;
201 PCRL_CONTEXT context;
203 TRACE("(%p, %p, %p, %p)\n", store, crl, toReplace, ppStoreContext);
205 context = ContextList_Add(ms->crls, crl, toReplace);
206 if (context)
208 context->hCertStore = store;
209 if (ppStoreContext)
210 *ppStoreContext = CertDuplicateCRLContext(context);
212 return context != 0;
215 static void *CRYPT_MemEnumCrl(WINECRYPT_CERTSTORE *store, void *pPrev)
217 WINE_MEMSTORE *ms = (WINE_MEMSTORE *)store;
218 void *ret;
220 TRACE("(%p, %p)\n", store, pPrev);
222 ret = ContextList_Enum(ms->crls, pPrev);
223 if (!ret)
224 SetLastError(CRYPT_E_NOT_FOUND);
226 TRACE("returning %p\n", ret);
227 return ret;
230 static BOOL CRYPT_MemDeleteCrl(WINECRYPT_CERTSTORE *store, void *pCrlContext)
232 WINE_MEMSTORE *ms = (WINE_MEMSTORE *)store;
233 BOOL ret;
235 if (ContextList_Remove(ms->crls, pCrlContext))
236 ret = CertFreeCRLContext(pCrlContext);
237 else
238 ret = TRUE;
239 return ret;
242 static BOOL CRYPT_MemAddCtl(WINECRYPT_CERTSTORE *store, void *ctl,
243 void *toReplace, const void **ppStoreContext)
245 WINE_MEMSTORE *ms = (WINE_MEMSTORE *)store;
246 PCTL_CONTEXT context;
248 TRACE("(%p, %p, %p, %p)\n", store, ctl, toReplace, ppStoreContext);
250 context = ContextList_Add(ms->ctls, ctl, toReplace);
251 if (context)
253 context->hCertStore = store;
254 if (ppStoreContext)
255 *ppStoreContext = CertDuplicateCTLContext(context);
257 return context != 0;
260 static void *CRYPT_MemEnumCtl(WINECRYPT_CERTSTORE *store, void *pPrev)
262 WINE_MEMSTORE *ms = (WINE_MEMSTORE *)store;
263 void *ret;
265 TRACE("(%p, %p)\n", store, pPrev);
267 ret = ContextList_Enum(ms->ctls, pPrev);
268 if (!ret)
269 SetLastError(CRYPT_E_NOT_FOUND);
271 TRACE("returning %p\n", ret);
272 return ret;
275 static BOOL CRYPT_MemDeleteCtl(WINECRYPT_CERTSTORE *store, void *pCtlContext)
277 WINE_MEMSTORE *ms = (WINE_MEMSTORE *)store;
278 BOOL ret;
280 if (ContextList_Remove(ms->ctls, pCtlContext))
281 ret = CertFreeCTLContext(pCtlContext);
282 else
283 ret = TRUE;
284 return ret;
287 static void MemStore_closeStore(WINECRYPT_CERTSTORE *cert_store, DWORD dwFlags)
289 WINE_MEMSTORE *store = (WINE_MEMSTORE*)cert_store;
291 TRACE("(%p, %08x)\n", store, dwFlags);
292 if (dwFlags)
293 FIXME("Unimplemented flags: %08x\n", dwFlags);
295 ContextList_Free(store->certs);
296 ContextList_Free(store->crls);
297 ContextList_Free(store->ctls);
298 CRYPT_FreeStore((WINECRYPT_CERTSTORE*)store);
301 static BOOL MemStore_control(WINECRYPT_CERTSTORE *store, DWORD dwFlags,
302 DWORD dwCtrlType, void const *pvCtrlPara)
304 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
305 return FALSE;
308 static const store_vtbl_t MemStoreVtbl = {
309 MemStore_closeStore,
310 MemStore_control
313 static WINECRYPT_CERTSTORE *CRYPT_MemOpenStore(HCRYPTPROV hCryptProv,
314 DWORD dwFlags, const void *pvPara)
316 WINE_MEMSTORE *store;
318 TRACE("(%ld, %08x, %p)\n", hCryptProv, dwFlags, pvPara);
320 if (dwFlags & CERT_STORE_DELETE_FLAG)
322 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
323 store = NULL;
325 else
327 store = CryptMemAlloc(sizeof(WINE_MEMSTORE));
328 if (store)
330 memset(store, 0, sizeof(WINE_MEMSTORE));
331 CRYPT_InitStore(&store->hdr, dwFlags, StoreTypeMem, &MemStoreVtbl);
332 store->hdr.certs.addContext = CRYPT_MemAddCert;
333 store->hdr.certs.enumContext = CRYPT_MemEnumCert;
334 store->hdr.certs.deleteContext = CRYPT_MemDeleteCert;
335 store->hdr.crls.addContext = CRYPT_MemAddCrl;
336 store->hdr.crls.enumContext = CRYPT_MemEnumCrl;
337 store->hdr.crls.deleteContext = CRYPT_MemDeleteCrl;
338 store->hdr.ctls.addContext = CRYPT_MemAddCtl;
339 store->hdr.ctls.enumContext = CRYPT_MemEnumCtl;
340 store->hdr.ctls.deleteContext = CRYPT_MemDeleteCtl;
341 store->certs = ContextList_Create(pCertInterface,
342 sizeof(CERT_CONTEXT));
343 store->crls = ContextList_Create(pCRLInterface,
344 sizeof(CRL_CONTEXT));
345 store->ctls = ContextList_Create(pCTLInterface,
346 sizeof(CTL_CONTEXT));
347 /* Mem store doesn't need crypto provider, so close it */
348 if (hCryptProv && !(dwFlags & CERT_STORE_NO_CRYPT_RELEASE_FLAG))
349 CryptReleaseContext(hCryptProv, 0);
352 return (WINECRYPT_CERTSTORE*)store;
355 static const WCHAR rootW[] = { 'R','o','o','t',0 };
357 static WINECRYPT_CERTSTORE *CRYPT_SysRegOpenStoreW(HCRYPTPROV hCryptProv,
358 DWORD dwFlags, const void *pvPara)
360 static const WCHAR fmt[] = { '%','s','\\','%','s',0 };
361 LPCWSTR storeName = pvPara;
362 LPWSTR storePath;
363 WINECRYPT_CERTSTORE *store = NULL;
364 HKEY root;
365 LPCWSTR base;
367 TRACE("(%ld, %08x, %s)\n", hCryptProv, dwFlags,
368 debugstr_w(pvPara));
370 if (!pvPara)
372 SetLastError(E_INVALIDARG);
373 return NULL;
375 /* FIXME: In Windows, the root store (even the current user location) is
376 * protected: adding to it or removing from it present a user interface,
377 * and the keys are owned by the system process, not the current user.
378 * Wine's registry doesn't implement access controls, so a similar
379 * mechanism isn't possible yet.
381 if ((dwFlags & CERT_SYSTEM_STORE_LOCATION_MASK) ==
382 CERT_SYSTEM_STORE_LOCAL_MACHINE && !lstrcmpiW(storeName, rootW))
383 return CRYPT_RootOpenStore(hCryptProv, dwFlags);
385 switch (dwFlags & CERT_SYSTEM_STORE_LOCATION_MASK)
387 case CERT_SYSTEM_STORE_LOCAL_MACHINE:
388 root = HKEY_LOCAL_MACHINE;
389 base = CERT_LOCAL_MACHINE_SYSTEM_STORE_REGPATH;
390 break;
391 case CERT_SYSTEM_STORE_CURRENT_USER:
392 root = HKEY_CURRENT_USER;
393 base = CERT_LOCAL_MACHINE_SYSTEM_STORE_REGPATH;
394 break;
395 case CERT_SYSTEM_STORE_CURRENT_SERVICE:
396 /* hklm\Software\Microsoft\Cryptography\Services\servicename\
397 * SystemCertificates
399 FIXME("CERT_SYSTEM_STORE_CURRENT_SERVICE, %s: stub\n",
400 debugstr_w(storeName));
401 return NULL;
402 case CERT_SYSTEM_STORE_SERVICES:
403 /* hklm\Software\Microsoft\Cryptography\Services\servicename\
404 * SystemCertificates
406 FIXME("CERT_SYSTEM_STORE_SERVICES, %s: stub\n",
407 debugstr_w(storeName));
408 return NULL;
409 case CERT_SYSTEM_STORE_USERS:
410 /* hku\user sid\Software\Microsoft\SystemCertificates */
411 FIXME("CERT_SYSTEM_STORE_USERS, %s: stub\n",
412 debugstr_w(storeName));
413 return NULL;
414 case CERT_SYSTEM_STORE_CURRENT_USER_GROUP_POLICY:
415 root = HKEY_CURRENT_USER;
416 base = CERT_GROUP_POLICY_SYSTEM_STORE_REGPATH;
417 break;
418 case CERT_SYSTEM_STORE_LOCAL_MACHINE_GROUP_POLICY:
419 root = HKEY_LOCAL_MACHINE;
420 base = CERT_GROUP_POLICY_SYSTEM_STORE_REGPATH;
421 break;
422 case CERT_SYSTEM_STORE_LOCAL_MACHINE_ENTERPRISE:
423 /* hklm\Software\Microsoft\EnterpriseCertificates */
424 FIXME("CERT_SYSTEM_STORE_LOCAL_MACHINE_ENTERPRISE, %s: stub\n",
425 debugstr_w(storeName));
426 return NULL;
427 default:
428 SetLastError(E_INVALIDARG);
429 return NULL;
432 storePath = CryptMemAlloc((lstrlenW(base) + lstrlenW(storeName) + 2) *
433 sizeof(WCHAR));
434 if (storePath)
436 LONG rc;
437 HKEY key;
438 REGSAM sam = dwFlags & CERT_STORE_READONLY_FLAG ? KEY_READ :
439 KEY_ALL_ACCESS;
441 wsprintfW(storePath, fmt, base, storeName);
442 if (dwFlags & CERT_STORE_OPEN_EXISTING_FLAG)
443 rc = RegOpenKeyExW(root, storePath, 0, sam, &key);
444 else
446 DWORD disp;
448 rc = RegCreateKeyExW(root, storePath, 0, NULL, 0, sam, NULL,
449 &key, &disp);
450 if (!rc && dwFlags & CERT_STORE_CREATE_NEW_FLAG &&
451 disp == REG_OPENED_EXISTING_KEY)
453 RegCloseKey(key);
454 rc = ERROR_FILE_EXISTS;
457 if (!rc)
459 store = CRYPT_RegOpenStore(hCryptProv, dwFlags, key);
460 RegCloseKey(key);
462 else
463 SetLastError(rc);
464 CryptMemFree(storePath);
466 return store;
469 static WINECRYPT_CERTSTORE *CRYPT_SysRegOpenStoreA(HCRYPTPROV hCryptProv,
470 DWORD dwFlags, const void *pvPara)
472 int len;
473 WINECRYPT_CERTSTORE *ret = NULL;
475 TRACE("(%ld, %08x, %s)\n", hCryptProv, dwFlags,
476 debugstr_a(pvPara));
478 if (!pvPara)
480 SetLastError(ERROR_FILE_NOT_FOUND);
481 return NULL;
483 len = MultiByteToWideChar(CP_ACP, 0, pvPara, -1, NULL, 0);
484 if (len)
486 LPWSTR storeName = CryptMemAlloc(len * sizeof(WCHAR));
488 if (storeName)
490 MultiByteToWideChar(CP_ACP, 0, pvPara, -1, storeName, len);
491 ret = CRYPT_SysRegOpenStoreW(hCryptProv, dwFlags, storeName);
492 CryptMemFree(storeName);
495 return ret;
498 static WINECRYPT_CERTSTORE *CRYPT_SysOpenStoreW(HCRYPTPROV hCryptProv,
499 DWORD dwFlags, const void *pvPara)
501 HCERTSTORE store = 0;
502 BOOL ret;
504 TRACE("(%ld, %08x, %s)\n", hCryptProv, dwFlags,
505 debugstr_w(pvPara));
507 if (!pvPara)
509 SetLastError(ERROR_FILE_NOT_FOUND);
510 return NULL;
512 /* This returns a different error than system registry stores if the
513 * location is invalid.
515 switch (dwFlags & CERT_SYSTEM_STORE_LOCATION_MASK)
517 case CERT_SYSTEM_STORE_LOCAL_MACHINE:
518 case CERT_SYSTEM_STORE_CURRENT_USER:
519 case CERT_SYSTEM_STORE_CURRENT_SERVICE:
520 case CERT_SYSTEM_STORE_SERVICES:
521 case CERT_SYSTEM_STORE_USERS:
522 case CERT_SYSTEM_STORE_CURRENT_USER_GROUP_POLICY:
523 case CERT_SYSTEM_STORE_LOCAL_MACHINE_GROUP_POLICY:
524 case CERT_SYSTEM_STORE_LOCAL_MACHINE_ENTERPRISE:
525 ret = TRUE;
526 break;
527 default:
528 SetLastError(ERROR_FILE_NOT_FOUND);
529 ret = FALSE;
531 if (ret)
533 HCERTSTORE regStore = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY_W,
534 0, 0, dwFlags, pvPara);
536 if (regStore)
538 store = CertOpenStore(CERT_STORE_PROV_COLLECTION, 0, 0,
539 CERT_STORE_CREATE_NEW_FLAG, NULL);
540 CertAddStoreToCollection(store, regStore,
541 dwFlags & CERT_STORE_READONLY_FLAG ? 0 :
542 CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
543 CertCloseStore(regStore, 0);
544 /* CERT_SYSTEM_STORE_CURRENT_USER returns both the HKCU and HKLM
545 * stores.
547 if ((dwFlags & CERT_SYSTEM_STORE_LOCATION_MASK) ==
548 CERT_SYSTEM_STORE_CURRENT_USER)
550 dwFlags &= ~CERT_SYSTEM_STORE_CURRENT_USER;
551 dwFlags |= CERT_SYSTEM_STORE_LOCAL_MACHINE;
552 regStore = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY_W, 0,
553 0, dwFlags, pvPara);
554 if (regStore)
556 CertAddStoreToCollection(store, regStore,
557 dwFlags & CERT_STORE_READONLY_FLAG ? 0 :
558 CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
559 CertCloseStore(regStore, 0);
562 /* System store doesn't need crypto provider, so close it */
563 if (hCryptProv && !(dwFlags & CERT_STORE_NO_CRYPT_RELEASE_FLAG))
564 CryptReleaseContext(hCryptProv, 0);
567 return store;
570 static WINECRYPT_CERTSTORE *CRYPT_SysOpenStoreA(HCRYPTPROV hCryptProv,
571 DWORD dwFlags, const void *pvPara)
573 int len;
574 WINECRYPT_CERTSTORE *ret = NULL;
576 TRACE("(%ld, %08x, %s)\n", hCryptProv, dwFlags,
577 debugstr_a(pvPara));
579 if (!pvPara)
581 SetLastError(ERROR_FILE_NOT_FOUND);
582 return NULL;
584 len = MultiByteToWideChar(CP_ACP, 0, pvPara, -1, NULL, 0);
585 if (len)
587 LPWSTR storeName = CryptMemAlloc(len * sizeof(WCHAR));
589 if (storeName)
591 MultiByteToWideChar(CP_ACP, 0, pvPara, -1, storeName, len);
592 ret = CRYPT_SysOpenStoreW(hCryptProv, dwFlags, storeName);
593 CryptMemFree(storeName);
596 return ret;
599 static void WINAPI CRYPT_MsgCloseStore(HCERTSTORE hCertStore, DWORD dwFlags)
601 HCRYPTMSG msg = hCertStore;
603 TRACE("(%p, %08x)\n", msg, dwFlags);
604 CryptMsgClose(msg);
607 static void *msgProvFuncs[] = {
608 CRYPT_MsgCloseStore,
611 static WINECRYPT_CERTSTORE *CRYPT_MsgOpenStore(HCRYPTPROV hCryptProv,
612 DWORD dwFlags, const void *pvPara)
614 WINECRYPT_CERTSTORE *store = NULL;
615 HCRYPTMSG msg = (HCRYPTMSG)pvPara;
616 WINECRYPT_CERTSTORE *memStore;
618 TRACE("(%ld, %08x, %p)\n", hCryptProv, dwFlags, pvPara);
620 memStore = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
621 CERT_STORE_CREATE_NEW_FLAG, NULL);
622 if (memStore)
624 BOOL ret;
625 DWORD size, count, i;
627 size = sizeof(count);
628 ret = CryptMsgGetParam(msg, CMSG_CERT_COUNT_PARAM, 0, &count, &size);
629 for (i = 0; ret && i < count; i++)
631 size = 0;
632 ret = CryptMsgGetParam(msg, CMSG_CERT_PARAM, i, NULL, &size);
633 if (ret)
635 LPBYTE buf = CryptMemAlloc(size);
637 if (buf)
639 ret = CryptMsgGetParam(msg, CMSG_CERT_PARAM, i, buf, &size);
640 if (ret)
641 ret = CertAddEncodedCertificateToStore(memStore,
642 X509_ASN_ENCODING, buf, size, CERT_STORE_ADD_ALWAYS,
643 NULL);
644 CryptMemFree(buf);
648 size = sizeof(count);
649 ret = CryptMsgGetParam(msg, CMSG_CRL_COUNT_PARAM, 0, &count, &size);
650 for (i = 0; ret && i < count; i++)
652 size = 0;
653 ret = CryptMsgGetParam(msg, CMSG_CRL_PARAM, i, NULL, &size);
654 if (ret)
656 LPBYTE buf = CryptMemAlloc(size);
658 if (buf)
660 ret = CryptMsgGetParam(msg, CMSG_CRL_PARAM, i, buf, &size);
661 if (ret)
662 ret = CertAddEncodedCRLToStore(memStore,
663 X509_ASN_ENCODING, buf, size, CERT_STORE_ADD_ALWAYS,
664 NULL);
665 CryptMemFree(buf);
669 if (ret)
671 CERT_STORE_PROV_INFO provInfo = { 0 };
673 provInfo.cbSize = sizeof(provInfo);
674 provInfo.cStoreProvFunc = sizeof(msgProvFuncs) /
675 sizeof(msgProvFuncs[0]);
676 provInfo.rgpvStoreProvFunc = msgProvFuncs;
677 provInfo.hStoreProv = CryptMsgDuplicate(msg);
678 store = CRYPT_ProvCreateStore(dwFlags, memStore, &provInfo);
679 /* Msg store doesn't need crypto provider, so close it */
680 if (hCryptProv && !(dwFlags & CERT_STORE_NO_CRYPT_RELEASE_FLAG))
681 CryptReleaseContext(hCryptProv, 0);
683 else
684 CertCloseStore(memStore, 0);
686 TRACE("returning %p\n", store);
687 return store;
690 static WINECRYPT_CERTSTORE *CRYPT_PKCSOpenStore(HCRYPTPROV hCryptProv,
691 DWORD dwFlags, const void *pvPara)
693 HCRYPTMSG msg;
694 WINECRYPT_CERTSTORE *store = NULL;
695 const CRYPT_DATA_BLOB *data = pvPara;
696 BOOL ret;
697 DWORD msgOpenFlags = dwFlags & CERT_STORE_NO_CRYPT_RELEASE_FLAG ? 0 :
698 CMSG_CRYPT_RELEASE_CONTEXT_FLAG;
700 TRACE("(%ld, %08x, %p)\n", hCryptProv, dwFlags, pvPara);
702 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, msgOpenFlags, CMSG_SIGNED,
703 hCryptProv, NULL, NULL);
704 ret = CryptMsgUpdate(msg, data->pbData, data->cbData, TRUE);
705 if (!ret)
707 CryptMsgClose(msg);
708 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, msgOpenFlags, 0,
709 hCryptProv, NULL, NULL);
710 ret = CryptMsgUpdate(msg, data->pbData, data->cbData, TRUE);
711 if (ret)
713 DWORD type, size = sizeof(type);
715 /* Only signed messages are allowed, check type */
716 ret = CryptMsgGetParam(msg, CMSG_TYPE_PARAM, 0, &type, &size);
717 if (ret && type != CMSG_SIGNED)
719 SetLastError(CRYPT_E_INVALID_MSG_TYPE);
720 ret = FALSE;
724 if (ret)
725 store = CRYPT_MsgOpenStore(0, dwFlags, msg);
726 CryptMsgClose(msg);
727 TRACE("returning %p\n", store);
728 return store;
731 static WINECRYPT_CERTSTORE *CRYPT_SerializedOpenStore(HCRYPTPROV hCryptProv,
732 DWORD dwFlags, const void *pvPara)
734 HCERTSTORE store;
735 const CRYPT_DATA_BLOB *data = pvPara;
737 TRACE("(%ld, %08x, %p)\n", hCryptProv, dwFlags, pvPara);
739 if (dwFlags & CERT_STORE_DELETE_FLAG)
741 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
742 return NULL;
745 store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
746 CERT_STORE_CREATE_NEW_FLAG, NULL);
747 if (store)
749 if (!CRYPT_ReadSerializedStoreFromBlob(data, store))
751 CertCloseStore(store, 0);
752 store = NULL;
755 TRACE("returning %p\n", store);
756 return (WINECRYPT_CERTSTORE*)store;
759 static WINECRYPT_CERTSTORE *CRYPT_PhysOpenStoreW(HCRYPTPROV hCryptProv,
760 DWORD dwFlags, const void *pvPara)
762 if (dwFlags & CERT_SYSTEM_STORE_RELOCATE_FLAG)
763 FIXME("(%ld, %08x, %p): stub\n", hCryptProv, dwFlags, pvPara);
764 else
765 FIXME("(%ld, %08x, %s): stub\n", hCryptProv, dwFlags,
766 debugstr_w(pvPara));
767 return NULL;
770 HCERTSTORE WINAPI CertOpenStore(LPCSTR lpszStoreProvider,
771 DWORD dwMsgAndCertEncodingType, HCRYPTPROV_LEGACY hCryptProv, DWORD dwFlags,
772 const void* pvPara)
774 WINECRYPT_CERTSTORE *hcs;
775 StoreOpenFunc openFunc = NULL;
777 TRACE("(%s, %08x, %08lx, %08x, %p)\n", debugstr_a(lpszStoreProvider),
778 dwMsgAndCertEncodingType, hCryptProv, dwFlags, pvPara);
780 if (IS_INTOID(lpszStoreProvider))
782 switch (LOWORD(lpszStoreProvider))
784 case LOWORD(CERT_STORE_PROV_MSG):
785 openFunc = CRYPT_MsgOpenStore;
786 break;
787 case LOWORD(CERT_STORE_PROV_MEMORY):
788 openFunc = CRYPT_MemOpenStore;
789 break;
790 case LOWORD(CERT_STORE_PROV_FILE):
791 openFunc = CRYPT_FileOpenStore;
792 break;
793 case LOWORD(CERT_STORE_PROV_PKCS7):
794 openFunc = CRYPT_PKCSOpenStore;
795 break;
796 case LOWORD(CERT_STORE_PROV_SERIALIZED):
797 openFunc = CRYPT_SerializedOpenStore;
798 break;
799 case LOWORD(CERT_STORE_PROV_REG):
800 openFunc = CRYPT_RegOpenStore;
801 break;
802 case LOWORD(CERT_STORE_PROV_FILENAME_A):
803 openFunc = CRYPT_FileNameOpenStoreA;
804 break;
805 case LOWORD(CERT_STORE_PROV_FILENAME_W):
806 openFunc = CRYPT_FileNameOpenStoreW;
807 break;
808 case LOWORD(CERT_STORE_PROV_COLLECTION):
809 openFunc = CRYPT_CollectionOpenStore;
810 break;
811 case LOWORD(CERT_STORE_PROV_SYSTEM_A):
812 openFunc = CRYPT_SysOpenStoreA;
813 break;
814 case LOWORD(CERT_STORE_PROV_SYSTEM_W):
815 openFunc = CRYPT_SysOpenStoreW;
816 break;
817 case LOWORD(CERT_STORE_PROV_SYSTEM_REGISTRY_A):
818 openFunc = CRYPT_SysRegOpenStoreA;
819 break;
820 case LOWORD(CERT_STORE_PROV_SYSTEM_REGISTRY_W):
821 openFunc = CRYPT_SysRegOpenStoreW;
822 break;
823 case LOWORD(CERT_STORE_PROV_PHYSICAL_W):
824 openFunc = CRYPT_PhysOpenStoreW;
825 break;
826 default:
827 if (LOWORD(lpszStoreProvider))
828 FIXME("unimplemented type %d\n", LOWORD(lpszStoreProvider));
831 else if (!strcasecmp(lpszStoreProvider, sz_CERT_STORE_PROV_MEMORY))
832 openFunc = CRYPT_MemOpenStore;
833 else if (!strcasecmp(lpszStoreProvider, sz_CERT_STORE_PROV_FILENAME_W))
834 openFunc = CRYPT_FileOpenStore;
835 else if (!strcasecmp(lpszStoreProvider, sz_CERT_STORE_PROV_SYSTEM))
836 openFunc = CRYPT_SysOpenStoreW;
837 else if (!strcasecmp(lpszStoreProvider, sz_CERT_STORE_PROV_PKCS7))
838 openFunc = CRYPT_PKCSOpenStore;
839 else if (!strcasecmp(lpszStoreProvider, sz_CERT_STORE_PROV_SERIALIZED))
840 openFunc = CRYPT_SerializedOpenStore;
841 else if (!strcasecmp(lpszStoreProvider, sz_CERT_STORE_PROV_COLLECTION))
842 openFunc = CRYPT_CollectionOpenStore;
843 else if (!strcasecmp(lpszStoreProvider, sz_CERT_STORE_PROV_SYSTEM_REGISTRY))
844 openFunc = CRYPT_SysRegOpenStoreW;
845 else
847 FIXME("unimplemented type %s\n", lpszStoreProvider);
848 openFunc = NULL;
851 if (!openFunc)
852 hcs = CRYPT_ProvOpenStore(lpszStoreProvider, dwMsgAndCertEncodingType,
853 hCryptProv, dwFlags, pvPara);
854 else
855 hcs = openFunc(hCryptProv, dwFlags, pvPara);
856 return hcs;
859 HCERTSTORE WINAPI CertOpenSystemStoreA(HCRYPTPROV_LEGACY hProv,
860 LPCSTR szSubSystemProtocol)
862 if (!szSubSystemProtocol)
864 SetLastError(E_INVALIDARG);
865 return 0;
867 return CertOpenStore(CERT_STORE_PROV_SYSTEM_A, 0, hProv,
868 CERT_SYSTEM_STORE_CURRENT_USER, szSubSystemProtocol);
871 HCERTSTORE WINAPI CertOpenSystemStoreW(HCRYPTPROV_LEGACY hProv,
872 LPCWSTR szSubSystemProtocol)
874 if (!szSubSystemProtocol)
876 SetLastError(E_INVALIDARG);
877 return 0;
879 return CertOpenStore(CERT_STORE_PROV_SYSTEM_W, 0, hProv,
880 CERT_SYSTEM_STORE_CURRENT_USER, szSubSystemProtocol);
883 BOOL WINAPI CertAddCertificateContextToStore(HCERTSTORE hCertStore,
884 PCCERT_CONTEXT pCertContext, DWORD dwAddDisposition,
885 PCCERT_CONTEXT *ppStoreContext)
887 WINECRYPT_CERTSTORE *store = hCertStore;
888 BOOL ret = TRUE;
889 PCCERT_CONTEXT toAdd = NULL, existing = NULL;
891 TRACE("(%p, %p, %08x, %p)\n", hCertStore, pCertContext,
892 dwAddDisposition, ppStoreContext);
894 switch (dwAddDisposition)
896 case CERT_STORE_ADD_ALWAYS:
897 break;
898 case CERT_STORE_ADD_NEW:
899 case CERT_STORE_ADD_REPLACE_EXISTING:
900 case CERT_STORE_ADD_REPLACE_EXISTING_INHERIT_PROPERTIES:
901 case CERT_STORE_ADD_USE_EXISTING:
902 case CERT_STORE_ADD_NEWER:
903 case CERT_STORE_ADD_NEWER_INHERIT_PROPERTIES:
905 BYTE hashToAdd[20];
906 DWORD size = sizeof(hashToAdd);
908 ret = CertGetCertificateContextProperty(pCertContext, CERT_HASH_PROP_ID,
909 hashToAdd, &size);
910 if (ret)
912 CRYPT_HASH_BLOB blob = { sizeof(hashToAdd), hashToAdd };
914 existing = CertFindCertificateInStore(hCertStore,
915 pCertContext->dwCertEncodingType, 0, CERT_FIND_SHA1_HASH, &blob,
916 NULL);
918 break;
920 default:
921 FIXME("Unimplemented add disposition %d\n", dwAddDisposition);
922 SetLastError(E_INVALIDARG);
923 ret = FALSE;
926 switch (dwAddDisposition)
928 case CERT_STORE_ADD_ALWAYS:
929 toAdd = CertDuplicateCertificateContext(pCertContext);
930 break;
931 case CERT_STORE_ADD_NEW:
932 if (existing)
934 TRACE("found matching certificate, not adding\n");
935 SetLastError(CRYPT_E_EXISTS);
936 ret = FALSE;
938 else
939 toAdd = CertDuplicateCertificateContext(pCertContext);
940 break;
941 case CERT_STORE_ADD_REPLACE_EXISTING:
942 toAdd = CertDuplicateCertificateContext(pCertContext);
943 break;
944 case CERT_STORE_ADD_REPLACE_EXISTING_INHERIT_PROPERTIES:
945 toAdd = CertDuplicateCertificateContext(pCertContext);
946 if (existing)
947 Context_CopyProperties(toAdd, existing);
948 break;
949 case CERT_STORE_ADD_USE_EXISTING:
950 if (existing)
952 Context_CopyProperties(existing, pCertContext);
953 if (ppStoreContext)
954 *ppStoreContext = CertDuplicateCertificateContext(existing);
956 else
957 toAdd = CertDuplicateCertificateContext(pCertContext);
958 break;
959 case CERT_STORE_ADD_NEWER:
960 if (existing)
962 if (CompareFileTime(&existing->pCertInfo->NotBefore,
963 &pCertContext->pCertInfo->NotBefore) >= 0)
965 TRACE("existing certificate is newer, not adding\n");
966 SetLastError(CRYPT_E_EXISTS);
967 ret = FALSE;
969 else
970 toAdd = CertDuplicateCertificateContext(pCertContext);
972 else
973 toAdd = CertDuplicateCertificateContext(pCertContext);
974 break;
975 case CERT_STORE_ADD_NEWER_INHERIT_PROPERTIES:
976 if (existing)
978 if (CompareFileTime(&existing->pCertInfo->NotBefore,
979 &pCertContext->pCertInfo->NotBefore) >= 0)
981 TRACE("existing certificate is newer, not adding\n");
982 SetLastError(CRYPT_E_EXISTS);
983 ret = FALSE;
985 else
987 toAdd = CertDuplicateCertificateContext(pCertContext);
988 Context_CopyProperties(toAdd, existing);
991 else
992 toAdd = CertDuplicateCertificateContext(pCertContext);
993 break;
996 if (toAdd)
998 if (store)
999 ret = store->certs.addContext(store, (void *)toAdd,
1000 (void *)existing, (const void **)ppStoreContext);
1001 else if (ppStoreContext)
1002 *ppStoreContext = CertDuplicateCertificateContext(toAdd);
1003 CertFreeCertificateContext(toAdd);
1005 CertFreeCertificateContext(existing);
1007 TRACE("returning %d\n", ret);
1008 return ret;
1011 PCCERT_CONTEXT WINAPI CertEnumCertificatesInStore(HCERTSTORE hCertStore,
1012 PCCERT_CONTEXT pPrev)
1014 WINECRYPT_CERTSTORE *hcs = hCertStore;
1015 PCCERT_CONTEXT ret;
1017 TRACE("(%p, %p)\n", hCertStore, pPrev);
1018 if (!hCertStore)
1019 ret = NULL;
1020 else if (hcs->dwMagic != WINE_CRYPTCERTSTORE_MAGIC)
1021 ret = NULL;
1022 else
1023 ret = (PCCERT_CONTEXT)hcs->certs.enumContext(hcs, (void *)pPrev);
1024 return ret;
1027 BOOL WINAPI CertDeleteCertificateFromStore(PCCERT_CONTEXT pCertContext)
1029 BOOL ret;
1031 TRACE("(%p)\n", pCertContext);
1033 if (!pCertContext)
1034 ret = TRUE;
1035 else if (!pCertContext->hCertStore)
1036 ret = CertFreeCertificateContext(pCertContext);
1037 else
1039 WINECRYPT_CERTSTORE *hcs = pCertContext->hCertStore;
1041 if (hcs->dwMagic != WINE_CRYPTCERTSTORE_MAGIC)
1042 ret = FALSE;
1043 else
1044 ret = hcs->certs.deleteContext(hcs, (void *)pCertContext);
1045 if (ret)
1046 ret = CertFreeCertificateContext(pCertContext);
1048 return ret;
1051 #define CrlContext_CopyProperties(to, from) \
1052 Context_CopyProperties((to), (from), sizeof(CRL_CONTEXT))
1054 BOOL WINAPI CertAddCRLContextToStore(HCERTSTORE hCertStore,
1055 PCCRL_CONTEXT pCrlContext, DWORD dwAddDisposition,
1056 PCCRL_CONTEXT* ppStoreContext)
1058 WINECRYPT_CERTSTORE *store = hCertStore;
1059 BOOL ret = TRUE;
1060 PCCRL_CONTEXT toAdd = NULL, existing = NULL;
1062 TRACE("(%p, %p, %08x, %p)\n", hCertStore, pCrlContext,
1063 dwAddDisposition, ppStoreContext);
1065 /* Weird case to pass a test */
1066 if (dwAddDisposition == 0)
1068 SetLastError(STATUS_ACCESS_VIOLATION);
1069 return FALSE;
1071 if (dwAddDisposition != CERT_STORE_ADD_ALWAYS)
1073 existing = CertFindCRLInStore(hCertStore, 0, 0, CRL_FIND_EXISTING,
1074 pCrlContext, NULL);
1077 switch (dwAddDisposition)
1079 case CERT_STORE_ADD_ALWAYS:
1080 toAdd = CertDuplicateCRLContext(pCrlContext);
1081 break;
1082 case CERT_STORE_ADD_NEW:
1083 if (existing)
1085 TRACE("found matching CRL, not adding\n");
1086 SetLastError(CRYPT_E_EXISTS);
1087 ret = FALSE;
1089 else
1090 toAdd = CertDuplicateCRLContext(pCrlContext);
1091 break;
1092 case CERT_STORE_ADD_NEWER:
1093 if (existing)
1095 LONG newer = CompareFileTime(&existing->pCrlInfo->ThisUpdate,
1096 &pCrlContext->pCrlInfo->ThisUpdate);
1098 if (newer < 0)
1099 toAdd = CertDuplicateCRLContext(pCrlContext);
1100 else
1102 TRACE("existing CRL is newer, not adding\n");
1103 SetLastError(CRYPT_E_EXISTS);
1104 ret = FALSE;
1107 else
1108 toAdd = CertDuplicateCRLContext(pCrlContext);
1109 break;
1110 case CERT_STORE_ADD_NEWER_INHERIT_PROPERTIES:
1111 if (existing)
1113 LONG newer = CompareFileTime(&existing->pCrlInfo->ThisUpdate,
1114 &pCrlContext->pCrlInfo->ThisUpdate);
1116 if (newer < 0)
1118 toAdd = CertDuplicateCRLContext(pCrlContext);
1119 Context_CopyProperties(toAdd, existing);
1121 else
1123 TRACE("existing CRL is newer, not adding\n");
1124 SetLastError(CRYPT_E_EXISTS);
1125 ret = FALSE;
1128 else
1129 toAdd = CertDuplicateCRLContext(pCrlContext);
1130 break;
1131 case CERT_STORE_ADD_REPLACE_EXISTING:
1132 toAdd = CertDuplicateCRLContext(pCrlContext);
1133 break;
1134 case CERT_STORE_ADD_REPLACE_EXISTING_INHERIT_PROPERTIES:
1135 toAdd = CertDuplicateCRLContext(pCrlContext);
1136 if (existing)
1137 Context_CopyProperties(toAdd, existing);
1138 break;
1139 case CERT_STORE_ADD_USE_EXISTING:
1140 if (existing)
1142 Context_CopyProperties(existing, pCrlContext);
1143 if (ppStoreContext)
1144 *ppStoreContext = CertDuplicateCRLContext(existing);
1146 else
1147 toAdd = CertDuplicateCRLContext(pCrlContext);
1148 break;
1149 default:
1150 FIXME("Unimplemented add disposition %d\n", dwAddDisposition);
1151 ret = FALSE;
1154 if (toAdd)
1156 if (store)
1157 ret = store->crls.addContext(store, (void *)toAdd,
1158 (void *)existing, (const void **)ppStoreContext);
1159 else if (ppStoreContext)
1160 *ppStoreContext = CertDuplicateCRLContext(toAdd);
1161 CertFreeCRLContext(toAdd);
1163 CertFreeCRLContext(existing);
1165 TRACE("returning %d\n", ret);
1166 return ret;
1169 BOOL WINAPI CertDeleteCRLFromStore(PCCRL_CONTEXT pCrlContext)
1171 BOOL ret;
1173 TRACE("(%p)\n", pCrlContext);
1175 if (!pCrlContext)
1176 ret = TRUE;
1177 else if (!pCrlContext->hCertStore)
1178 ret = CertFreeCRLContext(pCrlContext);
1179 else
1181 WINECRYPT_CERTSTORE *hcs = pCrlContext->hCertStore;
1183 if (hcs->dwMagic != WINE_CRYPTCERTSTORE_MAGIC)
1184 ret = FALSE;
1185 else
1186 ret = hcs->crls.deleteContext(hcs, (void *)pCrlContext);
1187 if (ret)
1188 ret = CertFreeCRLContext(pCrlContext);
1190 return ret;
1193 PCCRL_CONTEXT WINAPI CertEnumCRLsInStore(HCERTSTORE hCertStore,
1194 PCCRL_CONTEXT pPrev)
1196 WINECRYPT_CERTSTORE *hcs = hCertStore;
1197 PCCRL_CONTEXT ret;
1199 TRACE("(%p, %p)\n", hCertStore, pPrev);
1200 if (!hCertStore)
1201 ret = NULL;
1202 else if (hcs->dwMagic != WINE_CRYPTCERTSTORE_MAGIC)
1203 ret = NULL;
1204 else
1205 ret = (PCCRL_CONTEXT)hcs->crls.enumContext(hcs, (void *)pPrev);
1206 return ret;
1209 HCERTSTORE WINAPI CertDuplicateStore(HCERTSTORE hCertStore)
1211 WINECRYPT_CERTSTORE *hcs = hCertStore;
1213 TRACE("(%p)\n", hCertStore);
1215 if (hcs && hcs->dwMagic == WINE_CRYPTCERTSTORE_MAGIC)
1216 InterlockedIncrement(&hcs->ref);
1217 return hCertStore;
1220 BOOL WINAPI CertCloseStore(HCERTSTORE hCertStore, DWORD dwFlags)
1222 WINECRYPT_CERTSTORE *hcs = hCertStore;
1224 TRACE("(%p, %08x)\n", hCertStore, dwFlags);
1226 if( ! hCertStore )
1227 return TRUE;
1229 if ( hcs->dwMagic != WINE_CRYPTCERTSTORE_MAGIC )
1230 return FALSE;
1232 if (hcs->ref <= 0)
1233 ERR("%p's ref count is %d\n", hcs, hcs->ref);
1234 if (InterlockedDecrement(&hcs->ref) == 0)
1236 TRACE("%p's ref count is 0, freeing\n", hcs);
1237 hcs->dwMagic = 0;
1238 hcs->vtbl->closeStore(hcs, dwFlags);
1240 else
1241 TRACE("%p's ref count is %d\n", hcs, hcs->ref);
1242 return TRUE;
1245 BOOL WINAPI CertControlStore(HCERTSTORE hCertStore, DWORD dwFlags,
1246 DWORD dwCtrlType, void const *pvCtrlPara)
1248 WINECRYPT_CERTSTORE *hcs = hCertStore;
1249 BOOL ret;
1251 TRACE("(%p, %08x, %d, %p)\n", hCertStore, dwFlags, dwCtrlType,
1252 pvCtrlPara);
1254 if (!hcs)
1255 ret = FALSE;
1256 else if (hcs->dwMagic != WINE_CRYPTCERTSTORE_MAGIC)
1257 ret = FALSE;
1258 else
1260 if (hcs->vtbl->control)
1261 ret = hcs->vtbl->control(hcs, dwFlags, dwCtrlType, pvCtrlPara);
1262 else
1263 ret = TRUE;
1265 return ret;
1268 BOOL WINAPI CertGetStoreProperty(HCERTSTORE hCertStore, DWORD dwPropId,
1269 void *pvData, DWORD *pcbData)
1271 WINECRYPT_CERTSTORE *store = hCertStore;
1272 BOOL ret = FALSE;
1274 TRACE("(%p, %d, %p, %p)\n", hCertStore, dwPropId, pvData, pcbData);
1276 switch (dwPropId)
1278 case CERT_ACCESS_STATE_PROP_ID:
1279 if (!pvData)
1281 *pcbData = sizeof(DWORD);
1282 ret = TRUE;
1284 else if (*pcbData < sizeof(DWORD))
1286 SetLastError(ERROR_MORE_DATA);
1287 *pcbData = sizeof(DWORD);
1289 else
1291 DWORD state = 0;
1293 if (store->type != StoreTypeMem &&
1294 !(store->dwOpenFlags & CERT_STORE_READONLY_FLAG))
1295 state |= CERT_ACCESS_STATE_WRITE_PERSIST_FLAG;
1296 *(DWORD *)pvData = state;
1297 ret = TRUE;
1299 break;
1300 default:
1301 if (store->properties)
1303 CRYPT_DATA_BLOB blob;
1305 ret = ContextPropertyList_FindProperty(store->properties, dwPropId,
1306 &blob);
1307 if (ret)
1309 if (!pvData)
1310 *pcbData = blob.cbData;
1311 else if (*pcbData < blob.cbData)
1313 SetLastError(ERROR_MORE_DATA);
1314 *pcbData = blob.cbData;
1315 ret = FALSE;
1317 else
1319 memcpy(pvData, blob.pbData, blob.cbData);
1320 *pcbData = blob.cbData;
1323 else
1324 SetLastError(CRYPT_E_NOT_FOUND);
1326 else
1327 SetLastError(CRYPT_E_NOT_FOUND);
1329 return ret;
1332 BOOL WINAPI CertSetStoreProperty(HCERTSTORE hCertStore, DWORD dwPropId,
1333 DWORD dwFlags, const void *pvData)
1335 WINECRYPT_CERTSTORE *store = hCertStore;
1336 BOOL ret = FALSE;
1338 TRACE("(%p, %d, %08x, %p)\n", hCertStore, dwPropId, dwFlags, pvData);
1340 if (!store->properties)
1341 store->properties = ContextPropertyList_Create();
1342 switch (dwPropId)
1344 case CERT_ACCESS_STATE_PROP_ID:
1345 SetLastError(E_INVALIDARG);
1346 break;
1347 default:
1348 if (pvData)
1350 const CRYPT_DATA_BLOB *blob = pvData;
1352 ret = ContextPropertyList_SetProperty(store->properties, dwPropId,
1353 blob->pbData, blob->cbData);
1355 else
1357 ContextPropertyList_RemoveProperty(store->properties, dwPropId);
1358 ret = TRUE;
1361 return ret;
1364 static LONG CRYPT_OpenParentStore(DWORD dwFlags,
1365 void *pvSystemStoreLocationPara, HKEY *key)
1367 HKEY root;
1368 LPCWSTR base;
1370 TRACE("(%08x, %p)\n", dwFlags, pvSystemStoreLocationPara);
1372 switch (dwFlags & CERT_SYSTEM_STORE_LOCATION_MASK)
1374 case CERT_SYSTEM_STORE_LOCAL_MACHINE:
1375 root = HKEY_LOCAL_MACHINE;
1376 base = CERT_LOCAL_MACHINE_SYSTEM_STORE_REGPATH;
1377 break;
1378 case CERT_SYSTEM_STORE_CURRENT_USER:
1379 root = HKEY_CURRENT_USER;
1380 base = CERT_LOCAL_MACHINE_SYSTEM_STORE_REGPATH;
1381 break;
1382 case CERT_SYSTEM_STORE_CURRENT_SERVICE:
1383 /* hklm\Software\Microsoft\Cryptography\Services\servicename\
1384 * SystemCertificates
1386 FIXME("CERT_SYSTEM_STORE_CURRENT_SERVICE\n");
1387 return ERROR_FILE_NOT_FOUND;
1388 case CERT_SYSTEM_STORE_SERVICES:
1389 /* hklm\Software\Microsoft\Cryptography\Services\servicename\
1390 * SystemCertificates
1392 FIXME("CERT_SYSTEM_STORE_SERVICES\n");
1393 return ERROR_FILE_NOT_FOUND;
1394 case CERT_SYSTEM_STORE_USERS:
1395 /* hku\user sid\Software\Microsoft\SystemCertificates */
1396 FIXME("CERT_SYSTEM_STORE_USERS\n");
1397 return ERROR_FILE_NOT_FOUND;
1398 case CERT_SYSTEM_STORE_CURRENT_USER_GROUP_POLICY:
1399 root = HKEY_CURRENT_USER;
1400 base = CERT_GROUP_POLICY_SYSTEM_STORE_REGPATH;
1401 break;
1402 case CERT_SYSTEM_STORE_LOCAL_MACHINE_GROUP_POLICY:
1403 root = HKEY_LOCAL_MACHINE;
1404 base = CERT_GROUP_POLICY_SYSTEM_STORE_REGPATH;
1405 break;
1406 case CERT_SYSTEM_STORE_LOCAL_MACHINE_ENTERPRISE:
1407 /* hklm\Software\Microsoft\EnterpriseCertificates */
1408 FIXME("CERT_SYSTEM_STORE_LOCAL_MACHINE_ENTERPRISE\n");
1409 return ERROR_FILE_NOT_FOUND;
1410 default:
1411 return ERROR_FILE_NOT_FOUND;
1414 return RegOpenKeyExW(root, base, 0, KEY_READ, key);
1417 BOOL WINAPI CertEnumSystemStore(DWORD dwFlags, void *pvSystemStoreLocationPara,
1418 void *pvArg, PFN_CERT_ENUM_SYSTEM_STORE pfnEnum)
1420 BOOL ret = FALSE;
1421 LONG rc;
1422 HKEY key;
1423 CERT_SYSTEM_STORE_INFO info = { sizeof(info) };
1425 TRACE("(%08x, %p, %p, %p)\n", dwFlags, pvSystemStoreLocationPara, pvArg,
1426 pfnEnum);
1428 rc = CRYPT_OpenParentStore(dwFlags, pvArg, &key);
1429 if (!rc)
1431 DWORD index = 0;
1433 ret = TRUE;
1434 do {
1435 WCHAR name[MAX_PATH];
1436 DWORD size = sizeof(name) / sizeof(name[0]);
1438 rc = RegEnumKeyExW(key, index++, name, &size, NULL, NULL, NULL,
1439 NULL);
1440 if (!rc)
1441 ret = pfnEnum(name, dwFlags, &info, NULL, pvArg);
1442 } while (ret && !rc);
1443 if (ret && rc != ERROR_NO_MORE_ITEMS)
1444 SetLastError(rc);
1446 else
1447 SetLastError(rc);
1448 /* Include root store for the local machine location (it isn't in the
1449 * registry)
1451 if (ret && (dwFlags & CERT_SYSTEM_STORE_LOCATION_MASK) ==
1452 CERT_SYSTEM_STORE_LOCAL_MACHINE)
1453 ret = pfnEnum(rootW, dwFlags, &info, NULL, pvArg);
1454 return ret;
1457 BOOL WINAPI CertEnumPhysicalStore(const void *pvSystemStore, DWORD dwFlags,
1458 void *pvArg, PFN_CERT_ENUM_PHYSICAL_STORE pfnEnum)
1460 if (dwFlags & CERT_SYSTEM_STORE_RELOCATE_FLAG)
1461 FIXME("(%p, %08x, %p, %p): stub\n", pvSystemStore, dwFlags, pvArg,
1462 pfnEnum);
1463 else
1464 FIXME("(%s, %08x, %p, %p): stub\n", debugstr_w(pvSystemStore),
1465 dwFlags, pvArg,
1466 pfnEnum);
1467 return FALSE;
1470 BOOL WINAPI CertRegisterPhysicalStore(const void *pvSystemStore, DWORD dwFlags,
1471 LPCWSTR pwszStoreName, PCERT_PHYSICAL_STORE_INFO pStoreInfo, void *pvReserved)
1473 if (dwFlags & CERT_SYSTEM_STORE_RELOCATE_FLAG)
1474 FIXME("(%p, %08x, %s, %p, %p): stub\n", pvSystemStore, dwFlags,
1475 debugstr_w(pwszStoreName), pStoreInfo, pvReserved);
1476 else
1477 FIXME("(%s, %08x, %s, %p, %p): stub\n", debugstr_w(pvSystemStore),
1478 dwFlags, debugstr_w(pwszStoreName), pStoreInfo, pvReserved);
1479 return FALSE;