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