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
23 #include "wine/debug.h"
24 #include "wine/unicode.h"
25 #include "crypt32_private.h"
27 WINE_DEFAULT_DEBUG_CHANNEL(crypt
);
29 typedef struct _WINE_FILESTOREINFO
36 } WINE_FILESTOREINFO
, *PWINE_FILESTOREINFO
;
38 static void WINAPI
CRYPT_FileCloseStore(HCERTSTORE hCertStore
, DWORD dwFlags
)
40 PWINE_FILESTOREINFO store
= (PWINE_FILESTOREINFO
)hCertStore
;
42 TRACE("(%p, %08x)\n", store
, dwFlags
);
44 CertSaveStore(store
->memStore
, X509_ASN_ENCODING
| PKCS_7_ASN_ENCODING
,
45 store
->type
, CERT_STORE_SAVE_TO_FILE
, store
->file
, 0);
46 CertCloseStore(store
->memStore
, dwFlags
);
47 CloseHandle(store
->file
);
51 static BOOL WINAPI
CRYPT_FileWriteCert(HCERTSTORE hCertStore
,
52 PCCERT_CONTEXT cert
, DWORD dwFlags
)
54 PWINE_FILESTOREINFO store
= (PWINE_FILESTOREINFO
)hCertStore
;
56 TRACE("(%p, %p, %d)\n", hCertStore
, cert
, dwFlags
);
61 static BOOL WINAPI
CRYPT_FileDeleteCert(HCERTSTORE hCertStore
,
62 PCCERT_CONTEXT pCertContext
, DWORD dwFlags
)
64 PWINE_FILESTOREINFO store
= (PWINE_FILESTOREINFO
)hCertStore
;
66 TRACE("(%p, %p, %08x)\n", hCertStore
, pCertContext
, dwFlags
);
71 static BOOL WINAPI
CRYPT_FileWriteCRL(HCERTSTORE hCertStore
,
72 PCCRL_CONTEXT crl
, DWORD dwFlags
)
74 PWINE_FILESTOREINFO store
= (PWINE_FILESTOREINFO
)hCertStore
;
76 TRACE("(%p, %p, %d)\n", hCertStore
, crl
, dwFlags
);
81 static BOOL WINAPI
CRYPT_FileDeleteCRL(HCERTSTORE hCertStore
,
82 PCCRL_CONTEXT pCrlContext
, DWORD dwFlags
)
84 PWINE_FILESTOREINFO store
= (PWINE_FILESTOREINFO
)hCertStore
;
86 TRACE("(%p, %p, %08x)\n", hCertStore
, pCrlContext
, dwFlags
);
91 static BOOL
CRYPT_ReadBlobFromFile(HANDLE file
, PCERT_BLOB blob
)
95 blob
->cbData
= GetFileSize(file
, NULL
);
98 blob
->pbData
= CryptMemAlloc(blob
->cbData
);
103 ret
= ReadFile(file
, blob
->pbData
, blob
->cbData
, &read
, NULL
);
109 static BOOL WINAPI
CRYPT_FileControl(HCERTSTORE hCertStore
, DWORD dwFlags
,
110 DWORD dwCtrlType
, void const *pvCtrlPara
)
112 PWINE_FILESTOREINFO store
= (PWINE_FILESTOREINFO
)hCertStore
;
115 TRACE("(%p, %08x, %d, %p)\n", hCertStore
, dwFlags
, dwCtrlType
,
120 case CERT_STORE_CTRL_RESYNC
:
121 CRYPT_EmptyStore(store
->memStore
);
122 store
->dirty
= FALSE
;
123 if (store
->type
== CERT_STORE_SAVE_AS_STORE
)
124 ret
= CRYPT_ReadSerializedStoreFromFile(store
->file
,
126 else if (store
->type
== CERT_STORE_SAVE_AS_PKCS7
)
128 CERT_BLOB blob
= { 0, NULL
};
130 ret
= CRYPT_ReadBlobFromFile(store
->file
, &blob
);
133 HCERTSTORE messageStore
;
135 ret
= CryptQueryObject(CERT_QUERY_OBJECT_BLOB
, &blob
,
136 CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED
,
137 CERT_QUERY_FORMAT_FLAG_BINARY
, 0, NULL
, NULL
, NULL
,
138 &messageStore
, NULL
, NULL
);
141 PCCERT_CONTEXT cert
= NULL
;
142 PCCRL_CONTEXT crl
= NULL
;
145 cert
= CertEnumCertificatesInStore(messageStore
, cert
);
147 CertAddCertificateContextToStore(store
->memStore
,
148 cert
, CERT_STORE_ADD_ALWAYS
, NULL
);
151 crl
= CertEnumCRLsInStore(messageStore
, crl
);
153 CertAddCRLContextToStore(store
->memStore
, crl
,
154 CERT_STORE_ADD_ALWAYS
, NULL
);
157 CryptMemFree(blob
.pbData
);
162 WARN("unknown type %d\n", store
->type
);
166 case CERT_STORE_CTRL_COMMIT
:
167 if (!(store
->dwOpenFlags
& CERT_FILE_STORE_COMMIT_ENABLE_FLAG
))
169 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
172 else if (store
->dirty
)
173 ret
= CertSaveStore(store
->memStore
,
174 X509_ASN_ENCODING
| PKCS_7_ASN_ENCODING
,
175 store
->type
, CERT_STORE_SAVE_TO_FILE
, store
->file
, 0);
180 FIXME("%d: stub\n", dwCtrlType
);
186 static void *fileProvFuncs
[] = {
187 CRYPT_FileCloseStore
,
188 NULL
, /* CERT_STORE_PROV_READ_CERT_FUNC */
190 CRYPT_FileDeleteCert
,
191 NULL
, /* CERT_STORE_PROV_SET_CERT_PROPERTY_FUNC */
192 NULL
, /* CERT_STORE_PROV_READ_CRL_FUNC */
195 NULL
, /* CERT_STORE_PROV_SET_CRL_PROPERTY_FUNC */
196 NULL
, /* CERT_STORE_PROV_READ_CTL_FUNC */
197 NULL
, /* CERT_STORE_PROV_WRITE_CTL_FUNC */
198 NULL
, /* CERT_STORE_PROV_DELETE_CTL_FUNC */
199 NULL
, /* CERT_STORE_PROV_SET_CTL_PROPERTY_FUNC */
203 static PWINECRYPT_CERTSTORE
CRYPT_CreateFileStore(DWORD dwFlags
,
204 HCERTSTORE memStore
, HANDLE file
, DWORD type
)
206 PWINECRYPT_CERTSTORE store
= NULL
;
207 PWINE_FILESTOREINFO info
= CryptMemAlloc(sizeof(WINE_FILESTOREINFO
));
211 CERT_STORE_PROV_INFO provInfo
= { 0 };
213 info
->dwOpenFlags
= dwFlags
;
214 info
->memStore
= memStore
;
218 provInfo
.cbSize
= sizeof(provInfo
);
219 provInfo
.cStoreProvFunc
= sizeof(fileProvFuncs
) /
220 sizeof(fileProvFuncs
[0]);
221 provInfo
.rgpvStoreProvFunc
= fileProvFuncs
;
222 provInfo
.hStoreProv
= info
;
223 store
= CRYPT_ProvCreateStore(dwFlags
, memStore
, &provInfo
);
228 PWINECRYPT_CERTSTORE
CRYPT_FileOpenStore(HCRYPTPROV hCryptProv
, DWORD dwFlags
,
231 PWINECRYPT_CERTSTORE store
= NULL
;
232 HANDLE file
= (HANDLE
)pvPara
;
234 TRACE("(%ld, %08x, %p)\n", hCryptProv
, dwFlags
, pvPara
);
238 SetLastError(ERROR_INVALID_HANDLE
);
241 if (dwFlags
& CERT_STORE_DELETE_FLAG
)
243 SetLastError(E_INVALIDARG
);
246 if ((dwFlags
& CERT_STORE_READONLY_FLAG
) &&
247 (dwFlags
& CERT_FILE_STORE_COMMIT_ENABLE_FLAG
))
249 SetLastError(E_INVALIDARG
);
253 if (DuplicateHandle(GetCurrentProcess(), (HANDLE
)pvPara
,
254 GetCurrentProcess(), &file
, dwFlags
& CERT_STORE_READONLY_FLAG
?
255 GENERIC_READ
: GENERIC_READ
| GENERIC_WRITE
, TRUE
, 0))
259 memStore
= CertOpenStore(CERT_STORE_PROV_MEMORY
, 0, 0,
260 CERT_STORE_CREATE_NEW_FLAG
, NULL
);
263 if (CRYPT_ReadSerializedStoreFromFile(file
, memStore
))
265 store
= CRYPT_CreateFileStore(dwFlags
, memStore
, file
,
266 CERT_STORE_SAVE_AS_STORE
);
267 /* File store doesn't need crypto provider, so close it */
269 !(dwFlags
& CERT_STORE_NO_CRYPT_RELEASE_FLAG
))
270 CryptReleaseContext(hCryptProv
, 0);
274 TRACE("returning %p\n", store
);
278 PWINECRYPT_CERTSTORE
CRYPT_FileNameOpenStoreW(HCRYPTPROV hCryptProv
,
279 DWORD dwFlags
, const void *pvPara
)
281 HCERTSTORE store
= 0;
282 LPCWSTR fileName
= (LPCWSTR
)pvPara
;
283 DWORD access
, create
;
286 TRACE("(%ld, %08x, %s)\n", hCryptProv
, dwFlags
, debugstr_w(fileName
));
290 SetLastError(ERROR_PATH_NOT_FOUND
);
293 if ((dwFlags
& CERT_STORE_READONLY_FLAG
) &&
294 (dwFlags
& CERT_FILE_STORE_COMMIT_ENABLE_FLAG
))
296 SetLastError(E_INVALIDARG
);
300 access
= GENERIC_READ
;
301 if (dwFlags
& CERT_FILE_STORE_COMMIT_ENABLE_FLAG
)
302 access
|= GENERIC_WRITE
;
303 if (dwFlags
& CERT_STORE_CREATE_NEW_FLAG
)
305 else if (dwFlags
& CERT_STORE_OPEN_EXISTING_FLAG
)
306 create
= OPEN_EXISTING
;
308 create
= OPEN_ALWAYS
;
309 file
= CreateFileW(fileName
, access
, FILE_SHARE_READ
, NULL
, create
,
310 FILE_ATTRIBUTE_NORMAL
, NULL
);
311 if (file
!= INVALID_HANDLE_VALUE
)
313 HCERTSTORE memStore
= NULL
;
314 DWORD size
= GetFileSize(file
, NULL
), type
= 0;
316 /* If the file isn't empty, try to get the type from the file itself */
322 /* Close the file so CryptQueryObject can succeed.. */
324 ret
= CryptQueryObject(CERT_QUERY_OBJECT_FILE
, fileName
,
325 CERT_QUERY_CONTENT_FLAG_CERT
|
326 CERT_QUERY_CONTENT_FLAG_SERIALIZED_STORE
|
327 CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED
,
328 CERT_QUERY_FORMAT_FLAG_BINARY
, 0, NULL
, &contentType
, NULL
,
329 &memStore
, NULL
, NULL
);
332 if (contentType
== CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED
)
333 type
= CERT_STORE_SAVE_AS_PKCS7
;
335 type
= CERT_STORE_SAVE_AS_STORE
;
336 /* and reopen the file. */
337 file
= CreateFileW(fileName
, access
, FILE_SHARE_READ
, NULL
,
338 create
, FILE_ATTRIBUTE_NORMAL
, NULL
);
343 static const WCHAR spc
[] = { 's','p','c',0 };
344 static const WCHAR p7c
[] = { 'p','7','c',0 };
345 LPCWSTR ext
= strrchrW(fileName
, '.');
350 if (!lstrcmpiW(ext
, spc
) || !lstrcmpiW(ext
, p7c
))
351 type
= CERT_STORE_SAVE_AS_PKCS7
;
354 type
= CERT_STORE_SAVE_AS_STORE
;
355 memStore
= CertOpenStore(CERT_STORE_PROV_MEMORY
, 0, 0,
356 CERT_STORE_CREATE_NEW_FLAG
, NULL
);
360 store
= CRYPT_CreateFileStore(dwFlags
, memStore
, file
, type
);
361 /* File store doesn't need crypto provider, so close it */
362 if (hCryptProv
&& !(dwFlags
& CERT_STORE_NO_CRYPT_RELEASE_FLAG
))
363 CryptReleaseContext(hCryptProv
, 0);
366 return (PWINECRYPT_CERTSTORE
)store
;
369 PWINECRYPT_CERTSTORE
CRYPT_FileNameOpenStoreA(HCRYPTPROV hCryptProv
,
370 DWORD dwFlags
, const void *pvPara
)
373 PWINECRYPT_CERTSTORE ret
= NULL
;
375 TRACE("(%ld, %08x, %s)\n", hCryptProv
, dwFlags
,
376 debugstr_a((LPCSTR
)pvPara
));
380 SetLastError(ERROR_FILE_NOT_FOUND
);
383 len
= MultiByteToWideChar(CP_ACP
, 0, (LPCSTR
)pvPara
, -1, NULL
, 0);
386 LPWSTR storeName
= CryptMemAlloc(len
* sizeof(WCHAR
));
390 MultiByteToWideChar(CP_ACP
, 0, (LPCSTR
)pvPara
, -1, storeName
, len
);
391 ret
= CRYPT_FileNameOpenStoreW(hCryptProv
, dwFlags
, storeName
);
392 CryptMemFree(storeName
);