2 * crypt32 cert functions tests
4 * Copyright 2005 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
29 #include "wine/test.h"
31 /* The following aren't defined in wincrypt.h, as they're "reserved" */
32 #define CERT_CERT_PROP_ID 32
33 #define CERT_CRL_PROP_ID 33
34 #define CERT_CTL_PROP_ID 34
36 struct CertPropIDHeader
43 static void testCryptHashCert(void)
45 static const BYTE emptyHash[] = { 0xda, 0x39, 0xa3, 0xee, 0x5e, 0x6b, 0x4b,
46 0x0d, 0x32, 0x55, 0xbf, 0xef, 0x95, 0x60, 0x18, 0x90, 0xaf, 0xd8, 0x07,
48 static const BYTE knownHash[] = { 0xae, 0x9d, 0xbf, 0x6d, 0xf5, 0x46, 0xee,
49 0x8b, 0xc5, 0x7a, 0x13, 0xba, 0xc2, 0xb1, 0x04, 0xf2, 0xbf, 0x52, 0xa8,
51 static const BYTE toHash[] = "abcdefghijklmnopqrstuvwxyz0123456789.,;!?:";
54 DWORD hashLen = sizeof(hash);
56 /* NULL buffer and nonzero length crashes
57 ret = CryptHashCertificate(0, 0, 0, NULL, size, hash, &hashLen);
58 empty hash length also crashes
59 ret = CryptHashCertificate(0, 0, 0, buf, size, hash, NULL);
62 ret = CryptHashCertificate(0, 0, 0, toHash, sizeof(toHash), NULL,
64 ok(ret, "CryptHashCertificate failed: %08lx\n", GetLastError());
65 ok(hashLen == sizeof(hash),
66 "Got unexpected size of hash %ld, expected %d\n", hashLen, sizeof(hash));
67 /* Test with empty buffer */
68 ret = CryptHashCertificate(0, 0, 0, NULL, 0, hash, &hashLen);
69 ok(ret, "CryptHashCertificate failed: %08lx\n", GetLastError());
70 ok(!memcmp(hash, emptyHash, sizeof(emptyHash)),
71 "Unexpected hash of nothing\n");
72 /* Test a known value */
73 ret = CryptHashCertificate(0, 0, 0, toHash, sizeof(toHash), hash,
75 ok(ret, "CryptHashCertificate failed: %08lx\n", GetLastError());
76 ok(!memcmp(hash, knownHash, sizeof(knownHash)), "Unexpected hash\n");
79 static const BYTE emptyCert[] = { 0x30, 0x00 };
80 static const BYTE bigCert[] = "\x30\x7a\x02\x01\x01\x30\x02\x06\x00"
81 "\x30\x15\x31\x13\x30\x11\x06\x03\x55\x04\x03\x13\x0a\x4a\x75\x61\x6e\x20\x4c"
82 "\x61\x6e\x67\x00\x30\x22\x18\x0f\x31\x36\x30\x31\x30\x31\x30\x31\x30\x30\x30"
83 "\x30\x30\x30\x5a\x18\x0f\x31\x36\x30\x31\x30\x31\x30\x31\x30\x30\x30\x30\x30"
84 "\x30\x5a\x30\x15\x31\x13\x30\x11\x06\x03\x55\x04\x03\x13\x0a\x4a\x75\x61\x6e"
85 "\x20\x4c\x61\x6e\x67\x00\x30\x07\x30\x02\x06\x00\x03\x01\x00\xa3\x16\x30\x14"
86 "\x30\x12\x06\x03\x55\x1d\x13\x01\x01\xff\x04\x08\x30\x06\x01\x01\xff\x02\x01"
88 static const BYTE signedBigCert[] = {
89 0x30, 0x81, 0x93, 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06, 0x00, 0x30,
90 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a,
91 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x22, 0x18, 0x0f,
92 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
93 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30,
94 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06,
95 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61,
96 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3,
97 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff,
98 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
99 0x00, 0x03, 0x11, 0x00, 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07,
100 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00 };
101 static const BYTE serializedCert[] = { 0x20, 0x00, 0x00, 0x00,
102 0x01, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x30, 0x7a, 0x02, 0x01, 0x01,
103 0x30, 0x02, 0x06, 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55,
104 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67,
105 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31,
106 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31,
107 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15,
108 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75,
109 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06,
110 0x00, 0x03, 0x01, 0x00, 0xa3, 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55,
111 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02,
114 static void testMemStore(void)
116 HCERTSTORE store1, store2;
117 PCCERT_CONTEXT context;
121 store1 = CertOpenStore(0, 0, 0, 0, NULL);
122 ok(!store1 && GetLastError() == ERROR_FILE_NOT_FOUND,
123 "Expected ERROR_FILE_NOT_FOUND, got %ld\n", GetLastError());
125 store1 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
126 CERT_STORE_DELETE_FLAG, NULL);
127 ok(!store1 && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED,
128 "Expected ERROR_CALL_NOT_IMPLEMENTED, got %ld\n", GetLastError());
131 store1 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
132 CERT_STORE_CREATE_NEW_FLAG, NULL);
133 ok(store1 != NULL, "CertOpenStore failed: %ld\n", GetLastError());
134 /* open existing doesn't */
135 store2 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
136 CERT_STORE_OPEN_EXISTING_FLAG, NULL);
137 ok(store2 != NULL, "CertOpenStore failed: %ld\n", GetLastError());
138 ok(store1 != store2, "Expected different stores\n");
140 /* add a bogus (empty) cert */
142 ret = CertAddEncodedCertificateToStore(store1, X509_ASN_ENCODING, emptyCert,
143 sizeof(emptyCert), CERT_STORE_ADD_ALWAYS, &context);
144 /* Windows returns CRYPT_E_ASN1_EOD, but accept CRYPT_E_ASN1_CORRUPT as
145 * well (because matching errors is tough in this case)
147 ok(!ret && (GetLastError() == CRYPT_E_ASN1_EOD || GetLastError() ==
148 CRYPT_E_ASN1_CORRUPT),
149 "Expected CRYPT_E_ASN1_EOD or CRYPT_E_ASN1_CORRUPT, got %08lx\n",
151 /* add a "signed" cert--the signature isn't a real signature, so this adds
152 * without any check of the signature's validity
154 ret = CertAddEncodedCertificateToStore(store1, X509_ASN_ENCODING,
155 signedBigCert, sizeof(signedBigCert), CERT_STORE_ADD_ALWAYS, &context);
156 ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\n", GetLastError());
157 ok(context != NULL, "Expected a valid cert context\n");
160 ok(context->cbCertEncoded == sizeof(signedBigCert),
161 "Expected cert of %d bytes, got %ld\n", sizeof(signedBigCert),
162 context->cbCertEncoded);
163 ok(!memcmp(context->pbCertEncoded, signedBigCert,
164 sizeof(signedBigCert)), "Unexpected encoded cert in context\n");
165 /* remove it, the rest of the tests will work on an unsigned cert */
166 ret = CertDeleteCertificateFromStore(context);
167 ok(ret, "CertDeleteCertificateFromStore failed: %08lx\n",
170 /* add a cert to store1 */
171 ret = CertAddEncodedCertificateToStore(store1, X509_ASN_ENCODING, bigCert,
172 sizeof(bigCert) - 1, CERT_STORE_ADD_ALWAYS, &context);
173 ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\n", GetLastError());
174 ok(context != NULL, "Expected a valid cert context\n");
180 ok(context->cbCertEncoded == sizeof(bigCert) - 1,
181 "Expected cert of %d bytes, got %ld\n", sizeof(bigCert) - 1,
182 context->cbCertEncoded);
183 ok(!memcmp(context->pbCertEncoded, bigCert, sizeof(bigCert) - 1),
184 "Unexpected encoded cert in context\n");
185 ok(context->hCertStore == store1, "Unexpected store\n");
187 /* check serializing this element */
189 ret = CertSerializeCertificateStoreElement(NULL, 0, NULL, NULL);
190 ret = CertSerializeCertificateStoreElement(context, 0, NULL, NULL);
191 ret = CertSerializeCertificateStoreElement(NULL, 0, NULL, &size);
193 /* apparently flags are ignored */
194 ret = CertSerializeCertificateStoreElement(context, 1, NULL, &size);
195 ok(ret, "CertSerializeCertificateStoreElement failed: %08lx\n",
197 buf = HeapAlloc(GetProcessHeap(), 0, size);
200 ret = CertSerializeCertificateStoreElement(context, 0, buf, &size);
201 ok(size == sizeof(serializedCert), "Expected size %d, got %ld\n",
202 sizeof(serializedCert), size);
203 ok(!memcmp(serializedCert, buf, size),
204 "Unexpected serialized cert\n");
205 HeapFree(GetProcessHeap(), 0, buf);
208 ret = CertFreeCertificateContext(context);
209 ok(ret, "CertFreeCertificateContext failed: %08lx\n", GetLastError());
211 /* verify the cert's in store1 */
212 context = CertEnumCertificatesInStore(store1, NULL);
213 ok(context != NULL, "Expected a valid context\n");
214 context = CertEnumCertificatesInStore(store1, context);
215 ok(!context && GetLastError() == CRYPT_E_NOT_FOUND,
216 "Expected CRYPT_E_NOT_FOUND, got %08lx\n", GetLastError());
217 /* verify store2 (the "open existing" mem store) is still empty */
218 context = CertEnumCertificatesInStore(store2, NULL);
219 ok(!context, "Expected an empty store\n");
220 /* delete the cert from store1, and check it's empty */
221 context = CertEnumCertificatesInStore(store1, NULL);
224 /* Deleting a bitwise copy crashes with an access to an uninitialized
225 * pointer, so a cert context has some special data out there in memory
228 memcpy(©, context, sizeof(copy));
229 ret = CertDeleteCertificateFromStore(©);
231 PCCERT_CONTEXT copy = CertDuplicateCertificateContext(context);
233 ok(copy != NULL, "CertDuplicateCertificateContext failed: %08lx\n",
235 ret = CertDeleteCertificateFromStore(context);
236 ok(ret, "CertDeleteCertificateFromStore failed: %08lx\n",
238 /* try deleting a copy */
239 ret = CertDeleteCertificateFromStore(copy);
240 ok(ret, "CertDeleteCertificateFromStore failed: %08lx\n",
242 /* check that the store is empty */
243 context = CertEnumCertificatesInStore(store1, NULL);
244 ok(!context, "Expected an empty store\n");
247 /* close an empty store */
248 ret = CertCloseStore(NULL, 0);
249 ok(ret, "CertCloseStore failed: %ld\n", GetLastError());
250 ret = CertCloseStore(store1, 0);
251 ok(ret, "CertCloseStore failed: %ld\n", GetLastError());
252 ret = CertCloseStore(store2, 0);
253 ok(ret, "CertCloseStore failed: %ld\n", GetLastError());
255 /* This seems nonsensical, but you can open a read-only mem store, only
258 store1 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
259 CERT_STORE_READONLY_FLAG, NULL);
260 ok(store1 != NULL, "CertOpenStore failed: %ld\n", GetLastError());
261 /* yep, this succeeds */
262 ret = CertAddEncodedCertificateToStore(store1, X509_ASN_ENCODING, bigCert,
263 sizeof(bigCert) - 1, CERT_STORE_ADD_ALWAYS, &context);
264 ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\n", GetLastError());
265 ok(context != NULL, "Expected a valid cert context\n");
268 ok(context->cbCertEncoded == sizeof(bigCert) - 1,
269 "Expected cert of %d bytes, got %ld\n", sizeof(bigCert) - 1,
270 context->cbCertEncoded);
271 ok(!memcmp(context->pbCertEncoded, bigCert, sizeof(bigCert) - 1),
272 "Unexpected encoded cert in context\n");
273 ok(context->hCertStore == store1, "Unexpected store\n");
274 ret = CertDeleteCertificateFromStore(context);
275 ok(ret, "CertDeleteCertificateFromStore failed: %08lx\n",
278 CertCloseStore(store1, 0);
281 static const BYTE bigCert2[] = "\x30\x7a\x02\x01\x01\x30\x02\x06\x00"
282 "\x30\x15\x31\x13\x30\x11\x06\x03\x55\x04\x03\x13\x0a\x41\x6c\x65\x78\x20\x4c"
283 "\x61\x6e\x67\x00\x30\x22\x18\x0f\x31\x36\x30\x31\x30\x31\x30\x31\x30\x30\x30"
284 "\x30\x30\x30\x5a\x18\x0f\x31\x36\x30\x31\x30\x31\x30\x31\x30\x30\x30\x30\x30"
285 "\x30\x5a\x30\x15\x31\x13\x30\x11\x06\x03\x55\x04\x03\x13\x0a\x41\x6c\x65\x78"
286 "\x20\x4c\x61\x6e\x67\x00\x30\x07\x30\x02\x06\x00\x03\x01\x00\xa3\x16\x30\x14"
287 "\x30\x12\x06\x03\x55\x1d\x13\x01\x01\xff\x04\x08\x30\x06\x01\x01\xff\x02\x01"
290 static void testCollectionStore(void)
292 HCERTSTORE store1, store2, collection, collection2;
293 PCCERT_CONTEXT context;
296 collection = CertOpenStore(CERT_STORE_PROV_COLLECTION, 0, 0,
297 CERT_STORE_CREATE_NEW_FLAG, NULL);
299 /* Try adding a cert to any empty collection */
300 ret = CertAddEncodedCertificateToStore(collection, X509_ASN_ENCODING,
301 bigCert, sizeof(bigCert) - 1, CERT_STORE_ADD_ALWAYS, NULL);
302 ok(!ret && GetLastError() == HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED),
303 "Expected HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED), got %08lx\n",
306 /* Create and add a cert to a memory store */
307 store1 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
308 CERT_STORE_CREATE_NEW_FLAG, NULL);
309 ret = CertAddEncodedCertificateToStore(store1, X509_ASN_ENCODING,
310 bigCert, sizeof(bigCert) - 1, CERT_STORE_ADD_ALWAYS, NULL);
311 ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\n", GetLastError());
312 /* Add the memory store to the collection, without allowing adding */
313 ret = CertAddStoreToCollection(collection, store1, 0, 0);
314 ok(ret, "CertAddStoreToCollection failed: %08lx\n", GetLastError());
315 /* Verify the cert is in the collection */
316 context = CertEnumCertificatesInStore(collection, NULL);
317 ok(context != NULL, "Expected a valid context\n");
320 ok(context->hCertStore == collection, "Unexpected store\n");
321 CertFreeCertificateContext(context);
323 /* Check that adding to the collection isn't allowed */
324 ret = CertAddEncodedCertificateToStore(collection, X509_ASN_ENCODING,
325 bigCert2, sizeof(bigCert2) - 1, CERT_STORE_ADD_ALWAYS, NULL);
326 ok(!ret && GetLastError() == HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED),
327 "Expected HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED), got %08lx\n",
330 /* Create a new memory store */
331 store2 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
332 CERT_STORE_CREATE_NEW_FLAG, NULL);
333 /* Try adding a store to a non-collection store */
334 ret = CertAddStoreToCollection(store1, store2,
335 CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
336 ok(!ret && GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
337 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
339 /* Try adding some bogus stores */
340 /* This crashes in Windows
341 ret = CertAddStoreToCollection(0, store2,
342 CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
344 /* This "succeeds"... */
345 ret = CertAddStoreToCollection(collection, 0,
346 CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
347 ok(ret, "CertAddStoreToCollection failed: %08lx\n", GetLastError());
348 /* while this crashes.
349 ret = CertAddStoreToCollection(collection, 1,
350 CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
353 /* Add it to the collection, this time allowing adding */
354 ret = CertAddStoreToCollection(collection, store2,
355 CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
356 ok(ret, "CertAddStoreToCollection failed: %08lx\n", GetLastError());
357 /* Check that adding to the collection is allowed */
358 ret = CertAddEncodedCertificateToStore(collection, X509_ASN_ENCODING,
359 bigCert2, sizeof(bigCert2) - 1, CERT_STORE_ADD_ALWAYS, NULL);
360 ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\n", GetLastError());
361 /* Now check that it was actually added to store2 */
362 context = CertEnumCertificatesInStore(store2, NULL);
363 ok(context != NULL, "Expected a valid context\n");
366 ok(context->hCertStore == store2, "Unexpected store\n");
367 CertFreeCertificateContext(context);
369 /* Check that the collection has both bigCert and bigCert2. bigCert comes
370 * first because store1 was added first.
372 context = CertEnumCertificatesInStore(collection, NULL);
373 ok(context != NULL, "Expected a valid context\n");
376 ok(context->hCertStore == collection, "Unexpected store\n");
377 ok(context->cbCertEncoded == sizeof(bigCert) - 1,
378 "Expected size %d, got %ld\n", sizeof(bigCert) - 1,
379 context->cbCertEncoded);
380 ok(!memcmp(context->pbCertEncoded, bigCert, context->cbCertEncoded),
381 "Unexpected cert\n");
382 context = CertEnumCertificatesInStore(collection, context);
383 ok(context != NULL, "Expected a valid context\n");
386 ok(context->hCertStore == collection, "Unexpected store\n");
387 ok(context->cbCertEncoded == sizeof(bigCert2) - 1,
388 "Expected size %d, got %ld\n", sizeof(bigCert2) - 1,
389 context->cbCertEncoded);
390 ok(!memcmp(context->pbCertEncoded, bigCert2,
391 context->cbCertEncoded), "Unexpected cert\n");
392 context = CertEnumCertificatesInStore(collection, context);
393 ok(!context, "Unexpected cert\n");
396 /* close store2, and check that the collection is unmodified */
397 CertCloseStore(store2, 0);
398 context = CertEnumCertificatesInStore(collection, NULL);
399 ok(context != NULL, "Expected a valid context\n");
402 ok(context->hCertStore == collection, "Unexpected store\n");
403 ok(context->cbCertEncoded == sizeof(bigCert) - 1,
404 "Expected size %d, got %ld\n", sizeof(bigCert) - 1,
405 context->cbCertEncoded);
406 ok(!memcmp(context->pbCertEncoded, bigCert, context->cbCertEncoded),
407 "Unexpected cert\n");
408 context = CertEnumCertificatesInStore(collection, context);
409 ok(context != NULL, "Expected a valid context\n");
412 ok(context->hCertStore == collection, "Unexpected store\n");
413 ok(context->cbCertEncoded == sizeof(bigCert2) - 1,
414 "Expected size %d, got %ld\n", sizeof(bigCert2) - 1,
415 context->cbCertEncoded);
416 ok(!memcmp(context->pbCertEncoded, bigCert2,
417 context->cbCertEncoded), "Unexpected cert\n");
418 context = CertEnumCertificatesInStore(collection, context);
419 ok(!context, "Unexpected cert\n");
423 /* Adding a collection to a collection is legal */
424 collection2 = CertOpenStore(CERT_STORE_PROV_COLLECTION, 0, 0,
425 CERT_STORE_CREATE_NEW_FLAG, NULL);
426 ret = CertAddStoreToCollection(collection2, collection,
427 CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
428 ok(ret, "CertAddStoreToCollection failed: %08lx\n", GetLastError());
429 /* check the contents of collection2 */
430 context = CertEnumCertificatesInStore(collection2, NULL);
431 ok(context != NULL, "Expected a valid context\n");
434 ok(context->hCertStore == collection2, "Unexpected store\n");
435 ok(context->cbCertEncoded == sizeof(bigCert) - 1,
436 "Expected size %d, got %ld\n", sizeof(bigCert) - 1,
437 context->cbCertEncoded);
438 ok(!memcmp(context->pbCertEncoded, bigCert, context->cbCertEncoded),
439 "Unexpected cert\n");
440 context = CertEnumCertificatesInStore(collection2, context);
441 ok(context != NULL, "Expected a valid context\n");
444 ok(context->hCertStore == collection2, "Unexpected store\n");
445 ok(context->cbCertEncoded == sizeof(bigCert2) - 1,
446 "Expected size %d, got %ld\n", sizeof(bigCert2) - 1,
447 context->cbCertEncoded);
448 ok(!memcmp(context->pbCertEncoded, bigCert2,
449 context->cbCertEncoded), "Unexpected cert\n");
450 context = CertEnumCertificatesInStore(collection2, context);
451 ok(!context, "Unexpected cert\n");
455 /* I'd like to test closing the collection in the middle of enumeration,
456 * but my tests have been inconsistent. The first time calling
457 * CertEnumCertificatesInStore on a closed collection succeeded, while the
458 * second crashed. So anything appears to be fair game.
459 * I'd also like to test removing a store from a collection in the middle
460 * of an enumeration, but my tests in Windows have been inconclusive.
461 * In one scenario it worked. In another scenario, about a third of the
462 * time this leads to "random" crashes elsewhere in the code. This
463 * probably means this is not allowed.
466 CertCloseStore(store1, 0);
467 CertCloseStore(collection, 0);
468 CertCloseStore(collection2, 0);
470 /* Add the same cert to two memory stores, then put them in a collection */
471 store1 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
472 CERT_STORE_CREATE_NEW_FLAG, NULL);
473 ok(store1 != 0, "CertOpenStore failed: %08lx\n", GetLastError());
474 store2 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
475 CERT_STORE_CREATE_NEW_FLAG, NULL);
476 ok(store2 != 0, "CertOpenStore failed: %08lx\n", GetLastError());
478 ret = CertAddEncodedCertificateToStore(store1, X509_ASN_ENCODING,
479 bigCert, sizeof(bigCert) - 1, CERT_STORE_ADD_ALWAYS, NULL);
480 ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\n", GetLastError());
481 ret = CertAddEncodedCertificateToStore(store2, X509_ASN_ENCODING,
482 bigCert, sizeof(bigCert) - 1, CERT_STORE_ADD_ALWAYS, NULL);
483 ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\n", GetLastError());
484 collection = CertOpenStore(CERT_STORE_PROV_COLLECTION, 0, 0,
485 CERT_STORE_CREATE_NEW_FLAG, NULL);
486 ok(collection != 0, "CertOpenStore failed: %08lx\n", GetLastError());
488 ret = CertAddStoreToCollection(collection, store1,
489 CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
490 ok(ret, "CertAddStoreToCollection failed: %08lx\n", GetLastError());
491 ret = CertAddStoreToCollection(collection, store2,
492 CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
493 ok(ret, "CertAddStoreToCollection failed: %08lx\n", GetLastError());
495 /* Check that the collection has two copies of the same cert */
496 context = CertEnumCertificatesInStore(collection, NULL);
497 ok(context != NULL, "Expected a valid context\n");
500 ok(context->hCertStore == collection, "Unexpected store\n");
501 ok(context->cbCertEncoded == sizeof(bigCert) - 1,
502 "Expected size %d, got %ld\n", sizeof(bigCert) - 1,
503 context->cbCertEncoded);
504 ok(!memcmp(context->pbCertEncoded, bigCert, context->cbCertEncoded),
505 "Unexpected cert\n");
506 context = CertEnumCertificatesInStore(collection, context);
507 ok(context != NULL, "Expected a valid context\n");
510 ok(context->hCertStore == collection, "Unexpected store\n");
511 ok(context->cbCertEncoded == sizeof(bigCert) - 1,
512 "Expected size %d, got %ld\n", sizeof(bigCert) - 1,
513 context->cbCertEncoded);
514 ok(!memcmp(context->pbCertEncoded, bigCert, context->cbCertEncoded),
515 "Unexpected cert\n");
516 context = CertEnumCertificatesInStore(collection, context);
517 ok(context == NULL, "Unexpected cert\n");
521 /* The following would check whether I can delete an identical cert, rather
522 * than one enumerated from the store. It crashes, so that means I must
523 * only call CertDeleteCertificateFromStore with contexts enumerated from
525 context = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert,
526 sizeof(bigCert) - 1);
527 ok(context != NULL, "CertCreateCertificateContext failed: %08lx\n",
531 ret = CertDeleteCertificateFromStore(collection, context);
532 printf("ret is %d, GetLastError is %08lx\n", ret, GetLastError());
533 CertFreeCertificateContext(context);
537 /* Now check deleting from the collection. */
538 context = CertEnumCertificatesInStore(collection, NULL);
539 ok(context != NULL, "Expected a valid context\n");
542 CertDeleteCertificateFromStore(context);
543 /* store1 should now be empty */
544 context = CertEnumCertificatesInStore(store1, NULL);
545 ok(!context, "Unexpected cert\n");
546 /* and there should be one certificate in the collection */
547 context = CertEnumCertificatesInStore(collection, NULL);
548 ok(context != NULL, "Expected a valid cert\n");
551 ok(context->hCertStore == collection, "Unexpected store\n");
552 ok(context->cbCertEncoded == sizeof(bigCert) - 1,
553 "Expected size %d, got %ld\n", sizeof(bigCert) - 1,
554 context->cbCertEncoded);
555 ok(!memcmp(context->pbCertEncoded, bigCert, context->cbCertEncoded),
556 "Unexpected cert\n");
558 context = CertEnumCertificatesInStore(collection, context);
559 ok(context == NULL, "Unexpected cert\n");
562 /* Finally, test removing stores from the collection. No return value, so
563 * it's a bit funny to test.
566 CertRemoveStoreFromCollection(NULL, NULL);
568 /* This "succeeds," no crash, no last error set */
569 SetLastError(0xdeadbeef);
570 CertRemoveStoreFromCollection(store2, collection);
571 ok(GetLastError() == 0xdeadbeef,
572 "Didn't expect an error to be set: %08lx\n", GetLastError());
574 /* After removing store2, the collection should be empty */
575 SetLastError(0xdeadbeef);
576 CertRemoveStoreFromCollection(collection, store2);
577 ok(GetLastError() == 0xdeadbeef,
578 "Didn't expect an error to be set: %08lx\n", GetLastError());
579 context = CertEnumCertificatesInStore(collection, NULL);
580 ok(!context, "Unexpected cert\n");
582 CertCloseStore(collection, 0);
583 CertCloseStore(store2, 0);
584 CertCloseStore(store1, 0);
587 /* Looks for the property with ID propID in the buffer buf. Returns a pointer
588 * to its header if found, NULL if not.
590 static const struct CertPropIDHeader *findPropID(const BYTE *buf, DWORD size,
593 const struct CertPropIDHeader *ret = NULL;
596 while (size && !ret && !failed)
598 if (size < sizeof(struct CertPropIDHeader))
602 const struct CertPropIDHeader *hdr =
603 (const struct CertPropIDHeader *)buf;
605 size -= sizeof(struct CertPropIDHeader);
606 buf += sizeof(struct CertPropIDHeader);
609 else if (hdr->propID == propID)
621 typedef DWORD (WINAPI *SHDeleteKeyAFunc)(HKEY, LPCSTR);
623 static void testRegStore(void)
625 static const char tempKey[] = "Software\\Wine\\CryptTemp";
631 store = CertOpenStore(CERT_STORE_PROV_REG, 0, 0, 0, NULL);
632 ok(!store && GetLastError() == ERROR_INVALID_HANDLE,
633 "Expected ERROR_INVALID_HANDLE, got %ld\n", GetLastError());
634 store = CertOpenStore(CERT_STORE_PROV_REG, 0, 0, 0, key);
635 ok(!store && GetLastError() == ERROR_INVALID_HANDLE,
636 "Expected ERROR_INVALID_HANDLE, got %ld\n", GetLastError());
638 /* Opening up any old key works.. */
639 key = HKEY_CURRENT_USER;
640 store = CertOpenStore(CERT_STORE_PROV_REG, 0, 0, 0, key);
641 /* Not sure if this is a bug in DuplicateHandle, marking todo_wine for now
643 todo_wine ok(store != 0, "CertOpenStore failed: %08lx\n", GetLastError());
644 CertCloseStore(store, 0);
646 rc = RegCreateKeyExA(HKEY_CURRENT_USER, tempKey, 0, NULL, 0, KEY_ALL_ACCESS,
648 ok(!rc, "RegCreateKeyExA failed: %ld\n", rc);
654 static const char certificates[] = "Certificates\\";
655 char subKeyName[sizeof(certificates) + 20 * 2 + 1], *ptr;
657 PCCERT_CONTEXT context;
659 store = CertOpenStore(CERT_STORE_PROV_REG, 0, 0, 0, key);
660 ok(store != 0, "CertOpenStore failed: %08lx\n", GetLastError());
661 /* Add a certificate. It isn't persisted right away, since it's only
662 * added to the cache..
664 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
665 bigCert2, sizeof(bigCert2) - 1, CERT_STORE_ADD_ALWAYS, NULL);
666 ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\n",
668 /* so flush the cache to force a commit.. */
669 ret = CertControlStore(store, 0, CERT_STORE_CTRL_COMMIT, NULL);
670 ok(ret, "CertControlStore failed: %08lx\n", GetLastError());
671 /* and check that the expected subkey was written. */
673 ret = CryptHashCertificate(0, 0, 0, bigCert2, sizeof(bigCert2) - 1,
675 ok(ret, "CryptHashCertificate failed: %ld\n", GetLastError());
676 strcpy(subKeyName, certificates);
677 for (i = 0, ptr = subKeyName + sizeof(certificates) - 1; i < size;
679 sprintf(ptr, "%02X", hash[i]);
680 rc = RegCreateKeyExA(key, subKeyName, 0, NULL, 0, KEY_ALL_ACCESS, NULL,
682 ok(!rc, "RegCreateKeyExA failed: %ld\n", rc);
688 RegQueryValueExA(subKey, "Blob", NULL, NULL, NULL, &size);
689 buf = HeapAlloc(GetProcessHeap(), 0, size);
692 rc = RegQueryValueExA(subKey, "Blob", NULL, NULL, buf, &size);
693 ok(!rc, "RegQueryValueExA failed: %ld\n", rc);
696 const struct CertPropIDHeader *hdr;
698 /* Both the hash and the cert should be present */
699 hdr = findPropID(buf, size, CERT_CERT_PROP_ID);
700 ok(hdr != NULL, "Expected to find a cert property\n");
703 ok(hdr->cb == sizeof(bigCert2) - 1,
704 "Unexpected size %ld of cert property, expected %d\n",
705 hdr->cb, sizeof(bigCert2) - 1);
706 ok(!memcmp((BYTE *)hdr + sizeof(*hdr), bigCert2,
707 hdr->cb), "Unexpected cert in cert property\n");
709 hdr = findPropID(buf, size, CERT_HASH_PROP_ID);
710 ok(hdr != NULL, "Expected to find a hash property\n");
713 ok(hdr->cb == sizeof(hash),
714 "Unexpected size %ld of hash property, expected %d\n",
715 hdr->cb, sizeof(hash));
716 ok(!memcmp((BYTE *)hdr + sizeof(*hdr), hash,
717 hdr->cb), "Unexpected hash in cert property\n");
720 HeapFree(GetProcessHeap(), 0, buf);
725 /* Remove the existing context */
726 context = CertEnumCertificatesInStore(store, NULL);
727 ok(context != NULL, "Expected a cert context\n");
729 CertDeleteCertificateFromStore(context);
730 ret = CertControlStore(store, 0, CERT_STORE_CTRL_COMMIT, NULL);
731 ok(ret, "CertControlStore failed: %08lx\n", GetLastError());
733 /* Add a serialized cert with a bogus hash directly to the registry */
734 memset(hash, 0, sizeof(hash));
735 strcpy(subKeyName, certificates);
736 for (i = 0, ptr = subKeyName + sizeof(certificates) - 1;
737 i < sizeof(hash); i++, ptr += 2)
738 sprintf(ptr, "%02X", hash[i]);
739 rc = RegCreateKeyExA(key, subKeyName, 0, NULL, 0, KEY_ALL_ACCESS, NULL,
741 ok(!rc, "RegCreateKeyExA failed: %ld\n", rc);
744 BYTE buf[sizeof(struct CertPropIDHeader) * 2 + sizeof(hash) +
745 sizeof(bigCert) - 1], *ptr;
747 struct CertPropIDHeader *hdr;
749 hdr = (struct CertPropIDHeader *)buf;
750 hdr->propID = CERT_HASH_PROP_ID;
752 hdr->cb = sizeof(hash);
753 ptr = buf + sizeof(*hdr);
754 memcpy(ptr, hash, sizeof(hash));
756 hdr = (struct CertPropIDHeader *)ptr;
757 hdr->propID = CERT_CERT_PROP_ID;
759 hdr->cb = sizeof(bigCert) - 1;
761 memcpy(ptr, bigCert, sizeof(bigCert) - 1);
763 rc = RegSetValueExA(subKey, "Blob", 0, REG_BINARY, buf,
765 ok(!rc, "RegSetValueExA failed: %ld\n", rc);
767 ret = CertControlStore(store, 0, CERT_STORE_CTRL_RESYNC, NULL);
768 ok(ret, "CertControlStore failed: %08lx\n", GetLastError());
770 /* Make sure the bogus hash cert gets loaded. */
774 context = CertEnumCertificatesInStore(store, context);
777 } while (context != NULL);
778 ok(certCount == 1, "Expected 1 certificates, got %ld\n", certCount);
783 /* Add another serialized cert directly to the registry, this time
784 * under the correct key name (named with the correct hash value).
787 ret = CryptHashCertificate(0, 0, 0, bigCert2,
788 sizeof(bigCert2) - 1, hash, &size);
789 ok(ret, "CryptHashCertificate failed: %ld\n", GetLastError());
790 strcpy(subKeyName, certificates);
791 for (i = 0, ptr = subKeyName + sizeof(certificates) - 1;
792 i < sizeof(hash); i++, ptr += 2)
793 sprintf(ptr, "%02X", hash[i]);
794 rc = RegCreateKeyExA(key, subKeyName, 0, NULL, 0, KEY_ALL_ACCESS, NULL,
796 ok(!rc, "RegCreateKeyExA failed: %ld\n", rc);
799 BYTE buf[sizeof(struct CertPropIDHeader) * 2 + sizeof(hash) +
800 sizeof(bigCert2) - 1], *ptr;
802 PCCERT_CONTEXT context;
803 struct CertPropIDHeader *hdr;
805 /* First try with a bogus hash... */
806 hdr = (struct CertPropIDHeader *)buf;
807 hdr->propID = CERT_HASH_PROP_ID;
809 hdr->cb = sizeof(hash);
810 ptr = buf + sizeof(*hdr);
811 memset(ptr, 0, sizeof(hash));
813 hdr = (struct CertPropIDHeader *)ptr;
814 hdr->propID = CERT_CERT_PROP_ID;
816 hdr->cb = sizeof(bigCert2) - 1;
818 memcpy(ptr, bigCert2, sizeof(bigCert2) - 1);
820 rc = RegSetValueExA(subKey, "Blob", 0, REG_BINARY, buf,
822 ok(!rc, "RegSetValueExA failed: %ld\n", rc);
824 ret = CertControlStore(store, 0, CERT_STORE_CTRL_RESYNC, NULL);
825 ok(ret, "CertControlStore failed: %08lx\n", GetLastError());
827 /* and make sure just one cert still gets loaded. */
831 context = CertEnumCertificatesInStore(store, context);
834 } while (context != NULL);
835 ok(certCount == 1, "Expected 1 certificates, got %ld\n", certCount);
837 /* Try again with the correct hash... */
838 ptr = buf + sizeof(*hdr);
839 memcpy(ptr, hash, sizeof(hash));
841 rc = RegSetValueExA(subKey, "Blob", 0, REG_BINARY, buf,
843 ok(!rc, "RegSetValueExA failed: %ld\n", rc);
845 ret = CertControlStore(store, 0, CERT_STORE_CTRL_RESYNC, NULL);
846 ok(ret, "CertControlStore failed: %08lx\n", GetLastError());
848 /* and make sure two certs get loaded. */
852 context = CertEnumCertificatesInStore(store, context);
855 } while (context != NULL);
856 ok(certCount == 2, "Expected 2 certificates, got %ld\n", certCount);
860 CertCloseStore(store, 0);
861 /* Is delete allowed on a reg store? */
862 store = CertOpenStore(CERT_STORE_PROV_REG, 0, 0,
863 CERT_STORE_DELETE_FLAG, key);
864 ok(store == NULL, "Expected NULL return from CERT_STORE_DELETE_FLAG\n");
865 ok(GetLastError() == 0, "CertOpenStore failed: %08lx\n",
870 /* The CertOpenStore with CERT_STORE_DELETE_FLAG above will delete the
871 * contents of the key, but not the key itself.
873 rc = RegCreateKeyExA(HKEY_CURRENT_USER, tempKey, 0, NULL, 0, KEY_ALL_ACCESS,
875 ok(!rc, "RegCreateKeyExA failed: %ld\n", rc);
876 ok(disp == REG_OPENED_EXISTING_KEY,
877 "Expected REG_OPENED_EXISTING_KEY, got %ld\n", disp);
881 rc = RegDeleteKeyA(HKEY_CURRENT_USER, tempKey);
884 HMODULE shlwapi = LoadLibraryA("shlwapi");
886 /* Use shlwapi's SHDeleteKeyA to _really_ blow away the key,
887 * otherwise subsequent tests will fail.
891 SHDeleteKeyAFunc pSHDeleteKeyA =
892 (SHDeleteKeyAFunc)GetProcAddress(shlwapi, "SHDeleteKeyA");
895 pSHDeleteKeyA(HKEY_CURRENT_USER, tempKey);
896 FreeLibrary(shlwapi);
902 static const char MyA[] = { 'M','y',0,0 };
903 static const WCHAR MyW[] = { 'M','y',0 };
904 static const WCHAR BogusW[] = { 'B','o','g','u','s',0 };
905 static const WCHAR BogusPathW[] = { 'S','o','f','t','w','a','r','e','\\',
906 'M','i','c','r','o','s','o','f','t','\\','S','y','s','t','e','m','C','e','r',
907 't','i','f','i','c','a','t','e','s','\\','B','o','g','u','s',0 };
909 static void testSystemRegStore(void)
911 HCERTSTORE store, memStore;
913 /* Check with a UNICODE name */
914 store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY, 0, 0,
915 CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_OPEN_EXISTING_FLAG, MyW);
916 /* Not all OSes support CERT_STORE_PROV_SYSTEM_REGISTRY, so don't continue
917 * testing if they don't.
922 /* Check that it isn't a collection store */
923 memStore = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
924 CERT_STORE_CREATE_NEW_FLAG, NULL);
927 BOOL ret = CertAddStoreToCollection(store, memStore, 0, 0);
929 ok(!ret && GetLastError() ==
930 HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
931 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
933 CertCloseStore(memStore, 0);
935 CertCloseStore(store, 0);
937 /* Check opening a bogus store */
938 store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY, 0, 0,
939 CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_OPEN_EXISTING_FLAG, BogusW);
940 ok(!store && GetLastError() == ERROR_FILE_NOT_FOUND,
941 "Expected ERROR_FILE_NOT_FOUND, got %08lx\n", GetLastError());
942 store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY, 0, 0,
943 CERT_SYSTEM_STORE_CURRENT_USER, BogusW);
944 ok(store != 0, "CertOpenStore failed: %08lx\n", GetLastError());
946 CertCloseStore(store, 0);
947 /* Now check whether deleting is allowed */
948 store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY, 0, 0,
949 CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_DELETE_FLAG, BogusW);
950 RegDeleteKeyW(HKEY_CURRENT_USER, BogusPathW);
952 store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY, 0, 0, 0, NULL);
953 ok(!store && GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
954 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
956 store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY, 0, 0,
957 CERT_SYSTEM_STORE_LOCAL_MACHINE | CERT_SYSTEM_STORE_CURRENT_USER, MyA);
958 ok(!store && GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
959 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
961 store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY, 0, 0,
962 CERT_SYSTEM_STORE_LOCAL_MACHINE | CERT_SYSTEM_STORE_CURRENT_USER, MyW);
963 ok(!store && GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
964 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
966 /* The name is expected to be UNICODE, check with an ASCII name */
967 store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY, 0, 0,
968 CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_OPEN_EXISTING_FLAG, MyA);
969 ok(!store && GetLastError() == ERROR_FILE_NOT_FOUND,
970 "Expected ERROR_FILE_NOT_FOUND, got %08lx\n", GetLastError());
973 static void testSystemStore(void)
975 static const WCHAR baskslashW[] = { '\\',0 };
977 WCHAR keyName[MAX_PATH];
981 store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0, 0, NULL);
982 ok(!store && GetLastError() == ERROR_FILE_NOT_FOUND,
983 "Expected ERROR_FILE_NOT_FOUND, got %08lx\n", GetLastError());
984 store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0,
985 CERT_SYSTEM_STORE_LOCAL_MACHINE | CERT_SYSTEM_STORE_CURRENT_USER, MyA);
986 ok(!store && GetLastError() == ERROR_FILE_NOT_FOUND,
987 "Expected ERROR_FILE_NOT_FOUND, got %08lx\n", GetLastError());
988 store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0,
989 CERT_SYSTEM_STORE_LOCAL_MACHINE | CERT_SYSTEM_STORE_CURRENT_USER, MyW);
990 ok(!store && GetLastError() == ERROR_FILE_NOT_FOUND,
991 "Expected ERROR_FILE_NOT_FOUND, got %08lx\n", GetLastError());
992 /* The name is expected to be UNICODE, first check with an ASCII name */
993 store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0,
994 CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_OPEN_EXISTING_FLAG, MyA);
995 ok(!store && GetLastError() == ERROR_FILE_NOT_FOUND,
996 "Expected ERROR_FILE_NOT_FOUND, got %08lx\n", GetLastError());
997 /* Create the expected key */
998 lstrcpyW(keyName, CERT_LOCAL_MACHINE_SYSTEM_STORE_REGPATH);
999 lstrcatW(keyName, baskslashW);
1000 lstrcatW(keyName, MyW);
1001 rc = RegCreateKeyExW(HKEY_CURRENT_USER, keyName, 0, NULL, 0, KEY_READ,
1003 ok(!rc, "RegCreateKeyEx failed: %ld\n", rc);
1006 /* Check opening with a UNICODE name, specifying the create new flag */
1007 store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0,
1008 CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_CREATE_NEW_FLAG, MyW);
1009 ok(!store && GetLastError() == ERROR_FILE_EXISTS,
1010 "Expected ERROR_FILE_EXISTS, got %08lx\n", GetLastError());
1011 /* Now check opening with a UNICODE name, this time opening existing */
1012 store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0,
1013 CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_OPEN_EXISTING_FLAG, MyW);
1014 ok(store != 0, "CertOpenStore failed: %08lx\n", GetLastError());
1017 HCERTSTORE memStore = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
1018 CERT_STORE_CREATE_NEW_FLAG, NULL);
1020 /* Check that it's a collection store */
1023 BOOL ret = CertAddStoreToCollection(store, memStore, 0, 0);
1025 /* FIXME: this'll fail on NT4, but what error will it give? */
1026 ok(ret, "CertAddStoreToCollection failed: %08lx\n", GetLastError());
1027 CertCloseStore(memStore, 0);
1029 CertCloseStore(store, 0);
1032 /* Check opening a bogus store */
1033 store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0,
1034 CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_OPEN_EXISTING_FLAG, BogusW);
1035 ok(!store && GetLastError() == ERROR_FILE_NOT_FOUND,
1036 "Expected ERROR_FILE_NOT_FOUND, got %08lx\n", GetLastError());
1037 store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0,
1038 CERT_SYSTEM_STORE_CURRENT_USER, BogusW);
1039 ok(store != 0, "CertOpenStore failed: %08lx\n", GetLastError());
1041 CertCloseStore(store, 0);
1042 /* Now check whether deleting is allowed */
1043 store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0,
1044 CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_DELETE_FLAG, BogusW);
1045 RegDeleteKeyW(HKEY_CURRENT_USER, BogusPathW);
1048 static void testCertOpenSystemStore(void)
1052 store = CertOpenSystemStoreW(0, NULL);
1053 ok(!store && GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
1054 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
1056 /* This succeeds, and on WinXP at least, the Bogus key is created under
1057 * HKCU (but not under HKLM, even when run as an administrator.)
1059 store = CertOpenSystemStoreW(0, BogusW);
1060 ok(store != 0, "CertOpenSystemStore failed: %08lx\n", GetLastError());
1062 CertCloseStore(store, 0);
1063 /* Delete it so other tests succeed next time around */
1064 store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0,
1065 CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_DELETE_FLAG, BogusW);
1066 RegDeleteKeyW(HKEY_CURRENT_USER, BogusPathW);
1069 static void testCertProperties(void)
1071 PCCERT_CONTEXT context = CertCreateCertificateContext(X509_ASN_ENCODING,
1072 bigCert, sizeof(bigCert) - 1);
1074 ok(context != NULL, "CertCreateCertificateContext failed: %08lx\n",
1078 DWORD propID, numProps, access, size;
1080 BYTE hash[20] = { 0 }, hashProperty[20];
1081 CRYPT_DATA_BLOB blob;
1084 propID = CertEnumCertificateContextProperties(NULL, 0);
1090 propID = CertEnumCertificateContextProperties(context, propID);
1093 } while (propID != 0);
1094 ok(numProps == 0, "Expected 0 properties, got %ld\n", numProps);
1096 /* Tests with a NULL cert context. Prop ID 0 fails.. */
1097 ret = CertSetCertificateContextProperty(NULL, 0, 0, NULL);
1098 ok(!ret && GetLastError() ==
1099 HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
1100 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
1102 /* while this just crashes.
1103 ret = CertSetCertificateContextProperty(NULL,
1104 CERT_KEY_PROV_HANDLE_PROP_ID, 0, NULL);
1107 ret = CertSetCertificateContextProperty(context, 0, 0, NULL);
1108 ok(!ret && GetLastError() ==
1109 HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
1110 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
1112 /* Can't set the cert property directly, this crashes.
1113 ret = CertSetCertificateContextProperty(context,
1114 CERT_CERT_PROP_ID, 0, bigCert2);
1118 ret = CertGetCertificateContextProperty(context,
1119 CERT_ACCESS_STATE_PROP_ID, 0, NULL);
1121 size = sizeof(access);
1122 ret = CertGetCertificateContextProperty(context,
1123 CERT_ACCESS_STATE_PROP_ID, &access, &size);
1124 ok(ret, "CertGetCertificateContextProperty failed: %08lx\n",
1126 ok(!(access & CERT_ACCESS_STATE_WRITE_PERSIST_FLAG),
1127 "Didn't expect a persisted cert\n");
1128 /* Trying to set this "read only" property crashes.
1129 access |= CERT_ACCESS_STATE_WRITE_PERSIST_FLAG;
1130 ret = CertSetCertificateContextProperty(context,
1131 CERT_ACCESS_STATE_PROP_ID, 0, &access);
1134 /* Can I set the hash to an invalid hash? */
1136 blob.cbData = sizeof(hash);
1137 ret = CertSetCertificateContextProperty(context, CERT_HASH_PROP_ID, 0,
1139 ok(ret, "CertSetCertificateContextProperty failed: %08lx\n",
1141 size = sizeof(hashProperty);
1142 ret = CertGetCertificateContextProperty(context, CERT_HASH_PROP_ID,
1143 hashProperty, &size);
1144 ok(!memcmp(hashProperty, hash, sizeof(hash)), "Unexpected hash\n");
1145 /* Delete the (bogus) hash, and get the real one */
1146 ret = CertSetCertificateContextProperty(context, CERT_HASH_PROP_ID, 0,
1148 ok(ret, "CertSetCertificateContextProperty failed: %08lx\n",
1150 size = sizeof(hash);
1151 ret = CryptHashCertificate(0, 0, 0, bigCert, sizeof(bigCert) - 1,
1153 ok(ret, "CryptHashCertificate failed: %08lx\n", GetLastError());
1154 ret = CertGetCertificateContextProperty(context, CERT_HASH_PROP_ID,
1155 hashProperty, &size);
1156 ok(ret, "CertGetCertificateContextProperty failed: %08lx\n",
1158 ok(!memcmp(hash, hashProperty, sizeof(hash)), "Unexpected hash\n");
1160 /* Now that the hash property is set, we should get one property when
1166 propID = CertEnumCertificateContextProperties(context, propID);
1169 } while (propID != 0);
1170 ok(numProps == 1, "Expected 1 properties, got %ld\n", numProps);
1172 CertFreeCertificateContext(context);
1176 static void testAddSerialized(void)
1180 BYTE buf[sizeof(struct CertPropIDHeader) * 2 + 20 + sizeof(bigCert) - 1] =
1183 struct CertPropIDHeader *hdr;
1184 PCCERT_CONTEXT context;
1186 ret = CertAddSerializedElementToStore(0, NULL, 0, 0, 0, 0, NULL, NULL);
1187 ok(!ret && GetLastError() == ERROR_END_OF_MEDIA,
1188 "Expected ERROR_END_OF_MEDIA, got %08lx\n", GetLastError());
1190 store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
1191 CERT_STORE_CREATE_NEW_FLAG, NULL);
1192 ok(store != 0, "CertOpenStore failed: %08lx\n", GetLastError());
1194 ret = CertAddSerializedElementToStore(store, NULL, 0, 0, 0, 0, NULL, NULL);
1195 ok(!ret && GetLastError() == ERROR_END_OF_MEDIA,
1196 "Expected ERROR_END_OF_MEDIA, got %08lx\n", GetLastError());
1198 /* Test with an empty property */
1199 hdr = (struct CertPropIDHeader *)buf;
1200 hdr->propID = CERT_CERT_PROP_ID;
1203 ret = CertAddSerializedElementToStore(store, buf, sizeof(buf), 0, 0, 0,
1205 ok(!ret && GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
1206 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
1208 /* Test with a bad size in property header */
1209 hdr->cb = sizeof(bigCert) - 2;
1210 memcpy(buf + sizeof(struct CertPropIDHeader), bigCert, sizeof(bigCert) - 1);
1211 ret = CertAddSerializedElementToStore(store, buf, sizeof(buf), 0, 0, 0,
1213 ok(!ret && GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
1214 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
1216 ret = CertAddSerializedElementToStore(store, buf,
1217 sizeof(struct CertPropIDHeader) + sizeof(bigCert) - 1, 0, 0, 0, NULL,
1219 ok(!ret && GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
1220 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
1222 ret = CertAddSerializedElementToStore(store, buf,
1223 sizeof(struct CertPropIDHeader) + sizeof(bigCert) - 1, CERT_STORE_ADD_NEW,
1225 ok(!ret && GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
1226 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
1228 /* Kosher size in property header, but no context type */
1229 hdr->cb = sizeof(bigCert) - 1;
1230 ret = CertAddSerializedElementToStore(store, buf, sizeof(buf), 0, 0, 0,
1232 ok(!ret && GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
1233 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
1235 ret = CertAddSerializedElementToStore(store, buf,
1236 sizeof(struct CertPropIDHeader) + sizeof(bigCert) - 1, 0, 0, 0, NULL,
1238 ok(!ret && GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
1239 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
1241 ret = CertAddSerializedElementToStore(store, buf,
1242 sizeof(struct CertPropIDHeader) + sizeof(bigCert) - 1, CERT_STORE_ADD_NEW,
1244 ok(!ret && GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
1245 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
1247 /* With a bad context type */
1248 ret = CertAddSerializedElementToStore(store, buf, sizeof(buf), 0, 0,
1249 CERT_STORE_CRL_CONTEXT_FLAG, NULL, NULL);
1250 ok(!ret && GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
1251 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
1253 ret = CertAddSerializedElementToStore(store, buf,
1254 sizeof(struct CertPropIDHeader) + sizeof(bigCert) - 1, 0, 0,
1255 CERT_STORE_CRL_CONTEXT_FLAG, NULL, NULL);
1256 ok(!ret && GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
1257 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
1259 ret = CertAddSerializedElementToStore(store, buf,
1260 sizeof(struct CertPropIDHeader) + sizeof(bigCert) - 1, CERT_STORE_ADD_NEW,
1261 0, CERT_STORE_CRL_CONTEXT_FLAG, NULL, NULL);
1262 ok(!ret && GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
1263 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
1265 /* Bad unknown field, good type */
1267 ret = CertAddSerializedElementToStore(store, buf, sizeof(buf), 0, 0,
1268 CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL, NULL);
1269 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
1270 "Expected ERROR_FILE_NOT_FOUND got %08lx\n", GetLastError());
1271 ret = CertAddSerializedElementToStore(store, buf,
1272 sizeof(struct CertPropIDHeader) + sizeof(bigCert) - 1, 0, 0,
1273 CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL, NULL);
1274 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
1275 "Expected ERROR_FILE_NOT_FOUND got %08lx\n", GetLastError());
1276 ret = CertAddSerializedElementToStore(store, buf,
1277 sizeof(struct CertPropIDHeader) + sizeof(bigCert) - 1, CERT_STORE_ADD_NEW,
1278 0, CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL, NULL);
1279 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
1280 "Expected ERROR_FILE_NOT_FOUND got %08lx\n", GetLastError());
1281 /* Most everything okay, but bad add disposition */
1284 ret = CertAddSerializedElementToStore(store, buf, sizeof(buf), 0, 0,
1285 CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL, NULL);
1287 ret = CertAddSerializedElementToStore(store, buf,
1288 sizeof(struct CertPropIDHeader) + sizeof(bigCert) - 1, 0, 0,
1289 CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL, NULL);
1291 /* Everything okay, but buffer's too big */
1292 ret = CertAddSerializedElementToStore(store, buf, sizeof(buf),
1293 CERT_STORE_ADD_NEW, 0, CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL, NULL);
1294 ok(ret, "CertAddSerializedElementToStore failed: %08lx\n", GetLastError());
1295 /* Everything okay, check it's not re-added */
1296 ret = CertAddSerializedElementToStore(store, buf,
1297 sizeof(struct CertPropIDHeader) + sizeof(bigCert) - 1, CERT_STORE_ADD_NEW,
1298 0, CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL, NULL);
1299 ok(!ret && GetLastError() == CRYPT_E_EXISTS,
1300 "Expected CRYPT_E_EXISTS, got %08lx\n", GetLastError());
1302 context = CertEnumCertificatesInStore(store, NULL);
1303 ok(context != NULL, "Expected a cert\n");
1305 CertDeleteCertificateFromStore(context);
1307 /* Try adding with a bogus hash. Oddly enough, it succeeds, and the hash,
1308 * when queried, is the real hash rather than the bogus hash.
1310 hdr = (struct CertPropIDHeader *)(buf + sizeof(struct CertPropIDHeader) +
1311 sizeof(bigCert) - 1);
1312 hdr->propID = CERT_HASH_PROP_ID;
1314 hdr->cb = sizeof(hash);
1315 memset(hash, 0xc, sizeof(hash));
1316 memcpy((LPBYTE)hdr + sizeof(struct CertPropIDHeader), hash, sizeof(hash));
1317 ret = CertAddSerializedElementToStore(store, buf, sizeof(buf),
1318 CERT_STORE_ADD_NEW, 0, CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL,
1319 (const void **)&context);
1320 ok(ret, "CertAddSerializedElementToStore failed: %08lx\n", GetLastError());
1323 BYTE hashVal[20], realHash[20];
1324 DWORD size = sizeof(hashVal);
1326 ret = CryptHashCertificate(0, 0, 0, bigCert, sizeof(bigCert) - 1,
1328 ok(ret, "CryptHashCertificate failed: %08lx\n", GetLastError());
1329 ret = CertGetCertificateContextProperty(context, CERT_HASH_PROP_ID,
1331 ok(ret, "CertGetCertificateContextProperty failed: %08lx\n",
1333 ok(!memcmp(hashVal, realHash, size), "Unexpected hash\n");
1336 CertCloseStore(store, 0);
1341 testCryptHashCert();
1343 /* various combinations of CertOpenStore */
1345 testCollectionStore();
1347 testSystemRegStore();
1350 testCertOpenSystemStore();
1352 testCertProperties();
1353 testAddSerialized();