2 * Copyright 2004-2007 Juan Lang
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
25 #include "wine/debug.h"
26 #include "crypt32_private.h"
28 WINE_DEFAULT_DEBUG_CHANNEL(crypt
);
30 typedef struct _WINE_PROVIDERSTORE
32 WINECRYPT_CERTSTORE hdr
;
33 DWORD dwStoreProvFlags
;
34 WINECRYPT_CERTSTORE
*memStore
;
35 HCERTSTOREPROV hStoreProv
;
36 PFN_CERT_STORE_PROV_CLOSE provCloseStore
;
37 PFN_CERT_STORE_PROV_WRITE_CERT provWriteCert
;
38 PFN_CERT_STORE_PROV_DELETE_CERT provDeleteCert
;
39 PFN_CERT_STORE_PROV_WRITE_CRL provWriteCrl
;
40 PFN_CERT_STORE_PROV_DELETE_CRL provDeleteCrl
;
41 PFN_CERT_STORE_PROV_WRITE_CTL provWriteCtl
;
42 PFN_CERT_STORE_PROV_DELETE_CTL provDeleteCtl
;
43 PFN_CERT_STORE_PROV_CONTROL provControl
;
46 static void ProvStore_addref(WINECRYPT_CERTSTORE
*store
)
48 LONG ref
= InterlockedIncrement(&store
->ref
);
49 TRACE("ref = %d\n", ref
);
52 static DWORD
ProvStore_release(WINECRYPT_CERTSTORE
*cert_store
, DWORD flags
)
54 WINE_PROVIDERSTORE
*store
= (WINE_PROVIDERSTORE
*)cert_store
;
58 FIXME("Unimplemented flags %x\n", flags
);
60 ref
= InterlockedDecrement(&store
->hdr
.ref
);
61 TRACE("(%p) ref=%d\n", store
, ref
);
66 if (store
->provCloseStore
)
67 store
->provCloseStore(store
->hStoreProv
, flags
);
68 if (!(store
->dwStoreProvFlags
& CERT_STORE_PROV_EXTERNAL_FLAG
))
69 store
->memStore
->vtbl
->release(store
->memStore
, flags
);
70 CRYPT_FreeStore(&store
->hdr
);
74 static void ProvStore_releaseContext(WINECRYPT_CERTSTORE
*store
, context_t
*context
)
76 /* As long as we don't have contexts properly stored (and hack around hCertStore
77 in add* and enum* functions), this function should never be called. */
81 static BOOL
ProvStore_addCert(WINECRYPT_CERTSTORE
*store
, context_t
*cert
,
82 context_t
*toReplace
, context_t
**ppStoreContext
, BOOL use_link
)
84 WINE_PROVIDERSTORE
*ps
= (WINE_PROVIDERSTORE
*)store
;
87 TRACE("(%p, %p, %p, %p)\n", store
, cert
, toReplace
, ppStoreContext
);
90 ret
= ps
->memStore
->vtbl
->certs
.addContext(ps
->memStore
, cert
, toReplace
,
91 ppStoreContext
, TRUE
);
95 if (ps
->provWriteCert
)
96 ret
= ps
->provWriteCert(ps
->hStoreProv
, context_ptr(cert
), CERT_STORE_PROV_WRITE_ADD_FLAG
);
98 ret
= ps
->memStore
->vtbl
->certs
.addContext(ps
->memStore
, cert
, NULL
,
99 ppStoreContext
, TRUE
);
101 /* dirty trick: replace the returned context's hCertStore with
104 if (ret
&& ppStoreContext
)
105 (*(cert_t
**)ppStoreContext
)->ctx
.hCertStore
= store
;
109 static context_t
*ProvStore_enumCert(WINECRYPT_CERTSTORE
*store
, context_t
*prev
)
111 WINE_PROVIDERSTORE
*ps
= (WINE_PROVIDERSTORE
*)store
;
114 ret
= (cert_t
*)ps
->memStore
->vtbl
->certs
.enumContext(ps
->memStore
, prev
);
118 /* same dirty trick: replace the returned context's hCertStore with
121 ret
->ctx
.hCertStore
= store
;
125 static BOOL
ProvStore_deleteCert(WINECRYPT_CERTSTORE
*store
, context_t
*context
)
127 WINE_PROVIDERSTORE
*ps
= (WINE_PROVIDERSTORE
*)store
;
130 TRACE("(%p, %p)\n", store
, context
);
132 if (ps
->provDeleteCert
)
133 ret
= ps
->provDeleteCert(ps
->hStoreProv
, context_ptr(context
), 0);
135 ret
= ps
->memStore
->vtbl
->certs
.delete(ps
->memStore
, context
);
139 static BOOL
ProvStore_addCRL(WINECRYPT_CERTSTORE
*store
, context_t
*crl
,
140 context_t
*toReplace
, context_t
**ppStoreContext
, BOOL use_link
)
142 WINE_PROVIDERSTORE
*ps
= (WINE_PROVIDERSTORE
*)store
;
145 TRACE("(%p, %p, %p, %p)\n", store
, crl
, toReplace
, ppStoreContext
);
148 ret
= ps
->memStore
->vtbl
->crls
.addContext(ps
->memStore
, crl
, toReplace
,
149 ppStoreContext
, TRUE
);
152 if (ps
->hdr
.dwOpenFlags
& CERT_STORE_READONLY_FLAG
)
154 SetLastError(ERROR_ACCESS_DENIED
);
160 if (ps
->provWriteCrl
)
161 ret
= ps
->provWriteCrl(ps
->hStoreProv
, context_ptr(crl
),
162 CERT_STORE_PROV_WRITE_ADD_FLAG
);
164 ret
= ps
->memStore
->vtbl
->crls
.addContext(ps
->memStore
, crl
, NULL
,
165 ppStoreContext
, TRUE
);
168 /* dirty trick: replace the returned context's hCertStore with
171 if (ret
&& ppStoreContext
)
172 (*(crl_t
**)ppStoreContext
)->ctx
.hCertStore
= store
;
176 static context_t
*ProvStore_enumCRL(WINECRYPT_CERTSTORE
*store
, context_t
*prev
)
178 WINE_PROVIDERSTORE
*ps
= (WINE_PROVIDERSTORE
*)store
;
181 ret
= (crl_t
*)ps
->memStore
->vtbl
->crls
.enumContext(ps
->memStore
, prev
);
185 /* same dirty trick: replace the returned context's hCertStore with
188 ret
->ctx
.hCertStore
= store
;
192 static BOOL
ProvStore_deleteCRL(WINECRYPT_CERTSTORE
*store
, context_t
*crl
)
194 WINE_PROVIDERSTORE
*ps
= (WINE_PROVIDERSTORE
*)store
;
197 TRACE("(%p, %p)\n", store
, crl
);
199 if (ps
->provDeleteCrl
)
200 ret
= ps
->provDeleteCrl(ps
->hStoreProv
, context_ptr(crl
), 0);
202 ret
= ps
->memStore
->vtbl
->crls
.delete(ps
->memStore
, crl
);
206 static BOOL
ProvStore_addCTL(WINECRYPT_CERTSTORE
*store
, context_t
*ctl
,
207 context_t
*toReplace
, context_t
**ppStoreContext
, BOOL use_link
)
209 WINE_PROVIDERSTORE
*ps
= (WINE_PROVIDERSTORE
*)store
;
212 TRACE("(%p, %p, %p, %p)\n", store
, ctl
, toReplace
, ppStoreContext
);
215 ret
= ps
->memStore
->vtbl
->ctls
.addContext(ps
->memStore
, ctl
, toReplace
,
216 ppStoreContext
, TRUE
);
219 if (ps
->hdr
.dwOpenFlags
& CERT_STORE_READONLY_FLAG
)
221 SetLastError(ERROR_ACCESS_DENIED
);
227 if (ps
->provWriteCtl
)
228 ret
= ps
->provWriteCtl(ps
->hStoreProv
, context_ptr(ctl
),
229 CERT_STORE_PROV_WRITE_ADD_FLAG
);
231 ret
= ps
->memStore
->vtbl
->ctls
.addContext(ps
->memStore
, ctl
, NULL
,
232 ppStoreContext
, TRUE
);
235 /* dirty trick: replace the returned context's hCertStore with
238 if (ret
&& ppStoreContext
)
239 (*(ctl_t
**)ppStoreContext
)->ctx
.hCertStore
= store
;
243 static context_t
*ProvStore_enumCTL(WINECRYPT_CERTSTORE
*store
, context_t
*prev
)
245 WINE_PROVIDERSTORE
*ps
= (WINE_PROVIDERSTORE
*)store
;
248 ret
= (ctl_t
*)ps
->memStore
->vtbl
->ctls
.enumContext(ps
->memStore
, prev
);
252 /* same dirty trick: replace the returned context's hCertStore with
255 ret
->ctx
.hCertStore
= store
;
259 static BOOL
ProvStore_deleteCTL(WINECRYPT_CERTSTORE
*store
, context_t
*ctl
)
261 WINE_PROVIDERSTORE
*ps
= (WINE_PROVIDERSTORE
*)store
;
264 TRACE("(%p, %p)\n", store
, ctl
);
266 if (ps
->provDeleteCtl
)
267 ret
= ps
->provDeleteCtl(ps
->hStoreProv
, context_ptr(ctl
), 0);
269 ret
= ps
->memStore
->vtbl
->ctls
.delete(ps
->memStore
, ctl
);
273 static BOOL
ProvStore_control(WINECRYPT_CERTSTORE
*cert_store
, DWORD dwFlags
, DWORD dwCtrlType
, void const *pvCtrlPara
)
275 WINE_PROVIDERSTORE
*store
= (WINE_PROVIDERSTORE
*)cert_store
;
278 TRACE("(%p, %08x, %d, %p)\n", store
, dwFlags
, dwCtrlType
,
281 if (store
->provControl
)
282 ret
= store
->provControl(store
->hStoreProv
, dwFlags
, dwCtrlType
,
287 static const store_vtbl_t ProvStoreVtbl
= {
290 ProvStore_releaseContext
,
307 WINECRYPT_CERTSTORE
*CRYPT_ProvCreateStore(DWORD dwFlags
,
308 WINECRYPT_CERTSTORE
*memStore
, const CERT_STORE_PROV_INFO
*pProvInfo
)
310 WINE_PROVIDERSTORE
*ret
= CryptMemAlloc(sizeof(WINE_PROVIDERSTORE
));
314 CRYPT_InitStore(&ret
->hdr
, dwFlags
, StoreTypeProvider
, &ProvStoreVtbl
);
315 ret
->dwStoreProvFlags
= pProvInfo
->dwStoreProvFlags
;
316 if (ret
->dwStoreProvFlags
& CERT_STORE_PROV_EXTERNAL_FLAG
)
318 CertCloseStore(memStore
, 0);
319 ret
->memStore
= NULL
;
322 ret
->memStore
= memStore
;
323 ret
->hStoreProv
= pProvInfo
->hStoreProv
;
324 if (pProvInfo
->cStoreProvFunc
> CERT_STORE_PROV_CLOSE_FUNC
)
325 ret
->provCloseStore
=
326 pProvInfo
->rgpvStoreProvFunc
[CERT_STORE_PROV_CLOSE_FUNC
];
328 ret
->provCloseStore
= NULL
;
329 if (pProvInfo
->cStoreProvFunc
>
330 CERT_STORE_PROV_WRITE_CERT_FUNC
)
331 ret
->provWriteCert
= pProvInfo
->rgpvStoreProvFunc
[
332 CERT_STORE_PROV_WRITE_CERT_FUNC
];
334 ret
->provWriteCert
= NULL
;
335 if (pProvInfo
->cStoreProvFunc
>
336 CERT_STORE_PROV_DELETE_CERT_FUNC
)
337 ret
->provDeleteCert
= pProvInfo
->rgpvStoreProvFunc
[
338 CERT_STORE_PROV_DELETE_CERT_FUNC
];
340 ret
->provDeleteCert
= NULL
;
341 if (pProvInfo
->cStoreProvFunc
>
342 CERT_STORE_PROV_WRITE_CRL_FUNC
)
343 ret
->provWriteCrl
= pProvInfo
->rgpvStoreProvFunc
[
344 CERT_STORE_PROV_WRITE_CRL_FUNC
];
346 ret
->provWriteCrl
= NULL
;
347 if (pProvInfo
->cStoreProvFunc
>
348 CERT_STORE_PROV_DELETE_CRL_FUNC
)
349 ret
->provDeleteCrl
= pProvInfo
->rgpvStoreProvFunc
[
350 CERT_STORE_PROV_DELETE_CRL_FUNC
];
352 ret
->provDeleteCrl
= NULL
;
353 if (pProvInfo
->cStoreProvFunc
>
354 CERT_STORE_PROV_WRITE_CTL_FUNC
)
355 ret
->provWriteCtl
= pProvInfo
->rgpvStoreProvFunc
[
356 CERT_STORE_PROV_WRITE_CTL_FUNC
];
358 ret
->provWriteCtl
= NULL
;
359 if (pProvInfo
->cStoreProvFunc
>
360 CERT_STORE_PROV_DELETE_CTL_FUNC
)
361 ret
->provDeleteCtl
= pProvInfo
->rgpvStoreProvFunc
[
362 CERT_STORE_PROV_DELETE_CTL_FUNC
];
364 ret
->provDeleteCtl
= NULL
;
365 if (pProvInfo
->cStoreProvFunc
>
366 CERT_STORE_PROV_CONTROL_FUNC
)
367 ret
->provControl
= pProvInfo
->rgpvStoreProvFunc
[
368 CERT_STORE_PROV_CONTROL_FUNC
];
370 ret
->provControl
= NULL
;
372 return (WINECRYPT_CERTSTORE
*)ret
;
375 WINECRYPT_CERTSTORE
*CRYPT_ProvOpenStore(LPCSTR lpszStoreProvider
,
376 DWORD dwEncodingType
, HCRYPTPROV hCryptProv
, DWORD dwFlags
, const void *pvPara
)
378 static HCRYPTOIDFUNCSET set
= NULL
;
379 PFN_CERT_DLL_OPEN_STORE_PROV_FUNC provOpenFunc
;
380 HCRYPTOIDFUNCADDR hFunc
;
381 WINECRYPT_CERTSTORE
*ret
= NULL
;
384 set
= CryptInitOIDFunctionSet(CRYPT_OID_OPEN_STORE_PROV_FUNC
, 0);
385 CryptGetOIDFunctionAddress(set
, dwEncodingType
, lpszStoreProvider
, 0,
386 (void **)&provOpenFunc
, &hFunc
);
389 CERT_STORE_PROV_INFO provInfo
= { 0 };
391 provInfo
.cbSize
= sizeof(provInfo
);
392 if (dwFlags
& CERT_STORE_DELETE_FLAG
)
393 provOpenFunc(lpszStoreProvider
, dwEncodingType
, hCryptProv
,
394 dwFlags
, pvPara
, NULL
, &provInfo
);
399 memStore
= CertOpenStore(CERT_STORE_PROV_MEMORY
, 0, 0,
400 CERT_STORE_CREATE_NEW_FLAG
, NULL
);
403 if (provOpenFunc(lpszStoreProvider
, dwEncodingType
, hCryptProv
,
404 dwFlags
, pvPara
, memStore
, &provInfo
))
405 ret
= CRYPT_ProvCreateStore(dwFlags
, memStore
, &provInfo
);
407 CertCloseStore(memStore
, 0);
410 CryptFreeOIDFunctionAddress(hFunc
, 0);
413 SetLastError(ERROR_FILE_NOT_FOUND
);