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 "crypt32_private.h"
26 WINE_DEFAULT_DEBUG_CHANNEL(crypt
);
28 typedef struct _WINE_FILESTOREINFO
37 static void WINAPI
CRYPT_FileCloseStore(HCERTSTORE hCertStore
, DWORD dwFlags
)
39 WINE_FILESTOREINFO
*store
= hCertStore
;
41 TRACE("(%p, %08lx)\n", store
, dwFlags
);
43 CertSaveStore(store
->memStore
, X509_ASN_ENCODING
| PKCS_7_ASN_ENCODING
,
44 store
->type
, CERT_STORE_SAVE_TO_FILE
, store
->file
, 0);
45 CloseHandle(store
->file
);
49 static BOOL WINAPI
CRYPT_FileWriteCert(HCERTSTORE hCertStore
,
50 PCCERT_CONTEXT cert
, DWORD dwFlags
)
52 WINE_FILESTOREINFO
*store
= hCertStore
;
54 TRACE("(%p, %p, %ld)\n", hCertStore
, cert
, dwFlags
);
59 static BOOL WINAPI
CRYPT_FileDeleteCert(HCERTSTORE hCertStore
,
60 PCCERT_CONTEXT pCertContext
, DWORD dwFlags
)
62 WINE_FILESTOREINFO
*store
= hCertStore
;
64 TRACE("(%p, %p, %08lx)\n", hCertStore
, pCertContext
, dwFlags
);
69 static BOOL WINAPI
CRYPT_FileWriteCRL(HCERTSTORE hCertStore
,
70 PCCRL_CONTEXT crl
, DWORD dwFlags
)
72 WINE_FILESTOREINFO
*store
= hCertStore
;
74 TRACE("(%p, %p, %ld)\n", hCertStore
, crl
, dwFlags
);
79 static BOOL WINAPI
CRYPT_FileDeleteCRL(HCERTSTORE hCertStore
,
80 PCCRL_CONTEXT pCrlContext
, DWORD dwFlags
)
82 WINE_FILESTOREINFO
*store
= hCertStore
;
84 TRACE("(%p, %p, %08lx)\n", hCertStore
, pCrlContext
, dwFlags
);
89 static BOOL WINAPI
CRYPT_FileWriteCTL(HCERTSTORE hCertStore
,
90 PCCTL_CONTEXT ctl
, DWORD dwFlags
)
92 WINE_FILESTOREINFO
*store
= hCertStore
;
94 TRACE("(%p, %p, %ld)\n", hCertStore
, ctl
, dwFlags
);
99 static BOOL WINAPI
CRYPT_FileDeleteCTL(HCERTSTORE hCertStore
,
100 PCCTL_CONTEXT pCtlContext
, DWORD dwFlags
)
102 WINE_FILESTOREINFO
*store
= hCertStore
;
104 TRACE("(%p, %p, %08lx)\n", hCertStore
, pCtlContext
, dwFlags
);
109 static BOOL
CRYPT_ReadBlobFromFile(HANDLE file
, PCERT_BLOB blob
)
113 blob
->cbData
= GetFileSize(file
, NULL
);
116 blob
->pbData
= CryptMemAlloc(blob
->cbData
);
121 ret
= ReadFile(file
, blob
->pbData
, blob
->cbData
, &read
, NULL
) && read
== blob
->cbData
;
122 if (!ret
) CryptMemFree(blob
->pbData
);
130 static BOOL WINAPI
CRYPT_FileControl(HCERTSTORE hCertStore
, DWORD dwFlags
,
131 DWORD dwCtrlType
, void const *pvCtrlPara
)
133 WINE_FILESTOREINFO
*store
= hCertStore
;
136 TRACE("(%p, %08lx, %ld, %p)\n", hCertStore
, dwFlags
, dwCtrlType
,
141 case CERT_STORE_CTRL_RESYNC
:
142 store
->dirty
= FALSE
;
143 if (store
->type
== CERT_STORE_SAVE_AS_STORE
)
145 HCERTSTORE memStore
= CertOpenStore(CERT_STORE_PROV_MEMORY
, 0, 0,
146 CERT_STORE_CREATE_NEW_FLAG
, NULL
);
148 /* FIXME: if I could translate a handle to a path, I could use
149 * CryptQueryObject instead, but there's no API to do so yet.
151 ret
= CRYPT_ReadSerializedStoreFromFile(store
->file
, memStore
);
153 I_CertUpdateStore(store
->memStore
, memStore
, 0, 0);
154 CertCloseStore(memStore
, 0);
156 else if (store
->type
== CERT_STORE_SAVE_AS_PKCS7
)
158 CERT_BLOB blob
= { 0, NULL
};
160 ret
= CRYPT_ReadBlobFromFile(store
->file
, &blob
);
163 HCERTSTORE messageStore
;
165 ret
= CryptQueryObject(CERT_QUERY_OBJECT_BLOB
, &blob
,
166 CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED
,
167 CERT_QUERY_FORMAT_FLAG_BINARY
, 0, NULL
, NULL
, NULL
,
168 &messageStore
, NULL
, NULL
);
169 I_CertUpdateStore(store
->memStore
, messageStore
, 0, 0);
170 CertCloseStore(messageStore
, 0);
171 CryptMemFree(blob
.pbData
);
176 WARN("unknown type %ld\n", store
->type
);
180 case CERT_STORE_CTRL_COMMIT
:
181 if (!(store
->dwOpenFlags
& CERT_FILE_STORE_COMMIT_ENABLE_FLAG
))
183 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
186 else if (store
->dirty
)
187 ret
= CertSaveStore(store
->memStore
,
188 X509_ASN_ENCODING
| PKCS_7_ASN_ENCODING
,
189 store
->type
, CERT_STORE_SAVE_TO_FILE
, store
->file
, 0);
194 FIXME("%ld: stub\n", dwCtrlType
);
200 static void *fileProvFuncs
[] = {
201 CRYPT_FileCloseStore
,
202 NULL
, /* CERT_STORE_PROV_READ_CERT_FUNC */
204 CRYPT_FileDeleteCert
,
205 NULL
, /* CERT_STORE_PROV_SET_CERT_PROPERTY_FUNC */
206 NULL
, /* CERT_STORE_PROV_READ_CRL_FUNC */
209 NULL
, /* CERT_STORE_PROV_SET_CRL_PROPERTY_FUNC */
210 NULL
, /* CERT_STORE_PROV_READ_CTL_FUNC */
213 NULL
, /* CERT_STORE_PROV_SET_CTL_PROPERTY_FUNC */
217 static WINECRYPT_CERTSTORE
*CRYPT_CreateFileStore(DWORD dwFlags
,
218 HCERTSTORE memStore
, HANDLE file
, DWORD type
)
220 WINECRYPT_CERTSTORE
*store
= NULL
;
221 WINE_FILESTOREINFO
*info
= CryptMemAlloc(sizeof(WINE_FILESTOREINFO
));
225 CERT_STORE_PROV_INFO provInfo
= { 0 };
227 info
->dwOpenFlags
= dwFlags
;
228 info
->memStore
= memStore
;
232 provInfo
.cbSize
= sizeof(provInfo
);
233 provInfo
.cStoreProvFunc
= ARRAY_SIZE(fileProvFuncs
);
234 provInfo
.rgpvStoreProvFunc
= fileProvFuncs
;
235 provInfo
.hStoreProv
= info
;
236 store
= CRYPT_ProvCreateStore(dwFlags
, memStore
, &provInfo
);
241 WINECRYPT_CERTSTORE
*CRYPT_FileOpenStore(HCRYPTPROV hCryptProv
, DWORD dwFlags
,
244 WINECRYPT_CERTSTORE
*store
= NULL
;
245 HANDLE file
= (HANDLE
)pvPara
;
247 TRACE("(%Id, %08lx, %p)\n", hCryptProv
, dwFlags
, pvPara
);
251 SetLastError(ERROR_INVALID_HANDLE
);
254 if (dwFlags
& CERT_STORE_DELETE_FLAG
)
256 SetLastError(E_INVALIDARG
);
259 if ((dwFlags
& CERT_STORE_READONLY_FLAG
) &&
260 (dwFlags
& CERT_FILE_STORE_COMMIT_ENABLE_FLAG
))
262 SetLastError(E_INVALIDARG
);
266 if (DuplicateHandle(GetCurrentProcess(), (HANDLE
)pvPara
,
267 GetCurrentProcess(), &file
, dwFlags
& CERT_STORE_READONLY_FLAG
?
268 GENERIC_READ
: GENERIC_READ
| GENERIC_WRITE
, TRUE
, 0))
272 memStore
= CertOpenStore(CERT_STORE_PROV_MEMORY
, 0, 0,
273 CERT_STORE_CREATE_NEW_FLAG
, NULL
);
276 if (CRYPT_ReadSerializedStoreFromFile(file
, memStore
))
278 store
= CRYPT_CreateFileStore(dwFlags
, memStore
, file
,
279 CERT_STORE_SAVE_AS_STORE
);
280 /* File store doesn't need crypto provider, so close it */
282 !(dwFlags
& CERT_STORE_NO_CRYPT_RELEASE_FLAG
))
283 CryptReleaseContext(hCryptProv
, 0);
287 TRACE("returning %p\n", store
);
291 WINECRYPT_CERTSTORE
*CRYPT_FileNameOpenStoreW(HCRYPTPROV hCryptProv
,
292 DWORD dwFlags
, const void *pvPara
)
294 HCERTSTORE store
= 0;
295 LPCWSTR fileName
= pvPara
;
296 DWORD access
, create
;
299 TRACE("(%Id, %08lx, %s)\n", hCryptProv
, dwFlags
, debugstr_w(fileName
));
303 SetLastError(ERROR_PATH_NOT_FOUND
);
306 if ((dwFlags
& CERT_STORE_READONLY_FLAG
) &&
307 (dwFlags
& CERT_FILE_STORE_COMMIT_ENABLE_FLAG
))
309 SetLastError(E_INVALIDARG
);
313 access
= GENERIC_READ
;
314 if (dwFlags
& CERT_FILE_STORE_COMMIT_ENABLE_FLAG
)
315 access
|= GENERIC_WRITE
;
316 if (dwFlags
& CERT_STORE_CREATE_NEW_FLAG
)
318 else if (dwFlags
& CERT_STORE_OPEN_EXISTING_FLAG
)
319 create
= OPEN_EXISTING
;
321 create
= OPEN_ALWAYS
;
322 file
= CreateFileW(fileName
, access
, FILE_SHARE_READ
, NULL
, create
,
323 FILE_ATTRIBUTE_NORMAL
, NULL
);
324 if (file
!= INVALID_HANDLE_VALUE
)
326 HCERTSTORE memStore
= NULL
;
327 DWORD size
= GetFileSize(file
, NULL
), type
= 0;
329 /* If the file isn't empty, try to get the type from the file itself */
335 /* Close the file so CryptQueryObject can succeed.. */
337 ret
= CryptQueryObject(CERT_QUERY_OBJECT_FILE
, fileName
,
338 CERT_QUERY_CONTENT_FLAG_CERT
|
339 CERT_QUERY_CONTENT_FLAG_SERIALIZED_STORE
|
340 CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED
,
341 CERT_QUERY_FORMAT_FLAG_ALL
, 0, NULL
, &contentType
, NULL
,
342 &memStore
, NULL
, NULL
);
345 if (contentType
== CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED
)
346 type
= CERT_STORE_SAVE_AS_PKCS7
;
348 type
= CERT_STORE_SAVE_AS_STORE
;
349 /* and reopen the file. */
350 file
= CreateFileW(fileName
, access
, FILE_SHARE_READ
, NULL
,
351 create
, FILE_ATTRIBUTE_NORMAL
, NULL
);
356 LPCWSTR ext
= wcsrchr(fileName
, '.');
361 if (!lstrcmpiW(ext
, L
"spc") || !lstrcmpiW(ext
, L
"p7c"))
362 type
= CERT_STORE_SAVE_AS_PKCS7
;
365 type
= CERT_STORE_SAVE_AS_STORE
;
366 memStore
= CertOpenStore(CERT_STORE_PROV_MEMORY
, 0, 0,
367 CERT_STORE_CREATE_NEW_FLAG
, NULL
);
371 store
= CRYPT_CreateFileStore(dwFlags
, memStore
, file
, type
);
372 /* File store doesn't need crypto provider, so close it */
373 if (hCryptProv
&& !(dwFlags
& CERT_STORE_NO_CRYPT_RELEASE_FLAG
))
374 CryptReleaseContext(hCryptProv
, 0);
380 WINECRYPT_CERTSTORE
*CRYPT_FileNameOpenStoreA(HCRYPTPROV hCryptProv
,
381 DWORD dwFlags
, const void *pvPara
)
384 WINECRYPT_CERTSTORE
*ret
= NULL
;
386 TRACE("(%Id, %08lx, %s)\n", hCryptProv
, dwFlags
,
391 SetLastError(ERROR_FILE_NOT_FOUND
);
394 len
= MultiByteToWideChar(CP_ACP
, 0, pvPara
, -1, NULL
, 0);
397 LPWSTR storeName
= CryptMemAlloc(len
* sizeof(WCHAR
));
401 MultiByteToWideChar(CP_ACP
, 0, pvPara
, -1, storeName
, len
);
402 ret
= CRYPT_FileNameOpenStoreW(hCryptProv
, dwFlags
, storeName
);
403 CryptMemFree(storeName
);