- Merge from trunk up to r45543
[reactos.git] / dll / win32 / crypt32 / store.c
1 /*
2 * Copyright 2002 Mike McCormack for CodeWeavers
3 * Copyright 2004-2006 Juan Lang
4 *
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.
9 *
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.
14 *
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
18 *
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.
24 */
25
26 #include "config.h"
27 #include "wine/port.h"
28
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"
41
42 WINE_DEFAULT_DEBUG_CHANNEL(crypt);
43
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,
56 };
57 PCWINE_CONTEXT_INTERFACE pCertInterface = &gCertInterface;
58
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,
71 };
72 PCWINE_CONTEXT_INTERFACE pCRLInterface = &gCRLInterface;
73
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,
86 };
87 PCWINE_CONTEXT_INTERFACE pCTLInterface = &gCTLInterface;
88
89 typedef struct _WINE_MEMSTORE
90 {
91 WINECRYPT_CERTSTORE hdr;
92 struct ContextList *certs;
93 struct ContextList *crls;
94 struct ContextList *ctls;
95 } WINE_MEMSTORE, *PWINE_MEMSTORE;
96
97 void CRYPT_InitStore(WINECRYPT_CERTSTORE *store, DWORD dwFlags,
98 CertStoreType type)
99 {
100 store->ref = 1;
101 store->dwMagic = WINE_CRYPTCERTSTORE_MAGIC;
102 store->type = type;
103 store->dwOpenFlags = dwFlags;
104 store->properties = NULL;
105 }
106
107 void CRYPT_FreeStore(PWINECRYPT_CERTSTORE store)
108 {
109 if (store->properties)
110 ContextPropertyList_Free(store->properties);
111 CryptMemFree(store);
112 }
113
114 BOOL WINAPI I_CertUpdateStore(HCERTSTORE store1, HCERTSTORE store2, DWORD unk0,
115 DWORD unk1)
116 {
117 static BOOL warned = FALSE;
118 const WINE_CONTEXT_INTERFACE * const interfaces[] = { pCertInterface,
119 pCRLInterface, pCTLInterface };
120 DWORD i;
121
122 TRACE("(%p, %p, %08x, %08x)\n", store1, store2, unk0, unk1);
123 if (!warned)
124 {
125 FIXME("semi-stub\n");
126 warned = TRUE;
127 }
128
129 /* Poor-man's resync: empty first store, then add everything from second
130 * store to it.
131 */
132 for (i = 0; i < sizeof(interfaces) / sizeof(interfaces[0]); i++)
133 {
134 const void *context;
135
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);
147 }
148 return TRUE;
149 }
150
151 static BOOL CRYPT_MemAddCert(PWINECRYPT_CERTSTORE store, void *cert,
152 void *toReplace, const void **ppStoreContext)
153 {
154 WINE_MEMSTORE *ms = (WINE_MEMSTORE *)store;
155 PCERT_CONTEXT context;
156
157 TRACE("(%p, %p, %p, %p)\n", store, cert, toReplace, ppStoreContext);
158
159 context = ContextList_Add(ms->certs, cert, toReplace);
160 if (context)
161 {
162 context->hCertStore = store;
163 if (ppStoreContext)
164 *ppStoreContext = CertDuplicateCertificateContext(context);
165 }
166 return context ? TRUE : FALSE;
167 }
168
169 static void *CRYPT_MemEnumCert(PWINECRYPT_CERTSTORE store, void *pPrev)
170 {
171 WINE_MEMSTORE *ms = (WINE_MEMSTORE *)store;
172 void *ret;
173
174 TRACE("(%p, %p)\n", store, pPrev);
175
176 ret = ContextList_Enum(ms->certs, pPrev);
177 if (!ret)
178 SetLastError(CRYPT_E_NOT_FOUND);
179
180 TRACE("returning %p\n", ret);
181 return ret;
182 }
183
184 static BOOL CRYPT_MemDeleteCert(PWINECRYPT_CERTSTORE store, void *pCertContext)
185 {
186 WINE_MEMSTORE *ms = (WINE_MEMSTORE *)store;
187 BOOL ret;
188
189 if (ContextList_Remove(ms->certs, pCertContext))
190 ret = CertFreeCertificateContext(pCertContext);
191 else
192 ret = TRUE;
193 return ret;
194 }
195
196 static BOOL CRYPT_MemAddCrl(PWINECRYPT_CERTSTORE store, void *crl,
197 void *toReplace, const void **ppStoreContext)
198 {
199 WINE_MEMSTORE *ms = (WINE_MEMSTORE *)store;
200 PCRL_CONTEXT context;
201
202 TRACE("(%p, %p, %p, %p)\n", store, crl, toReplace, ppStoreContext);
203
204 context = ContextList_Add(ms->crls, crl, toReplace);
205 if (context)
206 {
207 context->hCertStore = store;
208 if (ppStoreContext)
209 *ppStoreContext = CertDuplicateCRLContext(context);
210 }
211 return context ? TRUE : FALSE;
212 }
213
214 static void *CRYPT_MemEnumCrl(PWINECRYPT_CERTSTORE store, void *pPrev)
215 {
216 WINE_MEMSTORE *ms = (WINE_MEMSTORE *)store;
217 void *ret;
218
219 TRACE("(%p, %p)\n", store, pPrev);
220
221 ret = ContextList_Enum(ms->crls, pPrev);
222 if (!ret)
223 SetLastError(CRYPT_E_NOT_FOUND);
224
225 TRACE("returning %p\n", ret);
226 return ret;
227 }
228
229 static BOOL CRYPT_MemDeleteCrl(PWINECRYPT_CERTSTORE store, void *pCrlContext)
230 {
231 WINE_MEMSTORE *ms = (WINE_MEMSTORE *)store;
232 BOOL ret;
233
234 if (ContextList_Remove(ms->crls, pCrlContext))
235 ret = CertFreeCRLContext(pCrlContext);
236 else
237 ret = TRUE;
238 return ret;
239 }
240
241 static BOOL CRYPT_MemAddCtl(PWINECRYPT_CERTSTORE store, void *ctl,
242 void *toReplace, const void **ppStoreContext)
243 {
244 WINE_MEMSTORE *ms = (WINE_MEMSTORE *)store;
245 PCTL_CONTEXT context;
246
247 TRACE("(%p, %p, %p, %p)\n", store, ctl, toReplace, ppStoreContext);
248
249 context = ContextList_Add(ms->ctls, ctl, toReplace);
250 if (context)
251 {
252 context->hCertStore = store;
253 if (ppStoreContext)
254 *ppStoreContext = CertDuplicateCTLContext(context);
255 }
256 return context ? TRUE : FALSE;
257 }
258
259 static void *CRYPT_MemEnumCtl(PWINECRYPT_CERTSTORE store, void *pPrev)
260 {
261 WINE_MEMSTORE *ms = (WINE_MEMSTORE *)store;
262 void *ret;
263
264 TRACE("(%p, %p)\n", store, pPrev);
265
266 ret = ContextList_Enum(ms->ctls, pPrev);
267 if (!ret)
268 SetLastError(CRYPT_E_NOT_FOUND);
269
270 TRACE("returning %p\n", ret);
271 return ret;
272 }
273
274 static BOOL CRYPT_MemDeleteCtl(PWINECRYPT_CERTSTORE store, void *pCtlContext)
275 {
276 WINE_MEMSTORE *ms = (WINE_MEMSTORE *)store;
277 BOOL ret;
278
279 if (ContextList_Remove(ms->ctls, pCtlContext))
280 ret = CertFreeCTLContext(pCtlContext);
281 else
282 ret = TRUE;
283 return ret;
284 }
285
286 static BOOL WINAPI CRYPT_MemControl(HCERTSTORE hCertStore, DWORD dwFlags,
287 DWORD dwCtrlType, void const *pvCtrlPara)
288 {
289 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
290 return FALSE;
291 }
292
293 static void WINAPI CRYPT_MemCloseStore(HCERTSTORE hCertStore, DWORD dwFlags)
294 {
295 WINE_MEMSTORE *store = hCertStore;
296
297 TRACE("(%p, %08x)\n", store, dwFlags);
298 if (dwFlags)
299 FIXME("Unimplemented flags: %08x\n", dwFlags);
300
301 ContextList_Free(store->certs);
302 ContextList_Free(store->crls);
303 ContextList_Free(store->ctls);
304 CRYPT_FreeStore((PWINECRYPT_CERTSTORE)store);
305 }
306
307 static WINECRYPT_CERTSTORE *CRYPT_MemOpenStore(HCRYPTPROV hCryptProv,
308 DWORD dwFlags, const void *pvPara)
309 {
310 PWINE_MEMSTORE store;
311
312 TRACE("(%ld, %08x, %p)\n", hCryptProv, dwFlags, pvPara);
313
314 if (dwFlags & CERT_STORE_DELETE_FLAG)
315 {
316 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
317 store = NULL;
318 }
319 else
320 {
321 store = CryptMemAlloc(sizeof(WINE_MEMSTORE));
322 if (store)
323 {
324 memset(store, 0, sizeof(WINE_MEMSTORE));
325 CRYPT_InitStore(&store->hdr, dwFlags, StoreTypeMem);
326 store->hdr.closeStore = CRYPT_MemCloseStore;
327 store->hdr.certs.addContext = CRYPT_MemAddCert;
328 store->hdr.certs.enumContext = CRYPT_MemEnumCert;
329 store->hdr.certs.deleteContext = CRYPT_MemDeleteCert;
330 store->hdr.crls.addContext = CRYPT_MemAddCrl;
331 store->hdr.crls.enumContext = CRYPT_MemEnumCrl;
332 store->hdr.crls.deleteContext = CRYPT_MemDeleteCrl;
333 store->hdr.ctls.addContext = CRYPT_MemAddCtl;
334 store->hdr.ctls.enumContext = CRYPT_MemEnumCtl;
335 store->hdr.ctls.deleteContext = CRYPT_MemDeleteCtl;
336 store->hdr.control = CRYPT_MemControl;
337 store->certs = ContextList_Create(pCertInterface,
338 sizeof(CERT_CONTEXT));
339 store->crls = ContextList_Create(pCRLInterface,
340 sizeof(CRL_CONTEXT));
341 store->ctls = ContextList_Create(pCTLInterface,
342 sizeof(CTL_CONTEXT));
343 /* Mem store doesn't need crypto provider, so close it */
344 if (hCryptProv && !(dwFlags & CERT_STORE_NO_CRYPT_RELEASE_FLAG))
345 CryptReleaseContext(hCryptProv, 0);
346 }
347 }
348 return (PWINECRYPT_CERTSTORE)store;
349 }
350
351 static const WCHAR rootW[] = { 'R','o','o','t',0 };
352
353 static PWINECRYPT_CERTSTORE CRYPT_SysRegOpenStoreW(HCRYPTPROV hCryptProv,
354 DWORD dwFlags, const void *pvPara)
355 {
356 static const WCHAR fmt[] = { '%','s','\\','%','s',0 };
357 LPCWSTR storeName = pvPara;
358 LPWSTR storePath;
359 PWINECRYPT_CERTSTORE store = NULL;
360 HKEY root;
361 LPCWSTR base;
362
363 TRACE("(%ld, %08x, %s)\n", hCryptProv, dwFlags,
364 debugstr_w(pvPara));
365
366 if (!pvPara)
367 {
368 SetLastError(E_INVALIDARG);
369 return NULL;
370 }
371 /* FIXME: In Windows, the root store (even the current user location) is
372 * protected: adding to it or removing from it present a user interface,
373 * and the keys are owned by the system process, not the current user.
374 * Wine's registry doesn't implement access controls, so a similar
375 * mechanism isn't possible yet.
376 */
377 if ((dwFlags & CERT_SYSTEM_STORE_LOCATION_MASK) ==
378 CERT_SYSTEM_STORE_LOCAL_MACHINE && !lstrcmpiW(storeName, rootW))
379 return CRYPT_RootOpenStore(hCryptProv, dwFlags);
380
381 switch (dwFlags & CERT_SYSTEM_STORE_LOCATION_MASK)
382 {
383 case CERT_SYSTEM_STORE_LOCAL_MACHINE:
384 root = HKEY_LOCAL_MACHINE;
385 base = CERT_LOCAL_MACHINE_SYSTEM_STORE_REGPATH;
386 break;
387 case CERT_SYSTEM_STORE_CURRENT_USER:
388 root = HKEY_CURRENT_USER;
389 base = CERT_LOCAL_MACHINE_SYSTEM_STORE_REGPATH;
390 break;
391 case CERT_SYSTEM_STORE_CURRENT_SERVICE:
392 /* hklm\Software\Microsoft\Cryptography\Services\servicename\
393 * SystemCertificates
394 */
395 FIXME("CERT_SYSTEM_STORE_CURRENT_SERVICE, %s: stub\n",
396 debugstr_w(storeName));
397 return NULL;
398 case CERT_SYSTEM_STORE_SERVICES:
399 /* hklm\Software\Microsoft\Cryptography\Services\servicename\
400 * SystemCertificates
401 */
402 FIXME("CERT_SYSTEM_STORE_SERVICES, %s: stub\n",
403 debugstr_w(storeName));
404 return NULL;
405 case CERT_SYSTEM_STORE_USERS:
406 /* hku\user sid\Software\Microsoft\SystemCertificates */
407 FIXME("CERT_SYSTEM_STORE_USERS, %s: stub\n",
408 debugstr_w(storeName));
409 return NULL;
410 case CERT_SYSTEM_STORE_CURRENT_USER_GROUP_POLICY:
411 root = HKEY_CURRENT_USER;
412 base = CERT_GROUP_POLICY_SYSTEM_STORE_REGPATH;
413 break;
414 case CERT_SYSTEM_STORE_LOCAL_MACHINE_GROUP_POLICY:
415 root = HKEY_LOCAL_MACHINE;
416 base = CERT_GROUP_POLICY_SYSTEM_STORE_REGPATH;
417 break;
418 case CERT_SYSTEM_STORE_LOCAL_MACHINE_ENTERPRISE:
419 /* hklm\Software\Microsoft\EnterpriseCertificates */
420 FIXME("CERT_SYSTEM_STORE_LOCAL_MACHINE_ENTERPRISE, %s: stub\n",
421 debugstr_w(storeName));
422 return NULL;
423 default:
424 SetLastError(E_INVALIDARG);
425 return NULL;
426 }
427
428 storePath = CryptMemAlloc((lstrlenW(base) + lstrlenW(storeName) + 2) *
429 sizeof(WCHAR));
430 if (storePath)
431 {
432 LONG rc;
433 HKEY key;
434 REGSAM sam = dwFlags & CERT_STORE_READONLY_FLAG ? KEY_READ :
435 KEY_ALL_ACCESS;
436
437 wsprintfW(storePath, fmt, base, storeName);
438 if (dwFlags & CERT_STORE_OPEN_EXISTING_FLAG)
439 rc = RegOpenKeyExW(root, storePath, 0, sam, &key);
440 else
441 {
442 DWORD disp;
443
444 rc = RegCreateKeyExW(root, storePath, 0, NULL, 0, sam, NULL,
445 &key, &disp);
446 if (!rc && dwFlags & CERT_STORE_CREATE_NEW_FLAG &&
447 disp == REG_OPENED_EXISTING_KEY)
448 {
449 RegCloseKey(key);
450 rc = ERROR_FILE_EXISTS;
451 }
452 }
453 if (!rc)
454 {
455 store = CRYPT_RegOpenStore(hCryptProv, dwFlags, key);
456 RegCloseKey(key);
457 }
458 else
459 SetLastError(rc);
460 CryptMemFree(storePath);
461 }
462 return store;
463 }
464
465 static PWINECRYPT_CERTSTORE CRYPT_SysRegOpenStoreA(HCRYPTPROV hCryptProv,
466 DWORD dwFlags, const void *pvPara)
467 {
468 int len;
469 PWINECRYPT_CERTSTORE ret = NULL;
470
471 TRACE("(%ld, %08x, %s)\n", hCryptProv, dwFlags,
472 debugstr_a(pvPara));
473
474 if (!pvPara)
475 {
476 SetLastError(ERROR_FILE_NOT_FOUND);
477 return NULL;
478 }
479 len = MultiByteToWideChar(CP_ACP, 0, pvPara, -1, NULL, 0);
480 if (len)
481 {
482 LPWSTR storeName = CryptMemAlloc(len * sizeof(WCHAR));
483
484 if (storeName)
485 {
486 MultiByteToWideChar(CP_ACP, 0, pvPara, -1, storeName, len);
487 ret = CRYPT_SysRegOpenStoreW(hCryptProv, dwFlags, storeName);
488 CryptMemFree(storeName);
489 }
490 }
491 return ret;
492 }
493
494 static PWINECRYPT_CERTSTORE CRYPT_SysOpenStoreW(HCRYPTPROV hCryptProv,
495 DWORD dwFlags, const void *pvPara)
496 {
497 HCERTSTORE store = 0;
498 BOOL ret;
499
500 TRACE("(%ld, %08x, %s)\n", hCryptProv, dwFlags,
501 debugstr_w(pvPara));
502
503 if (!pvPara)
504 {
505 SetLastError(ERROR_FILE_NOT_FOUND);
506 return NULL;
507 }
508 /* This returns a different error than system registry stores if the
509 * location is invalid.
510 */
511 switch (dwFlags & CERT_SYSTEM_STORE_LOCATION_MASK)
512 {
513 case CERT_SYSTEM_STORE_LOCAL_MACHINE:
514 case CERT_SYSTEM_STORE_CURRENT_USER:
515 case CERT_SYSTEM_STORE_CURRENT_SERVICE:
516 case CERT_SYSTEM_STORE_SERVICES:
517 case CERT_SYSTEM_STORE_USERS:
518 case CERT_SYSTEM_STORE_CURRENT_USER_GROUP_POLICY:
519 case CERT_SYSTEM_STORE_LOCAL_MACHINE_GROUP_POLICY:
520 case CERT_SYSTEM_STORE_LOCAL_MACHINE_ENTERPRISE:
521 ret = TRUE;
522 break;
523 default:
524 SetLastError(ERROR_FILE_NOT_FOUND);
525 ret = FALSE;
526 }
527 if (ret)
528 {
529 HCERTSTORE regStore = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY_W,
530 0, 0, dwFlags, pvPara);
531
532 if (regStore)
533 {
534 store = CertOpenStore(CERT_STORE_PROV_COLLECTION, 0, 0,
535 CERT_STORE_CREATE_NEW_FLAG, NULL);
536 CertAddStoreToCollection(store, regStore,
537 dwFlags & CERT_STORE_READONLY_FLAG ? 0 :
538 CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
539 CertCloseStore(regStore, 0);
540 /* CERT_SYSTEM_STORE_CURRENT_USER returns both the HKCU and HKLM
541 * stores.
542 */
543 if ((dwFlags & CERT_SYSTEM_STORE_LOCATION_MASK) ==
544 CERT_SYSTEM_STORE_CURRENT_USER)
545 {
546 dwFlags &= ~CERT_SYSTEM_STORE_CURRENT_USER;
547 dwFlags |= CERT_SYSTEM_STORE_LOCAL_MACHINE;
548 regStore = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY_W, 0,
549 0, dwFlags, pvPara);
550 if (regStore)
551 {
552 CertAddStoreToCollection(store, regStore,
553 dwFlags & CERT_STORE_READONLY_FLAG ? 0 :
554 CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
555 CertCloseStore(regStore, 0);
556 }
557 }
558 /* System store doesn't need crypto provider, so close it */
559 if (hCryptProv && !(dwFlags & CERT_STORE_NO_CRYPT_RELEASE_FLAG))
560 CryptReleaseContext(hCryptProv, 0);
561 }
562 }
563 return store;
564 }
565
566 static PWINECRYPT_CERTSTORE CRYPT_SysOpenStoreA(HCRYPTPROV hCryptProv,
567 DWORD dwFlags, const void *pvPara)
568 {
569 int len;
570 PWINECRYPT_CERTSTORE ret = NULL;
571
572 TRACE("(%ld, %08x, %s)\n", hCryptProv, dwFlags,
573 debugstr_a(pvPara));
574
575 if (!pvPara)
576 {
577 SetLastError(ERROR_FILE_NOT_FOUND);
578 return NULL;
579 }
580 len = MultiByteToWideChar(CP_ACP, 0, pvPara, -1, NULL, 0);
581 if (len)
582 {
583 LPWSTR storeName = CryptMemAlloc(len * sizeof(WCHAR));
584
585 if (storeName)
586 {
587 MultiByteToWideChar(CP_ACP, 0, pvPara, -1, storeName, len);
588 ret = CRYPT_SysOpenStoreW(hCryptProv, dwFlags, storeName);
589 CryptMemFree(storeName);
590 }
591 }
592 return ret;
593 }
594
595 static void WINAPI CRYPT_MsgCloseStore(HCERTSTORE hCertStore, DWORD dwFlags)
596 {
597 HCRYPTMSG msg = hCertStore;
598
599 TRACE("(%p, %08x)\n", msg, dwFlags);
600 CryptMsgClose(msg);
601 }
602
603 static void *msgProvFuncs[] = {
604 CRYPT_MsgCloseStore,
605 };
606
607 static PWINECRYPT_CERTSTORE CRYPT_MsgOpenStore(HCRYPTPROV hCryptProv,
608 DWORD dwFlags, const void *pvPara)
609 {
610 PWINECRYPT_CERTSTORE store = NULL;
611 HCRYPTMSG msg = (HCRYPTMSG)pvPara;
612 PWINECRYPT_CERTSTORE memStore;
613
614 TRACE("(%ld, %08x, %p)\n", hCryptProv, dwFlags, pvPara);
615
616 memStore = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
617 CERT_STORE_CREATE_NEW_FLAG, NULL);
618 if (memStore)
619 {
620 BOOL ret;
621 DWORD size, count, i;
622
623 size = sizeof(count);
624 ret = CryptMsgGetParam(msg, CMSG_CERT_COUNT_PARAM, 0, &count, &size);
625 for (i = 0; ret && i < count; i++)
626 {
627 size = 0;
628 ret = CryptMsgGetParam(msg, CMSG_CERT_PARAM, i, NULL, &size);
629 if (ret)
630 {
631 LPBYTE buf = CryptMemAlloc(size);
632
633 if (buf)
634 {
635 ret = CryptMsgGetParam(msg, CMSG_CERT_PARAM, i, buf, &size);
636 if (ret)
637 ret = CertAddEncodedCertificateToStore(memStore,
638 X509_ASN_ENCODING, buf, size, CERT_STORE_ADD_ALWAYS,
639 NULL);
640 CryptMemFree(buf);
641 }
642 }
643 }
644 size = sizeof(count);
645 ret = CryptMsgGetParam(msg, CMSG_CRL_COUNT_PARAM, 0, &count, &size);
646 for (i = 0; ret && i < count; i++)
647 {
648 size = 0;
649 ret = CryptMsgGetParam(msg, CMSG_CRL_PARAM, i, NULL, &size);
650 if (ret)
651 {
652 LPBYTE buf = CryptMemAlloc(size);
653
654 if (buf)
655 {
656 ret = CryptMsgGetParam(msg, CMSG_CRL_PARAM, i, buf, &size);
657 if (ret)
658 ret = CertAddEncodedCRLToStore(memStore,
659 X509_ASN_ENCODING, buf, size, CERT_STORE_ADD_ALWAYS,
660 NULL);
661 CryptMemFree(buf);
662 }
663 }
664 }
665 if (ret)
666 {
667 CERT_STORE_PROV_INFO provInfo = { 0 };
668
669 provInfo.cbSize = sizeof(provInfo);
670 provInfo.cStoreProvFunc = sizeof(msgProvFuncs) /
671 sizeof(msgProvFuncs[0]);
672 provInfo.rgpvStoreProvFunc = msgProvFuncs;
673 provInfo.hStoreProv = CryptMsgDuplicate(msg);
674 store = CRYPT_ProvCreateStore(dwFlags, memStore, &provInfo);
675 /* Msg store doesn't need crypto provider, so close it */
676 if (hCryptProv && !(dwFlags & CERT_STORE_NO_CRYPT_RELEASE_FLAG))
677 CryptReleaseContext(hCryptProv, 0);
678 }
679 else
680 CertCloseStore(memStore, 0);
681 }
682 TRACE("returning %p\n", store);
683 return store;
684 }
685
686 static PWINECRYPT_CERTSTORE CRYPT_PKCSOpenStore(HCRYPTPROV hCryptProv,
687 DWORD dwFlags, const void *pvPara)
688 {
689 HCRYPTMSG msg;
690 PWINECRYPT_CERTSTORE store = NULL;
691 const CRYPT_DATA_BLOB *data = pvPara;
692 BOOL ret;
693 DWORD msgOpenFlags = dwFlags & CERT_STORE_NO_CRYPT_RELEASE_FLAG ? 0 :
694 CMSG_CRYPT_RELEASE_CONTEXT_FLAG;
695
696 TRACE("(%ld, %08x, %p)\n", hCryptProv, dwFlags, pvPara);
697
698 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, msgOpenFlags, CMSG_SIGNED,
699 hCryptProv, NULL, NULL);
700 ret = CryptMsgUpdate(msg, data->pbData, data->cbData, TRUE);
701 if (!ret)
702 {
703 CryptMsgClose(msg);
704 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, msgOpenFlags, 0,
705 hCryptProv, NULL, NULL);
706 ret = CryptMsgUpdate(msg, data->pbData, data->cbData, TRUE);
707 if (ret)
708 {
709 DWORD type, size = sizeof(type);
710
711 /* Only signed messages are allowed, check type */
712 ret = CryptMsgGetParam(msg, CMSG_TYPE_PARAM, 0, &type, &size);
713 if (ret && type != CMSG_SIGNED)
714 {
715 SetLastError(CRYPT_E_INVALID_MSG_TYPE);
716 ret = FALSE;
717 }
718 }
719 }
720 if (ret)
721 store = CRYPT_MsgOpenStore(0, dwFlags, msg);
722 CryptMsgClose(msg);
723 TRACE("returning %p\n", store);
724 return store;
725 }
726
727 static PWINECRYPT_CERTSTORE CRYPT_PhysOpenStoreW(HCRYPTPROV hCryptProv,
728 DWORD dwFlags, const void *pvPara)
729 {
730 if (dwFlags & CERT_SYSTEM_STORE_RELOCATE_FLAG)
731 FIXME("(%ld, %08x, %p): stub\n", hCryptProv, dwFlags, pvPara);
732 else
733 FIXME("(%ld, %08x, %s): stub\n", hCryptProv, dwFlags,
734 debugstr_w(pvPara));
735 return NULL;
736 }
737
738 HCERTSTORE WINAPI CertOpenStore(LPCSTR lpszStoreProvider,
739 DWORD dwMsgAndCertEncodingType, HCRYPTPROV_LEGACY hCryptProv, DWORD dwFlags,
740 const void* pvPara)
741 {
742 WINECRYPT_CERTSTORE *hcs;
743 StoreOpenFunc openFunc = NULL;
744
745 TRACE("(%s, %08x, %08lx, %08x, %p)\n", debugstr_a(lpszStoreProvider),
746 dwMsgAndCertEncodingType, hCryptProv, dwFlags, pvPara);
747
748 if (!HIWORD(lpszStoreProvider))
749 {
750 switch (LOWORD(lpszStoreProvider))
751 {
752 case LOWORD(CERT_STORE_PROV_MSG):
753 openFunc = CRYPT_MsgOpenStore;
754 break;
755 case LOWORD(CERT_STORE_PROV_MEMORY):
756 openFunc = CRYPT_MemOpenStore;
757 break;
758 case LOWORD(CERT_STORE_PROV_FILE):
759 openFunc = CRYPT_FileOpenStore;
760 break;
761 case LOWORD(CERT_STORE_PROV_PKCS7):
762 openFunc = CRYPT_PKCSOpenStore;
763 break;
764 case LOWORD(CERT_STORE_PROV_REG):
765 openFunc = CRYPT_RegOpenStore;
766 break;
767 case LOWORD(CERT_STORE_PROV_FILENAME_A):
768 openFunc = CRYPT_FileNameOpenStoreA;
769 break;
770 case LOWORD(CERT_STORE_PROV_FILENAME_W):
771 openFunc = CRYPT_FileNameOpenStoreW;
772 break;
773 case LOWORD(CERT_STORE_PROV_COLLECTION):
774 openFunc = CRYPT_CollectionOpenStore;
775 break;
776 case LOWORD(CERT_STORE_PROV_SYSTEM_A):
777 openFunc = CRYPT_SysOpenStoreA;
778 break;
779 case LOWORD(CERT_STORE_PROV_SYSTEM_W):
780 openFunc = CRYPT_SysOpenStoreW;
781 break;
782 case LOWORD(CERT_STORE_PROV_SYSTEM_REGISTRY_A):
783 openFunc = CRYPT_SysRegOpenStoreA;
784 break;
785 case LOWORD(CERT_STORE_PROV_SYSTEM_REGISTRY_W):
786 openFunc = CRYPT_SysRegOpenStoreW;
787 break;
788 case LOWORD(CERT_STORE_PROV_PHYSICAL_W):
789 openFunc = CRYPT_PhysOpenStoreW;
790 break;
791 default:
792 if (LOWORD(lpszStoreProvider))
793 FIXME("unimplemented type %d\n", LOWORD(lpszStoreProvider));
794 }
795 }
796 else if (!strcasecmp(lpszStoreProvider, sz_CERT_STORE_PROV_MEMORY))
797 openFunc = CRYPT_MemOpenStore;
798 else if (!strcasecmp(lpszStoreProvider, sz_CERT_STORE_PROV_FILENAME_W))
799 openFunc = CRYPT_FileOpenStore;
800 else if (!strcasecmp(lpszStoreProvider, sz_CERT_STORE_PROV_SYSTEM))
801 openFunc = CRYPT_SysOpenStoreW;
802 else if (!strcasecmp(lpszStoreProvider, sz_CERT_STORE_PROV_COLLECTION))
803 openFunc = CRYPT_CollectionOpenStore;
804 else if (!strcasecmp(lpszStoreProvider, sz_CERT_STORE_PROV_SYSTEM_REGISTRY))
805 openFunc = CRYPT_SysRegOpenStoreW;
806 else
807 {
808 FIXME("unimplemented type %s\n", lpszStoreProvider);
809 openFunc = NULL;
810 }
811
812 if (!openFunc)
813 hcs = CRYPT_ProvOpenStore(lpszStoreProvider, dwMsgAndCertEncodingType,
814 hCryptProv, dwFlags, pvPara);
815 else
816 hcs = openFunc(hCryptProv, dwFlags, pvPara);
817 return hcs;
818 }
819
820 HCERTSTORE WINAPI CertOpenSystemStoreA(HCRYPTPROV_LEGACY hProv,
821 LPCSTR szSubSystemProtocol)
822 {
823 if (!szSubSystemProtocol)
824 {
825 SetLastError(E_INVALIDARG);
826 return 0;
827 }
828 return CertOpenStore(CERT_STORE_PROV_SYSTEM_A, 0, hProv,
829 CERT_SYSTEM_STORE_CURRENT_USER, szSubSystemProtocol);
830 }
831
832 HCERTSTORE WINAPI CertOpenSystemStoreW(HCRYPTPROV_LEGACY hProv,
833 LPCWSTR szSubSystemProtocol)
834 {
835 if (!szSubSystemProtocol)
836 {
837 SetLastError(E_INVALIDARG);
838 return 0;
839 }
840 return CertOpenStore(CERT_STORE_PROV_SYSTEM_W, 0, hProv,
841 CERT_SYSTEM_STORE_CURRENT_USER, szSubSystemProtocol);
842 }
843
844 #define CertContext_CopyProperties(to, from) \
845 Context_CopyProperties((to), (from), sizeof(CERT_CONTEXT))
846
847 BOOL WINAPI CertAddCertificateContextToStore(HCERTSTORE hCertStore,
848 PCCERT_CONTEXT pCertContext, DWORD dwAddDisposition,
849 PCCERT_CONTEXT *ppStoreContext)
850 {
851 PWINECRYPT_CERTSTORE store = hCertStore;
852 BOOL ret = TRUE;
853 PCCERT_CONTEXT toAdd = NULL, existing = NULL;
854
855 TRACE("(%p, %p, %08x, %p)\n", hCertStore, pCertContext,
856 dwAddDisposition, ppStoreContext);
857
858 if (dwAddDisposition != CERT_STORE_ADD_ALWAYS)
859 {
860 BYTE hashToAdd[20];
861 DWORD size = sizeof(hashToAdd);
862
863 ret = CertGetCertificateContextProperty(pCertContext, CERT_HASH_PROP_ID,
864 hashToAdd, &size);
865 if (ret)
866 {
867 CRYPT_HASH_BLOB blob = { sizeof(hashToAdd), hashToAdd };
868
869 existing = CertFindCertificateInStore(hCertStore,
870 pCertContext->dwCertEncodingType, 0, CERT_FIND_SHA1_HASH, &blob,
871 NULL);
872 }
873 }
874
875 switch (dwAddDisposition)
876 {
877 case CERT_STORE_ADD_ALWAYS:
878 toAdd = CertDuplicateCertificateContext(pCertContext);
879 break;
880 case CERT_STORE_ADD_NEW:
881 if (existing)
882 {
883 TRACE("found matching certificate, not adding\n");
884 SetLastError(CRYPT_E_EXISTS);
885 ret = FALSE;
886 }
887 else
888 toAdd = CertDuplicateCertificateContext(pCertContext);
889 break;
890 case CERT_STORE_ADD_REPLACE_EXISTING:
891 toAdd = CertDuplicateCertificateContext(pCertContext);
892 break;
893 case CERT_STORE_ADD_REPLACE_EXISTING_INHERIT_PROPERTIES:
894 toAdd = CertDuplicateCertificateContext(pCertContext);
895 if (existing)
896 CertContext_CopyProperties(toAdd, existing);
897 break;
898 case CERT_STORE_ADD_USE_EXISTING:
899 if (existing)
900 {
901 CertContext_CopyProperties(existing, pCertContext);
902 if (ppStoreContext)
903 *ppStoreContext = CertDuplicateCertificateContext(existing);
904 }
905 else
906 toAdd = CertDuplicateCertificateContext(pCertContext);
907 break;
908 case CERT_STORE_ADD_NEWER:
909 if (existing)
910 {
911 if (CompareFileTime(&existing->pCertInfo->NotBefore,
912 &pCertContext->pCertInfo->NotBefore) >= 0)
913 {
914 TRACE("existing certificate is newer, not adding\n");
915 SetLastError(CRYPT_E_EXISTS);
916 ret = FALSE;
917 }
918 else
919 toAdd = CertDuplicateCertificateContext(pCertContext);
920 }
921 else
922 toAdd = CertDuplicateCertificateContext(pCertContext);
923 break;
924 case CERT_STORE_ADD_NEWER_INHERIT_PROPERTIES:
925 if (existing)
926 {
927 if (CompareFileTime(&existing->pCertInfo->NotBefore,
928 &pCertContext->pCertInfo->NotBefore) >= 0)
929 {
930 TRACE("existing certificate is newer, not adding\n");
931 SetLastError(CRYPT_E_EXISTS);
932 ret = FALSE;
933 }
934 else
935 {
936 toAdd = CertDuplicateCertificateContext(pCertContext);
937 CertContext_CopyProperties(toAdd, existing);
938 }
939 }
940 else
941 toAdd = CertDuplicateCertificateContext(pCertContext);
942 break;
943 default:
944 FIXME("Unimplemented add disposition %d\n", dwAddDisposition);
945 SetLastError(E_INVALIDARG);
946 ret = FALSE;
947 }
948
949 if (toAdd)
950 {
951 if (store)
952 ret = store->certs.addContext(store, (void *)toAdd,
953 (void *)existing, (const void **)ppStoreContext);
954 else if (ppStoreContext)
955 *ppStoreContext = CertDuplicateCertificateContext(toAdd);
956 CertFreeCertificateContext(toAdd);
957 }
958 CertFreeCertificateContext(existing);
959
960 TRACE("returning %d\n", ret);
961 return ret;
962 }
963
964 PCCERT_CONTEXT WINAPI CertEnumCertificatesInStore(HCERTSTORE hCertStore,
965 PCCERT_CONTEXT pPrev)
966 {
967 WINECRYPT_CERTSTORE *hcs = hCertStore;
968 PCCERT_CONTEXT ret;
969
970 TRACE("(%p, %p)\n", hCertStore, pPrev);
971 if (!hCertStore)
972 ret = NULL;
973 else if (hcs->dwMagic != WINE_CRYPTCERTSTORE_MAGIC)
974 ret = NULL;
975 else
976 ret = (PCCERT_CONTEXT)hcs->certs.enumContext(hcs, (void *)pPrev);
977 return ret;
978 }
979
980 BOOL WINAPI CertDeleteCertificateFromStore(PCCERT_CONTEXT pCertContext)
981 {
982 BOOL ret;
983
984 TRACE("(%p)\n", pCertContext);
985
986 if (!pCertContext)
987 ret = TRUE;
988 else if (!pCertContext->hCertStore)
989 ret = CertFreeCertificateContext(pCertContext);
990 else
991 {
992 PWINECRYPT_CERTSTORE hcs = pCertContext->hCertStore;
993
994 if (hcs->dwMagic != WINE_CRYPTCERTSTORE_MAGIC)
995 ret = FALSE;
996 else
997 ret = hcs->certs.deleteContext(hcs, (void *)pCertContext);
998 if (ret)
999 ret = CertFreeCertificateContext(pCertContext);
1000 }
1001 return ret;
1002 }
1003
1004 #define CrlContext_CopyProperties(to, from) \
1005 Context_CopyProperties((to), (from), sizeof(CRL_CONTEXT))
1006
1007 BOOL WINAPI CertAddCRLContextToStore(HCERTSTORE hCertStore,
1008 PCCRL_CONTEXT pCrlContext, DWORD dwAddDisposition,
1009 PCCRL_CONTEXT* ppStoreContext)
1010 {
1011 PWINECRYPT_CERTSTORE store = hCertStore;
1012 BOOL ret = TRUE;
1013 PCCRL_CONTEXT toAdd = NULL, existing = NULL;
1014
1015 TRACE("(%p, %p, %08x, %p)\n", hCertStore, pCrlContext,
1016 dwAddDisposition, ppStoreContext);
1017
1018 /* Weird case to pass a test */
1019 if (dwAddDisposition == 0)
1020 {
1021 SetLastError(STATUS_ACCESS_VIOLATION);
1022 return FALSE;
1023 }
1024 if (dwAddDisposition != CERT_STORE_ADD_ALWAYS)
1025 {
1026 existing = CertFindCRLInStore(hCertStore, 0, 0, CRL_FIND_EXISTING,
1027 pCrlContext, NULL);
1028 }
1029
1030 switch (dwAddDisposition)
1031 {
1032 case CERT_STORE_ADD_ALWAYS:
1033 toAdd = CertDuplicateCRLContext(pCrlContext);
1034 break;
1035 case CERT_STORE_ADD_NEW:
1036 if (existing)
1037 {
1038 TRACE("found matching CRL, not adding\n");
1039 SetLastError(CRYPT_E_EXISTS);
1040 ret = FALSE;
1041 }
1042 else
1043 toAdd = CertDuplicateCRLContext(pCrlContext);
1044 break;
1045 case CERT_STORE_ADD_NEWER:
1046 if (existing)
1047 {
1048 LONG newer = CompareFileTime(&existing->pCrlInfo->ThisUpdate,
1049 &pCrlContext->pCrlInfo->ThisUpdate);
1050
1051 if (newer < 0)
1052 toAdd = CertDuplicateCRLContext(pCrlContext);
1053 else
1054 {
1055 TRACE("existing CRL is newer, not adding\n");
1056 SetLastError(CRYPT_E_EXISTS);
1057 ret = FALSE;
1058 }
1059 }
1060 else
1061 toAdd = CertDuplicateCRLContext(pCrlContext);
1062 break;
1063 case CERT_STORE_ADD_NEWER_INHERIT_PROPERTIES:
1064 if (existing)
1065 {
1066 LONG newer = CompareFileTime(&existing->pCrlInfo->ThisUpdate,
1067 &pCrlContext->pCrlInfo->ThisUpdate);
1068
1069 if (newer < 0)
1070 {
1071 toAdd = CertDuplicateCRLContext(pCrlContext);
1072 CrlContext_CopyProperties(toAdd, existing);
1073 }
1074 else
1075 {
1076 TRACE("existing CRL is newer, not adding\n");
1077 SetLastError(CRYPT_E_EXISTS);
1078 ret = FALSE;
1079 }
1080 }
1081 else
1082 toAdd = CertDuplicateCRLContext(pCrlContext);
1083 break;
1084 case CERT_STORE_ADD_REPLACE_EXISTING:
1085 toAdd = CertDuplicateCRLContext(pCrlContext);
1086 break;
1087 case CERT_STORE_ADD_REPLACE_EXISTING_INHERIT_PROPERTIES:
1088 toAdd = CertDuplicateCRLContext(pCrlContext);
1089 if (existing)
1090 CrlContext_CopyProperties(toAdd, existing);
1091 break;
1092 case CERT_STORE_ADD_USE_EXISTING:
1093 if (existing)
1094 {
1095 CrlContext_CopyProperties(existing, pCrlContext);
1096 if (ppStoreContext)
1097 *ppStoreContext = CertDuplicateCRLContext(existing);
1098 }
1099 else
1100 toAdd = CertDuplicateCRLContext(pCrlContext);
1101 break;
1102 default:
1103 FIXME("Unimplemented add disposition %d\n", dwAddDisposition);
1104 ret = FALSE;
1105 }
1106
1107 if (toAdd)
1108 {
1109 if (store)
1110 ret = store->crls.addContext(store, (void *)toAdd,
1111 (void *)existing, (const void **)ppStoreContext);
1112 else if (ppStoreContext)
1113 *ppStoreContext = CertDuplicateCRLContext(toAdd);
1114 CertFreeCRLContext(toAdd);
1115 }
1116 CertFreeCRLContext(existing);
1117
1118 TRACE("returning %d\n", ret);
1119 return ret;
1120 }
1121
1122 BOOL WINAPI CertDeleteCRLFromStore(PCCRL_CONTEXT pCrlContext)
1123 {
1124 BOOL ret;
1125
1126 TRACE("(%p)\n", pCrlContext);
1127
1128 if (!pCrlContext)
1129 ret = TRUE;
1130 else if (!pCrlContext->hCertStore)
1131 ret = CertFreeCRLContext(pCrlContext);
1132 else
1133 {
1134 PWINECRYPT_CERTSTORE hcs = pCrlContext->hCertStore;
1135
1136 if (hcs->dwMagic != WINE_CRYPTCERTSTORE_MAGIC)
1137 ret = FALSE;
1138 else
1139 ret = hcs->crls.deleteContext(hcs, (void *)pCrlContext);
1140 if (ret)
1141 ret = CertFreeCRLContext(pCrlContext);
1142 }
1143 return ret;
1144 }
1145
1146 PCCRL_CONTEXT WINAPI CertEnumCRLsInStore(HCERTSTORE hCertStore,
1147 PCCRL_CONTEXT pPrev)
1148 {
1149 WINECRYPT_CERTSTORE *hcs = hCertStore;
1150 PCCRL_CONTEXT ret;
1151
1152 TRACE("(%p, %p)\n", hCertStore, pPrev);
1153 if (!hCertStore)
1154 ret = NULL;
1155 else if (hcs->dwMagic != WINE_CRYPTCERTSTORE_MAGIC)
1156 ret = NULL;
1157 else
1158 ret = (PCCRL_CONTEXT)hcs->crls.enumContext(hcs, (void *)pPrev);
1159 return ret;
1160 }
1161
1162 HCERTSTORE WINAPI CertDuplicateStore(HCERTSTORE hCertStore)
1163 {
1164 WINECRYPT_CERTSTORE *hcs = hCertStore;
1165
1166 TRACE("(%p)\n", hCertStore);
1167
1168 if (hcs && hcs->dwMagic == WINE_CRYPTCERTSTORE_MAGIC)
1169 InterlockedIncrement(&hcs->ref);
1170 return hCertStore;
1171 }
1172
1173 BOOL WINAPI CertCloseStore(HCERTSTORE hCertStore, DWORD dwFlags)
1174 {
1175 WINECRYPT_CERTSTORE *hcs = hCertStore;
1176
1177 TRACE("(%p, %08x)\n", hCertStore, dwFlags);
1178
1179 if( ! hCertStore )
1180 return TRUE;
1181
1182 if ( hcs->dwMagic != WINE_CRYPTCERTSTORE_MAGIC )
1183 return FALSE;
1184
1185 if (hcs->ref <= 0)
1186 ERR("%p's ref count is %d\n", hcs, hcs->ref);
1187 if (InterlockedDecrement(&hcs->ref) == 0)
1188 {
1189 TRACE("%p's ref count is 0, freeing\n", hcs);
1190 hcs->dwMagic = 0;
1191 hcs->closeStore(hcs, dwFlags);
1192 }
1193 else
1194 TRACE("%p's ref count is %d\n", hcs, hcs->ref);
1195 return TRUE;
1196 }
1197
1198 BOOL WINAPI CertControlStore(HCERTSTORE hCertStore, DWORD dwFlags,
1199 DWORD dwCtrlType, void const *pvCtrlPara)
1200 {
1201 WINECRYPT_CERTSTORE *hcs = hCertStore;
1202 BOOL ret;
1203
1204 TRACE("(%p, %08x, %d, %p)\n", hCertStore, dwFlags, dwCtrlType,
1205 pvCtrlPara);
1206
1207 if (!hcs)
1208 ret = FALSE;
1209 else if (hcs->dwMagic != WINE_CRYPTCERTSTORE_MAGIC)
1210 ret = FALSE;
1211 else
1212 {
1213 if (hcs->control)
1214 ret = hcs->control(hCertStore, dwFlags, dwCtrlType, pvCtrlPara);
1215 else
1216 ret = TRUE;
1217 }
1218 return ret;
1219 }
1220
1221 BOOL WINAPI CertGetStoreProperty(HCERTSTORE hCertStore, DWORD dwPropId,
1222 void *pvData, DWORD *pcbData)
1223 {
1224 PWINECRYPT_CERTSTORE store = hCertStore;
1225 BOOL ret = FALSE;
1226
1227 TRACE("(%p, %d, %p, %p)\n", hCertStore, dwPropId, pvData, pcbData);
1228
1229 switch (dwPropId)
1230 {
1231 case CERT_ACCESS_STATE_PROP_ID:
1232 if (!pvData)
1233 {
1234 *pcbData = sizeof(DWORD);
1235 ret = TRUE;
1236 }
1237 else if (*pcbData < sizeof(DWORD))
1238 {
1239 SetLastError(ERROR_MORE_DATA);
1240 *pcbData = sizeof(DWORD);
1241 }
1242 else
1243 {
1244 DWORD state = 0;
1245
1246 if (store->type != StoreTypeMem &&
1247 !(store->dwOpenFlags & CERT_STORE_READONLY_FLAG))
1248 state |= CERT_ACCESS_STATE_WRITE_PERSIST_FLAG;
1249 *(DWORD *)pvData = state;
1250 ret = TRUE;
1251 }
1252 break;
1253 default:
1254 if (store->properties)
1255 {
1256 CRYPT_DATA_BLOB blob;
1257
1258 ret = ContextPropertyList_FindProperty(store->properties, dwPropId,
1259 &blob);
1260 if (ret)
1261 {
1262 if (!pvData)
1263 *pcbData = blob.cbData;
1264 else if (*pcbData < blob.cbData)
1265 {
1266 SetLastError(ERROR_MORE_DATA);
1267 *pcbData = blob.cbData;
1268 ret = FALSE;
1269 }
1270 else
1271 {
1272 memcpy(pvData, blob.pbData, blob.cbData);
1273 *pcbData = blob.cbData;
1274 }
1275 }
1276 else
1277 SetLastError(CRYPT_E_NOT_FOUND);
1278 }
1279 else
1280 SetLastError(CRYPT_E_NOT_FOUND);
1281 }
1282 return ret;
1283 }
1284
1285 BOOL WINAPI CertSetStoreProperty(HCERTSTORE hCertStore, DWORD dwPropId,
1286 DWORD dwFlags, const void *pvData)
1287 {
1288 PWINECRYPT_CERTSTORE store = hCertStore;
1289 BOOL ret = FALSE;
1290
1291 TRACE("(%p, %d, %08x, %p)\n", hCertStore, dwPropId, dwFlags, pvData);
1292
1293 if (!store->properties)
1294 store->properties = ContextPropertyList_Create();
1295 switch (dwPropId)
1296 {
1297 case CERT_ACCESS_STATE_PROP_ID:
1298 SetLastError(E_INVALIDARG);
1299 break;
1300 default:
1301 if (pvData)
1302 {
1303 const CRYPT_DATA_BLOB *blob = pvData;
1304
1305 ret = ContextPropertyList_SetProperty(store->properties, dwPropId,
1306 blob->pbData, blob->cbData);
1307 }
1308 else
1309 {
1310 ContextPropertyList_RemoveProperty(store->properties, dwPropId);
1311 ret = TRUE;
1312 }
1313 }
1314 return ret;
1315 }
1316
1317 static LONG CRYPT_OpenParentStore(DWORD dwFlags,
1318 void *pvSystemStoreLocationPara, HKEY *key)
1319 {
1320 HKEY root;
1321 LPCWSTR base;
1322
1323 TRACE("(%08x, %p)\n", dwFlags, pvSystemStoreLocationPara);
1324
1325 switch (dwFlags & CERT_SYSTEM_STORE_LOCATION_MASK)
1326 {
1327 case CERT_SYSTEM_STORE_LOCAL_MACHINE:
1328 root = HKEY_LOCAL_MACHINE;
1329 base = CERT_LOCAL_MACHINE_SYSTEM_STORE_REGPATH;
1330 break;
1331 case CERT_SYSTEM_STORE_CURRENT_USER:
1332 root = HKEY_CURRENT_USER;
1333 base = CERT_LOCAL_MACHINE_SYSTEM_STORE_REGPATH;
1334 break;
1335 case CERT_SYSTEM_STORE_CURRENT_SERVICE:
1336 /* hklm\Software\Microsoft\Cryptography\Services\servicename\
1337 * SystemCertificates
1338 */
1339 FIXME("CERT_SYSTEM_STORE_CURRENT_SERVICE\n");
1340 return ERROR_FILE_NOT_FOUND;
1341 case CERT_SYSTEM_STORE_SERVICES:
1342 /* hklm\Software\Microsoft\Cryptography\Services\servicename\
1343 * SystemCertificates
1344 */
1345 FIXME("CERT_SYSTEM_STORE_SERVICES\n");
1346 return ERROR_FILE_NOT_FOUND;
1347 case CERT_SYSTEM_STORE_USERS:
1348 /* hku\user sid\Software\Microsoft\SystemCertificates */
1349 FIXME("CERT_SYSTEM_STORE_USERS\n");
1350 return ERROR_FILE_NOT_FOUND;
1351 case CERT_SYSTEM_STORE_CURRENT_USER_GROUP_POLICY:
1352 root = HKEY_CURRENT_USER;
1353 base = CERT_GROUP_POLICY_SYSTEM_STORE_REGPATH;
1354 break;
1355 case CERT_SYSTEM_STORE_LOCAL_MACHINE_GROUP_POLICY:
1356 root = HKEY_LOCAL_MACHINE;
1357 base = CERT_GROUP_POLICY_SYSTEM_STORE_REGPATH;
1358 break;
1359 case CERT_SYSTEM_STORE_LOCAL_MACHINE_ENTERPRISE:
1360 /* hklm\Software\Microsoft\EnterpriseCertificates */
1361 FIXME("CERT_SYSTEM_STORE_LOCAL_MACHINE_ENTERPRISE\n");
1362 return ERROR_FILE_NOT_FOUND;
1363 default:
1364 return ERROR_FILE_NOT_FOUND;
1365 }
1366
1367 return RegOpenKeyExW(root, base, 0, KEY_READ, key);
1368 }
1369
1370 BOOL WINAPI CertEnumSystemStore(DWORD dwFlags, void *pvSystemStoreLocationPara,
1371 void *pvArg, PFN_CERT_ENUM_SYSTEM_STORE pfnEnum)
1372 {
1373 BOOL ret = FALSE;
1374 LONG rc;
1375 HKEY key;
1376 CERT_SYSTEM_STORE_INFO info = { sizeof(info) };
1377
1378 TRACE("(%08x, %p, %p, %p)\n", dwFlags, pvSystemStoreLocationPara, pvArg,
1379 pfnEnum);
1380
1381 rc = CRYPT_OpenParentStore(dwFlags, pvArg, &key);
1382 if (!rc)
1383 {
1384 DWORD index = 0;
1385
1386 ret = TRUE;
1387 do {
1388 WCHAR name[MAX_PATH];
1389 DWORD size = sizeof(name) / sizeof(name[0]);
1390
1391 rc = RegEnumKeyExW(key, index++, name, &size, NULL, NULL, NULL,
1392 NULL);
1393 if (!rc)
1394 ret = pfnEnum(name, dwFlags, &info, NULL, pvArg);
1395 } while (ret && !rc);
1396 if (ret && rc != ERROR_NO_MORE_ITEMS)
1397 SetLastError(rc);
1398 }
1399 else
1400 SetLastError(rc);
1401 /* Include root store for the local machine location (it isn't in the
1402 * registry)
1403 */
1404 if (ret && (dwFlags & CERT_SYSTEM_STORE_LOCATION_MASK) ==
1405 CERT_SYSTEM_STORE_LOCAL_MACHINE)
1406 ret = pfnEnum(rootW, dwFlags, &info, NULL, pvArg);
1407 return ret;
1408 }
1409
1410 BOOL WINAPI CertEnumPhysicalStore(const void *pvSystemStore, DWORD dwFlags,
1411 void *pvArg, PFN_CERT_ENUM_PHYSICAL_STORE pfnEnum)
1412 {
1413 if (dwFlags & CERT_SYSTEM_STORE_RELOCATE_FLAG)
1414 FIXME("(%p, %08x, %p, %p): stub\n", pvSystemStore, dwFlags, pvArg,
1415 pfnEnum);
1416 else
1417 FIXME("(%s, %08x, %p, %p): stub\n", debugstr_w(pvSystemStore),
1418 dwFlags, pvArg,
1419 pfnEnum);
1420 return FALSE;
1421 }