~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Wine Cross Reference
wine/dlls/crypt32/store.c

Version: ~ [ wine-1.1.0 ] ~ [ wine-1.0 ] ~ [ wine-1.0-rc5 ] ~ [ wine-1.0-rc4 ] ~ [ wine-1.0-rc3 ] ~ [ wine-1.0-rc2 ] ~ [ wine-1.0-rc1 ] ~ [ wine-0.9.61 ] ~ [ wine-0.9.60 ] ~ [ wine-0.9.59 ] ~ [ wine-0.9.58 ] ~ [ wine-0.9.57 ] ~ [ wine-0.9.56 ] ~ [ wine-0.9.55 ] ~ [ wine-0.9.54 ] ~ [ wine-0.9.53 ] ~ [ wine-0.9.52 ] ~ [ wine-0.9.51 ] ~ [ wine-0.9.50 ] ~ [ wine-0.9.49 ] ~ [ wine-0.9.48 ] ~ [ wine-0.9.47 ] ~ [ wine-0.9.46 ] ~ [ wine-0.9.45 ] ~ [ wine-0.9.44 ] ~ [ wine-0.9.43 ] ~ [ wine-0.9.42 ] ~ [ wine-0.9.41 ] ~ [ wine-0.9.40 ] ~ [ wine-0.9.39 ] ~ [ wine-0.9.38 ] ~ [ wine-0.9.37 ] ~ [ wine-0.9.36 ] ~ [ wine-0.9.35 ] ~ [ wine-0.9.34 ] ~ [ wine-0.9.33 ] ~ [ wine-0.9.32 ] ~ [ wine-0.9.31 ] ~ [ wine-0.9.30 ] ~ [ wine-0.9.29 ] ~ [ wine-0.9.28 ] ~ [ wine-0.9.27 ] ~ [ wine-0.9.26 ] ~ [ wine-0.9.25 ] ~ [ wine-0.9.24 ] ~ [ wine-0.9.23 ] ~ [ wine-0.9.22 ] ~ [ wine-0.9.21 ] ~ [ wine-0.9.20 ] ~ [ wine-0.9.19 ] ~ [ wine-0.9.18 ] ~ [ wine-0.9.17 ] ~ [ wine-0.9.16 ] ~ [ wine-0.9.15 ] ~ [ wine-0.9.14 ] ~ [ wine-0.9.13 ] ~ [ wine-0.9.12 ] ~ [ wine-0.9.11 ] ~ [ wine-0.9.10 ] ~ [ wine-0.9.9 ] ~ [ wine-0.9.8 ] ~ [ wine-0.9.7 ] ~ [ wine-0.9.6 ] ~ [ wine-0.9.5 ] ~ [ wine-0.9.4 ] ~ [ wine-0.9.3 ] ~ [ wine-0.9.2 ] ~ [ wine-0.9.1 ] ~ [ wine-0.9 ] ~ [ wine20050930 ] ~ [ wine20050830 ] ~ [ wine20050725 ] ~ [ wine20050628 ] ~ [ wine20050524 ] ~ [ wine20050419 ] ~ [ wine20050310 ] ~ [ wine20050211 ] ~ [ wine20050111 ] ~ [ wine20041201 ] ~ [ wine20041019 ] ~ [ wine20040914 ] ~ [ wine20040813 ] ~ [ wine20040716 ] ~ [ wine20040615 ] ~ [ wine20040505 ] ~ [ wine20040408 ] ~ [ wine20040309 ] ~ [ wine20040213 ] ~ [ wine20040121 ] ~ [ wine20031212 ] ~ [ wine20031118 ] ~ [ wine20031016 ] ~ [ wine20030911 ] ~ [ wine20030813 ] ~ [ wine20030709 ] ~ [ wine20030618 ] ~ [ wine20030508 ] ~ [ wine20030408 ] ~ [ wine20030318 ] ~ [ wine20030219 ] ~ [ wine20030115 ] ~ [ wine20021219 ] ~ [ wine20021125 ] ~ [ wine20021031 ] ~ [ wine20021007 ] ~ [ wine20020904 ] ~ [ wine20020804 ] ~ [ wine20020710 ] ~ [ wine20020605 ] ~ [ wine20020509 ] ~ [ wine20020411 ] ~ [ wine20020310 ] ~ [ wine20020228 ] ~ [ wine20011226 ] ~ [ wine20011108 ] ~ [ wine20011004 ] ~ [ wine20010824 ] ~ [ wine20010731 ] ~ [ wine20010629 ] ~ [ wine20010510 ] ~ [ wine20010418 ] ~ [ wine20010326 ] ~ [ wine20010305 ] ~ [ wine20010216 ] ~ [ wine20010112 ] ~ [ wine20001222 ] ~ [ wine20001202 ] ~ [ wine20001026 ] ~ [ wine20001002 ] ~ [ wine20000909 ] ~ [ wine20000821 ] ~ [ wine20000801 ] ~ [ wine20000716 ] ~ [ wine20000326 ] ~ [ wine20000227 ] ~ [ wine20000130 ] ~ [ wine20000109 ] ~

  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 
