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,
113 static const BYTE signedCRL
[] = { 0x30, 0x45, 0x30, 0x2c, 0x30, 0x02, 0x06,
114 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
115 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18, 0x0f,
116 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
117 0x30, 0x5a, 0x30, 0x02, 0x06, 0x00, 0x03, 0x11, 0x00, 0x0f, 0x0e, 0x0d, 0x0c,
118 0x0b, 0x0a, 0x09, 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00 };
120 static void testMemStore(void)
122 HCERTSTORE store1
, store2
;
123 PCCERT_CONTEXT context
;
127 store1
= CertOpenStore(0, 0, 0, 0, NULL
);
128 ok(!store1
&& GetLastError() == ERROR_FILE_NOT_FOUND
,
129 "Expected ERROR_FILE_NOT_FOUND, got %ld\n", GetLastError());
131 store1
= CertOpenStore(CERT_STORE_PROV_MEMORY
, 0, 0,
132 CERT_STORE_DELETE_FLAG
, NULL
);
133 ok(!store1
&& GetLastError() == ERROR_CALL_NOT_IMPLEMENTED
,
134 "Expected ERROR_CALL_NOT_IMPLEMENTED, got %ld\n", GetLastError());
137 store1
= CertOpenStore(CERT_STORE_PROV_MEMORY
, 0, 0,
138 CERT_STORE_CREATE_NEW_FLAG
, NULL
);
139 ok(store1
!= NULL
, "CertOpenStore failed: %ld\n", GetLastError());
140 /* open existing doesn't */
141 store2
= CertOpenStore(CERT_STORE_PROV_MEMORY
, 0, 0,
142 CERT_STORE_OPEN_EXISTING_FLAG
, NULL
);
143 ok(store2
!= NULL
, "CertOpenStore failed: %ld\n", GetLastError());
144 ok(store1
!= store2
, "Expected different stores\n");
146 /* add a bogus (empty) cert */
148 ret
= CertAddEncodedCertificateToStore(store1
, X509_ASN_ENCODING
, emptyCert
,
149 sizeof(emptyCert
), CERT_STORE_ADD_ALWAYS
, &context
);
150 /* Windows returns CRYPT_E_ASN1_EOD, but accept CRYPT_E_ASN1_CORRUPT as
151 * well (because matching errors is tough in this case)
153 ok(!ret
&& (GetLastError() == CRYPT_E_ASN1_EOD
|| GetLastError() ==
154 CRYPT_E_ASN1_CORRUPT
),
155 "Expected CRYPT_E_ASN1_EOD or CRYPT_E_ASN1_CORRUPT, got %08lx\n",
157 /* add a "signed" cert--the signature isn't a real signature, so this adds
158 * without any check of the signature's validity
160 ret
= CertAddEncodedCertificateToStore(store1
, X509_ASN_ENCODING
,
161 signedBigCert
, sizeof(signedBigCert
), CERT_STORE_ADD_ALWAYS
, &context
);
162 ok(ret
, "CertAddEncodedCertificateToStore failed: %08lx\n", GetLastError());
163 ok(context
!= NULL
, "Expected a valid cert context\n");
166 ok(context
->cbCertEncoded
== sizeof(signedBigCert
),
167 "Expected cert of %d bytes, got %ld\n", sizeof(signedBigCert
),
168 context
->cbCertEncoded
);
169 ok(!memcmp(context
->pbCertEncoded
, signedBigCert
,
170 sizeof(signedBigCert
)), "Unexpected encoded cert in context\n");
171 /* remove it, the rest of the tests will work on an unsigned cert */
172 ret
= CertDeleteCertificateFromStore(context
);
173 ok(ret
, "CertDeleteCertificateFromStore failed: %08lx\n",
176 /* try adding a "signed" CRL as a cert */
177 ret
= CertAddEncodedCertificateToStore(store1
, X509_ASN_ENCODING
,
178 signedCRL
, sizeof(signedCRL
), CERT_STORE_ADD_ALWAYS
, &context
);
179 ok(!ret
&& (GetLastError() == CRYPT_E_ASN1_BADTAG
|| GetLastError() ==
180 CRYPT_E_ASN1_CORRUPT
),
181 "Expected CRYPT_E_ASN1_BADTAG or CRYPT_E_ASN1_CORRUPT, got %08lx\n",
183 /* add a cert to store1 */
184 ret
= CertAddEncodedCertificateToStore(store1
, X509_ASN_ENCODING
, bigCert
,
185 sizeof(bigCert
) - 1, CERT_STORE_ADD_ALWAYS
, &context
);
186 ok(ret
, "CertAddEncodedCertificateToStore failed: %08lx\n", GetLastError());
187 ok(context
!= NULL
, "Expected a valid cert context\n");
193 ok(context
->cbCertEncoded
== sizeof(bigCert
) - 1,
194 "Expected cert of %d bytes, got %ld\n", sizeof(bigCert
) - 1,
195 context
->cbCertEncoded
);
196 ok(!memcmp(context
->pbCertEncoded
, bigCert
, sizeof(bigCert
) - 1),
197 "Unexpected encoded cert in context\n");
198 ok(context
->hCertStore
== store1
, "Unexpected store\n");
200 /* check serializing this element */
202 ret = CertSerializeCertificateStoreElement(NULL, 0, NULL, NULL);
203 ret = CertSerializeCertificateStoreElement(context, 0, NULL, NULL);
204 ret = CertSerializeCertificateStoreElement(NULL, 0, NULL, &size);
206 /* apparently flags are ignored */
207 ret
= CertSerializeCertificateStoreElement(context
, 1, NULL
, &size
);
208 ok(ret
, "CertSerializeCertificateStoreElement failed: %08lx\n",
210 buf
= HeapAlloc(GetProcessHeap(), 0, size
);
213 ret
= CertSerializeCertificateStoreElement(context
, 0, buf
, &size
);
214 ok(size
== sizeof(serializedCert
), "Expected size %d, got %ld\n",
215 sizeof(serializedCert
), size
);
216 ok(!memcmp(serializedCert
, buf
, size
),
217 "Unexpected serialized cert\n");
218 HeapFree(GetProcessHeap(), 0, buf
);
221 ret
= CertFreeCertificateContext(context
);
222 ok(ret
, "CertFreeCertificateContext failed: %08lx\n", GetLastError());
224 /* verify the cert's in store1 */
225 context
= CertEnumCertificatesInStore(store1
, NULL
);
226 ok(context
!= NULL
, "Expected a valid context\n");
227 context
= CertEnumCertificatesInStore(store1
, context
);
228 ok(!context
&& GetLastError() == CRYPT_E_NOT_FOUND
,
229 "Expected CRYPT_E_NOT_FOUND, got %08lx\n", GetLastError());
230 /* verify store2 (the "open existing" mem store) is still empty */
231 context
= CertEnumCertificatesInStore(store2
, NULL
);
232 ok(!context
, "Expected an empty store\n");
233 /* delete the cert from store1, and check it's empty */
234 context
= CertEnumCertificatesInStore(store1
, NULL
);
237 /* Deleting a bitwise copy crashes with an access to an uninitialized
238 * pointer, so a cert context has some special data out there in memory
241 memcpy(©, context, sizeof(copy));
242 ret = CertDeleteCertificateFromStore(©);
244 PCCERT_CONTEXT copy
= CertDuplicateCertificateContext(context
);
246 ok(copy
!= NULL
, "CertDuplicateCertificateContext failed: %08lx\n",
248 ret
= CertDeleteCertificateFromStore(context
);
249 ok(ret
, "CertDeleteCertificateFromStore failed: %08lx\n",
251 /* try deleting a copy */
252 ret
= CertDeleteCertificateFromStore(copy
);
253 ok(ret
, "CertDeleteCertificateFromStore failed: %08lx\n",
255 /* check that the store is empty */
256 context
= CertEnumCertificatesInStore(store1
, NULL
);
257 ok(!context
, "Expected an empty store\n");
260 /* close an empty store */
261 ret
= CertCloseStore(NULL
, 0);
262 ok(ret
, "CertCloseStore failed: %ld\n", GetLastError());
263 ret
= CertCloseStore(store1
, 0);
264 ok(ret
, "CertCloseStore failed: %ld\n", GetLastError());
265 ret
= CertCloseStore(store2
, 0);
266 ok(ret
, "CertCloseStore failed: %ld\n", GetLastError());
268 /* This seems nonsensical, but you can open a read-only mem store, only
271 store1
= CertOpenStore(CERT_STORE_PROV_MEMORY
, 0, 0,
272 CERT_STORE_READONLY_FLAG
, NULL
);
273 ok(store1
!= NULL
, "CertOpenStore failed: %ld\n", GetLastError());
274 /* yep, this succeeds */
275 ret
= CertAddEncodedCertificateToStore(store1
, X509_ASN_ENCODING
, bigCert
,
276 sizeof(bigCert
) - 1, CERT_STORE_ADD_ALWAYS
, &context
);
277 ok(ret
, "CertAddEncodedCertificateToStore failed: %08lx\n", GetLastError());
278 ok(context
!= NULL
, "Expected a valid cert context\n");
281 ok(context
->cbCertEncoded
== sizeof(bigCert
) - 1,
282 "Expected cert of %d bytes, got %ld\n", sizeof(bigCert
) - 1,
283 context
->cbCertEncoded
);
284 ok(!memcmp(context
->pbCertEncoded
, bigCert
, sizeof(bigCert
) - 1),
285 "Unexpected encoded cert in context\n");
286 ok(context
->hCertStore
== store1
, "Unexpected store\n");
287 ret
= CertDeleteCertificateFromStore(context
);
288 ok(ret
, "CertDeleteCertificateFromStore failed: %08lx\n",
291 CertCloseStore(store1
, 0);
294 static const BYTE bigCert2
[] = "\x30\x7a\x02\x01\x01\x30\x02\x06\x00"
295 "\x30\x15\x31\x13\x30\x11\x06\x03\x55\x04\x03\x13\x0a\x41\x6c\x65\x78\x20\x4c"
296 "\x61\x6e\x67\x00\x30\x22\x18\x0f\x31\x36\x30\x31\x30\x31\x30\x31\x30\x30\x30"
297 "\x30\x30\x30\x5a\x18\x0f\x31\x36\x30\x31\x30\x31\x30\x31\x30\x30\x30\x30\x30"
298 "\x30\x5a\x30\x15\x31\x13\x30\x11\x06\x03\x55\x04\x03\x13\x0a\x41\x6c\x65\x78"
299 "\x20\x4c\x61\x6e\x67\x00\x30\x07\x30\x02\x06\x00\x03\x01\x00\xa3\x16\x30\x14"
300 "\x30\x12\x06\x03\x55\x1d\x13\x01\x01\xff\x04\x08\x30\x06\x01\x01\xff\x02\x01"
303 static void testCollectionStore(void)
305 HCERTSTORE store1
, store2
, collection
, collection2
;
306 PCCERT_CONTEXT context
;
309 collection
= CertOpenStore(CERT_STORE_PROV_COLLECTION
, 0, 0,
310 CERT_STORE_CREATE_NEW_FLAG
, NULL
);
312 /* Try adding a cert to any empty collection */
313 ret
= CertAddEncodedCertificateToStore(collection
, X509_ASN_ENCODING
,
314 bigCert
, sizeof(bigCert
) - 1, CERT_STORE_ADD_ALWAYS
, NULL
);
315 ok(!ret
&& GetLastError() == HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED
),
316 "Expected HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED), got %08lx\n",
319 /* Create and add a cert to a memory store */
320 store1
= CertOpenStore(CERT_STORE_PROV_MEMORY
, 0, 0,
321 CERT_STORE_CREATE_NEW_FLAG
, NULL
);
322 ret
= CertAddEncodedCertificateToStore(store1
, X509_ASN_ENCODING
,
323 bigCert
, sizeof(bigCert
) - 1, CERT_STORE_ADD_ALWAYS
, NULL
);
324 ok(ret
, "CertAddEncodedCertificateToStore failed: %08lx\n", GetLastError());
325 /* Add the memory store to the collection, without allowing adding */
326 ret
= CertAddStoreToCollection(collection
, store1
, 0, 0);
327 ok(ret
, "CertAddStoreToCollection failed: %08lx\n", GetLastError());
328 /* Verify the cert is in the collection */
329 context
= CertEnumCertificatesInStore(collection
, NULL
);
330 ok(context
!= NULL
, "Expected a valid context\n");
333 ok(context
->hCertStore
== collection
, "Unexpected store\n");
334 CertFreeCertificateContext(context
);
336 /* Check that adding to the collection isn't allowed */
337 ret
= CertAddEncodedCertificateToStore(collection
, X509_ASN_ENCODING
,
338 bigCert2
, sizeof(bigCert2
) - 1, CERT_STORE_ADD_ALWAYS
, NULL
);
339 ok(!ret
&& GetLastError() == HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED
),
340 "Expected HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED), got %08lx\n",
343 /* Create a new memory store */
344 store2
= CertOpenStore(CERT_STORE_PROV_MEMORY
, 0, 0,
345 CERT_STORE_CREATE_NEW_FLAG
, NULL
);
346 /* Try adding a store to a non-collection store */
347 ret
= CertAddStoreToCollection(store1
, store2
,
348 CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG
, 0);
349 ok(!ret
&& GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER
),
350 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
352 /* Try adding some bogus stores */
353 /* This crashes in Windows
354 ret = CertAddStoreToCollection(0, store2,
355 CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
357 /* This "succeeds"... */
358 ret
= CertAddStoreToCollection(collection
, 0,
359 CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG
, 0);
360 ok(ret
, "CertAddStoreToCollection failed: %08lx\n", GetLastError());
361 /* while this crashes.
362 ret = CertAddStoreToCollection(collection, 1,
363 CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
366 /* Add it to the collection, this time allowing adding */
367 ret
= CertAddStoreToCollection(collection
, store2
,
368 CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG
, 0);
369 ok(ret
, "CertAddStoreToCollection failed: %08lx\n", GetLastError());
370 /* Check that adding to the collection is allowed */
371 ret
= CertAddEncodedCertificateToStore(collection
, X509_ASN_ENCODING
,
372 bigCert2
, sizeof(bigCert2
) - 1, CERT_STORE_ADD_ALWAYS
, NULL
);
373 ok(ret
, "CertAddEncodedCertificateToStore failed: %08lx\n", GetLastError());
374 /* Now check that it was actually added to store2 */
375 context
= CertEnumCertificatesInStore(store2
, NULL
);
376 ok(context
!= NULL
, "Expected a valid context\n");
379 ok(context
->hCertStore
== store2
, "Unexpected store\n");
380 CertFreeCertificateContext(context
);
382 /* Check that the collection has both bigCert and bigCert2. bigCert comes
383 * first because store1 was added first.
385 context
= CertEnumCertificatesInStore(collection
, NULL
);
386 ok(context
!= NULL
, "Expected a valid context\n");
389 ok(context
->hCertStore
== collection
, "Unexpected store\n");
390 ok(context
->cbCertEncoded
== sizeof(bigCert
) - 1,
391 "Expected size %d, got %ld\n", sizeof(bigCert
) - 1,
392 context
->cbCertEncoded
);
393 ok(!memcmp(context
->pbCertEncoded
, bigCert
, context
->cbCertEncoded
),
394 "Unexpected cert\n");
395 context
= CertEnumCertificatesInStore(collection
, context
);
396 ok(context
!= NULL
, "Expected a valid context\n");
399 ok(context
->hCertStore
== collection
, "Unexpected store\n");
400 ok(context
->cbCertEncoded
== sizeof(bigCert2
) - 1,
401 "Expected size %d, got %ld\n", sizeof(bigCert2
) - 1,
402 context
->cbCertEncoded
);
403 ok(!memcmp(context
->pbCertEncoded
, bigCert2
,
404 context
->cbCertEncoded
), "Unexpected cert\n");
405 context
= CertEnumCertificatesInStore(collection
, context
);
406 ok(!context
, "Unexpected cert\n");
409 /* close store2, and check that the collection is unmodified */
410 CertCloseStore(store2
, 0);
411 context
= CertEnumCertificatesInStore(collection
, NULL
);
412 ok(context
!= NULL
, "Expected a valid context\n");
415 ok(context
->hCertStore
== collection
, "Unexpected store\n");
416 ok(context
->cbCertEncoded
== sizeof(bigCert
) - 1,
417 "Expected size %d, got %ld\n", sizeof(bigCert
) - 1,
418 context
->cbCertEncoded
);
419 ok(!memcmp(context
->pbCertEncoded
, bigCert
, context
->cbCertEncoded
),
420 "Unexpected cert\n");
421 context
= CertEnumCertificatesInStore(collection
, context
);
422 ok(context
!= NULL
, "Expected a valid context\n");
425 ok(context
->hCertStore
== collection
, "Unexpected store\n");
426 ok(context
->cbCertEncoded
== sizeof(bigCert2
) - 1,
427 "Expected size %d, got %ld\n", sizeof(bigCert2
) - 1,
428 context
->cbCertEncoded
);
429 ok(!memcmp(context
->pbCertEncoded
, bigCert2
,
430 context
->cbCertEncoded
), "Unexpected cert\n");
431 context
= CertEnumCertificatesInStore(collection
, context
);
432 ok(!context
, "Unexpected cert\n");
436 /* Adding a collection to a collection is legal */
437 collection2
= CertOpenStore(CERT_STORE_PROV_COLLECTION
, 0, 0,
438 CERT_STORE_CREATE_NEW_FLAG
, NULL
);
439 ret
= CertAddStoreToCollection(collection2
, collection
,
440 CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG
, 0);
441 ok(ret
, "CertAddStoreToCollection failed: %08lx\n", GetLastError());
442 /* check the contents of collection2 */
443 context
= CertEnumCertificatesInStore(collection2
, NULL
);
444 ok(context
!= NULL
, "Expected a valid context\n");
447 ok(context
->hCertStore
== collection2
, "Unexpected store\n");
448 ok(context
->cbCertEncoded
== sizeof(bigCert
) - 1,
449 "Expected size %d, got %ld\n", sizeof(bigCert
) - 1,
450 context
->cbCertEncoded
);
451 ok(!memcmp(context
->pbCertEncoded
, bigCert
, context
->cbCertEncoded
),
452 "Unexpected cert\n");
453 context
= CertEnumCertificatesInStore(collection2
, context
);
454 ok(context
!= NULL
, "Expected a valid context\n");
457 ok(context
->hCertStore
== collection2
, "Unexpected store\n");
458 ok(context
->cbCertEncoded
== sizeof(bigCert2
) - 1,
459 "Expected size %d, got %ld\n", sizeof(bigCert2
) - 1,
460 context
->cbCertEncoded
);
461 ok(!memcmp(context
->pbCertEncoded
, bigCert2
,
462 context
->cbCertEncoded
), "Unexpected cert\n");
463 context
= CertEnumCertificatesInStore(collection2
, context
);
464 ok(!context
, "Unexpected cert\n");
468 /* I'd like to test closing the collection in the middle of enumeration,
469 * but my tests have been inconsistent. The first time calling
470 * CertEnumCertificatesInStore on a closed collection succeeded, while the
471 * second crashed. So anything appears to be fair game.
472 * I'd also like to test removing a store from a collection in the middle
473 * of an enumeration, but my tests in Windows have been inconclusive.
474 * In one scenario it worked. In another scenario, about a third of the
475 * time this leads to "random" crashes elsewhere in the code. This
476 * probably means this is not allowed.
479 CertCloseStore(store1
, 0);
480 CertCloseStore(collection
, 0);
481 CertCloseStore(collection2
, 0);
483 /* Add the same cert to two memory stores, then put them in a collection */
484 store1
= CertOpenStore(CERT_STORE_PROV_MEMORY
, 0, 0,
485 CERT_STORE_CREATE_NEW_FLAG
, NULL
);
486 ok(store1
!= 0, "CertOpenStore failed: %08lx\n", GetLastError());
487 store2
= CertOpenStore(CERT_STORE_PROV_MEMORY
, 0, 0,
488 CERT_STORE_CREATE_NEW_FLAG
, NULL
);
489 ok(store2
!= 0, "CertOpenStore failed: %08lx\n", GetLastError());
491 ret
= CertAddEncodedCertificateToStore(store1
, X509_ASN_ENCODING
,
492 bigCert
, sizeof(bigCert
) - 1, CERT_STORE_ADD_ALWAYS
, NULL
);
493 ok(ret
, "CertAddEncodedCertificateToStore failed: %08lx\n", GetLastError());
494 ret
= CertAddEncodedCertificateToStore(store2
, X509_ASN_ENCODING
,
495 bigCert
, sizeof(bigCert
) - 1, CERT_STORE_ADD_ALWAYS
, NULL
);
496 ok(ret
, "CertAddEncodedCertificateToStore failed: %08lx\n", GetLastError());
497 collection
= CertOpenStore(CERT_STORE_PROV_COLLECTION
, 0, 0,
498 CERT_STORE_CREATE_NEW_FLAG
, NULL
);
499 ok(collection
!= 0, "CertOpenStore failed: %08lx\n", GetLastError());
501 ret
= CertAddStoreToCollection(collection
, store1
,
502 CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG
, 0);
503 ok(ret
, "CertAddStoreToCollection failed: %08lx\n", GetLastError());
504 ret
= CertAddStoreToCollection(collection
, store2
,
505 CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG
, 0);
506 ok(ret
, "CertAddStoreToCollection failed: %08lx\n", GetLastError());
508 /* Check that the collection has two copies of the same cert */
509 context
= CertEnumCertificatesInStore(collection
, NULL
);
510 ok(context
!= NULL
, "Expected a valid context\n");
513 ok(context
->hCertStore
== collection
, "Unexpected store\n");
514 ok(context
->cbCertEncoded
== sizeof(bigCert
) - 1,
515 "Expected size %d, got %ld\n", sizeof(bigCert
) - 1,
516 context
->cbCertEncoded
);
517 ok(!memcmp(context
->pbCertEncoded
, bigCert
, context
->cbCertEncoded
),
518 "Unexpected cert\n");
519 context
= CertEnumCertificatesInStore(collection
, context
);
520 ok(context
!= NULL
, "Expected a valid context\n");
523 ok(context
->hCertStore
== collection
, "Unexpected store\n");
524 ok(context
->cbCertEncoded
== sizeof(bigCert
) - 1,
525 "Expected size %d, got %ld\n", sizeof(bigCert
) - 1,
526 context
->cbCertEncoded
);
527 ok(!memcmp(context
->pbCertEncoded
, bigCert
, context
->cbCertEncoded
),
528 "Unexpected cert\n");
529 context
= CertEnumCertificatesInStore(collection
, context
);
530 ok(context
== NULL
, "Unexpected cert\n");
534 /* The following would check whether I can delete an identical cert, rather
535 * than one enumerated from the store. It crashes, so that means I must
536 * only call CertDeleteCertificateFromStore with contexts enumerated from
538 context = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert,
539 sizeof(bigCert) - 1);
540 ok(context != NULL, "CertCreateCertificateContext failed: %08lx\n",
544 ret = CertDeleteCertificateFromStore(collection, context);
545 printf("ret is %d, GetLastError is %08lx\n", ret, GetLastError());
546 CertFreeCertificateContext(context);
550 /* Now check deleting from the collection. */
551 context
= CertEnumCertificatesInStore(collection
, NULL
);
552 ok(context
!= NULL
, "Expected a valid context\n");
555 CertDeleteCertificateFromStore(context
);
556 /* store1 should now be empty */
557 context
= CertEnumCertificatesInStore(store1
, NULL
);
558 ok(!context
, "Unexpected cert\n");
559 /* and there should be one certificate in the collection */
560 context
= CertEnumCertificatesInStore(collection
, NULL
);
561 ok(context
!= NULL
, "Expected a valid cert\n");
564 ok(context
->hCertStore
== collection
, "Unexpected store\n");
565 ok(context
->cbCertEncoded
== sizeof(bigCert
) - 1,
566 "Expected size %d, got %ld\n", sizeof(bigCert
) - 1,
567 context
->cbCertEncoded
);
568 ok(!memcmp(context
->pbCertEncoded
, bigCert
, context
->cbCertEncoded
),
569 "Unexpected cert\n");
571 context
= CertEnumCertificatesInStore(collection
, context
);
572 ok(context
== NULL
, "Unexpected cert\n");
575 /* Finally, test removing stores from the collection. No return value, so
576 * it's a bit funny to test.
579 CertRemoveStoreFromCollection(NULL, NULL);
581 /* This "succeeds," no crash, no last error set */
582 SetLastError(0xdeadbeef);
583 CertRemoveStoreFromCollection(store2
, collection
);
584 ok(GetLastError() == 0xdeadbeef,
585 "Didn't expect an error to be set: %08lx\n", GetLastError());
587 /* After removing store2, the collection should be empty */
588 SetLastError(0xdeadbeef);
589 CertRemoveStoreFromCollection(collection
, store2
);
590 ok(GetLastError() == 0xdeadbeef,
591 "Didn't expect an error to be set: %08lx\n", GetLastError());
592 context
= CertEnumCertificatesInStore(collection
, NULL
);
593 ok(!context
, "Unexpected cert\n");
595 CertCloseStore(collection
, 0);
596 CertCloseStore(store2
, 0);
597 CertCloseStore(store1
, 0);
600 /* Looks for the property with ID propID in the buffer buf. Returns a pointer
601 * to its header if found, NULL if not.
603 static const struct CertPropIDHeader
*findPropID(const BYTE
*buf
, DWORD size
,
606 const struct CertPropIDHeader
*ret
= NULL
;
609 while (size
&& !ret
&& !failed
)
611 if (size
< sizeof(struct CertPropIDHeader
))
615 const struct CertPropIDHeader
*hdr
=
616 (const struct CertPropIDHeader
*)buf
;
618 size
-= sizeof(struct CertPropIDHeader
);
619 buf
+= sizeof(struct CertPropIDHeader
);
622 else if (hdr
->propID
== propID
)
634 typedef DWORD (WINAPI
*SHDeleteKeyAFunc
)(HKEY
, LPCSTR
);
636 static void testRegStore(void)
638 static const char tempKey
[] = "Software\\Wine\\CryptTemp";
644 store
= CertOpenStore(CERT_STORE_PROV_REG
, 0, 0, 0, NULL
);
645 ok(!store
&& GetLastError() == ERROR_INVALID_HANDLE
,
646 "Expected ERROR_INVALID_HANDLE, got %ld\n", GetLastError());
647 store
= CertOpenStore(CERT_STORE_PROV_REG
, 0, 0, 0, key
);
648 ok(!store
&& GetLastError() == ERROR_INVALID_HANDLE
,
649 "Expected ERROR_INVALID_HANDLE, got %ld\n", GetLastError());
651 /* Opening up any old key works.. */
652 key
= HKEY_CURRENT_USER
;
653 store
= CertOpenStore(CERT_STORE_PROV_REG
, 0, 0, 0, key
);
654 /* Not sure if this is a bug in DuplicateHandle, marking todo_wine for now
656 todo_wine
ok(store
!= 0, "CertOpenStore failed: %08lx\n", GetLastError());
657 CertCloseStore(store
, 0);
659 rc
= RegCreateKeyExA(HKEY_CURRENT_USER
, tempKey
, 0, NULL
, 0, KEY_ALL_ACCESS
,
661 ok(!rc
, "RegCreateKeyExA failed: %ld\n", rc
);
667 static const char certificates
[] = "Certificates\\";
668 char subKeyName
[sizeof(certificates
) + 20 * 2 + 1], *ptr
;
670 PCCERT_CONTEXT context
;
672 store
= CertOpenStore(CERT_STORE_PROV_REG
, 0, 0, 0, key
);
673 ok(store
!= 0, "CertOpenStore failed: %08lx\n", GetLastError());
674 /* Add a certificate. It isn't persisted right away, since it's only
675 * added to the cache..
677 ret
= CertAddEncodedCertificateToStore(store
, X509_ASN_ENCODING
,
678 bigCert2
, sizeof(bigCert2
) - 1, CERT_STORE_ADD_ALWAYS
, NULL
);
679 ok(ret
, "CertAddEncodedCertificateToStore failed: %08lx\n",
681 /* so flush the cache to force a commit.. */
682 ret
= CertControlStore(store
, 0, CERT_STORE_CTRL_COMMIT
, NULL
);
683 ok(ret
, "CertControlStore failed: %08lx\n", GetLastError());
684 /* and check that the expected subkey was written. */
686 ret
= CryptHashCertificate(0, 0, 0, bigCert2
, sizeof(bigCert2
) - 1,
688 ok(ret
, "CryptHashCertificate failed: %ld\n", GetLastError());
689 strcpy(subKeyName
, certificates
);
690 for (i
= 0, ptr
= subKeyName
+ sizeof(certificates
) - 1; i
< size
;
692 sprintf(ptr
, "%02X", hash
[i
]);
693 rc
= RegCreateKeyExA(key
, subKeyName
, 0, NULL
, 0, KEY_ALL_ACCESS
, NULL
,
695 ok(!rc
, "RegCreateKeyExA failed: %ld\n", rc
);
701 RegQueryValueExA(subKey
, "Blob", NULL
, NULL
, NULL
, &size
);
702 buf
= HeapAlloc(GetProcessHeap(), 0, size
);
705 rc
= RegQueryValueExA(subKey
, "Blob", NULL
, NULL
, buf
, &size
);
706 ok(!rc
, "RegQueryValueExA failed: %ld\n", rc
);
709 const struct CertPropIDHeader
*hdr
;
711 /* Both the hash and the cert should be present */
712 hdr
= findPropID(buf
, size
, CERT_CERT_PROP_ID
);
713 ok(hdr
!= NULL
, "Expected to find a cert property\n");
716 ok(hdr
->cb
== sizeof(bigCert2
) - 1,
717 "Unexpected size %ld of cert property, expected %d\n",
718 hdr
->cb
, sizeof(bigCert2
) - 1);
719 ok(!memcmp((BYTE
*)hdr
+ sizeof(*hdr
), bigCert2
,
720 hdr
->cb
), "Unexpected cert in cert property\n");
722 hdr
= findPropID(buf
, size
, CERT_HASH_PROP_ID
);
723 ok(hdr
!= NULL
, "Expected to find a hash property\n");
726 ok(hdr
->cb
== sizeof(hash
),
727 "Unexpected size %ld of hash property, expected %d\n",
728 hdr
->cb
, sizeof(hash
));
729 ok(!memcmp((BYTE
*)hdr
+ sizeof(*hdr
), hash
,
730 hdr
->cb
), "Unexpected hash in cert property\n");
733 HeapFree(GetProcessHeap(), 0, buf
);
738 /* Remove the existing context */
739 context
= CertEnumCertificatesInStore(store
, NULL
);
740 ok(context
!= NULL
, "Expected a cert context\n");
742 CertDeleteCertificateFromStore(context
);
743 ret
= CertControlStore(store
, 0, CERT_STORE_CTRL_COMMIT
, NULL
);
744 ok(ret
, "CertControlStore failed: %08lx\n", GetLastError());
746 /* Add a serialized cert with a bogus hash directly to the registry */
747 memset(hash
, 0, sizeof(hash
));
748 strcpy(subKeyName
, certificates
);
749 for (i
= 0, ptr
= subKeyName
+ sizeof(certificates
) - 1;
750 i
< sizeof(hash
); i
++, ptr
+= 2)
751 sprintf(ptr
, "%02X", hash
[i
]);
752 rc
= RegCreateKeyExA(key
, subKeyName
, 0, NULL
, 0, KEY_ALL_ACCESS
, NULL
,
754 ok(!rc
, "RegCreateKeyExA failed: %ld\n", rc
);
757 BYTE buf
[sizeof(struct CertPropIDHeader
) * 2 + sizeof(hash
) +
758 sizeof(bigCert
) - 1], *ptr
;
760 struct CertPropIDHeader
*hdr
;
762 hdr
= (struct CertPropIDHeader
*)buf
;
763 hdr
->propID
= CERT_HASH_PROP_ID
;
765 hdr
->cb
= sizeof(hash
);
766 ptr
= buf
+ sizeof(*hdr
);
767 memcpy(ptr
, hash
, sizeof(hash
));
769 hdr
= (struct CertPropIDHeader
*)ptr
;
770 hdr
->propID
= CERT_CERT_PROP_ID
;
772 hdr
->cb
= sizeof(bigCert
) - 1;
774 memcpy(ptr
, bigCert
, sizeof(bigCert
) - 1);
776 rc
= RegSetValueExA(subKey
, "Blob", 0, REG_BINARY
, buf
,
778 ok(!rc
, "RegSetValueExA failed: %ld\n", rc
);
780 ret
= CertControlStore(store
, 0, CERT_STORE_CTRL_RESYNC
, NULL
);
781 ok(ret
, "CertControlStore failed: %08lx\n", GetLastError());
783 /* Make sure the bogus hash cert gets loaded. */
787 context
= CertEnumCertificatesInStore(store
, context
);
790 } while (context
!= NULL
);
791 ok(certCount
== 1, "Expected 1 certificates, got %ld\n", certCount
);
796 /* Add another serialized cert directly to the registry, this time
797 * under the correct key name (named with the correct hash value).
800 ret
= CryptHashCertificate(0, 0, 0, bigCert2
,
801 sizeof(bigCert2
) - 1, hash
, &size
);
802 ok(ret
, "CryptHashCertificate failed: %ld\n", GetLastError());
803 strcpy(subKeyName
, certificates
);
804 for (i
= 0, ptr
= subKeyName
+ sizeof(certificates
) - 1;
805 i
< sizeof(hash
); i
++, ptr
+= 2)
806 sprintf(ptr
, "%02X", hash
[i
]);
807 rc
= RegCreateKeyExA(key
, subKeyName
, 0, NULL
, 0, KEY_ALL_ACCESS
, NULL
,
809 ok(!rc
, "RegCreateKeyExA failed: %ld\n", rc
);
812 BYTE buf
[sizeof(struct CertPropIDHeader
) * 2 + sizeof(hash
) +
813 sizeof(bigCert2
) - 1], *ptr
;
815 PCCERT_CONTEXT context
;
816 struct CertPropIDHeader
*hdr
;
818 /* First try with a bogus hash... */
819 hdr
= (struct CertPropIDHeader
*)buf
;
820 hdr
->propID
= CERT_HASH_PROP_ID
;
822 hdr
->cb
= sizeof(hash
);
823 ptr
= buf
+ sizeof(*hdr
);
824 memset(ptr
, 0, sizeof(hash
));
826 hdr
= (struct CertPropIDHeader
*)ptr
;
827 hdr
->propID
= CERT_CERT_PROP_ID
;
829 hdr
->cb
= sizeof(bigCert2
) - 1;
831 memcpy(ptr
, bigCert2
, sizeof(bigCert2
) - 1);
833 rc
= RegSetValueExA(subKey
, "Blob", 0, REG_BINARY
, buf
,
835 ok(!rc
, "RegSetValueExA failed: %ld\n", rc
);
837 ret
= CertControlStore(store
, 0, CERT_STORE_CTRL_RESYNC
, NULL
);
838 ok(ret
, "CertControlStore failed: %08lx\n", GetLastError());
840 /* and make sure just one cert still gets loaded. */
844 context
= CertEnumCertificatesInStore(store
, context
);
847 } while (context
!= NULL
);
848 ok(certCount
== 1, "Expected 1 certificates, got %ld\n", certCount
);
850 /* Try again with the correct hash... */
851 ptr
= buf
+ sizeof(*hdr
);
852 memcpy(ptr
, hash
, sizeof(hash
));
854 rc
= RegSetValueExA(subKey
, "Blob", 0, REG_BINARY
, buf
,
856 ok(!rc
, "RegSetValueExA failed: %ld\n", rc
);
858 ret
= CertControlStore(store
, 0, CERT_STORE_CTRL_RESYNC
, NULL
);
859 ok(ret
, "CertControlStore failed: %08lx\n", GetLastError());
861 /* and make sure two certs get loaded. */
865 context
= CertEnumCertificatesInStore(store
, context
);
868 } while (context
!= NULL
);
869 ok(certCount
== 2, "Expected 2 certificates, got %ld\n", certCount
);
873 CertCloseStore(store
, 0);
874 /* Is delete allowed on a reg store? */
875 store
= CertOpenStore(CERT_STORE_PROV_REG
, 0, 0,
876 CERT_STORE_DELETE_FLAG
, key
);
877 ok(store
== NULL
, "Expected NULL return from CERT_STORE_DELETE_FLAG\n");
878 ok(GetLastError() == 0, "CertOpenStore failed: %08lx\n",
883 /* The CertOpenStore with CERT_STORE_DELETE_FLAG above will delete the
884 * contents of the key, but not the key itself.
886 rc
= RegCreateKeyExA(HKEY_CURRENT_USER
, tempKey
, 0, NULL
, 0, KEY_ALL_ACCESS
,
888 ok(!rc
, "RegCreateKeyExA failed: %ld\n", rc
);
889 ok(disp
== REG_OPENED_EXISTING_KEY
,
890 "Expected REG_OPENED_EXISTING_KEY, got %ld\n", disp
);
894 rc
= RegDeleteKeyA(HKEY_CURRENT_USER
, tempKey
);
897 HMODULE shlwapi
= LoadLibraryA("shlwapi");
899 /* Use shlwapi's SHDeleteKeyA to _really_ blow away the key,
900 * otherwise subsequent tests will fail.
904 SHDeleteKeyAFunc pSHDeleteKeyA
=
905 (SHDeleteKeyAFunc
)GetProcAddress(shlwapi
, "SHDeleteKeyA");
908 pSHDeleteKeyA(HKEY_CURRENT_USER
, tempKey
);
909 FreeLibrary(shlwapi
);
915 static const char MyA
[] = { 'M','y',0,0 };
916 static const WCHAR MyW
[] = { 'M','y',0 };
917 static const WCHAR BogusW
[] = { 'B','o','g','u','s',0 };
918 static const WCHAR BogusPathW
[] = { 'S','o','f','t','w','a','r','e','\\',
919 'M','i','c','r','o','s','o','f','t','\\','S','y','s','t','e','m','C','e','r',
920 't','i','f','i','c','a','t','e','s','\\','B','o','g','u','s',0 };
922 static void testSystemRegStore(void)
924 HCERTSTORE store
, memStore
;
926 /* Check with a UNICODE name */
927 store
= CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY
, 0, 0,
928 CERT_SYSTEM_STORE_CURRENT_USER
| CERT_STORE_OPEN_EXISTING_FLAG
, MyW
);
929 /* Not all OSes support CERT_STORE_PROV_SYSTEM_REGISTRY, so don't continue
930 * testing if they don't.
935 /* Check that it isn't a collection store */
936 memStore
= CertOpenStore(CERT_STORE_PROV_MEMORY
, 0, 0,
937 CERT_STORE_CREATE_NEW_FLAG
, NULL
);
940 BOOL ret
= CertAddStoreToCollection(store
, memStore
, 0, 0);
942 ok(!ret
&& GetLastError() ==
943 HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER
),
944 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
946 CertCloseStore(memStore
, 0);
948 CertCloseStore(store
, 0);
950 /* Check opening a bogus store */
951 store
= CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY
, 0, 0,
952 CERT_SYSTEM_STORE_CURRENT_USER
| CERT_STORE_OPEN_EXISTING_FLAG
, BogusW
);
953 ok(!store
&& GetLastError() == ERROR_FILE_NOT_FOUND
,
954 "Expected ERROR_FILE_NOT_FOUND, got %08lx\n", GetLastError());
955 store
= CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY
, 0, 0,
956 CERT_SYSTEM_STORE_CURRENT_USER
, BogusW
);
957 ok(store
!= 0, "CertOpenStore failed: %08lx\n", GetLastError());
959 CertCloseStore(store
, 0);
960 /* Now check whether deleting is allowed */
961 store
= CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY
, 0, 0,
962 CERT_SYSTEM_STORE_CURRENT_USER
| CERT_STORE_DELETE_FLAG
, BogusW
);
963 RegDeleteKeyW(HKEY_CURRENT_USER
, BogusPathW
);
965 store
= CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY
, 0, 0, 0, NULL
);
966 ok(!store
&& GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER
),
967 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
969 store
= CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY
, 0, 0,
970 CERT_SYSTEM_STORE_LOCAL_MACHINE
| CERT_SYSTEM_STORE_CURRENT_USER
, MyA
);
971 ok(!store
&& GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER
),
972 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
974 store
= CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY
, 0, 0,
975 CERT_SYSTEM_STORE_LOCAL_MACHINE
| CERT_SYSTEM_STORE_CURRENT_USER
, MyW
);
976 ok(!store
&& GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER
),
977 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
979 /* The name is expected to be UNICODE, check with an ASCII name */
980 store
= CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY
, 0, 0,
981 CERT_SYSTEM_STORE_CURRENT_USER
| CERT_STORE_OPEN_EXISTING_FLAG
, MyA
);
982 ok(!store
&& GetLastError() == ERROR_FILE_NOT_FOUND
,
983 "Expected ERROR_FILE_NOT_FOUND, got %08lx\n", GetLastError());
986 static void testSystemStore(void)
988 static const WCHAR baskslashW
[] = { '\\',0 };
990 WCHAR keyName
[MAX_PATH
];
994 store
= CertOpenStore(CERT_STORE_PROV_SYSTEM
, 0, 0, 0, NULL
);
995 ok(!store
&& GetLastError() == ERROR_FILE_NOT_FOUND
,
996 "Expected ERROR_FILE_NOT_FOUND, got %08lx\n", GetLastError());
997 store
= CertOpenStore(CERT_STORE_PROV_SYSTEM
, 0, 0,
998 CERT_SYSTEM_STORE_LOCAL_MACHINE
| CERT_SYSTEM_STORE_CURRENT_USER
, MyA
);
999 ok(!store
&& GetLastError() == ERROR_FILE_NOT_FOUND
,
1000 "Expected ERROR_FILE_NOT_FOUND, got %08lx\n", GetLastError());
1001 store
= CertOpenStore(CERT_STORE_PROV_SYSTEM
, 0, 0,
1002 CERT_SYSTEM_STORE_LOCAL_MACHINE
| CERT_SYSTEM_STORE_CURRENT_USER
, MyW
);
1003 ok(!store
&& GetLastError() == ERROR_FILE_NOT_FOUND
,
1004 "Expected ERROR_FILE_NOT_FOUND, got %08lx\n", GetLastError());
1005 /* The name is expected to be UNICODE, first check with an ASCII name */
1006 store
= CertOpenStore(CERT_STORE_PROV_SYSTEM
, 0, 0,
1007 CERT_SYSTEM_STORE_CURRENT_USER
| CERT_STORE_OPEN_EXISTING_FLAG
, MyA
);
1008 ok(!store
&& GetLastError() == ERROR_FILE_NOT_FOUND
,
1009 "Expected ERROR_FILE_NOT_FOUND, got %08lx\n", GetLastError());
1010 /* Create the expected key */
1011 lstrcpyW(keyName
, CERT_LOCAL_MACHINE_SYSTEM_STORE_REGPATH
);
1012 lstrcatW(keyName
, baskslashW
);
1013 lstrcatW(keyName
, MyW
);
1014 rc
= RegCreateKeyExW(HKEY_CURRENT_USER
, keyName
, 0, NULL
, 0, KEY_READ
,
1016 ok(!rc
, "RegCreateKeyEx failed: %ld\n", rc
);
1019 /* Check opening with a UNICODE name, specifying the create new flag */
1020 store
= CertOpenStore(CERT_STORE_PROV_SYSTEM
, 0, 0,
1021 CERT_SYSTEM_STORE_CURRENT_USER
| CERT_STORE_CREATE_NEW_FLAG
, MyW
);
1022 ok(!store
&& GetLastError() == ERROR_FILE_EXISTS
,
1023 "Expected ERROR_FILE_EXISTS, got %08lx\n", GetLastError());
1024 /* Now check opening with a UNICODE name, this time opening existing */
1025 store
= CertOpenStore(CERT_STORE_PROV_SYSTEM
, 0, 0,
1026 CERT_SYSTEM_STORE_CURRENT_USER
| CERT_STORE_OPEN_EXISTING_FLAG
, MyW
);
1027 ok(store
!= 0, "CertOpenStore failed: %08lx\n", GetLastError());
1030 HCERTSTORE memStore
= CertOpenStore(CERT_STORE_PROV_MEMORY
, 0, 0,
1031 CERT_STORE_CREATE_NEW_FLAG
, NULL
);
1033 /* Check that it's a collection store */
1036 BOOL ret
= CertAddStoreToCollection(store
, memStore
, 0, 0);
1038 /* FIXME: this'll fail on NT4, but what error will it give? */
1039 ok(ret
, "CertAddStoreToCollection failed: %08lx\n", GetLastError());
1040 CertCloseStore(memStore
, 0);
1042 CertCloseStore(store
, 0);
1045 /* Check opening a bogus store */
1046 store
= CertOpenStore(CERT_STORE_PROV_SYSTEM
, 0, 0,
1047 CERT_SYSTEM_STORE_CURRENT_USER
| CERT_STORE_OPEN_EXISTING_FLAG
, BogusW
);
1048 ok(!store
&& GetLastError() == ERROR_FILE_NOT_FOUND
,
1049 "Expected ERROR_FILE_NOT_FOUND, got %08lx\n", GetLastError());
1050 store
= CertOpenStore(CERT_STORE_PROV_SYSTEM
, 0, 0,
1051 CERT_SYSTEM_STORE_CURRENT_USER
, BogusW
);
1052 ok(store
!= 0, "CertOpenStore failed: %08lx\n", GetLastError());
1054 CertCloseStore(store
, 0);
1055 /* Now check whether deleting is allowed */
1056 store
= CertOpenStore(CERT_STORE_PROV_SYSTEM
, 0, 0,
1057 CERT_SYSTEM_STORE_CURRENT_USER
| CERT_STORE_DELETE_FLAG
, BogusW
);
1058 RegDeleteKeyW(HKEY_CURRENT_USER
, BogusPathW
);
1061 static void testCertOpenSystemStore(void)
1065 store
= CertOpenSystemStoreW(0, NULL
);
1066 ok(!store
&& GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER
),
1067 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
1069 /* This succeeds, and on WinXP at least, the Bogus key is created under
1070 * HKCU (but not under HKLM, even when run as an administrator.)
1072 store
= CertOpenSystemStoreW(0, BogusW
);
1073 ok(store
!= 0, "CertOpenSystemStore failed: %08lx\n", GetLastError());
1075 CertCloseStore(store
, 0);
1076 /* Delete it so other tests succeed next time around */
1077 store
= CertOpenStore(CERT_STORE_PROV_SYSTEM
, 0, 0,
1078 CERT_SYSTEM_STORE_CURRENT_USER
| CERT_STORE_DELETE_FLAG
, BogusW
);
1079 RegDeleteKeyW(HKEY_CURRENT_USER
, BogusPathW
);
1082 static void testCertProperties(void)
1084 PCCERT_CONTEXT context
= CertCreateCertificateContext(X509_ASN_ENCODING
,
1085 bigCert
, sizeof(bigCert
) - 1);
1087 ok(context
!= NULL
, "CertCreateCertificateContext failed: %08lx\n",
1091 DWORD propID
, numProps
, access
, size
;
1093 BYTE hash
[20] = { 0 }, hashProperty
[20];
1094 CRYPT_DATA_BLOB blob
;
1097 propID = CertEnumCertificateContextProperties(NULL, 0);
1103 propID
= CertEnumCertificateContextProperties(context
, propID
);
1106 } while (propID
!= 0);
1107 ok(numProps
== 0, "Expected 0 properties, got %ld\n", numProps
);
1109 /* Tests with a NULL cert context. Prop ID 0 fails.. */
1110 ret
= CertSetCertificateContextProperty(NULL
, 0, 0, NULL
);
1111 ok(!ret
&& GetLastError() ==
1112 HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER
),
1113 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
1115 /* while this just crashes.
1116 ret = CertSetCertificateContextProperty(NULL,
1117 CERT_KEY_PROV_HANDLE_PROP_ID, 0, NULL);
1120 ret
= CertSetCertificateContextProperty(context
, 0, 0, NULL
);
1121 ok(!ret
&& GetLastError() ==
1122 HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER
),
1123 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
1125 /* Can't set the cert property directly, this crashes.
1126 ret = CertSetCertificateContextProperty(context,
1127 CERT_CERT_PROP_ID, 0, bigCert2);
1131 ret = CertGetCertificateContextProperty(context,
1132 CERT_ACCESS_STATE_PROP_ID, 0, NULL);
1134 size
= sizeof(access
);
1135 ret
= CertGetCertificateContextProperty(context
,
1136 CERT_ACCESS_STATE_PROP_ID
, &access
, &size
);
1137 ok(ret
, "CertGetCertificateContextProperty failed: %08lx\n",
1139 ok(!(access
& CERT_ACCESS_STATE_WRITE_PERSIST_FLAG
),
1140 "Didn't expect a persisted cert\n");
1141 /* Trying to set this "read only" property crashes.
1142 access |= CERT_ACCESS_STATE_WRITE_PERSIST_FLAG;
1143 ret = CertSetCertificateContextProperty(context,
1144 CERT_ACCESS_STATE_PROP_ID, 0, &access);
1147 /* Can I set the hash to an invalid hash? */
1149 blob
.cbData
= sizeof(hash
);
1150 ret
= CertSetCertificateContextProperty(context
, CERT_HASH_PROP_ID
, 0,
1152 ok(ret
, "CertSetCertificateContextProperty failed: %08lx\n",
1154 size
= sizeof(hashProperty
);
1155 ret
= CertGetCertificateContextProperty(context
, CERT_HASH_PROP_ID
,
1156 hashProperty
, &size
);
1157 ok(!memcmp(hashProperty
, hash
, sizeof(hash
)), "Unexpected hash\n");
1158 /* Delete the (bogus) hash, and get the real one */
1159 ret
= CertSetCertificateContextProperty(context
, CERT_HASH_PROP_ID
, 0,
1161 ok(ret
, "CertSetCertificateContextProperty failed: %08lx\n",
1163 size
= sizeof(hash
);
1164 ret
= CryptHashCertificate(0, 0, 0, bigCert
, sizeof(bigCert
) - 1,
1166 ok(ret
, "CryptHashCertificate failed: %08lx\n", GetLastError());
1167 ret
= CertGetCertificateContextProperty(context
, CERT_HASH_PROP_ID
,
1168 hashProperty
, &size
);
1169 ok(ret
, "CertGetCertificateContextProperty failed: %08lx\n",
1171 ok(!memcmp(hash
, hashProperty
, sizeof(hash
)), "Unexpected hash\n");
1173 /* Now that the hash property is set, we should get one property when
1179 propID
= CertEnumCertificateContextProperties(context
, propID
);
1182 } while (propID
!= 0);
1183 ok(numProps
== 1, "Expected 1 properties, got %ld\n", numProps
);
1185 CertFreeCertificateContext(context
);
1189 static void testAddSerialized(void)
1193 BYTE buf
[sizeof(struct CertPropIDHeader
) * 2 + 20 + sizeof(bigCert
) - 1] =
1196 struct CertPropIDHeader
*hdr
;
1197 PCCERT_CONTEXT context
;
1199 ret
= CertAddSerializedElementToStore(0, NULL
, 0, 0, 0, 0, NULL
, NULL
);
1200 ok(!ret
&& GetLastError() == ERROR_END_OF_MEDIA
,
1201 "Expected ERROR_END_OF_MEDIA, got %08lx\n", GetLastError());
1203 store
= CertOpenStore(CERT_STORE_PROV_MEMORY
, 0, 0,
1204 CERT_STORE_CREATE_NEW_FLAG
, NULL
);
1205 ok(store
!= 0, "CertOpenStore failed: %08lx\n", GetLastError());
1207 ret
= CertAddSerializedElementToStore(store
, NULL
, 0, 0, 0, 0, NULL
, NULL
);
1208 ok(!ret
&& GetLastError() == ERROR_END_OF_MEDIA
,
1209 "Expected ERROR_END_OF_MEDIA, got %08lx\n", GetLastError());
1211 /* Test with an empty property */
1212 hdr
= (struct CertPropIDHeader
*)buf
;
1213 hdr
->propID
= CERT_CERT_PROP_ID
;
1216 ret
= CertAddSerializedElementToStore(store
, buf
, sizeof(buf
), 0, 0, 0,
1218 ok(!ret
&& GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER
),
1219 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
1221 /* Test with a bad size in property header */
1222 hdr
->cb
= sizeof(bigCert
) - 2;
1223 memcpy(buf
+ sizeof(struct CertPropIDHeader
), bigCert
, sizeof(bigCert
) - 1);
1224 ret
= CertAddSerializedElementToStore(store
, buf
, sizeof(buf
), 0, 0, 0,
1226 ok(!ret
&& GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER
),
1227 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
1229 ret
= CertAddSerializedElementToStore(store
, buf
,
1230 sizeof(struct CertPropIDHeader
) + sizeof(bigCert
) - 1, 0, 0, 0, NULL
,
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, CERT_STORE_ADD_NEW
,
1238 ok(!ret
&& GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER
),
1239 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
1241 /* Kosher size in property header, but no context type */
1242 hdr
->cb
= sizeof(bigCert
) - 1;
1243 ret
= CertAddSerializedElementToStore(store
, buf
, sizeof(buf
), 0, 0, 0,
1245 ok(!ret
&& GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER
),
1246 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
1248 ret
= CertAddSerializedElementToStore(store
, buf
,
1249 sizeof(struct CertPropIDHeader
) + sizeof(bigCert
) - 1, 0, 0, 0, NULL
,
1251 ok(!ret
&& GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER
),
1252 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
1254 ret
= CertAddSerializedElementToStore(store
, buf
,
1255 sizeof(struct CertPropIDHeader
) + sizeof(bigCert
) - 1, CERT_STORE_ADD_NEW
,
1257 ok(!ret
&& GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER
),
1258 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
1260 /* With a bad context type */
1261 ret
= CertAddSerializedElementToStore(store
, buf
, sizeof(buf
), 0, 0,
1262 CERT_STORE_CRL_CONTEXT_FLAG
, NULL
, NULL
);
1263 ok(!ret
&& GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER
),
1264 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
1266 ret
= CertAddSerializedElementToStore(store
, buf
,
1267 sizeof(struct CertPropIDHeader
) + sizeof(bigCert
) - 1, 0, 0,
1268 CERT_STORE_CRL_CONTEXT_FLAG
, NULL
, NULL
);
1269 ok(!ret
&& GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER
),
1270 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
1272 ret
= CertAddSerializedElementToStore(store
, buf
,
1273 sizeof(struct CertPropIDHeader
) + sizeof(bigCert
) - 1, CERT_STORE_ADD_NEW
,
1274 0, CERT_STORE_CRL_CONTEXT_FLAG
, NULL
, NULL
);
1275 ok(!ret
&& GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER
),
1276 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
1278 /* Bad unknown field, good type */
1280 ret
= CertAddSerializedElementToStore(store
, buf
, sizeof(buf
), 0, 0,
1281 CERT_STORE_CERTIFICATE_CONTEXT_FLAG
, NULL
, NULL
);
1282 ok(!ret
&& GetLastError() == ERROR_FILE_NOT_FOUND
,
1283 "Expected ERROR_FILE_NOT_FOUND got %08lx\n", GetLastError());
1284 ret
= CertAddSerializedElementToStore(store
, buf
,
1285 sizeof(struct CertPropIDHeader
) + sizeof(bigCert
) - 1, 0, 0,
1286 CERT_STORE_CERTIFICATE_CONTEXT_FLAG
, NULL
, NULL
);
1287 ok(!ret
&& GetLastError() == ERROR_FILE_NOT_FOUND
,
1288 "Expected ERROR_FILE_NOT_FOUND got %08lx\n", GetLastError());
1289 ret
= CertAddSerializedElementToStore(store
, buf
,
1290 sizeof(struct CertPropIDHeader
) + sizeof(bigCert
) - 1, CERT_STORE_ADD_NEW
,
1291 0, CERT_STORE_CERTIFICATE_CONTEXT_FLAG
, NULL
, NULL
);
1292 ok(!ret
&& GetLastError() == ERROR_FILE_NOT_FOUND
,
1293 "Expected ERROR_FILE_NOT_FOUND got %08lx\n", GetLastError());
1294 /* Most everything okay, but bad add disposition */
1297 ret = CertAddSerializedElementToStore(store, buf, sizeof(buf), 0, 0,
1298 CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL, NULL);
1300 ret = CertAddSerializedElementToStore(store, buf,
1301 sizeof(struct CertPropIDHeader) + sizeof(bigCert) - 1, 0, 0,
1302 CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL, NULL);
1304 /* Everything okay, but buffer's too big */
1305 ret
= CertAddSerializedElementToStore(store
, buf
, sizeof(buf
),
1306 CERT_STORE_ADD_NEW
, 0, CERT_STORE_CERTIFICATE_CONTEXT_FLAG
, NULL
, NULL
);
1307 ok(ret
, "CertAddSerializedElementToStore failed: %08lx\n", GetLastError());
1308 /* Everything okay, check it's not re-added */
1309 ret
= CertAddSerializedElementToStore(store
, buf
,
1310 sizeof(struct CertPropIDHeader
) + sizeof(bigCert
) - 1, CERT_STORE_ADD_NEW
,
1311 0, CERT_STORE_CERTIFICATE_CONTEXT_FLAG
, NULL
, NULL
);
1312 ok(!ret
&& GetLastError() == CRYPT_E_EXISTS
,
1313 "Expected CRYPT_E_EXISTS, got %08lx\n", GetLastError());
1315 context
= CertEnumCertificatesInStore(store
, NULL
);
1316 ok(context
!= NULL
, "Expected a cert\n");
1318 CertDeleteCertificateFromStore(context
);
1320 /* Try adding with a bogus hash. Oddly enough, it succeeds, and the hash,
1321 * when queried, is the real hash rather than the bogus hash.
1323 hdr
= (struct CertPropIDHeader
*)(buf
+ sizeof(struct CertPropIDHeader
) +
1324 sizeof(bigCert
) - 1);
1325 hdr
->propID
= CERT_HASH_PROP_ID
;
1327 hdr
->cb
= sizeof(hash
);
1328 memset(hash
, 0xc, sizeof(hash
));
1329 memcpy((LPBYTE
)hdr
+ sizeof(struct CertPropIDHeader
), hash
, sizeof(hash
));
1330 ret
= CertAddSerializedElementToStore(store
, buf
, sizeof(buf
),
1331 CERT_STORE_ADD_NEW
, 0, CERT_STORE_CERTIFICATE_CONTEXT_FLAG
, NULL
,
1332 (const void **)&context
);
1333 ok(ret
, "CertAddSerializedElementToStore failed: %08lx\n", GetLastError());
1336 BYTE hashVal
[20], realHash
[20];
1337 DWORD size
= sizeof(hashVal
);
1339 ret
= CryptHashCertificate(0, 0, 0, bigCert
, sizeof(bigCert
) - 1,
1341 ok(ret
, "CryptHashCertificate failed: %08lx\n", GetLastError());
1342 ret
= CertGetCertificateContextProperty(context
, CERT_HASH_PROP_ID
,
1344 ok(ret
, "CertGetCertificateContextProperty failed: %08lx\n",
1346 ok(!memcmp(hashVal
, realHash
, size
), "Unexpected hash\n");
1349 CertCloseStore(store
, 0);
1354 testCryptHashCert();
1356 /* various combinations of CertOpenStore */
1358 testCollectionStore();
1360 testSystemRegStore();
1363 testCertOpenSystemStore();
1365 testCertProperties();
1366 testAddSerialized();