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