crypt32/tests: Add a trailing '\n' to ok() calls.
[wine.git] / dlls / crypt32 / tests / store.c
bloba396dfe907115477520b3ce384ecd02d04d480fa
1 /*
2 * crypt32 cert store function tests
4 * Copyright 2005-2006 Juan Lang
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #include <stdio.h>
22 #include <stdarg.h>
24 #include <windef.h>
25 #include <winbase.h>
26 #include <winuser.h>
27 #include <shlobj.h>
28 #include <shlwapi.h>
29 #include <winreg.h>
30 #include <winerror.h>
31 #include <wincrypt.h>
33 #include "wine/test.h"
35 /* The following aren't defined in wincrypt.h, as they're "reserved" */
36 #define CERT_CERT_PROP_ID 32
37 #define CERT_CRL_PROP_ID 33
38 #define CERT_CTL_PROP_ID 34
40 struct CertPropIDHeader
42 DWORD propID;
43 DWORD unknown1;
44 DWORD cb;
47 static const BYTE emptyCert[] = { 0x30, 0x00 };
48 static const BYTE bigCert[] = { 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
49 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
50 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x22,
51 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30,
52 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30,
53 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30,
54 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20,
55 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01,
56 0x00, 0xa3, 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01,
57 0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
58 static const BYTE signedBigCert[] = {
59 0x30, 0x81, 0x93, 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06, 0x00, 0x30,
60 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a,
61 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x22, 0x18, 0x0f,
62 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
63 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30,
64 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06,
65 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61,
66 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3,
67 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff,
68 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
69 0x00, 0x03, 0x11, 0x00, 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07,
70 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00 };
71 static const BYTE serializedCert[] = { 0x20, 0x00, 0x00, 0x00,
72 0x01, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x30, 0x7a, 0x02, 0x01, 0x01,
73 0x30, 0x02, 0x06, 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55,
74 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67,
75 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31,
76 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31,
77 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15,
78 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75,
79 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06,
80 0x00, 0x03, 0x01, 0x00, 0xa3, 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55,
81 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02,
82 0x01, 0x01 };
83 static const BYTE signedCRL[] = { 0x30, 0x45, 0x30, 0x2c, 0x30, 0x02, 0x06,
84 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
85 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18, 0x0f,
86 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
87 0x30, 0x5a, 0x30, 0x02, 0x06, 0x00, 0x03, 0x11, 0x00, 0x0f, 0x0e, 0x0d, 0x0c,
88 0x0b, 0x0a, 0x09, 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00 };
89 static const BYTE bigCert2[] = { 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
90 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
91 0x0a, 0x41, 0x6c, 0x65, 0x78, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x22,
92 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30,
93 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30,
94 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30,
95 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x41, 0x6c, 0x65, 0x78, 0x20,
96 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01,
97 0x00, 0xa3, 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01,
98 0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
99 static const BYTE signedCTLWithCTLInnerContent[] = {
100 0x30,0x82,0x01,0x0f,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,
101 0xa0,0x82,0x01,0x00,0x30,0x81,0xfd,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,
102 0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x30,0x06,0x09,
103 0x2b,0x06,0x01,0x04,0x01,0x82,0x37,0x0a,0x01,0xa0,0x23,0x30,0x21,0x30,0x00,
104 0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,
105 0x30,0x5a,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,
106 0x00,0x31,0x81,0xb5,0x30,0x81,0xb2,0x02,0x01,0x01,0x30,0x1a,0x30,0x15,0x31,
107 0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,
108 0x4c,0x61,0x6e,0x67,0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,
109 0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0xa0,0x3b,0x30,0x18,0x06,0x09,0x2a,0x86,
110 0x48,0x86,0xf7,0x0d,0x01,0x09,0x03,0x31,0x0b,0x06,0x09,0x2b,0x06,0x01,0x04,
111 0x01,0x82,0x37,0x0a,0x01,0x30,0x1f,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,
112 0x01,0x09,0x04,0x31,0x12,0x04,0x10,0x54,0x71,0xbc,0xe1,0x56,0x31,0xa2,0xf9,
113 0x65,0x70,0x34,0xf8,0xe2,0xe9,0xb4,0xf4,0x30,0x04,0x06,0x00,0x05,0x00,0x04,
114 0x40,0x2f,0x1b,0x9f,0x5a,0x4a,0x15,0x73,0xfa,0xb1,0x93,0x3d,0x09,0x52,0xdf,
115 0x6b,0x98,0x4b,0x13,0x5e,0xe7,0xbf,0x65,0xf4,0x9c,0xc2,0xb1,0x77,0x09,0xb1,
116 0x66,0x4d,0x72,0x0d,0xb1,0x1a,0x50,0x20,0xe0,0x57,0xa2,0x39,0xc7,0xcd,0x7f,
117 0x8e,0xe7,0x5f,0x76,0x2b,0xd1,0x6a,0x82,0xb3,0x30,0x25,0x61,0xf6,0x25,0x23,
118 0x57,0x6c,0x0b,0x47,0xb8 };
121 static BOOL (WINAPI *pCertAddStoreToCollection)(HCERTSTORE,HCERTSTORE,DWORD,DWORD);
122 static BOOL (WINAPI *pCertControlStore)(HCERTSTORE,DWORD,DWORD,void const*);
123 static PCCRL_CONTEXT (WINAPI *pCertEnumCRLsInStore)(HCERTSTORE,PCCRL_CONTEXT);
124 static BOOL (WINAPI *pCertEnumSystemStore)(DWORD,void*,void*,PFN_CERT_ENUM_SYSTEM_STORE);
125 static BOOL (WINAPI *pCertGetStoreProperty)(HCERTSTORE,DWORD,void*,DWORD*);
126 static void (WINAPI *pCertRemoveStoreFromCollection)(HCERTSTORE,HCERTSTORE);
127 static BOOL (WINAPI *pCertSetStoreProperty)(HCERTSTORE,DWORD,DWORD,const void*);
128 static BOOL (WINAPI *pCertAddCertificateLinkToStore)(HCERTSTORE,PCCERT_CONTEXT,DWORD,PCCERT_CONTEXT*);
129 static BOOL (WINAPI *pCertRegisterSystemStore)(const void*,DWORD,void*,void*);
130 static BOOL (WINAPI *pCertUnregisterSystemStore)(const void*,DWORD);
132 #define test_store_is_empty(store) _test_store_is_empty(__LINE__,store)
133 static void _test_store_is_empty(unsigned line, HCERTSTORE store)
135 const CERT_CONTEXT *cert;
137 cert = CertEnumCertificatesInStore(store, NULL);
138 ok_(__FILE__,line)(!cert && GetLastError() == CRYPT_E_NOT_FOUND, "store is not empty\n");
141 static void testMemStore(void)
143 HCERTSTORE store1, store2;
144 PCCERT_CONTEXT context;
145 BOOL ret;
146 DWORD GLE;
148 /* NULL provider */
149 store1 = CertOpenStore(0, 0, 0, 0, NULL);
150 ok(!store1 && GetLastError() == ERROR_FILE_NOT_FOUND,
151 "Expected ERROR_FILE_NOT_FOUND, got %d\n", GetLastError());
152 /* weird flags */
153 store1 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
154 CERT_STORE_DELETE_FLAG, NULL);
155 ok(!store1 && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED,
156 "Expected ERROR_CALL_NOT_IMPLEMENTED, got %d\n", GetLastError());
158 /* normal */
159 store1 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
160 CERT_STORE_CREATE_NEW_FLAG, NULL);
161 ok(store1 != NULL, "CertOpenStore failed: %d\n", GetLastError());
162 /* open existing doesn't */
163 store2 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
164 CERT_STORE_OPEN_EXISTING_FLAG, NULL);
165 ok(store2 != NULL, "CertOpenStore failed: %d\n", GetLastError());
166 ok(store1 != store2, "Expected different stores\n");
168 /* add a bogus (empty) cert */
169 context = NULL;
170 ret = CertAddEncodedCertificateToStore(store1, X509_ASN_ENCODING, emptyCert,
171 sizeof(emptyCert), CERT_STORE_ADD_ALWAYS, &context);
172 /* Windows returns CRYPT_E_ASN1_EOD or OSS_DATA_ERROR, but accept
173 * CRYPT_E_ASN1_CORRUPT as well (because matching errors is tough in this
174 * case)
176 GLE = GetLastError();
177 ok(!ret && (GLE == CRYPT_E_ASN1_EOD || GLE == CRYPT_E_ASN1_CORRUPT ||
178 GLE == OSS_DATA_ERROR),
179 "Expected CRYPT_E_ASN1_EOD or CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
180 GLE);
181 /* add a "signed" cert--the signature isn't a real signature, so this adds
182 * without any check of the signature's validity
184 ret = CertAddEncodedCertificateToStore(store1, X509_ASN_ENCODING,
185 signedBigCert, sizeof(signedBigCert), CERT_STORE_ADD_ALWAYS, &context);
186 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n", GetLastError());
187 ok(context != NULL, "Expected a valid cert context\n");
188 if (context)
190 ok(context->cbCertEncoded == sizeof(signedBigCert),
191 "Wrong cert size %d\n", context->cbCertEncoded);
192 ok(!memcmp(context->pbCertEncoded, signedBigCert,
193 sizeof(signedBigCert)), "Unexpected encoded cert in context\n");
194 /* remove it, the rest of the tests will work on an unsigned cert */
195 ret = CertDeleteCertificateFromStore(context);
196 ok(ret, "CertDeleteCertificateFromStore failed: %08x\n",
197 GetLastError());
199 /* try adding a "signed" CRL as a cert */
200 ret = CertAddEncodedCertificateToStore(store1, X509_ASN_ENCODING,
201 signedCRL, sizeof(signedCRL), CERT_STORE_ADD_ALWAYS, &context);
202 GLE = GetLastError();
203 ok(!ret && (GLE == CRYPT_E_ASN1_BADTAG || GLE == CRYPT_E_ASN1_CORRUPT ||
204 GLE == OSS_DATA_ERROR),
205 "Expected CRYPT_E_ASN1_BADTAG or CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
206 GLE);
207 /* add a cert to store1 */
208 ret = CertAddEncodedCertificateToStore(store1, X509_ASN_ENCODING, bigCert,
209 sizeof(bigCert), CERT_STORE_ADD_ALWAYS, &context);
210 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n", GetLastError());
211 ok(context != NULL, "Expected a valid cert context\n");
212 if (context)
214 DWORD size;
215 BYTE *buf;
217 ok(context->cbCertEncoded == sizeof(bigCert),
218 "Wrong cert size %d\n", context->cbCertEncoded);
219 ok(!memcmp(context->pbCertEncoded, bigCert, sizeof(bigCert)),
220 "Unexpected encoded cert in context\n");
221 ok(context->hCertStore == store1, "Unexpected store\n");
223 /* check serializing this element */
224 /* These crash
225 ret = CertSerializeCertificateStoreElement(NULL, 0, NULL, NULL);
226 ret = CertSerializeCertificateStoreElement(context, 0, NULL, NULL);
227 ret = CertSerializeCertificateStoreElement(NULL, 0, NULL, &size);
229 /* apparently flags are ignored */
230 ret = CertSerializeCertificateStoreElement(context, 1, NULL, &size);
231 ok(ret, "CertSerializeCertificateStoreElement failed: %08x\n",
232 GetLastError());
233 buf = HeapAlloc(GetProcessHeap(), 0, size);
234 if (buf)
236 ret = CertSerializeCertificateStoreElement(context, 0, buf, &size);
237 ok(ret, "CertSerializeCertificateStoreElement failed: %08x\n", GetLastError());
238 ok(size == sizeof(serializedCert), "Wrong size %d\n", size);
239 ok(!memcmp(serializedCert, buf, size),
240 "Unexpected serialized cert\n");
241 HeapFree(GetProcessHeap(), 0, buf);
244 ret = CertFreeCertificateContext(context);
245 ok(ret, "CertFreeCertificateContext failed: %08x\n", GetLastError());
247 /* verify the cert's in store1 */
248 context = CertEnumCertificatesInStore(store1, NULL);
249 ok(context != NULL, "Expected a valid context\n");
250 context = CertEnumCertificatesInStore(store1, context);
251 ok(!context && GetLastError() == CRYPT_E_NOT_FOUND,
252 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
253 /* verify store2 (the "open existing" mem store) is still empty */
254 context = CertEnumCertificatesInStore(store2, NULL);
255 ok(!context, "Expected an empty store\n");
256 /* delete the cert from store1, and check it's empty */
257 context = CertEnumCertificatesInStore(store1, NULL);
258 if (context)
260 /* Deleting a bitwise copy crashes with an access to an uninitialized
261 * pointer, so a cert context has some special data out there in memory
262 * someplace
263 CERT_CONTEXT copy;
264 memcpy(&copy, context, sizeof(copy));
265 ret = CertDeleteCertificateFromStore(&copy);
267 PCCERT_CONTEXT copy = CertDuplicateCertificateContext(context);
269 ok(copy != NULL, "CertDuplicateCertificateContext failed: %08x\n",
270 GetLastError());
271 ret = CertDeleteCertificateFromStore(context);
272 ok(ret, "CertDeleteCertificateFromStore failed: %08x\n",
273 GetLastError());
274 /* try deleting a copy */
275 ret = CertDeleteCertificateFromStore(copy);
276 ok(ret, "CertDeleteCertificateFromStore failed: %08x\n",
277 GetLastError());
278 /* check that the store is empty */
279 context = CertEnumCertificatesInStore(store1, NULL);
280 ok(!context, "Expected an empty store\n");
283 /* close an empty store */
284 ret = CertCloseStore(NULL, 0);
285 ok(ret, "CertCloseStore failed: %d\n", GetLastError());
286 ret = CertCloseStore(store1, 0);
287 ok(ret, "CertCloseStore failed: %d\n", GetLastError());
288 ret = CertCloseStore(store2, 0);
289 ok(ret, "CertCloseStore failed: %d\n", GetLastError());
291 /* This seems nonsensical, but you can open a read-only mem store, only
292 * it isn't read-only
294 store1 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
295 CERT_STORE_READONLY_FLAG, NULL);
296 ok(store1 != NULL, "CertOpenStore failed: %d\n", GetLastError());
297 /* yep, this succeeds */
298 ret = CertAddEncodedCertificateToStore(store1, X509_ASN_ENCODING, bigCert,
299 sizeof(bigCert), CERT_STORE_ADD_ALWAYS, &context);
300 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n", GetLastError());
301 ok(context != NULL, "Expected a valid cert context\n");
302 if (context)
304 ok(context->cbCertEncoded == sizeof(bigCert),
305 "Wrong cert size %d\n", context->cbCertEncoded);
306 ok(!memcmp(context->pbCertEncoded, bigCert, sizeof(bigCert)),
307 "Unexpected encoded cert in context\n");
308 ok(context->hCertStore == store1, "Unexpected store\n");
309 ret = CertDeleteCertificateFromStore(context);
310 ok(ret, "CertDeleteCertificateFromStore failed: %08x\n",
311 GetLastError());
313 CertCloseStore(store1, 0);
316 static void compareStore(HCERTSTORE store, LPCSTR name, const BYTE *pb,
317 DWORD cb, BOOL todo)
319 BOOL ret;
320 CRYPT_DATA_BLOB blob = { 0, NULL };
322 ret = CertSaveStore(store, X509_ASN_ENCODING, CERT_STORE_SAVE_AS_STORE,
323 CERT_STORE_SAVE_TO_MEMORY, &blob, 0);
324 ok(ret, "CertSaveStore failed: %08x\n", GetLastError());
325 todo_wine_if (todo)
326 ok(blob.cbData == cb, "%s: expected size %d, got %d\n", name, cb,
327 blob.cbData);
328 blob.pbData = HeapAlloc(GetProcessHeap(), 0, blob.cbData);
329 if (blob.pbData)
331 ret = CertSaveStore(store, X509_ASN_ENCODING, CERT_STORE_SAVE_AS_STORE,
332 CERT_STORE_SAVE_TO_MEMORY, &blob, 0);
333 ok(ret, "CertSaveStore failed: %08x\n", GetLastError());
334 todo_wine_if (todo)
335 ok(!memcmp(pb, blob.pbData, cb), "%s: unexpected value\n", name);
336 HeapFree(GetProcessHeap(), 0, blob.pbData);
340 static const BYTE serializedStoreWithCert[] = {
341 0x00,0x00,0x00,0x00,0x43,0x45,0x52,0x54,0x20,0x00,0x00,0x00,0x01,0x00,0x00,
342 0x00,0x7c,0x00,0x00,0x00,0x30,0x7a,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,
343 0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,
344 0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,
345 0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,
346 0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,
347 0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,
348 0x20,0x4c,0x61,0x6e,0x67,0x00,0x30,0x07,0x30,0x02,0x06,0x00,0x03,0x01,0x00,
349 0xa3,0x16,0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,
350 0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,
351 0x00,0x00,0x00,0x00,0x00,0x00 };
353 static const struct
355 HKEY key;
356 DWORD cert_store;
357 BOOL appdata_file;
358 WCHAR store_name[16];
359 const WCHAR *base_reg_path;
360 } reg_store_saved_certs[] = {
361 { HKEY_LOCAL_MACHINE, CERT_SYSTEM_STORE_LOCAL_MACHINE, FALSE,
362 {'R','O','O','T',0}, CERT_LOCAL_MACHINE_SYSTEM_STORE_REGPATH },
363 { HKEY_LOCAL_MACHINE, CERT_SYSTEM_STORE_LOCAL_MACHINE, FALSE,
364 {'M','Y',0}, CERT_LOCAL_MACHINE_SYSTEM_STORE_REGPATH },
365 { HKEY_LOCAL_MACHINE, CERT_SYSTEM_STORE_LOCAL_MACHINE, FALSE,
366 {'C','A',0}, CERT_LOCAL_MACHINE_SYSTEM_STORE_REGPATH },
367 /* Adding to HKCU\Root triggers safety warning. */
368 { HKEY_CURRENT_USER, CERT_SYSTEM_STORE_CURRENT_USER, TRUE,
369 {'M','Y',0}, CERT_LOCAL_MACHINE_SYSTEM_STORE_REGPATH },
370 { HKEY_CURRENT_USER, CERT_SYSTEM_STORE_CURRENT_USER, FALSE,
371 {'C','A',0}, CERT_LOCAL_MACHINE_SYSTEM_STORE_REGPATH }
374 /* Testing whether system stores are available for adding new certs
375 * and checking directly in the registry whether they are actually saved or deleted.
376 * Windows treats HKCU\My (at least) as a special case and uses AppData directory
377 * for storing certs, not registry.
379 static void testRegStoreSavedCerts(void)
381 static const WCHAR fmt[] =
382 { '%','s','\\','%','s','\\','%','s','\\','%','s',0},
383 ms_certs[] =
384 { 'M','i','c','r','o','s','o','f','t','\\','S','y','s','t','e','m','C','e','r','t','i','f','i','c','a','t','e','s',0},
385 certs[] =
386 {'C','e','r','t','i','f','i','c','a','t','e','s',0},
387 bigCert_hash[] = {
388 '6','E','3','0','9','0','7','1','5','F','D','9','2','3',
389 '5','6','E','B','A','E','2','5','4','0','E','6','2','2',
390 'D','A','1','9','2','6','0','2','A','6','0','8',0};
391 PCCERT_CONTEXT cert1, cert2;
392 HCERTSTORE store;
393 HANDLE cert_file;
394 HRESULT pathres;
395 WCHAR key_name[MAX_PATH], appdata_path[MAX_PATH];
396 HKEY key;
397 BOOL ret;
398 DWORD res,i;
400 for (i = 0; i < sizeof(reg_store_saved_certs) / sizeof(reg_store_saved_certs[0]); i++)
402 DWORD err;
404 store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY_W,0,0,
405 reg_store_saved_certs[i].cert_store, reg_store_saved_certs[i].store_name);
407 err = GetLastError();
408 if (!store)
410 ok (err == ERROR_ACCESS_DENIED, "Failed to create store at %d (%08x)\n", i, err);
411 skip("Insufficient privileges for the test %d\n", i);
412 continue;
414 ok (store!=NULL, "Failed to open the store at %d, %x\n", i, GetLastError());
415 cert1 = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert, sizeof(bigCert));
416 ok (cert1 != NULL, "Create cert context failed at %d, %x\n", i, GetLastError());
417 ret = CertAddCertificateContextToStore(store, cert1, CERT_STORE_ADD_REPLACE_EXISTING, NULL);
418 /* Addittional skip per Win7, it allows opening HKLM store, but disallows adding certs */
419 err = GetLastError();
420 if (!ret)
422 ok (err == ERROR_ACCESS_DENIED, "Failed to add certificate to store at %d (%08x)\n", i, err);
423 skip("Insufficient privileges for the test %d\n", i);
424 continue;
426 ok (ret, "Adding to the store failed at %d, %x\n", i, err);
427 CertFreeCertificateContext(cert1);
428 CertCloseStore(store, 0);
430 wsprintfW(key_name, fmt, reg_store_saved_certs[i].base_reg_path,
431 reg_store_saved_certs[i].store_name, certs, bigCert_hash);
433 if (!reg_store_saved_certs[i].appdata_file)
435 res = RegOpenKeyExW(reg_store_saved_certs[i].key, key_name, 0, KEY_ALL_ACCESS, &key);
436 ok (!res, "The cert hasn't been saved at %d, %x\n", i, GetLastError());
437 if (!res) RegCloseKey(key);
438 } else
440 pathres = SHGetFolderPathW(NULL, CSIDL_APPDATA, NULL, 0, appdata_path);
441 ok (pathres == S_OK,
442 "Failed to get app data path at %d (%x)\n", pathres, GetLastError());
443 if (pathres == S_OK)
445 PathAppendW(appdata_path, ms_certs);
446 PathAppendW(appdata_path, reg_store_saved_certs[i].store_name);
447 PathAppendW(appdata_path, certs);
448 PathAppendW(appdata_path, bigCert_hash);
450 cert_file = CreateFileW(appdata_path, GENERIC_READ, 0, NULL,
451 OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
452 todo_wine ok (cert_file != INVALID_HANDLE_VALUE,
453 "Cert was not saved in AppData at %d (%x)\n", i, GetLastError());
454 CloseHandle(cert_file);
458 /* deleting cert from store */
459 store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY_W,0,0,
460 reg_store_saved_certs[i].cert_store, reg_store_saved_certs[i].store_name);
461 ok (store!=NULL, "Failed to open the store at %d, %x\n", i, GetLastError());
463 cert1 = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert, sizeof(bigCert));
464 ok (cert1 != NULL, "Create cert context failed at %d, %x\n", i, GetLastError());
466 cert2 = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
467 CERT_FIND_EXISTING, cert1, NULL);
468 ok (cert2 != NULL, "Failed to find cert in the store at %d, %x\n", i, GetLastError());
470 ret = CertDeleteCertificateFromStore(cert2);
471 ok (ret, "Failed to delete certificate from store at %d, %x\n", i, GetLastError());
473 CertFreeCertificateContext(cert1);
474 CertFreeCertificateContext(cert2);
475 CertCloseStore(store, 0);
477 res = RegOpenKeyExW(reg_store_saved_certs[i].key, key_name, 0, KEY_ALL_ACCESS, &key);
478 ok (res, "The cert's registry entry should be absent at %i, %x\n", i, GetLastError());
479 if (!res) RegCloseKey(key);
481 if (reg_store_saved_certs[i].appdata_file)
483 cert_file = CreateFileW(appdata_path, GENERIC_READ, 0, NULL,
484 OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
485 ok (cert_file == INVALID_HANDLE_VALUE,
486 "Cert should have been absent in AppData %d\n", i);
488 CloseHandle(cert_file);
494 * This test checks that certificate falls into correct store of a collection
495 * depending on the access flags and priorities.
497 static void testStoresInCollection(void)
499 PCCERT_CONTEXT cert1, cert2, tcert1;
500 HCERTSTORE collection, ro_store, rw_store, rw_store_2, tstore;
501 static const WCHAR WineTestRO_W[] = { 'W','i','n','e','T','e','s','t','_','R','O',0 },
502 WineTestRW_W[] = { 'W','i','n','e','T','e','s','t','_','R','W',0 },
503 WineTestRW2_W[]= { 'W','i','n','e','T','e','s','t','_','R','W','2',0 };
504 BOOL ret;
506 if (!pCertAddStoreToCollection)
508 win_skip("CertAddStoreToCollection() is not available\n");
509 return;
511 collection = CertOpenStore(CERT_STORE_PROV_COLLECTION, 0, 0,
512 CERT_STORE_CREATE_NEW_FLAG, NULL);
513 ok(collection != NULL, "Failed to init collection store, last error %x\n", GetLastError());
514 /* Add read-only store to collection with very high priority*/
515 ro_store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY_W, 0, 0,
516 CERT_SYSTEM_STORE_CURRENT_USER, WineTestRO_W);
517 ok(ro_store != NULL, "Failed to init ro store %x\n", GetLastError());
519 ret = CertAddStoreToCollection(collection, ro_store, 0, 1000);
520 ok (ret, "Failed to add read-only store to collection %x\n", GetLastError());
522 cert1 = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert, sizeof(bigCert));
523 ok (cert1 != NULL, "Create cert context failed %x\n", GetLastError());
524 ret = CertAddCertificateContextToStore(collection, cert1, CERT_STORE_ADD_ALWAYS, NULL);
525 ok (!ret, "Added cert to collection with single read-only store %x\n", GetLastError());
527 /* Add read-write store to collection with the lowest priority*/
528 rw_store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY_W, 0, 0,
529 CERT_SYSTEM_STORE_CURRENT_USER, WineTestRW_W);
530 ok (rw_store != NULL, "Failed to open rw store %x\n", GetLastError());
531 ret = CertAddStoreToCollection(collection, rw_store, CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
532 ok (ret, "Failed to add rw store to collection %x\n", GetLastError());
533 /** Adding certificate to collection should fall into rw store,
534 * even though prioirty of the ro_store is higher */
535 ret = CertAddCertificateContextToStore(collection, cert1, CERT_STORE_ADD_REPLACE_EXISTING, NULL);
536 ok (ret, "Failed to add cert to the collection %x\n", GetLastError());
538 tcert1 = CertEnumCertificatesInStore(ro_store, NULL);
539 ok (!tcert1, "Read-only ro_store contains cert\n");
541 tcert1 = CertEnumCertificatesInStore(rw_store, NULL);
542 ok (cert1 && tcert1->cbCertEncoded == cert1->cbCertEncoded,
543 "Unexpected cert in the rw store\n");
544 CertFreeCertificateContext(tcert1);
546 tcert1 = CertEnumCertificatesInStore(collection, NULL);
547 ok (tcert1 && tcert1->cbCertEncoded == cert1->cbCertEncoded,
548 "Unexpected cert in the collection\n");
549 CertFreeCertificateContext(tcert1);
551 /** adding one more rw store with higher priority*/
552 rw_store_2 = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY_W, 0, 0,
553 CERT_SYSTEM_STORE_CURRENT_USER, WineTestRW2_W);
554 ok (rw_store_2 != NULL, "Failed to init second rw store %x\n", GetLastError());
555 ret = CertAddStoreToCollection(collection, rw_store_2, CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 50);
556 ok (ret, "Failed to add rw_store_2 to collection %x\n",GetLastError());
558 cert2 = CertCreateCertificateContext(X509_ASN_ENCODING, signedBigCert, sizeof(signedBigCert));
559 ok (cert2 != NULL, "Failed to create cert context %x\n", GetLastError());
560 ret = CertAddCertificateContextToStore(collection, cert2, CERT_STORE_ADD_REPLACE_EXISTING, NULL);
561 ok (ret, "Failed to add cert3 to the store %x\n",GetLastError());
563 /** checking certificates in the stores */
564 tcert1 = CertEnumCertificatesInStore(ro_store, 0);
565 ok (tcert1 == NULL, "Read-only store not empty\n");
567 tcert1 = CertEnumCertificatesInStore(rw_store, NULL);
568 ok (tcert1 && tcert1->cbCertEncoded == cert1->cbCertEncoded,
569 "Unexpected cert in the rw_store\n");
570 CertFreeCertificateContext(tcert1);
572 tcert1 = CertEnumCertificatesInStore(rw_store_2, NULL);
573 ok (tcert1 && tcert1->cbCertEncoded == cert2->cbCertEncoded,
574 "Unexpected cert in the rw_store_2\n");
575 CertFreeCertificateContext(tcert1);
577 /** checking certificates in the collection */
578 tcert1 = CertEnumCertificatesInStore(collection, NULL);
579 ok (tcert1 && tcert1->cbCertEncoded == cert2->cbCertEncoded,
580 "cert2 expected in the collection got %p, %x\n",tcert1, GetLastError());
581 tcert1 = CertEnumCertificatesInStore(collection, tcert1);
582 ok (tcert1 && tcert1->cbCertEncoded == cert1->cbCertEncoded,
583 "cert1 expected in the collection got %p, %x\n",tcert1, GetLastError());
584 tcert1 = CertEnumCertificatesInStore(collection, tcert1);
585 ok (tcert1==NULL,"Unexpected cert in the collection %p %x\n",tcert1, GetLastError());
587 /* checking whether certs had been saved */
588 tstore = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY_W,0,0,
589 CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_OPEN_EXISTING_FLAG, WineTestRW_W);
590 ok (tstore!=NULL, "Failed to open existing rw store\n");
591 tcert1 = CertEnumCertificatesInStore(tstore, NULL);
592 todo_wine
593 ok(tcert1 && tcert1->cbCertEncoded == cert1->cbCertEncoded, "cert1 wasn't saved\n");
594 CertFreeCertificateContext(tcert1);
595 CertCloseStore(tstore,0);
597 tstore = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY_W,0,0,
598 CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_OPEN_EXISTING_FLAG, WineTestRW2_W);
599 ok (tstore!=NULL, "Failed to open existing rw2 store\n");
600 tcert1 = CertEnumCertificatesInStore(tstore, NULL);
601 todo_wine
602 ok (tcert1 && tcert1->cbCertEncoded == cert2->cbCertEncoded, "cert2 wasn't saved\n");
603 CertFreeCertificateContext(tcert1);
604 CertCloseStore(tstore,0);
606 CertCloseStore(collection,0);
607 CertCloseStore(ro_store,0);
608 CertCloseStore(rw_store,0);
609 CertCloseStore(rw_store_2,0);
611 /* reopening registry stores to check whether certs had been saved */
612 rw_store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY_W,0,0,
613 CERT_SYSTEM_STORE_CURRENT_USER, WineTestRW_W);
614 tcert1 = CertEnumCertificatesInStore(rw_store, NULL);
615 ok (tcert1 && tcert1->cbCertEncoded == cert1->cbCertEncoded,
616 "Unexpected cert in store %p\n", tcert1);
617 CertFreeCertificateContext(tcert1);
618 CertCloseStore(rw_store,0);
620 rw_store_2 = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY_W,0,0,
621 CERT_SYSTEM_STORE_CURRENT_USER, WineTestRW2_W);
622 tcert1 = CertEnumCertificatesInStore(rw_store_2, NULL);
623 ok (tcert1 && tcert1->cbCertEncoded == cert2->cbCertEncoded,
624 "Unexpected cert in store %p\n", tcert1);
625 CertFreeCertificateContext(tcert1);
626 CertCloseStore(rw_store_2,0);
628 CertFreeCertificateContext(cert1);
629 CertFreeCertificateContext(cert2);
630 CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY_W,0,0,
631 CERT_STORE_DELETE_FLAG|CERT_SYSTEM_STORE_CURRENT_USER,WineTestRO_W);
632 CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY_W,0,0,
633 CERT_STORE_DELETE_FLAG|CERT_SYSTEM_STORE_CURRENT_USER,WineTestRW_W);
634 CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY_W,0,0,
635 CERT_STORE_DELETE_FLAG|CERT_SYSTEM_STORE_CURRENT_USER,WineTestRW2_W);
639 static void testCollectionStore(void)
641 HCERTSTORE store1, store2, collection, collection2;
642 PCCERT_CONTEXT context;
643 BOOL ret;
644 static const WCHAR szPrefix[] = { 'c','e','r',0 };
645 static const WCHAR szDot[] = { '.',0 };
646 WCHAR filename[MAX_PATH];
647 HANDLE file;
649 if (!pCertAddStoreToCollection)
651 win_skip("CertAddStoreToCollection() is not available\n");
652 return;
655 collection = CertOpenStore(CERT_STORE_PROV_COLLECTION, 0, 0,
656 CERT_STORE_CREATE_NEW_FLAG, NULL);
658 /* Try adding a cert to any empty collection */
659 ret = CertAddEncodedCertificateToStore(collection, X509_ASN_ENCODING,
660 bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, NULL);
661 ok(!ret && GetLastError() == E_ACCESSDENIED,
662 "Expected E_ACCESSDENIED, got %08x\n", GetLastError());
664 /* Create and add a cert to a memory store */
665 store1 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
666 CERT_STORE_CREATE_NEW_FLAG, NULL);
667 ret = CertAddEncodedCertificateToStore(store1, X509_ASN_ENCODING,
668 bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, NULL);
669 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n", GetLastError());
670 /* Add the memory store to the collection, without allowing adding */
671 ret = pCertAddStoreToCollection(collection, store1, 0, 0);
672 ok(ret, "CertAddStoreToCollection failed: %08x\n", GetLastError());
673 /* Verify the cert is in the collection */
674 context = CertEnumCertificatesInStore(collection, NULL);
675 ok(context != NULL, "Expected a valid context\n");
676 if (context)
678 ok(context->hCertStore == collection, "Unexpected store\n");
679 CertFreeCertificateContext(context);
681 /* Check that adding to the collection isn't allowed */
682 ret = CertAddEncodedCertificateToStore(collection, X509_ASN_ENCODING,
683 bigCert2, sizeof(bigCert2), CERT_STORE_ADD_ALWAYS, NULL);
684 ok(!ret && GetLastError() == E_ACCESSDENIED,
685 "Expected E_ACCESSDENIED, got %08x\n", GetLastError());
687 /* Create a new memory store */
688 store2 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
689 CERT_STORE_CREATE_NEW_FLAG, NULL);
690 /* Try adding a store to a non-collection store */
691 ret = pCertAddStoreToCollection(store1, store2,
692 CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
693 ok(!ret && GetLastError() == E_INVALIDARG,
694 "Expected E_INVALIDARG, got %08x\n", GetLastError());
695 /* Try adding some bogus stores */
696 /* This crashes in Windows
697 ret = pCertAddStoreToCollection(0, store2,
698 CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
700 /* This "succeeds"... */
701 ret = pCertAddStoreToCollection(collection, 0,
702 CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
703 ok(ret, "CertAddStoreToCollection failed: %08x\n", GetLastError());
704 /* while this crashes.
705 ret = pCertAddStoreToCollection(collection, 1,
706 CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
709 /* Add it to the collection, this time allowing adding */
710 ret = pCertAddStoreToCollection(collection, store2,
711 CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
712 ok(ret, "CertAddStoreToCollection failed: %08x\n", GetLastError());
713 /* Check that adding to the collection is allowed */
714 ret = CertAddEncodedCertificateToStore(collection, X509_ASN_ENCODING,
715 bigCert2, sizeof(bigCert2), CERT_STORE_ADD_ALWAYS, NULL);
716 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n", GetLastError());
717 /* Now check that it was actually added to store2 */
718 context = CertEnumCertificatesInStore(store2, NULL);
719 ok(context != NULL, "Expected a valid context\n");
720 if (context)
722 ok(context->hCertStore == store2, "Unexpected store\n");
723 CertFreeCertificateContext(context);
725 /* Check that the collection has both bigCert and bigCert2. bigCert comes
726 * first because store1 was added first.
728 context = CertEnumCertificatesInStore(collection, NULL);
729 ok(context != NULL, "Expected a valid context\n");
730 if (context)
732 ok(context->hCertStore == collection, "Unexpected store\n");
733 ok(context->cbCertEncoded == sizeof(bigCert),
734 "Wrong size %d\n", context->cbCertEncoded);
735 ok(!memcmp(context->pbCertEncoded, bigCert, context->cbCertEncoded),
736 "Unexpected cert\n");
737 context = CertEnumCertificatesInStore(collection, context);
738 ok(context != NULL, "Expected a valid context\n");
739 if (context)
741 ok(context->hCertStore == collection, "Unexpected store\n");
742 ok(context->cbCertEncoded == sizeof(bigCert2),
743 "Wrong size %d\n", context->cbCertEncoded);
744 ok(!memcmp(context->pbCertEncoded, bigCert2,
745 context->cbCertEncoded), "Unexpected cert\n");
746 context = CertEnumCertificatesInStore(collection, context);
747 ok(!context, "Unexpected cert\n");
750 /* close store2, and check that the collection is unmodified */
751 CertCloseStore(store2, 0);
752 context = CertEnumCertificatesInStore(collection, NULL);
753 ok(context != NULL, "Expected a valid context\n");
754 if (context)
756 ok(context->hCertStore == collection, "Unexpected store\n");
757 ok(context->cbCertEncoded == sizeof(bigCert),
758 "Wrong size %d\n", context->cbCertEncoded);
759 ok(!memcmp(context->pbCertEncoded, bigCert, context->cbCertEncoded),
760 "Unexpected cert\n");
761 context = CertEnumCertificatesInStore(collection, context);
762 ok(context != NULL, "Expected a valid context\n");
763 if (context)
765 ok(context->hCertStore == collection, "Unexpected store\n");
766 ok(context->cbCertEncoded == sizeof(bigCert2),
767 "Wrong size %d\n", context->cbCertEncoded);
768 ok(!memcmp(context->pbCertEncoded, bigCert2,
769 context->cbCertEncoded), "Unexpected cert\n");
770 context = CertEnumCertificatesInStore(collection, context);
771 ok(!context, "Unexpected cert\n");
775 /* Adding a collection to a collection is legal */
776 collection2 = CertOpenStore(CERT_STORE_PROV_COLLECTION, 0, 0,
777 CERT_STORE_CREATE_NEW_FLAG, NULL);
778 ret = pCertAddStoreToCollection(collection2, collection,
779 CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
780 ok(ret, "CertAddStoreToCollection failed: %08x\n", GetLastError());
781 /* check the contents of collection2 */
782 context = CertEnumCertificatesInStore(collection2, NULL);
783 ok(context != NULL, "Expected a valid context\n");
784 if (context)
786 ok(context->hCertStore == collection2, "Unexpected store\n");
787 ok(context->cbCertEncoded == sizeof(bigCert),
788 "Wrong size %d\n", context->cbCertEncoded);
789 ok(!memcmp(context->pbCertEncoded, bigCert, context->cbCertEncoded),
790 "Unexpected cert\n");
791 context = CertEnumCertificatesInStore(collection2, context);
792 ok(context != NULL, "Expected a valid context\n");
793 if (context)
795 ok(context->hCertStore == collection2, "Unexpected store\n");
796 ok(context->cbCertEncoded == sizeof(bigCert2),
797 "Wrong size %d\n", context->cbCertEncoded);
798 ok(!memcmp(context->pbCertEncoded, bigCert2,
799 context->cbCertEncoded), "Unexpected cert\n");
800 context = CertEnumCertificatesInStore(collection2, context);
801 ok(!context, "Unexpected cert\n");
805 /* I'd like to test closing the collection in the middle of enumeration,
806 * but my tests have been inconsistent. The first time calling
807 * CertEnumCertificatesInStore on a closed collection succeeded, while the
808 * second crashed. So anything appears to be fair game.
809 * I'd also like to test removing a store from a collection in the middle
810 * of an enumeration, but my tests in Windows have been inconclusive.
811 * In one scenario it worked. In another scenario, about a third of the
812 * time this leads to "random" crashes elsewhere in the code. This
813 * probably means this is not allowed.
816 CertCloseStore(store1, 0);
817 CertCloseStore(collection, 0);
818 CertCloseStore(collection2, 0);
820 /* Add the same cert to two memory stores, then put them in a collection */
821 store1 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
822 CERT_STORE_CREATE_NEW_FLAG, NULL);
823 ok(store1 != 0, "CertOpenStore failed: %08x\n", GetLastError());
824 store2 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
825 CERT_STORE_CREATE_NEW_FLAG, NULL);
826 ok(store2 != 0, "CertOpenStore failed: %08x\n", GetLastError());
828 ret = CertAddEncodedCertificateToStore(store1, X509_ASN_ENCODING,
829 bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, NULL);
830 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n", GetLastError());
831 ret = CertAddEncodedCertificateToStore(store2, X509_ASN_ENCODING,
832 bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, NULL);
833 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n", GetLastError());
834 collection = CertOpenStore(CERT_STORE_PROV_COLLECTION, 0, 0,
835 CERT_STORE_CREATE_NEW_FLAG, NULL);
836 ok(collection != 0, "CertOpenStore failed: %08x\n", GetLastError());
838 ret = pCertAddStoreToCollection(collection, store1,
839 CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
840 ok(ret, "CertAddStoreToCollection failed: %08x\n", GetLastError());
841 ret = pCertAddStoreToCollection(collection, store2,
842 CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
843 ok(ret, "CertAddStoreToCollection failed: %08x\n", GetLastError());
845 /* Check that the collection has two copies of the same cert */
846 context = CertEnumCertificatesInStore(collection, NULL);
847 ok(context != NULL, "Expected a valid context\n");
848 if (context)
850 ok(context->hCertStore == collection, "Unexpected store\n");
851 ok(context->cbCertEncoded == sizeof(bigCert),
852 "Wrong size %d\n", context->cbCertEncoded);
853 ok(!memcmp(context->pbCertEncoded, bigCert, context->cbCertEncoded),
854 "Unexpected cert\n");
855 context = CertEnumCertificatesInStore(collection, context);
856 ok(context != NULL, "Expected a valid context\n");
857 if (context)
859 ok(context->hCertStore == collection, "Unexpected store\n");
860 ok(context->cbCertEncoded == sizeof(bigCert),
861 "Wrong size %d\n", context->cbCertEncoded);
862 ok(!memcmp(context->pbCertEncoded, bigCert, context->cbCertEncoded),
863 "Unexpected cert\n");
864 context = CertEnumCertificatesInStore(collection, context);
865 ok(context == NULL, "Unexpected cert\n");
869 /* The following would check whether I can delete an identical cert, rather
870 * than one enumerated from the store. It crashes, so that means I must
871 * only call CertDeleteCertificateFromStore with contexts enumerated from
872 * the store.
873 context = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert,
874 sizeof(bigCert));
875 ok(context != NULL, "CertCreateCertificateContext failed: %08x\n",
876 GetLastError());
877 if (context)
879 ret = CertDeleteCertificateFromStore(collection, context);
880 printf("ret is %d, GetLastError is %08x\n", ret, GetLastError());
881 CertFreeCertificateContext(context);
885 /* Now check deleting from the collection. */
886 context = CertEnumCertificatesInStore(collection, NULL);
887 ok(context != NULL, "Expected a valid context\n");
888 if (context)
890 CertDeleteCertificateFromStore(context);
891 /* store1 should now be empty */
892 context = CertEnumCertificatesInStore(store1, NULL);
893 ok(!context, "Unexpected cert\n");
894 /* and there should be one certificate in the collection */
895 context = CertEnumCertificatesInStore(collection, NULL);
896 ok(context != NULL, "Expected a valid cert\n");
897 if (context)
899 ok(context->hCertStore == collection, "Unexpected store\n");
900 ok(context->cbCertEncoded == sizeof(bigCert),
901 "Wrong size %d\n", context->cbCertEncoded);
902 ok(!memcmp(context->pbCertEncoded, bigCert, context->cbCertEncoded),
903 "Unexpected cert\n");
905 context = CertEnumCertificatesInStore(collection, context);
906 ok(context == NULL, "Unexpected cert\n");
909 if (!pCertRemoveStoreFromCollection)
911 win_skip("CertRemoveStoreFromCollection() is not available\n");
913 else
915 /* Finally, test removing stores from the collection. No return
916 * value, so it's a bit funny to test.
918 /* This crashes
919 * pCertRemoveStoreFromCollection(NULL, NULL);
921 /* This "succeeds," no crash, no last error set */
922 SetLastError(0xdeadbeef);
923 pCertRemoveStoreFromCollection(store2, collection);
924 ok(GetLastError() == 0xdeadbeef,
925 "Didn't expect an error to be set: %08x\n", GetLastError());
927 /* After removing store2, the collection should be empty */
928 SetLastError(0xdeadbeef);
929 pCertRemoveStoreFromCollection(collection, store2);
930 ok(GetLastError() == 0xdeadbeef,
931 "Didn't expect an error to be set: %08x\n", GetLastError());
932 context = CertEnumCertificatesInStore(collection, NULL);
933 ok(!context, "Unexpected cert\n");
936 CertCloseStore(collection, 0);
937 CertCloseStore(store2, 0);
938 CertCloseStore(store1, 0);
940 /* Test adding certificates to and deleting certificates from collections.
942 store1 = CertOpenSystemStoreA(0, "My");
943 collection = CertOpenStore(CERT_STORE_PROV_COLLECTION, 0, 0,
944 CERT_STORE_CREATE_NEW_FLAG, NULL);
946 ret = CertAddEncodedCertificateToStore(store1, X509_ASN_ENCODING,
947 bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, &context);
948 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n", GetLastError());
949 CertDeleteCertificateFromStore(context);
951 pCertAddStoreToCollection(collection, store1,
952 CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
954 ret = CertAddEncodedCertificateToStore(collection, X509_ASN_ENCODING,
955 bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, &context);
956 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n", GetLastError());
957 CertDeleteCertificateFromStore(context);
959 CertCloseStore(collection, 0);
960 CertCloseStore(store1, 0);
962 /* Test whether a collection store can be committed */
963 if (!pCertControlStore)
965 win_skip("CertControlStore() is not available\n");
966 return;
968 collection = CertOpenStore(CERT_STORE_PROV_COLLECTION, 0, 0,
969 CERT_STORE_CREATE_NEW_FLAG, NULL);
971 SetLastError(0xdeadbeef);
972 ret = pCertControlStore(collection, 0, CERT_STORE_CTRL_COMMIT, NULL);
973 ok(ret, "CertControlStore failed: %08x\n", GetLastError());
975 /* Adding a mem store that can't be committed prevents a successful commit.
977 store1 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
978 CERT_STORE_CREATE_NEW_FLAG, NULL);
979 pCertAddStoreToCollection(collection, store1, 0, 0);
980 SetLastError(0xdeadbeef);
981 ret = pCertControlStore(collection, 0, CERT_STORE_CTRL_COMMIT, NULL);
982 ok(!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED,
983 "expected ERROR_CALL_NOT_IMPLEMENTED, got %d\n", GetLastError());
984 pCertRemoveStoreFromCollection(collection, store1);
985 CertCloseStore(store1, 0);
987 /* Test adding a cert to a collection with a file store, committing the
988 * change to the collection, and comparing the resulting file.
990 if (!GetTempFileNameW(szDot, szPrefix, 0, filename))
991 return;
993 DeleteFileW(filename);
994 file = CreateFileW(filename, GENERIC_READ | GENERIC_WRITE, 0, NULL,
995 CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
996 if (file == INVALID_HANDLE_VALUE)
997 return;
999 store1 = CertOpenStore(CERT_STORE_PROV_FILE, 0, 0,
1000 CERT_FILE_STORE_COMMIT_ENABLE_FLAG, file);
1001 ok(store1 != NULL, "CertOpenStore failed: %08x\n", GetLastError());
1002 CloseHandle(file);
1003 pCertAddStoreToCollection(collection, store1,
1004 CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
1005 CertCloseStore(store1, 0);
1007 ret = CertAddEncodedCertificateToStore(collection, X509_ASN_ENCODING,
1008 bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, NULL);
1009 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
1010 GetLastError());
1011 ret = pCertControlStore(collection, 0, CERT_STORE_CTRL_COMMIT, NULL);
1012 ok(ret, "CertControlStore failed: %d\n", ret);
1013 compareStore(collection, "serialized store with cert",
1014 serializedStoreWithCert, sizeof(serializedStoreWithCert), FALSE);
1015 CertCloseStore(collection, 0);
1017 DeleteFileW(filename);
1020 /* Looks for the property with ID propID in the buffer buf. Returns a pointer
1021 * to its header if found, NULL if not.
1023 static const struct CertPropIDHeader *findPropID(const BYTE *buf, DWORD size,
1024 DWORD propID)
1026 const struct CertPropIDHeader *ret = NULL;
1027 BOOL failed = FALSE;
1029 while (size && !ret && !failed)
1031 if (size < sizeof(struct CertPropIDHeader))
1032 failed = TRUE;
1033 else
1035 const struct CertPropIDHeader *hdr =
1036 (const struct CertPropIDHeader *)buf;
1038 size -= sizeof(struct CertPropIDHeader);
1039 buf += sizeof(struct CertPropIDHeader);
1040 if (size < hdr->cb)
1041 failed = TRUE;
1042 else if (hdr->propID == propID)
1043 ret = hdr;
1044 else
1046 buf += hdr->cb;
1047 size -= hdr->cb;
1051 return ret;
1054 static void testRegStore(void)
1056 static const char tempKey[] = "Software\\Wine\\CryptTemp";
1057 HCERTSTORE store;
1058 LONG rc;
1059 HKEY key = NULL;
1060 DWORD disp, GLE;
1062 store = CertOpenStore(CERT_STORE_PROV_REG, 0, 0, 0, NULL);
1063 GLE = GetLastError();
1064 ok(!store && (GLE == ERROR_INVALID_HANDLE || GLE == ERROR_BADKEY),
1065 "Expected ERROR_INVALID_HANDLE or ERROR_BADKEY, got %d\n", GLE);
1066 store = CertOpenStore(CERT_STORE_PROV_REG, 0, 0, 0, key);
1067 GLE = GetLastError();
1068 ok(!store && (GLE == ERROR_INVALID_HANDLE || GLE == ERROR_BADKEY),
1069 "Expected ERROR_INVALID_HANDLE or ERROR_BADKEY, got %d\n", GLE);
1071 /* Opening up any old key works.. */
1072 key = HKEY_CURRENT_USER;
1073 store = CertOpenStore(CERT_STORE_PROV_REG, 0, 0, 0, key);
1074 /* Not sure if this is a bug in DuplicateHandle, marking todo_wine for now
1076 todo_wine ok(store != 0, "CertOpenStore failed: %08x\n", GetLastError());
1077 CertCloseStore(store, 0);
1079 /* It looks like the remainder pretty much needs CertControlStore() */
1080 if (!pCertControlStore)
1082 win_skip("CertControlStore() is not available\n");
1083 return;
1086 rc = RegCreateKeyExA(HKEY_CURRENT_USER, tempKey, 0, NULL, 0, KEY_ALL_ACCESS,
1087 NULL, &key, NULL);
1088 ok(!rc, "RegCreateKeyExA failed: %d\n", rc);
1089 if (key)
1091 BOOL ret;
1092 BYTE hash[20];
1093 DWORD size, i;
1094 static const char certificates[] = "Certificates\\";
1095 char subKeyName[sizeof(certificates) + 20 * 2 + 1], *ptr;
1096 HKEY subKey;
1097 PCCERT_CONTEXT context;
1099 store = CertOpenStore(CERT_STORE_PROV_REG, 0, 0, 0, key);
1100 ok(store != 0, "CertOpenStore failed: %08x\n", GetLastError());
1101 /* Add a certificate. It isn't persisted right away, since it's only
1102 * added to the cache..
1104 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1105 bigCert2, sizeof(bigCert2), CERT_STORE_ADD_ALWAYS, NULL);
1106 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
1107 GetLastError());
1108 /* so flush the cache to force a commit.. */
1109 ret = pCertControlStore(store, 0, CERT_STORE_CTRL_COMMIT, NULL);
1110 ok(ret, "CertControlStore failed: %08x\n", GetLastError());
1111 /* and check that the expected subkey was written. */
1112 size = sizeof(hash);
1113 ret = CryptHashCertificate(0, 0, 0, bigCert2, sizeof(bigCert2),
1114 hash, &size);
1115 ok(ret, "CryptHashCertificate failed: %d\n", GetLastError());
1116 strcpy(subKeyName, certificates);
1117 for (i = 0, ptr = subKeyName + sizeof(certificates) - 1; i < size;
1118 i++, ptr += 2)
1119 sprintf(ptr, "%02X", hash[i]);
1120 rc = RegCreateKeyExA(key, subKeyName, 0, NULL, 0, KEY_ALL_ACCESS, NULL,
1121 &subKey, NULL);
1122 ok(!rc, "RegCreateKeyExA failed: %d\n", rc);
1123 if (subKey)
1125 LPBYTE buf;
1127 size = 0;
1128 RegQueryValueExA(subKey, "Blob", NULL, NULL, NULL, &size);
1129 buf = HeapAlloc(GetProcessHeap(), 0, size);
1130 if (buf)
1132 rc = RegQueryValueExA(subKey, "Blob", NULL, NULL, buf, &size);
1133 ok(!rc, "RegQueryValueExA failed: %d\n", rc);
1134 if (!rc)
1136 const struct CertPropIDHeader *hdr;
1138 /* Both the hash and the cert should be present */
1139 hdr = findPropID(buf, size, CERT_CERT_PROP_ID);
1140 ok(hdr != NULL, "Expected to find a cert property\n");
1141 if (hdr)
1143 ok(hdr->cb == sizeof(bigCert2),
1144 "Wrong size %d of cert property\n", hdr->cb);
1145 ok(!memcmp((const BYTE *)hdr + sizeof(*hdr), bigCert2,
1146 hdr->cb), "Unexpected cert in cert property\n");
1148 hdr = findPropID(buf, size, CERT_HASH_PROP_ID);
1149 ok(hdr != NULL, "Expected to find a hash property\n");
1150 if (hdr)
1152 ok(hdr->cb == sizeof(hash),
1153 "Wrong size %d of hash property\n", hdr->cb);
1154 ok(!memcmp((const BYTE *)hdr + sizeof(*hdr), hash,
1155 hdr->cb), "Unexpected hash in cert property\n");
1158 HeapFree(GetProcessHeap(), 0, buf);
1160 RegCloseKey(subKey);
1163 /* Remove the existing context */
1164 context = CertEnumCertificatesInStore(store, NULL);
1165 ok(context != NULL, "Expected a cert context\n");
1166 if (context)
1167 CertDeleteCertificateFromStore(context);
1168 ret = pCertControlStore(store, 0, CERT_STORE_CTRL_COMMIT, NULL);
1169 ok(ret, "CertControlStore failed: %08x\n", GetLastError());
1171 /* Add a serialized cert with a bogus hash directly to the registry */
1172 memset(hash, 0, sizeof(hash));
1173 strcpy(subKeyName, certificates);
1174 for (i = 0, ptr = subKeyName + sizeof(certificates) - 1;
1175 i < sizeof(hash); i++, ptr += 2)
1176 sprintf(ptr, "%02X", hash[i]);
1177 rc = RegCreateKeyExA(key, subKeyName, 0, NULL, 0, KEY_ALL_ACCESS, NULL,
1178 &subKey, NULL);
1179 ok(!rc, "RegCreateKeyExA failed: %d\n", rc);
1180 if (subKey)
1182 BYTE buf[sizeof(struct CertPropIDHeader) * 2 + sizeof(hash) +
1183 sizeof(bigCert)], *ptr;
1184 DWORD certCount = 0;
1185 struct CertPropIDHeader *hdr;
1187 hdr = (struct CertPropIDHeader *)buf;
1188 hdr->propID = CERT_HASH_PROP_ID;
1189 hdr->unknown1 = 1;
1190 hdr->cb = sizeof(hash);
1191 ptr = buf + sizeof(*hdr);
1192 memcpy(ptr, hash, sizeof(hash));
1193 ptr += sizeof(hash);
1194 hdr = (struct CertPropIDHeader *)ptr;
1195 hdr->propID = CERT_CERT_PROP_ID;
1196 hdr->unknown1 = 1;
1197 hdr->cb = sizeof(bigCert);
1198 ptr += sizeof(*hdr);
1199 memcpy(ptr, bigCert, sizeof(bigCert));
1201 rc = RegSetValueExA(subKey, "Blob", 0, REG_BINARY, buf,
1202 sizeof(buf));
1203 ok(!rc, "RegSetValueExA failed: %d\n", rc);
1205 ret = pCertControlStore(store, 0, CERT_STORE_CTRL_RESYNC, NULL);
1206 ok(ret, "CertControlStore failed: %08x\n", GetLastError());
1208 /* Make sure the bogus hash cert gets loaded. */
1209 certCount = 0;
1210 context = NULL;
1211 do {
1212 context = CertEnumCertificatesInStore(store, context);
1213 if (context)
1214 certCount++;
1215 } while (context != NULL);
1216 ok(certCount == 1, "Expected 1 certificates, got %d\n", certCount);
1218 RegCloseKey(subKey);
1221 /* Add another serialized cert directly to the registry, this time
1222 * under the correct key name (named with the correct hash value).
1224 size = sizeof(hash);
1225 ret = CryptHashCertificate(0, 0, 0, bigCert2,
1226 sizeof(bigCert2), hash, &size);
1227 ok(ret, "CryptHashCertificate failed: %d\n", GetLastError());
1228 strcpy(subKeyName, certificates);
1229 for (i = 0, ptr = subKeyName + sizeof(certificates) - 1;
1230 i < sizeof(hash); i++, ptr += 2)
1231 sprintf(ptr, "%02X", hash[i]);
1232 rc = RegCreateKeyExA(key, subKeyName, 0, NULL, 0, KEY_ALL_ACCESS, NULL,
1233 &subKey, NULL);
1234 ok(!rc, "RegCreateKeyExA failed: %d\n", rc);
1235 if (subKey)
1237 BYTE buf[sizeof(struct CertPropIDHeader) * 2 + sizeof(hash) +
1238 sizeof(bigCert2)], *ptr;
1239 DWORD certCount = 0;
1240 PCCERT_CONTEXT context;
1241 struct CertPropIDHeader *hdr;
1243 /* First try with a bogus hash... */
1244 hdr = (struct CertPropIDHeader *)buf;
1245 hdr->propID = CERT_HASH_PROP_ID;
1246 hdr->unknown1 = 1;
1247 hdr->cb = sizeof(hash);
1248 ptr = buf + sizeof(*hdr);
1249 memset(ptr, 0, sizeof(hash));
1250 ptr += sizeof(hash);
1251 hdr = (struct CertPropIDHeader *)ptr;
1252 hdr->propID = CERT_CERT_PROP_ID;
1253 hdr->unknown1 = 1;
1254 hdr->cb = sizeof(bigCert2);
1255 ptr += sizeof(*hdr);
1256 memcpy(ptr, bigCert2, sizeof(bigCert2));
1258 rc = RegSetValueExA(subKey, "Blob", 0, REG_BINARY, buf,
1259 sizeof(buf));
1260 ok(!rc, "RegSetValueExA failed: %d\n", rc);
1262 ret = pCertControlStore(store, 0, CERT_STORE_CTRL_RESYNC, NULL);
1263 ok(ret, "CertControlStore failed: %08x\n", GetLastError());
1265 /* and make sure just one cert still gets loaded. */
1266 certCount = 0;
1267 context = NULL;
1268 do {
1269 context = CertEnumCertificatesInStore(store, context);
1270 if (context)
1271 certCount++;
1272 } while (context != NULL);
1273 ok(certCount == 1 ||
1274 broken(certCount == 2) /* NT4 */ ,
1275 "Expected 1 certificates, got %d\n", certCount);
1277 /* Try again with the correct hash... */
1278 ptr = buf + sizeof(*hdr);
1279 memcpy(ptr, hash, sizeof(hash));
1281 rc = RegSetValueExA(subKey, "Blob", 0, REG_BINARY, buf,
1282 sizeof(buf));
1283 ok(!rc, "RegSetValueExA failed: %d\n", rc);
1285 ret = pCertControlStore(store, 0, CERT_STORE_CTRL_RESYNC, NULL);
1286 ok(ret, "CertControlStore failed: %08x\n", GetLastError());
1288 /* and make sure two certs get loaded. */
1289 certCount = 0;
1290 context = NULL;
1291 do {
1292 context = CertEnumCertificatesInStore(store, context);
1293 if (context)
1294 certCount++;
1295 } while (context != NULL);
1296 ok(certCount == 2, "Expected 2 certificates, got %d\n", certCount);
1298 RegCloseKey(subKey);
1300 CertCloseStore(store, 0);
1301 /* Is delete allowed on a reg store? */
1302 store = CertOpenStore(CERT_STORE_PROV_REG, 0, 0,
1303 CERT_STORE_DELETE_FLAG, key);
1304 ok(store == NULL, "Expected NULL return from CERT_STORE_DELETE_FLAG\n");
1305 ok(GetLastError() == 0, "CertOpenStore failed: %08x\n",
1306 GetLastError());
1308 RegCloseKey(key);
1310 /* The CertOpenStore with CERT_STORE_DELETE_FLAG above will delete the
1311 * contents of the key, but not the key itself.
1313 rc = RegCreateKeyExA(HKEY_CURRENT_USER, tempKey, 0, NULL, 0, KEY_ALL_ACCESS,
1314 NULL, &key, &disp);
1315 ok(!rc, "RegCreateKeyExA failed: %d\n", rc);
1316 ok(disp == REG_OPENED_EXISTING_KEY,
1317 "Expected REG_OPENED_EXISTING_KEY, got %d\n", disp);
1318 if (!rc)
1320 RegCloseKey(key);
1321 rc = RegDeleteKeyA(HKEY_CURRENT_USER, tempKey);
1322 if (rc)
1324 HMODULE shlwapi = LoadLibraryA("shlwapi");
1326 /* Use shlwapi's SHDeleteKeyA to _really_ blow away the key,
1327 * otherwise subsequent tests will fail.
1329 if (shlwapi)
1331 DWORD (WINAPI *pSHDeleteKeyA)(HKEY, LPCSTR);
1333 pSHDeleteKeyA = (void*)GetProcAddress(shlwapi, "SHDeleteKeyA");
1334 if (pSHDeleteKeyA)
1335 pSHDeleteKeyA(HKEY_CURRENT_USER, tempKey);
1336 FreeLibrary(shlwapi);
1342 static const char MyA[] = { 'M','y',0,0 };
1343 static const WCHAR MyW[] = { 'M','y',0 };
1344 static const WCHAR BogusW[] = { 'B','o','g','u','s',0 };
1345 static const WCHAR BogusPathW[] = { 'S','o','f','t','w','a','r','e','\\',
1346 'M','i','c','r','o','s','o','f','t','\\','S','y','s','t','e','m','C','e','r',
1347 't','i','f','i','c','a','t','e','s','\\','B','o','g','u','s',0 };
1349 static void testSystemRegStore(void)
1351 HCERTSTORE store, memStore;
1353 /* Check with a UNICODE name */
1354 store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY, 0, 0,
1355 CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_OPEN_EXISTING_FLAG, MyW);
1356 /* Not all OSes support CERT_STORE_PROV_SYSTEM_REGISTRY, so don't continue
1357 * testing if they don't.
1359 if (!store)
1360 return;
1362 /* Check that it isn't a collection store */
1363 memStore = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
1364 CERT_STORE_CREATE_NEW_FLAG, NULL);
1365 if (memStore)
1367 if (pCertAddStoreToCollection)
1369 BOOL ret = pCertAddStoreToCollection(store, memStore, 0, 0);
1370 ok(!ret && GetLastError() == E_INVALIDARG,
1371 "Expected E_INVALIDARG, got %08x\n", GetLastError());
1373 CertCloseStore(memStore, 0);
1375 CertCloseStore(store, 0);
1377 /* Check opening a bogus store */
1378 store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY, 0, 0,
1379 CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_OPEN_EXISTING_FLAG, BogusW);
1380 ok(!store && GetLastError() == ERROR_FILE_NOT_FOUND,
1381 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
1382 store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY, 0, 0,
1383 CERT_SYSTEM_STORE_CURRENT_USER, BogusW);
1384 ok(store != 0, "CertOpenStore failed: %08x\n", GetLastError());
1385 if (store)
1386 CertCloseStore(store, 0);
1387 /* Now check whether deleting is allowed */
1388 store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY, 0, 0,
1389 CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_DELETE_FLAG, BogusW);
1390 ok(!store, "CertOpenStore failed: %08x\n", GetLastError());
1391 RegDeleteKeyW(HKEY_CURRENT_USER, BogusPathW);
1393 store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY, 0, 0, 0, NULL);
1394 ok(!store && GetLastError() == E_INVALIDARG,
1395 "Expected E_INVALIDARG, got %08x\n", GetLastError());
1396 store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY, 0, 0,
1397 CERT_SYSTEM_STORE_LOCAL_MACHINE | CERT_SYSTEM_STORE_CURRENT_USER, MyA);
1398 ok(!store && GetLastError() == E_INVALIDARG,
1399 "Expected E_INVALIDARG, got %08x\n", GetLastError());
1400 store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY, 0, 0,
1401 CERT_SYSTEM_STORE_LOCAL_MACHINE | CERT_SYSTEM_STORE_CURRENT_USER, MyW);
1402 ok(!store && GetLastError() == E_INVALIDARG,
1403 "Expected E_INVALIDARG, got %08x\n", GetLastError());
1404 /* The name is expected to be UNICODE, check with an ASCII name */
1405 store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY, 0, 0,
1406 CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_OPEN_EXISTING_FLAG, MyA);
1407 ok(!store && GetLastError() == ERROR_FILE_NOT_FOUND,
1408 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
1411 static void testSystemStore(void)
1413 static const WCHAR baskslashW[] = { '\\',0 };
1414 HCERTSTORE store;
1415 WCHAR keyName[MAX_PATH];
1416 HKEY key;
1417 LONG rc;
1419 store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0, 0, NULL);
1420 ok(!store && GetLastError() == ERROR_FILE_NOT_FOUND,
1421 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
1422 store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0,
1423 CERT_SYSTEM_STORE_LOCAL_MACHINE | CERT_SYSTEM_STORE_CURRENT_USER, MyA);
1424 ok(!store && GetLastError() == ERROR_FILE_NOT_FOUND,
1425 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
1426 store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0,
1427 CERT_SYSTEM_STORE_LOCAL_MACHINE | CERT_SYSTEM_STORE_CURRENT_USER, MyW);
1428 ok(!store && GetLastError() == ERROR_FILE_NOT_FOUND,
1429 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
1430 /* The name is expected to be UNICODE, first check with an ASCII name */
1431 store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0,
1432 CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_OPEN_EXISTING_FLAG, MyA);
1433 ok(!store && GetLastError() == ERROR_FILE_NOT_FOUND,
1434 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
1435 /* Create the expected key */
1436 lstrcpyW(keyName, CERT_LOCAL_MACHINE_SYSTEM_STORE_REGPATH);
1437 lstrcatW(keyName, baskslashW);
1438 lstrcatW(keyName, MyW);
1439 rc = RegCreateKeyExW(HKEY_CURRENT_USER, keyName, 0, NULL, 0, KEY_READ,
1440 NULL, &key, NULL);
1441 ok(!rc, "RegCreateKeyEx failed: %d\n", rc);
1442 if (!rc)
1443 RegCloseKey(key);
1444 /* Check opening with a UNICODE name, specifying the create new flag */
1445 store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0,
1446 CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_CREATE_NEW_FLAG, MyW);
1447 ok(!store && GetLastError() == ERROR_FILE_EXISTS,
1448 "Expected ERROR_FILE_EXISTS, got %08x\n", GetLastError());
1449 /* Now check opening with a UNICODE name, this time opening existing */
1450 store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0,
1451 CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_OPEN_EXISTING_FLAG, MyW);
1452 ok(store != 0, "CertOpenStore failed: %08x\n", GetLastError());
1453 if (store)
1455 HCERTSTORE memStore = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
1456 CERT_STORE_CREATE_NEW_FLAG, NULL);
1458 /* Check that it's a collection store */
1459 if (memStore)
1461 if (pCertAddStoreToCollection)
1463 BOOL ret = pCertAddStoreToCollection(store, memStore, 0, 0);
1464 /* FIXME: this'll fail on NT4, but what error will it give? */
1465 ok(ret, "CertAddStoreToCollection failed: %08x\n", GetLastError());
1467 CertCloseStore(memStore, 0);
1469 CertCloseStore(store, 0);
1472 /* Check opening a bogus store */
1473 store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0,
1474 CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_OPEN_EXISTING_FLAG, BogusW);
1475 ok(!store, "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
1476 store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0,
1477 CERT_SYSTEM_STORE_CURRENT_USER, BogusW);
1478 ok(store != 0, "CertOpenStore failed: %08x\n", GetLastError());
1479 if (store)
1480 CertCloseStore(store, 0);
1481 /* Now check whether deleting is allowed */
1482 store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0,
1483 CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_DELETE_FLAG, BogusW);
1484 ok(!store, "Didn't expect a store to be returned when deleting\n");
1485 RegDeleteKeyW(HKEY_CURRENT_USER, BogusPathW);
1488 static const BYTE serializedStoreWithCertAndCRL[] = {
1489 0x00,0x00,0x00,0x00,0x43,0x45,0x52,0x54,0x20,0x00,0x00,0x00,0x01,0x00,0x00,
1490 0x00,0x7c,0x00,0x00,0x00,0x30,0x7a,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,
1491 0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,
1492 0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,
1493 0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,
1494 0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,
1495 0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,
1496 0x20,0x4c,0x61,0x6e,0x67,0x00,0x30,0x07,0x30,0x02,0x06,0x00,0x03,0x01,0x00,
1497 0xa3,0x16,0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,
1498 0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01,0x21,0x00,0x00,0x00,0x01,0x00,
1499 0x00,0x00,0x47,0x00,0x00,0x00,0x30,0x45,0x30,0x2c,0x30,0x02,0x06,0x00,0x30,
1500 0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,
1501 0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
1502 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00,0x03,0x11,
1503 0x00,0x0f,0x0e,0x0d,0x0c,0x0b,0x0a,0x09,0x08,0x07,0x06,0x05,0x04,0x03,0x02,
1504 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 };
1506 static void testFileStore(void)
1508 static const WCHAR szPrefix[] = { 'c','e','r',0 };
1509 static const WCHAR szDot[] = { '.',0 };
1510 WCHAR filename[MAX_PATH];
1511 HCERTSTORE store;
1512 BOOL ret;
1513 PCCERT_CONTEXT cert;
1514 HANDLE file;
1516 if (!pCertControlStore)
1518 win_skip("CertControlStore() is not available\n");
1519 return;
1522 store = CertOpenStore(CERT_STORE_PROV_FILE, 0, 0, 0, NULL);
1523 ok(!store && GetLastError() == ERROR_INVALID_HANDLE,
1524 "Expected ERROR_INVALID_HANDLE, got %08x\n", GetLastError());
1526 if (!GetTempFileNameW(szDot, szPrefix, 0, filename))
1527 return;
1529 DeleteFileW(filename);
1530 file = CreateFileW(filename, GENERIC_READ | GENERIC_WRITE, 0, NULL,
1531 CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
1532 if (file == INVALID_HANDLE_VALUE)
1533 return;
1535 store = CertOpenStore(CERT_STORE_PROV_FILE, 0, 0, CERT_STORE_DELETE_FLAG,
1536 file);
1537 ok(!store && GetLastError() == E_INVALIDARG,
1538 "Expected E_INVALIDARG, got %08x\n", GetLastError());
1539 store = CertOpenStore(CERT_STORE_PROV_FILE, 0, 0,
1540 CERT_FILE_STORE_COMMIT_ENABLE_FLAG | CERT_STORE_READONLY_FLAG, file);
1541 ok(!store && GetLastError() == E_INVALIDARG,
1542 "Expected E_INVALIDARG, got %08x\n", GetLastError());
1544 /* A "read-only" file store.. */
1545 store = CertOpenStore(CERT_STORE_PROV_FILE, 0, 0,
1546 CERT_STORE_OPEN_EXISTING_FLAG | CERT_STORE_READONLY_FLAG, file);
1547 ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError());
1548 if (store)
1550 DWORD size;
1552 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1553 bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, NULL);
1554 /* apparently allows adding certificates.. */
1555 ok(ret, "CertAddEncodedCertificateToStore failed: %d\n", ret);
1556 /* but not commits.. */
1557 ret = pCertControlStore(store, 0, CERT_STORE_CTRL_COMMIT, NULL);
1558 ok(!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED,
1559 "Expected ERROR_CALL_NOT_IMPLEMENTED, got %08x\n", GetLastError());
1560 /* It still has certs in memory.. */
1561 cert = CertEnumCertificatesInStore(store, NULL);
1562 ok(cert != NULL, "CertEnumCertificatesInStore failed: %08x\n",
1563 GetLastError());
1564 CertFreeCertificateContext(cert);
1565 /* but the file size is still 0. */
1566 size = GetFileSize(file, NULL);
1567 ok(size == 0, "Expected size 0, got %d\n", size);
1568 CertCloseStore(store, 0);
1571 /* The create new flag is allowed.. */
1572 store = CertOpenStore(CERT_STORE_PROV_FILE, 0, 0,
1573 CERT_STORE_CREATE_NEW_FLAG, file);
1574 ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError());
1575 if (store)
1577 /* but without the commit enable flag, commits don't happen. */
1578 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1579 bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, NULL);
1580 ok(ret, "CertAddEncodedCertificateToStore failed: %d\n", ret);
1581 ret = pCertControlStore(store, 0, CERT_STORE_CTRL_COMMIT, NULL);
1582 ok(!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED,
1583 "Expected ERROR_CALL_NOT_IMPLEMENTED, got %08x\n", GetLastError());
1584 CertCloseStore(store, 0);
1586 /* as is the open existing flag. */
1587 store = CertOpenStore(CERT_STORE_PROV_FILE, 0, 0,
1588 CERT_STORE_OPEN_EXISTING_FLAG, file);
1589 ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError());
1590 if (store)
1592 /* but without the commit enable flag, commits don't happen. */
1593 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1594 bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, NULL);
1595 ok(ret, "CertAddEncodedCertificateToStore failed: %d\n", ret);
1596 ret = pCertControlStore(store, 0, CERT_STORE_CTRL_COMMIT, NULL);
1597 ok(!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED,
1598 "Expected ERROR_CALL_NOT_IMPLEMENTED, got %08x\n", GetLastError());
1599 CertCloseStore(store, 0);
1601 store = CertOpenStore(CERT_STORE_PROV_FILE, 0, 0,
1602 CERT_FILE_STORE_COMMIT_ENABLE_FLAG, file);
1603 ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError());
1604 if (store)
1606 CloseHandle(file);
1607 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1608 bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, NULL);
1609 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
1610 GetLastError());
1611 /* with commits enabled, commit is allowed */
1612 ret = pCertControlStore(store, 0, CERT_STORE_CTRL_COMMIT, NULL);
1613 ok(ret, "CertControlStore failed: %d\n", ret);
1614 compareStore(store, "serialized store with cert",
1615 serializedStoreWithCert, sizeof(serializedStoreWithCert), FALSE);
1616 CertCloseStore(store, 0);
1618 file = CreateFileW(filename, GENERIC_READ | GENERIC_WRITE, 0, NULL,
1619 OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
1620 if (file == INVALID_HANDLE_VALUE)
1621 return;
1622 store = CertOpenStore(CERT_STORE_PROV_FILE, 0, 0,
1623 CERT_FILE_STORE_COMMIT_ENABLE_FLAG, file);
1624 ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError());
1625 if (store)
1627 CloseHandle(file);
1628 ret = CertAddEncodedCRLToStore(store, X509_ASN_ENCODING, signedCRL,
1629 sizeof(signedCRL), CERT_STORE_ADD_ALWAYS, NULL);
1630 ok(ret, "CertAddEncodedCRLToStore failed: %08x\n", GetLastError());
1631 compareStore(store, "serialized store with cert and CRL",
1632 serializedStoreWithCertAndCRL, sizeof(serializedStoreWithCertAndCRL),
1633 FALSE);
1634 CertCloseStore(store, 0);
1637 DeleteFileW(filename);
1640 static BOOL initFileFromData(LPCWSTR filename, const BYTE *pb, DWORD cb)
1642 HANDLE file = CreateFileW(filename, GENERIC_READ | GENERIC_WRITE, 0, NULL,
1643 CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
1644 BOOL ret;
1646 if (file != INVALID_HANDLE_VALUE)
1648 DWORD written;
1650 ret = WriteFile(file, pb, cb, &written, NULL);
1651 CloseHandle(file);
1653 else
1654 ret = FALSE;
1655 return ret;
1658 static const BYTE base64SPC[] =
1659 "MIICJQYJKoZIhvcNAQcCoIICFjCCAhICAQExADALBgkqhkiG9w0BBwGgggH6MIIB"
1660 "9jCCAV+gAwIBAgIQnP8+EF4opr9OxH7h4uBPWTANBgkqhkiG9w0BAQQFADAUMRIw"
1661 "EAYDVQQDEwlKdWFuIExhbmcwHhcNMDgxMjEyMTcxMDE0WhcNMzkxMjMxMjM1OTU5"
1662 "WjAUMRIwEAYDVQQDEwlKdWFuIExhbmcwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJ"
1663 "AoGBALCgNjyNvOic0FOfjxvi43HbM+D5joDkhiGSXe+gbZlf8f16k07kkObFEunz"
1664 "mdB5coscmA7gyqiWNN4ZUyr2cA3lCbnpGPA/0IblyyOcuGIFmmCzeZaVa5ZG6xZP"
1665 "K7L7o+73Qo6jXVbGhBGnMZ7Q9sAn6s2933olnStnejnqwV0NAgMBAAGjSTBHMEUG"
1666 "A1UdAQQ+MDyAEFKbKEdXYyx+CWKcV6vxM6ShFjAUMRIwEAYDVQQDEwlKdWFuIExh"
1667 "bmeCEJz/PhBeKKa/TsR+4eLgT1kwDQYJKoZIhvcNAQEEBQADgYEALpkgLgW3mEaK"
1668 "idPQ3iPJYLG0Ub1wraqEl9bd42hrhzIdcDzlQgxnm8/5cHYVxIF/C20x/HJplb1R"
1669 "G6U1ipFe/q8byWD/9JpiBKMGPi9YlUTgXHfS9d4S/QWO1h9Z7KeipBYhoslQpHXu"
1670 "y9bUr8Adqi6SzgHpCnMu53dxgxUD1r4xAA==";
1671 /* Same as base64SPC, but as a wide-char string */
1672 static const WCHAR utf16Base64SPC[] = {
1673 'M','I','I','C','J','Q','Y','J','K','o','Z','I','h','v','c','N','A',
1674 'Q','c','C','o','I','I','C','F','j','C','C','A','h','I','C','A','Q',
1675 'E','x','A','D','A','L','B','g','k','q','h','k','i','G','9','w','0',
1676 'B','B','w','G','g','g','g','H','6','M','I','I','B','9','j','C','C',
1677 'A','V','+','g','A','w','I','B','A','g','I','Q','n','P','8','+','E',
1678 'F','4','o','p','r','9','O','x','H','7','h','4','u','B','P','W','T',
1679 'A','N','B','g','k','q','h','k','i','G','9','w','0','B','A','Q','Q',
1680 'F','A','D','A','U','M','R','I','w','E','A','Y','D','V','Q','Q','D',
1681 'E','w','l','K','d','W','F','u','I','E','x','h','b','m','c','w','H',
1682 'h','c','N','M','D','g','x','M','j','E','y','M','T','c','x','M','D',
1683 'E','0','W','h','c','N','M','z','k','x','M','j','M','x','M','j','M',
1684 '1','O','T','U','5','W','j','A','U','M','R','I','w','E','A','Y','D',
1685 'V','Q','Q','D','E','w','l','K','d','W','F','u','I','E','x','h','b',
1686 'm','c','w','g','Z','8','w','D','Q','Y','J','K','o','Z','I','h','v',
1687 'c','N','A','Q','E','B','B','Q','A','D','g','Y','0','A','M','I','G',
1688 'J','A','o','G','B','A','L','C','g','N','j','y','N','v','O','i','c',
1689 '0','F','O','f','j','x','v','i','4','3','H','b','M','+','D','5','j',
1690 'o','D','k','h','i','G','S','X','e','+','g','b','Z','l','f','8','f',
1691 '1','6','k','0','7','k','k','O','b','F','E','u','n','z','m','d','B',
1692 '5','c','o','s','c','m','A','7','g','y','q','i','W','N','N','4','Z',
1693 'U','y','r','2','c','A','3','l','C','b','n','p','G','P','A','/','0',
1694 'I','b','l','y','y','O','c','u','G','I','F','m','m','C','z','e','Z',
1695 'a','V','a','5','Z','G','6','x','Z','P','K','7','L','7','o','+','7',
1696 '3','Q','o','6','j','X','V','b','G','h','B','G','n','M','Z','7','Q',
1697 '9','s','A','n','6','s','2','9','3','3','o','l','n','S','t','n','e',
1698 'j','n','q','w','V','0','N','A','g','M','B','A','A','G','j','S','T',
1699 'B','H','M','E','U','G','A','1','U','d','A','Q','Q','+','M','D','y',
1700 'A','E','F','K','b','K','E','d','X','Y','y','x','+','C','W','K','c',
1701 'V','6','v','x','M','6','S','h','F','j','A','U','M','R','I','w','E',
1702 'A','Y','D','V','Q','Q','D','E','w','l','K','d','W','F','u','I','E',
1703 'x','h','b','m','e','C','E','J','z','/','P','h','B','e','K','K','a',
1704 '/','T','s','R','+','4','e','L','g','T','1','k','w','D','Q','Y','J',
1705 'K','o','Z','I','h','v','c','N','A','Q','E','E','B','Q','A','D','g',
1706 'Y','E','A','L','p','k','g','L','g','W','3','m','E','a','K','i','d',
1707 'P','Q','3','i','P','J','Y','L','G','0','U','b','1','w','r','a','q',
1708 'E','l','9','b','d','4','2','h','r','h','z','I','d','c','D','z','l',
1709 'Q','g','x','n','m','8','/','5','c','H','Y','V','x','I','F','/','C',
1710 '2','0','x','/','H','J','p','l','b','1','R','G','6','U','1','i','p',
1711 'F','e','/','q','8','b','y','W','D','/','9','J','p','i','B','K','M',
1712 'G','P','i','9','Y','l','U','T','g','X','H','f','S','9','d','4','S',
1713 '/','Q','W','O','1','h','9','Z','7','K','e','i','p','B','Y','h','o',
1714 's','l','Q','p','H','X','u','y','9','b','U','r','8','A','d','q','i',
1715 '6','S','z','g','H','p','C','n','M','u','5','3','d','x','g','x','U',
1716 'D','1','r','4','x','A','A','=','=',0 };
1718 static void testFileNameStore(void)
1720 static const WCHAR szPrefix[] = { 'c','e','r',0 };
1721 static const WCHAR spcPrefix[] = { 's','p','c',0 };
1722 static const WCHAR szDot[] = { '.',0 };
1723 WCHAR filename[MAX_PATH];
1724 HCERTSTORE store;
1725 BOOL ret;
1726 DWORD GLE;
1728 if (0)
1730 /* Crashes on NT4 */
1731 store = CertOpenStore(CERT_STORE_PROV_FILENAME_W, 0, 0, 0, NULL);
1732 GLE = GetLastError();
1733 ok(!store && (GLE == ERROR_PATH_NOT_FOUND || GLE == ERROR_INVALID_PARAMETER),
1734 "Expected ERROR_PATH_NOT_FOUND or ERROR_INVALID_PARAMETER, got %08x\n",
1735 GLE);
1738 if (!GetTempFileNameW(szDot, szPrefix, 0, filename))
1739 return;
1740 DeleteFileW(filename);
1742 /* The two flags are mutually exclusive */
1743 store = CertOpenStore(CERT_STORE_PROV_FILENAME_W, 0, 0,
1744 CERT_FILE_STORE_COMMIT_ENABLE_FLAG | CERT_STORE_READONLY_FLAG, filename);
1745 ok(!store && GetLastError() == E_INVALIDARG,
1746 "Expected E_INVALIDARG, got %08x\n", GetLastError());
1748 /* In all of the following tests, the encoding type seems to be ignored */
1749 if (initFileFromData(filename, bigCert, sizeof(bigCert)))
1751 PCCERT_CONTEXT cert;
1752 PCCRL_CONTEXT crl;
1754 store = CertOpenStore(CERT_STORE_PROV_FILENAME_W, 0, 0,
1755 CERT_STORE_READONLY_FLAG, filename);
1756 ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError());
1758 cert = CertEnumCertificatesInStore(store, NULL);
1759 ok(cert != NULL, "CertEnumCertificatesInStore failed: %08x\n",
1760 GetLastError());
1761 cert = CertEnumCertificatesInStore(store, cert);
1762 ok(!cert, "Expected only one cert\n");
1763 if (pCertEnumCRLsInStore)
1765 crl = pCertEnumCRLsInStore(store, NULL);
1766 ok(!crl, "Expected no CRLs\n");
1769 CertCloseStore(store, 0);
1770 DeleteFileW(filename);
1772 if (initFileFromData(filename, serializedStoreWithCert,
1773 sizeof(serializedStoreWithCert)))
1775 PCCERT_CONTEXT cert;
1776 PCCRL_CONTEXT crl;
1778 store = CertOpenStore(CERT_STORE_PROV_FILENAME_W, 0, 0,
1779 CERT_STORE_READONLY_FLAG, filename);
1780 ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError());
1782 cert = CertEnumCertificatesInStore(store, NULL);
1783 ok(cert != NULL, "CertEnumCertificatesInStore failed: %08x\n",
1784 GetLastError());
1785 cert = CertEnumCertificatesInStore(store, cert);
1786 ok(!cert, "Expected only one cert\n");
1787 if (pCertEnumCRLsInStore)
1789 crl = pCertEnumCRLsInStore(store, NULL);
1790 ok(!crl, "Expected no CRLs\n");
1793 CertCloseStore(store, 0);
1794 DeleteFileW(filename);
1796 if (initFileFromData(filename, serializedStoreWithCertAndCRL,
1797 sizeof(serializedStoreWithCertAndCRL)))
1799 PCCERT_CONTEXT cert;
1800 PCCRL_CONTEXT crl;
1802 store = CertOpenStore(CERT_STORE_PROV_FILENAME_W, 0, 0,
1803 CERT_STORE_READONLY_FLAG, filename);
1804 ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError());
1806 cert = CertEnumCertificatesInStore(store, NULL);
1807 ok(cert != NULL, "CertEnumCertificatesInStore failed: %08x\n",
1808 GetLastError());
1809 cert = CertEnumCertificatesInStore(store, cert);
1810 ok(!cert, "Expected only one cert\n");
1811 if (pCertEnumCRLsInStore)
1813 crl = pCertEnumCRLsInStore(store, NULL);
1814 ok(crl != NULL, "CertEnumCRLsInStore failed: %08x\n", GetLastError());
1815 crl = pCertEnumCRLsInStore(store, crl);
1816 ok(!crl, "Expected only one CRL\n");
1819 CertCloseStore(store, 0);
1820 /* Don't delete it this time, the next test uses it */
1822 /* Now that the file exists, we can open it read-only */
1823 store = CertOpenStore(CERT_STORE_PROV_FILENAME_W, 0, 0,
1824 CERT_STORE_READONLY_FLAG, filename);
1825 ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError());
1826 CertCloseStore(store, 0);
1827 DeleteFileW(filename);
1829 store = CertOpenStore(CERT_STORE_PROV_FILENAME_W, 0, 0,
1830 CERT_FILE_STORE_COMMIT_ENABLE_FLAG | CERT_STORE_CREATE_NEW_FLAG, filename);
1831 ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError());
1832 if (store)
1834 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1835 bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, NULL);
1836 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
1837 GetLastError());
1838 compareStore(store, "serialized store with cert",
1839 serializedStoreWithCert, sizeof(serializedStoreWithCert), FALSE);
1840 CertCloseStore(store, 0);
1842 store = CertOpenStore(CERT_STORE_PROV_FILENAME_W, 0, 0,
1843 CERT_FILE_STORE_COMMIT_ENABLE_FLAG, filename);
1844 ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError());
1845 if (store)
1847 ret = CertAddEncodedCRLToStore(store, X509_ASN_ENCODING,
1848 signedCRL, sizeof(signedCRL), CERT_STORE_ADD_ALWAYS, NULL);
1849 ok(ret, "CertAddEncodedCRLToStore failed: %08x\n", GetLastError());
1850 compareStore(store, "serialized store with cert and CRL",
1851 serializedStoreWithCertAndCRL, sizeof(serializedStoreWithCertAndCRL),
1852 FALSE);
1853 CertCloseStore(store, 0);
1855 DeleteFileW(filename);
1857 if (!GetTempFileNameW(szDot, spcPrefix, 0, filename))
1858 return;
1859 DeleteFileW(filename);
1861 if (initFileFromData(filename, base64SPC, sizeof(base64SPC)))
1863 PCCERT_CONTEXT cert;
1864 PCCRL_CONTEXT crl;
1866 store = CertOpenStore(CERT_STORE_PROV_FILENAME_W, 0, 0,
1867 CERT_STORE_READONLY_FLAG, filename);
1868 ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError());
1870 cert = CertEnumCertificatesInStore(store, NULL);
1871 ok(cert != NULL, "CertEnumCertificatesInStore failed: %08x\n",
1872 GetLastError());
1873 cert = CertEnumCertificatesInStore(store, cert);
1874 ok(!cert, "Expected only one cert\n");
1875 if (pCertEnumCRLsInStore)
1877 crl = pCertEnumCRLsInStore(store, NULL);
1878 ok(!crl, "Expected no CRLs\n");
1881 CertCloseStore(store, 0);
1882 DeleteFileW(filename);
1884 if (initFileFromData(filename, (BYTE *)utf16Base64SPC,
1885 sizeof(utf16Base64SPC)))
1887 PCCERT_CONTEXT cert;
1888 PCCRL_CONTEXT crl;
1890 store = CertOpenStore(CERT_STORE_PROV_FILENAME_W, 0, 0,
1891 CERT_STORE_READONLY_FLAG, filename);
1892 ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError());
1894 cert = CertEnumCertificatesInStore(store, NULL);
1895 ok(cert != NULL, "CertEnumCertificatesInStore failed: %08x\n",
1896 GetLastError());
1897 cert = CertEnumCertificatesInStore(store, cert);
1898 ok(!cert, "Expected only one cert\n");
1899 if (pCertEnumCRLsInStore)
1901 crl = pCertEnumCRLsInStore(store, NULL);
1902 ok(!crl, "Expected no CRLs\n");
1905 CertCloseStore(store, 0);
1906 DeleteFileW(filename);
1910 static const BYTE signedContent[] = {
1911 0x30,0x81,0xb2,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,0xa0,
1912 0x81,0xa4,0x30,0x81,0xa1,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,
1913 0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x13,0x06,0x09,0x2a,0x86,
1914 0x48,0x86,0xf7,0x0d,0x01,0x07,0x01,0xa0,0x06,0x04,0x04,0x01,0x02,0x03,0x04,
1915 0x31,0x77,0x30,0x75,0x02,0x01,0x01,0x30,0x1a,0x30,0x15,0x31,0x13,0x30,0x11,
1916 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
1917 0x67,0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,
1918 0x02,0x05,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04,0x40,0x81,0xa6,0x70,
1919 0xb3,0xef,0x59,0xd1,0x66,0xd1,0x9b,0xc0,0x9a,0xb6,0x9a,0x5e,0x6d,0x6f,0x6d,
1920 0x0d,0x59,0xa9,0xaa,0x6e,0xe9,0x2c,0xa0,0x1e,0xee,0xc2,0x60,0xbc,0x59,0xbe,
1921 0x3f,0x63,0x06,0x8d,0xc9,0x11,0x1d,0x23,0x64,0x92,0xef,0x2e,0xfc,0x57,0x29,
1922 0xa4,0xaf,0xe0,0xee,0x93,0x19,0x39,0x51,0xe4,0x44,0xb8,0x0b,0x28,0xf4,0xa8,
1923 0x0d };
1924 static const BYTE signedWithCertAndCrlBareContent[] = {
1925 0x30,0x82,0x01,0x4f,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,0x86,
1926 0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x13,0x06,0x09,0x2a,0x86,0x48,
1927 0x86,0xf7,0x0d,0x01,0x07,0x01,0xa0,0x06,0x04,0x04,0x01,0x02,0x03,0x04,0xa0,
1928 0x7c,0x30,0x7a,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,
1929 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
1930 0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,
1931 0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
1932 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,
1933 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
1934 0x67,0x00,0x30,0x07,0x30,0x02,0x06,0x00,0x03,0x01,0x00,0xa3,0x16,0x30,0x14,
1935 0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,
1936 0x01,0xff,0x02,0x01,0x01,0xa1,0x2e,0x30,0x2c,0x30,0x02,0x06,0x00,0x30,0x15,
1937 0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,
1938 0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
1939 0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x31,0x77,0x30,0x75,0x02,0x01,0x01,
1940 0x30,0x1a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,
1941 0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x02,0x01,0x01,0x30,0x0c,
1942 0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x04,0x06,
1943 0x00,0x05,0x00,0x04,0x40,0x81,0xa6,0x70,0xb3,0xef,0x59,0xd1,0x66,0xd1,0x9b,
1944 0xc0,0x9a,0xb6,0x9a,0x5e,0x6d,0x6f,0x6d,0x0d,0x59,0xa9,0xaa,0x6e,0xe9,0x2c,
1945 0xa0,0x1e,0xee,0xc2,0x60,0xbc,0x59,0xbe,0x3f,0x63,0x06,0x8d,0xc9,0x11,0x1d,
1946 0x23,0x64,0x92,0xef,0x2e,0xfc,0x57,0x29,0xa4,0xaf,0xe0,0xee,0x93,0x19,0x39,
1947 0x51,0xe4,0x44,0xb8,0x0b,0x28,0xf4,0xa8,0x0d };
1948 static const BYTE hashContent[] = {
1949 0x30,0x47,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x05,0xa0,0x3a,
1950 0x30,0x38,0x02,0x01,0x00,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,
1951 0x02,0x05,0x05,0x00,0x30,0x13,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
1952 0x07,0x01,0xa0,0x06,0x04,0x04,0x01,0x02,0x03,0x04,0x04,0x10,0x08,0xd6,0xc0,
1953 0x5a,0x21,0x51,0x2a,0x79,0xa1,0xdf,0xeb,0x9d,0x2a,0x8f,0x26,0x2f };
1954 static const BYTE hashBareContent[] = {
1955 0x30,0x38,0x02,0x01,0x00,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,
1956 0x02,0x05,0x05,0x00,0x30,0x13,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
1957 0x07,0x01,0xa0,0x06,0x04,0x04,0x01,0x02,0x03,0x04,0x04,0x10,0x08,0xd6,0xc0,
1958 0x5a,0x21,0x51,0x2a,0x79,0xa1,0xdf,0xeb,0x9d,0x2a,0x8f,0x26,0x2f };
1960 static void testMessageStore(void)
1962 HCERTSTORE store;
1963 HCRYPTMSG msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL,
1964 NULL);
1965 CRYPT_DATA_BLOB blob = { sizeof(signedWithCertAndCrlBareContent),
1966 (LPBYTE)signedWithCertAndCrlBareContent };
1967 DWORD count, size;
1968 BOOL ret;
1970 /* Crashes
1971 store = CertOpenStore(CERT_STORE_PROV_MSG, 0, 0, 0, NULL);
1973 SetLastError(0xdeadbeef);
1974 store = CertOpenStore(CERT_STORE_PROV_MSG, 0, 0, 0, msg);
1975 ok(!store && GetLastError() == CRYPT_E_INVALID_MSG_TYPE,
1976 "Expected CRYPT_E_INVALID_MSG_TYPE, got %08x\n", GetLastError());
1977 CryptMsgUpdate(msg, signedContent, sizeof(signedContent), TRUE);
1978 store = CertOpenStore(CERT_STORE_PROV_MSG, 0, 0, 0, msg);
1979 ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError());
1980 if (store)
1982 PCCERT_CONTEXT cert = NULL;
1983 PCCRL_CONTEXT crl = NULL;
1985 count = 0;
1986 do {
1987 cert = CertEnumCertificatesInStore(store, cert);
1988 if (cert)
1989 count++;
1990 } while (cert);
1991 ok(count == 0, "Expected 0 certificates, got %d\n", count);
1993 if (pCertEnumCRLsInStore)
1995 count = 0;
1996 do {
1997 crl = pCertEnumCRLsInStore(store, crl);
1998 if (crl)
1999 count++;
2000 } while (crl);
2001 ok(count == 0, "Expected 0 CRLs, got %d\n", count);
2004 /* Can add certs to a message store */
2005 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
2006 bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, NULL);
2007 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
2008 GetLastError());
2009 count = 0;
2010 do {
2011 cert = CertEnumCertificatesInStore(store, cert);
2012 if (cert)
2013 count++;
2014 } while (cert);
2015 ok(count == 1, "Expected 1 certificate, got %d\n", count);
2017 CertCloseStore(store, 0);
2019 /* but the added certs weren't actually added to the message */
2020 size = sizeof(count);
2021 ret = CryptMsgGetParam(msg, CMSG_CERT_COUNT_PARAM, 0, &count, &size);
2022 ok(ret, "CryptMsgGetParam failed: %08x\n", GetLastError());
2023 ok(count == 0, "Expected 0 certificates, got %d\n", count);
2024 CryptMsgClose(msg);
2026 /* Crashes
2027 store = CertOpenStore(CERT_STORE_PROV_PKCS7, 0, 0, 0, NULL);
2029 store = CertOpenStore(CERT_STORE_PROV_PKCS7, 0, 0, 0, &blob);
2030 ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError());
2031 if (store)
2033 DWORD count = 0;
2034 PCCERT_CONTEXT cert = NULL;
2035 PCCRL_CONTEXT crl = NULL;
2037 do {
2038 cert = CertEnumCertificatesInStore(store, cert);
2039 if (cert)
2040 count++;
2041 } while (cert);
2042 ok(count == 1, "Expected 1 certificate, got %d\n", count);
2044 if (pCertEnumCRLsInStore)
2046 count = 0;
2047 do {
2048 crl = pCertEnumCRLsInStore(store, crl);
2049 if (crl)
2050 count++;
2051 } while (crl);
2052 ok(count == 1, "Expected 1 CRL, got %d\n", count);
2054 CertCloseStore(store, 0);
2056 /* Encoding appears to be ignored */
2057 store = CertOpenStore(CERT_STORE_PROV_PKCS7, X509_ASN_ENCODING, 0, 0,
2058 &blob);
2059 ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError());
2060 if (store)
2061 CertCloseStore(store, 0);
2062 /* Messages other than signed messages aren't allowed */
2063 blob.cbData = sizeof(hashContent);
2064 blob.pbData = (LPBYTE)hashContent;
2065 SetLastError(0xdeadbeef);
2066 store = CertOpenStore(CERT_STORE_PROV_PKCS7, 0, 0, 0, &blob);
2067 ok(!store && GetLastError() == CRYPT_E_INVALID_MSG_TYPE,
2068 "Expected CRYPT_E_INVALID_MSG_TYPE, got %08x\n", GetLastError());
2069 blob.cbData = sizeof(hashBareContent);
2070 blob.pbData = (LPBYTE)hashBareContent;
2071 SetLastError(0xdeadbeef);
2072 store = CertOpenStore(CERT_STORE_PROV_PKCS7, 0, 0, 0, &blob);
2073 ok(!store &&
2074 (GetLastError() == CRYPT_E_ASN1_BADTAG ||
2075 broken(GetLastError() == OSS_DATA_ERROR)), /* NT4 */
2076 "Expected CRYPT_E_ASN1_BADTAG, got %08x\n", GetLastError());
2079 static void testSerializedStore(void)
2081 HCERTSTORE store;
2082 CRYPT_DATA_BLOB blob;
2084 if (0)
2086 /* Crash */
2087 store = CertOpenStore(CERT_STORE_PROV_SERIALIZED, 0, 0, 0, NULL);
2088 store = CertOpenStore(CERT_STORE_PROV_SERIALIZED, 0, 0,
2089 CERT_STORE_DELETE_FLAG, NULL);
2091 blob.cbData = sizeof(serializedStoreWithCert);
2092 blob.pbData = (BYTE *)serializedStoreWithCert;
2093 store = CertOpenStore(CERT_STORE_PROV_SERIALIZED, 0, 0,
2094 CERT_STORE_DELETE_FLAG, &blob);
2095 ok(!store && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED,
2096 "Expected ERROR_CALL_NOT_IMPLEMENTED, got %08x\n", GetLastError());
2097 store = CertOpenStore(CERT_STORE_PROV_SERIALIZED, 0, 0, 0, &blob);
2098 ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError());
2099 if (store)
2101 PCCERT_CONTEXT cert;
2102 PCCRL_CONTEXT crl;
2104 cert = CertEnumCertificatesInStore(store, NULL);
2105 ok(cert != NULL, "CertEnumCertificatesInStore failed: %08x\n",
2106 GetLastError());
2107 cert = CertEnumCertificatesInStore(store, cert);
2108 ok(!cert, "Expected only one cert\n");
2109 if (pCertEnumCRLsInStore)
2111 crl = pCertEnumCRLsInStore(store, NULL);
2112 ok(!crl, "Expected no CRLs\n");
2114 CertCloseStore(store, 0);
2116 blob.cbData = sizeof(serializedStoreWithCertAndCRL);
2117 blob.pbData = (BYTE *)serializedStoreWithCertAndCRL;
2118 store = CertOpenStore(CERT_STORE_PROV_SERIALIZED, 0, 0, 0, &blob);
2119 ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError());
2120 if (store)
2122 PCCERT_CONTEXT cert;
2123 PCCRL_CONTEXT crl;
2125 cert = CertEnumCertificatesInStore(store, NULL);
2126 ok(cert != NULL, "CertEnumCertificatesInStore failed: %08x\n",
2127 GetLastError());
2128 cert = CertEnumCertificatesInStore(store, cert);
2129 ok(!cert, "Expected only one cert\n");
2130 if (pCertEnumCRLsInStore)
2132 crl = pCertEnumCRLsInStore(store, NULL);
2133 ok(crl != NULL, "CertEnumCRLsInStore failed: %08x\n",
2134 GetLastError());
2135 crl = pCertEnumCRLsInStore(store, crl);
2136 ok(!crl, "Expected only one CRL\n");
2138 CertCloseStore(store, 0);
2142 static void testCertOpenSystemStore(void)
2144 HCERTSTORE store;
2146 store = CertOpenSystemStoreW(0, NULL);
2147 ok(!store && GetLastError() == E_INVALIDARG,
2148 "Expected E_INVALIDARG, got %08x\n", GetLastError());
2149 /* This succeeds, and on WinXP at least, the Bogus key is created under
2150 * HKCU (but not under HKLM, even when run as an administrator.)
2152 store = CertOpenSystemStoreW(0, BogusW);
2153 ok(store != 0, "CertOpenSystemStore failed: %08x\n", GetLastError());
2154 if (store)
2155 CertCloseStore(store, 0);
2156 /* Delete it so other tests succeed next time around */
2157 CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0,
2158 CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_DELETE_FLAG, BogusW);
2159 RegDeleteKeyW(HKEY_CURRENT_USER, BogusPathW);
2162 static const struct
2164 DWORD cert_store;
2165 BOOL expected;
2166 BOOL todo;
2167 } reg_system_store_test_data[] = {
2168 { CERT_SYSTEM_STORE_CURRENT_USER, TRUE, 0},
2169 /* Following tests could require administrator privileges and thus could be skipped */
2170 { CERT_SYSTEM_STORE_CURRENT_SERVICE, TRUE, 1},
2171 { CERT_SYSTEM_STORE_LOCAL_MACHINE, TRUE, 0},
2172 { CERT_SYSTEM_STORE_LOCAL_MACHINE_GROUP_POLICY, TRUE, 0},
2173 { CERT_SYSTEM_STORE_CURRENT_USER_GROUP_POLICY, TRUE, 0},
2174 { CERT_SYSTEM_STORE_LOCAL_MACHINE_ENTERPRISE, TRUE, 1}
2177 static void testCertRegisterSystemStore(void)
2179 BOOL ret, cur_flag;
2180 DWORD err = 0;
2181 HCERTSTORE hstore;
2182 static const WCHAR WineTestW[] = {'W','i','n','e','T','e','s','t',0};
2183 const CERT_CONTEXT *cert, *cert2;
2184 unsigned int i;
2186 if (!pCertRegisterSystemStore || !pCertUnregisterSystemStore)
2188 win_skip("CertRegisterSystemStore() or CertUnregisterSystemStore() is not available\n");
2189 return;
2192 for (i = 0; i < sizeof(reg_system_store_test_data) / sizeof(reg_system_store_test_data[0]); i++) {
2193 cur_flag = reg_system_store_test_data[i].cert_store;
2194 ret = pCertRegisterSystemStore(WineTestW, cur_flag, NULL, NULL);
2195 if (!ret)
2197 err = GetLastError();
2198 if (err == ERROR_ACCESS_DENIED)
2200 win_skip("Insufficient privileges for the flag %08x test\n", cur_flag);
2201 continue;
2204 todo_wine_if (reg_system_store_test_data[i].todo)
2205 ok (ret == reg_system_store_test_data[i].expected,
2206 "Store registration (dwFlags=%08x) failed, last error %x\n", cur_flag, err);
2207 if (!ret)
2209 skip("Nothing to test without registered store at %08x\n", cur_flag);
2210 continue;
2213 hstore = CertOpenStore(CERT_STORE_PROV_SYSTEM_W, 0, 0, CERT_STORE_OPEN_EXISTING_FLAG | cur_flag, WineTestW);
2214 ok (hstore != NULL, "Opening just registered store at %08x failed, last error %x\n", cur_flag, GetLastError());
2216 cert = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert, sizeof(bigCert));
2217 ok (cert != NULL, "Failed creating cert at %08x, last error: %x\n", cur_flag, GetLastError());
2218 if (cert)
2220 ret = CertAddCertificateContextToStore(hstore, cert, CERT_STORE_ADD_NEW, NULL);
2221 ok (ret, "Failed to add cert at %08x, last error: %x\n", cur_flag, GetLastError());
2223 cert2 = CertEnumCertificatesInStore(hstore, NULL);
2224 ok (cert2 != NULL && cert2->cbCertEncoded == cert->cbCertEncoded,
2225 "Unexpected cert encoded size at %08x, last error: %x\n", cur_flag, GetLastError());
2227 ret = CertDeleteCertificateFromStore(cert2);
2228 ok (ret, "Failed to delete certificate from the new store at %08x, last error: %x\n", cur_flag, GetLastError());
2230 CertFreeCertificateContext(cert);
2233 ret = CertCloseStore(hstore, 0);
2234 ok (ret, "CertCloseStore failed at %08x, last error %x\n", cur_flag, GetLastError());
2236 ret = pCertUnregisterSystemStore(WineTestW, cur_flag );
2237 todo_wine_if (reg_system_store_test_data[i].todo)
2238 ok( ret == reg_system_store_test_data[i].expected,
2239 "Unregistering failed at %08x, last error %d\n", cur_flag, GetLastError());
2244 struct EnumSystemStoreInfo
2246 BOOL goOn;
2247 DWORD storeCount;
2250 static BOOL CALLBACK enumSystemStoreCB(const void *systemStore, DWORD dwFlags,
2251 PCERT_SYSTEM_STORE_INFO pStoreInfo, void *pvReserved, void *pvArg)
2253 struct EnumSystemStoreInfo *info = pvArg;
2255 info->storeCount++;
2256 return info->goOn;
2259 static void testCertEnumSystemStore(void)
2261 BOOL ret;
2262 struct EnumSystemStoreInfo info = { FALSE, 0 };
2264 if (!pCertEnumSystemStore)
2266 win_skip("CertEnumSystemStore() is not available\n");
2267 return;
2270 SetLastError(0xdeadbeef);
2271 ret = pCertEnumSystemStore(0, NULL, NULL, NULL);
2272 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2273 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2274 /* Crashes
2275 ret = pCertEnumSystemStore(CERT_SYSTEM_STORE_LOCAL_MACHINE, NULL, NULL,
2276 NULL);
2279 SetLastError(0xdeadbeef);
2280 ret = pCertEnumSystemStore(CERT_SYSTEM_STORE_LOCAL_MACHINE, NULL, &info,
2281 enumSystemStoreCB);
2282 /* Callback returning FALSE stops enumeration */
2283 ok(!ret, "Expected CertEnumSystemStore to stop\n");
2284 ok(info.storeCount == 0 || info.storeCount == 1,
2285 "Expected 0 or 1 stores\n");
2287 info.goOn = TRUE;
2288 info.storeCount = 0;
2289 ret = pCertEnumSystemStore(CERT_SYSTEM_STORE_LOCAL_MACHINE, NULL, &info,
2290 enumSystemStoreCB);
2291 ok(ret, "CertEnumSystemStore failed: %08x\n", GetLastError());
2292 /* There should always be at least My, Root, and CA stores */
2293 ok(info.storeCount == 0 || info.storeCount >= 3,
2294 "Expected at least 3 stores\n");
2297 static void testStoreProperty(void)
2299 HCERTSTORE store;
2300 BOOL ret;
2301 DWORD propID, size = 0, state;
2302 CRYPT_DATA_BLOB blob;
2304 if (!pCertGetStoreProperty || !pCertSetStoreProperty)
2306 win_skip("CertGet/SetStoreProperty() is not available\n");
2307 return;
2310 /* Crash
2311 ret = pCertGetStoreProperty(NULL, 0, NULL, NULL);
2312 ret = pCertGetStoreProperty(NULL, 0, NULL, &size);
2313 ret = pCertGetStoreProperty(store, 0, NULL, NULL);
2316 store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
2317 CERT_STORE_CREATE_NEW_FLAG, NULL);
2318 /* Check a missing prop ID */
2319 SetLastError(0xdeadbeef);
2320 ret = pCertGetStoreProperty(store, 0, NULL, &size);
2321 ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
2322 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
2323 /* Contrary to MSDN, CERT_ACCESS_STATE_PROP_ID is supported for stores.. */
2324 size = sizeof(state);
2325 ret = pCertGetStoreProperty(store, CERT_ACCESS_STATE_PROP_ID, &state, &size);
2326 ok(ret, "CertGetStoreProperty failed for CERT_ACCESS_STATE_PROP_ID: %08x\n",
2327 GetLastError());
2328 ok(!state, "Expected a non-persisted store\n");
2329 /* and CERT_STORE_LOCALIZED_NAME_PROP_ID isn't supported by default. */
2330 size = 0;
2331 ret = pCertGetStoreProperty(store, CERT_STORE_LOCALIZED_NAME_PROP_ID, NULL,
2332 &size);
2333 ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
2334 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
2335 /* Delete an arbitrary property on a store */
2336 ret = pCertSetStoreProperty(store, CERT_FIRST_USER_PROP_ID, 0, NULL);
2337 ok(ret, "CertSetStoreProperty failed: %08x\n", GetLastError());
2338 /* Set an arbitrary property on a store */
2339 blob.pbData = (LPBYTE)&state;
2340 blob.cbData = sizeof(state);
2341 ret = pCertSetStoreProperty(store, CERT_FIRST_USER_PROP_ID, 0, &blob);
2342 ok(ret, "CertSetStoreProperty failed: %08x\n", GetLastError());
2343 /* Get an arbitrary property that's been set */
2344 ret = pCertGetStoreProperty(store, CERT_FIRST_USER_PROP_ID, NULL, &size);
2345 ok(ret, "CertGetStoreProperty failed: %08x\n", GetLastError());
2346 ok(size == sizeof(state), "Unexpected data size %d\n", size);
2347 ret = pCertGetStoreProperty(store, CERT_FIRST_USER_PROP_ID, &propID, &size);
2348 ok(ret, "CertGetStoreProperty failed: %08x\n", GetLastError());
2349 ok(propID == state, "CertGetStoreProperty got the wrong value\n");
2350 /* Delete it again */
2351 ret = pCertSetStoreProperty(store, CERT_FIRST_USER_PROP_ID, 0, NULL);
2352 ok(ret, "CertSetStoreProperty failed: %08x\n", GetLastError());
2353 /* And check that it's missing */
2354 SetLastError(0xdeadbeef);
2355 ret = pCertGetStoreProperty(store, CERT_FIRST_USER_PROP_ID, NULL, &size);
2356 ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
2357 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
2358 CertCloseStore(store, 0);
2360 /* Recheck on the My store.. */
2361 store = CertOpenSystemStoreW(0, MyW);
2362 size = sizeof(state);
2363 ret = pCertGetStoreProperty(store, CERT_ACCESS_STATE_PROP_ID, &state, &size);
2364 ok(ret, "CertGetStoreProperty failed for CERT_ACCESS_STATE_PROP_ID: %08x\n",
2365 GetLastError());
2366 ok(state, "Expected a persisted store\n");
2367 SetLastError(0xdeadbeef);
2368 size = 0;
2369 ret = pCertGetStoreProperty(store, CERT_STORE_LOCALIZED_NAME_PROP_ID, NULL,
2370 &size);
2371 ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
2372 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
2373 CertCloseStore(store, 0);
2376 static void testAddSerialized(void)
2378 BOOL ret;
2379 HCERTSTORE store;
2380 BYTE buf[sizeof(struct CertPropIDHeader) * 2 + 20 + sizeof(bigCert)] =
2381 { 0 };
2382 BYTE hash[20];
2383 struct CertPropIDHeader *hdr;
2384 PCCERT_CONTEXT context;
2386 ret = CertAddSerializedElementToStore(0, NULL, 0, 0, 0, 0, NULL, NULL);
2387 ok(!ret && GetLastError() == ERROR_END_OF_MEDIA,
2388 "Expected ERROR_END_OF_MEDIA, got %08x\n", GetLastError());
2390 store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
2391 CERT_STORE_CREATE_NEW_FLAG, NULL);
2392 ok(store != 0, "CertOpenStore failed: %08x\n", GetLastError());
2394 ret = CertAddSerializedElementToStore(store, NULL, 0, 0, 0, 0, NULL, NULL);
2395 ok(!ret && GetLastError() == ERROR_END_OF_MEDIA,
2396 "Expected ERROR_END_OF_MEDIA, got %08x\n", GetLastError());
2398 /* Test with an empty property */
2399 hdr = (struct CertPropIDHeader *)buf;
2400 hdr->propID = CERT_CERT_PROP_ID;
2401 hdr->unknown1 = 1;
2402 hdr->cb = 0;
2403 ret = CertAddSerializedElementToStore(store, buf, sizeof(buf), 0, 0, 0,
2404 NULL, NULL);
2405 ok(!ret && GetLastError() == E_INVALIDARG,
2406 "Expected E_INVALIDARG, got %08x\n", GetLastError());
2407 /* Test with a bad size in property header */
2408 hdr->cb = sizeof(bigCert) - 1;
2409 memcpy(buf + sizeof(struct CertPropIDHeader), bigCert, sizeof(bigCert));
2410 ret = CertAddSerializedElementToStore(store, buf, sizeof(buf), 0, 0, 0,
2411 NULL, NULL);
2412 ok(!ret && GetLastError() == E_INVALIDARG,
2413 "Expected E_INVALIDARG, got %08x\n", GetLastError());
2414 ret = CertAddSerializedElementToStore(store, buf,
2415 sizeof(struct CertPropIDHeader) + sizeof(bigCert), 0, 0, 0, NULL,
2416 NULL);
2417 ok(!ret && GetLastError() == E_INVALIDARG,
2418 "Expected E_INVALIDARG, got %08x\n", GetLastError());
2419 ret = CertAddSerializedElementToStore(store, buf,
2420 sizeof(struct CertPropIDHeader) + sizeof(bigCert), CERT_STORE_ADD_NEW,
2421 0, 0, NULL, NULL);
2422 ok(!ret && GetLastError() == E_INVALIDARG,
2423 "Expected E_INVALIDARG, got %08x\n", GetLastError());
2424 /* Kosher size in property header, but no context type */
2425 hdr->cb = sizeof(bigCert);
2426 ret = CertAddSerializedElementToStore(store, buf, sizeof(buf), 0, 0, 0,
2427 NULL, NULL);
2428 ok(!ret && GetLastError() == E_INVALIDARG,
2429 "Expected E_INVALIDARG, got %08x\n", GetLastError());
2430 ret = CertAddSerializedElementToStore(store, buf,
2431 sizeof(struct CertPropIDHeader) + sizeof(bigCert), 0, 0, 0, NULL,
2432 NULL);
2433 ok(!ret && GetLastError() == E_INVALIDARG,
2434 "Expected E_INVALIDARG, got %08x\n", GetLastError());
2435 ret = CertAddSerializedElementToStore(store, buf,
2436 sizeof(struct CertPropIDHeader) + sizeof(bigCert), CERT_STORE_ADD_NEW,
2437 0, 0, NULL, NULL);
2438 ok(!ret && GetLastError() == E_INVALIDARG,
2439 "Expected E_INVALIDARG, got %08x\n", GetLastError());
2440 /* With a bad context type */
2441 ret = CertAddSerializedElementToStore(store, buf, sizeof(buf), 0, 0,
2442 CERT_STORE_CRL_CONTEXT_FLAG, NULL, NULL);
2443 ok(!ret && GetLastError() == E_INVALIDARG,
2444 "Expected E_INVALIDARG, got %08x\n", GetLastError());
2445 ret = CertAddSerializedElementToStore(store, buf,
2446 sizeof(struct CertPropIDHeader) + sizeof(bigCert), 0, 0,
2447 CERT_STORE_CRL_CONTEXT_FLAG, NULL, NULL);
2448 ok(!ret && GetLastError() == E_INVALIDARG,
2449 "Expected E_INVALIDARG, got %08x\n", GetLastError());
2450 ret = CertAddSerializedElementToStore(store, buf,
2451 sizeof(struct CertPropIDHeader) + sizeof(bigCert), CERT_STORE_ADD_NEW,
2452 0, CERT_STORE_CRL_CONTEXT_FLAG, NULL, NULL);
2453 ok(!ret && GetLastError() == E_INVALIDARG,
2454 "Expected E_INVALIDARG, got %08x\n", GetLastError());
2455 /* Bad unknown field, good type */
2456 hdr->unknown1 = 2;
2457 ret = CertAddSerializedElementToStore(store, buf, sizeof(buf), 0, 0,
2458 CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL, NULL);
2459 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2460 "Expected ERROR_FILE_NOT_FOUND got %08x\n", GetLastError());
2461 ret = CertAddSerializedElementToStore(store, buf,
2462 sizeof(struct CertPropIDHeader) + sizeof(bigCert), 0, 0,
2463 CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL, NULL);
2464 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2465 "Expected ERROR_FILE_NOT_FOUND got %08x\n", GetLastError());
2466 ret = CertAddSerializedElementToStore(store, buf,
2467 sizeof(struct CertPropIDHeader) + sizeof(bigCert), CERT_STORE_ADD_NEW,
2468 0, CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL, NULL);
2469 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2470 "Expected ERROR_FILE_NOT_FOUND got %08x\n", GetLastError());
2471 /* Most everything okay, but bad add disposition */
2472 hdr->unknown1 = 1;
2473 /* This crashes
2474 ret = CertAddSerializedElementToStore(store, buf, sizeof(buf), 0, 0,
2475 CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL, NULL);
2476 * as does this
2477 ret = CertAddSerializedElementToStore(store, buf,
2478 sizeof(struct CertPropIDHeader) + sizeof(bigCert), 0, 0,
2479 CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL, NULL);
2481 /* Everything okay, but buffer's too big */
2482 ret = CertAddSerializedElementToStore(store, buf, sizeof(buf),
2483 CERT_STORE_ADD_NEW, 0, CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL, NULL);
2484 ok(ret, "CertAddSerializedElementToStore failed: %08x\n", GetLastError());
2485 /* Everything okay, check it's not re-added */
2486 ret = CertAddSerializedElementToStore(store, buf,
2487 sizeof(struct CertPropIDHeader) + sizeof(bigCert), CERT_STORE_ADD_NEW,
2488 0, CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL, NULL);
2489 ok(!ret && GetLastError() == CRYPT_E_EXISTS,
2490 "Expected CRYPT_E_EXISTS, got %08x\n", GetLastError());
2492 context = CertEnumCertificatesInStore(store, NULL);
2493 ok(context != NULL, "Expected a cert\n");
2494 if (context)
2495 CertDeleteCertificateFromStore(context);
2497 /* Try adding with a bogus hash. Oddly enough, it succeeds, and the hash,
2498 * when queried, is the real hash rather than the bogus hash.
2500 hdr = (struct CertPropIDHeader *)(buf + sizeof(struct CertPropIDHeader) +
2501 sizeof(bigCert));
2502 hdr->propID = CERT_HASH_PROP_ID;
2503 hdr->unknown1 = 1;
2504 hdr->cb = sizeof(hash);
2505 memset(hash, 0xc, sizeof(hash));
2506 memcpy((LPBYTE)hdr + sizeof(struct CertPropIDHeader), hash, sizeof(hash));
2507 ret = CertAddSerializedElementToStore(store, buf, sizeof(buf),
2508 CERT_STORE_ADD_NEW, 0, CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL,
2509 (const void **)&context);
2510 ok(ret, "CertAddSerializedElementToStore failed: %08x\n", GetLastError());
2511 if (context)
2513 BYTE hashVal[20], realHash[20];
2514 DWORD size = sizeof(hashVal);
2516 ret = CryptHashCertificate(0, 0, 0, bigCert, sizeof(bigCert),
2517 realHash, &size);
2518 ok(ret, "CryptHashCertificate failed: %08x\n", GetLastError());
2519 ret = CertGetCertificateContextProperty(context, CERT_HASH_PROP_ID,
2520 hashVal, &size);
2521 ok(ret, "CertGetCertificateContextProperty failed: %08x\n",
2522 GetLastError());
2523 ok(!memcmp(hashVal, realHash, size), "Unexpected hash\n");
2524 CertFreeCertificateContext(context);
2527 CertCloseStore(store, 0);
2530 static const BYTE serializedCertWithFriendlyName[] = {
2531 0x0b,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x12,0x00,0x00,0x00,0x57,0x00,0x69,
2532 0x00,0x6e,0x00,0x65,0x00,0x54,0x00,0x65,0x00,0x73,0x00,0x74,0x00,0x00,0x00,
2533 0x20,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x7c,0x00,0x00,0x00,0x30,0x7a,0x02,
2534 0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,
2535 0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x30,
2536 0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,
2537 0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,
2538 0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,
2539 0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x30,0x07,
2540 0x30,0x02,0x06,0x00,0x03,0x01,0x00,0xa3,0x16,0x30,0x14,0x30,0x12,0x06,0x03,
2541 0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,
2542 0x01 };
2543 static const BYTE serializedStoreWithCertWithFriendlyName[] = {
2544 0x00,0x00,0x00,0x00,0x43,0x45,0x52,0x54,0x0b,0x00,0x00,0x00,0x01,0x00,0x00,
2545 0x00,0x12,0x00,0x00,0x00,0x57,0x00,0x69,0x00,0x6e,0x00,0x65,0x00,0x54,0x00,
2546 0x65,0x00,0x73,0x00,0x74,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x01,0x00,0x00,
2547 0x00,0x7c,0x00,0x00,0x00,0x30,0x7a,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,
2548 0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,
2549 0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,
2550 0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,
2551 0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,
2552 0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,
2553 0x20,0x4c,0x61,0x6e,0x67,0x00,0x30,0x07,0x30,0x02,0x06,0x00,0x03,0x01,0x00,
2554 0xa3,0x16,0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,
2555 0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,
2556 0x00,0x00,0x00,0x00,0x00,0x00 };
2557 static const BYTE serializedStoreWithCertAndHash[] = {
2558 0x00,0x00,0x00,0x00,0x43,0x45,0x52,0x54,0x03,0x00,0x00,0x00,0x01,0x00,0x00,
2559 0x00,0x14,0x00,0x00,0x00,0x6e,0x30,0x90,0x71,0x5f,0xd9,0x23,0x56,0xeb,0xae,
2560 0x25,0x40,0xe6,0x22,0xda,0x19,0x26,0x02,0xa6,0x08,0x20,0x00,0x00,0x00,0x01,
2561 0x00,0x00,0x00,0x7c,0x00,0x00,0x00,0x30,0x7a,0x02,0x01,0x01,0x30,0x02,0x06,
2562 0x00,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,
2563 0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,
2564 0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,
2565 0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,
2566 0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,
2567 0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x30,0x07,0x30,0x02,0x06,0x00,0x03,
2568 0x01,0x00,0xa3,0x16,0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,
2569 0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01,0x00,0x00,0x00,0x00,
2570 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 };
2572 static void delete_test_key(void)
2574 HKEY root_key, test_key;
2575 static const WCHAR SysCertW[] = {'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\',
2576 'S','y','s','t','e','m','C','e','r','t','i','f','i','c','a','t','e','s',0};
2577 static const WCHAR WineTestW[] = {'W','i','n','e','T','e','s','t',0};
2578 WCHAR subkey_name[32];
2579 DWORD num_subkeys, subkey_name_len;
2580 int idx;
2582 if (RegOpenKeyExW(HKEY_CURRENT_USER, SysCertW, 0, KEY_READ, &root_key))
2583 return;
2584 if (RegOpenKeyExW(root_key, WineTestW, 0, KEY_READ, &test_key))
2586 RegCloseKey(root_key);
2587 return;
2589 RegQueryInfoKeyW(test_key, NULL, NULL, NULL, &num_subkeys, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
2590 for (idx = num_subkeys; idx-- > 0;)
2592 subkey_name_len = sizeof(subkey_name)/sizeof(WCHAR);
2593 RegEnumKeyExW(test_key, idx, subkey_name, &subkey_name_len, NULL, NULL, NULL, NULL);
2594 RegDeleteKeyW(test_key, subkey_name);
2596 RegCloseKey(test_key);
2597 RegDeleteKeyW(root_key, WineTestW);
2598 RegCloseKey(root_key);
2601 static void testAddCertificateLink(void)
2603 BOOL ret;
2604 HCERTSTORE store1, store2;
2605 PCCERT_CONTEXT source, linked;
2606 DWORD size;
2607 LPBYTE buf;
2608 CERT_NAME_BLOB blob;
2609 static const WCHAR szPrefix[] = { 'c','e','r',0 };
2610 static const WCHAR szDot[] = { '.',0 };
2611 static const WCHAR WineTestW[] = { 'W','i','n','e','T','e','s','t',0 };
2612 WCHAR filename1[MAX_PATH], filename2[MAX_PATH];
2613 HANDLE file;
2615 if (!pCertAddCertificateLinkToStore)
2617 win_skip("CertAddCertificateLinkToStore not found\n");
2618 return;
2621 if (0)
2623 /* Crashes, i.e. the store is dereferenced without checking. */
2624 ret = pCertAddCertificateLinkToStore(NULL, NULL, 0, NULL);
2627 /* Adding a certificate link to a store requires a valid add disposition */
2628 store1 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
2629 CERT_STORE_CREATE_NEW_FLAG, NULL);
2630 SetLastError(0xdeadbeef);
2631 ret = pCertAddCertificateLinkToStore(store1, NULL, 0, NULL);
2632 ok(!ret && GetLastError() == E_INVALIDARG,
2633 "expected E_INVALIDARG, got %08x\n", GetLastError());
2634 source = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert,
2635 sizeof(bigCert));
2636 SetLastError(0xdeadbeef);
2637 ret = pCertAddCertificateLinkToStore(store1, source, 0, NULL);
2638 ok(!ret && GetLastError() == E_INVALIDARG,
2639 "expected E_INVALIDARG, got %08x\n", GetLastError());
2640 ret = pCertAddCertificateLinkToStore(store1, source, CERT_STORE_ADD_ALWAYS,
2641 NULL);
2642 ok(ret, "CertAddCertificateLinkToStore failed: %08x\n", GetLastError());
2643 if (0)
2645 /* Crashes, i.e. the source certificate is dereferenced without
2646 * checking when a valid add disposition is given.
2648 ret = pCertAddCertificateLinkToStore(store1, NULL, CERT_STORE_ADD_ALWAYS,
2649 NULL);
2651 CertCloseStore(store1, 0);
2653 store1 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
2654 CERT_STORE_CREATE_NEW_FLAG, NULL);
2655 ret = pCertAddCertificateLinkToStore(store1, source, CERT_STORE_ADD_ALWAYS,
2656 &linked);
2657 ok(ret, "CertAddCertificateLinkToStore failed: %08x\n", GetLastError());
2658 if (ret)
2660 ok(linked->hCertStore == store1, "unexpected store\n");
2661 ret = CertSerializeCertificateStoreElement(linked, 0, NULL, &size);
2662 ok(ret, "CertSerializeCertificateStoreElement failed: %08x\n",
2663 GetLastError());
2664 buf = HeapAlloc(GetProcessHeap(), 0, size);
2665 if (buf)
2667 ret = CertSerializeCertificateStoreElement(linked, 0, buf, &size);
2668 ok(ret, "CertSerializeCertificateStoreElement failed: %08x\n",
2669 GetLastError());
2670 /* The serialized linked certificate is identical to the serialized
2671 * original certificate.
2673 ok(size == sizeof(serializedCert), "Wrong size %d\n", size);
2674 ok(!memcmp(serializedCert, buf, size),
2675 "Unexpected serialized cert\n");
2676 HeapFree(GetProcessHeap(), 0, buf);
2678 /* Set a friendly name on the source certificate... */
2679 blob.pbData = (LPBYTE)WineTestW;
2680 blob.cbData = sizeof(WineTestW);
2681 ret = CertSetCertificateContextProperty(source,
2682 CERT_FRIENDLY_NAME_PROP_ID, 0, &blob);
2683 ok(ret, "CertSetCertificateContextProperty failed: %08x\n",
2684 GetLastError());
2685 /* and the linked certificate has the same friendly name. */
2686 ret = CertGetCertificateContextProperty(linked,
2687 CERT_FRIENDLY_NAME_PROP_ID, NULL, &size);
2688 ok(ret, "CertGetCertificateContextProperty failed: %08x\n",
2689 GetLastError());
2690 buf = HeapAlloc(GetProcessHeap(), 0, size);
2691 if (buf)
2693 ret = CertGetCertificateContextProperty(linked,
2694 CERT_FRIENDLY_NAME_PROP_ID, buf, &size);
2695 ok(ret, "CertGetCertificateContextProperty failed: %08x\n",
2696 GetLastError());
2697 ok(!lstrcmpW((LPCWSTR)buf, WineTestW),
2698 "unexpected friendly name\n");
2699 HeapFree(GetProcessHeap(), 0, buf);
2701 CertFreeCertificateContext(linked);
2703 CertFreeCertificateContext(source);
2704 CertCloseStore(store1, 0);
2706 /* Test adding a cert to a file store, committing the change to the store,
2707 * and creating a link to the resulting cert.
2709 if (!GetTempFileNameW(szDot, szPrefix, 0, filename1))
2710 return;
2712 DeleteFileW(filename1);
2713 file = CreateFileW(filename1, GENERIC_READ | GENERIC_WRITE, 0, NULL,
2714 CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
2715 if (file == INVALID_HANDLE_VALUE)
2716 return;
2718 store1 = CertOpenStore(CERT_STORE_PROV_FILE, 0, 0,
2719 CERT_FILE_STORE_COMMIT_ENABLE_FLAG, file);
2720 ok(store1 != NULL, "CertOpenStore failed: %08x\n", GetLastError());
2721 CloseHandle(file);
2723 ret = CertAddEncodedCertificateToStore(store1, X509_ASN_ENCODING,
2724 bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, &source);
2725 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
2726 GetLastError());
2728 /* Test adding a link to a memory store. */
2729 store2 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
2730 CERT_STORE_CREATE_NEW_FLAG, NULL);
2731 ret = pCertAddCertificateLinkToStore(store2, source, CERT_STORE_ADD_ALWAYS,
2732 &linked);
2733 ok(ret, "CertAddCertificateLinkToStore failed: %08x\n", GetLastError());
2734 if (ret)
2736 ok(linked->hCertStore == store2, "unexpected store\n");
2737 ret = CertSerializeCertificateStoreElement(linked, 0, NULL, &size);
2738 ok(ret, "CertSerializeCertificateStoreElement failed: %08x\n",
2739 GetLastError());
2740 buf = HeapAlloc(GetProcessHeap(), 0, size);
2741 if (buf)
2743 ret = CertSerializeCertificateStoreElement(linked, 0, buf, &size);
2744 /* The serialized linked certificate is identical to the serialized
2745 * original certificate.
2747 ok(ret, "CertSerializeCertificateStoreElement failed: %08x\n", GetLastError());
2748 ok(size == sizeof(serializedCert), "Wrong size %d\n", size);
2749 ok(!memcmp(serializedCert, buf, size),
2750 "Unexpected serialized cert\n");
2751 HeapFree(GetProcessHeap(), 0, buf);
2753 /* Set a friendly name on the source certificate... */
2754 blob.pbData = (LPBYTE)WineTestW;
2755 blob.cbData = sizeof(WineTestW);
2756 ret = CertSetCertificateContextProperty(source,
2757 CERT_FRIENDLY_NAME_PROP_ID, 0, &blob);
2758 ok(ret, "CertSetCertificateContextProperty failed: %08x\n",
2759 GetLastError());
2760 /* and the linked certificate has the same friendly name. */
2761 ret = CertGetCertificateContextProperty(linked,
2762 CERT_FRIENDLY_NAME_PROP_ID, NULL, &size);
2763 ok(ret, "CertGetCertificateContextProperty failed: %08x\n",
2764 GetLastError());
2765 buf = HeapAlloc(GetProcessHeap(), 0, size);
2766 if (buf)
2768 ret = CertGetCertificateContextProperty(linked,
2769 CERT_FRIENDLY_NAME_PROP_ID, buf, &size);
2770 ok(ret, "CertGetCertificateContextProperty failed: %08x\n", GetLastError());
2771 ok(!lstrcmpW((LPCWSTR)buf, WineTestW),
2772 "unexpected friendly name\n");
2773 HeapFree(GetProcessHeap(), 0, buf);
2775 CertFreeCertificateContext(linked);
2777 CertCloseStore(store2, 0);
2779 if (!GetTempFileNameW(szDot, szPrefix, 0, filename2))
2780 return;
2782 DeleteFileW(filename2);
2783 file = CreateFileW(filename2, GENERIC_READ | GENERIC_WRITE, 0, NULL,
2784 CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
2785 if (file == INVALID_HANDLE_VALUE)
2786 return;
2788 store2 = CertOpenStore(CERT_STORE_PROV_FILE, 0, 0,
2789 CERT_FILE_STORE_COMMIT_ENABLE_FLAG, file);
2790 ok(store2 != NULL, "CertOpenStore failed: %08x\n", GetLastError());
2791 CloseHandle(file);
2792 /* Test adding a link to a file store. */
2793 ret = pCertAddCertificateLinkToStore(store2, source, CERT_STORE_ADD_ALWAYS,
2794 &linked);
2795 ok(ret, "CertAddCertificateLinkToStore failed: %08x\n", GetLastError());
2796 if (ret)
2798 ok(linked->hCertStore == store2, "unexpected store\n");
2799 ret = CertSerializeCertificateStoreElement(linked, 0, NULL, &size);
2800 ok(ret, "CertSerializeCertificateStoreElement failed: %08x\n",
2801 GetLastError());
2802 buf = HeapAlloc(GetProcessHeap(), 0, size);
2803 if (buf)
2805 ret = CertSerializeCertificateStoreElement(linked, 0, buf, &size);
2806 ok(ret, "CertSerializeCertificateStoreElement failed: %08x\n",
2807 GetLastError());
2808 /* The serialized linked certificate now contains the friendly
2809 * name property.
2811 ok(size == sizeof(serializedCertWithFriendlyName),
2812 "Wrong size %d\n", size);
2813 ok(!memcmp(serializedCertWithFriendlyName, buf, size),
2814 "Unexpected serialized cert\n");
2815 HeapFree(GetProcessHeap(), 0, buf);
2817 CertFreeCertificateContext(linked);
2818 compareStore(store2, "file store -> file store",
2819 serializedStoreWithCertWithFriendlyName,
2820 sizeof(serializedStoreWithCertWithFriendlyName), FALSE);
2822 CertCloseStore(store2, 0);
2823 DeleteFileW(filename2);
2825 CertFreeCertificateContext(source);
2827 CertCloseStore(store1, 0);
2828 DeleteFileW(filename1);
2830 /* Test adding a link to a system store (which is a collection store.) */
2831 store1 = CertOpenSystemStoreA(0, "My");
2832 source = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert,
2833 sizeof(bigCert));
2834 SetLastError(0xdeadbeef);
2835 ret = pCertAddCertificateLinkToStore(store1, source, CERT_STORE_ADD_ALWAYS,
2836 &linked);
2837 ok(!ret && GetLastError() == E_INVALIDARG,
2838 "expected E_INVALIDARG, got %08x\n", GetLastError());
2839 CertFreeCertificateContext(source);
2841 /* Test adding a link to a file store, where the linked certificate is
2842 * in a system store.
2844 ret = CertAddEncodedCertificateToStore(store1, X509_ASN_ENCODING,
2845 bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, &source);
2846 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
2847 GetLastError());
2848 if (!GetTempFileNameW(szDot, szPrefix, 0, filename1))
2849 return;
2851 DeleteFileW(filename1);
2852 file = CreateFileW(filename1, GENERIC_READ | GENERIC_WRITE, 0, NULL,
2853 CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
2854 if (file == INVALID_HANDLE_VALUE)
2855 return;
2857 store2 = CertOpenStore(CERT_STORE_PROV_FILE, 0, 0,
2858 CERT_FILE_STORE_COMMIT_ENABLE_FLAG, file);
2859 ok(store2 != NULL, "CertOpenStore failed: %08x\n", GetLastError());
2860 CloseHandle(file);
2862 ret = pCertAddCertificateLinkToStore(store2, source, CERT_STORE_ADD_ALWAYS,
2863 &linked);
2864 ok(ret, "CertAddCertificateLinkToStore failed: %08x\n", GetLastError());
2865 if (ret)
2867 ok(linked->hCertStore == store2, "unexpected store\n");
2868 ret = pCertControlStore(store2, 0, CERT_STORE_CTRL_COMMIT, NULL);
2869 ok(ret, "CertControlStore failed: %d\n", ret);
2870 compareStore(store2, "file store -> system store",
2871 serializedStoreWithCertAndHash,
2872 sizeof(serializedStoreWithCertAndHash), TRUE);
2873 CertFreeCertificateContext(linked);
2876 CertCloseStore(store2, 0);
2877 DeleteFileW(filename1);
2879 /* Test adding a link to a registry store, where the linked certificate is
2880 * in a system store.
2882 store2 = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY, 0, 0,
2883 CERT_SYSTEM_STORE_CURRENT_USER, WineTestW);
2884 ok(store2 != NULL, "CertOpenStore failed: %08x\n", GetLastError());
2885 ret = pCertAddCertificateLinkToStore(store2, source, CERT_STORE_ADD_ALWAYS,
2886 &linked);
2887 ok(ret, "CertAddCertificateLinkToStore failed: %08x\n", GetLastError());
2888 if (ret)
2890 ok(linked->hCertStore == store2, "unexpected store\n");
2891 CertDeleteCertificateFromStore(linked);
2893 CertCloseStore(store2, 0);
2895 CertFreeCertificateContext(source);
2896 CertCloseStore(store1, 0);
2898 delete_test_key();
2901 static DWORD countCertsInStore(HCERTSTORE store)
2903 PCCERT_CONTEXT cert = NULL;
2904 DWORD certs = 0;
2906 do {
2907 cert = CertEnumCertificatesInStore(store, cert);
2908 if (cert)
2909 certs++;
2910 } while (cert);
2911 return certs;
2914 static DWORD countCRLsInStore(HCERTSTORE store)
2916 PCCRL_CONTEXT crl = NULL;
2917 DWORD crls = 0;
2919 do {
2920 crl = pCertEnumCRLsInStore(store, crl);
2921 if (crl)
2922 crls++;
2923 } while (crl);
2924 return crls;
2927 static void testEmptyStore(void)
2929 const CERT_CONTEXT *cert, *cert2, *cert3;
2930 const CRL_CONTEXT *crl;
2931 const CTL_CONTEXT *ctl;
2932 HCERTSTORE store;
2933 BOOL res;
2935 cert = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert, sizeof(bigCert));
2936 ok(cert != NULL, "CertCreateCertificateContext failed\n");
2937 ok(cert->hCertStore != NULL, "cert->hCertStore == NULL\n");
2938 if(!cert->hCertStore) {
2939 CertFreeCertificateContext(cert);
2940 return;
2943 test_store_is_empty(cert->hCertStore);
2945 cert2 = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert2, sizeof(bigCert2));
2946 ok(cert2 != NULL, "CertCreateCertificateContext failed\n");
2947 ok(cert2->hCertStore == cert->hCertStore, "Unexpected hCertStore\n");
2949 test_store_is_empty(cert2->hCertStore);
2951 res = CertAddCertificateContextToStore(cert->hCertStore, cert2, CERT_STORE_ADD_NEW, &cert3);
2952 ok(res, "CertAddCertificateContextToStore failed\n");
2953 todo_wine
2954 ok(cert3 && cert3 != cert2, "Unexpected cert3\n");
2955 ok(cert3->hCertStore == cert->hCertStore, "Unexpected hCertStore\n");
2957 test_store_is_empty(cert->hCertStore);
2959 res = CertDeleteCertificateFromStore(cert3);
2960 ok(res, "CertDeleteCertificateContextFromStore failed\n");
2961 ok(cert3->hCertStore == cert->hCertStore, "Unexpected hCertStore\n");
2963 store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0, CERT_STORE_CREATE_NEW_FLAG, NULL);
2964 ok(store != NULL, "CertOpenStore failed\n");
2966 res = CertAddCertificateContextToStore(store, cert2, CERT_STORE_ADD_NEW, &cert3);
2967 ok(res, "CertAddCertificateContextToStore failed\n");
2968 ok(cert3 && cert3 != cert2, "Unexpected cert3\n");
2969 ok(cert3->hCertStore == store, "Unexpected hCertStore\n");
2971 res = CertDeleteCertificateFromStore(cert3);
2972 ok(res, "CertDeleteCertificateContextFromStore failed\n");
2973 ok(cert3->hCertStore == store, "Unexpected hCertStore\n");
2975 CertCloseStore(store, 0);
2977 res = CertCloseStore(cert->hCertStore, CERT_CLOSE_STORE_CHECK_FLAG);
2978 ok(!res && GetLastError() == E_UNEXPECTED, "CertCloseStore returned: %x(%x)\n", res, GetLastError());
2980 res = CertCloseStore(cert->hCertStore, 0);
2981 ok(!res && GetLastError() == E_UNEXPECTED, "CertCloseStore returned: %x(%x)\n", res, GetLastError());
2983 CertFreeCertificateContext(cert2);
2985 crl = CertCreateCRLContext(X509_ASN_ENCODING, signedCRL, sizeof(signedCRL));
2986 ok(crl != NULL, "CertCreateCRLContext failed\n");
2987 ok(crl->hCertStore == cert->hCertStore, "unexpected hCertStore\n");
2989 CertFreeCRLContext(crl);
2991 ctl = CertCreateCTLContext(X509_ASN_ENCODING, signedCTLWithCTLInnerContent, sizeof(signedCTLWithCTLInnerContent));
2992 ok(ctl != NULL, "CertCreateCTLContext failed\n");
2993 ok(ctl->hCertStore == cert->hCertStore, "unexpected hCertStore\n");
2995 CertFreeCTLContext(ctl);
2997 CertFreeCertificateContext(cert);
3000 static void testCloseStore(void)
3002 const CERT_CONTEXT *cert;
3003 const CRL_CONTEXT *crl;
3004 const CTL_CONTEXT *ctl;
3005 HCERTSTORE store, store2;
3006 BOOL res;
3008 store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0, CERT_STORE_CREATE_NEW_FLAG, NULL);
3009 ok(store != NULL, "CertOpenStore failed\n");
3011 res = CertCloseStore(store, CERT_CLOSE_STORE_CHECK_FLAG);
3012 ok(res, "CertCloseStore failed\n");
3014 store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0, CERT_STORE_CREATE_NEW_FLAG, NULL);
3015 ok(store != NULL, "CertOpenStore failed\n");
3017 store2 = CertDuplicateStore(store);
3018 ok(store2 != NULL, "CertCloneStore failed\n");
3019 ok(store2 == store, "unexpected store2\n");
3021 res = CertCloseStore(store, CERT_CLOSE_STORE_CHECK_FLAG);
3022 ok(!res && GetLastError() == CRYPT_E_PENDING_CLOSE, "CertCloseStore failed\n");
3024 res = CertCloseStore(store2, CERT_CLOSE_STORE_CHECK_FLAG);
3025 ok(res, "CertCloseStore failed\n");
3027 store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0, CERT_STORE_CREATE_NEW_FLAG, NULL);
3028 ok(store != NULL, "CertOpenStore failed\n");
3030 res = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING, bigCert,
3031 sizeof(bigCert), CERT_STORE_ADD_ALWAYS, &cert);
3032 ok(res, "CertAddEncodedCertificateToStore failed\n");
3034 /* There is still a reference from cert */
3035 res = CertCloseStore(store, CERT_CLOSE_STORE_CHECK_FLAG);
3036 ok(!res && GetLastError() == CRYPT_E_PENDING_CLOSE, "CertCloseStore failed\n");
3038 res = CertFreeCertificateContext(cert);
3039 ok(res, "CertFreeCertificateContext failed\n");
3041 store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0, CERT_STORE_CREATE_NEW_FLAG, NULL);
3042 ok(store != NULL, "CertOpenStore failed\n");
3044 res = CertAddEncodedCRLToStore(store, X509_ASN_ENCODING, signedCRL,
3045 sizeof(signedCRL), CERT_STORE_ADD_ALWAYS, &crl);
3046 ok(res, "CertAddEncodedCRLToStore failed\n");
3048 /* There is still a reference from CRL */
3049 res = CertCloseStore(store, CERT_CLOSE_STORE_CHECK_FLAG);
3050 ok(!res && GetLastError() == CRYPT_E_PENDING_CLOSE, "CertCloseStore failed\n");
3052 res = CertFreeCRLContext(crl);
3053 ok(res, "CertFreeCRLContext failed\n");
3055 store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0, CERT_STORE_CREATE_NEW_FLAG, NULL);
3056 ok(store != NULL, "CertOpenStore failed\n");
3058 res = CertAddEncodedCTLToStore(store, X509_ASN_ENCODING, signedCTLWithCTLInnerContent,
3059 sizeof(signedCTLWithCTLInnerContent), CERT_STORE_ADD_ALWAYS, &ctl);
3060 ok(res, "CertAddEncodedCTLToStore failed\n");
3062 /* There is still a reference from CTL */
3063 res = CertCloseStore(store, CERT_CLOSE_STORE_CHECK_FLAG);
3064 ok(!res && GetLastError() == CRYPT_E_PENDING_CLOSE, "CertCloseStore returned: %x(%u)\n", res, GetLastError());
3066 res = CertFreeCTLContext(ctl);
3067 ok(res, "CertFreeCTLContext failed\n");
3069 /* Add all kinds of contexts, then release external references and make sure that store is properly closed. */
3070 store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0, CERT_STORE_CREATE_NEW_FLAG, NULL);
3071 ok(store != NULL, "CertOpenStore failed\n");
3073 res = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING, bigCert,
3074 sizeof(bigCert), CERT_STORE_ADD_ALWAYS, &cert);
3075 ok(res, "CertAddEncodedCertificateToStore failed\n");
3077 res = CertAddEncodedCRLToStore(store, X509_ASN_ENCODING, signedCRL,
3078 sizeof(signedCRL), CERT_STORE_ADD_ALWAYS, &crl);
3079 ok(res, "CertAddEncodedCRLToStore failed\n");
3081 res = CertAddEncodedCTLToStore(store, X509_ASN_ENCODING, signedCTLWithCTLInnerContent,
3082 sizeof(signedCTLWithCTLInnerContent), CERT_STORE_ADD_ALWAYS, &ctl);
3083 ok(res, "CertAddEncodedCTLToStore failed\n");
3085 CertFreeCertificateContext(cert);
3086 CertFreeCRLContext(crl);
3087 CertFreeCTLContext(ctl);
3089 res = CertCloseStore(store, CERT_CLOSE_STORE_CHECK_FLAG);
3090 ok(res, "CertCloseStore failed\n");
3093 static void test_I_UpdateStore(void)
3095 HMODULE lib = GetModuleHandleA("crypt32");
3096 BOOL (WINAPI *pI_CertUpdatestore)(HCERTSTORE, HCERTSTORE, DWORD, DWORD) =
3097 (void *)GetProcAddress(lib, "I_CertUpdateStore");
3098 BOOL ret;
3099 HCERTSTORE store1, store2;
3100 PCCERT_CONTEXT cert;
3101 DWORD certs;
3103 if (!pI_CertUpdatestore)
3105 win_skip("No I_CertUpdateStore\n");
3106 return;
3108 store1 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
3109 CERT_STORE_CREATE_NEW_FLAG, NULL);
3110 store2 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
3111 CERT_STORE_CREATE_NEW_FLAG, NULL);
3113 /* Crash
3114 ret = pI_CertUpdatestore(NULL, NULL, 0, 0);
3115 ret = pI_CertUpdatestore(store1, NULL, 0, 0);
3116 ret = pI_CertUpdatestore(NULL, store2, 0, 0);
3118 ret = pI_CertUpdatestore(store1, store2, 0, 0);
3119 ok(ret, "I_CertUpdateStore failed: %08x\n", GetLastError());
3121 CertAddEncodedCertificateToStore(store2, X509_ASN_ENCODING, bigCert,
3122 sizeof(bigCert), CERT_STORE_ADD_ALWAYS, &cert);
3123 /* I_CertUpdateStore adds the contexts from store2 to store1 */
3124 ret = pI_CertUpdatestore(store1, store2, 0, 0);
3125 ok(ret, "I_CertUpdateStore failed: %08x\n", GetLastError());
3126 certs = countCertsInStore(store1);
3127 ok(certs == 1, "Expected 1 cert, got %d\n", certs);
3128 /* Calling it a second time has no effect */
3129 ret = pI_CertUpdatestore(store1, store2, 0, 0);
3130 ok(ret, "I_CertUpdateStore failed: %08x\n", GetLastError());
3131 certs = countCertsInStore(store1);
3132 ok(certs == 1, "Expected 1 cert, got %d\n", certs);
3134 /* The last parameters to I_CertUpdateStore appear to be ignored */
3135 ret = pI_CertUpdatestore(store1, store2, 1, 0);
3136 ok(ret, "I_CertUpdateStore failed: %08x\n", GetLastError());
3137 ret = pI_CertUpdatestore(store1, store2, 0, 1);
3138 ok(ret, "I_CertUpdateStore failed: %08x\n", GetLastError());
3140 CertAddEncodedCRLToStore(store2, X509_ASN_ENCODING, signedCRL,
3141 sizeof(signedCRL), CERT_STORE_ADD_ALWAYS, NULL);
3143 /* I_CertUpdateStore also adds the CRLs from store2 to store1 */
3144 ret = pI_CertUpdatestore(store1, store2, 0, 0);
3145 ok(ret, "I_CertUpdateStore failed: %08x\n", GetLastError());
3146 certs = countCertsInStore(store1);
3147 ok(certs == 1, "Expected 1 cert, got %d\n", certs);
3148 if (pCertEnumCRLsInStore)
3150 certs = countCRLsInStore(store1);
3151 ok(certs == 1, "Expected 1 CRL, got %d\n", certs);
3154 CertDeleteCertificateFromStore(cert);
3155 /* If a context is deleted from store2, I_CertUpdateStore deletes it
3156 * from store1
3158 ret = pI_CertUpdatestore(store1, store2, 0, 0);
3159 ok(ret, "I_CertUpdateStore failed: %08x\n", GetLastError());
3160 certs = countCertsInStore(store1);
3161 ok(certs == 0, "Expected 0 certs, got %d\n", certs);
3163 CertCloseStore(store1, 0);
3164 CertCloseStore(store2, 0);
3167 START_TEST(store)
3169 HMODULE hdll;
3171 hdll = GetModuleHandleA("Crypt32.dll");
3172 pCertAddStoreToCollection = (void*)GetProcAddress(hdll, "CertAddStoreToCollection");
3173 pCertControlStore = (void*)GetProcAddress(hdll, "CertControlStore");
3174 pCertEnumCRLsInStore = (void*)GetProcAddress(hdll, "CertEnumCRLsInStore");
3175 pCertEnumSystemStore = (void*)GetProcAddress(hdll, "CertEnumSystemStore");
3176 pCertGetStoreProperty = (void*)GetProcAddress(hdll, "CertGetStoreProperty");
3177 pCertRemoveStoreFromCollection = (void*)GetProcAddress(hdll, "CertRemoveStoreFromCollection");
3178 pCertSetStoreProperty = (void*)GetProcAddress(hdll, "CertSetStoreProperty");
3179 pCertAddCertificateLinkToStore = (void*)GetProcAddress(hdll, "CertAddCertificateLinkToStore");
3180 pCertRegisterSystemStore = (void*)GetProcAddress(hdll, "CertRegisterSystemStore");
3181 pCertUnregisterSystemStore = (void*)GetProcAddress(hdll, "CertUnregisterSystemStore");
3183 /* various combinations of CertOpenStore */
3184 testMemStore();
3185 testCollectionStore();
3186 testStoresInCollection();
3188 testRegStore();
3189 testRegStoreSavedCerts();
3191 testSystemRegStore();
3192 testSystemStore();
3193 testFileStore();
3194 testFileNameStore();
3195 testMessageStore();
3196 testSerializedStore();
3197 testCloseStore();
3199 testCertRegisterSystemStore();
3201 testCertOpenSystemStore();
3202 testCertEnumSystemStore();
3203 testStoreProperty();
3205 testAddSerialized();
3206 testAddCertificateLink();
3208 testEmptyStore();
3210 test_I_UpdateStore();