2 * crypt32 cert store function tests
4 * Copyright 2005-2006 Juan Lang
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
30 #include "wine/test.h"
32 /* The following aren't defined in wincrypt.h, as they're "reserved" */
33 #define CERT_CERT_PROP_ID 32
34 #define CERT_CRL_PROP_ID 33
35 #define CERT_CTL_PROP_ID 34
37 struct CertPropIDHeader
44 static const BYTE emptyCert[] = { 0x30, 0x00 };
45 static const BYTE bigCert[] = { 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
46 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
47 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x22,
48 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30,
49 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30,
50 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30,
51 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20,
52 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01,
53 0x00, 0xa3, 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01,
54 0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
55 static const BYTE subjectName[] = { 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06,
56 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61,
58 static const BYTE bigCertHash[] = { 0x6e, 0x30, 0x90, 0x71, 0x5f, 0xd9, 0x23,
59 0x56, 0xeb, 0xae, 0x25, 0x40, 0xe6, 0x22, 0xda, 0x19, 0x26, 0x02, 0xa6, 0x08 };
60 static const BYTE signedBigCert[] = {
61 0x30, 0x81, 0x93, 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06, 0x00, 0x30,
62 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a,
63 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x22, 0x18, 0x0f,
64 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
65 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30,
66 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06,
67 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61,
68 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3,
69 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff,
70 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
71 0x00, 0x03, 0x11, 0x00, 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07,
72 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00 };
73 static const BYTE serializedCert[] = { 0x20, 0x00, 0x00, 0x00,
74 0x01, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x30, 0x7a, 0x02, 0x01, 0x01,
75 0x30, 0x02, 0x06, 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55,
76 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67,
77 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31,
78 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31,
79 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15,
80 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75,
81 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06,
82 0x00, 0x03, 0x01, 0x00, 0xa3, 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55,
83 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02,
85 static const BYTE signedCRL[] = { 0x30, 0x45, 0x30, 0x2c, 0x30, 0x02, 0x06,
86 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
87 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18, 0x0f,
88 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
89 0x30, 0x5a, 0x30, 0x02, 0x06, 0x00, 0x03, 0x11, 0x00, 0x0f, 0x0e, 0x0d, 0x0c,
90 0x0b, 0x0a, 0x09, 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00 };
91 static const BYTE bigCert2[] = { 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
92 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
93 0x0a, 0x41, 0x6c, 0x65, 0x78, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x22,
94 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30,
95 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30,
96 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30,
97 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x41, 0x6c, 0x65, 0x78, 0x20,
98 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01,
99 0x00, 0xa3, 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01,
100 0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
101 static const BYTE subjectName2[] = { 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06,
102 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x41, 0x6c, 0x65, 0x78, 0x20, 0x4c, 0x61,
104 static const BYTE certWithUsage[] = { 0x30, 0x81, 0x93, 0x02, 0x01, 0x01, 0x30,
105 0x02, 0x06, 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04,
106 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00,
107 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30,
108 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30,
109 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31,
110 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61,
111 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00,
112 0x03, 0x01, 0x00, 0xa3, 0x2f, 0x30, 0x2d, 0x30, 0x2b, 0x06, 0x03, 0x55, 0x1d,
113 0x25, 0x01, 0x01, 0xff, 0x04, 0x21, 0x30, 0x1f, 0x06, 0x08, 0x2b, 0x06, 0x01,
114 0x05, 0x05, 0x07, 0x03, 0x03, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07,
115 0x03, 0x02, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01 };
116 static const BYTE serialNum[] = { 1 };
118 static void testDupCert(void)
122 store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
123 CERT_STORE_CREATE_NEW_FLAG, NULL);
124 ok(store != NULL, "CertOpenStore failed: %ld\n", GetLastError());
127 PCCERT_CONTEXT context, dupContext;
130 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
131 bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, &context);
132 ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\n",
134 ok(context != NULL, "Expected a valid cert context\n");
137 ok(context->cbCertEncoded == sizeof(bigCert),
138 "Expected cert of %d bytes, got %ld\n", sizeof(bigCert),
139 context->cbCertEncoded);
140 ok(!memcmp(context->pbCertEncoded, bigCert, sizeof(bigCert)),
141 "Unexpected encoded cert in context\n");
142 ok(context->hCertStore == store, "Unexpected store\n");
144 dupContext = CertDuplicateCertificateContext(context);
145 ok(dupContext != NULL, "Expected valid duplicate\n");
146 /* Not only is it a duplicate, it's identical: the address is the
149 ok(dupContext == context, "Expected identical context addresses\n");
150 CertFreeCertificateContext(dupContext);
151 CertFreeCertificateContext(context);
153 CertCloseStore(store, 0);
157 static void testFindCert(void)
161 store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
162 CERT_STORE_CREATE_NEW_FLAG, NULL);
163 ok(store != NULL, "CertOpenStore failed: %ld\n", GetLastError());
166 PCCERT_CONTEXT context = NULL;
168 CERT_INFO certInfo = { 0 };
169 CRYPT_HASH_BLOB blob;
171 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
172 bigCert, sizeof(bigCert), CERT_STORE_ADD_NEW, NULL);
173 ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\n",
175 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
176 bigCert2, sizeof(bigCert2), CERT_STORE_ADD_NEW, NULL);
177 ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\n",
179 /* This has the same name as bigCert */
180 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
181 certWithUsage, sizeof(certWithUsage), CERT_STORE_ADD_NEW, NULL);
182 ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\n",
186 context = CertFindCertificateInStore(NULL, 0, 0, 0, NULL, NULL);
189 /* Check first cert's there, by issuer */
190 certInfo.Subject.pbData = (LPBYTE)subjectName;
191 certInfo.Subject.cbData = sizeof(subjectName);
192 certInfo.SerialNumber.pbData = (LPBYTE)serialNum;
193 certInfo.SerialNumber.cbData = sizeof(serialNum);
194 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
195 CERT_FIND_ISSUER_NAME, &certInfo.Subject, NULL);
196 ok(context != NULL, "CertFindCertificateInStore failed: %08lx\n",
200 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
201 CERT_FIND_ISSUER_NAME, &certInfo.Subject, context);
202 ok(context != NULL, "Expected more than one cert\n");
205 context = CertFindCertificateInStore(store, X509_ASN_ENCODING,
206 0, CERT_FIND_ISSUER_NAME, &certInfo.Subject, context);
207 ok(context == NULL, "Expected precisely two certs\n");
211 /* Check second cert's there as well, by subject name */
212 certInfo.Subject.pbData = (LPBYTE)subjectName2;
213 certInfo.Subject.cbData = sizeof(subjectName2);
214 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
215 CERT_FIND_SUBJECT_NAME, &certInfo.Subject, NULL);
216 ok(context != NULL, "CertFindCertificateInStore failed: %08lx\n",
220 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
221 CERT_FIND_ISSUER_NAME, &certInfo.Subject, context);
222 ok(context == NULL, "Expected one cert only\n");
225 /* Strange but true: searching for the subject cert requires you to set
226 * the issuer, not the subject
228 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
229 CERT_FIND_SUBJECT_CERT, &certInfo.Subject, NULL);
230 ok(context == NULL, "Expected no certificate\n");
231 certInfo.Subject.pbData = NULL;
232 certInfo.Subject.cbData = 0;
233 certInfo.Issuer.pbData = (LPBYTE)subjectName2;
234 certInfo.Issuer.cbData = sizeof(subjectName2);
235 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
236 CERT_FIND_SUBJECT_CERT, &certInfo, NULL);
237 ok(context != NULL, "CertFindCertificateInStore failed: %08lx\n",
241 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
242 CERT_FIND_ISSUER_NAME, &certInfo.Subject, context);
243 ok(context == NULL, "Expected one cert only\n");
246 /* The nice thing about hashes, they're unique */
247 blob.pbData = (LPBYTE)bigCertHash;
248 blob.cbData = sizeof(bigCertHash);
249 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
250 CERT_FIND_SHA1_HASH, &blob, NULL);
251 ok(context != NULL, "CertFindCertificateInStore failed: %08lx\n",
255 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
256 CERT_FIND_ISSUER_NAME, &certInfo.Subject, context);
257 ok(context == NULL, "Expected one cert only\n");
260 CertCloseStore(store, 0);
264 static void testMemStore(void)
266 HCERTSTORE store1, store2;
267 PCCERT_CONTEXT context;
271 store1 = CertOpenStore(0, 0, 0, 0, NULL);
272 ok(!store1 && GetLastError() == ERROR_FILE_NOT_FOUND,
273 "Expected ERROR_FILE_NOT_FOUND, got %ld\n", GetLastError());
275 store1 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
276 CERT_STORE_DELETE_FLAG, NULL);
277 ok(!store1 && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED,
278 "Expected ERROR_CALL_NOT_IMPLEMENTED, got %ld\n", GetLastError());
281 store1 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
282 CERT_STORE_CREATE_NEW_FLAG, NULL);
283 ok(store1 != NULL, "CertOpenStore failed: %ld\n", GetLastError());
284 /* open existing doesn't */
285 store2 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
286 CERT_STORE_OPEN_EXISTING_FLAG, NULL);
287 ok(store2 != NULL, "CertOpenStore failed: %ld\n", GetLastError());
288 ok(store1 != store2, "Expected different stores\n");
290 /* add a bogus (empty) cert */
292 ret = CertAddEncodedCertificateToStore(store1, X509_ASN_ENCODING, emptyCert,
293 sizeof(emptyCert), CERT_STORE_ADD_ALWAYS, &context);
294 /* Windows returns CRYPT_E_ASN1_EOD, but accept CRYPT_E_ASN1_CORRUPT as
295 * well (because matching errors is tough in this case)
297 ok(!ret && (GetLastError() == CRYPT_E_ASN1_EOD || GetLastError() ==
298 CRYPT_E_ASN1_CORRUPT),
299 "Expected CRYPT_E_ASN1_EOD or CRYPT_E_ASN1_CORRUPT, got %08lx\n",
301 /* add a "signed" cert--the signature isn't a real signature, so this adds
302 * without any check of the signature's validity
304 ret = CertAddEncodedCertificateToStore(store1, X509_ASN_ENCODING,
305 signedBigCert, sizeof(signedBigCert), CERT_STORE_ADD_ALWAYS, &context);
306 ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\n", GetLastError());
307 ok(context != NULL, "Expected a valid cert context\n");
310 ok(context->cbCertEncoded == sizeof(signedBigCert),
311 "Expected cert of %d bytes, got %ld\n", sizeof(signedBigCert),
312 context->cbCertEncoded);
313 ok(!memcmp(context->pbCertEncoded, signedBigCert,
314 sizeof(signedBigCert)), "Unexpected encoded cert in context\n");
315 /* remove it, the rest of the tests will work on an unsigned cert */
316 ret = CertDeleteCertificateFromStore(context);
317 ok(ret, "CertDeleteCertificateFromStore failed: %08lx\n",
320 /* try adding a "signed" CRL as a cert */
321 ret = CertAddEncodedCertificateToStore(store1, X509_ASN_ENCODING,
322 signedCRL, sizeof(signedCRL), CERT_STORE_ADD_ALWAYS, &context);
323 ok(!ret && (GetLastError() == CRYPT_E_ASN1_BADTAG || GetLastError() ==
324 CRYPT_E_ASN1_CORRUPT),
325 "Expected CRYPT_E_ASN1_BADTAG or CRYPT_E_ASN1_CORRUPT, got %08lx\n",
327 /* add a cert to store1 */
328 ret = CertAddEncodedCertificateToStore(store1, X509_ASN_ENCODING, bigCert,
329 sizeof(bigCert), CERT_STORE_ADD_ALWAYS, &context);
330 ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\n", GetLastError());
331 ok(context != NULL, "Expected a valid cert context\n");
337 ok(context->cbCertEncoded == sizeof(bigCert),
338 "Expected cert of %d bytes, got %ld\n", sizeof(bigCert),
339 context->cbCertEncoded);
340 ok(!memcmp(context->pbCertEncoded, bigCert, sizeof(bigCert)),
341 "Unexpected encoded cert in context\n");
342 ok(context->hCertStore == store1, "Unexpected store\n");
344 /* check serializing this element */
346 ret = CertSerializeCertificateStoreElement(NULL, 0, NULL, NULL);
347 ret = CertSerializeCertificateStoreElement(context, 0, NULL, NULL);
348 ret = CertSerializeCertificateStoreElement(NULL, 0, NULL, &size);
350 /* apparently flags are ignored */
351 ret = CertSerializeCertificateStoreElement(context, 1, NULL, &size);
352 ok(ret, "CertSerializeCertificateStoreElement failed: %08lx\n",
354 buf = HeapAlloc(GetProcessHeap(), 0, size);
357 ret = CertSerializeCertificateStoreElement(context, 0, buf, &size);
358 ok(size == sizeof(serializedCert), "Expected size %d, got %ld\n",
359 sizeof(serializedCert), size);
360 ok(!memcmp(serializedCert, buf, size),
361 "Unexpected serialized cert\n");
362 HeapFree(GetProcessHeap(), 0, buf);
365 ret = CertFreeCertificateContext(context);
366 ok(ret, "CertFreeCertificateContext failed: %08lx\n", GetLastError());
368 /* verify the cert's in store1 */
369 context = CertEnumCertificatesInStore(store1, NULL);
370 ok(context != NULL, "Expected a valid context\n");
371 context = CertEnumCertificatesInStore(store1, context);
372 ok(!context && GetLastError() == CRYPT_E_NOT_FOUND,
373 "Expected CRYPT_E_NOT_FOUND, got %08lx\n", GetLastError());
374 /* verify store2 (the "open existing" mem store) is still empty */
375 context = CertEnumCertificatesInStore(store2, NULL);
376 ok(!context, "Expected an empty store\n");
377 /* delete the cert from store1, and check it's empty */
378 context = CertEnumCertificatesInStore(store1, NULL);
381 /* Deleting a bitwise copy crashes with an access to an uninitialized
382 * pointer, so a cert context has some special data out there in memory
385 memcpy(©, context, sizeof(copy));
386 ret = CertDeleteCertificateFromStore(©);
388 PCCERT_CONTEXT copy = CertDuplicateCertificateContext(context);
390 ok(copy != NULL, "CertDuplicateCertificateContext failed: %08lx\n",
392 ret = CertDeleteCertificateFromStore(context);
393 ok(ret, "CertDeleteCertificateFromStore failed: %08lx\n",
395 /* try deleting a copy */
396 ret = CertDeleteCertificateFromStore(copy);
397 ok(ret, "CertDeleteCertificateFromStore failed: %08lx\n",
399 /* check that the store is empty */
400 context = CertEnumCertificatesInStore(store1, NULL);
401 ok(!context, "Expected an empty store\n");
404 /* close an empty store */
405 ret = CertCloseStore(NULL, 0);
406 ok(ret, "CertCloseStore failed: %ld\n", GetLastError());
407 ret = CertCloseStore(store1, 0);
408 ok(ret, "CertCloseStore failed: %ld\n", GetLastError());
409 ret = CertCloseStore(store2, 0);
410 ok(ret, "CertCloseStore failed: %ld\n", GetLastError());
412 /* This seems nonsensical, but you can open a read-only mem store, only
415 store1 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
416 CERT_STORE_READONLY_FLAG, NULL);
417 ok(store1 != NULL, "CertOpenStore failed: %ld\n", GetLastError());
418 /* yep, this succeeds */
419 ret = CertAddEncodedCertificateToStore(store1, X509_ASN_ENCODING, bigCert,
420 sizeof(bigCert), CERT_STORE_ADD_ALWAYS, &context);
421 ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\n", GetLastError());
422 ok(context != NULL, "Expected a valid cert context\n");
425 ok(context->cbCertEncoded == sizeof(bigCert),
426 "Expected cert of %d bytes, got %ld\n", sizeof(bigCert),
427 context->cbCertEncoded);
428 ok(!memcmp(context->pbCertEncoded, bigCert, sizeof(bigCert)),
429 "Unexpected encoded cert in context\n");
430 ok(context->hCertStore == store1, "Unexpected store\n");
431 ret = CertDeleteCertificateFromStore(context);
432 ok(ret, "CertDeleteCertificateFromStore failed: %08lx\n",
435 CertCloseStore(store1, 0);
438 static void testCollectionStore(void)
440 HCERTSTORE store1, store2, collection, collection2;
441 PCCERT_CONTEXT context;
444 collection = CertOpenStore(CERT_STORE_PROV_COLLECTION, 0, 0,
445 CERT_STORE_CREATE_NEW_FLAG, NULL);
447 /* Try adding a cert to any empty collection */
448 ret = CertAddEncodedCertificateToStore(collection, X509_ASN_ENCODING,
449 bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, NULL);
450 ok(!ret && GetLastError() == HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED),
451 "Expected HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED), got %08lx\n",
454 /* Create and add a cert to a memory store */
455 store1 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
456 CERT_STORE_CREATE_NEW_FLAG, NULL);
457 ret = CertAddEncodedCertificateToStore(store1, X509_ASN_ENCODING,
458 bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, NULL);
459 ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\n", GetLastError());
460 /* Add the memory store to the collection, without allowing adding */
461 ret = CertAddStoreToCollection(collection, store1, 0, 0);
462 ok(ret, "CertAddStoreToCollection failed: %08lx\n", GetLastError());
463 /* Verify the cert is in the collection */
464 context = CertEnumCertificatesInStore(collection, NULL);
465 ok(context != NULL, "Expected a valid context\n");
468 ok(context->hCertStore == collection, "Unexpected store\n");
469 CertFreeCertificateContext(context);
471 /* Check that adding to the collection isn't allowed */
472 ret = CertAddEncodedCertificateToStore(collection, X509_ASN_ENCODING,
473 bigCert2, sizeof(bigCert2), CERT_STORE_ADD_ALWAYS, NULL);
474 ok(!ret && GetLastError() == HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED),
475 "Expected HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED), got %08lx\n",
478 /* Create a new memory store */
479 store2 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
480 CERT_STORE_CREATE_NEW_FLAG, NULL);
481 /* Try adding a store to a non-collection store */
482 ret = CertAddStoreToCollection(store1, store2,
483 CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
484 ok(!ret && GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
485 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
487 /* Try adding some bogus stores */
488 /* This crashes in Windows
489 ret = CertAddStoreToCollection(0, store2,
490 CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
492 /* This "succeeds"... */
493 ret = CertAddStoreToCollection(collection, 0,
494 CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
495 ok(ret, "CertAddStoreToCollection failed: %08lx\n", GetLastError());
496 /* while this crashes.
497 ret = CertAddStoreToCollection(collection, 1,
498 CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
501 /* Add it to the collection, this time allowing adding */
502 ret = CertAddStoreToCollection(collection, store2,
503 CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
504 ok(ret, "CertAddStoreToCollection failed: %08lx\n", GetLastError());
505 /* Check that adding to the collection is allowed */
506 ret = CertAddEncodedCertificateToStore(collection, X509_ASN_ENCODING,
507 bigCert2, sizeof(bigCert2), CERT_STORE_ADD_ALWAYS, NULL);
508 ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\n", GetLastError());
509 /* Now check that it was actually added to store2 */
510 context = CertEnumCertificatesInStore(store2, NULL);
511 ok(context != NULL, "Expected a valid context\n");
514 ok(context->hCertStore == store2, "Unexpected store\n");
515 CertFreeCertificateContext(context);
517 /* Check that the collection has both bigCert and bigCert2. bigCert comes
518 * first because store1 was added first.
520 context = CertEnumCertificatesInStore(collection, NULL);
521 ok(context != NULL, "Expected a valid context\n");
524 ok(context->hCertStore == collection, "Unexpected store\n");
525 ok(context->cbCertEncoded == sizeof(bigCert),
526 "Expected size %d, got %ld\n", sizeof(bigCert),
527 context->cbCertEncoded);
528 ok(!memcmp(context->pbCertEncoded, bigCert, context->cbCertEncoded),
529 "Unexpected cert\n");
530 context = CertEnumCertificatesInStore(collection, context);
531 ok(context != NULL, "Expected a valid context\n");
534 ok(context->hCertStore == collection, "Unexpected store\n");
535 ok(context->cbCertEncoded == sizeof(bigCert2),
536 "Expected size %d, got %ld\n", sizeof(bigCert2),
537 context->cbCertEncoded);
538 ok(!memcmp(context->pbCertEncoded, bigCert2,
539 context->cbCertEncoded), "Unexpected cert\n");
540 context = CertEnumCertificatesInStore(collection, context);
541 ok(!context, "Unexpected cert\n");
544 /* close store2, and check that the collection is unmodified */
545 CertCloseStore(store2, 0);
546 context = CertEnumCertificatesInStore(collection, NULL);
547 ok(context != NULL, "Expected a valid context\n");
550 ok(context->hCertStore == collection, "Unexpected store\n");
551 ok(context->cbCertEncoded == sizeof(bigCert),
552 "Expected size %d, got %ld\n", sizeof(bigCert),
553 context->cbCertEncoded);
554 ok(!memcmp(context->pbCertEncoded, bigCert, context->cbCertEncoded),
555 "Unexpected cert\n");
556 context = CertEnumCertificatesInStore(collection, context);
557 ok(context != NULL, "Expected a valid context\n");
560 ok(context->hCertStore == collection, "Unexpected store\n");
561 ok(context->cbCertEncoded == sizeof(bigCert2),
562 "Expected size %d, got %ld\n", sizeof(bigCert2),
563 context->cbCertEncoded);
564 ok(!memcmp(context->pbCertEncoded, bigCert2,
565 context->cbCertEncoded), "Unexpected cert\n");
566 context = CertEnumCertificatesInStore(collection, context);
567 ok(!context, "Unexpected cert\n");
571 /* Adding a collection to a collection is legal */
572 collection2 = CertOpenStore(CERT_STORE_PROV_COLLECTION, 0, 0,
573 CERT_STORE_CREATE_NEW_FLAG, NULL);
574 ret = CertAddStoreToCollection(collection2, collection,
575 CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
576 ok(ret, "CertAddStoreToCollection failed: %08lx\n", GetLastError());
577 /* check the contents of collection2 */
578 context = CertEnumCertificatesInStore(collection2, NULL);
579 ok(context != NULL, "Expected a valid context\n");
582 ok(context->hCertStore == collection2, "Unexpected store\n");
583 ok(context->cbCertEncoded == sizeof(bigCert),
584 "Expected size %d, got %ld\n", sizeof(bigCert),
585 context->cbCertEncoded);
586 ok(!memcmp(context->pbCertEncoded, bigCert, context->cbCertEncoded),
587 "Unexpected cert\n");
588 context = CertEnumCertificatesInStore(collection2, context);
589 ok(context != NULL, "Expected a valid context\n");
592 ok(context->hCertStore == collection2, "Unexpected store\n");
593 ok(context->cbCertEncoded == sizeof(bigCert2),
594 "Expected size %d, got %ld\n", sizeof(bigCert2),
595 context->cbCertEncoded);
596 ok(!memcmp(context->pbCertEncoded, bigCert2,
597 context->cbCertEncoded), "Unexpected cert\n");
598 context = CertEnumCertificatesInStore(collection2, context);
599 ok(!context, "Unexpected cert\n");
603 /* I'd like to test closing the collection in the middle of enumeration,
604 * but my tests have been inconsistent. The first time calling
605 * CertEnumCertificatesInStore on a closed collection succeeded, while the
606 * second crashed. So anything appears to be fair game.
607 * I'd also like to test removing a store from a collection in the middle
608 * of an enumeration, but my tests in Windows have been inconclusive.
609 * In one scenario it worked. In another scenario, about a third of the
610 * time this leads to "random" crashes elsewhere in the code. This
611 * probably means this is not allowed.
614 CertCloseStore(store1, 0);
615 CertCloseStore(collection, 0);
616 CertCloseStore(collection2, 0);
618 /* Add the same cert to two memory stores, then put them in a collection */
619 store1 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
620 CERT_STORE_CREATE_NEW_FLAG, NULL);
621 ok(store1 != 0, "CertOpenStore failed: %08lx\n", GetLastError());
622 store2 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
623 CERT_STORE_CREATE_NEW_FLAG, NULL);
624 ok(store2 != 0, "CertOpenStore failed: %08lx\n", GetLastError());
626 ret = CertAddEncodedCertificateToStore(store1, X509_ASN_ENCODING,
627 bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, NULL);
628 ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\n", GetLastError());
629 ret = CertAddEncodedCertificateToStore(store2, X509_ASN_ENCODING,
630 bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, NULL);
631 ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\n", GetLastError());
632 collection = CertOpenStore(CERT_STORE_PROV_COLLECTION, 0, 0,
633 CERT_STORE_CREATE_NEW_FLAG, NULL);
634 ok(collection != 0, "CertOpenStore failed: %08lx\n", GetLastError());
636 ret = CertAddStoreToCollection(collection, store1,
637 CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
638 ok(ret, "CertAddStoreToCollection failed: %08lx\n", GetLastError());
639 ret = CertAddStoreToCollection(collection, store2,
640 CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
641 ok(ret, "CertAddStoreToCollection failed: %08lx\n", GetLastError());
643 /* Check that the collection has two copies of the same cert */
644 context = CertEnumCertificatesInStore(collection, NULL);
645 ok(context != NULL, "Expected a valid context\n");
648 ok(context->hCertStore == collection, "Unexpected store\n");
649 ok(context->cbCertEncoded == sizeof(bigCert),
650 "Expected size %d, got %ld\n", sizeof(bigCert),
651 context->cbCertEncoded);
652 ok(!memcmp(context->pbCertEncoded, bigCert, context->cbCertEncoded),
653 "Unexpected cert\n");
654 context = CertEnumCertificatesInStore(collection, context);
655 ok(context != NULL, "Expected a valid context\n");
658 ok(context->hCertStore == collection, "Unexpected store\n");
659 ok(context->cbCertEncoded == sizeof(bigCert),
660 "Expected size %d, got %ld\n", sizeof(bigCert),
661 context->cbCertEncoded);
662 ok(!memcmp(context->pbCertEncoded, bigCert, context->cbCertEncoded),
663 "Unexpected cert\n");
664 context = CertEnumCertificatesInStore(collection, context);
665 ok(context == NULL, "Unexpected cert\n");
669 /* The following would check whether I can delete an identical cert, rather
670 * than one enumerated from the store. It crashes, so that means I must
671 * only call CertDeleteCertificateFromStore with contexts enumerated from
673 context = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert,
675 ok(context != NULL, "CertCreateCertificateContext failed: %08lx\n",
679 ret = CertDeleteCertificateFromStore(collection, context);
680 printf("ret is %d, GetLastError is %08lx\n", ret, GetLastError());
681 CertFreeCertificateContext(context);
685 /* Now check deleting from the collection. */
686 context = CertEnumCertificatesInStore(collection, NULL);
687 ok(context != NULL, "Expected a valid context\n");
690 CertDeleteCertificateFromStore(context);
691 /* store1 should now be empty */
692 context = CertEnumCertificatesInStore(store1, NULL);
693 ok(!context, "Unexpected cert\n");
694 /* and there should be one certificate in the collection */
695 context = CertEnumCertificatesInStore(collection, NULL);
696 ok(context != NULL, "Expected a valid cert\n");
699 ok(context->hCertStore == collection, "Unexpected store\n");
700 ok(context->cbCertEncoded == sizeof(bigCert),
701 "Expected size %d, got %ld\n", sizeof(bigCert),
702 context->cbCertEncoded);
703 ok(!memcmp(context->pbCertEncoded, bigCert, context->cbCertEncoded),
704 "Unexpected cert\n");
706 context = CertEnumCertificatesInStore(collection, context);
707 ok(context == NULL, "Unexpected cert\n");
710 /* Finally, test removing stores from the collection. No return value, so
711 * it's a bit funny to test.
714 CertRemoveStoreFromCollection(NULL, NULL);
716 /* This "succeeds," no crash, no last error set */
717 SetLastError(0xdeadbeef);
718 CertRemoveStoreFromCollection(store2, collection);
719 ok(GetLastError() == 0xdeadbeef,
720 "Didn't expect an error to be set: %08lx\n", GetLastError());
722 /* After removing store2, the collection should be empty */
723 SetLastError(0xdeadbeef);
724 CertRemoveStoreFromCollection(collection, store2);
725 ok(GetLastError() == 0xdeadbeef,
726 "Didn't expect an error to be set: %08lx\n", GetLastError());
727 context = CertEnumCertificatesInStore(collection, NULL);
728 ok(!context, "Unexpected cert\n");
730 CertCloseStore(collection, 0);
731 CertCloseStore(store2, 0);
732 CertCloseStore(store1, 0);
735 /* Looks for the property with ID propID in the buffer buf. Returns a pointer
736 * to its header if found, NULL if not.
738 static const struct CertPropIDHeader *findPropID(const BYTE *buf, DWORD size,
741 const struct CertPropIDHeader *ret = NULL;
744 while (size && !ret && !failed)
746 if (size < sizeof(struct CertPropIDHeader))
750 const struct CertPropIDHeader *hdr =
751 (const struct CertPropIDHeader *)buf;
753 size -= sizeof(struct CertPropIDHeader);
754 buf += sizeof(struct CertPropIDHeader);
757 else if (hdr->propID == propID)
769 typedef DWORD (WINAPI *SHDeleteKeyAFunc)(HKEY, LPCSTR);
771 static void testRegStore(void)
773 static const char tempKey[] = "Software\\Wine\\CryptTemp";
779 store = CertOpenStore(CERT_STORE_PROV_REG, 0, 0, 0, NULL);
780 ok(!store && GetLastError() == ERROR_INVALID_HANDLE,
781 "Expected ERROR_INVALID_HANDLE, got %ld\n", GetLastError());
782 store = CertOpenStore(CERT_STORE_PROV_REG, 0, 0, 0, key);
783 ok(!store && GetLastError() == ERROR_INVALID_HANDLE,
784 "Expected ERROR_INVALID_HANDLE, got %ld\n", GetLastError());
786 /* Opening up any old key works.. */
787 key = HKEY_CURRENT_USER;
788 store = CertOpenStore(CERT_STORE_PROV_REG, 0, 0, 0, key);
789 /* Not sure if this is a bug in DuplicateHandle, marking todo_wine for now
791 todo_wine ok(store != 0, "CertOpenStore failed: %08lx\n", GetLastError());
792 CertCloseStore(store, 0);
794 rc = RegCreateKeyExA(HKEY_CURRENT_USER, tempKey, 0, NULL, 0, KEY_ALL_ACCESS,
796 ok(!rc, "RegCreateKeyExA failed: %ld\n", rc);
802 static const char certificates[] = "Certificates\\";
803 char subKeyName[sizeof(certificates) + 20 * 2 + 1], *ptr;
805 PCCERT_CONTEXT context;
807 store = CertOpenStore(CERT_STORE_PROV_REG, 0, 0, 0, key);
808 ok(store != 0, "CertOpenStore failed: %08lx\n", GetLastError());
809 /* Add a certificate. It isn't persisted right away, since it's only
810 * added to the cache..
812 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
813 bigCert2, sizeof(bigCert2), CERT_STORE_ADD_ALWAYS, NULL);
814 ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\n",
816 /* so flush the cache to force a commit.. */
817 ret = CertControlStore(store, 0, CERT_STORE_CTRL_COMMIT, NULL);
818 ok(ret, "CertControlStore failed: %08lx\n", GetLastError());
819 /* and check that the expected subkey was written. */
821 ret = CryptHashCertificate(0, 0, 0, bigCert2, sizeof(bigCert2),
823 ok(ret, "CryptHashCertificate failed: %ld\n", GetLastError());
824 strcpy(subKeyName, certificates);
825 for (i = 0, ptr = subKeyName + sizeof(certificates) - 1; i < size;
827 sprintf(ptr, "%02X", hash[i]);
828 rc = RegCreateKeyExA(key, subKeyName, 0, NULL, 0, KEY_ALL_ACCESS, NULL,
830 ok(!rc, "RegCreateKeyExA failed: %ld\n", rc);
836 RegQueryValueExA(subKey, "Blob", NULL, NULL, NULL, &size);
837 buf = HeapAlloc(GetProcessHeap(), 0, size);
840 rc = RegQueryValueExA(subKey, "Blob", NULL, NULL, buf, &size);
841 ok(!rc, "RegQueryValueExA failed: %ld\n", rc);
844 const struct CertPropIDHeader *hdr;
846 /* Both the hash and the cert should be present */
847 hdr = findPropID(buf, size, CERT_CERT_PROP_ID);
848 ok(hdr != NULL, "Expected to find a cert property\n");
851 ok(hdr->cb == sizeof(bigCert2),
852 "Unexpected size %ld of cert property, expected %d\n",
853 hdr->cb, sizeof(bigCert2));
854 ok(!memcmp((BYTE *)hdr + sizeof(*hdr), bigCert2,
855 hdr->cb), "Unexpected cert in cert property\n");
857 hdr = findPropID(buf, size, CERT_HASH_PROP_ID);
858 ok(hdr != NULL, "Expected to find a hash property\n");
861 ok(hdr->cb == sizeof(hash),
862 "Unexpected size %ld of hash property, expected %d\n",
863 hdr->cb, sizeof(hash));
864 ok(!memcmp((BYTE *)hdr + sizeof(*hdr), hash,
865 hdr->cb), "Unexpected hash in cert property\n");
868 HeapFree(GetProcessHeap(), 0, buf);
873 /* Remove the existing context */
874 context = CertEnumCertificatesInStore(store, NULL);
875 ok(context != NULL, "Expected a cert context\n");
877 CertDeleteCertificateFromStore(context);
878 ret = CertControlStore(store, 0, CERT_STORE_CTRL_COMMIT, NULL);
879 ok(ret, "CertControlStore failed: %08lx\n", GetLastError());
881 /* Add a serialized cert with a bogus hash directly to the registry */
882 memset(hash, 0, sizeof(hash));
883 strcpy(subKeyName, certificates);
884 for (i = 0, ptr = subKeyName + sizeof(certificates) - 1;
885 i < sizeof(hash); i++, ptr += 2)
886 sprintf(ptr, "%02X", hash[i]);
887 rc = RegCreateKeyExA(key, subKeyName, 0, NULL, 0, KEY_ALL_ACCESS, NULL,
889 ok(!rc, "RegCreateKeyExA failed: %ld\n", rc);
892 BYTE buf[sizeof(struct CertPropIDHeader) * 2 + sizeof(hash) +
893 sizeof(bigCert)], *ptr;
895 struct CertPropIDHeader *hdr;
897 hdr = (struct CertPropIDHeader *)buf;
898 hdr->propID = CERT_HASH_PROP_ID;
900 hdr->cb = sizeof(hash);
901 ptr = buf + sizeof(*hdr);
902 memcpy(ptr, hash, sizeof(hash));
904 hdr = (struct CertPropIDHeader *)ptr;
905 hdr->propID = CERT_CERT_PROP_ID;
907 hdr->cb = sizeof(bigCert);
909 memcpy(ptr, bigCert, sizeof(bigCert));
911 rc = RegSetValueExA(subKey, "Blob", 0, REG_BINARY, buf,
913 ok(!rc, "RegSetValueExA failed: %ld\n", rc);
915 ret = CertControlStore(store, 0, CERT_STORE_CTRL_RESYNC, NULL);
916 ok(ret, "CertControlStore failed: %08lx\n", GetLastError());
918 /* Make sure the bogus hash cert gets loaded. */
922 context = CertEnumCertificatesInStore(store, context);
925 } while (context != NULL);
926 ok(certCount == 1, "Expected 1 certificates, got %ld\n", certCount);
931 /* Add another serialized cert directly to the registry, this time
932 * under the correct key name (named with the correct hash value).
935 ret = CryptHashCertificate(0, 0, 0, bigCert2,
936 sizeof(bigCert2), hash, &size);
937 ok(ret, "CryptHashCertificate failed: %ld\n", GetLastError());
938 strcpy(subKeyName, certificates);
939 for (i = 0, ptr = subKeyName + sizeof(certificates) - 1;
940 i < sizeof(hash); i++, ptr += 2)
941 sprintf(ptr, "%02X", hash[i]);
942 rc = RegCreateKeyExA(key, subKeyName, 0, NULL, 0, KEY_ALL_ACCESS, NULL,
944 ok(!rc, "RegCreateKeyExA failed: %ld\n", rc);
947 BYTE buf[sizeof(struct CertPropIDHeader) * 2 + sizeof(hash) +
948 sizeof(bigCert2)], *ptr;
950 PCCERT_CONTEXT context;
951 struct CertPropIDHeader *hdr;
953 /* First try with a bogus hash... */
954 hdr = (struct CertPropIDHeader *)buf;
955 hdr->propID = CERT_HASH_PROP_ID;
957 hdr->cb = sizeof(hash);
958 ptr = buf + sizeof(*hdr);
959 memset(ptr, 0, sizeof(hash));
961 hdr = (struct CertPropIDHeader *)ptr;
962 hdr->propID = CERT_CERT_PROP_ID;
964 hdr->cb = sizeof(bigCert2);
966 memcpy(ptr, bigCert2, sizeof(bigCert2));
968 rc = RegSetValueExA(subKey, "Blob", 0, REG_BINARY, buf,
970 ok(!rc, "RegSetValueExA failed: %ld\n", rc);
972 ret = CertControlStore(store, 0, CERT_STORE_CTRL_RESYNC, NULL);
973 ok(ret, "CertControlStore failed: %08lx\n", GetLastError());
975 /* and make sure just one cert still gets loaded. */
979 context = CertEnumCertificatesInStore(store, context);
982 } while (context != NULL);
983 ok(certCount == 1, "Expected 1 certificates, got %ld\n", certCount);
985 /* Try again with the correct hash... */
986 ptr = buf + sizeof(*hdr);
987 memcpy(ptr, hash, sizeof(hash));
989 rc = RegSetValueExA(subKey, "Blob", 0, REG_BINARY, buf,
991 ok(!rc, "RegSetValueExA failed: %ld\n", rc);
993 ret = CertControlStore(store, 0, CERT_STORE_CTRL_RESYNC, NULL);
994 ok(ret, "CertControlStore failed: %08lx\n", GetLastError());
996 /* and make sure two certs get loaded. */
1000 context = CertEnumCertificatesInStore(store, context);
1003 } while (context != NULL);
1004 ok(certCount == 2, "Expected 2 certificates, got %ld\n", certCount);
1006 RegCloseKey(subKey);
1008 CertCloseStore(store, 0);
1009 /* Is delete allowed on a reg store? */
1010 store = CertOpenStore(CERT_STORE_PROV_REG, 0, 0,
1011 CERT_STORE_DELETE_FLAG, key);
1012 ok(store == NULL, "Expected NULL return from CERT_STORE_DELETE_FLAG\n");
1013 ok(GetLastError() == 0, "CertOpenStore failed: %08lx\n",
1018 /* The CertOpenStore with CERT_STORE_DELETE_FLAG above will delete the
1019 * contents of the key, but not the key itself.
1021 rc = RegCreateKeyExA(HKEY_CURRENT_USER, tempKey, 0, NULL, 0, KEY_ALL_ACCESS,
1023 ok(!rc, "RegCreateKeyExA failed: %ld\n", rc);
1024 ok(disp == REG_OPENED_EXISTING_KEY,
1025 "Expected REG_OPENED_EXISTING_KEY, got %ld\n", disp);
1029 rc = RegDeleteKeyA(HKEY_CURRENT_USER, tempKey);
1032 HMODULE shlwapi = LoadLibraryA("shlwapi");
1034 /* Use shlwapi's SHDeleteKeyA to _really_ blow away the key,
1035 * otherwise subsequent tests will fail.
1039 SHDeleteKeyAFunc pSHDeleteKeyA =
1040 (SHDeleteKeyAFunc)GetProcAddress(shlwapi, "SHDeleteKeyA");
1043 pSHDeleteKeyA(HKEY_CURRENT_USER, tempKey);
1044 FreeLibrary(shlwapi);
1050 static const char MyA[] = { 'M','y',0,0 };
1051 static const WCHAR MyW[] = { 'M','y',0 };
1052 static const WCHAR BogusW[] = { 'B','o','g','u','s',0 };
1053 static const WCHAR BogusPathW[] = { 'S','o','f','t','w','a','r','e','\\',
1054 'M','i','c','r','o','s','o','f','t','\\','S','y','s','t','e','m','C','e','r',
1055 't','i','f','i','c','a','t','e','s','\\','B','o','g','u','s',0 };
1057 static void testSystemRegStore(void)
1059 HCERTSTORE store, memStore;
1061 /* Check with a UNICODE name */
1062 store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY, 0, 0,
1063 CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_OPEN_EXISTING_FLAG, MyW);
1064 /* Not all OSes support CERT_STORE_PROV_SYSTEM_REGISTRY, so don't continue
1065 * testing if they don't.
1070 /* Check that it isn't a collection store */
1071 memStore = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
1072 CERT_STORE_CREATE_NEW_FLAG, NULL);
1075 BOOL ret = CertAddStoreToCollection(store, memStore, 0, 0);
1077 ok(!ret && GetLastError() ==
1078 HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
1079 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
1081 CertCloseStore(memStore, 0);
1083 CertCloseStore(store, 0);
1085 /* Check opening a bogus store */
1086 store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY, 0, 0,
1087 CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_OPEN_EXISTING_FLAG, BogusW);
1088 ok(!store && GetLastError() == ERROR_FILE_NOT_FOUND,
1089 "Expected ERROR_FILE_NOT_FOUND, got %08lx\n", GetLastError());
1090 store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY, 0, 0,
1091 CERT_SYSTEM_STORE_CURRENT_USER, BogusW);
1092 ok(store != 0, "CertOpenStore failed: %08lx\n", GetLastError());
1094 CertCloseStore(store, 0);
1095 /* Now check whether deleting is allowed */
1096 store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY, 0, 0,
1097 CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_DELETE_FLAG, BogusW);
1098 RegDeleteKeyW(HKEY_CURRENT_USER, BogusPathW);
1100 store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY, 0, 0, 0, NULL);
1101 ok(!store && GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
1102 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
1104 store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY, 0, 0,
1105 CERT_SYSTEM_STORE_LOCAL_MACHINE | CERT_SYSTEM_STORE_CURRENT_USER, MyA);
1106 ok(!store && GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
1107 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
1109 store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY, 0, 0,
1110 CERT_SYSTEM_STORE_LOCAL_MACHINE | CERT_SYSTEM_STORE_CURRENT_USER, MyW);
1111 ok(!store && GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
1112 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
1114 /* The name is expected to be UNICODE, check with an ASCII name */
1115 store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY, 0, 0,
1116 CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_OPEN_EXISTING_FLAG, MyA);
1117 ok(!store && GetLastError() == ERROR_FILE_NOT_FOUND,
1118 "Expected ERROR_FILE_NOT_FOUND, got %08lx\n", GetLastError());
1121 static void testSystemStore(void)
1123 static const WCHAR baskslashW[] = { '\\',0 };
1125 WCHAR keyName[MAX_PATH];
1129 store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0, 0, NULL);
1130 ok(!store && GetLastError() == ERROR_FILE_NOT_FOUND,
1131 "Expected ERROR_FILE_NOT_FOUND, got %08lx\n", GetLastError());
1132 store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0,
1133 CERT_SYSTEM_STORE_LOCAL_MACHINE | CERT_SYSTEM_STORE_CURRENT_USER, MyA);
1134 ok(!store && GetLastError() == ERROR_FILE_NOT_FOUND,
1135 "Expected ERROR_FILE_NOT_FOUND, got %08lx\n", GetLastError());
1136 store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0,
1137 CERT_SYSTEM_STORE_LOCAL_MACHINE | CERT_SYSTEM_STORE_CURRENT_USER, MyW);
1138 ok(!store && GetLastError() == ERROR_FILE_NOT_FOUND,
1139 "Expected ERROR_FILE_NOT_FOUND, got %08lx\n", GetLastError());
1140 /* The name is expected to be UNICODE, first check with an ASCII name */
1141 store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0,
1142 CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_OPEN_EXISTING_FLAG, MyA);
1143 ok(!store && GetLastError() == ERROR_FILE_NOT_FOUND,
1144 "Expected ERROR_FILE_NOT_FOUND, got %08lx\n", GetLastError());
1145 /* Create the expected key */
1146 lstrcpyW(keyName, CERT_LOCAL_MACHINE_SYSTEM_STORE_REGPATH);
1147 lstrcatW(keyName, baskslashW);
1148 lstrcatW(keyName, MyW);
1149 rc = RegCreateKeyExW(HKEY_CURRENT_USER, keyName, 0, NULL, 0, KEY_READ,
1151 ok(!rc, "RegCreateKeyEx failed: %ld\n", rc);
1154 /* Check opening with a UNICODE name, specifying the create new flag */
1155 store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0,
1156 CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_CREATE_NEW_FLAG, MyW);
1157 ok(!store && GetLastError() == ERROR_FILE_EXISTS,
1158 "Expected ERROR_FILE_EXISTS, got %08lx\n", GetLastError());
1159 /* Now check opening with a UNICODE name, this time opening existing */
1160 store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0,
1161 CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_OPEN_EXISTING_FLAG, MyW);
1162 ok(store != 0, "CertOpenStore failed: %08lx\n", GetLastError());
1165 HCERTSTORE memStore = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
1166 CERT_STORE_CREATE_NEW_FLAG, NULL);
1168 /* Check that it's a collection store */
1171 BOOL ret = CertAddStoreToCollection(store, memStore, 0, 0);
1173 /* FIXME: this'll fail on NT4, but what error will it give? */
1174 ok(ret, "CertAddStoreToCollection failed: %08lx\n", GetLastError());
1175 CertCloseStore(memStore, 0);
1177 CertCloseStore(store, 0);
1180 /* Check opening a bogus store */
1181 store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0,
1182 CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_OPEN_EXISTING_FLAG, BogusW);
1183 ok(!store && GetLastError() == ERROR_FILE_NOT_FOUND,
1184 "Expected ERROR_FILE_NOT_FOUND, got %08lx\n", GetLastError());
1185 store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0,
1186 CERT_SYSTEM_STORE_CURRENT_USER, BogusW);
1187 ok(store != 0, "CertOpenStore failed: %08lx\n", GetLastError());
1189 CertCloseStore(store, 0);
1190 /* Now check whether deleting is allowed */
1191 store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0,
1192 CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_DELETE_FLAG, BogusW);
1193 RegDeleteKeyW(HKEY_CURRENT_USER, BogusPathW);
1196 static void testCertOpenSystemStore(void)
1200 store = CertOpenSystemStoreW(0, NULL);
1201 ok(!store && GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
1202 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
1204 /* This succeeds, and on WinXP at least, the Bogus key is created under
1205 * HKCU (but not under HKLM, even when run as an administrator.)
1207 store = CertOpenSystemStoreW(0, BogusW);
1208 ok(store != 0, "CertOpenSystemStore failed: %08lx\n", GetLastError());
1210 CertCloseStore(store, 0);
1211 /* Delete it so other tests succeed next time around */
1212 store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0,
1213 CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_DELETE_FLAG, BogusW);
1214 RegDeleteKeyW(HKEY_CURRENT_USER, BogusPathW);
1217 static void checkHash(const BYTE *data, DWORD dataLen, ALG_ID algID,
1218 PCCERT_CONTEXT context, DWORD propID)
1220 BYTE hash[20] = { 0 }, hashProperty[20];
1224 memset(hash, 0, sizeof(hash));
1225 memset(hashProperty, 0, sizeof(hashProperty));
1226 size = sizeof(hash);
1227 ret = CryptHashCertificate(0, algID, 0, data, dataLen, hash, &size);
1228 ok(ret, "CryptHashCertificate failed: %08lx\n", GetLastError());
1229 ret = CertGetCertificateContextProperty(context, propID, hashProperty,
1231 ok(ret, "CertGetCertificateContextProperty failed: %08lx\n",
1233 ok(!memcmp(hash, hashProperty, size), "Unexpected hash for property %ld\n",
1237 static void testCertProperties(void)
1239 PCCERT_CONTEXT context = CertCreateCertificateContext(X509_ASN_ENCODING,
1240 bigCert, sizeof(bigCert));
1242 ok(context != NULL, "CertCreateCertificateContext failed: %08lx\n",
1246 DWORD propID, numProps, access, size;
1248 BYTE hash[20] = { 0 }, hashProperty[20];
1249 CRYPT_DATA_BLOB blob;
1252 propID = CertEnumCertificateContextProperties(NULL, 0);
1258 propID = CertEnumCertificateContextProperties(context, propID);
1261 } while (propID != 0);
1262 ok(numProps == 0, "Expected 0 properties, got %ld\n", numProps);
1264 /* Tests with a NULL cert context. Prop ID 0 fails.. */
1265 ret = CertSetCertificateContextProperty(NULL, 0, 0, NULL);
1266 ok(!ret && GetLastError() ==
1267 HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
1268 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
1270 /* while this just crashes.
1271 ret = CertSetCertificateContextProperty(NULL,
1272 CERT_KEY_PROV_HANDLE_PROP_ID, 0, NULL);
1275 ret = CertSetCertificateContextProperty(context, 0, 0, NULL);
1276 ok(!ret && GetLastError() ==
1277 HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
1278 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
1280 /* Can't set the cert property directly, this crashes.
1281 ret = CertSetCertificateContextProperty(context,
1282 CERT_CERT_PROP_ID, 0, bigCert2);
1286 ret = CertGetCertificateContextProperty(context,
1287 CERT_ACCESS_STATE_PROP_ID, 0, NULL);
1288 ret = CertGetCertificateContextProperty(context, CERT_HASH_PROP_ID,
1290 ret = CertGetCertificateContextProperty(context, CERT_HASH_PROP_ID,
1291 hashProperty, NULL);
1293 /* A missing prop */
1295 ret = CertGetCertificateContextProperty(context,
1296 CERT_KEY_PROV_INFO_PROP_ID, NULL, &size);
1297 ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
1298 "Expected CRYPT_E_NOT_FOUND, got %08lx\n", GetLastError());
1299 /* And, an implicit property */
1300 size = sizeof(access);
1301 ret = CertGetCertificateContextProperty(context,
1302 CERT_ACCESS_STATE_PROP_ID, &access, &size);
1303 ok(ret, "CertGetCertificateContextProperty failed: %08lx\n",
1305 ok(!(access & CERT_ACCESS_STATE_WRITE_PERSIST_FLAG),
1306 "Didn't expect a persisted cert\n");
1307 /* Trying to set this "read only" property crashes.
1308 access |= CERT_ACCESS_STATE_WRITE_PERSIST_FLAG;
1309 ret = CertSetCertificateContextProperty(context,
1310 CERT_ACCESS_STATE_PROP_ID, 0, &access);
1313 /* Can I set the hash to an invalid hash? */
1315 blob.cbData = sizeof(hash);
1316 ret = CertSetCertificateContextProperty(context, CERT_HASH_PROP_ID, 0,
1318 ok(ret, "CertSetCertificateContextProperty failed: %08lx\n",
1320 size = sizeof(hashProperty);
1321 ret = CertGetCertificateContextProperty(context, CERT_HASH_PROP_ID,
1322 hashProperty, &size);
1323 ok(!memcmp(hashProperty, hash, sizeof(hash)), "Unexpected hash\n");
1324 /* Delete the (bogus) hash, and get the real one */
1325 ret = CertSetCertificateContextProperty(context, CERT_HASH_PROP_ID, 0,
1327 ok(ret, "CertSetCertificateContextProperty failed: %08lx\n",
1329 checkHash(bigCert, sizeof(bigCert), CALG_SHA1, context,
1332 /* Now that the hash property is set, we should get one property when
1338 propID = CertEnumCertificateContextProperties(context, propID);
1341 } while (propID != 0);
1342 ok(numProps == 1, "Expected 1 properties, got %ld\n", numProps);
1344 /* Check a few other implicit properties */
1345 checkHash(bigCert, sizeof(bigCert), CALG_MD5, context,
1346 CERT_MD5_HASH_PROP_ID);
1348 context->pCertInfo->Subject.pbData,
1349 context->pCertInfo->Subject.cbData,
1350 CALG_MD5, context, CERT_SUBJECT_NAME_MD5_HASH_PROP_ID);
1352 context->pCertInfo->SubjectPublicKeyInfo.PublicKey.pbData,
1353 context->pCertInfo->SubjectPublicKeyInfo.PublicKey.cbData,
1354 CALG_MD5, context, CERT_SUBJECT_PUBLIC_KEY_MD5_HASH_PROP_ID);
1356 /* Odd: this doesn't fail on other certificates, so there must be
1357 * something weird about this cert that causes it to fail.
1360 ret = CertGetCertificateContextProperty(context,
1361 CERT_KEY_IDENTIFIER_PROP_ID, NULL, &size);
1362 todo_wine ok(!ret && GetLastError() == ERROR_INVALID_DATA,
1363 "Expected ERROR_INVALID_DATA, got %08lx\n", GetLastError());
1365 CertFreeCertificateContext(context);
1369 static void testAddSerialized(void)
1373 BYTE buf[sizeof(struct CertPropIDHeader) * 2 + 20 + sizeof(bigCert)] =
1376 struct CertPropIDHeader *hdr;
1377 PCCERT_CONTEXT context;
1379 ret = CertAddSerializedElementToStore(0, NULL, 0, 0, 0, 0, NULL, NULL);
1380 ok(!ret && GetLastError() == ERROR_END_OF_MEDIA,
1381 "Expected ERROR_END_OF_MEDIA, got %08lx\n", GetLastError());
1383 store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
1384 CERT_STORE_CREATE_NEW_FLAG, NULL);
1385 ok(store != 0, "CertOpenStore failed: %08lx\n", GetLastError());
1387 ret = CertAddSerializedElementToStore(store, NULL, 0, 0, 0, 0, NULL, NULL);
1388 ok(!ret && GetLastError() == ERROR_END_OF_MEDIA,
1389 "Expected ERROR_END_OF_MEDIA, got %08lx\n", GetLastError());
1391 /* Test with an empty property */
1392 hdr = (struct CertPropIDHeader *)buf;
1393 hdr->propID = CERT_CERT_PROP_ID;
1396 ret = CertAddSerializedElementToStore(store, buf, sizeof(buf), 0, 0, 0,
1398 ok(!ret && GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
1399 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
1401 /* Test with a bad size in property header */
1402 hdr->cb = sizeof(bigCert) - 1;
1403 memcpy(buf + sizeof(struct CertPropIDHeader), bigCert, sizeof(bigCert));
1404 ret = CertAddSerializedElementToStore(store, buf, sizeof(buf), 0, 0, 0,
1406 ok(!ret && GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
1407 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
1409 ret = CertAddSerializedElementToStore(store, buf,
1410 sizeof(struct CertPropIDHeader) + sizeof(bigCert), 0, 0, 0, NULL,
1412 ok(!ret && GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
1413 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
1415 ret = CertAddSerializedElementToStore(store, buf,
1416 sizeof(struct CertPropIDHeader) + sizeof(bigCert), CERT_STORE_ADD_NEW,
1418 ok(!ret && GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
1419 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
1421 /* Kosher size in property header, but no context type */
1422 hdr->cb = sizeof(bigCert);
1423 ret = CertAddSerializedElementToStore(store, buf, sizeof(buf), 0, 0, 0,
1425 ok(!ret && GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
1426 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
1428 ret = CertAddSerializedElementToStore(store, buf,
1429 sizeof(struct CertPropIDHeader) + sizeof(bigCert), 0, 0, 0, NULL,
1431 ok(!ret && GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
1432 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
1434 ret = CertAddSerializedElementToStore(store, buf,
1435 sizeof(struct CertPropIDHeader) + sizeof(bigCert), CERT_STORE_ADD_NEW,
1437 ok(!ret && GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
1438 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
1440 /* With a bad context type */
1441 ret = CertAddSerializedElementToStore(store, buf, sizeof(buf), 0, 0,
1442 CERT_STORE_CRL_CONTEXT_FLAG, NULL, NULL);
1443 ok(!ret && GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
1444 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
1446 ret = CertAddSerializedElementToStore(store, buf,
1447 sizeof(struct CertPropIDHeader) + sizeof(bigCert), 0, 0,
1448 CERT_STORE_CRL_CONTEXT_FLAG, NULL, NULL);
1449 ok(!ret && GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
1450 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
1452 ret = CertAddSerializedElementToStore(store, buf,
1453 sizeof(struct CertPropIDHeader) + sizeof(bigCert), CERT_STORE_ADD_NEW,
1454 0, CERT_STORE_CRL_CONTEXT_FLAG, NULL, NULL);
1455 ok(!ret && GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
1456 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
1458 /* Bad unknown field, good type */
1460 ret = CertAddSerializedElementToStore(store, buf, sizeof(buf), 0, 0,
1461 CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL, NULL);
1462 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
1463 "Expected ERROR_FILE_NOT_FOUND got %08lx\n", GetLastError());
1464 ret = CertAddSerializedElementToStore(store, buf,
1465 sizeof(struct CertPropIDHeader) + sizeof(bigCert), 0, 0,
1466 CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL, NULL);
1467 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
1468 "Expected ERROR_FILE_NOT_FOUND got %08lx\n", GetLastError());
1469 ret = CertAddSerializedElementToStore(store, buf,
1470 sizeof(struct CertPropIDHeader) + sizeof(bigCert), CERT_STORE_ADD_NEW,
1471 0, CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL, NULL);
1472 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
1473 "Expected ERROR_FILE_NOT_FOUND got %08lx\n", GetLastError());
1474 /* Most everything okay, but bad add disposition */
1477 ret = CertAddSerializedElementToStore(store, buf, sizeof(buf), 0, 0,
1478 CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL, NULL);
1480 ret = CertAddSerializedElementToStore(store, buf,
1481 sizeof(struct CertPropIDHeader) + sizeof(bigCert), 0, 0,
1482 CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL, NULL);
1484 /* Everything okay, but buffer's too big */
1485 ret = CertAddSerializedElementToStore(store, buf, sizeof(buf),
1486 CERT_STORE_ADD_NEW, 0, CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL, NULL);
1487 ok(ret, "CertAddSerializedElementToStore failed: %08lx\n", GetLastError());
1488 /* Everything okay, check it's not re-added */
1489 ret = CertAddSerializedElementToStore(store, buf,
1490 sizeof(struct CertPropIDHeader) + sizeof(bigCert), CERT_STORE_ADD_NEW,
1491 0, CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL, NULL);
1492 ok(!ret && GetLastError() == CRYPT_E_EXISTS,
1493 "Expected CRYPT_E_EXISTS, got %08lx\n", GetLastError());
1495 context = CertEnumCertificatesInStore(store, NULL);
1496 ok(context != NULL, "Expected a cert\n");
1498 CertDeleteCertificateFromStore(context);
1500 /* Try adding with a bogus hash. Oddly enough, it succeeds, and the hash,
1501 * when queried, is the real hash rather than the bogus hash.
1503 hdr = (struct CertPropIDHeader *)(buf + sizeof(struct CertPropIDHeader) +
1505 hdr->propID = CERT_HASH_PROP_ID;
1507 hdr->cb = sizeof(hash);
1508 memset(hash, 0xc, sizeof(hash));
1509 memcpy((LPBYTE)hdr + sizeof(struct CertPropIDHeader), hash, sizeof(hash));
1510 ret = CertAddSerializedElementToStore(store, buf, sizeof(buf),
1511 CERT_STORE_ADD_NEW, 0, CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL,
1512 (const void **)&context);
1513 ok(ret, "CertAddSerializedElementToStore failed: %08lx\n", GetLastError());
1516 BYTE hashVal[20], realHash[20];
1517 DWORD size = sizeof(hashVal);
1519 ret = CryptHashCertificate(0, 0, 0, bigCert, sizeof(bigCert),
1521 ok(ret, "CryptHashCertificate failed: %08lx\n", GetLastError());
1522 ret = CertGetCertificateContextProperty(context, CERT_HASH_PROP_ID,
1524 ok(ret, "CertGetCertificateContextProperty failed: %08lx\n",
1526 ok(!memcmp(hashVal, realHash, size), "Unexpected hash\n");
1527 CertFreeCertificateContext(context);
1530 CertCloseStore(store, 0);
1538 /* various combinations of CertOpenStore */
1540 testCollectionStore();
1542 testSystemRegStore();
1545 testCertOpenSystemStore();
1547 testCertProperties();
1548 testAddSerialized();