crypt32: Move registry stores to a separate file.
[wine.git] / dlls / crypt32 / store.c
blobc2ba2da4073fdd9b9b15197b7f2bf31492476fd6
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 PCWINE_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 PCWINE_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 PCWINE_CONTEXT_INTERFACE pCTLInterface = &gCTLInterface;
89 typedef struct _WINE_MEMSTORE
91 WINECRYPT_CERTSTORE hdr;
92 struct ContextList *certs;
93 struct ContextList *crls;
94 } WINE_MEMSTORE, *PWINE_MEMSTORE;
96 typedef struct _WINE_FILESTOREINFO
98 DWORD dwOpenFlags;
99 HCRYPTPROV cryptProv;
100 HCERTSTORE memStore;
101 HANDLE file;
102 BOOL dirty;
103 } WINE_FILESTOREINFO, *PWINE_FILESTOREINFO;
105 typedef struct _WINE_MSGSTOREINFO
107 DWORD dwOpenFlags;
108 HCRYPTPROV cryptProv;
109 HCERTSTORE memStore;
110 HCRYPTMSG msg;
111 } WINE_MSGSTOREINFO, *PWINE_MSGSTOREINFO;
113 void CRYPT_InitStore(WINECRYPT_CERTSTORE *store, HCRYPTPROV hCryptProv,
114 DWORD dwFlags, CertStoreType type)
116 store->ref = 1;
117 store->dwMagic = WINE_CRYPTCERTSTORE_MAGIC;
118 store->type = type;
119 if (!hCryptProv)
121 hCryptProv = CRYPT_GetDefaultProvider();
122 dwFlags |= CERT_STORE_NO_CRYPT_RELEASE_FLAG;
124 store->cryptProv = hCryptProv;
125 store->dwOpenFlags = dwFlags;
126 store->properties = NULL;
129 void CRYPT_FreeStore(PWINECRYPT_CERTSTORE store)
131 if (store->properties)
132 ContextPropertyList_Free(store->properties);
133 CryptMemFree(store);
136 static BOOL CRYPT_MemAddCert(PWINECRYPT_CERTSTORE store, void *cert,
137 void *toReplace, const void **ppStoreContext)
139 WINE_MEMSTORE *ms = (WINE_MEMSTORE *)store;
140 PCERT_CONTEXT context;
142 TRACE("(%p, %p, %p, %p)\n", store, cert, toReplace, ppStoreContext);
144 context = (PCERT_CONTEXT)ContextList_Add(ms->certs, cert, toReplace);
145 if (context)
147 context->hCertStore = store;
148 if (ppStoreContext)
149 *ppStoreContext = CertDuplicateCertificateContext(context);
151 return context ? TRUE : FALSE;
154 static void *CRYPT_MemEnumCert(PWINECRYPT_CERTSTORE store, void *pPrev)
156 WINE_MEMSTORE *ms = (WINE_MEMSTORE *)store;
157 void *ret;
159 TRACE("(%p, %p)\n", store, pPrev);
161 ret = ContextList_Enum(ms->certs, pPrev);
162 if (!ret)
163 SetLastError(CRYPT_E_NOT_FOUND);
165 TRACE("returning %p\n", ret);
166 return ret;
169 static BOOL CRYPT_MemDeleteCert(PWINECRYPT_CERTSTORE store, void *pCertContext)
171 WINE_MEMSTORE *ms = (WINE_MEMSTORE *)store;
173 ContextList_Delete(ms->certs, pCertContext);
174 return TRUE;
177 static BOOL CRYPT_MemAddCrl(PWINECRYPT_CERTSTORE store, void *crl,
178 void *toReplace, const void **ppStoreContext)
180 WINE_MEMSTORE *ms = (WINE_MEMSTORE *)store;
181 PCRL_CONTEXT context;
183 TRACE("(%p, %p, %p, %p)\n", store, crl, toReplace, ppStoreContext);
185 context = (PCRL_CONTEXT)ContextList_Add(ms->crls, crl, toReplace);
186 if (context)
188 context->hCertStore = store;
189 if (ppStoreContext)
190 *ppStoreContext = CertDuplicateCRLContext(context);
192 return context ? TRUE : FALSE;
195 static void *CRYPT_MemEnumCrl(PWINECRYPT_CERTSTORE store, void *pPrev)
197 WINE_MEMSTORE *ms = (WINE_MEMSTORE *)store;
198 void *ret;
200 TRACE("(%p, %p)\n", store, pPrev);
202 ret = ContextList_Enum(ms->crls, pPrev);
203 if (!ret)
204 SetLastError(CRYPT_E_NOT_FOUND);
206 TRACE("returning %p\n", ret);
207 return ret;
210 static BOOL CRYPT_MemDeleteCrl(PWINECRYPT_CERTSTORE store, void *pCrlContext)
212 WINE_MEMSTORE *ms = (WINE_MEMSTORE *)store;
214 ContextList_Delete(ms->crls, pCrlContext);
215 return TRUE;
218 void CRYPT_EmptyStore(HCERTSTORE store)
220 PCCERT_CONTEXT cert;
221 PCCRL_CONTEXT crl;
223 do {
224 cert = CertEnumCertificatesInStore(store, NULL);
225 if (cert)
226 CertDeleteCertificateFromStore(cert);
227 } while (cert);
228 do {
229 crl = CertEnumCRLsInStore(store, NULL);
230 if (crl)
231 CertDeleteCRLFromStore(crl);
232 } while (crl);
235 static void WINAPI CRYPT_MemCloseStore(HCERTSTORE hCertStore, DWORD dwFlags)
237 WINE_MEMSTORE *store = (WINE_MEMSTORE *)hCertStore;
239 TRACE("(%p, %08x)\n", store, dwFlags);
240 if (dwFlags)
241 FIXME("Unimplemented flags: %08x\n", dwFlags);
243 ContextList_Free(store->certs);
244 ContextList_Free(store->crls);
245 CRYPT_FreeStore((PWINECRYPT_CERTSTORE)store);
248 static WINECRYPT_CERTSTORE *CRYPT_MemOpenStore(HCRYPTPROV hCryptProv,
249 DWORD dwFlags, const void *pvPara)
251 PWINE_MEMSTORE store;
253 TRACE("(%ld, %08x, %p)\n", hCryptProv, dwFlags, pvPara);
255 if (dwFlags & CERT_STORE_DELETE_FLAG)
257 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
258 store = NULL;
260 else
262 store = CryptMemAlloc(sizeof(WINE_MEMSTORE));
263 if (store)
265 memset(store, 0, sizeof(WINE_MEMSTORE));
266 CRYPT_InitStore(&store->hdr, hCryptProv, dwFlags, StoreTypeMem);
267 store->hdr.closeStore = CRYPT_MemCloseStore;
268 store->hdr.certs.addContext = CRYPT_MemAddCert;
269 store->hdr.certs.enumContext = CRYPT_MemEnumCert;
270 store->hdr.certs.deleteContext = CRYPT_MemDeleteCert;
271 store->hdr.crls.addContext = CRYPT_MemAddCrl;
272 store->hdr.crls.enumContext = CRYPT_MemEnumCrl;
273 store->hdr.crls.deleteContext = CRYPT_MemDeleteCrl;
274 store->hdr.control = NULL;
275 store->certs = ContextList_Create(pCertInterface,
276 sizeof(CERT_CONTEXT));
277 store->crls = ContextList_Create(pCRLInterface,
278 sizeof(CRL_CONTEXT));
281 return (PWINECRYPT_CERTSTORE)store;
284 /* FIXME: this isn't complete for the Root store, in which the top-level
285 * self-signed CA certs reside. Adding a cert to the Root store should present
286 * the user with a dialog indicating the consequences of doing so, and asking
287 * the user to confirm whether the cert should be added.
289 static PWINECRYPT_CERTSTORE CRYPT_SysRegOpenStoreW(HCRYPTPROV hCryptProv,
290 DWORD dwFlags, const void *pvPara)
292 static const WCHAR fmt[] = { '%','s','\\','%','s',0 };
293 LPCWSTR storeName = (LPCWSTR)pvPara;
294 LPWSTR storePath;
295 PWINECRYPT_CERTSTORE store = NULL;
296 HKEY root;
297 LPCWSTR base;
298 BOOL ret;
300 TRACE("(%ld, %08x, %s)\n", hCryptProv, dwFlags,
301 debugstr_w((LPCWSTR)pvPara));
303 if (!pvPara)
305 SetLastError(E_INVALIDARG);
306 return NULL;
309 ret = TRUE;
310 switch (dwFlags & CERT_SYSTEM_STORE_LOCATION_MASK)
312 case CERT_SYSTEM_STORE_LOCAL_MACHINE:
313 root = HKEY_LOCAL_MACHINE;
314 base = CERT_LOCAL_MACHINE_SYSTEM_STORE_REGPATH;
315 break;
316 case CERT_SYSTEM_STORE_CURRENT_USER:
317 root = HKEY_CURRENT_USER;
318 base = CERT_LOCAL_MACHINE_SYSTEM_STORE_REGPATH;
319 break;
320 case CERT_SYSTEM_STORE_CURRENT_SERVICE:
321 /* hklm\Software\Microsoft\Cryptography\Services\servicename\
322 * SystemCertificates
324 FIXME("CERT_SYSTEM_STORE_CURRENT_SERVICE, %s: stub\n",
325 debugstr_w(storeName));
326 return NULL;
327 case CERT_SYSTEM_STORE_SERVICES:
328 /* hklm\Software\Microsoft\Cryptography\Services\servicename\
329 * SystemCertificates
331 FIXME("CERT_SYSTEM_STORE_SERVICES, %s: stub\n",
332 debugstr_w(storeName));
333 return NULL;
334 case CERT_SYSTEM_STORE_USERS:
335 /* hku\user sid\Software\Microsoft\SystemCertificates */
336 FIXME("CERT_SYSTEM_STORE_USERS, %s: stub\n",
337 debugstr_w(storeName));
338 return NULL;
339 case CERT_SYSTEM_STORE_CURRENT_USER_GROUP_POLICY:
340 root = HKEY_CURRENT_USER;
341 base = CERT_GROUP_POLICY_SYSTEM_STORE_REGPATH;
342 break;
343 case CERT_SYSTEM_STORE_LOCAL_MACHINE_GROUP_POLICY:
344 root = HKEY_LOCAL_MACHINE;
345 base = CERT_GROUP_POLICY_SYSTEM_STORE_REGPATH;
346 break;
347 case CERT_SYSTEM_STORE_LOCAL_MACHINE_ENTERPRISE:
348 /* hklm\Software\Microsoft\EnterpriseCertificates */
349 FIXME("CERT_SYSTEM_STORE_LOCAL_MACHINE_ENTERPRISE, %s: stub\n",
350 debugstr_w(storeName));
351 return NULL;
352 default:
353 SetLastError(E_INVALIDARG);
354 return NULL;
357 storePath = CryptMemAlloc((lstrlenW(base) + lstrlenW(storeName) + 2) *
358 sizeof(WCHAR));
359 if (storePath)
361 LONG rc;
362 HKEY key;
363 REGSAM sam = dwFlags & CERT_STORE_READONLY_FLAG ? KEY_READ :
364 KEY_ALL_ACCESS;
366 wsprintfW(storePath, fmt, base, storeName);
367 if (dwFlags & CERT_STORE_OPEN_EXISTING_FLAG)
368 rc = RegOpenKeyExW(root, storePath, 0, sam, &key);
369 else
371 DWORD disp;
373 rc = RegCreateKeyExW(root, storePath, 0, NULL, 0, sam, NULL,
374 &key, &disp);
375 if (!rc && dwFlags & CERT_STORE_CREATE_NEW_FLAG &&
376 disp == REG_OPENED_EXISTING_KEY)
378 RegCloseKey(key);
379 rc = ERROR_FILE_EXISTS;
382 if (!rc)
384 store = CRYPT_RegOpenStore(hCryptProv, dwFlags, key);
385 RegCloseKey(key);
387 else
388 SetLastError(rc);
389 CryptMemFree(storePath);
391 return store;
394 static PWINECRYPT_CERTSTORE CRYPT_SysRegOpenStoreA(HCRYPTPROV hCryptProv,
395 DWORD dwFlags, const void *pvPara)
397 int len;
398 PWINECRYPT_CERTSTORE ret = NULL;
400 TRACE("(%ld, %08x, %s)\n", hCryptProv, dwFlags,
401 debugstr_a((LPCSTR)pvPara));
403 if (!pvPara)
405 SetLastError(ERROR_FILE_NOT_FOUND);
406 return NULL;
408 len = MultiByteToWideChar(CP_ACP, 0, (LPCSTR)pvPara, -1, NULL, 0);
409 if (len)
411 LPWSTR storeName = CryptMemAlloc(len * sizeof(WCHAR));
413 if (storeName)
415 MultiByteToWideChar(CP_ACP, 0, (LPCSTR)pvPara, -1, storeName, len);
416 ret = CRYPT_SysRegOpenStoreW(hCryptProv, dwFlags, storeName);
417 CryptMemFree(storeName);
420 return ret;
423 static PWINECRYPT_CERTSTORE CRYPT_SysOpenStoreW(HCRYPTPROV hCryptProv,
424 DWORD dwFlags, const void *pvPara)
426 HCERTSTORE store = 0;
427 BOOL ret;
429 TRACE("(%ld, %08x, %s)\n", hCryptProv, dwFlags,
430 debugstr_w((LPCWSTR)pvPara));
432 if (!pvPara)
434 SetLastError(ERROR_FILE_NOT_FOUND);
435 return NULL;
437 /* This returns a different error than system registry stores if the
438 * location is invalid.
440 switch (dwFlags & CERT_SYSTEM_STORE_LOCATION_MASK)
442 case CERT_SYSTEM_STORE_LOCAL_MACHINE:
443 case CERT_SYSTEM_STORE_CURRENT_USER:
444 case CERT_SYSTEM_STORE_CURRENT_SERVICE:
445 case CERT_SYSTEM_STORE_SERVICES:
446 case CERT_SYSTEM_STORE_USERS:
447 case CERT_SYSTEM_STORE_CURRENT_USER_GROUP_POLICY:
448 case CERT_SYSTEM_STORE_LOCAL_MACHINE_GROUP_POLICY:
449 case CERT_SYSTEM_STORE_LOCAL_MACHINE_ENTERPRISE:
450 ret = TRUE;
451 break;
452 default:
453 SetLastError(ERROR_FILE_NOT_FOUND);
454 ret = FALSE;
456 if (ret)
458 HCERTSTORE regStore = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY_W,
459 0, hCryptProv, dwFlags, pvPara);
461 if (regStore)
463 store = CertOpenStore(CERT_STORE_PROV_COLLECTION, 0, 0,
464 CERT_STORE_CREATE_NEW_FLAG, NULL);
465 CertAddStoreToCollection(store, regStore,
466 dwFlags & CERT_STORE_READONLY_FLAG ? 0 :
467 CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
468 CertCloseStore(regStore, 0);
469 /* CERT_SYSTEM_STORE_CURRENT_USER returns both the HKCU and HKLM
470 * stores.
472 if ((dwFlags & CERT_SYSTEM_STORE_LOCATION_MASK) ==
473 CERT_SYSTEM_STORE_CURRENT_USER)
475 dwFlags &= ~CERT_SYSTEM_STORE_CURRENT_USER;
476 dwFlags |= CERT_SYSTEM_STORE_LOCAL_MACHINE;
477 regStore = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY_W, 0,
478 hCryptProv, dwFlags, pvPara);
479 if (regStore)
481 CertAddStoreToCollection(store, regStore,
482 dwFlags & CERT_STORE_READONLY_FLAG ? 0 :
483 CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
484 CertCloseStore(regStore, 0);
489 return (PWINECRYPT_CERTSTORE)store;
492 static PWINECRYPT_CERTSTORE CRYPT_SysOpenStoreA(HCRYPTPROV hCryptProv,
493 DWORD dwFlags, const void *pvPara)
495 int len;
496 PWINECRYPT_CERTSTORE ret = NULL;
498 TRACE("(%ld, %08x, %s)\n", hCryptProv, dwFlags,
499 debugstr_a((LPCSTR)pvPara));
501 if (!pvPara)
503 SetLastError(ERROR_FILE_NOT_FOUND);
504 return NULL;
506 len = MultiByteToWideChar(CP_ACP, 0, (LPCSTR)pvPara, -1, NULL, 0);
507 if (len)
509 LPWSTR storeName = CryptMemAlloc(len * sizeof(WCHAR));
511 if (storeName)
513 MultiByteToWideChar(CP_ACP, 0, (LPCSTR)pvPara, -1, storeName, len);
514 ret = CRYPT_SysOpenStoreW(hCryptProv, dwFlags, storeName);
515 CryptMemFree(storeName);
518 return ret;
521 static void WINAPI CRYPT_FileCloseStore(HCERTSTORE hCertStore, DWORD dwFlags)
523 PWINE_FILESTOREINFO store = (PWINE_FILESTOREINFO)hCertStore;
525 TRACE("(%p, %08x)\n", store, dwFlags);
526 if (store->dirty)
527 CRYPT_WriteSerializedFile(store->file, store->memStore);
528 CertCloseStore(store->memStore, dwFlags);
529 CloseHandle(store->file);
530 CryptMemFree(store);
533 static BOOL WINAPI CRYPT_FileWriteCert(HCERTSTORE hCertStore,
534 PCCERT_CONTEXT cert, DWORD dwFlags)
536 PWINE_FILESTOREINFO store = (PWINE_FILESTOREINFO)hCertStore;
538 TRACE("(%p, %p, %d)\n", hCertStore, cert, dwFlags);
539 store->dirty = TRUE;
540 return TRUE;
543 static BOOL WINAPI CRYPT_FileDeleteCert(HCERTSTORE hCertStore,
544 PCCERT_CONTEXT pCertContext, DWORD dwFlags)
546 PWINE_FILESTOREINFO store = (PWINE_FILESTOREINFO)hCertStore;
548 TRACE("(%p, %p, %08x)\n", hCertStore, pCertContext, dwFlags);
549 store->dirty = TRUE;
550 return TRUE;
553 static BOOL WINAPI CRYPT_FileWriteCRL(HCERTSTORE hCertStore,
554 PCCRL_CONTEXT crl, DWORD dwFlags)
556 PWINE_FILESTOREINFO store = (PWINE_FILESTOREINFO)hCertStore;
558 TRACE("(%p, %p, %d)\n", hCertStore, crl, dwFlags);
559 store->dirty = TRUE;
560 return TRUE;
563 static BOOL WINAPI CRYPT_FileDeleteCRL(HCERTSTORE hCertStore,
564 PCCRL_CONTEXT pCrlContext, DWORD dwFlags)
566 PWINE_FILESTOREINFO store = (PWINE_FILESTOREINFO)hCertStore;
568 TRACE("(%p, %p, %08x)\n", hCertStore, pCrlContext, dwFlags);
569 store->dirty = TRUE;
570 return TRUE;
573 static BOOL WINAPI CRYPT_FileControl(HCERTSTORE hCertStore, DWORD dwFlags,
574 DWORD dwCtrlType, void const *pvCtrlPara)
576 PWINE_FILESTOREINFO store = (PWINE_FILESTOREINFO)hCertStore;
577 BOOL ret;
579 TRACE("(%p, %08x, %d, %p)\n", hCertStore, dwFlags, dwCtrlType,
580 pvCtrlPara);
582 switch (dwCtrlType)
584 case CERT_STORE_CTRL_RESYNC:
585 CRYPT_EmptyStore(store->memStore);
586 CRYPT_ReadSerializedFile(store->file, store);
587 ret = TRUE;
588 break;
589 case CERT_STORE_CTRL_COMMIT:
590 if (!(store->dwOpenFlags & CERT_FILE_STORE_COMMIT_ENABLE_FLAG))
592 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
593 ret = FALSE;
595 else if (store->dirty)
596 ret = CRYPT_WriteSerializedFile(store->file, store->memStore);
597 else
598 ret = TRUE;
599 break;
600 default:
601 FIXME("%d: stub\n", dwCtrlType);
602 ret = FALSE;
604 return ret;
607 static void *fileProvFuncs[] = {
608 CRYPT_FileCloseStore,
609 NULL, /* CERT_STORE_PROV_READ_CERT_FUNC */
610 CRYPT_FileWriteCert,
611 CRYPT_FileDeleteCert,
612 NULL, /* CERT_STORE_PROV_SET_CERT_PROPERTY_FUNC */
613 NULL, /* CERT_STORE_PROV_READ_CRL_FUNC */
614 CRYPT_FileWriteCRL,
615 CRYPT_FileDeleteCRL,
616 NULL, /* CERT_STORE_PROV_SET_CRL_PROPERTY_FUNC */
617 NULL, /* CERT_STORE_PROV_READ_CTL_FUNC */
618 NULL, /* CERT_STORE_PROV_WRITE_CTL_FUNC */
619 NULL, /* CERT_STORE_PROV_DELETE_CTL_FUNC */
620 NULL, /* CERT_STORE_PROV_SET_CTL_PROPERTY_FUNC */
621 CRYPT_FileControl,
624 static PWINECRYPT_CERTSTORE CRYPT_FileOpenStore(HCRYPTPROV hCryptProv,
625 DWORD dwFlags, const void *pvPara)
627 PWINECRYPT_CERTSTORE store = NULL;
628 HANDLE file = (HANDLE)pvPara;
630 TRACE("(%ld, %08x, %p)\n", hCryptProv, dwFlags, pvPara);
632 if (!pvPara)
634 SetLastError(ERROR_INVALID_HANDLE);
635 return NULL;
637 if (dwFlags & CERT_STORE_DELETE_FLAG)
639 SetLastError(E_INVALIDARG);
640 return NULL;
642 if ((dwFlags & CERT_STORE_READONLY_FLAG) &&
643 (dwFlags & CERT_FILE_STORE_COMMIT_ENABLE_FLAG))
645 SetLastError(E_INVALIDARG);
646 return NULL;
649 if (DuplicateHandle(GetCurrentProcess(), (HANDLE)pvPara,
650 GetCurrentProcess(), &file, dwFlags & CERT_STORE_READONLY_FLAG ?
651 GENERIC_READ : GENERIC_READ | GENERIC_WRITE, TRUE, 0))
653 PWINECRYPT_CERTSTORE memStore;
655 memStore = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, hCryptProv,
656 CERT_STORE_CREATE_NEW_FLAG, NULL);
657 if (memStore)
659 if (CRYPT_ReadSerializedFile(file, memStore))
661 PWINE_FILESTOREINFO info = CryptMemAlloc(
662 sizeof(WINE_FILESTOREINFO));
664 if (info)
666 CERT_STORE_PROV_INFO provInfo = { 0 };
668 info->dwOpenFlags = dwFlags;
669 info->cryptProv = hCryptProv;
670 info->memStore = memStore;
671 info->file = file;
672 info->dirty = FALSE;
673 provInfo.cbSize = sizeof(provInfo);
674 provInfo.cStoreProvFunc = sizeof(fileProvFuncs) /
675 sizeof(fileProvFuncs[0]);
676 provInfo.rgpvStoreProvFunc = fileProvFuncs;
677 provInfo.hStoreProv = info;
678 store = CRYPT_ProvCreateStore(hCryptProv, dwFlags, memStore,
679 &provInfo);
684 TRACE("returning %p\n", store);
685 return store;
688 static PWINECRYPT_CERTSTORE CRYPT_FileNameOpenStoreW(HCRYPTPROV hCryptProv,
689 DWORD dwFlags, const void *pvPara)
691 HCERTSTORE store = 0;
692 LPCWSTR fileName = (LPCWSTR)pvPara;
693 DWORD access, create;
694 HANDLE file;
696 TRACE("(%ld, %08x, %s)\n", hCryptProv, dwFlags, debugstr_w(fileName));
698 if (!fileName)
700 SetLastError(ERROR_PATH_NOT_FOUND);
701 return NULL;
704 access = GENERIC_READ;
705 if (dwFlags & CERT_FILE_STORE_COMMIT_ENABLE_FLAG)
706 access |= GENERIC_WRITE;
707 if (dwFlags & CERT_STORE_CREATE_NEW_FLAG)
708 create = CREATE_NEW;
709 else if (dwFlags & CERT_STORE_OPEN_EXISTING_FLAG)
710 create = OPEN_EXISTING;
711 else
712 create = OPEN_ALWAYS;
713 file = CreateFileW(fileName, access, FILE_SHARE_READ, NULL, create,
714 FILE_ATTRIBUTE_NORMAL, NULL);
715 if (file != INVALID_HANDLE_VALUE)
717 /* FIXME: need to check whether it's a serialized store; if not, fall
718 * back to a PKCS#7 signed message, then to a single serialized cert.
720 store = CertOpenStore(CERT_STORE_PROV_FILE, 0, hCryptProv, dwFlags,
721 file);
722 CloseHandle(file);
724 return (PWINECRYPT_CERTSTORE)store;
727 static PWINECRYPT_CERTSTORE CRYPT_FileNameOpenStoreA(HCRYPTPROV hCryptProv,
728 DWORD dwFlags, const void *pvPara)
730 int len;
731 PWINECRYPT_CERTSTORE ret = NULL;
733 TRACE("(%ld, %08x, %s)\n", hCryptProv, dwFlags,
734 debugstr_a((LPCSTR)pvPara));
736 if (!pvPara)
738 SetLastError(ERROR_FILE_NOT_FOUND);
739 return NULL;
741 len = MultiByteToWideChar(CP_ACP, 0, (LPCSTR)pvPara, -1, NULL, 0);
742 if (len)
744 LPWSTR storeName = CryptMemAlloc(len * sizeof(WCHAR));
746 if (storeName)
748 MultiByteToWideChar(CP_ACP, 0, (LPCSTR)pvPara, -1, storeName, len);
749 ret = CRYPT_FileNameOpenStoreW(hCryptProv, dwFlags, storeName);
750 CryptMemFree(storeName);
753 return ret;
756 static void WINAPI CRYPT_MsgCloseStore(HCERTSTORE hCertStore, DWORD dwFlags)
758 PWINE_MSGSTOREINFO store = (PWINE_MSGSTOREINFO)hCertStore;
760 TRACE("(%p, %08x)\n", store, dwFlags);
761 CertCloseStore(store->memStore, dwFlags);
762 CryptMsgClose(store->msg);
763 CryptMemFree(store);
766 static void *msgProvFuncs[] = {
767 CRYPT_MsgCloseStore,
768 NULL, /* CERT_STORE_PROV_READ_CERT_FUNC */
769 NULL, /* CERT_STORE_PROV_WRITE_CERT_FUNC */
770 NULL, /* CERT_STORE_PROV_DELETE_CERT_FUNC */
771 NULL, /* CERT_STORE_PROV_SET_CERT_PROPERTY_FUNC */
772 NULL, /* CERT_STORE_PROV_READ_CRL_FUNC */
773 NULL, /* CERT_STORE_PROV_WRITE_CRL_FUNC */
774 NULL, /* CERT_STORE_PROV_DELETE_CRL_FUNC */
775 NULL, /* CERT_STORE_PROV_SET_CRL_PROPERTY_FUNC */
776 NULL, /* CERT_STORE_PROV_READ_CTL_FUNC */
777 NULL, /* CERT_STORE_PROV_WRITE_CTL_FUNC */
778 NULL, /* CERT_STORE_PROV_DELETE_CTL_FUNC */
779 NULL, /* CERT_STORE_PROV_SET_CTL_PROPERTY_FUNC */
780 NULL, /* CERT_STORE_PROV_CONTROL_FUNC */
783 static PWINECRYPT_CERTSTORE CRYPT_MsgOpenStore(HCRYPTPROV hCryptProv,
784 DWORD dwFlags, const void *pvPara)
786 PWINECRYPT_CERTSTORE store = NULL;
787 HCRYPTMSG msg = (HCRYPTMSG)pvPara;
788 PWINECRYPT_CERTSTORE memStore;
790 TRACE("(%ld, %08x, %p)\n", hCryptProv, dwFlags, pvPara);
792 memStore = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, hCryptProv,
793 CERT_STORE_CREATE_NEW_FLAG, NULL);
794 if (memStore)
796 BOOL ret;
797 DWORD size, count, i;
799 size = sizeof(count);
800 ret = CryptMsgGetParam(msg, CMSG_CERT_COUNT_PARAM, 0, &count, &size);
801 for (i = 0; ret && i < count; i++)
803 size = 0;
804 ret = CryptMsgGetParam(msg, CMSG_CERT_PARAM, i, NULL, &size);
805 if (ret)
807 LPBYTE buf = CryptMemAlloc(size);
809 if (buf)
811 ret = CryptMsgGetParam(msg, CMSG_CERT_PARAM, i, buf, &size);
812 if (ret)
813 ret = CertAddEncodedCertificateToStore(memStore,
814 X509_ASN_ENCODING, buf, size, CERT_STORE_ADD_ALWAYS,
815 NULL);
816 CryptMemFree(buf);
820 size = sizeof(count);
821 ret = CryptMsgGetParam(msg, CMSG_CRL_COUNT_PARAM, 0, &count, &size);
822 for (i = 0; ret && i < count; i++)
824 size = 0;
825 ret = CryptMsgGetParam(msg, CMSG_CRL_PARAM, i, NULL, &size);
826 if (ret)
828 LPBYTE buf = CryptMemAlloc(size);
830 if (buf)
832 ret = CryptMsgGetParam(msg, CMSG_CRL_PARAM, i, buf, &size);
833 if (ret)
834 ret = CertAddEncodedCRLToStore(memStore,
835 X509_ASN_ENCODING, buf, size, CERT_STORE_ADD_ALWAYS,
836 NULL);
837 CryptMemFree(buf);
841 if (ret)
843 PWINE_MSGSTOREINFO info = CryptMemAlloc(sizeof(WINE_MSGSTOREINFO));
845 if (info)
847 CERT_STORE_PROV_INFO provInfo = { 0 };
849 info->dwOpenFlags = dwFlags;
850 info->cryptProv = hCryptProv;
851 info->memStore = memStore;
852 info->msg = CryptMsgDuplicate(msg);
853 provInfo.cbSize = sizeof(provInfo);
854 provInfo.cStoreProvFunc = sizeof(msgProvFuncs) /
855 sizeof(msgProvFuncs[0]);
856 provInfo.rgpvStoreProvFunc = msgProvFuncs;
857 provInfo.hStoreProv = info;
858 store = CRYPT_ProvCreateStore(hCryptProv, dwFlags, memStore,
859 &provInfo);
861 else
862 CertCloseStore(memStore, 0);
864 else
865 CertCloseStore(memStore, 0);
867 TRACE("returning %p\n", store);
868 return store;
871 static PWINECRYPT_CERTSTORE CRYPT_PKCSOpenStore(HCRYPTPROV hCryptProv,
872 DWORD dwFlags, const void *pvPara)
874 HCRYPTMSG msg;
875 PWINECRYPT_CERTSTORE store = NULL;
876 const CRYPT_DATA_BLOB *data = (const CRYPT_DATA_BLOB *)pvPara;
877 BOOL ret;
879 TRACE("(%ld, %08x, %p)\n", hCryptProv, dwFlags, pvPara);
881 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, CMSG_SIGNED, 0, NULL,
882 NULL);
883 ret = CryptMsgUpdate(msg, data->pbData, data->cbData, TRUE);
884 if (!ret)
886 CryptMsgClose(msg);
887 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, NULL);
888 ret = CryptMsgUpdate(msg, data->pbData, data->cbData, TRUE);
889 if (ret)
891 DWORD type, size = sizeof(type);
893 /* Only signed messages are allowed, check type */
894 ret = CryptMsgGetParam(msg, CMSG_TYPE_PARAM, 0, &type, &size);
895 if (ret && type != CMSG_SIGNED)
897 SetLastError(CRYPT_E_INVALID_MSG_TYPE);
898 ret = FALSE;
902 if (ret)
903 store = CRYPT_MsgOpenStore(hCryptProv, dwFlags, msg);
904 CryptMsgClose(msg);
905 TRACE("returning %p\n", store);
906 return store;
909 static PWINECRYPT_CERTSTORE CRYPT_PhysOpenStoreW(HCRYPTPROV hCryptProv,
910 DWORD dwFlags, const void *pvPara)
912 if (dwFlags & CERT_SYSTEM_STORE_RELOCATE_FLAG)
913 FIXME("(%ld, %08x, %p): stub\n", hCryptProv, dwFlags, pvPara);
914 else
915 FIXME("(%ld, %08x, %s): stub\n", hCryptProv, dwFlags,
916 debugstr_w((LPCWSTR)pvPara));
917 return NULL;
920 HCERTSTORE WINAPI CertOpenStore(LPCSTR lpszStoreProvider,
921 DWORD dwMsgAndCertEncodingType, HCRYPTPROV_LEGACY hCryptProv, DWORD dwFlags,
922 const void* pvPara)
924 WINECRYPT_CERTSTORE *hcs;
925 StoreOpenFunc openFunc = NULL;
927 TRACE("(%s, %08x, %08lx, %08x, %p)\n", debugstr_a(lpszStoreProvider),
928 dwMsgAndCertEncodingType, hCryptProv, dwFlags, pvPara);
930 if (!HIWORD(lpszStoreProvider))
932 switch (LOWORD(lpszStoreProvider))
934 case (int)CERT_STORE_PROV_MSG:
935 openFunc = CRYPT_MsgOpenStore;
936 break;
937 case (int)CERT_STORE_PROV_MEMORY:
938 openFunc = CRYPT_MemOpenStore;
939 break;
940 case (int)CERT_STORE_PROV_FILE:
941 openFunc = CRYPT_FileOpenStore;
942 break;
943 case (int)CERT_STORE_PROV_PKCS7:
944 openFunc = CRYPT_PKCSOpenStore;
945 break;
946 case (int)CERT_STORE_PROV_REG:
947 openFunc = CRYPT_RegOpenStore;
948 break;
949 case (int)CERT_STORE_PROV_FILENAME_A:
950 openFunc = CRYPT_FileNameOpenStoreA;
951 break;
952 case (int)CERT_STORE_PROV_FILENAME_W:
953 openFunc = CRYPT_FileNameOpenStoreW;
954 break;
955 case (int)CERT_STORE_PROV_COLLECTION:
956 openFunc = CRYPT_CollectionOpenStore;
957 break;
958 case (int)CERT_STORE_PROV_SYSTEM_A:
959 openFunc = CRYPT_SysOpenStoreA;
960 break;
961 case (int)CERT_STORE_PROV_SYSTEM_W:
962 openFunc = CRYPT_SysOpenStoreW;
963 break;
964 case (int)CERT_STORE_PROV_SYSTEM_REGISTRY_A:
965 openFunc = CRYPT_SysRegOpenStoreA;
966 break;
967 case (int)CERT_STORE_PROV_SYSTEM_REGISTRY_W:
968 openFunc = CRYPT_SysRegOpenStoreW;
969 break;
970 case (int)CERT_STORE_PROV_PHYSICAL_W:
971 openFunc = CRYPT_PhysOpenStoreW;
972 break;
973 default:
974 if (LOWORD(lpszStoreProvider))
975 FIXME("unimplemented type %d\n", LOWORD(lpszStoreProvider));
978 else if (!strcasecmp(lpszStoreProvider, sz_CERT_STORE_PROV_MEMORY))
979 openFunc = CRYPT_MemOpenStore;
980 else if (!strcasecmp(lpszStoreProvider, sz_CERT_STORE_PROV_FILENAME_W))
981 openFunc = CRYPT_FileOpenStore;
982 else if (!strcasecmp(lpszStoreProvider, sz_CERT_STORE_PROV_SYSTEM))
983 openFunc = CRYPT_SysOpenStoreW;
984 else if (!strcasecmp(lpszStoreProvider, sz_CERT_STORE_PROV_COLLECTION))
985 openFunc = CRYPT_CollectionOpenStore;
986 else if (!strcasecmp(lpszStoreProvider, sz_CERT_STORE_PROV_SYSTEM_REGISTRY))
987 openFunc = CRYPT_SysRegOpenStoreW;
988 else
990 FIXME("unimplemented type %s\n", lpszStoreProvider);
991 openFunc = NULL;
994 if (!openFunc)
995 hcs = CRYPT_ProvOpenStore(lpszStoreProvider, dwMsgAndCertEncodingType,
996 hCryptProv, dwFlags, pvPara);
997 else
998 hcs = openFunc(hCryptProv, dwFlags, pvPara);
999 return (HCERTSTORE)hcs;
1002 HCERTSTORE WINAPI CertOpenSystemStoreA(HCRYPTPROV_LEGACY hProv,
1003 LPCSTR szSubSystemProtocol)
1005 if (!szSubSystemProtocol)
1007 SetLastError(E_INVALIDARG);
1008 return 0;
1010 return CertOpenStore(CERT_STORE_PROV_SYSTEM_A, 0, hProv,
1011 CERT_SYSTEM_STORE_CURRENT_USER, szSubSystemProtocol);
1014 HCERTSTORE WINAPI CertOpenSystemStoreW(HCRYPTPROV_LEGACY hProv,
1015 LPCWSTR szSubSystemProtocol)
1017 if (!szSubSystemProtocol)
1019 SetLastError(E_INVALIDARG);
1020 return 0;
1022 return CertOpenStore(CERT_STORE_PROV_SYSTEM_W, 0, hProv,
1023 CERT_SYSTEM_STORE_CURRENT_USER, szSubSystemProtocol);
1026 BOOL WINAPI CertSaveStore(HCERTSTORE hCertStore, DWORD dwMsgAndCertEncodingType,
1027 DWORD dwSaveAs, DWORD dwSaveTo, void* pvSaveToPara, DWORD dwFlags)
1029 FIXME("(%p,%d,%d,%d,%p,%08x) stub!\n", hCertStore,
1030 dwMsgAndCertEncodingType, dwSaveAs, dwSaveTo, pvSaveToPara, dwFlags);
1031 return TRUE;
1034 #define CertContext_CopyProperties(to, from) \
1035 Context_CopyProperties((to), (from), sizeof(CERT_CONTEXT))
1037 BOOL WINAPI CertAddCertificateContextToStore(HCERTSTORE hCertStore,
1038 PCCERT_CONTEXT pCertContext, DWORD dwAddDisposition,
1039 PCCERT_CONTEXT *ppStoreContext)
1041 PWINECRYPT_CERTSTORE store = (PWINECRYPT_CERTSTORE)hCertStore;
1042 BOOL ret = TRUE;
1043 PCCERT_CONTEXT toAdd = NULL, existing = NULL;
1045 TRACE("(%p, %p, %08x, %p)\n", hCertStore, pCertContext,
1046 dwAddDisposition, ppStoreContext);
1048 /* Weird case to pass a test */
1049 if (dwAddDisposition == 0)
1051 SetLastError(STATUS_ACCESS_VIOLATION);
1052 return FALSE;
1054 if (dwAddDisposition != CERT_STORE_ADD_ALWAYS)
1056 BYTE hashToAdd[20];
1057 DWORD size = sizeof(hashToAdd);
1059 ret = CertGetCertificateContextProperty(pCertContext, CERT_HASH_PROP_ID,
1060 hashToAdd, &size);
1061 if (ret)
1063 CRYPT_HASH_BLOB blob = { sizeof(hashToAdd), hashToAdd };
1065 existing = CertFindCertificateInStore(hCertStore,
1066 pCertContext->dwCertEncodingType, 0, CERT_FIND_SHA1_HASH, &blob,
1067 NULL);
1071 switch (dwAddDisposition)
1073 case CERT_STORE_ADD_ALWAYS:
1074 toAdd = CertDuplicateCertificateContext(pCertContext);
1075 break;
1076 case CERT_STORE_ADD_NEW:
1077 if (existing)
1079 TRACE("found matching certificate, not adding\n");
1080 SetLastError(CRYPT_E_EXISTS);
1081 ret = FALSE;
1083 else
1084 toAdd = CertDuplicateCertificateContext(pCertContext);
1085 break;
1086 case CERT_STORE_ADD_REPLACE_EXISTING:
1087 toAdd = CertDuplicateCertificateContext(pCertContext);
1088 break;
1089 case CERT_STORE_ADD_REPLACE_EXISTING_INHERIT_PROPERTIES:
1090 toAdd = CertDuplicateCertificateContext(pCertContext);
1091 if (existing)
1092 CertContext_CopyProperties(toAdd, existing);
1093 break;
1094 case CERT_STORE_ADD_USE_EXISTING:
1095 if (existing)
1097 CertContext_CopyProperties(existing, pCertContext);
1098 *ppStoreContext = CertDuplicateCertificateContext(existing);
1100 else
1101 toAdd = CertDuplicateCertificateContext(pCertContext);
1102 break;
1103 default:
1104 FIXME("Unimplemented add disposition %d\n", dwAddDisposition);
1105 ret = FALSE;
1108 if (toAdd)
1110 if (store)
1111 ret = store->certs.addContext(store, (void *)toAdd,
1112 (void *)existing, (const void **)ppStoreContext);
1113 else if (ppStoreContext)
1114 *ppStoreContext = CertDuplicateCertificateContext(toAdd);
1115 CertFreeCertificateContext(toAdd);
1117 CertFreeCertificateContext(existing);
1119 TRACE("returning %d\n", ret);
1120 return ret;
1123 PCCERT_CONTEXT WINAPI CertEnumCertificatesInStore(HCERTSTORE hCertStore,
1124 PCCERT_CONTEXT pPrev)
1126 WINECRYPT_CERTSTORE *hcs = (WINECRYPT_CERTSTORE *)hCertStore;
1127 PCCERT_CONTEXT ret;
1129 TRACE("(%p, %p)\n", hCertStore, pPrev);
1130 if (!hCertStore)
1131 ret = NULL;
1132 else if (hcs->dwMagic != WINE_CRYPTCERTSTORE_MAGIC)
1133 ret = NULL;
1134 else
1135 ret = (PCCERT_CONTEXT)hcs->certs.enumContext(hcs, (void *)pPrev);
1136 return ret;
1139 BOOL WINAPI CertDeleteCertificateFromStore(PCCERT_CONTEXT pCertContext)
1141 BOOL ret;
1143 TRACE("(%p)\n", pCertContext);
1145 if (!pCertContext)
1146 ret = TRUE;
1147 else if (!pCertContext->hCertStore)
1149 ret = TRUE;
1150 CertFreeCertificateContext(pCertContext);
1152 else
1154 PWINECRYPT_CERTSTORE hcs =
1155 (PWINECRYPT_CERTSTORE)pCertContext->hCertStore;
1157 if (hcs->dwMagic != WINE_CRYPTCERTSTORE_MAGIC)
1158 ret = FALSE;
1159 else
1160 ret = hcs->certs.deleteContext(hcs, (void *)pCertContext);
1161 CertFreeCertificateContext(pCertContext);
1163 return ret;
1166 #define CrlContext_CopyProperties(to, from) \
1167 Context_CopyProperties((to), (from), sizeof(CRL_CONTEXT))
1169 BOOL WINAPI CertAddCRLContextToStore(HCERTSTORE hCertStore,
1170 PCCRL_CONTEXT pCrlContext, DWORD dwAddDisposition,
1171 PCCRL_CONTEXT* ppStoreContext)
1173 PWINECRYPT_CERTSTORE store = (PWINECRYPT_CERTSTORE)hCertStore;
1174 BOOL ret = TRUE;
1175 PCCRL_CONTEXT toAdd = NULL, existing = NULL;
1177 TRACE("(%p, %p, %08x, %p)\n", hCertStore, pCrlContext,
1178 dwAddDisposition, ppStoreContext);
1180 /* Weird case to pass a test */
1181 if (dwAddDisposition == 0)
1183 SetLastError(STATUS_ACCESS_VIOLATION);
1184 return FALSE;
1186 if (dwAddDisposition != CERT_STORE_ADD_ALWAYS)
1188 existing = CertFindCRLInStore(hCertStore, 0, 0, CRL_FIND_EXISTING,
1189 pCrlContext, NULL);
1192 switch (dwAddDisposition)
1194 case CERT_STORE_ADD_ALWAYS:
1195 toAdd = CertDuplicateCRLContext(pCrlContext);
1196 break;
1197 case CERT_STORE_ADD_NEW:
1198 if (existing)
1200 TRACE("found matching CRL, not adding\n");
1201 SetLastError(CRYPT_E_EXISTS);
1202 ret = FALSE;
1204 else
1205 toAdd = CertDuplicateCRLContext(pCrlContext);
1206 break;
1207 case CERT_STORE_ADD_NEWER:
1208 if (existing)
1210 LONG newer = CompareFileTime(&existing->pCrlInfo->ThisUpdate,
1211 &pCrlContext->pCrlInfo->ThisUpdate);
1213 if (newer < 0)
1214 toAdd = CertDuplicateCRLContext(pCrlContext);
1215 else
1217 TRACE("existing CRL is newer, not adding\n");
1218 SetLastError(CRYPT_E_EXISTS);
1219 ret = FALSE;
1222 else
1223 toAdd = CertDuplicateCRLContext(pCrlContext);
1224 break;
1225 case CERT_STORE_ADD_REPLACE_EXISTING:
1226 toAdd = CertDuplicateCRLContext(pCrlContext);
1227 break;
1228 case CERT_STORE_ADD_REPLACE_EXISTING_INHERIT_PROPERTIES:
1229 toAdd = CertDuplicateCRLContext(pCrlContext);
1230 if (existing)
1231 CrlContext_CopyProperties(toAdd, existing);
1232 break;
1233 case CERT_STORE_ADD_USE_EXISTING:
1234 if (existing)
1235 CrlContext_CopyProperties(existing, pCrlContext);
1236 break;
1237 default:
1238 FIXME("Unimplemented add disposition %d\n", dwAddDisposition);
1239 ret = FALSE;
1242 if (toAdd)
1244 if (store)
1245 ret = store->crls.addContext(store, (void *)toAdd,
1246 (void *)existing, (const void **)ppStoreContext);
1247 else if (ppStoreContext)
1248 *ppStoreContext = CertDuplicateCRLContext(toAdd);
1249 CertFreeCRLContext(toAdd);
1251 CertFreeCRLContext(existing);
1253 TRACE("returning %d\n", ret);
1254 return ret;
1257 BOOL WINAPI CertDeleteCRLFromStore(PCCRL_CONTEXT pCrlContext)
1259 BOOL ret;
1261 TRACE("(%p)\n", pCrlContext);
1263 if (!pCrlContext)
1264 ret = TRUE;
1265 else if (!pCrlContext->hCertStore)
1267 ret = TRUE;
1268 CertFreeCRLContext(pCrlContext);
1270 else
1272 PWINECRYPT_CERTSTORE hcs =
1273 (PWINECRYPT_CERTSTORE)pCrlContext->hCertStore;
1275 if (hcs->dwMagic != WINE_CRYPTCERTSTORE_MAGIC)
1276 ret = FALSE;
1277 else
1278 ret = hcs->crls.deleteContext(hcs, (void *)pCrlContext);
1279 CertFreeCRLContext(pCrlContext);
1281 return ret;
1284 PCCRL_CONTEXT WINAPI CertEnumCRLsInStore(HCERTSTORE hCertStore,
1285 PCCRL_CONTEXT pPrev)
1287 WINECRYPT_CERTSTORE *hcs = (WINECRYPT_CERTSTORE *)hCertStore;
1288 PCCRL_CONTEXT ret;
1290 TRACE("(%p, %p)\n", hCertStore, pPrev);
1291 if (!hCertStore)
1292 ret = NULL;
1293 else if (hcs->dwMagic != WINE_CRYPTCERTSTORE_MAGIC)
1294 ret = NULL;
1295 else
1296 ret = (PCCRL_CONTEXT)hcs->crls.enumContext(hcs, (void *)pPrev);
1297 return ret;
1300 PCCTL_CONTEXT WINAPI CertCreateCTLContext(DWORD dwCertEncodingType,
1301 const BYTE* pbCtlEncoded, DWORD cbCtlEncoded)
1303 FIXME("(%08x, %p, %08x): stub\n", dwCertEncodingType, pbCtlEncoded,
1304 cbCtlEncoded);
1305 return NULL;
1308 BOOL WINAPI CertAddEncodedCTLToStore(HCERTSTORE hCertStore,
1309 DWORD dwMsgAndCertEncodingType, const BYTE *pbCtlEncoded, DWORD cbCtlEncoded,
1310 DWORD dwAddDisposition, PCCTL_CONTEXT *ppCtlContext)
1312 FIXME("(%p, %08x, %p, %d, %08x, %p): stub\n", hCertStore,
1313 dwMsgAndCertEncodingType, pbCtlEncoded, cbCtlEncoded, dwAddDisposition,
1314 ppCtlContext);
1315 return FALSE;
1318 BOOL WINAPI CertAddCTLContextToStore(HCERTSTORE hCertStore,
1319 PCCTL_CONTEXT pCtlContext, DWORD dwAddDisposition,
1320 PCCTL_CONTEXT* ppStoreContext)
1322 FIXME("(%p, %p, %08x, %p): stub\n", hCertStore, pCtlContext,
1323 dwAddDisposition, ppStoreContext);
1324 return TRUE;
1327 PCCTL_CONTEXT WINAPI CertDuplicateCTLContext(PCCTL_CONTEXT pCtlContext)
1329 FIXME("(%p): stub\n", pCtlContext );
1330 return pCtlContext;
1333 BOOL WINAPI CertFreeCTLContext(PCCTL_CONTEXT pCtlContext)
1335 FIXME("(%p): stub\n", pCtlContext );
1336 return TRUE;
1339 BOOL WINAPI CertDeleteCTLFromStore(PCCTL_CONTEXT pCtlContext)
1341 FIXME("(%p): stub\n", pCtlContext);
1342 return TRUE;
1345 PCCTL_CONTEXT WINAPI CertEnumCTLsInStore(HCERTSTORE hCertStore,
1346 PCCTL_CONTEXT pPrev)
1348 FIXME("(%p, %p): stub\n", hCertStore, pPrev);
1349 return NULL;
1352 HCERTSTORE WINAPI CertDuplicateStore(HCERTSTORE hCertStore)
1354 WINECRYPT_CERTSTORE *hcs = (WINECRYPT_CERTSTORE *)hCertStore;
1356 TRACE("(%p)\n", hCertStore);
1358 if (hcs && hcs->dwMagic == WINE_CRYPTCERTSTORE_MAGIC)
1359 InterlockedIncrement(&hcs->ref);
1360 return hCertStore;
1363 BOOL WINAPI CertCloseStore(HCERTSTORE hCertStore, DWORD dwFlags)
1365 WINECRYPT_CERTSTORE *hcs = (WINECRYPT_CERTSTORE *) hCertStore;
1367 TRACE("(%p, %08x)\n", hCertStore, dwFlags);
1369 if( ! hCertStore )
1370 return TRUE;
1372 if ( hcs->dwMagic != WINE_CRYPTCERTSTORE_MAGIC )
1373 return FALSE;
1375 if (InterlockedDecrement(&hcs->ref) == 0)
1377 TRACE("%p's ref count is 0, freeing\n", hcs);
1378 hcs->dwMagic = 0;
1379 if (!(hcs->dwOpenFlags & CERT_STORE_NO_CRYPT_RELEASE_FLAG))
1380 CryptReleaseContext(hcs->cryptProv, 0);
1381 hcs->closeStore(hcs, dwFlags);
1383 else
1384 TRACE("%p's ref count is %d\n", hcs, hcs->ref);
1385 return TRUE;
1388 BOOL WINAPI CertControlStore(HCERTSTORE hCertStore, DWORD dwFlags,
1389 DWORD dwCtrlType, void const *pvCtrlPara)
1391 WINECRYPT_CERTSTORE *hcs = (WINECRYPT_CERTSTORE *)hCertStore;
1392 BOOL ret;
1394 TRACE("(%p, %08x, %d, %p)\n", hCertStore, dwFlags, dwCtrlType,
1395 pvCtrlPara);
1397 if (!hcs)
1398 ret = FALSE;
1399 else if (hcs->dwMagic != WINE_CRYPTCERTSTORE_MAGIC)
1400 ret = FALSE;
1401 else
1403 if (hcs->control)
1404 ret = hcs->control(hCertStore, dwFlags, dwCtrlType, pvCtrlPara);
1405 else
1406 ret = TRUE;
1408 return ret;
1411 BOOL WINAPI CertGetStoreProperty(HCERTSTORE hCertStore, DWORD dwPropId,
1412 void *pvData, DWORD *pcbData)
1414 PWINECRYPT_CERTSTORE store = (PWINECRYPT_CERTSTORE)hCertStore;
1415 BOOL ret = FALSE;
1417 TRACE("(%p, %d, %p, %p)\n", hCertStore, dwPropId, pvData, pcbData);
1419 switch (dwPropId)
1421 case CERT_ACCESS_STATE_PROP_ID:
1422 if (!pvData)
1424 *pcbData = sizeof(DWORD);
1425 ret = TRUE;
1427 else if (*pcbData < sizeof(DWORD))
1429 SetLastError(ERROR_MORE_DATA);
1430 *pcbData = sizeof(DWORD);
1432 else
1434 DWORD state = 0;
1436 if (store->type != StoreTypeMem &&
1437 !(store->dwOpenFlags & CERT_STORE_READONLY_FLAG))
1438 state |= CERT_ACCESS_STATE_WRITE_PERSIST_FLAG;
1439 *(DWORD *)pvData = state;
1440 ret = TRUE;
1442 break;
1443 default:
1444 if (store->properties)
1446 CRYPT_DATA_BLOB blob;
1448 ret = ContextPropertyList_FindProperty(store->properties, dwPropId,
1449 &blob);
1450 if (ret)
1452 if (!pvData)
1453 *pcbData = blob.cbData;
1454 else if (*pcbData < blob.cbData)
1456 SetLastError(ERROR_MORE_DATA);
1457 *pcbData = blob.cbData;
1458 ret = FALSE;
1460 else
1462 memcpy(pvData, blob.pbData, blob.cbData);
1463 *pcbData = blob.cbData;
1466 else
1467 SetLastError(CRYPT_E_NOT_FOUND);
1469 else
1470 SetLastError(CRYPT_E_NOT_FOUND);
1472 return ret;
1475 BOOL WINAPI CertSetStoreProperty(HCERTSTORE hCertStore, DWORD dwPropId,
1476 DWORD dwFlags, const void *pvData)
1478 PWINECRYPT_CERTSTORE store = (PWINECRYPT_CERTSTORE)hCertStore;
1479 BOOL ret = FALSE;
1481 TRACE("(%p, %d, %08x, %p)\n", hCertStore, dwPropId, dwFlags, pvData);
1483 if (!store->properties)
1484 store->properties = ContextPropertyList_Create();
1485 switch (dwPropId)
1487 case CERT_ACCESS_STATE_PROP_ID:
1488 SetLastError(E_INVALIDARG);
1489 break;
1490 default:
1491 if (pvData)
1493 const CRYPT_DATA_BLOB *blob = (const CRYPT_DATA_BLOB *)pvData;
1495 ret = ContextPropertyList_SetProperty(store->properties, dwPropId,
1496 blob->pbData, blob->cbData);
1498 else
1500 ContextPropertyList_RemoveProperty(store->properties, dwPropId);
1501 ret = TRUE;
1504 return ret;
1507 DWORD WINAPI CertEnumCTLContextProperties(PCCTL_CONTEXT pCTLContext,
1508 DWORD dwPropId)
1510 FIXME("(%p, %d): stub\n", pCTLContext, dwPropId);
1511 return 0;
1514 BOOL WINAPI CertGetCTLContextProperty(PCCTL_CONTEXT pCTLContext,
1515 DWORD dwPropId, void *pvData, DWORD *pcbData)
1517 FIXME("(%p, %d, %p, %p): stub\n", pCTLContext, dwPropId, pvData, pcbData);
1518 return FALSE;
1521 BOOL WINAPI CertSetCTLContextProperty(PCCTL_CONTEXT pCTLContext,
1522 DWORD dwPropId, DWORD dwFlags, const void *pvData)
1524 FIXME("(%p, %d, %08x, %p): stub\n", pCTLContext, dwPropId, dwFlags,
1525 pvData);
1526 return FALSE;
1529 static LONG CRYPT_OpenParentStore(DWORD dwFlags,
1530 void *pvSystemStoreLocationPara, HKEY *key)
1532 HKEY root;
1533 LPCWSTR base;
1535 TRACE("(%08x, %p)\n", dwFlags, pvSystemStoreLocationPara);
1537 switch (dwFlags & CERT_SYSTEM_STORE_LOCATION_MASK)
1539 case CERT_SYSTEM_STORE_LOCAL_MACHINE:
1540 root = HKEY_LOCAL_MACHINE;
1541 base = CERT_LOCAL_MACHINE_SYSTEM_STORE_REGPATH;
1542 break;
1543 case CERT_SYSTEM_STORE_CURRENT_USER:
1544 root = HKEY_CURRENT_USER;
1545 base = CERT_LOCAL_MACHINE_SYSTEM_STORE_REGPATH;
1546 break;
1547 case CERT_SYSTEM_STORE_CURRENT_SERVICE:
1548 /* hklm\Software\Microsoft\Cryptography\Services\servicename\
1549 * SystemCertificates
1551 FIXME("CERT_SYSTEM_STORE_CURRENT_SERVICE\n");
1552 return ERROR_FILE_NOT_FOUND;
1553 case CERT_SYSTEM_STORE_SERVICES:
1554 /* hklm\Software\Microsoft\Cryptography\Services\servicename\
1555 * SystemCertificates
1557 FIXME("CERT_SYSTEM_STORE_SERVICES\n");
1558 return ERROR_FILE_NOT_FOUND;
1559 case CERT_SYSTEM_STORE_USERS:
1560 /* hku\user sid\Software\Microsoft\SystemCertificates */
1561 FIXME("CERT_SYSTEM_STORE_USERS\n");
1562 return ERROR_FILE_NOT_FOUND;
1563 case CERT_SYSTEM_STORE_CURRENT_USER_GROUP_POLICY:
1564 root = HKEY_CURRENT_USER;
1565 base = CERT_GROUP_POLICY_SYSTEM_STORE_REGPATH;
1566 break;
1567 case CERT_SYSTEM_STORE_LOCAL_MACHINE_GROUP_POLICY:
1568 root = HKEY_LOCAL_MACHINE;
1569 base = CERT_GROUP_POLICY_SYSTEM_STORE_REGPATH;
1570 break;
1571 case CERT_SYSTEM_STORE_LOCAL_MACHINE_ENTERPRISE:
1572 /* hklm\Software\Microsoft\EnterpriseCertificates */
1573 FIXME("CERT_SYSTEM_STORE_LOCAL_MACHINE_ENTERPRISE\n");
1574 return ERROR_FILE_NOT_FOUND;
1575 default:
1576 return ERROR_FILE_NOT_FOUND;
1579 return RegOpenKeyExW(root, base, 0, KEY_READ, key);
1582 BOOL WINAPI CertEnumSystemStore(DWORD dwFlags, void *pvSystemStoreLocationPara,
1583 void *pvArg, PFN_CERT_ENUM_SYSTEM_STORE pfnEnum)
1585 BOOL ret = FALSE;
1586 LONG rc;
1587 HKEY key;
1589 TRACE("(%08x, %p, %p, %p)\n", dwFlags, pvSystemStoreLocationPara, pvArg,
1590 pfnEnum);
1592 rc = CRYPT_OpenParentStore(dwFlags, pvArg, &key);
1593 if (!rc)
1595 DWORD index = 0;
1596 CERT_SYSTEM_STORE_INFO info = { sizeof(info) };
1598 ret = TRUE;
1599 do {
1600 WCHAR name[MAX_PATH];
1601 DWORD size = sizeof(name) / sizeof(name[0]);
1603 rc = RegEnumKeyExW(key, index++, name, &size, NULL, NULL, NULL,
1604 NULL);
1605 if (!rc)
1606 ret = pfnEnum(name, 0, &info, NULL, pvArg);
1607 } while (ret && !rc);
1608 if (ret && rc != ERROR_NO_MORE_ITEMS)
1609 SetLastError(rc);
1611 else
1612 SetLastError(rc);
1613 return ret;