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