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 testGetSubjectCert(void)
268 store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
269 CERT_STORE_CREATE_NEW_FLAG, NULL);
270 ok(store != NULL, "CertOpenStore failed: %ld\n", GetLastError());
273 PCCERT_CONTEXT context1, context2;
274 CERT_INFO info = { 0 };
277 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
278 bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, NULL);
279 ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\n",
281 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
282 bigCert2, sizeof(bigCert2), CERT_STORE_ADD_NEW, &context1);
283 ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\n",
285 ok(context1 != NULL, "Expected a context\n");
286 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
287 certWithUsage, sizeof(certWithUsage), CERT_STORE_ADD_NEW, NULL);
288 ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\n",
291 context2 = CertGetSubjectCertificateFromStore(store, X509_ASN_ENCODING,
293 ok(!context2 && GetLastError() ==
294 HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
295 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
297 context2 = CertGetSubjectCertificateFromStore(store, X509_ASN_ENCODING,
299 ok(!context2 && GetLastError() == CRYPT_E_NOT_FOUND,
300 "Expected CRYPT_E_NOT_FOUND, got %08lx\n", GetLastError());
301 info.SerialNumber.cbData = sizeof(serialNum);
302 info.SerialNumber.pbData = (LPBYTE)serialNum;
303 context2 = CertGetSubjectCertificateFromStore(store, X509_ASN_ENCODING,
305 ok(!context2 && GetLastError() == CRYPT_E_NOT_FOUND,
306 "Expected CRYPT_E_NOT_FOUND, got %08lx\n", GetLastError());
307 info.Issuer.cbData = sizeof(subjectName2);
308 info.Issuer.pbData = (LPBYTE)subjectName2;
309 context2 = CertGetSubjectCertificateFromStore(store, X509_ASN_ENCODING,
312 "CertGetSubjectCertificateFromStore failed: %08lx\n", GetLastError());
313 /* Not only should this find a context, but it should be the same
314 * (same address) as context1.
316 ok(context1 == context2, "Expected identical context addresses\n");
317 CertFreeCertificateContext(context2);
319 CertFreeCertificateContext(context1);
320 CertCloseStore(store, 0);
324 static void testMemStore(void)
326 HCERTSTORE store1, store2;
327 PCCERT_CONTEXT context;
331 store1 = CertOpenStore(0, 0, 0, 0, NULL);
332 ok(!store1 && GetLastError() == ERROR_FILE_NOT_FOUND,
333 "Expected ERROR_FILE_NOT_FOUND, got %ld\n", GetLastError());
335 store1 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
336 CERT_STORE_DELETE_FLAG, NULL);
337 ok(!store1 && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED,
338 "Expected ERROR_CALL_NOT_IMPLEMENTED, got %ld\n", GetLastError());
341 store1 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
342 CERT_STORE_CREATE_NEW_FLAG, NULL);
343 ok(store1 != NULL, "CertOpenStore failed: %ld\n", GetLastError());
344 /* open existing doesn't */
345 store2 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
346 CERT_STORE_OPEN_EXISTING_FLAG, NULL);
347 ok(store2 != NULL, "CertOpenStore failed: %ld\n", GetLastError());
348 ok(store1 != store2, "Expected different stores\n");
350 /* add a bogus (empty) cert */
352 ret = CertAddEncodedCertificateToStore(store1, X509_ASN_ENCODING, emptyCert,
353 sizeof(emptyCert), CERT_STORE_ADD_ALWAYS, &context);
354 /* Windows returns CRYPT_E_ASN1_EOD, but accept CRYPT_E_ASN1_CORRUPT as
355 * well (because matching errors is tough in this case)
357 ok(!ret && (GetLastError() == CRYPT_E_ASN1_EOD || GetLastError() ==
358 CRYPT_E_ASN1_CORRUPT),
359 "Expected CRYPT_E_ASN1_EOD or CRYPT_E_ASN1_CORRUPT, got %08lx\n",
361 /* add a "signed" cert--the signature isn't a real signature, so this adds
362 * without any check of the signature's validity
364 ret = CertAddEncodedCertificateToStore(store1, X509_ASN_ENCODING,
365 signedBigCert, sizeof(signedBigCert), CERT_STORE_ADD_ALWAYS, &context);
366 ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\n", GetLastError());
367 ok(context != NULL, "Expected a valid cert context\n");
370 ok(context->cbCertEncoded == sizeof(signedBigCert),
371 "Expected cert of %d bytes, got %ld\n", sizeof(signedBigCert),
372 context->cbCertEncoded);
373 ok(!memcmp(context->pbCertEncoded, signedBigCert,
374 sizeof(signedBigCert)), "Unexpected encoded cert in context\n");
375 /* remove it, the rest of the tests will work on an unsigned cert */
376 ret = CertDeleteCertificateFromStore(context);
377 ok(ret, "CertDeleteCertificateFromStore failed: %08lx\n",
380 /* try adding a "signed" CRL as a cert */
381 ret = CertAddEncodedCertificateToStore(store1, X509_ASN_ENCODING,
382 signedCRL, sizeof(signedCRL), CERT_STORE_ADD_ALWAYS, &context);
383 ok(!ret && (GetLastError() == CRYPT_E_ASN1_BADTAG || GetLastError() ==
384 CRYPT_E_ASN1_CORRUPT),
385 "Expected CRYPT_E_ASN1_BADTAG or CRYPT_E_ASN1_CORRUPT, got %08lx\n",
387 /* add a cert to store1 */
388 ret = CertAddEncodedCertificateToStore(store1, X509_ASN_ENCODING, bigCert,
389 sizeof(bigCert), CERT_STORE_ADD_ALWAYS, &context);
390 ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\n", GetLastError());
391 ok(context != NULL, "Expected a valid cert context\n");
397 ok(context->cbCertEncoded == sizeof(bigCert),
398 "Expected cert of %d bytes, got %ld\n", sizeof(bigCert),
399 context->cbCertEncoded);
400 ok(!memcmp(context->pbCertEncoded, bigCert, sizeof(bigCert)),
401 "Unexpected encoded cert in context\n");
402 ok(context->hCertStore == store1, "Unexpected store\n");
404 /* check serializing this element */
406 ret = CertSerializeCertificateStoreElement(NULL, 0, NULL, NULL);
407 ret = CertSerializeCertificateStoreElement(context, 0, NULL, NULL);
408 ret = CertSerializeCertificateStoreElement(NULL, 0, NULL, &size);
410 /* apparently flags are ignored */
411 ret = CertSerializeCertificateStoreElement(context, 1, NULL, &size);
412 ok(ret, "CertSerializeCertificateStoreElement failed: %08lx\n",
414 buf = HeapAlloc(GetProcessHeap(), 0, size);
417 ret = CertSerializeCertificateStoreElement(context, 0, buf, &size);
418 ok(size == sizeof(serializedCert), "Expected size %d, got %ld\n",
419 sizeof(serializedCert), size);
420 ok(!memcmp(serializedCert, buf, size),
421 "Unexpected serialized cert\n");
422 HeapFree(GetProcessHeap(), 0, buf);
425 ret = CertFreeCertificateContext(context);
426 ok(ret, "CertFreeCertificateContext failed: %08lx\n", GetLastError());
428 /* verify the cert's in store1 */
429 context = CertEnumCertificatesInStore(store1, NULL);
430 ok(context != NULL, "Expected a valid context\n");
431 context = CertEnumCertificatesInStore(store1, context);
432 ok(!context && GetLastError() == CRYPT_E_NOT_FOUND,
433 "Expected CRYPT_E_NOT_FOUND, got %08lx\n", GetLastError());
434 /* verify store2 (the "open existing" mem store) is still empty */
435 context = CertEnumCertificatesInStore(store2, NULL);
436 ok(!context, "Expected an empty store\n");
437 /* delete the cert from store1, and check it's empty */
438 context = CertEnumCertificatesInStore(store1, NULL);
441 /* Deleting a bitwise copy crashes with an access to an uninitialized
442 * pointer, so a cert context has some special data out there in memory
445 memcpy(©, context, sizeof(copy));
446 ret = CertDeleteCertificateFromStore(©);
448 PCCERT_CONTEXT copy = CertDuplicateCertificateContext(context);
450 ok(copy != NULL, "CertDuplicateCertificateContext failed: %08lx\n",
452 ret = CertDeleteCertificateFromStore(context);
453 ok(ret, "CertDeleteCertificateFromStore failed: %08lx\n",
455 /* try deleting a copy */
456 ret = CertDeleteCertificateFromStore(copy);
457 ok(ret, "CertDeleteCertificateFromStore failed: %08lx\n",
459 /* check that the store is empty */
460 context = CertEnumCertificatesInStore(store1, NULL);
461 ok(!context, "Expected an empty store\n");
464 /* close an empty store */
465 ret = CertCloseStore(NULL, 0);
466 ok(ret, "CertCloseStore failed: %ld\n", GetLastError());
467 ret = CertCloseStore(store1, 0);
468 ok(ret, "CertCloseStore failed: %ld\n", GetLastError());
469 ret = CertCloseStore(store2, 0);
470 ok(ret, "CertCloseStore failed: %ld\n", GetLastError());
472 /* This seems nonsensical, but you can open a read-only mem store, only
475 store1 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
476 CERT_STORE_READONLY_FLAG, NULL);
477 ok(store1 != NULL, "CertOpenStore failed: %ld\n", GetLastError());
478 /* yep, this succeeds */
479 ret = CertAddEncodedCertificateToStore(store1, X509_ASN_ENCODING, bigCert,
480 sizeof(bigCert), CERT_STORE_ADD_ALWAYS, &context);
481 ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\n", GetLastError());
482 ok(context != NULL, "Expected a valid cert context\n");
485 ok(context->cbCertEncoded == sizeof(bigCert),
486 "Expected cert of %d bytes, got %ld\n", sizeof(bigCert),
487 context->cbCertEncoded);
488 ok(!memcmp(context->pbCertEncoded, bigCert, sizeof(bigCert)),
489 "Unexpected encoded cert in context\n");
490 ok(context->hCertStore == store1, "Unexpected store\n");
491 ret = CertDeleteCertificateFromStore(context);
492 ok(ret, "CertDeleteCertificateFromStore failed: %08lx\n",
495 CertCloseStore(store1, 0);
498 static void testCollectionStore(void)
500 HCERTSTORE store1, store2, collection, collection2;
501 PCCERT_CONTEXT context;
504 collection = CertOpenStore(CERT_STORE_PROV_COLLECTION, 0, 0,
505 CERT_STORE_CREATE_NEW_FLAG, NULL);
507 /* Try adding a cert to any empty collection */
508 ret = CertAddEncodedCertificateToStore(collection, X509_ASN_ENCODING,
509 bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, NULL);
510 ok(!ret && GetLastError() == HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED),
511 "Expected HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED), got %08lx\n",
514 /* Create and add a cert to a memory store */
515 store1 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
516 CERT_STORE_CREATE_NEW_FLAG, NULL);
517 ret = CertAddEncodedCertificateToStore(store1, X509_ASN_ENCODING,
518 bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, NULL);
519 ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\n", GetLastError());
520 /* Add the memory store to the collection, without allowing adding */
521 ret = CertAddStoreToCollection(collection, store1, 0, 0);
522 ok(ret, "CertAddStoreToCollection failed: %08lx\n", GetLastError());
523 /* Verify the cert is in the collection */
524 context = CertEnumCertificatesInStore(collection, NULL);
525 ok(context != NULL, "Expected a valid context\n");
528 ok(context->hCertStore == collection, "Unexpected store\n");
529 CertFreeCertificateContext(context);
531 /* Check that adding to the collection isn't allowed */
532 ret = CertAddEncodedCertificateToStore(collection, X509_ASN_ENCODING,
533 bigCert2, sizeof(bigCert2), CERT_STORE_ADD_ALWAYS, NULL);
534 ok(!ret && GetLastError() == HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED),
535 "Expected HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED), got %08lx\n",
538 /* Create a new memory store */
539 store2 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
540 CERT_STORE_CREATE_NEW_FLAG, NULL);
541 /* Try adding a store to a non-collection store */
542 ret = CertAddStoreToCollection(store1, store2,
543 CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
544 ok(!ret && GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
545 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
547 /* Try adding some bogus stores */
548 /* This crashes in Windows
549 ret = CertAddStoreToCollection(0, store2,
550 CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
552 /* This "succeeds"... */
553 ret = CertAddStoreToCollection(collection, 0,
554 CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
555 ok(ret, "CertAddStoreToCollection failed: %08lx\n", GetLastError());
556 /* while this crashes.
557 ret = CertAddStoreToCollection(collection, 1,
558 CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
561 /* Add it to the collection, this time allowing adding */
562 ret = CertAddStoreToCollection(collection, store2,
563 CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
564 ok(ret, "CertAddStoreToCollection failed: %08lx\n", GetLastError());
565 /* Check that adding to the collection is allowed */
566 ret = CertAddEncodedCertificateToStore(collection, X509_ASN_ENCODING,
567 bigCert2, sizeof(bigCert2), CERT_STORE_ADD_ALWAYS, NULL);
568 ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\n", GetLastError());
569 /* Now check that it was actually added to store2 */
570 context = CertEnumCertificatesInStore(store2, NULL);
571 ok(context != NULL, "Expected a valid context\n");
574 ok(context->hCertStore == store2, "Unexpected store\n");
575 CertFreeCertificateContext(context);
577 /* Check that the collection has both bigCert and bigCert2. bigCert comes
578 * first because store1 was added first.
580 context = CertEnumCertificatesInStore(collection, NULL);
581 ok(context != NULL, "Expected a valid context\n");
584 ok(context->hCertStore == collection, "Unexpected store\n");
585 ok(context->cbCertEncoded == sizeof(bigCert),
586 "Expected size %d, got %ld\n", sizeof(bigCert),
587 context->cbCertEncoded);
588 ok(!memcmp(context->pbCertEncoded, bigCert, context->cbCertEncoded),
589 "Unexpected cert\n");
590 context = CertEnumCertificatesInStore(collection, context);
591 ok(context != NULL, "Expected a valid context\n");
594 ok(context->hCertStore == collection, "Unexpected store\n");
595 ok(context->cbCertEncoded == sizeof(bigCert2),
596 "Expected size %d, got %ld\n", sizeof(bigCert2),
597 context->cbCertEncoded);
598 ok(!memcmp(context->pbCertEncoded, bigCert2,
599 context->cbCertEncoded), "Unexpected cert\n");
600 context = CertEnumCertificatesInStore(collection, context);
601 ok(!context, "Unexpected cert\n");
604 /* close store2, and check that the collection is unmodified */
605 CertCloseStore(store2, 0);
606 context = CertEnumCertificatesInStore(collection, NULL);
607 ok(context != NULL, "Expected a valid context\n");
610 ok(context->hCertStore == collection, "Unexpected store\n");
611 ok(context->cbCertEncoded == sizeof(bigCert),
612 "Expected size %d, got %ld\n", sizeof(bigCert),
613 context->cbCertEncoded);
614 ok(!memcmp(context->pbCertEncoded, bigCert, context->cbCertEncoded),
615 "Unexpected cert\n");
616 context = CertEnumCertificatesInStore(collection, context);
617 ok(context != NULL, "Expected a valid context\n");
620 ok(context->hCertStore == collection, "Unexpected store\n");
621 ok(context->cbCertEncoded == sizeof(bigCert2),
622 "Expected size %d, got %ld\n", sizeof(bigCert2),
623 context->cbCertEncoded);
624 ok(!memcmp(context->pbCertEncoded, bigCert2,
625 context->cbCertEncoded), "Unexpected cert\n");
626 context = CertEnumCertificatesInStore(collection, context);
627 ok(!context, "Unexpected cert\n");
631 /* Adding a collection to a collection is legal */
632 collection2 = CertOpenStore(CERT_STORE_PROV_COLLECTION, 0, 0,
633 CERT_STORE_CREATE_NEW_FLAG, NULL);
634 ret = CertAddStoreToCollection(collection2, collection,
635 CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
636 ok(ret, "CertAddStoreToCollection failed: %08lx\n", GetLastError());
637 /* check the contents of collection2 */
638 context = CertEnumCertificatesInStore(collection2, NULL);
639 ok(context != NULL, "Expected a valid context\n");
642 ok(context->hCertStore == collection2, "Unexpected store\n");
643 ok(context->cbCertEncoded == sizeof(bigCert),
644 "Expected size %d, got %ld\n", sizeof(bigCert),
645 context->cbCertEncoded);
646 ok(!memcmp(context->pbCertEncoded, bigCert, context->cbCertEncoded),
647 "Unexpected cert\n");
648 context = CertEnumCertificatesInStore(collection2, context);
649 ok(context != NULL, "Expected a valid context\n");
652 ok(context->hCertStore == collection2, "Unexpected store\n");
653 ok(context->cbCertEncoded == sizeof(bigCert2),
654 "Expected size %d, got %ld\n", sizeof(bigCert2),
655 context->cbCertEncoded);
656 ok(!memcmp(context->pbCertEncoded, bigCert2,
657 context->cbCertEncoded), "Unexpected cert\n");
658 context = CertEnumCertificatesInStore(collection2, context);
659 ok(!context, "Unexpected cert\n");
663 /* I'd like to test closing the collection in the middle of enumeration,
664 * but my tests have been inconsistent. The first time calling
665 * CertEnumCertificatesInStore on a closed collection succeeded, while the
666 * second crashed. So anything appears to be fair game.
667 * I'd also like to test removing a store from a collection in the middle
668 * of an enumeration, but my tests in Windows have been inconclusive.
669 * In one scenario it worked. In another scenario, about a third of the
670 * time this leads to "random" crashes elsewhere in the code. This
671 * probably means this is not allowed.
674 CertCloseStore(store1, 0);
675 CertCloseStore(collection, 0);
676 CertCloseStore(collection2, 0);
678 /* Add the same cert to two memory stores, then put them in a collection */
679 store1 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
680 CERT_STORE_CREATE_NEW_FLAG, NULL);
681 ok(store1 != 0, "CertOpenStore failed: %08lx\n", GetLastError());
682 store2 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
683 CERT_STORE_CREATE_NEW_FLAG, NULL);
684 ok(store2 != 0, "CertOpenStore failed: %08lx\n", GetLastError());
686 ret = CertAddEncodedCertificateToStore(store1, X509_ASN_ENCODING,
687 bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, NULL);
688 ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\n", GetLastError());
689 ret = CertAddEncodedCertificateToStore(store2, X509_ASN_ENCODING,
690 bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, NULL);
691 ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\n", GetLastError());
692 collection = CertOpenStore(CERT_STORE_PROV_COLLECTION, 0, 0,
693 CERT_STORE_CREATE_NEW_FLAG, NULL);
694 ok(collection != 0, "CertOpenStore failed: %08lx\n", GetLastError());
696 ret = CertAddStoreToCollection(collection, store1,
697 CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
698 ok(ret, "CertAddStoreToCollection failed: %08lx\n", GetLastError());
699 ret = CertAddStoreToCollection(collection, store2,
700 CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
701 ok(ret, "CertAddStoreToCollection failed: %08lx\n", GetLastError());
703 /* Check that the collection has two copies of the same cert */
704 context = CertEnumCertificatesInStore(collection, NULL);
705 ok(context != NULL, "Expected a valid context\n");
708 ok(context->hCertStore == collection, "Unexpected store\n");
709 ok(context->cbCertEncoded == sizeof(bigCert),
710 "Expected size %d, got %ld\n", sizeof(bigCert),
711 context->cbCertEncoded);
712 ok(!memcmp(context->pbCertEncoded, bigCert, context->cbCertEncoded),
713 "Unexpected cert\n");
714 context = CertEnumCertificatesInStore(collection, context);
715 ok(context != NULL, "Expected a valid context\n");
718 ok(context->hCertStore == collection, "Unexpected store\n");
719 ok(context->cbCertEncoded == sizeof(bigCert),
720 "Expected size %d, got %ld\n", sizeof(bigCert),
721 context->cbCertEncoded);
722 ok(!memcmp(context->pbCertEncoded, bigCert, context->cbCertEncoded),
723 "Unexpected cert\n");
724 context = CertEnumCertificatesInStore(collection, context);
725 ok(context == NULL, "Unexpected cert\n");
729 /* The following would check whether I can delete an identical cert, rather
730 * than one enumerated from the store. It crashes, so that means I must
731 * only call CertDeleteCertificateFromStore with contexts enumerated from
733 context = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert,
735 ok(context != NULL, "CertCreateCertificateContext failed: %08lx\n",
739 ret = CertDeleteCertificateFromStore(collection, context);
740 printf("ret is %d, GetLastError is %08lx\n", ret, GetLastError());
741 CertFreeCertificateContext(context);
745 /* Now check deleting from the collection. */
746 context = CertEnumCertificatesInStore(collection, NULL);
747 ok(context != NULL, "Expected a valid context\n");
750 CertDeleteCertificateFromStore(context);
751 /* store1 should now be empty */
752 context = CertEnumCertificatesInStore(store1, NULL);
753 ok(!context, "Unexpected cert\n");
754 /* and there should be one certificate in the collection */
755 context = CertEnumCertificatesInStore(collection, NULL);
756 ok(context != NULL, "Expected a valid cert\n");
759 ok(context->hCertStore == collection, "Unexpected store\n");
760 ok(context->cbCertEncoded == sizeof(bigCert),
761 "Expected size %d, got %ld\n", sizeof(bigCert),
762 context->cbCertEncoded);
763 ok(!memcmp(context->pbCertEncoded, bigCert, context->cbCertEncoded),
764 "Unexpected cert\n");
766 context = CertEnumCertificatesInStore(collection, context);
767 ok(context == NULL, "Unexpected cert\n");
770 /* Finally, test removing stores from the collection. No return value, so
771 * it's a bit funny to test.
774 CertRemoveStoreFromCollection(NULL, NULL);
776 /* This "succeeds," no crash, no last error set */
777 SetLastError(0xdeadbeef);
778 CertRemoveStoreFromCollection(store2, collection);
779 ok(GetLastError() == 0xdeadbeef,
780 "Didn't expect an error to be set: %08lx\n", GetLastError());
782 /* After removing store2, the collection should be empty */
783 SetLastError(0xdeadbeef);
784 CertRemoveStoreFromCollection(collection, store2);
785 ok(GetLastError() == 0xdeadbeef,
786 "Didn't expect an error to be set: %08lx\n", GetLastError());
787 context = CertEnumCertificatesInStore(collection, NULL);
788 ok(!context, "Unexpected cert\n");
790 CertCloseStore(collection, 0);
791 CertCloseStore(store2, 0);
792 CertCloseStore(store1, 0);
795 /* Looks for the property with ID propID in the buffer buf. Returns a pointer
796 * to its header if found, NULL if not.
798 static const struct CertPropIDHeader *findPropID(const BYTE *buf, DWORD size,
801 const struct CertPropIDHeader *ret = NULL;
804 while (size && !ret && !failed)
806 if (size < sizeof(struct CertPropIDHeader))
810 const struct CertPropIDHeader *hdr =
811 (const struct CertPropIDHeader *)buf;
813 size -= sizeof(struct CertPropIDHeader);
814 buf += sizeof(struct CertPropIDHeader);
817 else if (hdr->propID == propID)
829 typedef DWORD (WINAPI *SHDeleteKeyAFunc)(HKEY, LPCSTR);
831 static void testRegStore(void)
833 static const char tempKey[] = "Software\\Wine\\CryptTemp";
839 store = CertOpenStore(CERT_STORE_PROV_REG, 0, 0, 0, NULL);
840 ok(!store && GetLastError() == ERROR_INVALID_HANDLE,
841 "Expected ERROR_INVALID_HANDLE, got %ld\n", GetLastError());
842 store = CertOpenStore(CERT_STORE_PROV_REG, 0, 0, 0, key);
843 ok(!store && GetLastError() == ERROR_INVALID_HANDLE,
844 "Expected ERROR_INVALID_HANDLE, got %ld\n", GetLastError());
846 /* Opening up any old key works.. */
847 key = HKEY_CURRENT_USER;
848 store = CertOpenStore(CERT_STORE_PROV_REG, 0, 0, 0, key);
849 /* Not sure if this is a bug in DuplicateHandle, marking todo_wine for now
851 todo_wine ok(store != 0, "CertOpenStore failed: %08lx\n", GetLastError());
852 CertCloseStore(store, 0);
854 rc = RegCreateKeyExA(HKEY_CURRENT_USER, tempKey, 0, NULL, 0, KEY_ALL_ACCESS,
856 ok(!rc, "RegCreateKeyExA failed: %ld\n", rc);
862 static const char certificates[] = "Certificates\\";
863 char subKeyName[sizeof(certificates) + 20 * 2 + 1], *ptr;
865 PCCERT_CONTEXT context;
867 store = CertOpenStore(CERT_STORE_PROV_REG, 0, 0, 0, key);
868 ok(store != 0, "CertOpenStore failed: %08lx\n", GetLastError());
869 /* Add a certificate. It isn't persisted right away, since it's only
870 * added to the cache..
872 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
873 bigCert2, sizeof(bigCert2), CERT_STORE_ADD_ALWAYS, NULL);
874 ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\n",
876 /* so flush the cache to force a commit.. */
877 ret = CertControlStore(store, 0, CERT_STORE_CTRL_COMMIT, NULL);
878 ok(ret, "CertControlStore failed: %08lx\n", GetLastError());
879 /* and check that the expected subkey was written. */
881 ret = CryptHashCertificate(0, 0, 0, bigCert2, sizeof(bigCert2),
883 ok(ret, "CryptHashCertificate failed: %ld\n", GetLastError());
884 strcpy(subKeyName, certificates);
885 for (i = 0, ptr = subKeyName + sizeof(certificates) - 1; i < size;
887 sprintf(ptr, "%02X", hash[i]);
888 rc = RegCreateKeyExA(key, subKeyName, 0, NULL, 0, KEY_ALL_ACCESS, NULL,
890 ok(!rc, "RegCreateKeyExA failed: %ld\n", rc);
896 RegQueryValueExA(subKey, "Blob", NULL, NULL, NULL, &size);
897 buf = HeapAlloc(GetProcessHeap(), 0, size);
900 rc = RegQueryValueExA(subKey, "Blob", NULL, NULL, buf, &size);
901 ok(!rc, "RegQueryValueExA failed: %ld\n", rc);
904 const struct CertPropIDHeader *hdr;
906 /* Both the hash and the cert should be present */
907 hdr = findPropID(buf, size, CERT_CERT_PROP_ID);
908 ok(hdr != NULL, "Expected to find a cert property\n");
911 ok(hdr->cb == sizeof(bigCert2),
912 "Unexpected size %ld of cert property, expected %d\n",
913 hdr->cb, sizeof(bigCert2));
914 ok(!memcmp((BYTE *)hdr + sizeof(*hdr), bigCert2,
915 hdr->cb), "Unexpected cert in cert property\n");
917 hdr = findPropID(buf, size, CERT_HASH_PROP_ID);
918 ok(hdr != NULL, "Expected to find a hash property\n");
921 ok(hdr->cb == sizeof(hash),
922 "Unexpected size %ld of hash property, expected %d\n",
923 hdr->cb, sizeof(hash));
924 ok(!memcmp((BYTE *)hdr + sizeof(*hdr), hash,
925 hdr->cb), "Unexpected hash in cert property\n");
928 HeapFree(GetProcessHeap(), 0, buf);
933 /* Remove the existing context */
934 context = CertEnumCertificatesInStore(store, NULL);
935 ok(context != NULL, "Expected a cert context\n");
937 CertDeleteCertificateFromStore(context);
938 ret = CertControlStore(store, 0, CERT_STORE_CTRL_COMMIT, NULL);
939 ok(ret, "CertControlStore failed: %08lx\n", GetLastError());
941 /* Add a serialized cert with a bogus hash directly to the registry */
942 memset(hash, 0, sizeof(hash));
943 strcpy(subKeyName, certificates);
944 for (i = 0, ptr = subKeyName + sizeof(certificates) - 1;
945 i < sizeof(hash); i++, ptr += 2)
946 sprintf(ptr, "%02X", hash[i]);
947 rc = RegCreateKeyExA(key, subKeyName, 0, NULL, 0, KEY_ALL_ACCESS, NULL,
949 ok(!rc, "RegCreateKeyExA failed: %ld\n", rc);
952 BYTE buf[sizeof(struct CertPropIDHeader) * 2 + sizeof(hash) +
953 sizeof(bigCert)], *ptr;
955 struct CertPropIDHeader *hdr;
957 hdr = (struct CertPropIDHeader *)buf;
958 hdr->propID = CERT_HASH_PROP_ID;
960 hdr->cb = sizeof(hash);
961 ptr = buf + sizeof(*hdr);
962 memcpy(ptr, hash, sizeof(hash));
964 hdr = (struct CertPropIDHeader *)ptr;
965 hdr->propID = CERT_CERT_PROP_ID;
967 hdr->cb = sizeof(bigCert);
969 memcpy(ptr, bigCert, sizeof(bigCert));
971 rc = RegSetValueExA(subKey, "Blob", 0, REG_BINARY, buf,
973 ok(!rc, "RegSetValueExA failed: %ld\n", rc);
975 ret = CertControlStore(store, 0, CERT_STORE_CTRL_RESYNC, NULL);
976 ok(ret, "CertControlStore failed: %08lx\n", GetLastError());
978 /* Make sure the bogus hash cert gets loaded. */
982 context = CertEnumCertificatesInStore(store, context);
985 } while (context != NULL);
986 ok(certCount == 1, "Expected 1 certificates, got %ld\n", certCount);
991 /* Add another serialized cert directly to the registry, this time
992 * under the correct key name (named with the correct hash value).
995 ret = CryptHashCertificate(0, 0, 0, bigCert2,
996 sizeof(bigCert2), hash, &size);
997 ok(ret, "CryptHashCertificate failed: %ld\n", GetLastError());
998 strcpy(subKeyName, certificates);
999 for (i = 0, ptr = subKeyName + sizeof(certificates) - 1;
1000 i < sizeof(hash); i++, ptr += 2)
1001 sprintf(ptr, "%02X", hash[i]);
1002 rc = RegCreateKeyExA(key, subKeyName, 0, NULL, 0, KEY_ALL_ACCESS, NULL,
1004 ok(!rc, "RegCreateKeyExA failed: %ld\n", rc);
1007 BYTE buf[sizeof(struct CertPropIDHeader) * 2 + sizeof(hash) +
1008 sizeof(bigCert2)], *ptr;
1009 DWORD certCount = 0;
1010 PCCERT_CONTEXT context;
1011 struct CertPropIDHeader *hdr;
1013 /* First try with a bogus hash... */
1014 hdr = (struct CertPropIDHeader *)buf;
1015 hdr->propID = CERT_HASH_PROP_ID;
1017 hdr->cb = sizeof(hash);
1018 ptr = buf + sizeof(*hdr);
1019 memset(ptr, 0, sizeof(hash));
1020 ptr += sizeof(hash);
1021 hdr = (struct CertPropIDHeader *)ptr;
1022 hdr->propID = CERT_CERT_PROP_ID;
1024 hdr->cb = sizeof(bigCert2);
1025 ptr += sizeof(*hdr);
1026 memcpy(ptr, bigCert2, sizeof(bigCert2));
1028 rc = RegSetValueExA(subKey, "Blob", 0, REG_BINARY, buf,
1030 ok(!rc, "RegSetValueExA failed: %ld\n", rc);
1032 ret = CertControlStore(store, 0, CERT_STORE_CTRL_RESYNC, NULL);
1033 ok(ret, "CertControlStore failed: %08lx\n", GetLastError());
1035 /* and make sure just one cert still gets loaded. */
1039 context = CertEnumCertificatesInStore(store, context);
1042 } while (context != NULL);
1043 ok(certCount == 1, "Expected 1 certificates, got %ld\n", certCount);
1045 /* Try again with the correct hash... */
1046 ptr = buf + sizeof(*hdr);
1047 memcpy(ptr, hash, sizeof(hash));
1049 rc = RegSetValueExA(subKey, "Blob", 0, REG_BINARY, buf,
1051 ok(!rc, "RegSetValueExA failed: %ld\n", rc);
1053 ret = CertControlStore(store, 0, CERT_STORE_CTRL_RESYNC, NULL);
1054 ok(ret, "CertControlStore failed: %08lx\n", GetLastError());
1056 /* and make sure two certs get loaded. */
1060 context = CertEnumCertificatesInStore(store, context);
1063 } while (context != NULL);
1064 ok(certCount == 2, "Expected 2 certificates, got %ld\n", certCount);
1066 RegCloseKey(subKey);
1068 CertCloseStore(store, 0);
1069 /* Is delete allowed on a reg store? */
1070 store = CertOpenStore(CERT_STORE_PROV_REG, 0, 0,
1071 CERT_STORE_DELETE_FLAG, key);
1072 ok(store == NULL, "Expected NULL return from CERT_STORE_DELETE_FLAG\n");
1073 ok(GetLastError() == 0, "CertOpenStore failed: %08lx\n",
1078 /* The CertOpenStore with CERT_STORE_DELETE_FLAG above will delete the
1079 * contents of the key, but not the key itself.
1081 rc = RegCreateKeyExA(HKEY_CURRENT_USER, tempKey, 0, NULL, 0, KEY_ALL_ACCESS,
1083 ok(!rc, "RegCreateKeyExA failed: %ld\n", rc);
1084 ok(disp == REG_OPENED_EXISTING_KEY,
1085 "Expected REG_OPENED_EXISTING_KEY, got %ld\n", disp);
1089 rc = RegDeleteKeyA(HKEY_CURRENT_USER, tempKey);
1092 HMODULE shlwapi = LoadLibraryA("shlwapi");
1094 /* Use shlwapi's SHDeleteKeyA to _really_ blow away the key,
1095 * otherwise subsequent tests will fail.
1099 SHDeleteKeyAFunc pSHDeleteKeyA =
1100 (SHDeleteKeyAFunc)GetProcAddress(shlwapi, "SHDeleteKeyA");
1103 pSHDeleteKeyA(HKEY_CURRENT_USER, tempKey);
1104 FreeLibrary(shlwapi);
1110 static const char MyA[] = { 'M','y',0,0 };
1111 static const WCHAR MyW[] = { 'M','y',0 };
1112 static const WCHAR BogusW[] = { 'B','o','g','u','s',0 };
1113 static const WCHAR BogusPathW[] = { 'S','o','f','t','w','a','r','e','\\',
1114 'M','i','c','r','o','s','o','f','t','\\','S','y','s','t','e','m','C','e','r',
1115 't','i','f','i','c','a','t','e','s','\\','B','o','g','u','s',0 };
1117 static void testSystemRegStore(void)
1119 HCERTSTORE store, memStore;
1121 /* Check with a UNICODE name */
1122 store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY, 0, 0,
1123 CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_OPEN_EXISTING_FLAG, MyW);
1124 /* Not all OSes support CERT_STORE_PROV_SYSTEM_REGISTRY, so don't continue
1125 * testing if they don't.
1130 /* Check that it isn't a collection store */
1131 memStore = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
1132 CERT_STORE_CREATE_NEW_FLAG, NULL);
1135 BOOL ret = CertAddStoreToCollection(store, memStore, 0, 0);
1137 ok(!ret && GetLastError() ==
1138 HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
1139 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
1141 CertCloseStore(memStore, 0);
1143 CertCloseStore(store, 0);
1145 /* Check opening a bogus store */
1146 store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY, 0, 0,
1147 CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_OPEN_EXISTING_FLAG, BogusW);
1148 ok(!store && GetLastError() == ERROR_FILE_NOT_FOUND,
1149 "Expected ERROR_FILE_NOT_FOUND, got %08lx\n", GetLastError());
1150 store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY, 0, 0,
1151 CERT_SYSTEM_STORE_CURRENT_USER, BogusW);
1152 ok(store != 0, "CertOpenStore failed: %08lx\n", GetLastError());
1154 CertCloseStore(store, 0);
1155 /* Now check whether deleting is allowed */
1156 store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY, 0, 0,
1157 CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_DELETE_FLAG, BogusW);
1158 RegDeleteKeyW(HKEY_CURRENT_USER, BogusPathW);
1160 store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY, 0, 0, 0, NULL);
1161 ok(!store && GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
1162 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
1164 store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY, 0, 0,
1165 CERT_SYSTEM_STORE_LOCAL_MACHINE | CERT_SYSTEM_STORE_CURRENT_USER, MyA);
1166 ok(!store && GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
1167 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
1169 store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY, 0, 0,
1170 CERT_SYSTEM_STORE_LOCAL_MACHINE | CERT_SYSTEM_STORE_CURRENT_USER, MyW);
1171 ok(!store && GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
1172 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
1174 /* The name is expected to be UNICODE, check with an ASCII name */
1175 store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY, 0, 0,
1176 CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_OPEN_EXISTING_FLAG, MyA);
1177 ok(!store && GetLastError() == ERROR_FILE_NOT_FOUND,
1178 "Expected ERROR_FILE_NOT_FOUND, got %08lx\n", GetLastError());
1181 static void testSystemStore(void)
1183 static const WCHAR baskslashW[] = { '\\',0 };
1185 WCHAR keyName[MAX_PATH];
1189 store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0, 0, NULL);
1190 ok(!store && GetLastError() == ERROR_FILE_NOT_FOUND,
1191 "Expected ERROR_FILE_NOT_FOUND, got %08lx\n", GetLastError());
1192 store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0,
1193 CERT_SYSTEM_STORE_LOCAL_MACHINE | CERT_SYSTEM_STORE_CURRENT_USER, MyA);
1194 ok(!store && GetLastError() == ERROR_FILE_NOT_FOUND,
1195 "Expected ERROR_FILE_NOT_FOUND, got %08lx\n", GetLastError());
1196 store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0,
1197 CERT_SYSTEM_STORE_LOCAL_MACHINE | CERT_SYSTEM_STORE_CURRENT_USER, MyW);
1198 ok(!store && GetLastError() == ERROR_FILE_NOT_FOUND,
1199 "Expected ERROR_FILE_NOT_FOUND, got %08lx\n", GetLastError());
1200 /* The name is expected to be UNICODE, first check with an ASCII name */
1201 store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0,
1202 CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_OPEN_EXISTING_FLAG, MyA);
1203 ok(!store && GetLastError() == ERROR_FILE_NOT_FOUND,
1204 "Expected ERROR_FILE_NOT_FOUND, got %08lx\n", GetLastError());
1205 /* Create the expected key */
1206 lstrcpyW(keyName, CERT_LOCAL_MACHINE_SYSTEM_STORE_REGPATH);
1207 lstrcatW(keyName, baskslashW);
1208 lstrcatW(keyName, MyW);
1209 rc = RegCreateKeyExW(HKEY_CURRENT_USER, keyName, 0, NULL, 0, KEY_READ,
1211 ok(!rc, "RegCreateKeyEx failed: %ld\n", rc);
1214 /* Check opening with a UNICODE name, specifying the create new flag */
1215 store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0,
1216 CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_CREATE_NEW_FLAG, MyW);
1217 ok(!store && GetLastError() == ERROR_FILE_EXISTS,
1218 "Expected ERROR_FILE_EXISTS, got %08lx\n", GetLastError());
1219 /* Now check opening with a UNICODE name, this time opening existing */
1220 store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0,
1221 CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_OPEN_EXISTING_FLAG, MyW);
1222 ok(store != 0, "CertOpenStore failed: %08lx\n", GetLastError());
1225 HCERTSTORE memStore = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
1226 CERT_STORE_CREATE_NEW_FLAG, NULL);
1228 /* Check that it's a collection store */
1231 BOOL ret = CertAddStoreToCollection(store, memStore, 0, 0);
1233 /* FIXME: this'll fail on NT4, but what error will it give? */
1234 ok(ret, "CertAddStoreToCollection failed: %08lx\n", GetLastError());
1235 CertCloseStore(memStore, 0);
1237 CertCloseStore(store, 0);
1240 /* Check opening a bogus store */
1241 store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0,
1242 CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_OPEN_EXISTING_FLAG, BogusW);
1243 ok(!store && GetLastError() == ERROR_FILE_NOT_FOUND,
1244 "Expected ERROR_FILE_NOT_FOUND, got %08lx\n", GetLastError());
1245 store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0,
1246 CERT_SYSTEM_STORE_CURRENT_USER, BogusW);
1247 ok(store != 0, "CertOpenStore failed: %08lx\n", GetLastError());
1249 CertCloseStore(store, 0);
1250 /* Now check whether deleting is allowed */
1251 store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0,
1252 CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_DELETE_FLAG, BogusW);
1253 RegDeleteKeyW(HKEY_CURRENT_USER, BogusPathW);
1256 static void testCertOpenSystemStore(void)
1260 store = CertOpenSystemStoreW(0, NULL);
1261 ok(!store && GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
1262 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
1264 /* This succeeds, and on WinXP at least, the Bogus key is created under
1265 * HKCU (but not under HKLM, even when run as an administrator.)
1267 store = CertOpenSystemStoreW(0, BogusW);
1268 ok(store != 0, "CertOpenSystemStore failed: %08lx\n", GetLastError());
1270 CertCloseStore(store, 0);
1271 /* Delete it so other tests succeed next time around */
1272 store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0,
1273 CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_DELETE_FLAG, BogusW);
1274 RegDeleteKeyW(HKEY_CURRENT_USER, BogusPathW);
1277 static void checkHash(const BYTE *data, DWORD dataLen, ALG_ID algID,
1278 PCCERT_CONTEXT context, DWORD propID)
1280 BYTE hash[20] = { 0 }, hashProperty[20];
1284 memset(hash, 0, sizeof(hash));
1285 memset(hashProperty, 0, sizeof(hashProperty));
1286 size = sizeof(hash);
1287 ret = CryptHashCertificate(0, algID, 0, data, dataLen, hash, &size);
1288 ok(ret, "CryptHashCertificate failed: %08lx\n", GetLastError());
1289 ret = CertGetCertificateContextProperty(context, propID, hashProperty,
1291 ok(ret, "CertGetCertificateContextProperty failed: %08lx\n",
1293 ok(!memcmp(hash, hashProperty, size), "Unexpected hash for property %ld\n",
1297 static void testCertProperties(void)
1299 PCCERT_CONTEXT context = CertCreateCertificateContext(X509_ASN_ENCODING,
1300 bigCert, sizeof(bigCert));
1302 ok(context != NULL, "CertCreateCertificateContext failed: %08lx\n",
1306 DWORD propID, numProps, access, size;
1308 BYTE hash[20] = { 0 }, hashProperty[20];
1309 CRYPT_DATA_BLOB blob;
1312 propID = CertEnumCertificateContextProperties(NULL, 0);
1318 propID = CertEnumCertificateContextProperties(context, propID);
1321 } while (propID != 0);
1322 ok(numProps == 0, "Expected 0 properties, got %ld\n", numProps);
1324 /* Tests with a NULL cert context. Prop ID 0 fails.. */
1325 ret = CertSetCertificateContextProperty(NULL, 0, 0, NULL);
1326 ok(!ret && GetLastError() ==
1327 HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
1328 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
1330 /* while this just crashes.
1331 ret = CertSetCertificateContextProperty(NULL,
1332 CERT_KEY_PROV_HANDLE_PROP_ID, 0, NULL);
1335 ret = CertSetCertificateContextProperty(context, 0, 0, NULL);
1336 ok(!ret && GetLastError() ==
1337 HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
1338 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
1340 /* Can't set the cert property directly, this crashes.
1341 ret = CertSetCertificateContextProperty(context,
1342 CERT_CERT_PROP_ID, 0, bigCert2);
1346 ret = CertGetCertificateContextProperty(context,
1347 CERT_ACCESS_STATE_PROP_ID, 0, NULL);
1348 ret = CertGetCertificateContextProperty(context, CERT_HASH_PROP_ID,
1350 ret = CertGetCertificateContextProperty(context, CERT_HASH_PROP_ID,
1351 hashProperty, NULL);
1353 /* A missing prop */
1355 ret = CertGetCertificateContextProperty(context,
1356 CERT_KEY_PROV_INFO_PROP_ID, NULL, &size);
1357 ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
1358 "Expected CRYPT_E_NOT_FOUND, got %08lx\n", GetLastError());
1359 /* And, an implicit property */
1360 size = sizeof(access);
1361 ret = CertGetCertificateContextProperty(context,
1362 CERT_ACCESS_STATE_PROP_ID, &access, &size);
1363 ok(ret, "CertGetCertificateContextProperty failed: %08lx\n",
1365 ok(!(access & CERT_ACCESS_STATE_WRITE_PERSIST_FLAG),
1366 "Didn't expect a persisted cert\n");
1367 /* Trying to set this "read only" property crashes.
1368 access |= CERT_ACCESS_STATE_WRITE_PERSIST_FLAG;
1369 ret = CertSetCertificateContextProperty(context,
1370 CERT_ACCESS_STATE_PROP_ID, 0, &access);
1373 /* Can I set the hash to an invalid hash? */
1375 blob.cbData = sizeof(hash);
1376 ret = CertSetCertificateContextProperty(context, CERT_HASH_PROP_ID, 0,
1378 ok(ret, "CertSetCertificateContextProperty failed: %08lx\n",
1380 size = sizeof(hashProperty);
1381 ret = CertGetCertificateContextProperty(context, CERT_HASH_PROP_ID,
1382 hashProperty, &size);
1383 ok(!memcmp(hashProperty, hash, sizeof(hash)), "Unexpected hash\n");
1384 /* Delete the (bogus) hash, and get the real one */
1385 ret = CertSetCertificateContextProperty(context, CERT_HASH_PROP_ID, 0,
1387 ok(ret, "CertSetCertificateContextProperty failed: %08lx\n",
1389 checkHash(bigCert, sizeof(bigCert), CALG_SHA1, context,
1392 /* Now that the hash property is set, we should get one property when
1398 propID = CertEnumCertificateContextProperties(context, propID);
1401 } while (propID != 0);
1402 ok(numProps == 1, "Expected 1 properties, got %ld\n", numProps);
1404 /* Check a few other implicit properties */
1405 checkHash(bigCert, sizeof(bigCert), CALG_MD5, context,
1406 CERT_MD5_HASH_PROP_ID);
1408 context->pCertInfo->Subject.pbData,
1409 context->pCertInfo->Subject.cbData,
1410 CALG_MD5, context, CERT_SUBJECT_NAME_MD5_HASH_PROP_ID);
1412 context->pCertInfo->SubjectPublicKeyInfo.PublicKey.pbData,
1413 context->pCertInfo->SubjectPublicKeyInfo.PublicKey.cbData,
1414 CALG_MD5, context, CERT_SUBJECT_PUBLIC_KEY_MD5_HASH_PROP_ID);
1416 /* Odd: this doesn't fail on other certificates, so there must be
1417 * something weird about this cert that causes it to fail.
1420 ret = CertGetCertificateContextProperty(context,
1421 CERT_KEY_IDENTIFIER_PROP_ID, NULL, &size);
1422 todo_wine ok(!ret && GetLastError() == ERROR_INVALID_DATA,
1423 "Expected ERROR_INVALID_DATA, got %08lx\n", GetLastError());
1425 CertFreeCertificateContext(context);
1429 static void testAddSerialized(void)
1433 BYTE buf[sizeof(struct CertPropIDHeader) * 2 + 20 + sizeof(bigCert)] =
1436 struct CertPropIDHeader *hdr;
1437 PCCERT_CONTEXT context;
1439 ret = CertAddSerializedElementToStore(0, NULL, 0, 0, 0, 0, NULL, NULL);
1440 ok(!ret && GetLastError() == ERROR_END_OF_MEDIA,
1441 "Expected ERROR_END_OF_MEDIA, got %08lx\n", GetLastError());
1443 store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
1444 CERT_STORE_CREATE_NEW_FLAG, NULL);
1445 ok(store != 0, "CertOpenStore failed: %08lx\n", GetLastError());
1447 ret = CertAddSerializedElementToStore(store, NULL, 0, 0, 0, 0, NULL, NULL);
1448 ok(!ret && GetLastError() == ERROR_END_OF_MEDIA,
1449 "Expected ERROR_END_OF_MEDIA, got %08lx\n", GetLastError());
1451 /* Test with an empty property */
1452 hdr = (struct CertPropIDHeader *)buf;
1453 hdr->propID = CERT_CERT_PROP_ID;
1456 ret = CertAddSerializedElementToStore(store, buf, sizeof(buf), 0, 0, 0,
1458 ok(!ret && GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
1459 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
1461 /* Test with a bad size in property header */
1462 hdr->cb = sizeof(bigCert) - 1;
1463 memcpy(buf + sizeof(struct CertPropIDHeader), bigCert, sizeof(bigCert));
1464 ret = CertAddSerializedElementToStore(store, buf, sizeof(buf), 0, 0, 0,
1466 ok(!ret && GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
1467 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
1469 ret = CertAddSerializedElementToStore(store, buf,
1470 sizeof(struct CertPropIDHeader) + sizeof(bigCert), 0, 0, 0, NULL,
1472 ok(!ret && GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
1473 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
1475 ret = CertAddSerializedElementToStore(store, buf,
1476 sizeof(struct CertPropIDHeader) + sizeof(bigCert), CERT_STORE_ADD_NEW,
1478 ok(!ret && GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
1479 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
1481 /* Kosher size in property header, but no context type */
1482 hdr->cb = sizeof(bigCert);
1483 ret = CertAddSerializedElementToStore(store, buf, sizeof(buf), 0, 0, 0,
1485 ok(!ret && GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
1486 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
1488 ret = CertAddSerializedElementToStore(store, buf,
1489 sizeof(struct CertPropIDHeader) + sizeof(bigCert), 0, 0, 0, NULL,
1491 ok(!ret && GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
1492 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
1494 ret = CertAddSerializedElementToStore(store, buf,
1495 sizeof(struct CertPropIDHeader) + sizeof(bigCert), CERT_STORE_ADD_NEW,
1497 ok(!ret && GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
1498 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
1500 /* With a bad context type */
1501 ret = CertAddSerializedElementToStore(store, buf, sizeof(buf), 0, 0,
1502 CERT_STORE_CRL_CONTEXT_FLAG, NULL, NULL);
1503 ok(!ret && GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
1504 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
1506 ret = CertAddSerializedElementToStore(store, buf,
1507 sizeof(struct CertPropIDHeader) + sizeof(bigCert), 0, 0,
1508 CERT_STORE_CRL_CONTEXT_FLAG, NULL, NULL);
1509 ok(!ret && GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
1510 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
1512 ret = CertAddSerializedElementToStore(store, buf,
1513 sizeof(struct CertPropIDHeader) + sizeof(bigCert), CERT_STORE_ADD_NEW,
1514 0, CERT_STORE_CRL_CONTEXT_FLAG, NULL, NULL);
1515 ok(!ret && GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
1516 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
1518 /* Bad unknown field, good type */
1520 ret = CertAddSerializedElementToStore(store, buf, sizeof(buf), 0, 0,
1521 CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL, NULL);
1522 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
1523 "Expected ERROR_FILE_NOT_FOUND got %08lx\n", GetLastError());
1524 ret = CertAddSerializedElementToStore(store, buf,
1525 sizeof(struct CertPropIDHeader) + sizeof(bigCert), 0, 0,
1526 CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL, NULL);
1527 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
1528 "Expected ERROR_FILE_NOT_FOUND got %08lx\n", GetLastError());
1529 ret = CertAddSerializedElementToStore(store, buf,
1530 sizeof(struct CertPropIDHeader) + sizeof(bigCert), CERT_STORE_ADD_NEW,
1531 0, CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL, NULL);
1532 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
1533 "Expected ERROR_FILE_NOT_FOUND got %08lx\n", GetLastError());
1534 /* Most everything okay, but bad add disposition */
1537 ret = CertAddSerializedElementToStore(store, buf, sizeof(buf), 0, 0,
1538 CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL, NULL);
1540 ret = CertAddSerializedElementToStore(store, buf,
1541 sizeof(struct CertPropIDHeader) + sizeof(bigCert), 0, 0,
1542 CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL, NULL);
1544 /* Everything okay, but buffer's too big */
1545 ret = CertAddSerializedElementToStore(store, buf, sizeof(buf),
1546 CERT_STORE_ADD_NEW, 0, CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL, NULL);
1547 ok(ret, "CertAddSerializedElementToStore failed: %08lx\n", GetLastError());
1548 /* Everything okay, check it's not re-added */
1549 ret = CertAddSerializedElementToStore(store, buf,
1550 sizeof(struct CertPropIDHeader) + sizeof(bigCert), CERT_STORE_ADD_NEW,
1551 0, CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL, NULL);
1552 ok(!ret && GetLastError() == CRYPT_E_EXISTS,
1553 "Expected CRYPT_E_EXISTS, got %08lx\n", GetLastError());
1555 context = CertEnumCertificatesInStore(store, NULL);
1556 ok(context != NULL, "Expected a cert\n");
1558 CertDeleteCertificateFromStore(context);
1560 /* Try adding with a bogus hash. Oddly enough, it succeeds, and the hash,
1561 * when queried, is the real hash rather than the bogus hash.
1563 hdr = (struct CertPropIDHeader *)(buf + sizeof(struct CertPropIDHeader) +
1565 hdr->propID = CERT_HASH_PROP_ID;
1567 hdr->cb = sizeof(hash);
1568 memset(hash, 0xc, sizeof(hash));
1569 memcpy((LPBYTE)hdr + sizeof(struct CertPropIDHeader), hash, sizeof(hash));
1570 ret = CertAddSerializedElementToStore(store, buf, sizeof(buf),
1571 CERT_STORE_ADD_NEW, 0, CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL,
1572 (const void **)&context);
1573 ok(ret, "CertAddSerializedElementToStore failed: %08lx\n", GetLastError());
1576 BYTE hashVal[20], realHash[20];
1577 DWORD size = sizeof(hashVal);
1579 ret = CryptHashCertificate(0, 0, 0, bigCert, sizeof(bigCert),
1581 ok(ret, "CryptHashCertificate failed: %08lx\n", GetLastError());
1582 ret = CertGetCertificateContextProperty(context, CERT_HASH_PROP_ID,
1584 ok(ret, "CertGetCertificateContextProperty failed: %08lx\n",
1586 ok(!memcmp(hashVal, realHash, size), "Unexpected hash\n");
1587 CertFreeCertificateContext(context);
1590 CertCloseStore(store, 0);
1597 testGetSubjectCert();
1599 /* various combinations of CertOpenStore */
1601 testCollectionStore();
1603 testSystemRegStore();
1606 testCertOpenSystemStore();
1608 testCertProperties();
1609 testAddSerialized();