295     TRACE("(%ld, %08x, %s)\n", hCryptProv, dwFlags,
296      debugstr_w((LPCWSTR)pvPara));
297 
298     if (!pvPara)
299     {
300         SetLastError(E_INVALIDARG);
301         return NULL;
302     }
303     if (!lstrcmpiW(storeName, rootW))
304         return CRYPT_RootOpenStore(hCryptProv, dwFlags);
305 
306     switch (dwFlags & CERT_SYSTEM_STORE_LOCATION_MASK)
307     {
308     case CERT_SYSTEM_STORE_LOCAL_MACHINE:
309         root = HKEY_LOCAL_MACHINE;
310         base = CERT_LOCAL_MACHINE_SYSTEM_STORE_REGPATH;
311         break;
312     case CERT_SYSTEM_STORE_CURRENT_USER:
313         root = HKEY_CURRENT_USER;
314         base = CERT_LOCAL_MACHINE_SYSTEM_STORE_REGPATH;
315         break;
316     case CERT_SYSTEM_STORE_CURRENT_SERVICE:
317         /* hklm\Software\Microsoft\Cryptography\Services\servicename\
318          * SystemCertificates
319          */
320         FIXME("CERT_SYSTEM_STORE_CURRENT_SERVICE, %s: stub\n",
321          debugstr_w(storeName));
322         return NULL;
323     case CERT_SYSTEM_STORE_SERVICES:
324         /* hklm\Software\Microsoft\Cryptography\Services\servicename\
325          * SystemCertificates
326          */
327         FIXME("CERT_SYSTEM_STORE_SERVICES, %s: stub\n",
328          debugstr_w(storeName));
329         return NULL;
330     case CERT_SYSTEM_STORE_USERS:
331         /* hku\user sid\Software\Microsoft\SystemCertificates */
332         FIXME("CERT_SYSTEM_STORE_USERS, %s: stub\n",
333          debugstr_w(storeName));
334         return NULL;
335     case CERT_SYSTEM_STORE_CURRENT_USER_GROUP_POLICY:
336         root = HKEY_CURRENT_USER;
337         base = CERT_GROUP_POLICY_SYSTEM_STORE_REGPATH;
338         break;
339     case CERT_SYSTEM_STORE_LOCAL_MACHINE_GROUP_POLICY:
340         root = HKEY_LOCAL_MACHINE;
341         base = CERT_GROUP_POLICY_SYSTEM_STORE_REGPATH;
342         break;
343     case CERT_SYSTEM_STORE_LOCAL_MACHINE_ENTERPRISE:
344         /* hklm\Software\Microsoft\EnterpriseCertificates */
345         FIXME("CERT_SYSTEM_STORE_LOCAL_MACHINE_ENTERPRISE, %s: stub\n",
346          debugstr_w(storeName));
347         return NULL;
348     default:
349         SetLastError(E_INVALIDARG);
350         return NULL;
351     }
352 
353     storePath = CryptMemAlloc((lstrlenW(base) + lstrlenW(storeName) + 2) *
354      sizeof(WCHAR));
355     if (storePath)
356     {
357         LONG rc;
358         HKEY key;
359         REGSAM sam = dwFlags & CERT_STORE_READONLY_FLAG ? KEY_READ :
360             KEY_ALL_ACCESS;
361 
362         wsprintfW(storePath, fmt, base, storeName);
363         if (dwFlags & CERT_STORE_OPEN_EXISTING_FLAG)
364             rc = RegOpenKeyExW(root, storePath, 0, sam, &key);
365         else
366         {
367             DWORD disp;
368 
369             rc = RegCreateKeyExW(root, storePath, 0, NULL, 0, sam, NULL,
370                                  &key, &disp);
371             if (!rc && dwFlags & CERT_STORE_CREATE_NEW_FLAG &&
372                 disp == REG_OPENED_EXISTING_KEY)
373             {
374                 RegCloseKey(key);
375                 rc = ERROR_FILE_EXISTS;
376             }
377         }
378         if (!rc)
379         {
380             store = CRYPT_RegOpenStore(hCryptProv, dwFlags, key);
381             RegCloseKey(key);
382         }
383         else
384             SetLastError(rc);
385         CryptMemFree(storePath);
386     }
387     return store;
388 }
389 
390 static PWINECRYPT_CERTSTORE CRYPT_SysRegOpenStoreA(HCRYPTPROV hCryptProv,
391  DWORD dwFlags, const void *pvPara)
392 {
393     int len;
394     PWINECRYPT_CERTSTORE ret = NULL;
395 
396     TRACE("(%ld, %08x, %s)\n", hCryptProv, dwFlags,
397      debugstr_a((LPCSTR)pvPara));
398 
399     if (!pvPara)
400     {
401         SetLastError(ERROR_FILE_NOT_FOUND);
402         return NULL;
403     }
404     len = MultiByteToWideChar(CP_ACP, 0, (LPCSTR)pvPara, -1, NULL, 0);
405     if (len)
406     {
407         LPWSTR storeName = CryptMemAlloc(len * sizeof(WCHAR));
408 
409         if (storeName)
410         {
411             MultiByteToWideChar(CP_ACP, 0, (LPCSTR)pvPara, -1, storeName, len);
412             ret = CRYPT_SysRegOpenStoreW(hCryptProv, dwFlags, storeName);
413             CryptMemFree(storeName);
414         }
415     }
416     return ret;
417 }
418 
419 static PWINECRYPT_CERTSTORE CRYPT_SysOpenStoreW(HCRYPTPROV hCryptProv,
420  DWORD dwFlags, const void *pvPara)
421 {
422     HCERTSTORE store = 0;
423     BOOL ret;
424 
425     TRACE("(%ld, %08x, %s)\n", hCryptProv, dwFlags,
426      debugstr_w((LPCWSTR)pvPara));
427 
428     if (!pvPara)
429     {
430         SetLastError(ERROR_FILE_NOT_FOUND);
431         return NULL;
432     }
433     /* This returns a different error than system registry stores if the
434      * location is invalid.
435      */
436     switch (dwFlags & CERT_SYSTEM_STORE_LOCATION_MASK)
437     {
438     case CERT_SYSTEM_STORE_LOCAL_MACHINE:
439     case CERT_SYSTEM_STORE_CURRENT_USER:
440     case CERT_SYSTEM_STORE_CURRENT_SERVICE:
441     case CERT_SYSTEM_STORE_SERVICES:
442     case CERT_SYSTEM_STORE_USERS:
443     case CERT_SYSTEM_STORE_CURRENT_USER_GROUP_POLICY:
444     case CERT_SYSTEM_STORE_LOCAL_MACHINE_GROUP_POLICY:
445     case CERT_SYSTEM_STORE_LOCAL_MACHINE_ENTERPRISE:
446         ret = TRUE;
447         break;
448     default:
449         SetLastError(ERROR_FILE_NOT_FOUND);
450         ret = FALSE;
451     }
452     if (ret)
453     {
454         HCERTSTORE regStore = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY_W,
455          0, 0, dwFlags, pvPara);
456 
457         if (regStore)
458         {
459             store = CertOpenStore(CERT_STORE_PROV_COLLECTION, 0, 0,
460              CERT_STORE_CREATE_NEW_FLAG, NULL);
461             CertAddStoreToCollection(store, regStore,
462              dwFlags & CERT_STORE_READONLY_FLAG ? 0 :
463              CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
464             CertCloseStore(regStore, 0);
465             /* CERT_SYSTEM_STORE_CURRENT_USER returns both the HKCU and HKLM
466              * stores.
467              */
468             if ((dwFlags & CERT_SYSTEM_STORE_LOCATION_MASK) ==
469              CERT_SYSTEM_STORE_CURRENT_USER)
470             {
471                 dwFlags &= ~CERT_SYSTEM_STORE_CURRENT_USER;
472                 dwFlags |= CERT_SYSTEM_STORE_LOCAL_MACHINE;
473                 regStore = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY_W, 0,
474                  0, dwFlags, pvPara);
475                 if (regStore)
476                 {
477                     CertAddStoreToCollection(store, regStore,
478                      dwFlags & CERT_STORE_READONLY_FLAG ? 0 :
479                      CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
480                     CertCloseStore(regStore, 0);
481                 }
482             }
483             /* System store doesn't need crypto provider, so close it */
484             if (hCryptProv && !(dwFlags & CERT_STORE_NO_CRYPT_RELEASE_FLAG))
485                 CryptReleaseContext(hCryptProv, 0);
486         }
487     }
488     return (PWINECRYPT_CERTSTORE)store;
489 }
490 
491 static PWINECRYPT_CERTSTORE CRYPT_SysOpenStoreA(HCRYPTPROV hCryptProv,
492  DWORD dwFlags, const void *pvPara)
493 {
494     int len;
495     PWINECRYPT_CERTSTORE ret = NULL;
496 
497     TRACE("(%ld, %08x, %s)\n", hCryptProv, dwFlags,
498      debugstr_a((LPCSTR)pvPara));
499 
500     if (!pvPara)
501     {
502         SetLastError(ERROR_FILE_NOT_FOUND);
503         return NULL;
504     }
505     len = MultiByteToWideChar(CP_ACP, 0, (LPCSTR)pvPara, -1, NULL, 0);
506     if (len)
507     {
508         LPWSTR storeName = CryptMemAlloc(len * sizeof(WCHAR));
509 
510         if (storeName)
511         {
512             MultiByteToWideChar(CP_ACP, 0, (LPCSTR)pvPara, -1, storeName, len);
513             ret = CRYPT_SysOpenStoreW(hCryptProv, dwFlags, storeName);
514             CryptMemFree(storeName);
515         }
516     }
517     return ret;
518 }
519 
520 static void WINAPI CRYPT_MsgCloseStore(HCERTSTORE hCertStore, DWORD dwFlags)
521 {
522     HCRYPTMSG msg = hCertStore;
523 
524     TRACE("(%p, %08x)\n", msg, dwFlags);
525     CryptMsgClose(msg);
526 }
527 
528 static void *msgProvFuncs[] = {
529     CRYPT_MsgCloseStore,
530 };
531 
532 static PWINECRYPT_CERTSTORE CRYPT_MsgOpenStore(HCRYPTPROV hCryptProv,
533  DWORD dwFlags, const void *pvPara)
534 {
535     PWINECRYPT_CERTSTORE store = NULL;
536     HCRYPTMSG msg = (HCRYPTMSG)pvPara;
537     PWINECRYPT_CERTSTORE memStore;
538 
539     TRACE("(%ld, %08x, %p)\n", hCryptProv, dwFlags, pvPara);
540 
541     memStore = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
542      CERT_STORE_CREATE_NEW_FLAG, NULL);
543     if (memStore)
544     {
545         BOOL ret;
546         DWORD size, count, i;
547 
548         size = sizeof(count);
549         ret = CryptMsgGetParam(msg, CMSG_CERT_COUNT_PARAM, 0, &count, &size);
550         for (i = 0; ret && i < count; i++)
551         {
552             size = 0;
553             ret = CryptMsgGetParam(msg, CMSG_CERT_PARAM, i, NULL, &size);
554             if (ret)
555             {
556                 LPBYTE buf = CryptMemAlloc(size);
557 
558                 if (buf)
559                 {
560                     ret = CryptMsgGetParam(msg, CMSG_CERT_PARAM, i, buf, &size);
561                     if (ret)
562                         ret = CertAddEncodedCertificateToStore(memStore,
563                          X509_ASN_ENCODING, buf, size, CERT_STORE_ADD_ALWAYS,
564                          NULL);
565                     CryptMemFree(buf);
566                 }
567             }
568         }
569         size = sizeof(count);
570         ret = CryptMsgGetParam(msg, CMSG_CRL_COUNT_PARAM, 0, &count, &size);
571         for (i = 0; ret && i < count; i++)
572         {
573             size = 0;
574             ret = CryptMsgGetParam(msg, CMSG_CRL_PARAM, i, NULL, &size);
575             if (ret)
576             {
577                 LPBYTE buf = CryptMemAlloc(size);
578 
579                 if (buf)
580                 {
581                     ret = CryptMsgGetParam(msg, CMSG_CRL_PARAM, i, buf, &size);
582                     if (ret)
583                         ret = CertAddEncodedCRLToStore(memStore,
584                          X509_ASN_ENCODING, buf, size, CERT_STORE_ADD_ALWAYS,
585                          NULL);
586                     CryptMemFree(buf);
587                 }
588             }
589         }
590         if (ret)
591         {
592             CERT_STORE_PROV_INFO provInfo = { 0 };
593 
594             provInfo.cbSize = sizeof(provInfo);
595             provInfo.cStoreProvFunc = sizeof(msgProvFuncs) /
596              sizeof(msgProvFuncs[0]);
597             provInfo.rgpvStoreProvFunc = msgProvFuncs;
598             provInfo.hStoreProv = CryptMsgDuplicate(msg);
599             store = CRYPT_ProvCreateStore(dwFlags, memStore, &provInfo);
600             /* Msg store doesn't need crypto provider, so close it */
601             if (hCryptProv && !(dwFlags & CERT_STORE_NO_CRYPT_RELEASE_FLAG))
602                 CryptReleaseContext(hCryptProv, 0);
603         }
604         else
605             CertCloseStore(memStore, 0);
606     }
607     TRACE("returning %p\n", store);
608     return store;
609 }
610 
611 static PWINECRYPT_CERTSTORE CRYPT_PKCSOpenStore(HCRYPTPROV hCryptProv,
612  DWORD dwFlags, const void *pvPara)
613 {
614     HCRYPTMSG msg;
615     PWINECRYPT_CERTSTORE store = NULL;
616     const CRYPT_DATA_BLOB *data = (const CRYPT_DATA_BLOB *)pvPara;
617     BOOL ret;
618     DWORD msgOpenFlags = dwFlags & CERT_STORE_NO_CRYPT_RELEASE_FLAG ? 0 :
619      CMSG_CRYPT_RELEASE_CONTEXT_FLAG;
620 
621     TRACE("(%ld, %08x, %p)\n", hCryptProv, dwFlags, pvPara);
622 
623     msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, msgOpenFlags, CMSG_SIGNED,
624      hCryptProv, NULL, NULL);
625     ret = CryptMsgUpdate(msg, data->pbData, data->cbData, TRUE);
626     if (!ret)
627     {
628         CryptMsgClose(msg);
629         msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, msgOpenFlags, 0,
630          hCryptProv, NULL, NULL);
631         ret = CryptMsgUpdate(msg, data->pbData, data->cbData, TRUE);
632         if (ret)
633         {
634             DWORD type, size = sizeof(type);
635 
636             /* Only signed messages are allowed, check type */
637             ret = CryptMsgGetParam(msg, CMSG_TYPE_PARAM, 0, &type, &size);
638             if (ret && type != CMSG_SIGNED)
639             {
640                 SetLastError(CRYPT_E_INVALID_MSG_TYPE);
641                 ret = FALSE;
642             }
643         }
644     }
645     if (ret)
646         store = CRYPT_MsgOpenStore(0, dwFlags, msg);
647     CryptMsgClose(msg);
648     TRACE("returning %p\n", store);
649     return store;
650 }
651 
652 static PWINECRYPT_CERTSTORE CRYPT_PhysOpenStoreW(HCRYPTPROV hCryptProv,
653  DWORD dwFlags, const void *pvPara)
654 {
655     if (dwFlags & CERT_SYSTEM_STORE_RELOCATE_FLAG)
656         FIXME("(%ld, %08x, %p): stub\n", hCryptProv, dwFlags, pvPara);
657     else
658         FIXME("(%ld, %08x, %s): stub\n", hCryptProv, dwFlags,
659          debugstr_w((LPCWSTR)pvPara));
660     return NULL;
661 }
662 
663 HCERTSTORE WINAPI CertOpenStore(LPCSTR lpszStoreProvider,
664  DWORD dwMsgAndCertEncodingType, HCRYPTPROV_LEGACY hCryptProv, DWORD dwFlags,
665  const void* pvPara)
666 {
667     WINECRYPT_CERTSTORE *hcs;
668     StoreOpenFunc openFunc = NULL;
669 
670     TRACE("(%s, %08x, %08lx, %08x, %p)\n", debugstr_a(lpszStoreProvider),
671           dwMsgAndCertEncodingType, hCryptProv, dwFlags, pvPara);
672 
673     if (!HIWORD(lpszStoreProvider))
674     {
675         switch (LOWORD(lpszStoreProvider))
676         {
677         case LOWORD(CERT_STORE_PROV_MSG):
678             openFunc = CRYPT_MsgOpenStore;
679             break;
680         case LOWORD(CERT_STORE_PROV_MEMORY):
681             openFunc = CRYPT_MemOpenStore;
682             break;
683         case LOWORD(CERT_STORE_PROV_FILE):
684             openFunc = CRYPT_FileOpenStore;
685             break;
686         case LOWORD(CERT_STORE_PROV_PKCS7):
687             openFunc = CRYPT_PKCSOpenStore;
688             break;
689         case LOWORD(CERT_STORE_PROV_REG):
690             openFunc = CRYPT_RegOpenStore;
691             break;
692         case LOWORD(CERT_STORE_PROV_FILENAME_A):
693             openFunc = CRYPT_FileNameOpenStoreA;
694             break;
695         case LOWORD(CERT_STORE_PROV_FILENAME_W):
696             openFunc = CRYPT_FileNameOpenStoreW;
697             break;
698         case LOWORD(CERT_STORE_PROV_COLLECTION):
699             openFunc = CRYPT_CollectionOpenStore;
700             break;
701         case LOWORD(CERT_STORE_PROV_SYSTEM_A):
702             openFunc = CRYPT_SysOpenStoreA;
703             break;
704         case LOWORD(CERT_STORE_PROV_SYSTEM_W):
705             openFunc = CRYPT_SysOpenStoreW;
706             break;
707         case LOWORD(CERT_STORE_PROV_SYSTEM_REGISTRY_A):
708             openFunc = CRYPT_SysRegOpenStoreA;
709             break;
710         case LOWORD(CERT_STORE_PROV_SYSTEM_REGISTRY_W):
711             openFunc = CRYPT_SysRegOpenStoreW;
712             break;
713         case LOWORD(CERT_STORE_PROV_PHYSICAL_W):
714             openFunc = CRYPT_PhysOpenStoreW;
715             break;
716         default:
717             if (LOWORD(lpszStoreProvider))
718                 FIXME("unimplemented type %d\n", LOWORD(lpszStoreProvider));
719         }
720     }
721     else if (!strcasecmp(lpszStoreProvider, sz_CERT_STORE_PROV_MEMORY))
722         openFunc = CRYPT_MemOpenStore;
723     else if (!strcasecmp(lpszStoreProvider, sz_CERT_STORE_PROV_FILENAME_W))
724         openFunc = CRYPT_FileOpenStore;
725     else if (!strcasecmp(lpszStoreProvider, sz_CERT_STORE_PROV_SYSTEM))
726         openFunc = CRYPT_SysOpenStoreW;
727     else if (!strcasecmp(lpszStoreProvider, sz_CERT_STORE_PROV_COLLECTION))
728         openFunc = CRYPT_CollectionOpenStore;
729     else if (!strcasecmp(lpszStoreProvider, sz_CERT_STORE_PROV_SYSTEM_REGISTRY))
730         openFunc = CRYPT_SysRegOpenStoreW;
731     else
732     {
733         FIXME("unimplemented type %s\n", lpszStoreProvider);
734         openFunc = NULL;
735     }
736 
737     if (!openFunc)
738         hcs = CRYPT_ProvOpenStore(lpszStoreProvider, dwMsgAndCertEncodingType,
739          hCryptProv, dwFlags, pvPara);
740     else
741         hcs = openFunc(hCryptProv, dwFlags, pvPara);
742     return (HCERTSTORE)hcs;
743 }
744 
745 HCERTSTORE WINAPI CertOpenSystemStoreA(HCRYPTPROV_LEGACY hProv,
746  LPCSTR szSubSystemProtocol)
747 {
748     if (!szSubSystemProtocol)
749     {
750         SetLastError(E_INVALIDARG);
751         return 0;
752     }
753     return CertOpenStore(CERT_STORE_PROV_SYSTEM_A, 0, hProv,
754      CERT_SYSTEM_STORE_CURRENT_USER, szSubSystemProtocol);
755 }
756 
757 HCERTSTORE WINAPI CertOpenSystemStoreW(HCRYPTPROV_LEGACY hProv,
758  LPCWSTR szSubSystemProtocol)
759 {
760     if (!szSubSystemProtocol)
761     {
762         SetLastError(E_INVALIDARG);
763         return 0;
764     }
765     return CertOpenStore(CERT_STORE_PROV_SYSTEM_W, 0, hProv,
766      CERT_SYSTEM_STORE_CURRENT_USER, szSubSystemProtocol);
767 }
768 
769 #define CertContext_CopyProperties(to, from) \
770  Context_CopyProperties((to), (from), sizeof(CERT_CONTEXT))
771 
772 BOOL WINAPI CertAddCertificateContextToStore(HCERTSTORE hCertStore,
773  PCCERT_CONTEXT pCertContext, DWORD dwAddDisposition,
774  PCCERT_CONTEXT *ppStoreContext)
775 {
776     PWINECRYPT_CERTSTORE store = (PWINECRYPT_CERTSTORE)hCertStore;
777     BOOL ret = TRUE;
778     PCCERT_CONTEXT toAdd = NULL, existing = NULL;
779 
780     TRACE("(%p, %p, %08x, %p)\n", hCertStore, pCertContext,
781      dwAddDisposition, ppStoreContext);
782 
783     if (dwAddDisposition != CERT_STORE_ADD_ALWAYS)
784     {
785         BYTE hashToAdd[20];
786         DWORD size = sizeof(hashToAdd);
787 
788         ret = CertGetCertificateContextProperty(pCertContext, CERT_HASH_PROP_ID,
789          hashToAdd, &size);
790         if (ret)
791         {
792             CRYPT_HASH_BLOB blob = { sizeof(hashToAdd), hashToAdd };
793 
794             existing = CertFindCertificateInStore(hCertStore,
795              pCertContext->dwCertEncodingType, 0, CERT_FIND_SHA1_HASH, &blob,
796              NULL);
797         }
798     }
799 
800     switch (dwAddDisposition)
801     {
802     case CERT_STORE_ADD_ALWAYS:
803         toAdd = CertDuplicateCertificateContext(pCertContext);
804         break;
805     case CERT_STORE_ADD_NEW:
806         if (existing)
807         {
808             TRACE("found matching certificate, not adding\n");
809             SetLastError(CRYPT_E_EXISTS);
810             ret = FALSE;
811         }
812         else
813             toAdd = CertDuplicateCertificateContext(pCertContext);
814         break;
815     case CERT_STORE_ADD_REPLACE_EXISTING:
816         toAdd = CertDuplicateCertificateContext(pCertContext);
817         break;
818     case CERT_STORE_ADD_REPLACE_EXISTING_INHERIT_PROPERTIES:
819         toAdd = CertDuplicateCertificateContext(pCertContext);
820         if (existing)
821             CertContext_CopyProperties(toAdd, existing);
822         break;
823     case CERT_STORE_ADD_USE_EXISTING:
824         if (existing)
825         {
826             CertContext_CopyProperties(existing, pCertContext);
827             *ppStoreContext = CertDuplicateCertificateContext(existing);
828         }
829         else
830             toAdd = CertDuplicateCertificateContext(pCertContext);
831         break;
832     case CERT_STORE_ADD_NEWER:
833         if (existing)
834         {
835             if (CompareFileTime(&existing->pCertInfo->NotBefore,
836              &pCertContext->pCertInfo->NotBefore) >= 0)
837             {
838                 TRACE("existing certificate is newer, not adding\n");
839                 SetLastError(CRYPT_E_EXISTS);
840                 ret = FALSE;
841             }
842             else
843                 toAdd = CertDuplicateCertificateContext(pCertContext);
844         }
845         else
846             toAdd = CertDuplicateCertificateContext(pCertContext);
847         break;
848     default:
849         FIXME("Unimplemented add disposition %d\n", dwAddDisposition);
850         SetLastError(E_INVALIDARG);
851         ret = FALSE;
852     }
853 
854     if (toAdd)
855     {
856         if (store)
857             ret = store->certs.addContext(store, (void *)toAdd,
858              (void *)existing, (const void **)ppStoreContext);
859         else if (ppStoreContext)
860             *ppStoreContext = CertDuplicateCertificateContext(toAdd);
861         CertFreeCertificateContext(toAdd);
862     }
863     CertFreeCertificateContext(existing);
864 
865     TRACE("returning %d\n", ret);
866     return ret;
867 }
868 
869 PCCERT_CONTEXT WINAPI CertEnumCertificatesInStore(HCERTSTORE hCertStore,
870  PCCERT_CONTEXT pPrev)
871 {
872     WINECRYPT_CERTSTORE *hcs = (WINECRYPT_CERTSTORE *)hCertStore;
873     PCCERT_CONTEXT ret;
874 
875     TRACE("(%p, %p)\n", hCertStore, pPrev);
876     if (!hCertStore)
877         ret = NULL;
878     else if (hcs->dwMagic != WINE_CRYPTCERTSTORE_MAGIC)
879         ret = NULL;
880     else
881         ret = (PCCERT_CONTEXT)hcs->certs.enumContext(hcs, (void *)pPrev);
882     return ret;
883 }
884 
885 BOOL WINAPI CertDeleteCertificateFromStore(PCCERT_CONTEXT pCertContext)
886 {
887     BOOL ret;
888 
889     TRACE("(%p)\n", pCertContext);
890 
891     if (!pCertContext)
892         ret = TRUE;
893     else if (!pCertContext->hCertStore)
894     {
895         ret = TRUE;
896         CertFreeCertificateContext(pCertContext);
897     }
898     else
899     {
900         PWINECRYPT_CERTSTORE hcs =
901          (PWINECRYPT_CERTSTORE)pCertContext->hCertStore;
902 
903         if (hcs->dwMagic != WINE_CRYPTCERTSTORE_MAGIC)
904             ret = FALSE;