Add AppDefaults app selection to control panel
[wine/gsoc-2012-control.git] / dlls / crypt32 / filestore.c
blob52e575271b040f33c572541e5ee700c73cbe1679
1 /*
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
18 #include <stdarg.h>
19 #include "windef.h"
20 #include "winbase.h"
21 #include "wincrypt.h"
22 #include "winnls.h"
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
31 DWORD dwOpenFlags;
32 HCERTSTORE memStore;
33 HANDLE file;
34 DWORD type;
35 BOOL dirty;
36 } WINE_FILESTOREINFO, *PWINE_FILESTOREINFO;
38 static void WINAPI CRYPT_FileCloseStore(HCERTSTORE hCertStore, DWORD dwFlags)
40 PWINE_FILESTOREINFO store = hCertStore;
42 TRACE("(%p, %08x)\n", store, dwFlags);
43 if (store->dirty)
44 CertSaveStore(store->memStore, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
45 store->type, CERT_STORE_SAVE_TO_FILE, store->file, 0);
46 CloseHandle(store->file);
47 CryptMemFree(store);
50 static BOOL WINAPI CRYPT_FileWriteCert(HCERTSTORE hCertStore,
51 PCCERT_CONTEXT cert, DWORD dwFlags)
53 PWINE_FILESTOREINFO store = hCertStore;
55 TRACE("(%p, %p, %d)\n", hCertStore, cert, dwFlags);
56 store->dirty = TRUE;
57 return TRUE;
60 static BOOL WINAPI CRYPT_FileDeleteCert(HCERTSTORE hCertStore,
61 PCCERT_CONTEXT pCertContext, DWORD dwFlags)
63 PWINE_FILESTOREINFO store = hCertStore;
65 TRACE("(%p, %p, %08x)\n", hCertStore, pCertContext, dwFlags);
66 store->dirty = TRUE;
67 return TRUE;
70 static BOOL WINAPI CRYPT_FileWriteCRL(HCERTSTORE hCertStore,
71 PCCRL_CONTEXT crl, DWORD dwFlags)
73 PWINE_FILESTOREINFO store = hCertStore;
75 TRACE("(%p, %p, %d)\n", hCertStore, crl, dwFlags);
76 store->dirty = TRUE;
77 return TRUE;
80 static BOOL WINAPI CRYPT_FileDeleteCRL(HCERTSTORE hCertStore,
81 PCCRL_CONTEXT pCrlContext, DWORD dwFlags)
83 PWINE_FILESTOREINFO store = hCertStore;
85 TRACE("(%p, %p, %08x)\n", hCertStore, pCrlContext, dwFlags);
86 store->dirty = TRUE;
87 return TRUE;
90 static BOOL WINAPI CRYPT_FileWriteCTL(HCERTSTORE hCertStore,
91 PCCTL_CONTEXT ctl, DWORD dwFlags)
93 PWINE_FILESTOREINFO store = hCertStore;
95 TRACE("(%p, %p, %d)\n", hCertStore, ctl, dwFlags);
96 store->dirty = TRUE;
97 return TRUE;
100 static BOOL WINAPI CRYPT_FileDeleteCTL(HCERTSTORE hCertStore,
101 PCCTL_CONTEXT pCtlContext, DWORD dwFlags)
103 PWINE_FILESTOREINFO store = hCertStore;
105 TRACE("(%p, %p, %08x)\n", hCertStore, pCtlContext, dwFlags);
106 store->dirty = TRUE;
107 return TRUE;
110 static BOOL CRYPT_ReadBlobFromFile(HANDLE file, PCERT_BLOB blob)
112 BOOL ret = TRUE;
114 blob->cbData = GetFileSize(file, NULL);
115 if (blob->cbData)
117 blob->pbData = CryptMemAlloc(blob->cbData);
118 if (blob->pbData)
120 DWORD read;
122 ret = ReadFile(file, blob->pbData, blob->cbData, &read, NULL);
125 return ret;
128 static BOOL WINAPI CRYPT_FileControl(HCERTSTORE hCertStore, DWORD dwFlags,
129 DWORD dwCtrlType, void const *pvCtrlPara)
131 PWINE_FILESTOREINFO store = hCertStore;
132 BOOL ret;
134 TRACE("(%p, %08x, %d, %p)\n", hCertStore, dwFlags, dwCtrlType,
135 pvCtrlPara);
137 switch (dwCtrlType)
139 case CERT_STORE_CTRL_RESYNC:
140 store->dirty = FALSE;
141 if (store->type == CERT_STORE_SAVE_AS_STORE)
143 HCERTSTORE memStore = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
144 CERT_STORE_CREATE_NEW_FLAG, NULL);
146 /* FIXME: if I could translate a handle to a path, I could use
147 * CryptQueryObject instead, but there's no API to do so yet.
149 ret = CRYPT_ReadSerializedStoreFromFile(store->file, memStore);
150 if (ret)
151 I_CertUpdateStore(store->memStore, memStore, 0, 0);
152 CertCloseStore(memStore, 0);
154 else if (store->type == CERT_STORE_SAVE_AS_PKCS7)
156 CERT_BLOB blob = { 0, NULL };
158 ret = CRYPT_ReadBlobFromFile(store->file, &blob);
159 if (ret)
161 HCERTSTORE messageStore;
163 ret = CryptQueryObject(CERT_QUERY_OBJECT_BLOB, &blob,
164 CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED,
165 CERT_QUERY_FORMAT_FLAG_BINARY, 0, NULL, NULL, NULL,
166 &messageStore, NULL, NULL);
167 I_CertUpdateStore(store->memStore, messageStore, 0, 0);
168 CertCloseStore(messageStore, 0);
169 CryptMemFree(blob.pbData);
172 else
174 WARN("unknown type %d\n", store->type);
175 ret = FALSE;
177 break;
178 case CERT_STORE_CTRL_COMMIT:
179 if (!(store->dwOpenFlags & CERT_FILE_STORE_COMMIT_ENABLE_FLAG))
181 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
182 ret = FALSE;
184 else if (store->dirty)
185 ret = CertSaveStore(store->memStore,
186 X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
187 store->type, CERT_STORE_SAVE_TO_FILE, store->file, 0);
188 else
189 ret = TRUE;
190 break;
191 default:
192 FIXME("%d: stub\n", dwCtrlType);
193 ret = FALSE;
195 return ret;
198 static void *fileProvFuncs[] = {
199 CRYPT_FileCloseStore,
200 NULL, /* CERT_STORE_PROV_READ_CERT_FUNC */
201 CRYPT_FileWriteCert,
202 CRYPT_FileDeleteCert,
203 NULL, /* CERT_STORE_PROV_SET_CERT_PROPERTY_FUNC */
204 NULL, /* CERT_STORE_PROV_READ_CRL_FUNC */
205 CRYPT_FileWriteCRL,
206 CRYPT_FileDeleteCRL,
207 NULL, /* CERT_STORE_PROV_SET_CRL_PROPERTY_FUNC */
208 NULL, /* CERT_STORE_PROV_READ_CTL_FUNC */
209 CRYPT_FileWriteCTL,
210 CRYPT_FileDeleteCTL,
211 NULL, /* CERT_STORE_PROV_SET_CTL_PROPERTY_FUNC */
212 CRYPT_FileControl,
215 static PWINECRYPT_CERTSTORE CRYPT_CreateFileStore(DWORD dwFlags,
216 HCERTSTORE memStore, HANDLE file, DWORD type)
218 PWINECRYPT_CERTSTORE store = NULL;
219 PWINE_FILESTOREINFO info = CryptMemAlloc(sizeof(WINE_FILESTOREINFO));
221 if (info)
223 CERT_STORE_PROV_INFO provInfo = { 0 };
225 info->dwOpenFlags = dwFlags;
226 info->memStore = memStore;
227 info->file = file;
228 info->type = type;
229 info->dirty = FALSE;
230 provInfo.cbSize = sizeof(provInfo);
231 provInfo.cStoreProvFunc = sizeof(fileProvFuncs) /
232 sizeof(fileProvFuncs[0]);
233 provInfo.rgpvStoreProvFunc = fileProvFuncs;
234 provInfo.hStoreProv = info;
235 store = CRYPT_ProvCreateStore(dwFlags, memStore, &provInfo);
237 return store;
240 PWINECRYPT_CERTSTORE CRYPT_FileOpenStore(HCRYPTPROV hCryptProv, DWORD dwFlags,
241 const void *pvPara)
243 PWINECRYPT_CERTSTORE store = NULL;
244 HANDLE file = (HANDLE)pvPara;
246 TRACE("(%ld, %08x, %p)\n", hCryptProv, dwFlags, pvPara);
248 if (!pvPara)
250 SetLastError(ERROR_INVALID_HANDLE);
251 return NULL;
253 if (dwFlags & CERT_STORE_DELETE_FLAG)
255 SetLastError(E_INVALIDARG);
256 return NULL;
258 if ((dwFlags & CERT_STORE_READONLY_FLAG) &&
259 (dwFlags & CERT_FILE_STORE_COMMIT_ENABLE_FLAG))
261 SetLastError(E_INVALIDARG);
262 return NULL;
265 if (DuplicateHandle(GetCurrentProcess(), (HANDLE)pvPara,
266 GetCurrentProcess(), &file, dwFlags & CERT_STORE_READONLY_FLAG ?
267 GENERIC_READ : GENERIC_READ | GENERIC_WRITE, TRUE, 0))
269 HCERTSTORE memStore;
271 memStore = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
272 CERT_STORE_CREATE_NEW_FLAG, NULL);
273 if (memStore)
275 if (CRYPT_ReadSerializedStoreFromFile(file, memStore))
277 store = CRYPT_CreateFileStore(dwFlags, memStore, file,
278 CERT_STORE_SAVE_AS_STORE);
279 /* File store doesn't need crypto provider, so close it */
280 if (hCryptProv &&
281 !(dwFlags & CERT_STORE_NO_CRYPT_RELEASE_FLAG))
282 CryptReleaseContext(hCryptProv, 0);
286 TRACE("returning %p\n", store);
287 return store;
290 PWINECRYPT_CERTSTORE CRYPT_FileNameOpenStoreW(HCRYPTPROV hCryptProv,
291 DWORD dwFlags, const void *pvPara)
293 HCERTSTORE store = 0;
294 LPCWSTR fileName = pvPara;
295 DWORD access, create;
296 HANDLE file;
298 TRACE("(%ld, %08x, %s)\n", hCryptProv, dwFlags, debugstr_w(fileName));
300 if (!fileName)
302 SetLastError(ERROR_PATH_NOT_FOUND);
303 return NULL;
305 if ((dwFlags & CERT_STORE_READONLY_FLAG) &&
306 (dwFlags & CERT_FILE_STORE_COMMIT_ENABLE_FLAG))
308 SetLastError(E_INVALIDARG);
309 return NULL;
312 access = GENERIC_READ;
313 if (dwFlags & CERT_FILE_STORE_COMMIT_ENABLE_FLAG)
314 access |= GENERIC_WRITE;
315 if (dwFlags & CERT_STORE_CREATE_NEW_FLAG)
316 create = CREATE_NEW;
317 else if (dwFlags & CERT_STORE_OPEN_EXISTING_FLAG)
318 create = OPEN_EXISTING;
319 else
320 create = OPEN_ALWAYS;
321 file = CreateFileW(fileName, access, FILE_SHARE_READ, NULL, create,
322 FILE_ATTRIBUTE_NORMAL, NULL);
323 if (file != INVALID_HANDLE_VALUE)
325 HCERTSTORE memStore = NULL;
326 DWORD size = GetFileSize(file, NULL), type = 0;
328 /* If the file isn't empty, try to get the type from the file itself */
329 if (size)
331 DWORD contentType;
332 BOOL ret;
334 /* Close the file so CryptQueryObject can succeed.. */
335 CloseHandle(file);
336 ret = CryptQueryObject(CERT_QUERY_OBJECT_FILE, fileName,
337 CERT_QUERY_CONTENT_FLAG_CERT |
338 CERT_QUERY_CONTENT_FLAG_SERIALIZED_STORE |
339 CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED,
340 CERT_QUERY_FORMAT_FLAG_ALL, 0, NULL, &contentType, NULL,
341 &memStore, NULL, NULL);
342 if (ret)
344 if (contentType == CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED)
345 type = CERT_STORE_SAVE_AS_PKCS7;
346 else
347 type = CERT_STORE_SAVE_AS_STORE;
348 /* and reopen the file. */
349 file = CreateFileW(fileName, access, FILE_SHARE_READ, NULL,
350 create, FILE_ATTRIBUTE_NORMAL, NULL);
353 else
355 static const WCHAR spc[] = { 's','p','c',0 };
356 static const WCHAR p7c[] = { 'p','7','c',0 };
357 LPCWSTR ext = strrchrW(fileName, '.');
359 if (ext)
361 ext++;
362 if (!lstrcmpiW(ext, spc) || !lstrcmpiW(ext, p7c))
363 type = CERT_STORE_SAVE_AS_PKCS7;
365 if (!type)
366 type = CERT_STORE_SAVE_AS_STORE;
367 memStore = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
368 CERT_STORE_CREATE_NEW_FLAG, NULL);
370 if (memStore)
372 store = CRYPT_CreateFileStore(dwFlags, memStore, file, type);
373 /* File store doesn't need crypto provider, so close it */
374 if (hCryptProv && !(dwFlags & CERT_STORE_NO_CRYPT_RELEASE_FLAG))
375 CryptReleaseContext(hCryptProv, 0);
378 return store;
381 PWINECRYPT_CERTSTORE CRYPT_FileNameOpenStoreA(HCRYPTPROV hCryptProv,
382 DWORD dwFlags, const void *pvPara)
384 int len;
385 PWINECRYPT_CERTSTORE ret = NULL;
387 TRACE("(%ld, %08x, %s)\n", hCryptProv, dwFlags,
388 debugstr_a(pvPara));
390 if (!pvPara)
392 SetLastError(ERROR_FILE_NOT_FOUND);
393 return NULL;
395 len = MultiByteToWideChar(CP_ACP, 0, pvPara, -1, NULL, 0);
396 if (len)
398 LPWSTR storeName = CryptMemAlloc(len * sizeof(WCHAR));
400 if (storeName)
402 MultiByteToWideChar(CP_ACP, 0, pvPara, -1, storeName, len);
403 ret = CRYPT_FileNameOpenStoreW(hCryptProv, dwFlags, storeName);
404 CryptMemFree(storeName);
407 return ret;