Merge PR #283 "[USBPORT] Transaction Translator (TT) support bringup"
[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 < sizeof(interfaces) / sizeof(interfaces[0]); 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 = sizeof(msgProvFuncs) /
721 sizeof(msgProvFuncs[0]);
722 provInfo.rgpvStoreProvFunc = msgProvFuncs;
723 provInfo.hStoreProv = CryptMsgDuplicate(msg);
724 store = CRYPT_ProvCreateStore(dwFlags, memStore, &provInfo);
725 /* Msg store doesn't need crypto provider, so close it */
726 if (hCryptProv && !(dwFlags & CERT_STORE_NO_CRYPT_RELEASE_FLAG))
727 CryptReleaseContext(hCryptProv, 0);
728 }
729 else
730 CertCloseStore(memStore, 0);
731 }
732 TRACE("returning %p\n", store);
733 return store;
734 }
735
736 static WINECRYPT_CERTSTORE *CRYPT_PKCSOpenStore(HCRYPTPROV hCryptProv,
737 DWORD dwFlags, const void *pvPara)
738 {
739 HCRYPTMSG msg;
740 WINECRYPT_CERTSTORE *store = NULL;
741 const CRYPT_DATA_BLOB *data = pvPara;
742 BOOL ret;
743 DWORD msgOpenFlags = dwFlags & CERT_STORE_NO_CRYPT_RELEASE_FLAG ? 0 :
744 CMSG_CRYPT_RELEASE_CONTEXT_FLAG;
745
746 TRACE("(%ld, %08x, %p)\n", hCryptProv, dwFlags, pvPara);
747
748 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, msgOpenFlags, CMSG_SIGNED,
749 hCryptProv, NULL, NULL);
750 ret = CryptMsgUpdate(msg, data->pbData, data->cbData, TRUE);
751 if (!ret)
752 {
753 CryptMsgClose(msg);
754 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, msgOpenFlags, 0,
755 hCryptProv, NULL, NULL);
756 ret = CryptMsgUpdate(msg, data->pbData, data->cbData, TRUE);
757 if (ret)
758 {
759 DWORD type, size = sizeof(type);
760
761 /* Only signed messages are allowed, check type */
762 ret = CryptMsgGetParam(msg, CMSG_TYPE_PARAM, 0, &type, &size);
763 if (ret && type != CMSG_SIGNED)
764 {
765 SetLastError(CRYPT_E_INVALID_MSG_TYPE);
766 ret = FALSE;
767 }
768 }
769 }
770 if (ret)
771 store = CRYPT_MsgOpenStore(0, dwFlags, msg);
772 CryptMsgClose(msg);
773 TRACE("returning %p\n", store);
774 return store;
775 }
776
777 static WINECRYPT_CERTSTORE *CRYPT_SerializedOpenStore(HCRYPTPROV hCryptProv,
778 DWORD dwFlags, const void *pvPara)
779 {
780 HCERTSTORE store;
781 const CRYPT_DATA_BLOB *data = pvPara;
782
783 TRACE("(%ld, %08x, %p)\n", hCryptProv, dwFlags, pvPara);
784
785 if (dwFlags & CERT_STORE_DELETE_FLAG)
786 {
787 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
788 return NULL;
789 }
790
791 store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
792 CERT_STORE_CREATE_NEW_FLAG, NULL);
793 if (store)
794 {
795 if (!CRYPT_ReadSerializedStoreFromBlob(data, store))
796 {
797 CertCloseStore(store, 0);
798 store = NULL;
799 }
800 }
801 TRACE("returning %p\n", store);
802 return (WINECRYPT_CERTSTORE*)store;
803 }
804
805 static WINECRYPT_CERTSTORE *CRYPT_PhysOpenStoreW(HCRYPTPROV hCryptProv,
806 DWORD dwFlags, const void *pvPara)
807 {
808 if (dwFlags & CERT_SYSTEM_STORE_RELOCATE_FLAG)
809 FIXME("(%ld, %08x, %p): stub\n", hCryptProv, dwFlags, pvPara);
810 else
811 FIXME("(%ld, %08x, %s): stub\n", hCryptProv, dwFlags,
812 debugstr_w(pvPara));
813 return NULL;
814 }
815
816 HCERTSTORE WINAPI CertOpenStore(LPCSTR lpszStoreProvider,
817 DWORD dwMsgAndCertEncodingType, HCRYPTPROV_LEGACY hCryptProv, DWORD dwFlags,
818 const void* pvPara)
819 {
820 WINECRYPT_CERTSTORE *hcs;
821 StoreOpenFunc openFunc = NULL;
822
823 TRACE("(%s, %08x, %08lx, %08x, %p)\n", debugstr_a(lpszStoreProvider),
824 dwMsgAndCertEncodingType, hCryptProv, dwFlags, pvPara);
825
826 if (IS_INTOID(lpszStoreProvider))
827 {
828 switch (LOWORD(lpszStoreProvider))
829 {
830 case LOWORD(CERT_STORE_PROV_MSG):
831 openFunc = CRYPT_MsgOpenStore;
832 break;
833 case LOWORD(CERT_STORE_PROV_MEMORY):
834 openFunc = CRYPT_MemOpenStore;
835 break;
836 case LOWORD(CERT_STORE_PROV_FILE):
837 openFunc = CRYPT_FileOpenStore;
838 break;
839 case LOWORD(CERT_STORE_PROV_PKCS7):
840 openFunc = CRYPT_PKCSOpenStore;
841 break;
842 case LOWORD(CERT_STORE_PROV_SERIALIZED):
843 openFunc = CRYPT_SerializedOpenStore;
844 break;
845 case LOWORD(CERT_STORE_PROV_REG):
846 openFunc = CRYPT_RegOpenStore;
847 break;
848 case LOWORD(CERT_STORE_PROV_FILENAME_A):
849 openFunc = CRYPT_FileNameOpenStoreA;
850 break;
851 case LOWORD(CERT_STORE_PROV_FILENAME_W):
852 openFunc = CRYPT_FileNameOpenStoreW;
853 break;
854 case LOWORD(CERT_STORE_PROV_COLLECTION):
855 openFunc = CRYPT_CollectionOpenStore;
856 break;
857 case LOWORD(CERT_STORE_PROV_SYSTEM_A):
858 openFunc = CRYPT_SysOpenStoreA;
859 break;
860 case LOWORD(CERT_STORE_PROV_SYSTEM_W):
861 openFunc = CRYPT_SysOpenStoreW;
862 break;
863 case LOWORD(CERT_STORE_PROV_SYSTEM_REGISTRY_A):
864 openFunc = CRYPT_SysRegOpenStoreA;
865 break;
866 case LOWORD(CERT_STORE_PROV_SYSTEM_REGISTRY_W):
867 openFunc = CRYPT_SysRegOpenStoreW;
868 break;
869 case LOWORD(CERT_STORE_PROV_PHYSICAL_W):
870 openFunc = CRYPT_PhysOpenStoreW;
871 break;
872 default:
873 if (LOWORD(lpszStoreProvider))
874 FIXME("unimplemented type %d\n", LOWORD(lpszStoreProvider));
875 }
876 }
877 else if (!strcasecmp(lpszStoreProvider, sz_CERT_STORE_PROV_MEMORY))
878 openFunc = CRYPT_MemOpenStore;
879 else if (!strcasecmp(lpszStoreProvider, sz_CERT_STORE_PROV_FILENAME_W))
880 openFunc = CRYPT_FileOpenStore;
881 else if (!strcasecmp(lpszStoreProvider, sz_CERT_STORE_PROV_SYSTEM))
882 openFunc = CRYPT_SysOpenStoreW;
883 else if (!strcasecmp(lpszStoreProvider, sz_CERT_STORE_PROV_PKCS7))
884 openFunc = CRYPT_PKCSOpenStore;
885 else if (!strcasecmp(lpszStoreProvider, sz_CERT_STORE_PROV_SERIALIZED))
886 openFunc = CRYPT_SerializedOpenStore;
887 else if (!strcasecmp(lpszStoreProvider, sz_CERT_STORE_PROV_COLLECTION))
888 openFunc = CRYPT_CollectionOpenStore;
889 else if (!strcasecmp(lpszStoreProvider, sz_CERT_STORE_PROV_SYSTEM_REGISTRY))
890 openFunc = CRYPT_SysRegOpenStoreW;
891 else
892 {
893 FIXME("unimplemented type %s\n", lpszStoreProvider);
894 openFunc = NULL;
895 }
896
897 if (!openFunc)
898 hcs = CRYPT_ProvOpenStore(lpszStoreProvider, dwMsgAndCertEncodingType,
899 hCryptProv, dwFlags, pvPara);
900 else
901 hcs = openFunc(hCryptProv, dwFlags, pvPara);
902 return hcs;
903 }
904
905 HCERTSTORE WINAPI CertOpenSystemStoreA(HCRYPTPROV_LEGACY hProv,
906 LPCSTR szSubSystemProtocol)
907 {
908 if (!szSubSystemProtocol)
909 {
910 SetLastError(E_INVALIDARG);
911 return 0;
912 }
913 return CertOpenStore(CERT_STORE_PROV_SYSTEM_A, 0, hProv,
914 CERT_SYSTEM_STORE_CURRENT_USER, szSubSystemProtocol);
915 }
916
917 HCERTSTORE WINAPI CertOpenSystemStoreW(HCRYPTPROV_LEGACY hProv,
918 LPCWSTR szSubSystemProtocol)
919 {
920 if (!szSubSystemProtocol)
921 {
922 SetLastError(E_INVALIDARG);
923 return 0;
924 }
925 return CertOpenStore(CERT_STORE_PROV_SYSTEM_W, 0, hProv,
926 CERT_SYSTEM_STORE_CURRENT_USER, szSubSystemProtocol);
927 }
928
929 PCCERT_CONTEXT WINAPI CertEnumCertificatesInStore(HCERTSTORE hCertStore, PCCERT_CONTEXT pPrev)
930 {
931 cert_t *prev = pPrev ? cert_from_ptr(pPrev) : NULL, *ret;
932 WINECRYPT_CERTSTORE *hcs = hCertStore;
933
934 TRACE("(%p, %p)\n", hCertStore, pPrev);
935 if (!hCertStore)
936 ret = NULL;
937 else if (hcs->dwMagic != WINE_CRYPTCERTSTORE_MAGIC)
938 ret = NULL;
939 else
940 ret = (cert_t*)hcs->vtbl->certs.enumContext(hcs, prev ? &prev->base : NULL);
941 return ret ? &ret->ctx : NULL;
942 }
943
944 BOOL WINAPI CertDeleteCertificateFromStore(PCCERT_CONTEXT pCertContext)
945 {
946 WINECRYPT_CERTSTORE *hcs;
947
948 TRACE("(%p)\n", pCertContext);
949
950 if (!pCertContext)
951 return TRUE;
952
953 hcs = pCertContext->hCertStore;
954
955 if (hcs->dwMagic != WINE_CRYPTCERTSTORE_MAGIC)
956 return FALSE;
957
958 return hcs->vtbl->certs.delete(hcs, &cert_from_ptr(pCertContext)->base);
959 }
960
961 BOOL WINAPI CertAddCRLContextToStore(HCERTSTORE hCertStore,
962 PCCRL_CONTEXT pCrlContext, DWORD dwAddDisposition,
963 PCCRL_CONTEXT* ppStoreContext)
964 {
965 WINECRYPT_CERTSTORE *store = hCertStore;
966 BOOL ret = TRUE;
967 PCCRL_CONTEXT toAdd = NULL, existing = NULL;
968
969 TRACE("(%p, %p, %08x, %p)\n", hCertStore, pCrlContext,
970 dwAddDisposition, ppStoreContext);
971
972 /* Weird case to pass a test */
973 if (dwAddDisposition == 0)
974 {
975 SetLastError(STATUS_ACCESS_VIOLATION);
976 return FALSE;
977 }
978 if (dwAddDisposition != CERT_STORE_ADD_ALWAYS)
979 {
980 existing = CertFindCRLInStore(hCertStore, 0, 0, CRL_FIND_EXISTING,
981 pCrlContext, NULL);
982 }
983
984 switch (dwAddDisposition)
985 {
986 case CERT_STORE_ADD_ALWAYS:
987 toAdd = CertDuplicateCRLContext(pCrlContext);
988 break;
989 case CERT_STORE_ADD_NEW:
990 if (existing)
991 {
992 TRACE("found matching CRL, not adding\n");
993 SetLastError(CRYPT_E_EXISTS);
994 ret = FALSE;
995 }
996 else
997 toAdd = CertDuplicateCRLContext(pCrlContext);
998 break;
999 case CERT_STORE_ADD_NEWER:
1000 if (existing)
1001 {
1002 LONG newer = CompareFileTime(&existing->pCrlInfo->ThisUpdate,
1003 &pCrlContext->pCrlInfo->ThisUpdate);
1004
1005 if (newer < 0)
1006 toAdd = CertDuplicateCRLContext(pCrlContext);
1007 else
1008 {
1009 TRACE("existing CRL is newer, not adding\n");
1010 SetLastError(CRYPT_E_EXISTS);
1011 ret = FALSE;
1012 }
1013 }
1014 else
1015 toAdd = CertDuplicateCRLContext(pCrlContext);
1016 break;
1017 case CERT_STORE_ADD_NEWER_INHERIT_PROPERTIES:
1018 if (existing)
1019 {
1020 LONG newer = CompareFileTime(&existing->pCrlInfo->ThisUpdate,
1021 &pCrlContext->pCrlInfo->ThisUpdate);
1022
1023 if (newer < 0)
1024 {
1025 toAdd = CertDuplicateCRLContext(pCrlContext);
1026 Context_CopyProperties(toAdd, existing);
1027 }
1028 else
1029 {
1030 TRACE("existing CRL is newer, not adding\n");
1031 SetLastError(CRYPT_E_EXISTS);
1032 ret = FALSE;
1033 }
1034 }
1035 else
1036 toAdd = CertDuplicateCRLContext(pCrlContext);
1037 break;
1038 case CERT_STORE_ADD_REPLACE_EXISTING:
1039 toAdd = CertDuplicateCRLContext(pCrlContext);
1040 break;
1041 case CERT_STORE_ADD_REPLACE_EXISTING_INHERIT_PROPERTIES:
1042 toAdd = CertDuplicateCRLContext(pCrlContext);
1043 if (existing)
1044 Context_CopyProperties(toAdd, existing);
1045 break;
1046 case CERT_STORE_ADD_USE_EXISTING:
1047 if (existing)
1048 {
1049 Context_CopyProperties(existing, pCrlContext);
1050 if (ppStoreContext)
1051 *ppStoreContext = CertDuplicateCRLContext(existing);
1052 }
1053 else
1054 toAdd = CertDuplicateCRLContext(pCrlContext);
1055 break;
1056 default:
1057 FIXME("Unimplemented add disposition %d\n", dwAddDisposition);
1058 ret = FALSE;
1059 }
1060
1061 if (toAdd)
1062 {
1063 if (store) {
1064 context_t *ret_context;
1065 ret = store->vtbl->crls.addContext(store, context_from_ptr(toAdd),
1066 existing ? context_from_ptr(existing) : NULL, ppStoreContext ? &ret_context : NULL, FALSE);
1067 if (ret && ppStoreContext)
1068 *ppStoreContext = context_ptr(ret_context);
1069 }else if (ppStoreContext) {
1070 *ppStoreContext = CertDuplicateCRLContext(toAdd);
1071 }
1072 CertFreeCRLContext(toAdd);
1073 }
1074 if (existing)
1075 CertFreeCRLContext(existing);
1076
1077 TRACE("returning %d\n", ret);
1078 return ret;
1079 }
1080
1081 BOOL WINAPI CertDeleteCRLFromStore(PCCRL_CONTEXT pCrlContext)
1082 {
1083 WINECRYPT_CERTSTORE *hcs;
1084 BOOL ret;
1085
1086 TRACE("(%p)\n", pCrlContext);
1087
1088 if (!pCrlContext)
1089 return TRUE;
1090
1091 hcs = pCrlContext->hCertStore;
1092
1093 if (hcs->dwMagic != WINE_CRYPTCERTSTORE_MAGIC)
1094 return FALSE;
1095
1096 ret = hcs->vtbl->crls.delete(hcs, &crl_from_ptr(pCrlContext)->base);
1097 if (ret)
1098 ret = CertFreeCRLContext(pCrlContext);
1099 return ret;
1100 }
1101
1102 PCCRL_CONTEXT WINAPI CertEnumCRLsInStore(HCERTSTORE hCertStore, PCCRL_CONTEXT pPrev)
1103 {
1104 crl_t *ret, *prev = pPrev ? crl_from_ptr(pPrev) : NULL;
1105 WINECRYPT_CERTSTORE *hcs = hCertStore;
1106
1107 TRACE("(%p, %p)\n", hCertStore, pPrev);
1108 if (!hCertStore)
1109 ret = NULL;
1110 else if (hcs->dwMagic != WINE_CRYPTCERTSTORE_MAGIC)
1111 ret = NULL;
1112 else
1113 ret = (crl_t*)hcs->vtbl->crls.enumContext(hcs, prev ? &prev->base : NULL);
1114 return ret ? &ret->ctx : NULL;
1115 }
1116
1117 HCERTSTORE WINAPI CertDuplicateStore(HCERTSTORE hCertStore)
1118 {
1119 WINECRYPT_CERTSTORE *hcs = hCertStore;
1120
1121 TRACE("(%p)\n", hCertStore);
1122
1123 if (hcs && hcs->dwMagic == WINE_CRYPTCERTSTORE_MAGIC)
1124 hcs->vtbl->addref(hcs);
1125 return hCertStore;
1126 }
1127
1128 BOOL WINAPI CertCloseStore(HCERTSTORE hCertStore, DWORD dwFlags)
1129 {
1130 WINECRYPT_CERTSTORE *hcs = hCertStore;
1131 DWORD res;
1132
1133 TRACE("(%p, %08x)\n", hCertStore, dwFlags);
1134
1135 if( ! hCertStore )
1136 return TRUE;
1137
1138 if ( hcs->dwMagic != WINE_CRYPTCERTSTORE_MAGIC )
1139 return FALSE;
1140
1141 res = hcs->vtbl->release(hcs, dwFlags);
1142 if (res != ERROR_SUCCESS) {
1143 SetLastError(res);
1144 return FALSE;
1145 }
1146
1147 return TRUE;
1148 }
1149
1150 BOOL WINAPI CertControlStore(HCERTSTORE hCertStore, DWORD dwFlags,
1151 DWORD dwCtrlType, void const *pvCtrlPara)
1152 {
1153 WINECRYPT_CERTSTORE *hcs = hCertStore;
1154 BOOL ret;
1155
1156 TRACE("(%p, %08x, %d, %p)\n", hCertStore, dwFlags, dwCtrlType,
1157 pvCtrlPara);
1158
1159 if (!hcs)
1160 ret = FALSE;
1161 else if (hcs->dwMagic != WINE_CRYPTCERTSTORE_MAGIC)
1162 ret = FALSE;
1163 else
1164 {
1165 if (hcs->vtbl->control)
1166 ret = hcs->vtbl->control(hcs, dwFlags, dwCtrlType, pvCtrlPara);
1167 else
1168 ret = TRUE;
1169 }
1170 return ret;
1171 }
1172
1173 BOOL WINAPI CertGetStoreProperty(HCERTSTORE hCertStore, DWORD dwPropId,
1174 void *pvData, DWORD *pcbData)
1175 {
1176 WINECRYPT_CERTSTORE *store = hCertStore;
1177 BOOL ret = FALSE;
1178
1179 TRACE("(%p, %d, %p, %p)\n", hCertStore, dwPropId, pvData, pcbData);
1180
1181 switch (dwPropId)
1182 {
1183 case CERT_ACCESS_STATE_PROP_ID:
1184 if (!pvData)
1185 {
1186 *pcbData = sizeof(DWORD);
1187 ret = TRUE;
1188 }
1189 else if (*pcbData < sizeof(DWORD))
1190 {
1191 SetLastError(ERROR_MORE_DATA);
1192 *pcbData = sizeof(DWORD);
1193 }
1194 else
1195 {
1196 DWORD state = 0;
1197
1198 if (store->type != StoreTypeMem &&
1199 !(store->dwOpenFlags & CERT_STORE_READONLY_FLAG))
1200 state |= CERT_ACCESS_STATE_WRITE_PERSIST_FLAG;
1201 *(DWORD *)pvData = state;
1202 ret = TRUE;
1203 }
1204 break;
1205 default:
1206 if (store->properties)
1207 {
1208 CRYPT_DATA_BLOB blob;
1209
1210 ret = ContextPropertyList_FindProperty(store->properties, dwPropId,
1211 &blob);
1212 if (ret)
1213 {
1214 if (!pvData)
1215 *pcbData = blob.cbData;
1216 else if (*pcbData < blob.cbData)
1217 {
1218 SetLastError(ERROR_MORE_DATA);
1219 *pcbData = blob.cbData;
1220 ret = FALSE;
1221 }
1222 else
1223 {
1224 memcpy(pvData, blob.pbData, blob.cbData);
1225 *pcbData = blob.cbData;
1226 }
1227 }
1228 else
1229 SetLastError(CRYPT_E_NOT_FOUND);
1230 }
1231 else
1232 SetLastError(CRYPT_E_NOT_FOUND);
1233 }
1234 return ret;
1235 }
1236
1237 BOOL WINAPI CertSetStoreProperty(HCERTSTORE hCertStore, DWORD dwPropId,
1238 DWORD dwFlags, const void *pvData)
1239 {
1240 WINECRYPT_CERTSTORE *store = hCertStore;
1241 BOOL ret = FALSE;
1242
1243 TRACE("(%p, %d, %08x, %p)\n", hCertStore, dwPropId, dwFlags, pvData);
1244
1245 if (!store->properties)
1246 store->properties = ContextPropertyList_Create();
1247 switch (dwPropId)
1248 {
1249 case CERT_ACCESS_STATE_PROP_ID:
1250 SetLastError(E_INVALIDARG);
1251 break;
1252 default:
1253 if (pvData)
1254 {
1255 const CRYPT_DATA_BLOB *blob = pvData;
1256
1257 ret = ContextPropertyList_SetProperty(store->properties, dwPropId,
1258 blob->pbData, blob->cbData);
1259 }
1260 else
1261 {
1262 ContextPropertyList_RemoveProperty(store->properties, dwPropId);
1263 ret = TRUE;
1264 }
1265 }
1266 return ret;
1267 }
1268
1269 static LONG CRYPT_OpenParentStore(DWORD dwFlags,
1270 void *pvSystemStoreLocationPara, HKEY *key)
1271 {
1272 HKEY root;
1273 LPCWSTR base;
1274
1275 TRACE("(%08x, %p)\n", dwFlags, pvSystemStoreLocationPara);
1276
1277 switch (dwFlags & CERT_SYSTEM_STORE_LOCATION_MASK)
1278 {
1279 case CERT_SYSTEM_STORE_LOCAL_MACHINE:
1280 root = HKEY_LOCAL_MACHINE;
1281 base = CERT_LOCAL_MACHINE_SYSTEM_STORE_REGPATH;
1282 break;
1283 case CERT_SYSTEM_STORE_CURRENT_USER:
1284 root = HKEY_CURRENT_USER;
1285 base = CERT_LOCAL_MACHINE_SYSTEM_STORE_REGPATH;
1286 break;
1287 case CERT_SYSTEM_STORE_CURRENT_SERVICE:
1288 /* hklm\Software\Microsoft\Cryptography\Services\servicename\
1289 * SystemCertificates
1290 */
1291 FIXME("CERT_SYSTEM_STORE_CURRENT_SERVICE\n");
1292 return ERROR_FILE_NOT_FOUND;
1293 case CERT_SYSTEM_STORE_SERVICES:
1294 /* hklm\Software\Microsoft\Cryptography\Services\servicename\
1295 * SystemCertificates
1296 */
1297 FIXME("CERT_SYSTEM_STORE_SERVICES\n");
1298 return ERROR_FILE_NOT_FOUND;
1299 case CERT_SYSTEM_STORE_USERS:
1300 /* hku\user sid\Software\Microsoft\SystemCertificates */
1301 FIXME("CERT_SYSTEM_STORE_USERS\n");
1302 return ERROR_FILE_NOT_FOUND;
1303 case CERT_SYSTEM_STORE_CURRENT_USER_GROUP_POLICY:
1304 root = HKEY_CURRENT_USER;
1305 base = CERT_GROUP_POLICY_SYSTEM_STORE_REGPATH;
1306 break;
1307 case CERT_SYSTEM_STORE_LOCAL_MACHINE_GROUP_POLICY:
1308 root = HKEY_LOCAL_MACHINE;
1309 base = CERT_GROUP_POLICY_SYSTEM_STORE_REGPATH;
1310 break;
1311 case CERT_SYSTEM_STORE_LOCAL_MACHINE_ENTERPRISE:
1312 /* hklm\Software\Microsoft\EnterpriseCertificates */
1313 FIXME("CERT_SYSTEM_STORE_LOCAL_MACHINE_ENTERPRISE\n");
1314 return ERROR_FILE_NOT_FOUND;
1315 default:
1316 return ERROR_FILE_NOT_FOUND;
1317 }
1318
1319 return RegOpenKeyExW(root, base, 0, KEY_READ, key);
1320 }
1321
1322 BOOL WINAPI CertEnumSystemStore(DWORD dwFlags, void *pvSystemStoreLocationPara,
1323 void *pvArg, PFN_CERT_ENUM_SYSTEM_STORE pfnEnum)
1324 {
1325 BOOL ret = FALSE;
1326 LONG rc;
1327 HKEY key;
1328 CERT_SYSTEM_STORE_INFO info = { sizeof(info) };
1329
1330 TRACE("(%08x, %p, %p, %p)\n", dwFlags, pvSystemStoreLocationPara, pvArg,
1331 pfnEnum);
1332
1333 rc = CRYPT_OpenParentStore(dwFlags, pvArg, &key);
1334 if (!rc)
1335 {
1336 DWORD index = 0;
1337
1338 ret = TRUE;
1339 do {
1340 WCHAR name[MAX_PATH];
1341 DWORD size = sizeof(name) / sizeof(name[0]);
1342
1343 rc = RegEnumKeyExW(key, index++, name, &size, NULL, NULL, NULL,
1344 NULL);
1345 if (!rc)
1346 ret = pfnEnum(name, dwFlags, &info, NULL, pvArg);
1347 } while (ret && !rc);
1348 if (ret && rc != ERROR_NO_MORE_ITEMS)
1349 SetLastError(rc);
1350 }
1351 else
1352 SetLastError(rc);
1353 /* Include root store for the local machine location (it isn't in the
1354 * registry)
1355 */
1356 if (ret && (dwFlags & CERT_SYSTEM_STORE_LOCATION_MASK) ==
1357 CERT_SYSTEM_STORE_LOCAL_MACHINE)
1358 ret = pfnEnum(rootW, dwFlags, &info, NULL, pvArg);
1359 return ret;
1360 }
1361
1362 BOOL WINAPI CertEnumPhysicalStore(const void *pvSystemStore, DWORD dwFlags,
1363 void *pvArg, PFN_CERT_ENUM_PHYSICAL_STORE pfnEnum)
1364 {
1365 if (dwFlags & CERT_SYSTEM_STORE_RELOCATE_FLAG)
1366 FIXME("(%p, %08x, %p, %p): stub\n", pvSystemStore, dwFlags, pvArg,
1367 pfnEnum);
1368 else
1369 FIXME("(%s, %08x, %p, %p): stub\n", debugstr_w(pvSystemStore),
1370 dwFlags, pvArg,
1371 pfnEnum);
1372 return FALSE;
1373 }
1374
1375 BOOL WINAPI CertRegisterPhysicalStore(const void *pvSystemStore, DWORD dwFlags,
1376 LPCWSTR pwszStoreName, PCERT_PHYSICAL_STORE_INFO pStoreInfo, void *pvReserved)
1377 {
1378 if (dwFlags & CERT_SYSTEM_STORE_RELOCATE_FLAG)
1379 FIXME("(%p, %08x, %s, %p, %p): stub\n", pvSystemStore, dwFlags,
1380 debugstr_w(pwszStoreName), pStoreInfo, pvReserved);
1381 else
1382 FIXME("(%s, %08x, %s, %p, %p): stub\n", debugstr_w(pvSystemStore),
1383 dwFlags, debugstr_w(pwszStoreName), pStoreInfo, pvReserved);
1384 return FALSE;
1385 }
1386
1387 BOOL WINAPI CertUnregisterPhysicalStore(const void *pvSystemStore, DWORD dwFlags,
1388 LPCWSTR pwszStoreName)
1389 {
1390 FIXME("(%p, %08x, %s): stub\n", pvSystemStore, dwFlags, debugstr_w(pwszStoreName));
1391 return TRUE;
1392 }
1393
1394 BOOL WINAPI CertRegisterSystemStore(const void *pvSystemStore, DWORD dwFlags,
1395 PCERT_SYSTEM_STORE_INFO pStoreInfo, void *pvReserved)
1396 {
1397 HCERTSTORE hstore;
1398
1399 if (dwFlags & CERT_SYSTEM_STORE_RELOCATE_FLAG )
1400 {
1401 FIXME("(%p, %08x, %p, %p): flag not supported\n", pvSystemStore, dwFlags, pStoreInfo, pvReserved);
1402 return FALSE;
1403 }
1404
1405 TRACE("(%s, %08x, %p, %p)\n", debugstr_w(pvSystemStore), dwFlags, pStoreInfo, pvReserved);
1406
1407 hstore = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY_W, 0, 0, dwFlags, pvSystemStore);
1408 if (hstore)
1409 {
1410 CertCloseStore(hstore, 0);
1411 return TRUE;
1412 }
1413
1414 return FALSE;
1415 }
1416
1417 BOOL WINAPI CertUnregisterSystemStore(const void *pvSystemStore, DWORD dwFlags)
1418 {
1419 HCERTSTORE hstore;
1420
1421 if (dwFlags & CERT_SYSTEM_STORE_RELOCATE_FLAG)
1422 {
1423 FIXME("(%p, %08x): flag not supported\n", pvSystemStore, dwFlags);
1424 return FALSE;
1425 }
1426 TRACE("(%s, %08x)\n", debugstr_w(pvSystemStore), dwFlags);
1427
1428 hstore = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY_W, 0, 0, dwFlags | CERT_STORE_OPEN_EXISTING_FLAG, pvSystemStore);
1429 if (hstore == NULL)
1430 return FALSE;
1431
1432 hstore = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY_W, 0, 0, dwFlags | CERT_STORE_DELETE_FLAG, pvSystemStore);
1433 if (hstore == NULL && GetLastError() == 0)
1434 return TRUE;
1435
1436 return FALSE;
1437 }
1438
1439 static void EmptyStore_addref(WINECRYPT_CERTSTORE *store)
1440 {
1441 TRACE("(%p)\n", store);
1442 }
1443
1444 static DWORD EmptyStore_release(WINECRYPT_CERTSTORE *store, DWORD flags)
1445 {
1446 TRACE("(%p)\n", store);
1447 return E_UNEXPECTED;
1448 }
1449
1450 static void EmptyStore_releaseContext(WINECRYPT_CERTSTORE *store, context_t *context)
1451 {
1452 Context_Free(context);
1453 }
1454
1455 static BOOL EmptyStore_add(WINECRYPT_CERTSTORE *store, context_t *context,
1456 context_t *replace, context_t **ret_context, BOOL use_link)
1457 {
1458 TRACE("(%p, %p, %p, %p)\n", store, context, replace, ret_context);
1459
1460 /* FIXME: We should clone the context */
1461 if(ret_context) {
1462 Context_AddRef(context);
1463 *ret_context = context;
1464 }
1465
1466 return TRUE;
1467 }
1468
1469 static context_t *EmptyStore_enum(WINECRYPT_CERTSTORE *store, context_t *prev)
1470 {
1471 TRACE("(%p, %p)\n", store, prev);
1472
1473 SetLastError(CRYPT_E_NOT_FOUND);
1474 return NULL;
1475 }
1476
1477 static BOOL EmptyStore_delete(WINECRYPT_CERTSTORE *store, context_t *context)
1478 {
1479 return TRUE;
1480 }
1481
1482 static BOOL EmptyStore_control(WINECRYPT_CERTSTORE *store, DWORD flags, DWORD ctrl_type, void const *ctrl_para)
1483 {
1484 TRACE("()\n");
1485
1486 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1487 return FALSE;
1488 }
1489
1490 static const store_vtbl_t EmptyStoreVtbl = {
1491 EmptyStore_addref,
1492 EmptyStore_release,
1493 EmptyStore_releaseContext,
1494 EmptyStore_control,
1495 {
1496 EmptyStore_add,
1497 EmptyStore_enum,
1498 EmptyStore_delete
1499 }, {
1500 EmptyStore_add,
1501 EmptyStore_enum,
1502 EmptyStore_delete
1503 }, {
1504 EmptyStore_add,
1505 EmptyStore_enum,
1506 EmptyStore_delete
1507 }
1508 };
1509
1510 WINECRYPT_CERTSTORE empty_store;
1511
1512 void init_empty_store(void)
1513 {
1514 CRYPT_InitStore(&empty_store, CERT_STORE_READONLY_FLAG, StoreTypeEmpty, &EmptyStoreVtbl);
1515 }