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",
169 CertFreeCertificateContext(context);
171 /* add a cert to store1 */
172 ret = CertAddEncodedCertificateToStore(store1, X509_ASN_ENCODING, bigCert,
173 sizeof(bigCert) - 1, CERT_STORE_ADD_ALWAYS, &context);
174 ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\n", GetLastError());
175 ok(context != NULL, "Expected a valid cert context\n");
181 ok(context->cbCertEncoded == sizeof(bigCert) - 1,
182 "Expected cert of %d bytes, got %ld\n", sizeof(bigCert) - 1,
183 context->cbCertEncoded);
184 ok(!memcmp(context->pbCertEncoded, bigCert, sizeof(bigCert) - 1),
185 "Unexpected encoded cert in context\n");
186 ok(context->hCertStore == store1, "Unexpected store\n");
188 /* check serializing this element */
190 ret = CertSerializeCertificateStoreElement(NULL, 0, NULL, NULL);
191 ret = CertSerializeCertificateStoreElement(context, 0, NULL, NULL);
192 ret = CertSerializeCertificateStoreElement(NULL, 0, NULL, &size);
194 /* apparently flags are ignored */
195 ret = CertSerializeCertificateStoreElement(context, 1, NULL, &size);
196 ok(ret, "CertSerializeCertificateStoreElement failed: %08lx\n",
198 buf = HeapAlloc(GetProcessHeap(), 0, size);
201 ret = CertSerializeCertificateStoreElement(context, 0, buf, &size);
202 ok(size == sizeof(serializedCert), "Expected size %d, got %ld\n",
203 sizeof(serializedCert), size);
204 ok(!memcmp(serializedCert, buf, size),
205 "Unexpected serialized cert\n");
206 HeapFree(GetProcessHeap(), 0, buf);
209 ret = CertFreeCertificateContext(context);
210 ok(ret, "CertFreeCertificateContext failed: %08lx\n", GetLastError());
212 /* verify the cert's in store1 */
213 context = CertEnumCertificatesInStore(store1, NULL);
214 ok(context != NULL, "Expected a valid context\n");
215 context = CertEnumCertificatesInStore(store1, context);
216 ok(!context && GetLastError() == CRYPT_E_NOT_FOUND,
217 "Expected CRYPT_E_NOT_FOUND, got %08lx\n", GetLastError());
218 /* verify store2 (the "open existing" mem store) is still empty */
219 context = CertEnumCertificatesInStore(store2, NULL);
220 ok(!context, "Expected an empty store\n");
221 /* delete the cert from store1, and check it's empty */
222 context = CertEnumCertificatesInStore(store1, NULL);
225 /* Deleting a bitwise copy crashes with an access to an uninitialized
226 * pointer, so a cert context has some special data out there in memory
229 memcpy(©, context, sizeof(copy));
230 ret = CertDeleteCertificateFromStore(©);
232 PCCERT_CONTEXT copy = CertDuplicateCertificateContext(context);
234 ok(copy != NULL, "CertDuplicateCertificateContext failed: %08lx\n",
236 ret = CertDeleteCertificateFromStore(context);
237 ok(ret, "CertDeleteCertificateFromStore failed: %08lx\n",
239 /* try deleting a copy */
240 ret = CertDeleteCertificateFromStore(copy);
241 ok(ret, "CertDeleteCertificateFromStore failed: %08lx\n",
243 /* check that the store is empty */
244 context = CertEnumCertificatesInStore(store1, NULL);
245 ok(!context, "Expected an empty store\n");
248 /* close an empty store */
249 ret = CertCloseStore(NULL, 0);
250 ok(ret, "CertCloseStore failed: %ld\n", GetLastError());
251 ret = CertCloseStore(store1, 0);
252 ok(ret, "CertCloseStore failed: %ld\n", GetLastError());
253 ret = CertCloseStore(store2, 0);
254 ok(ret, "CertCloseStore failed: %ld\n", GetLastError());
256 /* This seems nonsensical, but you can open a read-only mem store, only
259 store1 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
260 CERT_STORE_READONLY_FLAG, NULL);
261 ok(store1 != NULL, "CertOpenStore failed: %ld\n", GetLastError());
262 /* yep, this succeeds */
263 ret = CertAddEncodedCertificateToStore(store1, X509_ASN_ENCODING, bigCert,
264 sizeof(bigCert) - 1, CERT_STORE_ADD_ALWAYS, &context);
265 ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\n", GetLastError());
266 ok(context != NULL, "Expected a valid cert context\n");
269 ok(context->cbCertEncoded == sizeof(bigCert) - 1,
270 "Expected cert of %d bytes, got %ld\n", sizeof(bigCert) - 1,
271 context->cbCertEncoded);
272 ok(!memcmp(context->pbCertEncoded, bigCert, sizeof(bigCert) - 1),
273 "Unexpected encoded cert in context\n");
274 ok(context->hCertStore == store1, "Unexpected store\n");
275 ret = CertDeleteCertificateFromStore(context);
276 ok(ret, "CertDeleteCertificateFromStore failed: %08lx\n",
279 CertCloseStore(store1, 0);
282 static const BYTE bigCert2[] = "\x30\x7a\x02\x01\x01\x30\x02\x06\x00"
283 "\x30\x15\x31\x13\x30\x11\x06\x03\x55\x04\x03\x13\x0a\x41\x6c\x65\x78\x20\x4c"
284 "\x61\x6e\x67\x00\x30\x22\x18\x0f\x31\x36\x30\x31\x30\x31\x30\x31\x30\x30\x30"
285 "\x30\x30\x30\x5a\x18\x0f\x31\x36\x30\x31\x30\x31\x30\x31\x30\x30\x30\x30\x30"
286 "\x30\x5a\x30\x15\x31\x13\x30\x11\x06\x03\x55\x04\x03\x13\x0a\x41\x6c\x65\x78"
287 "\x20\x4c\x61\x6e\x67\x00\x30\x07\x30\x02\x06\x00\x03\x01\x00\xa3\x16\x30\x14"
288 "\x30\x12\x06\x03\x55\x1d\x13\x01\x01\xff\x04\x08\x30\x06\x01\x01\xff\x02\x01"
291 static void testCollectionStore(void)
293 HCERTSTORE store1, store2, collection, collection2;
294 PCCERT_CONTEXT context;
297 collection = CertOpenStore(CERT_STORE_PROV_COLLECTION, 0, 0,
298 CERT_STORE_CREATE_NEW_FLAG, NULL);
300 /* Try adding a cert to any empty collection */
301 ret = CertAddEncodedCertificateToStore(collection, X509_ASN_ENCODING,
302 bigCert, sizeof(bigCert) - 1, CERT_STORE_ADD_ALWAYS, NULL);
303 ok(!ret && GetLastError() == HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED),
304 "Expected HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED), got %08lx\n",
307 /* Create and add a cert to a memory store */
308 store1 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
309 CERT_STORE_CREATE_NEW_FLAG, NULL);
310 ret = CertAddEncodedCertificateToStore(store1, X509_ASN_ENCODING,
311 bigCert, sizeof(bigCert) - 1, CERT_STORE_ADD_ALWAYS, NULL);
312 ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\n", GetLastError());
313 /* Add the memory store to the collection, without allowing adding */
314 ret = CertAddStoreToCollection(collection, store1, 0, 0);
315 ok(ret, "CertAddStoreToCollection failed: %08lx\n", GetLastError());
316 /* Verify the cert is in the collection */
317 context = CertEnumCertificatesInStore(collection, NULL);
318 ok(context != NULL, "Expected a valid context\n");
321 ok(context->hCertStore == collection, "Unexpected store\n");
322 CertFreeCertificateContext(context);
324 /* Check that adding to the collection isn't allowed */
325 ret = CertAddEncodedCertificateToStore(collection, X509_ASN_ENCODING,
326 bigCert2, sizeof(bigCert2) - 1, CERT_STORE_ADD_ALWAYS, NULL);
327 ok(!ret && GetLastError() == HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED),
328 "Expected HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED), got %08lx\n",
331 /* Create a new memory store */
332 store2 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
333 CERT_STORE_CREATE_NEW_FLAG, NULL);
334 /* Try adding a store to a non-collection store */
335 ret = CertAddStoreToCollection(store1, store2,
336 CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
337 ok(!ret && GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
338 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
340 /* Try adding some bogus stores */
341 /* This crashes in Windows
342 ret = CertAddStoreToCollection(0, store2,
343 CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
345 /* This "succeeds"... */
346 ret = CertAddStoreToCollection(collection, 0,
347 CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
348 ok(ret, "CertAddStoreToCollection failed: %08lx\n", GetLastError());
349 /* while this crashes.
350 ret = CertAddStoreToCollection(collection, 1,
351 CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
354 /* Add it to the collection, this time allowing adding */
355 ret = CertAddStoreToCollection(collection, store2,
356 CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
357 ok(ret, "CertAddStoreToCollection failed: %08lx\n", GetLastError());
358 /* Check that adding to the collection is allowed */
359 ret = CertAddEncodedCertificateToStore(collection, X509_ASN_ENCODING,
360 bigCert2, sizeof(bigCert2) - 1, CERT_STORE_ADD_ALWAYS, NULL);
361 ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\n", GetLastError());
362 /* Now check that it was actually added to store2 */
363 context = CertEnumCertificatesInStore(store2, NULL);
364 ok(context != NULL, "Expected a valid context\n");
367 ok(context->hCertStore == store2, "Unexpected store\n");
368 CertFreeCertificateContext(context);
370 /* Check that the collection has both bigCert and bigCert2. bigCert comes
371 * first because store1 was added first.
373 context = CertEnumCertificatesInStore(collection, NULL);
374 ok(context != NULL, "Expected a valid context\n");
377 ok(context->hCertStore == collection, "Unexpected store\n");
378 ok(context->cbCertEncoded == sizeof(bigCert) - 1,
379 "Expected size %d, got %ld\n", sizeof(bigCert) - 1,
380 context->cbCertEncoded);
381 ok(!memcmp(context->pbCertEncoded, bigCert, context->cbCertEncoded),
382 "Unexpected cert\n");
383 context = CertEnumCertificatesInStore(collection, context);
384 ok(context != NULL, "Expected a valid context\n");
387 ok(context->hCertStore == collection, "Unexpected store\n");
388 ok(context->cbCertEncoded == sizeof(bigCert2) - 1,
389 "Expected size %d, got %ld\n", sizeof(bigCert2) - 1,
390 context->cbCertEncoded);
391 ok(!memcmp(context->pbCertEncoded, bigCert2,
392 context->cbCertEncoded), "Unexpected cert\n");
393 context = CertEnumCertificatesInStore(collection, context);
394 ok(!context, "Unexpected cert\n");
397 /* close store2, and check that the collection is unmodified */
398 CertCloseStore(store2, 0);
399 context = CertEnumCertificatesInStore(collection, NULL);
400 ok(context != NULL, "Expected a valid context\n");
403 ok(context->hCertStore == collection, "Unexpected store\n");
404 ok(context->cbCertEncoded == sizeof(bigCert) - 1,
405 "Expected size %d, got %ld\n", sizeof(bigCert) - 1,
406 context->cbCertEncoded);
407 ok(!memcmp(context->pbCertEncoded, bigCert, context->cbCertEncoded),
408 "Unexpected cert\n");
409 context = CertEnumCertificatesInStore(collection, context);
410 ok(context != NULL, "Expected a valid context\n");
413 ok(context->hCertStore == collection, "Unexpected store\n");
414 ok(context->cbCertEncoded == sizeof(bigCert2) - 1,
415 "Expected size %d, got %ld\n", sizeof(bigCert2) - 1,
416 context->cbCertEncoded);
417 ok(!memcmp(context->pbCertEncoded, bigCert2,
418 context->cbCertEncoded), "Unexpected cert\n");
419 context = CertEnumCertificatesInStore(collection, context);
420 ok(!context, "Unexpected cert\n");
424 /* Adding a collection to a collection is legal */
425 collection2 = CertOpenStore(CERT_STORE_PROV_COLLECTION, 0, 0,
426 CERT_STORE_CREATE_NEW_FLAG, NULL);
427 ret = CertAddStoreToCollection(collection2, collection,
428 CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
429 ok(ret, "CertAddStoreToCollection failed: %08lx\n", GetLastError());
430 /* check the contents of collection2 */
431 context = CertEnumCertificatesInStore(collection2, NULL);
432 ok(context != NULL, "Expected a valid context\n");
435 ok(context->hCertStore == collection2, "Unexpected store\n");
436 ok(context->cbCertEncoded == sizeof(bigCert) - 1,
437 "Expected size %d, got %ld\n", sizeof(bigCert) - 1,
438 context->cbCertEncoded);
439 ok(!memcmp(context->pbCertEncoded, bigCert, context->cbCertEncoded),
440 "Unexpected cert\n");
441 context = CertEnumCertificatesInStore(collection2, context);
442 ok(context != NULL, "Expected a valid context\n");
445 ok(context->hCertStore == collection2, "Unexpected store\n");
446 ok(context->cbCertEncoded == sizeof(bigCert2) - 1,
447 "Expected size %d, got %ld\n", sizeof(bigCert2) - 1,
448 context->cbCertEncoded);
449 ok(!memcmp(context->pbCertEncoded, bigCert2,
450 context->cbCertEncoded), "Unexpected cert\n");
451 context = CertEnumCertificatesInStore(collection2, context);
452 ok(!context, "Unexpected cert\n");
456 /* I'd like to test closing the collection in the middle of enumeration,
457 * but my tests have been inconsistent. The first time calling
458 * CertEnumCertificatesInStore on a closed collection succeeded, while the
459 * second crashed. So anything appears to be fair game.
460 * I'd also like to test removing a store from a collection in the middle
461 * of an enumeration, but my tests in Windows have been inconclusive.
462 * In one scenario it worked. In another scenario, about a third of the
463 * time this leads to "random" crashes elsewhere in the code. This
464 * probably means this is not allowed.
467 CertCloseStore(store1, 0);
468 CertCloseStore(collection, 0);
469 CertCloseStore(collection2, 0);
471 /* Add the same cert to two memory stores, then put them in a collection */
472 store1 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
473 CERT_STORE_CREATE_NEW_FLAG, NULL);
474 ok(store1 != 0, "CertOpenStore failed: %08lx\n", GetLastError());
475 store2 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
476 CERT_STORE_CREATE_NEW_FLAG, NULL);
477 ok(store2 != 0, "CertOpenStore failed: %08lx\n", GetLastError());
479 ret = CertAddEncodedCertificateToStore(store1, X509_ASN_ENCODING,
480 bigCert, sizeof(bigCert) - 1, CERT_STORE_ADD_ALWAYS, NULL);
481 ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\n", GetLastError());
482 ret = CertAddEncodedCertificateToStore(store2, X509_ASN_ENCODING,
483 bigCert, sizeof(bigCert) - 1, CERT_STORE_ADD_ALWAYS, NULL);
484 ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\n", GetLastError());
485 collection = CertOpenStore(CERT_STORE_PROV_COLLECTION, 0, 0,
486 CERT_STORE_CREATE_NEW_FLAG, NULL);
487 ok(collection != 0, "CertOpenStore failed: %08lx\n", GetLastError());
489 ret = CertAddStoreToCollection(collection, store1,
490 CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
491 ok(ret, "CertAddStoreToCollection failed: %08lx\n", GetLastError());
492 ret = CertAddStoreToCollection(collection, store2,
493 CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
494 ok(ret, "CertAddStoreToCollection failed: %08lx\n", GetLastError());
496 /* Check that the collection has two copies of the same cert */
497 context = CertEnumCertificatesInStore(collection, NULL);
498 ok(context != NULL, "Expected a valid context\n");
501 ok(context->hCertStore == collection, "Unexpected store\n");
502 ok(context->cbCertEncoded == sizeof(bigCert) - 1,
503 "Expected size %d, got %ld\n", sizeof(bigCert) - 1,
504 context->cbCertEncoded);
505 ok(!memcmp(context->pbCertEncoded, bigCert, context->cbCertEncoded),
506 "Unexpected cert\n");
507 context = CertEnumCertificatesInStore(collection, context);
508 ok(context != NULL, "Expected a valid context\n");
511 ok(context->hCertStore == collection, "Unexpected store\n");
512 ok(context->cbCertEncoded == sizeof(bigCert) - 1,
513 "Expected size %d, got %ld\n", sizeof(bigCert) - 1,
514 context->cbCertEncoded);
515 ok(!memcmp(context->pbCertEncoded, bigCert, context->cbCertEncoded),
516 "Unexpected cert\n");
517 context = CertEnumCertificatesInStore(collection, context);
518 ok(context == NULL, "Unexpected cert\n");
522 /* The following would check whether I can delete an identical cert, rather
523 * than one enumerated from the store. It crashes, so that means I must
524 * only call CertDeleteCertificateFromStore with contexts enumerated from
526 context = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert,
527 sizeof(bigCert) - 1);
528 ok(context != NULL, "CertCreateCertificateContext failed: %08lx\n",
532 ret = CertDeleteCertificateFromStore(collection, context);
533 printf("ret is %d, GetLastError is %08lx\n", ret, GetLastError());
534 CertFreeCertificateContext(context);
538 /* Now check deleting from the collection. */
539 context = CertEnumCertificatesInStore(collection, NULL);
540 ok(context != NULL, "Expected a valid context\n");
543 CertDeleteCertificateFromStore(context);
544 /* store1 should now be empty */
545 context = CertEnumCertificatesInStore(store1, NULL);
546 ok(!context, "Unexpected cert\n");
547 /* and there should be one certificate in the collection */
548 context = CertEnumCertificatesInStore(collection, NULL);
549 ok(context != NULL, "Expected a valid cert\n");
552 ok(context->hCertStore == collection, "Unexpected store\n");
553 ok(context->cbCertEncoded == sizeof(bigCert) - 1,
554 "Expected size %d, got %ld\n", sizeof(bigCert) - 1,
555 context->cbCertEncoded);
556 ok(!memcmp(context->pbCertEncoded, bigCert, context->cbCertEncoded),
557 "Unexpected cert\n");
559 context = CertEnumCertificatesInStore(collection, context);
560 ok(context == NULL, "Unexpected cert\n");
563 /* Finally, test removing stores from the collection. No return value, so
564 * it's a bit funny to test.
567 CertRemoveStoreFromCollection(NULL, NULL);
569 /* This "succeeds," no crash, no last error set */
570 SetLastError(0xdeadbeef);
571 CertRemoveStoreFromCollection(store2, collection);
572 ok(GetLastError() == 0xdeadbeef,
573 "Didn't expect an error to be set: %08lx\n", GetLastError());
575 /* After removing store2, the collection should be empty */
576 SetLastError(0xdeadbeef);
577 CertRemoveStoreFromCollection(collection, store2);
578 ok(GetLastError() == 0xdeadbeef,
579 "Didn't expect an error to be set: %08lx\n", GetLastError());
580 context = CertEnumCertificatesInStore(collection, NULL);
581 ok(!context, "Unexpected cert\n");
583 CertCloseStore(collection, 0);
584 CertCloseStore(store2, 0);
585 CertCloseStore(store1, 0);
588 /* Looks for the property with ID propID in the buffer buf. Returns a pointer
589 * to its header if found, NULL if not.
591 static const struct CertPropIDHeader *findPropID(const BYTE *buf, DWORD size,
594 const struct CertPropIDHeader *ret = NULL;
597 while (size && !ret && !failed)
599 if (size < sizeof(struct CertPropIDHeader))
603 const struct CertPropIDHeader *hdr =
604 (const struct CertPropIDHeader *)buf;
606 size -= sizeof(struct CertPropIDHeader);
607 buf += sizeof(struct CertPropIDHeader);
610 else if (hdr->propID == propID)
622 typedef DWORD (WINAPI *SHDeleteKeyAFunc)(HKEY, LPCSTR);
624 static void testRegStore(void)
626 static const char tempKey[] = "Software\\Wine\\CryptTemp";
632 store = CertOpenStore(CERT_STORE_PROV_REG, 0, 0, 0, NULL);
633 ok(!store && GetLastError() == ERROR_INVALID_HANDLE,
634 "Expected ERROR_INVALID_HANDLE, got %ld\n", GetLastError());
635 store = CertOpenStore(CERT_STORE_PROV_REG, 0, 0, 0, key);
636 ok(!store && GetLastError() == ERROR_INVALID_HANDLE,
637 "Expected ERROR_INVALID_HANDLE, got %ld\n", GetLastError());
639 /* Opening up any old key works.. */
640 key = HKEY_CURRENT_USER;
641 store = CertOpenStore(CERT_STORE_PROV_REG, 0, 0, 0, key);
642 /* Not sure if this is a bug in DuplicateHandle, marking todo_wine for now
644 todo_wine ok(store != 0, "CertOpenStore failed: %08lx\n", GetLastError());
645 CertCloseStore(store, 0);
647 rc = RegCreateKeyExA(HKEY_CURRENT_USER, tempKey, 0, NULL, 0, KEY_ALL_ACCESS,
649 ok(!rc, "RegCreateKeyExA failed: %ld\n", rc);
655 static const char certificates[] = "Certificates\\";
656 char subKeyName[sizeof(certificates) + 20 * 2 + 1], *ptr;
658 PCCERT_CONTEXT context;
660 store = CertOpenStore(CERT_STORE_PROV_REG, 0, 0, 0, key);
661 ok(store != 0, "CertOpenStore failed: %08lx\n", GetLastError());
662 /* Add a certificate. It isn't persisted right away, since it's only
663 * added to the cache..
665 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
666 bigCert2, sizeof(bigCert2) - 1, CERT_STORE_ADD_ALWAYS, NULL);
667 ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\n",
669 /* so flush the cache to force a commit.. */
670 ret = CertControlStore(store, 0, CERT_STORE_CTRL_COMMIT, NULL);
671 ok(ret, "CertControlStore failed: %08lx\n", GetLastError());
672 /* and check that the expected subkey was written. */
674 ret = CryptHashCertificate(0, 0, 0, bigCert2, sizeof(bigCert2) - 1,
676 ok(ret, "CryptHashCertificate failed: %ld\n", GetLastError());
677 strcpy(subKeyName, certificates);
678 for (i = 0, ptr = subKeyName + sizeof(certificates) - 1; i < size;
680 sprintf(ptr, "%02X", hash[i]);
681 rc = RegCreateKeyExA(key, subKeyName, 0, NULL, 0, KEY_ALL_ACCESS, NULL,
683 ok(!rc, "RegCreateKeyExA failed: %ld\n", rc);
689 RegQueryValueExA(subKey, "Blob", NULL, NULL, NULL, &size);
690 buf = HeapAlloc(GetProcessHeap(), 0, size);
693 rc = RegQueryValueExA(subKey, "Blob", NULL, NULL, buf, &size);
694 ok(!rc, "RegQueryValueExA failed: %ld\n", rc);
697 const struct CertPropIDHeader *hdr;
699 /* Both the hash and the cert should be present */
700 hdr = findPropID(buf, size, CERT_CERT_PROP_ID);
701 ok(hdr != NULL, "Expected to find a cert property\n");
704 ok(hdr->cb == sizeof(bigCert2) - 1,
705 "Unexpected size %ld of cert property, expected %d\n",
706 hdr->cb, sizeof(bigCert2) - 1);
707 ok(!memcmp((BYTE *)hdr + sizeof(*hdr), bigCert2,
708 hdr->cb), "Unexpected cert in cert property\n");
710 hdr = findPropID(buf, size, CERT_HASH_PROP_ID);
711 ok(hdr != NULL, "Expected to find a hash property\n");
714 ok(hdr->cb == sizeof(hash),
715 "Unexpected size %ld of hash property, expected %d\n",
716 hdr->cb, sizeof(hash));
717 ok(!memcmp((BYTE *)hdr + sizeof(*hdr), hash,
718 hdr->cb), "Unexpected hash in cert property\n");
721 HeapFree(GetProcessHeap(), 0, buf);
726 /* Remove the existing context */
727 context = CertEnumCertificatesInStore(store, NULL);
728 ok(context != NULL, "Expected a cert context\n");
731 CertDeleteCertificateFromStore(context);
732 CertFreeCertificateContext(context);
734 ret = CertControlStore(store, 0, CERT_STORE_CTRL_COMMIT, NULL);
735 ok(ret, "CertControlStore failed: %08lx\n", GetLastError());
737 /* Add a serialized cert with a bogus hash directly to the registry */
738 memset(hash, 0, sizeof(hash));
739 strcpy(subKeyName, certificates);
740 for (i = 0, ptr = subKeyName + sizeof(certificates) - 1;
741 i < sizeof(hash); i++, ptr += 2)
742 sprintf(ptr, "%02X", hash[i]);
743 rc = RegCreateKeyExA(key, subKeyName, 0, NULL, 0, KEY_ALL_ACCESS, NULL,
745 ok(!rc, "RegCreateKeyExA failed: %ld\n", rc);
748 BYTE buf[sizeof(struct CertPropIDHeader) * 2 + sizeof(hash) +
749 sizeof(bigCert) - 1], *ptr;
751 struct CertPropIDHeader *hdr;
753 hdr = (struct CertPropIDHeader *)buf;
754 hdr->propID = CERT_HASH_PROP_ID;
756 hdr->cb = sizeof(hash);
757 ptr = buf + sizeof(*hdr);
758 memcpy(ptr, hash, sizeof(hash));
760 hdr = (struct CertPropIDHeader *)ptr;
761 hdr->propID = CERT_CERT_PROP_ID;
763 hdr->cb = sizeof(bigCert) - 1;
765 memcpy(ptr, bigCert, sizeof(bigCert) - 1);
767 rc = RegSetValueExA(subKey, "Blob", 0, REG_BINARY, buf,
769 ok(!rc, "RegSetValueExA failed: %ld\n", rc);
771 ret = CertControlStore(store, 0, CERT_STORE_CTRL_RESYNC, NULL);
772 ok(ret, "CertControlStore failed: %08lx\n", GetLastError());
774 /* Make sure the bogus hash cert gets loaded. */
778 context = CertEnumCertificatesInStore(store, context);
781 } while (context != NULL);
782 ok(certCount == 1, "Expected 1 certificates, got %ld\n", certCount);
787 /* Add another serialized cert directly to the registry, this time
788 * under the correct key name (named with the correct hash value).
791 ret = CryptHashCertificate(0, 0, 0, bigCert2,
792 sizeof(bigCert2) - 1, hash, &size);
793 ok(ret, "CryptHashCertificate failed: %ld\n", GetLastError());
794 strcpy(subKeyName, certificates);
795 for (i = 0, ptr = subKeyName + sizeof(certificates) - 1;
796 i < sizeof(hash); i++, ptr += 2)
797 sprintf(ptr, "%02X", hash[i]);
798 rc = RegCreateKeyExA(key, subKeyName, 0, NULL, 0, KEY_ALL_ACCESS, NULL,
800 ok(!rc, "RegCreateKeyExA failed: %ld\n", rc);
803 BYTE buf[sizeof(struct CertPropIDHeader) * 2 + sizeof(hash) +
804 sizeof(bigCert2) - 1], *ptr;
806 PCCERT_CONTEXT context;
807 struct CertPropIDHeader *hdr;
809 /* First try with a bogus hash... */
810 hdr = (struct CertPropIDHeader *)buf;
811 hdr->propID = CERT_HASH_PROP_ID;
813 hdr->cb = sizeof(hash);
814 ptr = buf + sizeof(*hdr);
815 memset(ptr, 0, sizeof(hash));
817 hdr = (struct CertPropIDHeader *)ptr;
818 hdr->propID = CERT_CERT_PROP_ID;
820 hdr->cb = sizeof(bigCert2) - 1;
822 memcpy(ptr, bigCert2, sizeof(bigCert2) - 1);
824 rc = RegSetValueExA(subKey, "Blob", 0, REG_BINARY, buf,
826 ok(!rc, "RegSetValueExA failed: %ld\n", rc);
828 ret = CertControlStore(store, 0, CERT_STORE_CTRL_RESYNC, NULL);
829 ok(ret, "CertControlStore failed: %08lx\n", GetLastError());
831 /* and make sure just one cert still gets loaded. */
835 context = CertEnumCertificatesInStore(store, context);
838 } while (context != NULL);
839 ok(certCount == 1, "Expected 1 certificates, got %ld\n", certCount);
841 /* Try again with the correct hash... */
842 ptr = buf + sizeof(*hdr);
843 memcpy(ptr, hash, sizeof(hash));
845 rc = RegSetValueExA(subKey, "Blob", 0, REG_BINARY, buf,
847 ok(!rc, "RegSetValueExA failed: %ld\n", rc);
849 ret = CertControlStore(store, 0, CERT_STORE_CTRL_RESYNC, NULL);
850 ok(ret, "CertControlStore failed: %08lx\n", GetLastError());
852 /* and make sure two certs get loaded. */
856 context = CertEnumCertificatesInStore(store, context);
859 } while (context != NULL);
860 ok(certCount == 2, "Expected 2 certificates, got %ld\n", certCount);
864 CertCloseStore(store, 0);
865 /* Is delete allowed on a reg store? */
866 store = CertOpenStore(CERT_STORE_PROV_REG, 0, 0,
867 CERT_STORE_DELETE_FLAG, key);
868 ok(store == NULL, "Expected NULL return from CERT_STORE_DELETE_FLAG\n");
869 ok(GetLastError() == 0, "CertOpenStore failed: %08lx\n",
874 /* The CertOpenStore with CERT_STORE_DELETE_FLAG above will delete the
875 * contents of the key, but not the key itself.
877 rc = RegCreateKeyExA(HKEY_CURRENT_USER, tempKey, 0, NULL, 0, KEY_ALL_ACCESS,
879 ok(!rc, "RegCreateKeyExA failed: %ld\n", rc);
880 ok(disp == REG_OPENED_EXISTING_KEY,
881 "Expected REG_OPENED_EXISTING_KEY, got %ld\n", disp);
885 rc = RegDeleteKeyA(HKEY_CURRENT_USER, tempKey);
886 /* There seems to be a bug in the registry code, not sure if it's a
887 * race condition in the recurse delete key implementation here, or if
888 * it's elsewhere in wine. Marking todo_wine for now.
890 todo_wine ok(!rc, "RegDeleteKeyA failed: %ld\n", rc);
893 HMODULE shlwapi = LoadLibraryA("shlwapi");
895 /* Use shlwapi's SHDeleteKeyA to _really_ blow away the key,
896 * otherwise subsequent tests will fail.
900 SHDeleteKeyAFunc pSHDeleteKeyA =
901 (SHDeleteKeyAFunc)GetProcAddress(shlwapi, "SHDeleteKeyA");
904 pSHDeleteKeyA(HKEY_CURRENT_USER, tempKey);
905 FreeLibrary(shlwapi);
911 static void testCertProperties(void)
913 PCCERT_CONTEXT context = CertCreateCertificateContext(X509_ASN_ENCODING,
914 bigCert, sizeof(bigCert) - 1);
916 ok(context != NULL, "CertCreateCertificateContext failed: %08lx\n",
920 DWORD propID, numProps, access, size;
922 BYTE hash[20] = { 0 }, hashProperty[20];
923 CRYPT_DATA_BLOB blob;
926 propID = CertEnumCertificateContextProperties(NULL, 0);
932 propID = CertEnumCertificateContextProperties(context, propID);
935 } while (propID != 0);
936 ok(numProps == 0, "Expected 0 properties, got %ld\n", numProps);
938 /* Tests with a NULL cert context. Prop ID 0 fails.. */
939 ret = CertSetCertificateContextProperty(NULL, 0, 0, NULL);
940 ok(!ret && GetLastError() ==
941 HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
942 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
944 /* while this just crashes.
945 ret = CertSetCertificateContextProperty(NULL,
946 CERT_KEY_PROV_HANDLE_PROP_ID, 0, NULL);
949 ret = CertSetCertificateContextProperty(context, 0, 0, NULL);
950 ok(!ret && GetLastError() ==
951 HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
952 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
954 /* Can't set the cert property directly, this crashes.
955 ret = CertSetCertificateContextProperty(context,
956 CERT_CERT_PROP_ID, 0, bigCert2);
960 ret = CertGetCertificateContextProperty(context,
961 CERT_ACCESS_STATE_PROP_ID, 0, NULL);
963 size = sizeof(access);
964 ret = CertGetCertificateContextProperty(context,
965 CERT_ACCESS_STATE_PROP_ID, &access, &size);
966 ok(ret, "CertGetCertificateContextProperty failed: %08lx\n",
968 ok(!(access & CERT_ACCESS_STATE_WRITE_PERSIST_FLAG),
969 "Didn't expect a persisted cert\n");
970 /* Trying to set this "read only" property crashes.
971 access |= CERT_ACCESS_STATE_WRITE_PERSIST_FLAG;
972 ret = CertSetCertificateContextProperty(context,
973 CERT_ACCESS_STATE_PROP_ID, 0, &access);
976 /* Can I set the hash to an invalid hash? */
978 blob.cbData = sizeof(hash);
979 ret = CertSetCertificateContextProperty(context, CERT_HASH_PROP_ID, 0,
981 ok(ret, "CertSetCertificateContextProperty failed: %08lx\n",
983 size = sizeof(hashProperty);
984 ret = CertGetCertificateContextProperty(context, CERT_HASH_PROP_ID,
985 hashProperty, &size);
986 ok(!memcmp(hashProperty, hash, sizeof(hash)), "Unexpected hash\n");
987 /* Delete the (bogus) hash, and get the real one */
988 ret = CertSetCertificateContextProperty(context, CERT_HASH_PROP_ID, 0,
990 ok(ret, "CertSetCertificateContextProperty failed: %08lx\n",
993 ret = CryptHashCertificate(0, 0, 0, bigCert, sizeof(bigCert) - 1,
995 ok(ret, "CryptHashCertificate failed: %08lx\n", GetLastError());
996 ret = CertGetCertificateContextProperty(context, CERT_HASH_PROP_ID,
997 hashProperty, &size);
998 ok(ret, "CertGetCertificateContextProperty failed: %08lx\n",
1000 ok(!memcmp(hash, hashProperty, sizeof(hash)), "Unexpected hash\n");
1002 /* Now that the hash property is set, we should get one property when
1008 propID = CertEnumCertificateContextProperties(context, propID);
1011 } while (propID != 0);
1012 ok(numProps == 1, "Expected 1 properties, got %ld\n", numProps);
1014 CertFreeCertificateContext(context);
1018 static void testAddSerialized(void)
1022 BYTE buf[sizeof(struct CertPropIDHeader) * 2 + 20 + sizeof(bigCert) - 1] =
1025 struct CertPropIDHeader *hdr;
1026 PCCERT_CONTEXT context;
1028 ret = CertAddSerializedElementToStore(0, NULL, 0, 0, 0, 0, NULL, NULL);
1029 ok(!ret && GetLastError() == ERROR_END_OF_MEDIA,
1030 "Expected ERROR_END_OF_MEDIA, got %08lx\n", GetLastError());
1032 store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
1033 CERT_STORE_CREATE_NEW_FLAG, NULL);
1034 ok(store != 0, "CertOpenStore failed: %08lx\n", GetLastError());
1036 ret = CertAddSerializedElementToStore(store, NULL, 0, 0, 0, 0, NULL, NULL);
1037 ok(!ret && GetLastError() == ERROR_END_OF_MEDIA,
1038 "Expected ERROR_END_OF_MEDIA, got %08lx\n", GetLastError());
1040 /* Test with an empty property */
1041 hdr = (struct CertPropIDHeader *)buf;
1042 hdr->propID = CERT_CERT_PROP_ID;
1045 ret = CertAddSerializedElementToStore(store, buf, sizeof(buf), 0, 0, 0,
1047 ok(!ret && GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
1048 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
1050 /* Test with a bad size in property header */
1051 hdr->cb = sizeof(bigCert) - 2;
1052 memcpy(buf + sizeof(struct CertPropIDHeader), bigCert, sizeof(bigCert) - 1);
1053 ret = CertAddSerializedElementToStore(store, buf, sizeof(buf), 0, 0, 0,
1055 ok(!ret && GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
1056 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
1058 ret = CertAddSerializedElementToStore(store, buf,
1059 sizeof(struct CertPropIDHeader) + sizeof(bigCert) - 1, 0, 0, 0, NULL,
1061 ok(!ret && GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
1062 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
1064 ret = CertAddSerializedElementToStore(store, buf,
1065 sizeof(struct CertPropIDHeader) + sizeof(bigCert) - 1, CERT_STORE_ADD_NEW,
1067 ok(!ret && GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
1068 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
1070 /* Kosher size in property header, but no context type */
1071 hdr->cb = sizeof(bigCert) - 1;
1072 ret = CertAddSerializedElementToStore(store, buf, sizeof(buf), 0, 0, 0,
1074 ok(!ret && GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
1075 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
1077 ret = CertAddSerializedElementToStore(store, buf,
1078 sizeof(struct CertPropIDHeader) + sizeof(bigCert) - 1, 0, 0, 0, NULL,
1080 ok(!ret && GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
1081 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
1083 ret = CertAddSerializedElementToStore(store, buf,
1084 sizeof(struct CertPropIDHeader) + sizeof(bigCert) - 1, CERT_STORE_ADD_NEW,
1086 ok(!ret && GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
1087 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
1089 /* With a bad context type */
1090 ret = CertAddSerializedElementToStore(store, buf, sizeof(buf), 0, 0,
1091 CERT_STORE_CRL_CONTEXT_FLAG, NULL, NULL);
1092 ok(!ret && GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
1093 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
1095 ret = CertAddSerializedElementToStore(store, buf,
1096 sizeof(struct CertPropIDHeader) + sizeof(bigCert) - 1, 0, 0,
1097 CERT_STORE_CRL_CONTEXT_FLAG, NULL, NULL);
1098 ok(!ret && GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
1099 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
1101 ret = CertAddSerializedElementToStore(store, buf,
1102 sizeof(struct CertPropIDHeader) + sizeof(bigCert) - 1, CERT_STORE_ADD_NEW,
1103 0, CERT_STORE_CRL_CONTEXT_FLAG, NULL, NULL);
1104 ok(!ret && GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
1105 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
1107 /* Bad unknown field, good type */
1109 ret = CertAddSerializedElementToStore(store, buf, sizeof(buf), 0, 0,
1110 CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL, NULL);
1111 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
1112 "Expected ERROR_FILE_NOT_FOUND got %08lx\n", GetLastError());
1113 ret = CertAddSerializedElementToStore(store, buf,
1114 sizeof(struct CertPropIDHeader) + sizeof(bigCert) - 1, 0, 0,
1115 CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL, NULL);
1116 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
1117 "Expected ERROR_FILE_NOT_FOUND got %08lx\n", GetLastError());
1118 ret = CertAddSerializedElementToStore(store, buf,
1119 sizeof(struct CertPropIDHeader) + sizeof(bigCert) - 1, CERT_STORE_ADD_NEW,
1120 0, CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL, NULL);
1121 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
1122 "Expected ERROR_FILE_NOT_FOUND got %08lx\n", GetLastError());
1123 /* Most everything okay, but bad add disposition */
1126 ret = CertAddSerializedElementToStore(store, buf, sizeof(buf), 0, 0,
1127 CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL, NULL);
1129 ret = CertAddSerializedElementToStore(store, buf,
1130 sizeof(struct CertPropIDHeader) + sizeof(bigCert) - 1, 0, 0,
1131 CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL, NULL);
1133 /* Everything okay, but buffer's too big */
1134 ret = CertAddSerializedElementToStore(store, buf, sizeof(buf),
1135 CERT_STORE_ADD_NEW, 0, CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL, NULL);
1136 ok(ret, "CertAddSerializedElementToStore failed: %08lx\n", GetLastError());
1137 /* Everything okay, check it's not re-added */
1138 ret = CertAddSerializedElementToStore(store, buf,
1139 sizeof(struct CertPropIDHeader) + sizeof(bigCert) - 1, CERT_STORE_ADD_NEW,
1140 0, CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL, NULL);
1141 ok(!ret && GetLastError() == CRYPT_E_EXISTS,
1142 "Expected CRYPT_E_EXISTS, got %08lx\n", GetLastError());
1144 context = CertEnumCertificatesInStore(store, NULL);
1145 ok(context != NULL, "Expected a cert\n");
1147 CertDeleteCertificateFromStore(context);
1149 /* Try adding with a bogus hash. Oddly enough, it succeeds, and the hash,
1150 * when queried, is the real hash rather than the bogus hash.
1152 hdr = (struct CertPropIDHeader *)(buf + sizeof(struct CertPropIDHeader) +
1153 sizeof(bigCert) - 1);
1154 hdr->propID = CERT_HASH_PROP_ID;
1156 hdr->cb = sizeof(hash);
1157 memset(hash, 0xc, sizeof(hash));
1158 memcpy((LPBYTE)hdr + sizeof(struct CertPropIDHeader), hash, sizeof(hash));
1159 ret = CertAddSerializedElementToStore(store, buf, sizeof(buf),
1160 CERT_STORE_ADD_NEW, 0, CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL,
1161 (const void **)&context);
1162 ok(ret, "CertAddSerializedElementToStore failed: %08lx\n", GetLastError());
1165 BYTE hashVal[20], realHash[20];
1166 DWORD size = sizeof(hashVal);
1168 ret = CryptHashCertificate(0, 0, 0, bigCert, sizeof(bigCert) - 1,
1170 ok(ret, "CryptHashCertificate failed: %08lx\n", GetLastError());
1171 ret = CertGetCertificateContextProperty(context, CERT_HASH_PROP_ID,
1173 ok(ret, "CertGetCertificateContextProperty failed: %08lx\n",
1175 ok(!memcmp(hashVal, realHash, size), "Unexpected hash\n");
1178 CertCloseStore(store, 0);
1183 testCryptHashCert();
1185 /* various combinations of CertOpenStore */
1187 testCollectionStore();
1190 testCertProperties();
1191 testAddSerialized();