991548227716813ae93299d9a47e9f0ac1277e06
[reactos.git] / modules / rostests / winetests / crypt32 / store.c
1 /*
2 * crypt32 cert store function tests
3 *
4 * Copyright 2005-2006 Juan Lang
5 *
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.
10 *
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.
15 *
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 */
20
21 #include <stdio.h>
22 #include <stdarg.h>
23
24 #include <windef.h>
25 #include <winbase.h>
26 #include <winuser.h>
27 #include <shlobj.h>
28 #include <shlwapi.h>
29 #include <winreg.h>
30 #include <winerror.h>
31 #include <wincrypt.h>
32
33 #include "wine/test.h"
34
35 /* The following aren't defined in wincrypt.h, as they're "reserved" */
36 #define CERT_CERT_PROP_ID 32
37 #define CERT_CRL_PROP_ID 33
38 #define CERT_CTL_PROP_ID 34
39
40 struct CertPropIDHeader
41 {
42 DWORD propID;
43 DWORD unknown1;
44 DWORD cb;
45 };
46
47 static const BYTE emptyCert[] = { 0x30, 0x00 };
48 static const BYTE bigCert[] = { 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
49 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
50 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x22,
51 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30,
52 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30,
53 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30,
54 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20,
55 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01,
56 0x00, 0xa3, 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01,
57 0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
58 static const BYTE signedBigCert[] = {
59 0x30, 0x81, 0x93, 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06, 0x00, 0x30,
60 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a,
61 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x22, 0x18, 0x0f,
62 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
63 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30,
64 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06,
65 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61,
66 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3,
67 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff,
68 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
69 0x00, 0x03, 0x11, 0x00, 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07,
70 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00 };
71 static const BYTE serializedCert[] = { 0x20, 0x00, 0x00, 0x00,
72 0x01, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x30, 0x7a, 0x02, 0x01, 0x01,
73 0x30, 0x02, 0x06, 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55,
74 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67,
75 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31,
76 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31,
77 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15,
78 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75,
79 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06,
80 0x00, 0x03, 0x01, 0x00, 0xa3, 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55,
81 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02,
82 0x01, 0x01 };
83 static const BYTE signedCRL[] = { 0x30, 0x45, 0x30, 0x2c, 0x30, 0x02, 0x06,
84 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
85 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18, 0x0f,
86 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
87 0x30, 0x5a, 0x30, 0x02, 0x06, 0x00, 0x03, 0x11, 0x00, 0x0f, 0x0e, 0x0d, 0x0c,
88 0x0b, 0x0a, 0x09, 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00 };
89 static const BYTE bigCert2[] = { 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
90 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
91 0x0a, 0x41, 0x6c, 0x65, 0x78, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x22,
92 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30,
93 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30,
94 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30,
95 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x41, 0x6c, 0x65, 0x78, 0x20,
96 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01,
97 0x00, 0xa3, 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01,
98 0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
99 static const BYTE signedCTLWithCTLInnerContent[] = {
100 0x30,0x82,0x01,0x0f,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,
101 0xa0,0x82,0x01,0x00,0x30,0x81,0xfd,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,
102 0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x30,0x06,0x09,
103 0x2b,0x06,0x01,0x04,0x01,0x82,0x37,0x0a,0x01,0xa0,0x23,0x30,0x21,0x30,0x00,
104 0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,
105 0x30,0x5a,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,
106 0x00,0x31,0x81,0xb5,0x30,0x81,0xb2,0x02,0x01,0x01,0x30,0x1a,0x30,0x15,0x31,
107 0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,
108 0x4c,0x61,0x6e,0x67,0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,
109 0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0xa0,0x3b,0x30,0x18,0x06,0x09,0x2a,0x86,
110 0x48,0x86,0xf7,0x0d,0x01,0x09,0x03,0x31,0x0b,0x06,0x09,0x2b,0x06,0x01,0x04,
111 0x01,0x82,0x37,0x0a,0x01,0x30,0x1f,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,
112 0x01,0x09,0x04,0x31,0x12,0x04,0x10,0x54,0x71,0xbc,0xe1,0x56,0x31,0xa2,0xf9,
113 0x65,0x70,0x34,0xf8,0xe2,0xe9,0xb4,0xf4,0x30,0x04,0x06,0x00,0x05,0x00,0x04,
114 0x40,0x2f,0x1b,0x9f,0x5a,0x4a,0x15,0x73,0xfa,0xb1,0x93,0x3d,0x09,0x52,0xdf,
115 0x6b,0x98,0x4b,0x13,0x5e,0xe7,0xbf,0x65,0xf4,0x9c,0xc2,0xb1,0x77,0x09,0xb1,
116 0x66,0x4d,0x72,0x0d,0xb1,0x1a,0x50,0x20,0xe0,0x57,0xa2,0x39,0xc7,0xcd,0x7f,
117 0x8e,0xe7,0x5f,0x76,0x2b,0xd1,0x6a,0x82,0xb3,0x30,0x25,0x61,0xf6,0x25,0x23,
118 0x57,0x6c,0x0b,0x47,0xb8 };
119
120 #define test_store_is_empty(store) _test_store_is_empty(__LINE__,store)
121 static void _test_store_is_empty(unsigned line, HCERTSTORE store)
122 {
123 const CERT_CONTEXT *cert;
124
125 cert = CertEnumCertificatesInStore(store, NULL);
126 ok_(__FILE__,line)(!cert && GetLastError() == CRYPT_E_NOT_FOUND, "store is not empty\n");
127 }
128
129 static void testMemStore(void)
130 {
131 HCERTSTORE store1, store2;
132 PCCERT_CONTEXT context;
133 BOOL ret;
134 DWORD GLE;
135
136 /* NULL provider */
137 store1 = CertOpenStore(0, 0, 0, 0, NULL);
138 ok(!store1 && GetLastError() == ERROR_FILE_NOT_FOUND,
139 "Expected ERROR_FILE_NOT_FOUND, got %d\n", GetLastError());
140 /* weird flags */
141 store1 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
142 CERT_STORE_DELETE_FLAG, NULL);
143 ok(!store1 && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED,
144 "Expected ERROR_CALL_NOT_IMPLEMENTED, got %d\n", GetLastError());
145
146 /* normal */
147 store1 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
148 CERT_STORE_CREATE_NEW_FLAG, NULL);
149 ok(store1 != NULL, "CertOpenStore failed: %d\n", GetLastError());
150 /* open existing doesn't */
151 store2 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
152 CERT_STORE_OPEN_EXISTING_FLAG, NULL);
153 ok(store2 != NULL, "CertOpenStore failed: %d\n", GetLastError());
154 ok(store1 != store2, "Expected different stores\n");
155
156 /* add a bogus (empty) cert */
157 context = NULL;
158 ret = CertAddEncodedCertificateToStore(store1, X509_ASN_ENCODING, emptyCert,
159 sizeof(emptyCert), CERT_STORE_ADD_ALWAYS, &context);
160 /* Windows returns CRYPT_E_ASN1_EOD or OSS_DATA_ERROR, but accept
161 * CRYPT_E_ASN1_CORRUPT as well (because matching errors is tough in this
162 * case)
163 */
164 GLE = GetLastError();
165 ok(!ret && (GLE == CRYPT_E_ASN1_EOD || GLE == CRYPT_E_ASN1_CORRUPT ||
166 GLE == OSS_DATA_ERROR),
167 "Expected CRYPT_E_ASN1_EOD or CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
168 GLE);
169 /* add a "signed" cert--the signature isn't a real signature, so this adds
170 * without any check of the signature's validity
171 */
172 ret = CertAddEncodedCertificateToStore(store1, X509_ASN_ENCODING,
173 signedBigCert, sizeof(signedBigCert), CERT_STORE_ADD_ALWAYS, &context);
174 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n", GetLastError());
175 ok(context != NULL, "Expected a valid cert context\n");
176 if (context)
177 {
178 ok(context->cbCertEncoded == sizeof(signedBigCert),
179 "Wrong cert size %d\n", context->cbCertEncoded);
180 ok(!memcmp(context->pbCertEncoded, signedBigCert,
181 sizeof(signedBigCert)), "Unexpected encoded cert in context\n");
182 /* remove it, the rest of the tests will work on an unsigned cert */
183 ret = CertDeleteCertificateFromStore(context);
184 ok(ret, "CertDeleteCertificateFromStore failed: %08x\n",
185 GetLastError());
186 }
187 /* try adding a "signed" CRL as a cert */
188 ret = CertAddEncodedCertificateToStore(store1, X509_ASN_ENCODING,
189 signedCRL, sizeof(signedCRL), CERT_STORE_ADD_ALWAYS, &context);
190 GLE = GetLastError();
191 ok(!ret && (GLE == CRYPT_E_ASN1_BADTAG || GLE == CRYPT_E_ASN1_CORRUPT ||
192 GLE == OSS_DATA_ERROR),
193 "Expected CRYPT_E_ASN1_BADTAG or CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
194 GLE);
195 /* add a cert to store1 */
196 ret = CertAddEncodedCertificateToStore(store1, X509_ASN_ENCODING, bigCert,
197 sizeof(bigCert), CERT_STORE_ADD_ALWAYS, &context);
198 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n", GetLastError());
199 ok(context != NULL, "Expected a valid cert context\n");
200 if (context)
201 {
202 DWORD size;
203 BYTE *buf;
204
205 ok(context->cbCertEncoded == sizeof(bigCert),
206 "Wrong cert size %d\n", context->cbCertEncoded);
207 ok(!memcmp(context->pbCertEncoded, bigCert, sizeof(bigCert)),
208 "Unexpected encoded cert in context\n");
209 ok(context->hCertStore == store1, "Unexpected store\n");
210
211 /* check serializing this element */
212 /* These crash
213 ret = CertSerializeCertificateStoreElement(NULL, 0, NULL, NULL);
214 ret = CertSerializeCertificateStoreElement(context, 0, NULL, NULL);
215 ret = CertSerializeCertificateStoreElement(NULL, 0, NULL, &size);
216 */
217 /* apparently flags are ignored */
218 ret = CertSerializeCertificateStoreElement(context, 1, NULL, &size);
219 ok(ret, "CertSerializeCertificateStoreElement failed: %08x\n",
220 GetLastError());
221 buf = HeapAlloc(GetProcessHeap(), 0, size);
222 if (buf)
223 {
224 ret = CertSerializeCertificateStoreElement(context, 0, buf, &size);
225 ok(ret, "CertSerializeCertificateStoreElement failed: %08x\n", GetLastError());
226 ok(size == sizeof(serializedCert), "Wrong size %d\n", size);
227 ok(!memcmp(serializedCert, buf, size),
228 "Unexpected serialized cert\n");
229 HeapFree(GetProcessHeap(), 0, buf);
230 }
231
232 ret = CertFreeCertificateContext(context);
233 ok(ret, "CertFreeCertificateContext failed: %08x\n", GetLastError());
234 }
235 /* verify the cert's in store1 */
236 context = CertEnumCertificatesInStore(store1, NULL);
237 ok(context != NULL, "Expected a valid context\n");
238 context = CertEnumCertificatesInStore(store1, context);
239 ok(!context && GetLastError() == CRYPT_E_NOT_FOUND,
240 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
241 /* verify store2 (the "open existing" mem store) is still empty */
242 context = CertEnumCertificatesInStore(store2, NULL);
243 ok(!context, "Expected an empty store\n");
244 /* delete the cert from store1, and check it's empty */
245 context = CertEnumCertificatesInStore(store1, NULL);
246 if (context)
247 {
248 /* Deleting a bitwise copy crashes with an access to an uninitialized
249 * pointer, so a cert context has some special data out there in memory
250 * someplace
251 CERT_CONTEXT copy;
252 memcpy(&copy, context, sizeof(copy));
253 ret = CertDeleteCertificateFromStore(&copy);
254 */
255 PCCERT_CONTEXT copy = CertDuplicateCertificateContext(context);
256
257 ok(copy != NULL, "CertDuplicateCertificateContext failed: %08x\n",
258 GetLastError());
259 ret = CertDeleteCertificateFromStore(context);
260 ok(ret, "CertDeleteCertificateFromStore failed: %08x\n",
261 GetLastError());
262 /* try deleting a copy */
263 ret = CertDeleteCertificateFromStore(copy);
264 ok(ret, "CertDeleteCertificateFromStore failed: %08x\n",
265 GetLastError());
266 /* check that the store is empty */
267 context = CertEnumCertificatesInStore(store1, NULL);
268 ok(!context, "Expected an empty store\n");
269 }
270
271 /* close an empty store */
272 ret = CertCloseStore(NULL, 0);
273 ok(ret, "CertCloseStore failed: %d\n", GetLastError());
274 ret = CertCloseStore(store1, 0);
275 ok(ret, "CertCloseStore failed: %d\n", GetLastError());
276 ret = CertCloseStore(store2, 0);
277 ok(ret, "CertCloseStore failed: %d\n", GetLastError());
278
279 /* This seems nonsensical, but you can open a read-only mem store, only
280 * it isn't read-only
281 */
282 store1 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
283 CERT_STORE_READONLY_FLAG, NULL);
284 ok(store1 != NULL, "CertOpenStore failed: %d\n", GetLastError());
285 /* yep, this succeeds */
286 ret = CertAddEncodedCertificateToStore(store1, X509_ASN_ENCODING, bigCert,
287 sizeof(bigCert), CERT_STORE_ADD_ALWAYS, &context);
288 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n", GetLastError());
289 ok(context != NULL, "Expected a valid cert context\n");
290 if (context)
291 {
292 ok(context->cbCertEncoded == sizeof(bigCert),
293 "Wrong cert size %d\n", context->cbCertEncoded);
294 ok(!memcmp(context->pbCertEncoded, bigCert, sizeof(bigCert)),
295 "Unexpected encoded cert in context\n");
296 ok(context->hCertStore == store1, "Unexpected store\n");
297 ret = CertDeleteCertificateFromStore(context);
298 ok(ret, "CertDeleteCertificateFromStore failed: %08x\n",
299 GetLastError());
300 }
301 CertCloseStore(store1, 0);
302 }
303
304 static void compareStore(HCERTSTORE store, LPCSTR name, const BYTE *pb,
305 DWORD cb, BOOL todo)
306 {
307 BOOL ret;
308 CRYPT_DATA_BLOB blob = { 0, NULL };
309
310 ret = CertSaveStore(store, X509_ASN_ENCODING, CERT_STORE_SAVE_AS_STORE,
311 CERT_STORE_SAVE_TO_MEMORY, &blob, 0);
312 ok(ret, "CertSaveStore failed: %08x\n", GetLastError());
313 todo_wine_if (todo)
314 ok(blob.cbData == cb, "%s: expected size %d, got %d\n", name, cb,
315 blob.cbData);
316 blob.pbData = HeapAlloc(GetProcessHeap(), 0, blob.cbData);
317 if (blob.pbData)
318 {
319 ret = CertSaveStore(store, X509_ASN_ENCODING, CERT_STORE_SAVE_AS_STORE,
320 CERT_STORE_SAVE_TO_MEMORY, &blob, 0);
321 ok(ret, "CertSaveStore failed: %08x\n", GetLastError());
322 todo_wine_if (todo)
323 ok(!memcmp(pb, blob.pbData, cb), "%s: unexpected value\n", name);
324 HeapFree(GetProcessHeap(), 0, blob.pbData);
325 }
326 }
327
328 static const BYTE serializedStoreWithCert[] = {
329 0x00,0x00,0x00,0x00,0x43,0x45,0x52,0x54,0x20,0x00,0x00,0x00,0x01,0x00,0x00,
330 0x00,0x7c,0x00,0x00,0x00,0x30,0x7a,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,
331 0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,
332 0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,
333 0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,
334 0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,
335 0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,
336 0x20,0x4c,0x61,0x6e,0x67,0x00,0x30,0x07,0x30,0x02,0x06,0x00,0x03,0x01,0x00,
337 0xa3,0x16,0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,
338 0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,
339 0x00,0x00,0x00,0x00,0x00,0x00 };
340
341 static const struct
342 {
343 HKEY key;
344 DWORD cert_store;
345 BOOL appdata_file;
346 WCHAR store_name[16];
347 const WCHAR *base_reg_path;
348 } reg_store_saved_certs[] = {
349 { HKEY_LOCAL_MACHINE, CERT_SYSTEM_STORE_LOCAL_MACHINE, FALSE,
350 {'R','O','O','T',0}, CERT_LOCAL_MACHINE_SYSTEM_STORE_REGPATH },
351 { HKEY_LOCAL_MACHINE, CERT_SYSTEM_STORE_LOCAL_MACHINE, FALSE,
352 {'M','Y',0}, CERT_LOCAL_MACHINE_SYSTEM_STORE_REGPATH },
353 { HKEY_LOCAL_MACHINE, CERT_SYSTEM_STORE_LOCAL_MACHINE, FALSE,
354 {'C','A',0}, CERT_LOCAL_MACHINE_SYSTEM_STORE_REGPATH },
355 /* Adding to HKCU\Root triggers safety warning. */
356 { HKEY_CURRENT_USER, CERT_SYSTEM_STORE_CURRENT_USER, TRUE,
357 {'M','Y',0}, CERT_LOCAL_MACHINE_SYSTEM_STORE_REGPATH },
358 { HKEY_CURRENT_USER, CERT_SYSTEM_STORE_CURRENT_USER, FALSE,
359 {'C','A',0}, CERT_LOCAL_MACHINE_SYSTEM_STORE_REGPATH }
360 };
361
362 /* Testing whether system stores are available for adding new certs
363 * and checking directly in the registry whether they are actually saved or deleted.
364 * Windows treats HKCU\My (at least) as a special case and uses AppData directory
365 * for storing certs, not registry.
366 */
367 static void testRegStoreSavedCerts(void)
368 {
369 static const WCHAR fmt[] =
370 { '%','s','\\','%','s','\\','%','s','\\','%','s',0},
371 ms_certs[] =
372 { 'M','i','c','r','o','s','o','f','t','\\','S','y','s','t','e','m','C','e','r','t','i','f','i','c','a','t','e','s',0},
373 certs[] =
374 {'C','e','r','t','i','f','i','c','a','t','e','s',0},
375 bigCert_hash[] = {
376 '6','E','3','0','9','0','7','1','5','F','D','9','2','3',
377 '5','6','E','B','A','E','2','5','4','0','E','6','2','2',
378 'D','A','1','9','2','6','0','2','A','6','0','8',0};
379 PCCERT_CONTEXT cert1, cert2;
380 HCERTSTORE store;
381 HANDLE cert_file;
382 HRESULT pathres;
383 WCHAR key_name[MAX_PATH], appdata_path[MAX_PATH];
384 HKEY key;
385 BOOL ret;
386 DWORD res,i;
387
388 for (i = 0; i < ARRAY_SIZE(reg_store_saved_certs); i++)
389 {
390 DWORD err;
391
392 store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY_W,0,0,
393 reg_store_saved_certs[i].cert_store, reg_store_saved_certs[i].store_name);
394
395 err = GetLastError();
396 if (!store)
397 {
398 ok (err == ERROR_ACCESS_DENIED, "Failed to create store at %d (%08x)\n", i, err);
399 skip("Insufficient privileges for the test %d\n", i);
400 continue;
401 }
402 ok (store!=NULL, "Failed to open the store at %d, %x\n", i, GetLastError());
403 cert1 = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert, sizeof(bigCert));
404 ok (cert1 != NULL, "Create cert context failed at %d, %x\n", i, GetLastError());
405 ret = CertAddCertificateContextToStore(store, cert1, CERT_STORE_ADD_REPLACE_EXISTING, NULL);
406 /* Addittional skip per Win7, it allows opening HKLM store, but disallows adding certs */
407 err = GetLastError();
408 if (!ret)
409 {
410 ok (err == ERROR_ACCESS_DENIED, "Failed to add certificate to store at %d (%08x)\n", i, err);
411 skip("Insufficient privileges for the test %d\n", i);
412 continue;
413 }
414 ok (ret, "Adding to the store failed at %d, %x\n", i, err);
415 CertFreeCertificateContext(cert1);
416 CertCloseStore(store, 0);
417
418 wsprintfW(key_name, fmt, reg_store_saved_certs[i].base_reg_path,
419 reg_store_saved_certs[i].store_name, certs, bigCert_hash);
420
421 if (!reg_store_saved_certs[i].appdata_file)
422 {
423 res = RegOpenKeyExW(reg_store_saved_certs[i].key, key_name, 0, KEY_ALL_ACCESS, &key);
424 ok (!res, "The cert hasn't been saved at %d, %x\n", i, GetLastError());
425 if (!res) RegCloseKey(key);
426 } else
427 {
428 pathres = SHGetFolderPathW(NULL, CSIDL_APPDATA, NULL, 0, appdata_path);
429 ok (pathres == S_OK,
430 "Failed to get app data path at %d (%x)\n", pathres, GetLastError());
431 if (pathres == S_OK)
432 {
433 PathAppendW(appdata_path, ms_certs);
434 PathAppendW(appdata_path, reg_store_saved_certs[i].store_name);
435 PathAppendW(appdata_path, certs);
436 PathAppendW(appdata_path, bigCert_hash);
437
438 cert_file = CreateFileW(appdata_path, GENERIC_READ, 0, NULL,
439 OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
440 todo_wine ok (cert_file != INVALID_HANDLE_VALUE,
441 "Cert was not saved in AppData at %d (%x)\n", i, GetLastError());
442 CloseHandle(cert_file);
443 }
444 }
445
446 /* deleting cert from store */
447 store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY_W,0,0,
448 reg_store_saved_certs[i].cert_store, reg_store_saved_certs[i].store_name);
449 ok (store!=NULL, "Failed to open the store at %d, %x\n", i, GetLastError());
450
451 cert1 = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert, sizeof(bigCert));
452 ok (cert1 != NULL, "Create cert context failed at %d, %x\n", i, GetLastError());
453
454 cert2 = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
455 CERT_FIND_EXISTING, cert1, NULL);
456 ok (cert2 != NULL, "Failed to find cert in the store at %d, %x\n", i, GetLastError());
457
458 ret = CertDeleteCertificateFromStore(cert2);
459 ok (ret, "Failed to delete certificate from store at %d, %x\n", i, GetLastError());
460
461 CertFreeCertificateContext(cert1);
462 CertFreeCertificateContext(cert2);
463 CertCloseStore(store, 0);
464
465 res = RegOpenKeyExW(reg_store_saved_certs[i].key, key_name, 0, KEY_ALL_ACCESS, &key);
466 ok (res, "The cert's registry entry should be absent at %i, %x\n", i, GetLastError());
467 if (!res) RegCloseKey(key);
468
469 if (reg_store_saved_certs[i].appdata_file)
470 {
471 cert_file = CreateFileW(appdata_path, GENERIC_READ, 0, NULL,
472 OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
473 ok (cert_file == INVALID_HANDLE_VALUE,
474 "Cert should have been absent in AppData %d\n", i);
475
476 CloseHandle(cert_file);
477 }
478 }
479 }
480
481 /**
482 * This test checks that certificate falls into correct store of a collection
483 * depending on the access flags and priorities.
484 */
485 static void testStoresInCollection(void)
486 {
487 PCCERT_CONTEXT cert1, cert2, tcert1;
488 HCERTSTORE collection, ro_store, rw_store, rw_store_2, tstore;
489 static const WCHAR WineTestRO_W[] = { 'W','i','n','e','T','e','s','t','_','R','O',0 },
490 WineTestRW_W[] = { 'W','i','n','e','T','e','s','t','_','R','W',0 },
491 WineTestRW2_W[]= { 'W','i','n','e','T','e','s','t','_','R','W','2',0 };
492 BOOL ret;
493
494 collection = CertOpenStore(CERT_STORE_PROV_COLLECTION, 0, 0,
495 CERT_STORE_CREATE_NEW_FLAG, NULL);
496 ok(collection != NULL, "Failed to init collection store, last error %x\n", GetLastError());
497 /* Add read-only store to collection with very high priority*/
498 ro_store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY_W, 0, 0,
499 CERT_SYSTEM_STORE_CURRENT_USER, WineTestRO_W);
500 ok(ro_store != NULL, "Failed to init ro store %x\n", GetLastError());
501
502 ret = CertAddStoreToCollection(collection, ro_store, 0, 1000);
503 ok (ret, "Failed to add read-only store to collection %x\n", GetLastError());
504
505 cert1 = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert, sizeof(bigCert));
506 ok (cert1 != NULL, "Create cert context failed %x\n", GetLastError());
507 ret = CertAddCertificateContextToStore(collection, cert1, CERT_STORE_ADD_ALWAYS, NULL);
508 ok (!ret, "Added cert to collection with single read-only store %x\n", GetLastError());
509
510 /* Add read-write store to collection with the lowest priority*/
511 rw_store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY_W, 0, 0,
512 CERT_SYSTEM_STORE_CURRENT_USER, WineTestRW_W);
513 ok (rw_store != NULL, "Failed to open rw store %x\n", GetLastError());
514 ret = CertAddStoreToCollection(collection, rw_store, CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
515 ok (ret, "Failed to add rw store to collection %x\n", GetLastError());
516 /** Adding certificate to collection should fall into rw store,
517 * even though prioirty of the ro_store is higher */
518 ret = CertAddCertificateContextToStore(collection, cert1, CERT_STORE_ADD_REPLACE_EXISTING, NULL);
519 ok (ret, "Failed to add cert to the collection %x\n", GetLastError());
520
521 tcert1 = CertEnumCertificatesInStore(ro_store, NULL);
522 ok (!tcert1, "Read-only ro_store contains cert\n");
523
524 tcert1 = CertEnumCertificatesInStore(rw_store, NULL);
525 ok (cert1 && tcert1->cbCertEncoded == cert1->cbCertEncoded,
526 "Unexpected cert in the rw store\n");
527 CertFreeCertificateContext(tcert1);
528
529 tcert1 = CertEnumCertificatesInStore(collection, NULL);
530 ok (tcert1 && tcert1->cbCertEncoded == cert1->cbCertEncoded,
531 "Unexpected cert in the collection\n");
532 CertFreeCertificateContext(tcert1);
533
534 /** adding one more rw store with higher priority*/
535 rw_store_2 = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY_W, 0, 0,
536 CERT_SYSTEM_STORE_CURRENT_USER, WineTestRW2_W);
537 ok (rw_store_2 != NULL, "Failed to init second rw store %x\n", GetLastError());
538 ret = CertAddStoreToCollection(collection, rw_store_2, CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 50);
539 ok (ret, "Failed to add rw_store_2 to collection %x\n",GetLastError());
540
541 cert2 = CertCreateCertificateContext(X509_ASN_ENCODING, signedBigCert, sizeof(signedBigCert));
542 ok (cert2 != NULL, "Failed to create cert context %x\n", GetLastError());
543 ret = CertAddCertificateContextToStore(collection, cert2, CERT_STORE_ADD_REPLACE_EXISTING, NULL);
544 ok (ret, "Failed to add cert3 to the store %x\n",GetLastError());
545
546 /** checking certificates in the stores */
547 tcert1 = CertEnumCertificatesInStore(ro_store, 0);
548 ok (tcert1 == NULL, "Read-only store not empty\n");
549
550 tcert1 = CertEnumCertificatesInStore(rw_store, NULL);
551 ok (tcert1 && tcert1->cbCertEncoded == cert1->cbCertEncoded,
552 "Unexpected cert in the rw_store\n");
553 CertFreeCertificateContext(tcert1);
554
555 tcert1 = CertEnumCertificatesInStore(rw_store_2, NULL);
556 ok (tcert1 && tcert1->cbCertEncoded == cert2->cbCertEncoded,
557 "Unexpected cert in the rw_store_2\n");
558 CertFreeCertificateContext(tcert1);
559
560 /** checking certificates in the collection */
561 tcert1 = CertEnumCertificatesInStore(collection, NULL);
562 ok (tcert1 && tcert1->cbCertEncoded == cert2->cbCertEncoded,
563 "cert2 expected in the collection got %p, %x\n",tcert1, GetLastError());
564 tcert1 = CertEnumCertificatesInStore(collection, tcert1);
565 ok (tcert1 && tcert1->cbCertEncoded == cert1->cbCertEncoded,
566 "cert1 expected in the collection got %p, %x\n",tcert1, GetLastError());
567 tcert1 = CertEnumCertificatesInStore(collection, tcert1);
568 ok (tcert1==NULL,"Unexpected cert in the collection %p %x\n",tcert1, GetLastError());
569
570 /* checking whether certs had been saved */
571 tstore = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY_W,0,0,
572 CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_OPEN_EXISTING_FLAG, WineTestRW_W);
573 ok (tstore!=NULL, "Failed to open existing rw store\n");
574 tcert1 = CertEnumCertificatesInStore(tstore, NULL);
575 todo_wine
576 ok(tcert1 && tcert1->cbCertEncoded == cert1->cbCertEncoded, "cert1 wasn't saved\n");
577 CertFreeCertificateContext(tcert1);
578 CertCloseStore(tstore,0);
579
580 tstore = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY_W,0,0,
581 CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_OPEN_EXISTING_FLAG, WineTestRW2_W);
582 ok (tstore!=NULL, "Failed to open existing rw2 store\n");
583 tcert1 = CertEnumCertificatesInStore(tstore, NULL);
584 todo_wine
585 ok (tcert1 && tcert1->cbCertEncoded == cert2->cbCertEncoded, "cert2 wasn't saved\n");
586 CertFreeCertificateContext(tcert1);
587 CertCloseStore(tstore,0);
588
589 CertCloseStore(collection,0);
590 CertCloseStore(ro_store,0);
591 CertCloseStore(rw_store,0);
592 CertCloseStore(rw_store_2,0);
593
594 /* reopening registry stores to check whether certs had been saved */
595 rw_store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY_W,0,0,
596 CERT_SYSTEM_STORE_CURRENT_USER, WineTestRW_W);
597 tcert1 = CertEnumCertificatesInStore(rw_store, NULL);
598 ok (tcert1 && tcert1->cbCertEncoded == cert1->cbCertEncoded,
599 "Unexpected cert in store %p\n", tcert1);
600 CertFreeCertificateContext(tcert1);
601 CertCloseStore(rw_store,0);
602
603 rw_store_2 = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY_W,0,0,
604 CERT_SYSTEM_STORE_CURRENT_USER, WineTestRW2_W);
605 tcert1 = CertEnumCertificatesInStore(rw_store_2, NULL);
606 ok (tcert1 && tcert1->cbCertEncoded == cert2->cbCertEncoded,
607 "Unexpected cert in store %p\n", tcert1);
608 CertFreeCertificateContext(tcert1);
609 CertCloseStore(rw_store_2,0);
610
611 CertFreeCertificateContext(cert1);
612 CertFreeCertificateContext(cert2);
613 CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY_W,0,0,
614 CERT_STORE_DELETE_FLAG|CERT_SYSTEM_STORE_CURRENT_USER,WineTestRO_W);
615 CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY_W,0,0,
616 CERT_STORE_DELETE_FLAG|CERT_SYSTEM_STORE_CURRENT_USER,WineTestRW_W);
617 CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY_W,0,0,
618 CERT_STORE_DELETE_FLAG|CERT_SYSTEM_STORE_CURRENT_USER,WineTestRW2_W);
619
620 }
621
622 static void testCollectionStore(void)
623 {
624 HCERTSTORE store1, store2, collection, collection2;
625 PCCERT_CONTEXT context;
626 BOOL ret;
627 static const WCHAR szPrefix[] = { 'c','e','r',0 };
628 static const WCHAR szDot[] = { '.',0 };
629 WCHAR filename[MAX_PATH];
630 HANDLE file;
631
632 collection = CertOpenStore(CERT_STORE_PROV_COLLECTION, 0, 0,
633 CERT_STORE_CREATE_NEW_FLAG, NULL);
634
635 /* Try adding a cert to any empty collection */
636 ret = CertAddEncodedCertificateToStore(collection, X509_ASN_ENCODING,
637 bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, NULL);
638 ok(!ret && GetLastError() == E_ACCESSDENIED,
639 "Expected E_ACCESSDENIED, got %08x\n", GetLastError());
640
641 /* Create and add a cert to a memory store */
642 store1 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
643 CERT_STORE_CREATE_NEW_FLAG, NULL);
644 ret = CertAddEncodedCertificateToStore(store1, X509_ASN_ENCODING,
645 bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, NULL);
646 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n", GetLastError());
647 /* Add the memory store to the collection, without allowing adding */
648 ret = CertAddStoreToCollection(collection, store1, 0, 0);
649 ok(ret, "CertAddStoreToCollection failed: %08x\n", GetLastError());
650 /* Verify the cert is in the collection */
651 context = CertEnumCertificatesInStore(collection, NULL);
652 ok(context != NULL, "Expected a valid context\n");
653 if (context)
654 {
655 ok(context->hCertStore == collection, "Unexpected store\n");
656 CertFreeCertificateContext(context);
657 }
658 /* Check that adding to the collection isn't allowed */
659 ret = CertAddEncodedCertificateToStore(collection, X509_ASN_ENCODING,
660 bigCert2, sizeof(bigCert2), CERT_STORE_ADD_ALWAYS, NULL);
661 ok(!ret && GetLastError() == E_ACCESSDENIED,
662 "Expected E_ACCESSDENIED, got %08x\n", GetLastError());
663
664 /* Create a new memory store */
665 store2 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
666 CERT_STORE_CREATE_NEW_FLAG, NULL);
667 /* Try adding a store to a non-collection store */
668 ret = CertAddStoreToCollection(store1, store2,
669 CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
670 ok(!ret && GetLastError() == E_INVALIDARG,
671 "Expected E_INVALIDARG, got %08x\n", GetLastError());
672 /* Try adding some bogus stores */
673 /* This crashes in Windows
674 ret = pCertAddStoreToCollection(0, store2,
675 CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
676 */
677 /* This "succeeds"... */
678 ret = CertAddStoreToCollection(collection, 0,
679 CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
680 ok(ret, "CertAddStoreToCollection failed: %08x\n", GetLastError());
681 /* while this crashes.
682 ret = pCertAddStoreToCollection(collection, 1,
683 CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
684 */
685
686 /* Add it to the collection, this time allowing adding */
687 ret = CertAddStoreToCollection(collection, store2,
688 CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
689 ok(ret, "CertAddStoreToCollection failed: %08x\n", GetLastError());
690 /* Check that adding to the collection is allowed */
691 ret = CertAddEncodedCertificateToStore(collection, X509_ASN_ENCODING,
692 bigCert2, sizeof(bigCert2), CERT_STORE_ADD_ALWAYS, NULL);
693 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n", GetLastError());
694 /* Now check that it was actually added to store2 */
695 context = CertEnumCertificatesInStore(store2, NULL);
696 ok(context != NULL, "Expected a valid context\n");
697 if (context)
698 {
699 ok(context->hCertStore == store2, "Unexpected store\n");
700 CertFreeCertificateContext(context);
701 }
702 /* Check that the collection has both bigCert and bigCert2. bigCert comes
703 * first because store1 was added first.
704 */
705 context = CertEnumCertificatesInStore(collection, NULL);
706 ok(context != NULL, "Expected a valid context\n");
707 if (context)
708 {
709 ok(context->hCertStore == collection, "Unexpected store\n");
710 ok(context->cbCertEncoded == sizeof(bigCert),
711 "Wrong size %d\n", 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");
716 if (context)
717 {
718 ok(context->hCertStore == collection, "Unexpected store\n");
719 ok(context->cbCertEncoded == sizeof(bigCert2),
720 "Wrong size %d\n", context->cbCertEncoded);
721 ok(!memcmp(context->pbCertEncoded, bigCert2,
722 context->cbCertEncoded), "Unexpected cert\n");
723 context = CertEnumCertificatesInStore(collection, context);
724 ok(!context, "Unexpected cert\n");
725 }
726 }
727 /* close store2, and check that the collection is unmodified */
728 CertCloseStore(store2, 0);
729 context = CertEnumCertificatesInStore(collection, NULL);
730 ok(context != NULL, "Expected a valid context\n");
731 if (context)
732 {
733 ok(context->hCertStore == collection, "Unexpected store\n");
734 ok(context->cbCertEncoded == sizeof(bigCert),
735 "Wrong size %d\n", context->cbCertEncoded);
736 ok(!memcmp(context->pbCertEncoded, bigCert, context->cbCertEncoded),
737 "Unexpected cert\n");
738 context = CertEnumCertificatesInStore(collection, context);
739 ok(context != NULL, "Expected a valid context\n");
740 if (context)
741 {
742 ok(context->hCertStore == collection, "Unexpected store\n");
743 ok(context->cbCertEncoded == sizeof(bigCert2),
744 "Wrong size %d\n", context->cbCertEncoded);
745 ok(!memcmp(context->pbCertEncoded, bigCert2,
746 context->cbCertEncoded), "Unexpected cert\n");
747 context = CertEnumCertificatesInStore(collection, context);
748 ok(!context, "Unexpected cert\n");
749 }
750 }
751
752 /* Adding a collection to a collection is legal */
753 collection2 = CertOpenStore(CERT_STORE_PROV_COLLECTION, 0, 0,
754 CERT_STORE_CREATE_NEW_FLAG, NULL);
755 ret = CertAddStoreToCollection(collection2, collection,
756 CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
757 ok(ret, "CertAddStoreToCollection failed: %08x\n", GetLastError());
758 /* check the contents of collection2 */
759 context = CertEnumCertificatesInStore(collection2, NULL);
760 ok(context != NULL, "Expected a valid context\n");
761 if (context)
762 {
763 ok(context->hCertStore == collection2, "Unexpected store\n");
764 ok(context->cbCertEncoded == sizeof(bigCert),
765 "Wrong size %d\n", context->cbCertEncoded);
766 ok(!memcmp(context->pbCertEncoded, bigCert, context->cbCertEncoded),
767 "Unexpected cert\n");
768 context = CertEnumCertificatesInStore(collection2, context);
769 ok(context != NULL, "Expected a valid context\n");
770 if (context)
771 {
772 ok(context->hCertStore == collection2, "Unexpected store\n");
773 ok(context->cbCertEncoded == sizeof(bigCert2),
774 "Wrong size %d\n", context->cbCertEncoded);
775 ok(!memcmp(context->pbCertEncoded, bigCert2,
776 context->cbCertEncoded), "Unexpected cert\n");
777 context = CertEnumCertificatesInStore(collection2, context);
778 ok(!context, "Unexpected cert\n");
779 }
780 }
781
782 /* I'd like to test closing the collection in the middle of enumeration,
783 * but my tests have been inconsistent. The first time calling
784 * CertEnumCertificatesInStore on a closed collection succeeded, while the
785 * second crashed. So anything appears to be fair game.
786 * I'd also like to test removing a store from a collection in the middle
787 * of an enumeration, but my tests in Windows have been inconclusive.
788 * In one scenario it worked. In another scenario, about a third of the
789 * time this leads to "random" crashes elsewhere in the code. This
790 * probably means this is not allowed.
791 */
792
793 CertCloseStore(store1, 0);
794 CertCloseStore(collection, 0);
795 CertCloseStore(collection2, 0);
796
797 /* Add the same cert to two memory stores, then put them in a collection */
798 store1 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
799 CERT_STORE_CREATE_NEW_FLAG, NULL);
800 ok(store1 != 0, "CertOpenStore failed: %08x\n", GetLastError());
801 store2 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
802 CERT_STORE_CREATE_NEW_FLAG, NULL);
803 ok(store2 != 0, "CertOpenStore failed: %08x\n", GetLastError());
804
805 ret = CertAddEncodedCertificateToStore(store1, X509_ASN_ENCODING,
806 bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, NULL);
807 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n", GetLastError());
808 ret = CertAddEncodedCertificateToStore(store2, X509_ASN_ENCODING,
809 bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, NULL);
810 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n", GetLastError());
811 collection = CertOpenStore(CERT_STORE_PROV_COLLECTION, 0, 0,
812 CERT_STORE_CREATE_NEW_FLAG, NULL);
813 ok(collection != 0, "CertOpenStore failed: %08x\n", GetLastError());
814
815 ret = CertAddStoreToCollection(collection, store1, CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
816 ok(ret, "CertAddStoreToCollection failed: %08x\n", GetLastError());
817 ret = CertAddStoreToCollection(collection, store2, CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
818 ok(ret, "CertAddStoreToCollection failed: %08x\n", GetLastError());
819
820 /* Check that the collection has two copies of the same cert */
821 context = CertEnumCertificatesInStore(collection, NULL);
822 ok(context != NULL, "Expected a valid context\n");
823 if (context)
824 {
825 ok(context->hCertStore == collection, "Unexpected store\n");
826 ok(context->cbCertEncoded == sizeof(bigCert),
827 "Wrong size %d\n", context->cbCertEncoded);
828 ok(!memcmp(context->pbCertEncoded, bigCert, context->cbCertEncoded),
829 "Unexpected cert\n");
830 context = CertEnumCertificatesInStore(collection, context);
831 ok(context != NULL, "Expected a valid context\n");
832 if (context)
833 {
834 ok(context->hCertStore == collection, "Unexpected store\n");
835 ok(context->cbCertEncoded == sizeof(bigCert),
836 "Wrong size %d\n", context->cbCertEncoded);
837 ok(!memcmp(context->pbCertEncoded, bigCert, context->cbCertEncoded),
838 "Unexpected cert\n");
839 context = CertEnumCertificatesInStore(collection, context);
840 ok(context == NULL, "Unexpected cert\n");
841 }
842 }
843
844 /* The following would check whether I can delete an identical cert, rather
845 * than one enumerated from the store. It crashes, so that means I must
846 * only call CertDeleteCertificateFromStore with contexts enumerated from
847 * the store.
848 context = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert,
849 sizeof(bigCert));
850 ok(context != NULL, "CertCreateCertificateContext failed: %08x\n",
851 GetLastError());
852 if (context)
853 {
854 ret = CertDeleteCertificateFromStore(collection, context);
855 printf("ret is %d, GetLastError is %08x\n", ret, GetLastError());
856 CertFreeCertificateContext(context);
857 }
858 */
859
860 /* Now check deleting from the collection. */
861 context = CertEnumCertificatesInStore(collection, NULL);
862 ok(context != NULL, "Expected a valid context\n");
863 if (context)
864 {
865 CertDeleteCertificateFromStore(context);
866 /* store1 should now be empty */
867 context = CertEnumCertificatesInStore(store1, NULL);
868 ok(!context, "Unexpected cert\n");
869 /* and there should be one certificate in the collection */
870 context = CertEnumCertificatesInStore(collection, NULL);
871 ok(context != NULL, "Expected a valid cert\n");
872 if (context)
873 {
874 ok(context->hCertStore == collection, "Unexpected store\n");
875 ok(context->cbCertEncoded == sizeof(bigCert),
876 "Wrong size %d\n", context->cbCertEncoded);
877 ok(!memcmp(context->pbCertEncoded, bigCert, context->cbCertEncoded),
878 "Unexpected cert\n");
879 }
880 context = CertEnumCertificatesInStore(collection, context);
881 ok(context == NULL, "Unexpected cert\n");
882 }
883
884 /* Finally, test removing stores from the collection. No return
885 * value, so it's a bit funny to test.
886 */
887 /* This crashes
888 * CertRemoveStoreFromCollection(NULL, NULL);
889 */
890 /* This "succeeds," no crash, no last error set */
891 SetLastError(0xdeadbeef);
892 CertRemoveStoreFromCollection(store2, collection);
893 ok(GetLastError() == 0xdeadbeef,
894 "Didn't expect an error to be set: %08x\n", GetLastError());
895
896 /* After removing store2, the collection should be empty */
897 SetLastError(0xdeadbeef);
898 CertRemoveStoreFromCollection(collection, store2);
899 ok(GetLastError() == 0xdeadbeef,
900 "Didn't expect an error to be set: %08x\n", GetLastError());
901 context = CertEnumCertificatesInStore(collection, NULL);
902 ok(!context, "Unexpected cert\n");
903
904 CertCloseStore(collection, 0);
905 CertCloseStore(store2, 0);
906 CertCloseStore(store1, 0);
907
908 /* Test adding certificates to and deleting certificates from collections.
909 */
910 store1 = CertOpenSystemStoreA(0, "My");
911 collection = CertOpenStore(CERT_STORE_PROV_COLLECTION, 0, 0,
912 CERT_STORE_CREATE_NEW_FLAG, NULL);
913
914 ret = CertAddEncodedCertificateToStore(store1, X509_ASN_ENCODING,
915 bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, &context);
916 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n", GetLastError());
917 CertDeleteCertificateFromStore(context);
918
919 CertAddStoreToCollection(collection, store1, CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
920
921 ret = CertAddEncodedCertificateToStore(collection, X509_ASN_ENCODING,
922 bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, &context);
923 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n", GetLastError());
924 CertDeleteCertificateFromStore(context);
925
926 CertCloseStore(collection, 0);
927 CertCloseStore(store1, 0);
928
929 /* Test whether a collection store can be committed */
930 collection = CertOpenStore(CERT_STORE_PROV_COLLECTION, 0, 0,
931 CERT_STORE_CREATE_NEW_FLAG, NULL);
932
933 SetLastError(0xdeadbeef);
934 ret = CertControlStore(collection, 0, CERT_STORE_CTRL_COMMIT, NULL);
935 ok(ret, "CertControlStore failed: %08x\n", GetLastError());
936
937 /* Adding a mem store that can't be committed prevents a successful commit.
938 */
939 store1 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
940 CERT_STORE_CREATE_NEW_FLAG, NULL);
941 CertAddStoreToCollection(collection, store1, 0, 0);
942 SetLastError(0xdeadbeef);
943 ret = CertControlStore(collection, 0, CERT_STORE_CTRL_COMMIT, NULL);
944 ok(!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED,
945 "expected ERROR_CALL_NOT_IMPLEMENTED, got %d\n", GetLastError());
946 CertRemoveStoreFromCollection(collection, store1);
947 CertCloseStore(store1, 0);
948
949 /* Test adding a cert to a collection with a file store, committing the
950 * change to the collection, and comparing the resulting file.
951 */
952 if (!GetTempFileNameW(szDot, szPrefix, 0, filename))
953 return;
954
955 DeleteFileW(filename);
956 file = CreateFileW(filename, GENERIC_READ | GENERIC_WRITE, 0, NULL,
957 CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
958 if (file == INVALID_HANDLE_VALUE)
959 return;
960
961 store1 = CertOpenStore(CERT_STORE_PROV_FILE, 0, 0,
962 CERT_FILE_STORE_COMMIT_ENABLE_FLAG, file);
963 ok(store1 != NULL, "CertOpenStore failed: %08x\n", GetLastError());
964 CloseHandle(file);
965 CertAddStoreToCollection(collection, store1, CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
966 CertCloseStore(store1, 0);
967
968 ret = CertAddEncodedCertificateToStore(collection, X509_ASN_ENCODING,
969 bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, NULL);
970 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
971 GetLastError());
972 ret = CertControlStore(collection, 0, CERT_STORE_CTRL_COMMIT, NULL);
973 ok(ret, "CertControlStore failed: %d\n", ret);
974 compareStore(collection, "serialized store with cert",
975 serializedStoreWithCert, sizeof(serializedStoreWithCert), FALSE);
976 CertCloseStore(collection, 0);
977
978 DeleteFileW(filename);
979 }
980
981 /* Looks for the property with ID propID in the buffer buf. Returns a pointer
982 * to its header if found, NULL if not.
983 */
984 static const struct CertPropIDHeader *findPropID(const BYTE *buf, DWORD size,
985 DWORD propID)
986 {
987 const struct CertPropIDHeader *ret = NULL;
988 BOOL failed = FALSE;
989
990 while (size && !ret && !failed)
991 {
992 if (size < sizeof(struct CertPropIDHeader))
993 failed = TRUE;
994 else
995 {
996 const struct CertPropIDHeader *hdr =
997 (const struct CertPropIDHeader *)buf;
998
999 size -= sizeof(struct CertPropIDHeader);
1000 buf += sizeof(struct CertPropIDHeader);
1001 if (size < hdr->cb)
1002 failed = TRUE;
1003 else if (hdr->propID == propID)
1004 ret = hdr;
1005 else
1006 {
1007 buf += hdr->cb;
1008 size -= hdr->cb;
1009 }
1010 }
1011 }
1012 return ret;
1013 }
1014
1015 static void testRegStore(void)
1016 {
1017 static const char tempKey[] = "Software\\Wine\\CryptTemp";
1018 HCERTSTORE store;
1019 LONG rc;
1020 HKEY key = NULL;
1021 DWORD disp, GLE;
1022
1023 store = CertOpenStore(CERT_STORE_PROV_REG, 0, 0, 0, NULL);
1024 GLE = GetLastError();
1025 ok(!store && (GLE == ERROR_INVALID_HANDLE || GLE == ERROR_BADKEY),
1026 "Expected ERROR_INVALID_HANDLE or ERROR_BADKEY, got %d\n", GLE);
1027 store = CertOpenStore(CERT_STORE_PROV_REG, 0, 0, 0, key);
1028 GLE = GetLastError();
1029 ok(!store && (GLE == ERROR_INVALID_HANDLE || GLE == ERROR_BADKEY),
1030 "Expected ERROR_INVALID_HANDLE or ERROR_BADKEY, got %d\n", GLE);
1031
1032 /* Opening up any old key works.. */
1033 key = HKEY_CURRENT_USER;
1034 store = CertOpenStore(CERT_STORE_PROV_REG, 0, 0, 0, key);
1035 /* Not sure if this is a bug in DuplicateHandle, marking todo_wine for now
1036 */
1037 todo_wine ok(store != 0, "CertOpenStore failed: %08x\n", GetLastError());
1038 CertCloseStore(store, 0);
1039
1040 rc = RegCreateKeyExA(HKEY_CURRENT_USER, tempKey, 0, NULL, 0, KEY_ALL_ACCESS,
1041 NULL, &key, NULL);
1042 ok(!rc, "RegCreateKeyExA failed: %d\n", rc);
1043 if (key)
1044 {
1045 BOOL ret;
1046 BYTE hash[20];
1047 DWORD size, i;
1048 static const char certificates[] = "Certificates\\";
1049 char subKeyName[sizeof(certificates) + 20 * 2 + 1], *ptr;
1050 HKEY subKey;
1051 PCCERT_CONTEXT context;
1052
1053 store = CertOpenStore(CERT_STORE_PROV_REG, 0, 0, 0, key);
1054 ok(store != 0, "CertOpenStore failed: %08x\n", GetLastError());
1055 /* Add a certificate. It isn't persisted right away, since it's only
1056 * added to the cache..
1057 */
1058 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1059 bigCert2, sizeof(bigCert2), CERT_STORE_ADD_ALWAYS, NULL);
1060 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
1061 GetLastError());
1062 /* so flush the cache to force a commit.. */
1063 ret = CertControlStore(store, 0, CERT_STORE_CTRL_COMMIT, NULL);
1064 ok(ret, "CertControlStore failed: %08x\n", GetLastError());
1065 /* and check that the expected subkey was written. */
1066 size = sizeof(hash);
1067 ret = CryptHashCertificate(0, 0, 0, bigCert2, sizeof(bigCert2),
1068 hash, &size);
1069 ok(ret, "CryptHashCertificate failed: %d\n", GetLastError());
1070 strcpy(subKeyName, certificates);
1071 for (i = 0, ptr = subKeyName + sizeof(certificates) - 1; i < size;
1072 i++, ptr += 2)
1073 sprintf(ptr, "%02X", hash[i]);
1074 rc = RegCreateKeyExA(key, subKeyName, 0, NULL, 0, KEY_ALL_ACCESS, NULL,
1075 &subKey, NULL);
1076 ok(!rc, "RegCreateKeyExA failed: %d\n", rc);
1077 if (subKey)
1078 {
1079 LPBYTE buf;
1080
1081 size = 0;
1082 RegQueryValueExA(subKey, "Blob", NULL, NULL, NULL, &size);
1083 buf = HeapAlloc(GetProcessHeap(), 0, size);
1084 if (buf)
1085 {
1086 rc = RegQueryValueExA(subKey, "Blob", NULL, NULL, buf, &size);
1087 ok(!rc, "RegQueryValueExA failed: %d\n", rc);
1088 if (!rc)
1089 {
1090 const struct CertPropIDHeader *hdr;
1091
1092 /* Both the hash and the cert should be present */
1093 hdr = findPropID(buf, size, CERT_CERT_PROP_ID);
1094 ok(hdr != NULL, "Expected to find a cert property\n");
1095 if (hdr)
1096 {
1097 ok(hdr->cb == sizeof(bigCert2),
1098 "Wrong size %d of cert property\n", hdr->cb);
1099 ok(!memcmp((const BYTE *)hdr + sizeof(*hdr), bigCert2,
1100 hdr->cb), "Unexpected cert in cert property\n");
1101 }
1102 hdr = findPropID(buf, size, CERT_HASH_PROP_ID);
1103 ok(hdr != NULL, "Expected to find a hash property\n");
1104 if (hdr)
1105 {
1106 ok(hdr->cb == sizeof(hash),
1107 "Wrong size %d of hash property\n", hdr->cb);
1108 ok(!memcmp((const BYTE *)hdr + sizeof(*hdr), hash,
1109 hdr->cb), "Unexpected hash in cert property\n");
1110 }
1111 }
1112 HeapFree(GetProcessHeap(), 0, buf);
1113 }
1114 RegCloseKey(subKey);
1115 }
1116
1117 /* Remove the existing context */
1118 context = CertEnumCertificatesInStore(store, NULL);
1119 ok(context != NULL, "Expected a cert context\n");
1120 if (context)
1121 CertDeleteCertificateFromStore(context);
1122 ret = CertControlStore(store, 0, CERT_STORE_CTRL_COMMIT, NULL);
1123 ok(ret, "CertControlStore failed: %08x\n", GetLastError());
1124
1125 /* Add a serialized cert with a bogus hash directly to the registry */
1126 memset(hash, 0, sizeof(hash));
1127 strcpy(subKeyName, certificates);
1128 for (i = 0, ptr = subKeyName + sizeof(certificates) - 1;
1129 i < sizeof(hash); i++, ptr += 2)
1130 sprintf(ptr, "%02X", hash[i]);
1131 rc = RegCreateKeyExA(key, subKeyName, 0, NULL, 0, KEY_ALL_ACCESS, NULL,
1132 &subKey, NULL);
1133 ok(!rc, "RegCreateKeyExA failed: %d\n", rc);
1134 if (subKey)
1135 {
1136 BYTE buf[sizeof(struct CertPropIDHeader) * 2 + sizeof(hash) +
1137 sizeof(bigCert)], *ptr;
1138 DWORD certCount = 0;
1139 struct CertPropIDHeader *hdr;
1140
1141 hdr = (struct CertPropIDHeader *)buf;
1142 hdr->propID = CERT_HASH_PROP_ID;
1143 hdr->unknown1 = 1;
1144 hdr->cb = sizeof(hash);
1145 ptr = buf + sizeof(*hdr);
1146 memcpy(ptr, hash, sizeof(hash));
1147 ptr += sizeof(hash);
1148 hdr = (struct CertPropIDHeader *)ptr;
1149 hdr->propID = CERT_CERT_PROP_ID;
1150 hdr->unknown1 = 1;
1151 hdr->cb = sizeof(bigCert);
1152 ptr += sizeof(*hdr);
1153 memcpy(ptr, bigCert, sizeof(bigCert));
1154
1155 rc = RegSetValueExA(subKey, "Blob", 0, REG_BINARY, buf,
1156 sizeof(buf));
1157 ok(!rc, "RegSetValueExA failed: %d\n", rc);
1158
1159 ret = CertControlStore(store, 0, CERT_STORE_CTRL_RESYNC, NULL);
1160 ok(ret, "CertControlStore failed: %08x\n", GetLastError());
1161
1162 /* Make sure the bogus hash cert gets loaded. */
1163 certCount = 0;
1164 context = NULL;
1165 do {
1166 context = CertEnumCertificatesInStore(store, context);
1167 if (context)
1168 certCount++;
1169 } while (context != NULL);
1170 ok(certCount == 1, "Expected 1 certificates, got %d\n", certCount);
1171
1172 RegCloseKey(subKey);
1173 }
1174
1175 /* Add another serialized cert directly to the registry, this time
1176 * under the correct key name (named with the correct hash value).
1177 */
1178 size = sizeof(hash);
1179 ret = CryptHashCertificate(0, 0, 0, bigCert2,
1180 sizeof(bigCert2), hash, &size);
1181 ok(ret, "CryptHashCertificate failed: %d\n", GetLastError());
1182 strcpy(subKeyName, certificates);
1183 for (i = 0, ptr = subKeyName + sizeof(certificates) - 1;
1184 i < sizeof(hash); i++, ptr += 2)
1185 sprintf(ptr, "%02X", hash[i]);
1186 rc = RegCreateKeyExA(key, subKeyName, 0, NULL, 0, KEY_ALL_ACCESS, NULL,
1187 &subKey, NULL);
1188 ok(!rc, "RegCreateKeyExA failed: %d\n", rc);
1189 if (subKey)
1190 {
1191 BYTE buf[sizeof(struct CertPropIDHeader) * 2 + sizeof(hash) +
1192 sizeof(bigCert2)], *ptr;
1193 DWORD certCount = 0;
1194 PCCERT_CONTEXT context;
1195 struct CertPropIDHeader *hdr;
1196
1197 /* First try with a bogus hash... */
1198 hdr = (struct CertPropIDHeader *)buf;
1199 hdr->propID = CERT_HASH_PROP_ID;
1200 hdr->unknown1 = 1;
1201 hdr->cb = sizeof(hash);
1202 ptr = buf + sizeof(*hdr);
1203 memset(ptr, 0, sizeof(hash));
1204 ptr += sizeof(hash);
1205 hdr = (struct CertPropIDHeader *)ptr;
1206 hdr->propID = CERT_CERT_PROP_ID;
1207 hdr->unknown1 = 1;
1208 hdr->cb = sizeof(bigCert2);
1209 ptr += sizeof(*hdr);
1210 memcpy(ptr, bigCert2, sizeof(bigCert2));
1211
1212 rc = RegSetValueExA(subKey, "Blob", 0, REG_BINARY, buf,
1213 sizeof(buf));
1214 ok(!rc, "RegSetValueExA failed: %d\n", rc);
1215
1216 ret = CertControlStore(store, 0, CERT_STORE_CTRL_RESYNC, NULL);
1217 ok(ret, "CertControlStore failed: %08x\n", GetLastError());
1218
1219 /* and make sure just one cert still gets loaded. */
1220 certCount = 0;
1221 context = NULL;
1222 do {
1223 context = CertEnumCertificatesInStore(store, context);
1224 if (context)
1225 certCount++;
1226 } while (context != NULL);
1227 ok(certCount == 1, "Expected 1 certificate, got %d\n", certCount);
1228
1229 /* Try again with the correct hash... */
1230 ptr = buf + sizeof(*hdr);
1231 memcpy(ptr, hash, sizeof(hash));
1232
1233 rc = RegSetValueExA(subKey, "Blob", 0, REG_BINARY, buf,
1234 sizeof(buf));
1235 ok(!rc, "RegSetValueExA failed: %d\n", rc);
1236
1237 ret = CertControlStore(store, 0, CERT_STORE_CTRL_RESYNC, NULL);
1238 ok(ret, "CertControlStore failed: %08x\n", GetLastError());
1239
1240 /* and make sure two certs get loaded. */
1241 certCount = 0;
1242 context = NULL;
1243 do {
1244 context = CertEnumCertificatesInStore(store, context);
1245 if (context)
1246 certCount++;
1247 } while (context != NULL);
1248 ok(certCount == 2, "Expected 2 certificates, got %d\n", certCount);
1249
1250 RegCloseKey(subKey);
1251 }
1252 CertCloseStore(store, 0);
1253 /* Is delete allowed on a reg store? */
1254 store = CertOpenStore(CERT_STORE_PROV_REG, 0, 0,
1255 CERT_STORE_DELETE_FLAG, key);
1256 ok(store == NULL, "Expected NULL return from CERT_STORE_DELETE_FLAG\n");
1257 ok(GetLastError() == 0, "CertOpenStore failed: %08x\n",
1258 GetLastError());
1259
1260 RegCloseKey(key);
1261 }
1262 /* The CertOpenStore with CERT_STORE_DELETE_FLAG above will delete the
1263 * contents of the key, but not the key itself.
1264 */
1265 rc = RegCreateKeyExA(HKEY_CURRENT_USER, tempKey, 0, NULL, 0, KEY_ALL_ACCESS,
1266 NULL, &key, &disp);
1267 ok(!rc, "RegCreateKeyExA failed: %d\n", rc);
1268 ok(disp == REG_OPENED_EXISTING_KEY,
1269 "Expected REG_OPENED_EXISTING_KEY, got %d\n", disp);
1270 if (!rc)
1271 {
1272 RegCloseKey(key);
1273 rc = RegDeleteKeyA(HKEY_CURRENT_USER, tempKey);
1274 if (rc)
1275 {
1276 /* Use shlwapi's SHDeleteKeyA to _really_ blow away the key,
1277 * otherwise subsequent tests will fail.
1278 */
1279 SHDeleteKeyA(HKEY_CURRENT_USER, tempKey);
1280 }
1281 }
1282 }
1283
1284 static const char MyA[] = { 'M','y',0,0 };
1285 static const WCHAR MyW[] = { 'M','y',0 };
1286 static const WCHAR BogusW[] = { 'B','o','g','u','s',0 };
1287 static const WCHAR BogusPathW[] = { 'S','o','f','t','w','a','r','e','\\',
1288 'M','i','c','r','o','s','o','f','t','\\','S','y','s','t','e','m','C','e','r',
1289 't','i','f','i','c','a','t','e','s','\\','B','o','g','u','s',0 };
1290
1291 static void testSystemRegStore(void)
1292 {
1293 HCERTSTORE store, memStore;
1294
1295 /* Check with a UNICODE name */
1296 store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY, 0, 0,
1297 CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_OPEN_EXISTING_FLAG, MyW);
1298 /* Not all OSes support CERT_STORE_PROV_SYSTEM_REGISTRY, so don't continue
1299 * testing if they don't.
1300 */
1301 if (!store)
1302 return;
1303
1304 /* Check that it isn't a collection store */
1305 memStore = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
1306 CERT_STORE_CREATE_NEW_FLAG, NULL);
1307 if (memStore)
1308 {
1309 BOOL ret = CertAddStoreToCollection(store, memStore, 0, 0);
1310 ok(!ret && GetLastError() == E_INVALIDARG, "Expected E_INVALIDARG, got %08x\n", GetLastError());
1311 CertCloseStore(memStore, 0);
1312 }
1313 CertCloseStore(store, 0);
1314
1315 /* Check opening a bogus store */
1316 store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY, 0, 0,
1317 CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_OPEN_EXISTING_FLAG, BogusW);
1318 ok(!store && GetLastError() == ERROR_FILE_NOT_FOUND,
1319 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
1320 store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY, 0, 0,
1321 CERT_SYSTEM_STORE_CURRENT_USER, BogusW);
1322 ok(store != 0, "CertOpenStore failed: %08x\n", GetLastError());
1323 if (store)
1324 CertCloseStore(store, 0);
1325 /* Now check whether deleting is allowed */
1326 store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY, 0, 0,
1327 CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_DELETE_FLAG, BogusW);
1328 ok(!store, "CertOpenStore failed: %08x\n", GetLastError());
1329 RegDeleteKeyW(HKEY_CURRENT_USER, BogusPathW);
1330
1331 store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY, 0, 0, 0, NULL);
1332 ok(!store && GetLastError() == E_INVALIDARG,
1333 "Expected E_INVALIDARG, got %08x\n", GetLastError());
1334 store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY, 0, 0,
1335 CERT_SYSTEM_STORE_LOCAL_MACHINE | CERT_SYSTEM_STORE_CURRENT_USER, MyA);
1336 ok(!store && GetLastError() == E_INVALIDARG,
1337 "Expected E_INVALIDARG, got %08x\n", GetLastError());
1338 store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY, 0, 0,
1339 CERT_SYSTEM_STORE_LOCAL_MACHINE | CERT_SYSTEM_STORE_CURRENT_USER, MyW);
1340 ok(!store && GetLastError() == E_INVALIDARG,
1341 "Expected E_INVALIDARG, got %08x\n", GetLastError());
1342 /* The name is expected to be UNICODE, check with an ASCII name */
1343 store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY, 0, 0,
1344 CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_OPEN_EXISTING_FLAG, MyA);
1345 ok(!store && GetLastError() == ERROR_FILE_NOT_FOUND,
1346 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
1347 }
1348
1349 static void testSystemStore(void)
1350 {
1351 static const WCHAR baskslashW[] = { '\\',0 };
1352 HCERTSTORE store;
1353 WCHAR keyName[MAX_PATH];
1354 HKEY key;
1355 LONG rc;
1356
1357 store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0, 0, NULL);
1358 ok(!store && GetLastError() == ERROR_FILE_NOT_FOUND,
1359 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
1360 store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0,
1361 CERT_SYSTEM_STORE_LOCAL_MACHINE | CERT_SYSTEM_STORE_CURRENT_USER, MyA);
1362 ok(!store && GetLastError() == ERROR_FILE_NOT_FOUND,
1363 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
1364 store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0,
1365 CERT_SYSTEM_STORE_LOCAL_MACHINE | CERT_SYSTEM_STORE_CURRENT_USER, MyW);
1366 ok(!store && GetLastError() == ERROR_FILE_NOT_FOUND,
1367 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
1368 /* The name is expected to be UNICODE, first check with an ASCII name */
1369 store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0,
1370 CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_OPEN_EXISTING_FLAG, MyA);
1371 ok(!store && GetLastError() == ERROR_FILE_NOT_FOUND,
1372 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
1373 /* Create the expected key */
1374 lstrcpyW(keyName, CERT_LOCAL_MACHINE_SYSTEM_STORE_REGPATH);
1375 lstrcatW(keyName, baskslashW);
1376 lstrcatW(keyName, MyW);
1377 rc = RegCreateKeyExW(HKEY_CURRENT_USER, keyName, 0, NULL, 0, KEY_READ,
1378 NULL, &key, NULL);
1379 ok(!rc, "RegCreateKeyEx failed: %d\n", rc);
1380 if (!rc)
1381 RegCloseKey(key);
1382 /* Check opening with a UNICODE name, specifying the create new flag */
1383 store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0,
1384 CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_CREATE_NEW_FLAG, MyW);
1385 ok(!store && GetLastError() == ERROR_FILE_EXISTS,
1386 "Expected ERROR_FILE_EXISTS, got %08x\n", GetLastError());
1387 /* Now check opening with a UNICODE name, this time opening existing */
1388 store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0,
1389 CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_OPEN_EXISTING_FLAG, MyW);
1390 ok(store != 0, "CertOpenStore failed: %08x\n", GetLastError());
1391 if (store)
1392 {
1393 HCERTSTORE memStore = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
1394 CERT_STORE_CREATE_NEW_FLAG, NULL);
1395
1396 /* Check that it's a collection store */
1397 if (memStore)
1398 {
1399 BOOL ret = CertAddStoreToCollection(store, memStore, 0, 0);
1400 ok(ret, "CertAddStoreToCollection failed: %08x\n", GetLastError());
1401 CertCloseStore(memStore, 0);
1402 }
1403 CertCloseStore(store, 0);
1404 }
1405
1406 /* Check opening a bogus store */
1407 store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0,
1408 CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_OPEN_EXISTING_FLAG, BogusW);
1409 ok(!store, "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
1410 store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0,
1411 CERT_SYSTEM_STORE_CURRENT_USER, BogusW);
1412 ok(store != 0, "CertOpenStore failed: %08x\n", GetLastError());
1413 if (store)
1414 CertCloseStore(store, 0);
1415 /* Now check whether deleting is allowed */
1416 store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0,
1417 CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_DELETE_FLAG, BogusW);
1418 ok(!store, "Didn't expect a store to be returned when deleting\n");
1419 RegDeleteKeyW(HKEY_CURRENT_USER, BogusPathW);
1420 }
1421
1422 static const BYTE serializedStoreWithCertAndCRL[] = {
1423 0x00,0x00,0x00,0x00,0x43,0x45,0x52,0x54,0x20,0x00,0x00,0x00,0x01,0x00,0x00,
1424 0x00,0x7c,0x00,0x00,0x00,0x30,0x7a,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,
1425 0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,
1426 0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,
1427 0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,
1428 0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,
1429 0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,
1430 0x20,0x4c,0x61,0x6e,0x67,0x00,0x30,0x07,0x30,0x02,0x06,0x00,0x03,0x01,0x00,
1431 0xa3,0x16,0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,
1432 0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01,0x21,0x00,0x00,0x00,0x01,0x00,
1433 0x00,0x00,0x47,0x00,0x00,0x00,0x30,0x45,0x30,0x2c,0x30,0x02,0x06,0x00,0x30,
1434 0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,
1435 0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
1436 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00,0x03,0x11,
1437 0x00,0x0f,0x0e,0x0d,0x0c,0x0b,0x0a,0x09,0x08,0x07,0x06,0x05,0x04,0x03,0x02,
1438 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 };
1439
1440 static void testFileStore(void)
1441 {
1442 static const WCHAR szPrefix[] = { 'c','e','r',0 };
1443 static const WCHAR szDot[] = { '.',0 };
1444 WCHAR filename[MAX_PATH];
1445 HCERTSTORE store;
1446 BOOL ret;
1447 PCCERT_CONTEXT cert;
1448 HANDLE file;
1449
1450 store = CertOpenStore(CERT_STORE_PROV_FILE, 0, 0, 0, NULL);
1451 ok(!store && GetLastError() == ERROR_INVALID_HANDLE,
1452 "Expected ERROR_INVALID_HANDLE, got %08x\n", GetLastError());
1453
1454 if (!GetTempFileNameW(szDot, szPrefix, 0, filename))
1455 return;
1456
1457 DeleteFileW(filename);
1458 file = CreateFileW(filename, GENERIC_READ | GENERIC_WRITE, 0, NULL,
1459 CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
1460 if (file == INVALID_HANDLE_VALUE)
1461 return;
1462
1463 store = CertOpenStore(CERT_STORE_PROV_FILE, 0, 0, CERT_STORE_DELETE_FLAG,
1464 file);
1465 ok(!store && GetLastError() == E_INVALIDARG,
1466 "Expected E_INVALIDARG, got %08x\n", GetLastError());
1467 store = CertOpenStore(CERT_STORE_PROV_FILE, 0, 0,
1468 CERT_FILE_STORE_COMMIT_ENABLE_FLAG | CERT_STORE_READONLY_FLAG, file);
1469 ok(!store && GetLastError() == E_INVALIDARG,
1470 "Expected E_INVALIDARG, got %08x\n", GetLastError());
1471
1472 /* A "read-only" file store.. */
1473 store = CertOpenStore(CERT_STORE_PROV_FILE, 0, 0,
1474 CERT_STORE_OPEN_EXISTING_FLAG | CERT_STORE_READONLY_FLAG, file);
1475 ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError());
1476 if (store)
1477 {
1478 DWORD size;
1479
1480 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1481 bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, NULL);
1482 /* apparently allows adding certificates.. */
1483 ok(ret, "CertAddEncodedCertificateToStore failed: %d\n", ret);
1484 /* but not commits.. */
1485 ret = CertControlStore(store, 0, CERT_STORE_CTRL_COMMIT, NULL);
1486 ok(!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED,
1487 "Expected ERROR_CALL_NOT_IMPLEMENTED, got %08x\n", GetLastError());
1488 /* It still has certs in memory.. */
1489 cert = CertEnumCertificatesInStore(store, NULL);
1490 ok(cert != NULL, "CertEnumCertificatesInStore failed: %08x\n",
1491 GetLastError());
1492 CertFreeCertificateContext(cert);
1493 /* but the file size is still 0. */
1494 size = GetFileSize(file, NULL);
1495 ok(size == 0, "Expected size 0, got %d\n", size);
1496 CertCloseStore(store, 0);
1497 }
1498
1499 /* The create new flag is allowed.. */
1500 store = CertOpenStore(CERT_STORE_PROV_FILE, 0, 0,
1501 CERT_STORE_CREATE_NEW_FLAG, file);
1502 ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError());
1503 if (store)
1504 {
1505 /* but without the commit enable flag, commits don't happen. */
1506 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1507 bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, NULL);
1508 ok(ret, "CertAddEncodedCertificateToStore failed: %d\n", ret);
1509 ret = CertControlStore(store, 0, CERT_STORE_CTRL_COMMIT, NULL);
1510 ok(!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED,
1511 "Expected ERROR_CALL_NOT_IMPLEMENTED, got %08x\n", GetLastError());
1512 CertCloseStore(store, 0);
1513 }
1514 /* as is the open existing flag. */
1515 store = CertOpenStore(CERT_STORE_PROV_FILE, 0, 0,
1516 CERT_STORE_OPEN_EXISTING_FLAG, file);
1517 ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError());
1518 if (store)
1519 {
1520 /* but without the commit enable flag, commits don't happen. */
1521 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1522 bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, NULL);
1523 ok(ret, "CertAddEncodedCertificateToStore failed: %d\n", ret);
1524 ret = CertControlStore(store, 0, CERT_STORE_CTRL_COMMIT, NULL);
1525 ok(!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED,
1526 "Expected ERROR_CALL_NOT_IMPLEMENTED, got %08x\n", GetLastError());
1527 CertCloseStore(store, 0);
1528 }
1529 store = CertOpenStore(CERT_STORE_PROV_FILE, 0, 0,
1530 CERT_FILE_STORE_COMMIT_ENABLE_FLAG, file);
1531 ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError());
1532 if (store)
1533 {
1534 CloseHandle(file);
1535 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1536 bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, NULL);
1537 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
1538 GetLastError());
1539 /* with commits enabled, commit is allowed */
1540 ret = CertControlStore(store, 0, CERT_STORE_CTRL_COMMIT, NULL);
1541 ok(ret, "CertControlStore failed: %d\n", ret);
1542 compareStore(store, "serialized store with cert",
1543 serializedStoreWithCert, sizeof(serializedStoreWithCert), FALSE);
1544 CertCloseStore(store, 0);
1545 }
1546 file = CreateFileW(filename, GENERIC_READ | GENERIC_WRITE, 0, NULL,
1547 OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
1548 if (file == INVALID_HANDLE_VALUE)
1549 return;
1550 store = CertOpenStore(CERT_STORE_PROV_FILE, 0, 0,
1551 CERT_FILE_STORE_COMMIT_ENABLE_FLAG, file);
1552 ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError());
1553 if (store)
1554 {
1555 CloseHandle(file);
1556 ret = CertAddEncodedCRLToStore(store, X509_ASN_ENCODING, signedCRL,
1557 sizeof(signedCRL), CERT_STORE_ADD_ALWAYS, NULL);
1558 ok(ret, "CertAddEncodedCRLToStore failed: %08x\n", GetLastError());
1559 compareStore(store, "serialized store with cert and CRL",
1560 serializedStoreWithCertAndCRL, sizeof(serializedStoreWithCertAndCRL),
1561 FALSE);
1562 CertCloseStore(store, 0);
1563 }
1564
1565 DeleteFileW(filename);
1566 }
1567
1568 static BOOL initFileFromData(LPCWSTR filename, const BYTE *pb, DWORD cb)
1569 {
1570 HANDLE file = CreateFileW(filename, GENERIC_READ | GENERIC_WRITE, 0, NULL,
1571 CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
1572 BOOL ret;
1573
1574 if (file != INVALID_HANDLE_VALUE)
1575 {
1576 DWORD written;
1577
1578 ret = WriteFile(file, pb, cb, &written, NULL);
1579 CloseHandle(file);
1580 }
1581 else
1582 ret = FALSE;
1583 return ret;
1584 }
1585
1586 static const BYTE base64SPC[] =
1587 "MIICJQYJKoZIhvcNAQcCoIICFjCCAhICAQExADALBgkqhkiG9w0BBwGgggH6MIIB"
1588 "9jCCAV+gAwIBAgIQnP8+EF4opr9OxH7h4uBPWTANBgkqhkiG9w0BAQQFADAUMRIw"
1589 "EAYDVQQDEwlKdWFuIExhbmcwHhcNMDgxMjEyMTcxMDE0WhcNMzkxMjMxMjM1OTU5"
1590 "WjAUMRIwEAYDVQQDEwlKdWFuIExhbmcwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJ"
1591 "AoGBALCgNjyNvOic0FOfjxvi43HbM+D5joDkhiGSXe+gbZlf8f16k07kkObFEunz"
1592 "mdB5coscmA7gyqiWNN4ZUyr2cA3lCbnpGPA/0IblyyOcuGIFmmCzeZaVa5ZG6xZP"
1593 "K7L7o+73Qo6jXVbGhBGnMZ7Q9sAn6s2933olnStnejnqwV0NAgMBAAGjSTBHMEUG"
1594 "A1UdAQQ+MDyAEFKbKEdXYyx+CWKcV6vxM6ShFjAUMRIwEAYDVQQDEwlKdWFuIExh"
1595 "bmeCEJz/PhBeKKa/TsR+4eLgT1kwDQYJKoZIhvcNAQEEBQADgYEALpkgLgW3mEaK"
1596 "idPQ3iPJYLG0Ub1wraqEl9bd42hrhzIdcDzlQgxnm8/5cHYVxIF/C20x/HJplb1R"
1597 "G6U1ipFe/q8byWD/9JpiBKMGPi9YlUTgXHfS9d4S/QWO1h9Z7KeipBYhoslQpHXu"
1598 "y9bUr8Adqi6SzgHpCnMu53dxgxUD1r4xAA==";
1599 /* Same as base64SPC, but as a wide-char string */
1600 static const WCHAR utf16Base64SPC[] = {
1601 'M','I','I','C','J','Q','Y','J','K','o','Z','I','h','v','c','N','A',
1602 'Q','c','C','o','I','I','C','F','j','C','C','A','h','I','C','A','Q',
1603 'E','x','A','D','A','L','B','g','k','q','h','k','i','G','9','w','0',
1604 'B','B','w','G','g','g','g','H','6','M','I','I','B','9','j','C','C',
1605 'A','V','+','g','A','w','I','B','A','g','I','Q','n','P','8','+','E',
1606 'F','4','o','p','r','9','O','x','H','7','h','4','u','B','P','W','T',
1607 'A','N','B','g','k','q','h','k','i','G','9','w','0','B','A','Q','Q',
1608 'F','A','D','A','U','M','R','I','w','E','A','Y','D','V','Q','Q','D',
1609 'E','w','l','K','d','W','F','u','I','E','x','h','b','m','c','w','H',
1610 'h','c','N','M','D','g','x','M','j','E','y','M','T','c','x','M','D',
1611 'E','0','W','h','c','N','M','z','k','x','M','j','M','x','M','j','M',
1612 '1','O','T','U','5','W','j','A','U','M','R','I','w','E','A','Y','D',
1613 'V','Q','Q','D','E','w','l','K','d','W','F','u','I','E','x','h','b',
1614 'm','c','w','g','Z','8','w','D','Q','Y','J','K','o','Z','I','h','v',
1615 'c','N','A','Q','E','B','B','Q','A','D','g','Y','0','A','M','I','G',
1616 'J','A','o','G','B','A','L','C','g','N','j','y','N','v','O','i','c',
1617 '0','F','O','f','j','x','v','i','4','3','H','b','M','+','D','5','j',
1618 'o','D','k','h','i','G','S','X','e','+','g','b','Z','l','f','8','f',
1619 '1','6','k','0','7','k','k','O','b','F','E','u','n','z','m','d','B',
1620 '5','c','o','s','c','m','A','7','g','y','q','i','W','N','N','4','Z',
1621 'U','y','r','2','c','A','3','l','C','b','n','p','G','P','A','/','0',
1622 'I','b','l','y','y','O','c','u','G','I','F','m','m','C','z','e','Z',
1623 'a','V','a','5','Z','G','6','x','Z','P','K','7','L','7','o','+','7',
1624 '3','Q','o','6','j','X','V','b','G','h','B','G','n','M','Z','7','Q',
1625 '9','s','A','n','6','s','2','9','3','3','o','l','n','S','t','n','e',
1626 'j','n','q','w','V','0','N','A','g','M','B','A','A','G','j','S','T',
1627 'B','H','M','E','U','G','A','1','U','d','A','Q','Q','+','M','D','y',
1628 'A','E','F','K','b','K','E','d','X','Y','y','x','+','C','W','K','c',
1629 'V','6','v','x','M','6','S','h','F','j','A','U','M','R','I','w','E',
1630 'A','Y','D','V','Q','Q','D','E','w','l','K','d','W','F','u','I','E',
1631 'x','h','b','m','e','C','E','J','z','/','P','h','B','e','K','K','a',
1632 '/','T','s','R','+','4','e','L','g','T','1','k','w','D','Q','Y','J',
1633 'K','o','Z','I','h','v','c','N','A','Q','E','E','B','Q','A','D','g',
1634 'Y','E','A','L','p','k','g','L','g','W','3','m','E','a','K','i','d',
1635 'P','Q','3','i','P','J','Y','L','G','0','U','b','1','w','r','a','q',
1636 'E','l','9','b','d','4','2','h','r','h','z','I','d','c','D','z','l',
1637 'Q','g','x','n','m','8','/','5','c','H','Y','V','x','I','F','/','C',
1638 '2','0','x','/','H','J','p','l','b','1','R','G','6','U','1','i','p',
1639 'F','e','/','q','8','b','y','W','D','/','9','J','p','i','B','K','M',
1640 'G','P','i','9','Y','l','U','T','g','X','H','f','S','9','d','4','S',
1641 '/','Q','W','O','1','h','9','Z','7','K','e','i','p','B','Y','h','o',
1642 's','l','Q','p','H','X','u','y','9','b','U','r','8','A','d','q','i',
1643 '6','S','z','g','H','p','C','n','M','u','5','3','d','x','g','x','U',
1644 'D','1','r','4','x','A','A','=','=',0 };
1645
1646 static void testFileNameStore(void)
1647 {
1648 static const WCHAR szPrefix[] = { 'c','e','r',0 };
1649 static const WCHAR spcPrefix[] = { 's','p','c',0 };
1650 static const WCHAR szDot[] = { '.',0 };
1651 WCHAR filename[MAX_PATH];
1652 HCERTSTORE store;
1653 BOOL ret;
1654 DWORD GLE;
1655
1656 store = CertOpenStore(CERT_STORE_PROV_FILENAME_W, 0, 0, 0, NULL);
1657 GLE = GetLastError();
1658 ok(!store && (GLE == ERROR_PATH_NOT_FOUND || GLE == ERROR_INVALID_PARAMETER),
1659 "Expected ERROR_PATH_NOT_FOUND or ERROR_INVALID_PARAMETER, got %08x\n",
1660 GLE);
1661
1662 if (!GetTempFileNameW(szDot, szPrefix, 0, filename))
1663 return;
1664 DeleteFileW(filename);
1665
1666 /* The two flags are mutually exclusive */
1667 store = CertOpenStore(CERT_STORE_PROV_FILENAME_W, 0, 0,
1668 CERT_FILE_STORE_COMMIT_ENABLE_FLAG | CERT_STORE_READONLY_FLAG, filename);
1669 ok(!store && GetLastError() == E_INVALIDARG,
1670 "Expected E_INVALIDARG, got %08x\n", GetLastError());
1671
1672 /* In all of the following tests, the encoding type seems to be ignored */
1673 if (initFileFromData(filename, bigCert, sizeof(bigCert)))
1674 {
1675 PCCERT_CONTEXT cert;
1676 PCCRL_CONTEXT crl;
1677
1678 store = CertOpenStore(CERT_STORE_PROV_FILENAME_W, 0, 0,
1679 CERT_STORE_READONLY_FLAG, filename);
1680 ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError());
1681
1682 cert = CertEnumCertificatesInStore(store, NULL);
1683 ok(cert != NULL, "CertEnumCertificatesInStore failed: %08x\n",
1684 GetLastError());
1685 cert = CertEnumCertificatesInStore(store, cert);
1686 ok(!cert, "Expected only one cert\n");
1687 crl = CertEnumCRLsInStore(store, NULL);
1688 ok(!crl, "Expected no CRLs\n");
1689
1690 CertCloseStore(store, 0);
1691 DeleteFileW(filename);
1692 }
1693 if (initFileFromData(filename, serializedStoreWithCert,
1694 sizeof(serializedStoreWithCert)))
1695 {
1696 PCCERT_CONTEXT cert;
1697 PCCRL_CONTEXT crl;
1698
1699 store = CertOpenStore(CERT_STORE_PROV_FILENAME_W, 0, 0,
1700 CERT_STORE_READONLY_FLAG, filename);
1701 ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError());
1702
1703 cert = CertEnumCertificatesInStore(store, NULL);
1704 ok(cert != NULL, "CertEnumCertificatesInStore failed: %08x\n",
1705 GetLastError());
1706 cert = CertEnumCertificatesInStore(store, cert);
1707 ok(!cert, "Expected only one cert\n");
1708 crl = CertEnumCRLsInStore(store, NULL);
1709 ok(!crl, "Expected no CRLs\n");
1710
1711 CertCloseStore(store, 0);
1712 DeleteFileW(filename);
1713 }
1714 if (initFileFromData(filename, serializedStoreWithCertAndCRL,
1715 sizeof(serializedStoreWithCertAndCRL)))
1716 {
1717 PCCERT_CONTEXT cert;
1718 PCCRL_CONTEXT crl;
1719
1720 store = CertOpenStore(CERT_STORE_PROV_FILENAME_W, 0, 0,
1721 CERT_STORE_READONLY_FLAG, filename);
1722 ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError());
1723
1724 cert = CertEnumCertificatesInStore(store, NULL);
1725 ok(cert != NULL, "CertEnumCertificatesInStore failed: %08x\n",
1726 GetLastError());
1727 cert = CertEnumCertificatesInStore(store, cert);
1728 ok(!cert, "Expected only one cert\n");
1729 crl = CertEnumCRLsInStore(store, NULL);
1730 ok(crl != NULL, "CertEnumCRLsInStore failed: %08x\n", GetLastError());
1731 crl = CertEnumCRLsInStore(store, crl);
1732 ok(!crl, "Expected only one CRL\n");
1733
1734 CertCloseStore(store, 0);
1735 /* Don't delete it this time, the next test uses it */
1736 }
1737 /* Now that the file exists, we can open it read-only */
1738 store = CertOpenStore(CERT_STORE_PROV_FILENAME_W, 0, 0,
1739 CERT_STORE_READONLY_FLAG, filename);
1740 ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError());
1741 CertCloseStore(store, 0);
1742 DeleteFileW(filename);
1743
1744 store = CertOpenStore(CERT_STORE_PROV_FILENAME_W, 0, 0,
1745 CERT_FILE_STORE_COMMIT_ENABLE_FLAG | CERT_STORE_CREATE_NEW_FLAG, filename);
1746 ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError());
1747 if (store)
1748 {
1749 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1750 bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, NULL);
1751 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
1752 GetLastError());
1753 compareStore(store, "serialized store with cert",
1754 serializedStoreWithCert, sizeof(serializedStoreWithCert), FALSE);
1755 CertCloseStore(store, 0);
1756 }
1757 store = CertOpenStore(CERT_STORE_PROV_FILENAME_W, 0, 0,
1758 CERT_FILE_STORE_COMMIT_ENABLE_FLAG, filename);
1759 ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError());
1760 if (store)
1761 {
1762 ret = CertAddEncodedCRLToStore(store, X509_ASN_ENCODING,
1763 signedCRL, sizeof(signedCRL), CERT_STORE_ADD_ALWAYS, NULL);
1764 ok(ret, "CertAddEncodedCRLToStore failed: %08x\n", GetLastError());
1765 compareStore(store, "serialized store with cert and CRL",
1766 serializedStoreWithCertAndCRL, sizeof(serializedStoreWithCertAndCRL),
1767 FALSE);
1768 CertCloseStore(store, 0);
1769 }
1770 DeleteFileW(filename);
1771
1772 if (!GetTempFileNameW(szDot, spcPrefix, 0, filename))
1773 return;
1774 DeleteFileW(filename);
1775
1776 if (initFileFromData(filename, base64SPC, sizeof(base64SPC)))
1777 {
1778 PCCERT_CONTEXT cert;
1779 PCCRL_CONTEXT crl;
1780
1781 store = CertOpenStore(CERT_STORE_PROV_FILENAME_W, 0, 0,
1782 CERT_STORE_READONLY_FLAG, filename);
1783 ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError());
1784
1785 cert = CertEnumCertificatesInStore(store, NULL);
1786 ok(cert != NULL, "CertEnumCertificatesInStore failed: %08x\n",
1787 GetLastError());
1788 cert = CertEnumCertificatesInStore(store, cert);
1789 ok(!cert, "Expected only one cert\n");
1790 crl = CertEnumCRLsInStore(store, NULL);
1791 ok(!crl, "Expected no CRLs\n");
1792
1793 CertCloseStore(store, 0);
1794 DeleteFileW(filename);
1795 }
1796 if (initFileFromData(filename, (BYTE *)utf16Base64SPC,
1797 sizeof(utf16Base64SPC)))
1798 {
1799 PCCERT_CONTEXT cert;
1800 PCCRL_CONTEXT crl;
1801
1802 store = CertOpenStore(CERT_STORE_PROV_FILENAME_W, 0, 0,
1803 CERT_STORE_READONLY_FLAG, filename);
1804 ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError());
1805
1806 cert = CertEnumCertificatesInStore(store, NULL);
1807 ok(cert != NULL, "CertEnumCertificatesInStore failed: %08x\n",
1808 GetLastError());
1809 cert = CertEnumCertificatesInStore(store, cert);
1810 ok(!cert, "Expected only one cert\n");
1811 crl = CertEnumCRLsInStore(store, NULL);
1812 ok(!crl, "Expected no CRLs\n");
1813
1814 CertCloseStore(store, 0);
1815 DeleteFileW(filename);
1816 }
1817 }
1818
1819 static const BYTE signedContent[] = {
1820 0x30,0x81,0xb2,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,0xa0,
1821 0x81,0xa4,0x30,0x81,0xa1,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,
1822 0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x13,0x06,0x09,0x2a,0x86,
1823 0x48,0x86,0xf7,0x0d,0x01,0x07,0x01,0xa0,0x06,0x04,0x04,0x01,0x02,0x03,0x04,
1824 0x31,0x77,0x30,0x75,0x02,0x01,0x01,0x30,0x1a,0x30,0x15,0x31,0x13,0x30,0x11,
1825 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
1826 0x67,0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,
1827 0x02,0x05,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04,0x40,0x81,0xa6,0x70,
1828 0xb3,0xef,0x59,0xd1,0x66,0xd1,0x9b,0xc0,0x9a,0xb6,0x9a,0x5e,0x6d,0x6f,0x6d,
1829 0x0d,0x59,0xa9,0xaa,0x6e,0xe9,0x2c,0xa0,0x1e,0xee,0xc2,0x60,0xbc,0x59,0xbe,
1830 0x3f,0x63,0x06,0x8d,0xc9,0x11,0x1d,0x23,0x64,0x92,0xef,0x2e,0xfc,0x57,0x29,
1831 0xa4,0xaf,0xe0,0xee,0x93,0x19,0x39,0x51,0xe4,0x44,0xb8,0x0b,0x28,0xf4,0xa8,
1832 0x0d };
1833 static const BYTE signedWithCertAndCrlBareContent[] = {
1834 0x30,0x82,0x01,0x4f,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,0x86,
1835 0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x13,0x06,0x09,0x2a,0x86,0x48,
1836 0x86,0xf7,0x0d,0x01,0x07,0x01,0xa0,0x06,0x04,0x04,0x01,0x02,0x03,0x04,0xa0,
1837 0x7c,0x30,0x7a,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,
1838 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
1839 0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,
1840 0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
1841 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,
1842 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
1843 0x67,0x00,0x30,0x07,0x30,0x02,0x06,0x00,0x03,0x01,0x00,0xa3,0x16,0x30,0x14,
1844 0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,
1845 0x01,0xff,0x02,0x01,0x01,0xa1,0x2e,0x30,0x2c,0x30,0x02,0x06,0x00,0x30,0x15,
1846 0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,
1847 0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
1848 0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x31,0x77,0x30,0x75,0x02,0x01,0x01,
1849 0x30,0x1a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,
1850 0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x02,0x01,0x01,0x30,0x0c,
1851 0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x04,0x06,
1852 0x00,0x05,0x00,0x04,0x40,0x81,0xa6,0x70,0xb3,0xef,0x59,0xd1,0x66,0xd1,0x9b,
1853 0xc0,0x9a,0xb6,0x9a,0x5e,0x6d,0x6f,0x6d,0x0d,0x59,0xa9,0xaa,0x6e,0xe9,0x2c,
1854 0xa0,0x1e,0xee,0xc2,0x60,0xbc,0x59,0xbe,0x3f,0x63,0x06,0x8d,0xc9,0x11,0x1d,
1855 0x23,0x64,0x92,0xef,0x2e,0xfc,0x57,0x29,0xa4,0xaf,0xe0,0xee,0x93,0x19,0x39,
1856 0x51,0xe4,0x44,0xb8,0x0b,0x28,0xf4,0xa8,0x0d };
1857 static const BYTE hashContent[] = {
1858 0x30,0x47,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x05,0xa0,0x3a,
1859 0x30,0x38,0x02,0x01,0x00,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,
1860 0x02,0x05,0x05,0x00,0x30,0x13,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
1861 0x07,0x01,0xa0,0x06,0x04,0x04,0x01,0x02,0x03,0x04,0x04,0x10,0x08,0xd6,0xc0,
1862 0x5a,0x21,0x51,0x2a,0x79,0xa1,0xdf,0xeb,0x9d,0x2a,0x8f,0x26,0x2f };
1863 static const BYTE hashBareContent[] = {
1864 0x30,0x38,0x02,0x01,0x00,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,
1865 0x02,0x05,0x05,0x00,0x30,0x13,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
1866 0x07,0x01,0xa0,0x06,0x04,0x04,0x01,0x02,0x03,0x04,0x04,0x10,0x08,0xd6,0xc0,
1867 0x5a,0x21,0x51,0x2a,0x79,0xa1,0xdf,0xeb,0x9d,0x2a,0x8f,0x26,0x2f };
1868
1869 static void testMessageStore(void)
1870 {
1871 HCERTSTORE store;
1872 HCRYPTMSG msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL,
1873 NULL);
1874 CRYPT_DATA_BLOB blob = { sizeof(signedWithCertAndCrlBareContent),
1875 (LPBYTE)signedWithCertAndCrlBareContent };
1876 DWORD count, size;
1877 BOOL ret;
1878
1879 /* Crashes
1880 store = CertOpenStore(CERT_STORE_PROV_MSG, 0, 0, 0, NULL);
1881 */
1882 SetLastError(0xdeadbeef);
1883 store = CertOpenStore(CERT_STORE_PROV_MSG, 0, 0, 0, msg);
1884 ok(!store && GetLastError() == CRYPT_E_INVALID_MSG_TYPE,
1885 "Expected CRYPT_E_INVALID_MSG_TYPE, got %08x\n", GetLastError());
1886 CryptMsgUpdate(msg, signedContent, sizeof(signedContent), TRUE);
1887 store = CertOpenStore(CERT_STORE_PROV_MSG, 0, 0, 0, msg);
1888 ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError());
1889 if (store)
1890 {
1891 PCCERT_CONTEXT cert = NULL;
1892 PCCRL_CONTEXT crl = NULL;
1893
1894 count = 0;
1895 do {
1896 cert = CertEnumCertificatesInStore(store, cert);
1897 if (cert)
1898 count++;
1899 } while (cert);
1900 ok(count == 0, "Expected 0 certificates, got %d\n", count);
1901
1902 count = 0;
1903 do {
1904 crl = CertEnumCRLsInStore(store, crl);
1905 if (crl)
1906 count++;
1907 } while (crl);
1908 ok(count == 0, "Expected 0 CRLs, got %d\n", count);
1909
1910 /* Can add certs to a message store */
1911 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1912 bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, NULL);
1913 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
1914 GetLastError());
1915 count = 0;
1916 do {
1917 cert = CertEnumCertificatesInStore(store, cert);
1918 if (cert)
1919 count++;
1920 } while (cert);
1921 ok(count == 1, "Expected 1 certificate, got %d\n", count);
1922
1923 CertCloseStore(store, 0);
1924 }
1925 /* but the added certs weren't actually added to the message */
1926 size = sizeof(count);
1927 ret = CryptMsgGetParam(msg, CMSG_CERT_COUNT_PARAM, 0, &count, &size);
1928 ok(ret, "CryptMsgGetParam failed: %08x\n", GetLastError());
1929 ok(count == 0, "Expected 0 certificates, got %d\n", count);
1930 CryptMsgClose(msg);
1931
1932 /* Crashes
1933 store = CertOpenStore(CERT_STORE_PROV_PKCS7, 0, 0, 0, NULL);
1934 */
1935 store = CertOpenStore(CERT_STORE_PROV_PKCS7, 0, 0, 0, &blob);
1936 ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError());
1937 if (store)
1938 {
1939 DWORD count = 0;
1940 PCCERT_CONTEXT cert = NULL;
1941 PCCRL_CONTEXT crl = NULL;
1942
1943 do {
1944 cert = CertEnumCertificatesInStore(store, cert);
1945 if (cert)
1946 count++;
1947 } while (cert);
1948 ok(count == 1, "Expected 1 certificate, got %d\n", count);
1949
1950 count = 0;
1951 do {
1952 crl = CertEnumCRLsInStore(store, crl);
1953 if (crl)
1954 count++;
1955 } while (crl);
1956 ok(count == 1, "Expected 1 CRL, got %d\n", count);
1957
1958 CertCloseStore(store, 0);
1959 }
1960 /* Encoding appears to be ignored */
1961 store = CertOpenStore(CERT_STORE_PROV_PKCS7, X509_ASN_ENCODING, 0, 0,
1962 &blob);
1963 ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError());
1964 if (store)
1965 CertCloseStore(store, 0);
1966 /* Messages other than signed messages aren't allowed */
1967 blob.cbData = sizeof(hashContent);
1968 blob.pbData = (LPBYTE)hashContent;
1969 SetLastError(0xdeadbeef);
1970 store = CertOpenStore(CERT_STORE_PROV_PKCS7, 0, 0, 0, &blob);
1971 ok(!store && GetLastError() == CRYPT_E_INVALID_MSG_TYPE,
1972 "Expected CRYPT_E_INVALID_MSG_TYPE, got %08x\n", GetLastError());
1973 blob.cbData = sizeof(hashBareContent);
1974 blob.pbData = (LPBYTE)hashBareContent;
1975 SetLastError(0xdeadbeef);
1976 store = CertOpenStore(CERT_STORE_PROV_PKCS7, 0, 0, 0, &blob);
1977 ok(!store && GetLastError() == CRYPT_E_ASN1_BADTAG,
1978 "Expected CRYPT_E_ASN1_BADTAG, got %08x\n", GetLastError());
1979 }
1980
1981 static void testSerializedStore(void)
1982 {
1983 HCERTSTORE store;
1984 CRYPT_DATA_BLOB blob;
1985
1986 if (0)
1987 {
1988 /* Crash */
1989 store = CertOpenStore(CERT_STORE_PROV_SERIALIZED, 0, 0, 0, NULL);
1990 store = CertOpenStore(CERT_STORE_PROV_SERIALIZED, 0, 0,
1991 CERT_STORE_DELETE_FLAG, NULL);
1992 }
1993 blob.cbData = sizeof(serializedStoreWithCert);
1994 blob.pbData = (BYTE *)serializedStoreWithCert;
1995 store = CertOpenStore(CERT_STORE_PROV_SERIALIZED, 0, 0,
1996 CERT_STORE_DELETE_FLAG, &blob);
1997 ok(!store && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED,
1998 "Expected ERROR_CALL_NOT_IMPLEMENTED, got %08x\n", GetLastError());
1999 store = CertOpenStore(CERT_STORE_PROV_SERIALIZED, 0, 0, 0, &blob);
2000 ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError());
2001 if (store)
2002 {
2003 PCCERT_CONTEXT cert;
2004 PCCRL_CONTEXT crl;
2005
2006 cert = CertEnumCertificatesInStore(store, NULL);
2007 ok(cert != NULL, "CertEnumCertificatesInStore failed: %08x\n",
2008 GetLastError());
2009 cert = CertEnumCertificatesInStore(store, cert);
2010 ok(!cert, "Expected only one cert\n");
2011 crl = CertEnumCRLsInStore(store, NULL);
2012 ok(!crl, "Expected no CRLs\n");
2013
2014 CertCloseStore(store, 0);
2015 }
2016 blob.cbData = sizeof(serializedStoreWithCertAndCRL);
2017 blob.pbData = (BYTE *)serializedStoreWithCertAndCRL;
2018 store = CertOpenStore(CERT_STORE_PROV_SERIALIZED, 0, 0, 0, &blob);
2019 ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError());
2020 if (store)
2021 {
2022 PCCERT_CONTEXT cert;
2023 PCCRL_CONTEXT crl;
2024
2025 cert = CertEnumCertificatesInStore(store, NULL);
2026 ok(cert != NULL, "CertEnumCertificatesInStore failed: %08x\n",
2027 GetLastError());
2028 cert = CertEnumCertificatesInStore(store, cert);
2029 ok(!cert, "Expected only one cert\n");
2030 crl = CertEnumCRLsInStore(store, NULL);
2031 ok(crl != NULL, "CertEnumCRLsInStore failed: %08x\n",
2032 GetLastError());
2033 crl = CertEnumCRLsInStore(store, crl);
2034 ok(!crl, "Expected only one CRL\n");
2035
2036 CertCloseStore(store, 0);
2037 }
2038 }
2039
2040 static void testCertOpenSystemStore(void)
2041 {
2042 HCERTSTORE store;
2043
2044 store = CertOpenSystemStoreW(0, NULL);
2045 ok(!store && GetLastError() == E_INVALIDARG,
2046 "Expected E_INVALIDARG, got %08x\n", GetLastError());
2047 /* This succeeds, and on WinXP at least, the Bogus key is created under
2048 * HKCU (but not under HKLM, even when run as an administrator.)
2049 */
2050 store = CertOpenSystemStoreW(0, BogusW);
2051 ok(store != 0, "CertOpenSystemStore failed: %08x\n", GetLastError());
2052 if (store)
2053 CertCloseStore(store, 0);
2054 /* Delete it so other tests succeed next time around */
2055 CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0,
2056 CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_DELETE_FLAG, BogusW);
2057 RegDeleteKeyW(HKEY_CURRENT_USER, BogusPathW);
2058 }
2059
2060 static const struct
2061 {
2062 DWORD cert_store;
2063 BOOL expected;
2064 BOOL todo;
2065 } reg_system_store_test_data[] = {
2066 { CERT_SYSTEM_STORE_CURRENT_USER, TRUE, 0},
2067 /* Following tests could require administrator privileges and thus could be skipped */
2068 { CERT_SYSTEM_STORE_CURRENT_SERVICE, TRUE, 1},
2069 { CERT_SYSTEM_STORE_LOCAL_MACHINE, TRUE, 0},
2070 { CERT_SYSTEM_STORE_LOCAL_MACHINE_GROUP_POLICY, TRUE, 0},
2071 { CERT_SYSTEM_STORE_CURRENT_USER_GROUP_POLICY, TRUE, 0},
2072 { CERT_SYSTEM_STORE_LOCAL_MACHINE_ENTERPRISE, TRUE, 1}
2073 };
2074
2075 static void testCertRegisterSystemStore(void)
2076 {
2077 BOOL ret, cur_flag;
2078 DWORD err = 0;
2079 HCERTSTORE hstore;
2080 static const WCHAR WineTestW[] = {'W','i','n','e','T','e','s','t',0};
2081 const CERT_CONTEXT *cert, *cert2;
2082 unsigned int i;
2083
2084 for (i = 0; i < ARRAY_SIZE(reg_system_store_test_data); i++) {
2085 cur_flag = reg_system_store_test_data[i].cert_store;
2086 ret = CertRegisterSystemStore(WineTestW, cur_flag, NULL, NULL);
2087 if (!ret)
2088 {
2089 err = GetLastError();
2090 if (err == ERROR_ACCESS_DENIED)
2091 {
2092 win_skip("Insufficient privileges for the flag %08x test\n", cur_flag);
2093 continue;
2094 }
2095 }
2096 todo_wine_if (reg_system_store_test_data[i].todo)
2097 ok (ret == reg_system_store_test_data[i].expected,
2098 "Store registration (dwFlags=%08x) failed, last error %x\n", cur_flag, err);
2099 if (!ret)
2100 {
2101 skip("Nothing to test without registered store at %08x\n", cur_flag);
2102 continue;
2103 }
2104
2105 hstore = CertOpenStore(CERT_STORE_PROV_SYSTEM_W, 0, 0, CERT_STORE_OPEN_EXISTING_FLAG | cur_flag, WineTestW);
2106 ok (hstore != NULL, "Opening just registered store at %08x failed, last error %x\n", cur_flag, GetLastError());
2107
2108 cert = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert, sizeof(bigCert));
2109 ok (cert != NULL, "Failed creating cert at %08x, last error: %x\n", cur_flag, GetLastError());
2110 if (cert)
2111 {
2112 ret = CertAddCertificateContextToStore(hstore, cert, CERT_STORE_ADD_NEW, NULL);
2113 ok (ret, "Failed to add cert at %08x, last error: %x\n", cur_flag, GetLastError());
2114
2115 cert2 = CertEnumCertificatesInStore(hstore, NULL);
2116 ok (cert2 != NULL && cert2->cbCertEncoded == cert->cbCertEncoded,
2117 "Unexpected cert encoded size at %08x, last error: %x\n", cur_flag, GetLastError());
2118
2119 ret = CertDeleteCertificateFromStore(cert2);
2120 ok (ret, "Failed to delete certificate from the new store at %08x, last error: %x\n", cur_flag, GetLastError());
2121
2122 CertFreeCertificateContext(cert);
2123 }
2124
2125 ret = CertCloseStore(hstore, 0);
2126 ok (ret, "CertCloseStore failed at %08x, last error %x\n", cur_flag, GetLastError());
2127
2128 ret = CertUnregisterSystemStore(WineTestW, cur_flag );
2129 todo_wine_if (reg_system_store_test_data[i].todo)
2130 ok( ret == reg_system_store_test_data[i].expected,
2131 "Unregistering failed at %08x, last error %d\n", cur_flag, GetLastError());
2132 }
2133
2134 }
2135
2136 struct EnumSystemStoreInfo
2137 {
2138 BOOL goOn;
2139 DWORD storeCount;
2140 };
2141
2142 static BOOL CALLBACK enumSystemStoreCB(const void *systemStore, DWORD dwFlags,
2143 PCERT_SYSTEM_STORE_INFO pStoreInfo, void *pvReserved, void *pvArg)
2144 {
2145 struct EnumSystemStoreInfo *info = pvArg;
2146
2147 info->storeCount++;
2148 return info->goOn;
2149 }
2150
2151 static void testCertEnumSystemStore(void)
2152 {
2153 BOOL ret;
2154 struct EnumSystemStoreInfo info = { FALSE, 0 };
2155
2156 SetLastError(0xdeadbeef);
2157 ret = CertEnumSystemStore(0, NULL, NULL, NULL);
2158 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2159 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2160 /* Crashes
2161 ret = CertEnumSystemStore(CERT_SYSTEM_STORE_LOCAL_MACHINE, NULL, NULL,
2162 NULL);
2163 */
2164
2165 SetLastError(0xdeadbeef);
2166 ret = CertEnumSystemStore(CERT_SYSTEM_STORE_LOCAL_MACHINE, NULL, &info,
2167 enumSystemStoreCB);
2168 /* Callback returning FALSE stops enumeration */
2169 ok(!ret, "Expected CertEnumSystemStore to stop\n");
2170 ok(info.storeCount == 0 || info.storeCount == 1,
2171 "Expected 0 or 1 stores\n");
2172
2173 info.goOn = TRUE;
2174 info.storeCount = 0;
2175 ret = CertEnumSystemStore(CERT_SYSTEM_STORE_LOCAL_MACHINE, NULL, &info,
2176 enumSystemStoreCB);
2177 ok(ret, "CertEnumSystemStore failed: %08x\n", GetLastError());
2178 /* There should always be at least My, Root, and CA stores */
2179 ok(info.storeCount == 0 || info.storeCount >= 3,
2180 "Expected at least 3 stores\n");
2181 }
2182
2183 static void testStoreProperty(void)
2184 {
2185 HCERTSTORE store;
2186 BOOL ret;
2187 DWORD propID, size = 0, state;
2188 CRYPT_DATA_BLOB blob;
2189
2190 /* Crash
2191 ret = CertGetStoreProperty(NULL, 0, NULL, NULL);
2192 ret = CertGetStoreProperty(NULL, 0, NULL, &size);
2193 ret = CertGetStoreProperty(store, 0, NULL, NULL);
2194 */
2195
2196 store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
2197 CERT_STORE_CREATE_NEW_FLAG, NULL);
2198 /* Check a missing prop ID */
2199 SetLastError(0xdeadbeef);
2200 ret = CertGetStoreProperty(store, 0, NULL, &size);
2201 ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
2202 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
2203 /* Contrary to MSDN, CERT_ACCESS_STATE_PROP_ID is supported for stores.. */
2204 size = sizeof(state);
2205 ret = CertGetStoreProperty(store, CERT_ACCESS_STATE_PROP_ID, &state, &size);
2206 ok(ret, "CertGetStoreProperty failed for CERT_ACCESS_STATE_PROP_ID: %08x\n",
2207 GetLastError());
2208 ok(!state, "Expected a non-persisted store\n");
2209 /* and CERT_STORE_LOCALIZED_NAME_PROP_ID isn't supported by default. */
2210 size = 0;
2211 ret = CertGetStoreProperty(store, CERT_STORE_LOCALIZED_NAME_PROP_ID, NULL,
2212 &size);
2213 ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
2214 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
2215 /* Delete an arbitrary property on a store */
2216 ret = CertSetStoreProperty(store, CERT_FIRST_USER_PROP_ID, 0, NULL);
2217 ok(ret, "CertSetStoreProperty failed: %08x\n", GetLastError());
2218 /* Set an arbitrary property on a store */
2219 blob.pbData = (LPBYTE)&state;
2220 blob.cbData = sizeof(state);
2221 ret = CertSetStoreProperty(store, CERT_FIRST_USER_PROP_ID, 0, &blob);
2222 ok(ret, "CertSetStoreProperty failed: %08x\n", GetLastError());
2223 /* Get an arbitrary property that's been set */
2224 ret = CertGetStoreProperty(store, CERT_FIRST_USER_PROP_ID, NULL, &size);
2225 ok(ret, "CertGetStoreProperty failed: %08x\n", GetLastError());
2226 ok(size == sizeof(state), "Unexpected data size %d\n", size);
2227 ret = CertGetStoreProperty(store, CERT_FIRST_USER_PROP_ID, &propID, &size);
2228 ok(ret, "CertGetStoreProperty failed: %08x\n", GetLastError());
2229 ok(propID == state, "CertGetStoreProperty got the wrong value\n");
2230 /* Delete it again */
2231 ret = CertSetStoreProperty(store, CERT_FIRST_USER_PROP_ID, 0, NULL);
2232 ok(ret, "CertSetStoreProperty failed: %08x\n", GetLastError());
2233 /* And check that it's missing */
2234 SetLastError(0xdeadbeef);
2235 ret = CertGetStoreProperty(store, CERT_FIRST_USER_PROP_ID, NULL, &size);
2236 ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
2237 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
2238 CertCloseStore(store, 0);
2239
2240 /* Recheck on the My store.. */
2241 store = CertOpenSystemStoreW(0, MyW);
2242 size = sizeof(state);
2243 ret = CertGetStoreProperty(store, CERT_ACCESS_STATE_PROP_ID, &state, &size);
2244 ok(ret, "CertGetStoreProperty failed for CERT_ACCESS_STATE_PROP_ID: %08x\n",
2245 GetLastError());
2246 ok(state, "Expected a persisted store\n");
2247 SetLastError(0xdeadbeef);
2248 size = 0;
2249 ret = CertGetStoreProperty(store, CERT_STORE_LOCALIZED_NAME_PROP_ID, NULL,
2250 &size);
2251 ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
2252 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
2253 CertCloseStore(store, 0);
2254 }
2255
2256 static void testAddSerialized(void)
2257 {
2258 BOOL ret;
2259 HCERTSTORE store;
2260 BYTE buf[sizeof(struct CertPropIDHeader) * 2 + 20 + sizeof(bigCert)] =
2261 { 0 };
2262 BYTE hash[20];
2263 struct CertPropIDHeader *hdr;
2264 PCCERT_CONTEXT context;
2265
2266 ret = CertAddSerializedElementToStore(0, NULL, 0, 0, 0, 0, NULL, NULL);
2267 ok(!ret && GetLastError() == ERROR_END_OF_MEDIA,
2268 "Expected ERROR_END_OF_MEDIA, got %08x\n", GetLastError());
2269
2270 store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
2271 CERT_STORE_CREATE_NEW_FLAG, NULL);
2272 ok(store != 0, "CertOpenStore failed: %08x\n", GetLastError());
2273
2274 ret = CertAddSerializedElementToStore(store, NULL, 0, 0, 0, 0, NULL, NULL);
2275 ok(!ret && GetLastError() == ERROR_END_OF_MEDIA,
2276 "Expected ERROR_END_OF_MEDIA, got %08x\n", GetLastError());
2277
2278 /* Test with an empty property */
2279 hdr = (struct CertPropIDHeader *)buf;
2280 hdr->propID = CERT_CERT_PROP_ID;
2281 hdr->unknown1 = 1;
2282 hdr->cb = 0;
2283 ret = CertAddSerializedElementToStore(store, buf, sizeof(buf), 0, 0, 0,
2284 NULL, NULL);
2285 ok(!ret && GetLastError() == E_INVALIDARG,
2286 "Expected E_INVALIDARG, got %08x\n", GetLastError());
2287 /* Test with a bad size in property header */
2288 hdr->cb = sizeof(bigCert) - 1;
2289 memcpy(buf + sizeof(struct CertPropIDHeader), bigCert, sizeof(bigCert));
2290 ret = CertAddSerializedElementToStore(store, buf, sizeof(buf), 0, 0, 0,
2291 NULL, NULL);
2292 ok(!ret && GetLastError() == E_INVALIDARG,
2293 "Expected E_INVALIDARG, got %08x\n", GetLastError());
2294 ret = CertAddSerializedElementToStore(store, buf,
2295 sizeof(struct CertPropIDHeader) + sizeof(bigCert), 0, 0, 0, NULL,
2296 NULL);
2297 ok(!ret && GetLastError() == E_INVALIDARG,
2298 "Expected E_INVALIDARG, got %08x\n", GetLastError());
2299 ret = CertAddSerializedElementToStore(store, buf,
2300 sizeof(struct CertPropIDHeader) + sizeof(bigCert), CERT_STORE_ADD_NEW,
2301 0, 0, NULL, NULL);
2302 ok(!ret && GetLastError() == E_INVALIDARG,
2303 "Expected E_INVALIDARG, got %08x\n", GetLastError());
2304 /* Kosher size in property header, but no context type */
2305 hdr->cb = sizeof(bigCert);
2306 ret = CertAddSerializedElementToStore(store, buf, sizeof(buf), 0, 0, 0,
2307 NULL, NULL);
2308 ok(!ret && GetLastError() == E_INVALIDARG,
2309 "Expected E_INVALIDARG, got %08x\n", GetLastError());
2310 ret = CertAddSerializedElementToStore(store, buf,
2311 sizeof(struct CertPropIDHeader) + sizeof(bigCert), 0, 0, 0, NULL,
2312 NULL);
2313 ok(!ret && GetLastError() == E_INVALIDARG,
2314 "Expected E_INVALIDARG, got %08x\n", GetLastError());
2315 ret = CertAddSerializedElementToStore(store, buf,
2316 sizeof(struct CertPropIDHeader) + sizeof(bigCert), CERT_STORE_ADD_NEW,
2317 0, 0, NULL, NULL);
2318 ok(!ret && GetLastError() == E_INVALIDARG,
2319 "Expected E_INVALIDARG, got %08x\n", GetLastError());
2320 /* With a bad context type */
2321 ret = CertAddSerializedElementToStore(store, buf, sizeof(buf), 0, 0,
2322 CERT_STORE_CRL_CONTEXT_FLAG, NULL, NULL);
2323 ok(!ret && GetLastError() == E_INVALIDARG,
2324 "Expected E_INVALIDARG, got %08x\n", GetLastError());
2325 ret = CertAddSerializedElementToStore(store, buf,
2326 sizeof(struct CertPropIDHeader) + sizeof(bigCert), 0, 0,
2327 CERT_STORE_CRL_CONTEXT_FLAG, NULL, NULL);
2328 ok(!ret && GetLastError() == E_INVALIDARG,
2329 "Expected E_INVALIDARG, got %08x\n", GetLastError());
2330 ret = CertAddSerializedElementToStore(store, buf,
2331 sizeof(struct CertPropIDHeader) + sizeof(bigCert), CERT_STORE_ADD_NEW,
2332 0, CERT_STORE_CRL_CONTEXT_FLAG, NULL, NULL);
2333 ok(!ret && GetLastError() == E_INVALIDARG,
2334 "Expected E_INVALIDARG, got %08x\n", GetLastError());
2335 /* Bad unknown field, good type */
2336 hdr->unknown1 = 2;
2337 ret = CertAddSerializedElementToStore(store, buf, sizeof(buf), 0, 0,
2338 CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL, NULL);
2339 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2340 "Expected ERROR_FILE_NOT_FOUND got %08x\n", GetLastError());
2341 ret = CertAddSerializedElementToStore(store, buf,
2342 sizeof(struct CertPropIDHeader) + sizeof(bigCert), 0, 0,
2343 CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL, NULL);
2344 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2345 "Expected ERROR_FILE_NOT_FOUND got %08x\n", GetLastError());
2346 ret = CertAddSerializedElementToStore(store, buf,
2347 sizeof(struct CertPropIDHeader) + sizeof(bigCert), CERT_STORE_ADD_NEW,
2348 0, CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL, NULL);
2349 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2350 "Expected ERROR_FILE_NOT_FOUND got %08x\n", GetLastError());
2351 /* Most everything okay, but bad add disposition */
2352 hdr->unknown1 = 1;
2353 /* This crashes
2354 ret = CertAddSerializedElementToStore(store, buf, sizeof(buf), 0, 0,
2355 CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL, NULL);
2356 * as does this
2357 ret = CertAddSerializedElementToStore(store, buf,
2358 sizeof(struct CertPropIDHeader) + sizeof(bigCert), 0, 0,
2359 CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL, NULL);
2360 */
2361 /* Everything okay, but buffer's too big */
2362 ret = CertAddSerializedElementToStore(store, buf, sizeof(buf),
2363 CERT_STORE_ADD_NEW, 0, CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL, NULL);
2364 ok(ret, "CertAddSerializedElementToStore failed: %08x\n", GetLastError());
2365 /* Everything okay, check it's not re-added */
2366 ret = CertAddSerializedElementToStore(store, buf,
2367 sizeof(struct CertPropIDHeader) + sizeof(bigCert), CERT_STORE_ADD_NEW,
2368 0, CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL, NULL);
2369 ok(!ret && GetLastError() == CRYPT_E_EXISTS,
2370 "Expected CRYPT_E_EXISTS, got %08x\n", GetLastError());
2371
2372 context = CertEnumCertificatesInStore(store, NULL);
2373 ok(context != NULL, "Expected a cert\n");
2374 if (context)
2375 CertDeleteCertificateFromStore(context);
2376
2377 /* Try adding with a bogus hash. Oddly enough, it succeeds, and the hash,
2378 * when queried, is the real hash rather than the bogus hash.
2379 */
2380 hdr = (struct CertPropIDHeader *)(buf + sizeof(struct CertPropIDHeader) +
2381 sizeof(bigCert));
2382 hdr->propID = CERT_HASH_PROP_ID;
2383 hdr->unknown1 = 1;
2384 hdr->cb = sizeof(hash);
2385 memset(hash, 0xc, sizeof(hash));
2386 memcpy((LPBYTE)hdr + sizeof(struct CertPropIDHeader), hash, sizeof(hash));
2387 ret = CertAddSerializedElementToStore(store, buf, sizeof(buf),
2388 CERT_STORE_ADD_NEW, 0, CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL,
2389 (const void **)&context);
2390 ok(ret, "CertAddSerializedElementToStore failed: %08x\n", GetLastError());
2391 if (context)
2392 {
2393 BYTE hashVal[20], realHash[20];
2394 DWORD size = sizeof(hashVal);
2395
2396 ret = CryptHashCertificate(0, 0, 0, bigCert, sizeof(bigCert),
2397 realHash, &size);
2398 ok(ret, "CryptHashCertificate failed: %08x\n", GetLastError());
2399 ret = CertGetCertificateContextProperty(context, CERT_HASH_PROP_ID,
2400 hashVal, &size);
2401 ok(ret, "CertGetCertificateContextProperty failed: %08x\n",
2402 GetLastError());
2403 ok(!memcmp(hashVal, realHash, size), "Unexpected hash\n");
2404 CertFreeCertificateContext(context);
2405 }
2406
2407 CertCloseStore(store, 0);
2408 }
2409
2410 static const BYTE serializedCertWithFriendlyName[] = {
2411 0x0b,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x12,0x00,0x00,0x00,0x57,0x00,0x69,
2412 0x00,0x6e,0x00,0x65,0x00,0x54,0x00,0x65,0x00,0x73,0x00,0x74,0x00,0x00,0x00,
2413 0x20,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x7c,0x00,0x00,0x00,0x30,0x7a,0x02,
2414 0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,
2415 0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x30,
2416 0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,
2417 0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,
2418 0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,
2419 0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x30,0x07,
2420 0x30,0x02,0x06,0x00,0x03,0x01,0x00,0xa3,0x16,0x30,0x14,0x30,0x12,0x06,0x03,
2421 0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,
2422 0x01 };
2423 static const BYTE serializedStoreWithCertWithFriendlyName[] = {
2424 0x00,0x00,0x00,0x00,0x43,0x45,0x52,0x54,0x0b,0x00,0x00,0x00,0x01,0x00,0x00,
2425 0x00,0x12,0x00,0x00,0x00,0x57,0x00,0x69,0x00,0x6e,0x00,0x65,0x00,0x54,0x00,
2426 0x65,0x00,0x73,0x00,0x74,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x01,0x00,0x00,
2427 0x00,0x7c,0x00,0x00,0x00,0x30,0x7a,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,
2428 0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,
2429 0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,
2430 0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,
2431 0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,
2432 0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,
2433 0x20,0x4c,0x61,0x6e,0x67,0x00,0x30,0x07,0x30,0x02,0x06,0x00,0x03,0x01,0x00,
2434 0xa3,0x16,0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,
2435 0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,
2436 0x00,0x00,0x00,0x00,0x00,0x00 };
2437 static const BYTE serializedStoreWithCertAndHash[] = {
2438 0x00,0x00,0x00,0x00,0x43,0x45,0x52,0x54,0x03,0x00,0x00,0x00,0x01,0x00,0x00,
2439 0x00,0x14,0x00,0x00,0x00,0x6e,0x30,0x90,0x71,0x5f,0xd9,0x23,0x56,0xeb,0xae,
2440 0x25,0x40,0xe6,0x22,0xda,0x19,0x26,0x02,0xa6,0x08,0x20,0x00,0x00,0x00,0x01,
2441 0x00,0x00,0x00,0x7c,0x00,0x00,0x00,0x30,0x7a,0x02,0x01,0x01,0x30,0x02,0x06,
2442 0x00,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,
2443 0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,
2444 0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,
2445 0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,
2446 0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,
2447 0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x30,0x07,0x30,0x02,0x06,0x00,0x03,
2448 0x01,0x00,0xa3,0x16,0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,
2449 0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01,0x00,0x00,0x00,0x00,
2450 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 };
2451
2452 static void delete_test_key(void)
2453 {
2454 HKEY root_key, test_key;
2455 static const WCHAR SysCertW[] = {'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\',
2456 'S','y','s','t','e','m','C','e','r','t','i','f','i','c','a','t','e','s',0};
2457 static const WCHAR WineTestW[] = {'W','i','n','e','T','e','s','t',0};
2458 WCHAR subkey_name[32];
2459 DWORD num_subkeys, subkey_name_len;
2460 int idx;
2461
2462 if (RegOpenKeyExW(HKEY_CURRENT_USER, SysCertW, 0, KEY_READ, &root_key))
2463 return;
2464 if (RegOpenKeyExW(root_key, WineTestW, 0, KEY_READ, &test_key))
2465 {
2466 RegCloseKey(root_key);
2467 return;
2468 }
2469 RegQueryInfoKeyW(test_key, NULL, NULL, NULL, &num_subkeys, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
2470 for (idx = num_subkeys; idx-- > 0;)
2471 {
2472 subkey_name_len = ARRAY_SIZE(subkey_name);
2473 RegEnumKeyExW(test_key, idx, subkey_name, &subkey_name_len, NULL, NULL, NULL, NULL);
2474 RegDeleteKeyW(test_key, subkey_name);
2475 }
2476 RegCloseKey(test_key);
2477 RegDeleteKeyW(root_key, WineTestW);
2478 RegCloseKey(root_key);
2479 }
2480
2481 static void testAddCertificateLink(void)
2482 {
2483 BOOL ret;
2484 HCERTSTORE store1, store2;
2485 PCCERT_CONTEXT source, linked;
2486 DWORD size;
2487 LPBYTE buf;
2488 CERT_NAME_BLOB blob;
2489 static const WCHAR szPrefix[] = { 'c','e','r',0 };
2490 static const WCHAR szDot[] = { '.',0 };
2491 static const WCHAR WineTestW[] = { 'W','i','n','e','T','e','s','t',0 };
2492 WCHAR filename1[MAX_PATH], filename2[MAX_PATH];
2493 HANDLE file;
2494
2495 if (0)
2496 {
2497 /* Crashes, i.e. the store is dereferenced without checking. */
2498 ret = CertAddCertificateLinkToStore(NULL, NULL, 0, NULL);
2499 }
2500
2501 /* Adding a certificate link to a store requires a valid add disposition */
2502 store1 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
2503 CERT_STORE_CREATE_NEW_FLAG, NULL);
2504 SetLastError(0xdeadbeef);
2505 ret = CertAddCertificateLinkToStore(store1, NULL, 0, NULL);
2506 ok(!ret && GetLastError() == E_INVALIDARG,
2507 "expected E_INVALIDARG, got %08x\n", GetLastError());
2508 source = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert,
2509 sizeof(bigCert));
2510 SetLastError(0xdeadbeef);
2511 ret = CertAddCertificateLinkToStore(store1, source, 0, NULL);
2512 ok(!ret && GetLastError() == E_INVALIDARG,
2513 "expected E_INVALIDARG, got %08x\n", GetLastError());
2514 ret = CertAddCertificateLinkToStore(store1, source, CERT_STORE_ADD_ALWAYS,
2515 NULL);
2516 ok(ret, "CertAddCertificateLinkToStore failed: %08x\n", GetLastError());
2517 if (0)
2518 {
2519 /* Crashes, i.e. the source certificate is dereferenced without
2520 * checking when a valid add disposition is given.
2521 */
2522 ret = CertAddCertificateLinkToStore(store1, NULL, CERT_STORE_ADD_ALWAYS,
2523 NULL);
2524 }
2525 CertCloseStore(store1, 0);
2526
2527 store1 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
2528 CERT_STORE_CREATE_NEW_FLAG, NULL);
2529 ret = CertAddCertificateLinkToStore(store1, source, CERT_STORE_ADD_ALWAYS,
2530 &linked);
2531 ok(ret, "CertAddCertificateLinkToStore failed: %08x\n", GetLastError());
2532 if (ret)
2533 {
2534 ok(linked->hCertStore == store1, "unexpected store\n");
2535 ret = CertSerializeCertificateStoreElement(linked, 0, NULL, &size);
2536 ok(ret, "CertSerializeCertificateStoreElement failed: %08x\n",
2537 GetLastError());
2538 buf = HeapAlloc(GetProcessHeap(), 0, size);
2539 if (buf)
2540 {
2541 ret = CertSerializeCertificateStoreElement(linked, 0, buf, &size);
2542 ok(ret, "CertSerializeCertificateStoreElement failed: %08x\n",
2543 GetLastError());
2544 /* The serialized linked certificate is identical to the serialized
2545 * original certificate.
2546 */
2547 ok(size == sizeof(serializedCert), "Wrong size %d\n", size);
2548 ok(!memcmp(serializedCert, buf, size),
2549 "Unexpected serialized cert\n");
2550 HeapFree(GetProcessHeap(), 0, buf);
2551 }
2552 /* Set a friendly name on the source certificate... */
2553 blob.pbData = (LPBYTE)WineTestW;
2554 blob.cbData = sizeof(WineTestW);
2555 ret = CertSetCertificateContextProperty(source,
2556 CERT_FRIENDLY_NAME_PROP_ID, 0, &blob);
2557 ok(ret, "CertSetCertificateContextProperty failed: %08x\n",
2558 GetLastError());
2559 /* and the linked certificate has the same friendly name. */
2560 ret = CertGetCertificateContextProperty(linked,
2561 CERT_FRIENDLY_NAME_PROP_ID, NULL, &size);
2562 ok(ret, "CertGetCertificateContextProperty failed: %08x\n",
2563 GetLastError());
2564 buf = HeapAlloc(GetProcessHeap(), 0, size);
2565 if (buf)
2566 {
2567 ret = CertGetCertificateContextProperty(linked,
2568 CERT_FRIENDLY_NAME_PROP_ID, buf, &size);
2569 ok(ret, "CertGetCertificateContextProperty failed: %08x\n",
2570 GetLastError());
2571 ok(!lstrcmpW((LPCWSTR)buf, WineTestW),
2572 "unexpected friendly name\n");
2573 HeapFree(GetProcessHeap(), 0, buf);
2574 }
2575 CertFreeCertificateContext(linked);
2576 }
2577 CertFreeCertificateContext(source);
2578 CertCloseStore(store1, 0);
2579
2580 /* Test adding a cert to a file store, committing the change to the store,
2581 * and creating a link to the resulting cert.
2582 */
2583 if (!GetTempFileNameW(szDot, szPrefix, 0, filename1))
2584 return;
2585
2586 DeleteFileW(filename1);
2587 file = CreateFileW(filename1, GENERIC_READ | GENERIC_WRITE, 0, NULL,
2588 CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
2589 if (file == INVALID_HANDLE_VALUE)
2590 return;
2591
2592 store1 = CertOpenStore(CERT_STORE_PROV_FILE, 0, 0,
2593 CERT_FILE_STORE_COMMIT_ENABLE_FLAG, file);
2594 ok(store1 != NULL, "CertOpenStore failed: %08x\n", GetLastError());
2595 CloseHandle(file);
2596
2597 ret = CertAddEncodedCertificateToStore(store1, X509_ASN_ENCODING,
2598 bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, &source);
2599 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
2600 GetLastError());
2601
2602 /* Test adding a link to a memory store. */
2603 store2 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
2604 CERT_STORE_CREATE_NEW_FLAG, NULL);
2605 ret = CertAddCertificateLinkToStore(store2, source, CERT_STORE_ADD_ALWAYS,
2606 &linked);
2607 ok(ret, "CertAddCertificateLinkToStore failed: %08x\n", GetLastError());
2608 if (ret)
2609 {
2610 ok(linked->hCertStore == store2, "unexpected store\n");
2611 ret = CertSerializeCertificateStoreElement(linked, 0, NULL, &size);
2612 ok(ret, "CertSerializeCertificateStoreElement failed: %08x\n",
2613 GetLastError());
2614 buf = HeapAlloc(GetProcessHeap(), 0, size);
2615 if (buf)
2616 {
2617 ret = CertSerializeCertificateStoreElement(linked, 0, buf, &size);
2618 /* The serialized linked certificate is identical to the serialized
2619 * original certificate.
2620 */
2621 ok(ret, "CertSerializeCertificateStoreElement failed: %08x\n", GetLastError());
2622 ok(size == sizeof(serializedCert), "Wrong size %d\n", size);
2623 ok(!memcmp(serializedCert, buf, size),
2624 "Unexpected serialized cert\n");
2625 HeapFree(GetProcessHeap(), 0, buf);
2626 }
2627 /* Set a friendly name on the source certificate... */
2628 blob.pbData = (LPBYTE)WineTestW;
2629 blob.cbData = sizeof(WineTestW);
2630 ret = CertSetCertificateContextProperty(source,
2631 CERT_FRIENDLY_NAME_PROP_ID, 0, &blob);
2632 ok(ret, "CertSetCertificateContextProperty failed: %08x\n",
2633 GetLastError());
2634 /* and the linked certificate has the same friendly name. */
2635 ret = CertGetCertificateContextProperty(linked,
2636 CERT_FRIENDLY_NAME_PROP_ID, NULL, &size);
2637 ok(ret, "CertGetCertificateContextProperty failed: %08x\n",
2638 GetLastError());
2639 buf = HeapAlloc(GetProcessHeap(), 0, size);
2640 if (buf)
2641 {
2642 ret = CertGetCertificateContextProperty(linked,
2643 CERT_FRIENDLY_NAME_PROP_ID, buf, &size);
2644 ok(ret, "CertGetCertificateContextProperty failed: %08x\n", GetLastError());
2645 ok(!lstrcmpW((LPCWSTR)buf, WineTestW),
2646 "unexpected friendly name\n");
2647 HeapFree(GetProcessHeap(), 0, buf);
2648 }
2649 CertFreeCertificateContext(linked);
2650 }
2651 CertCloseStore(store2, 0);
2652
2653 if (!GetTempFileNameW(szDot, szPrefix, 0, filename2))
2654 return;
2655
2656 DeleteFileW(filename2);
2657 file = CreateFileW(filename2, GENERIC_READ | GENERIC_WRITE, 0, NULL,
2658 CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
2659 if (file == INVALID_HANDLE_VALUE)
2660 return;
2661
2662 store2 = CertOpenStore(CERT_STORE_PROV_FILE, 0, 0,
2663 CERT_FILE_STORE_COMMIT_ENABLE_FLAG, file);
2664 ok(store2 != NULL, "CertOpenStore failed: %08x\n", GetLastError());
2665 CloseHandle(file);
2666 /* Test adding a link to a file store. */
2667 ret = CertAddCertificateLinkToStore(store2, source, CERT_STORE_ADD_ALWAYS,
2668 &linked);
2669 ok(ret, "CertAddCertificateLinkToStore failed: %08x\n", GetLastError());
2670 if (ret)
2671 {
2672 ok(linked->hCertStore == store2, "unexpected store\n");
2673 ret = CertSerializeCertificateStoreElement(linked, 0, NULL, &size);
2674 ok(ret, "CertSerializeCertificateStoreElement failed: %08x\n",
2675 GetLastError());
2676 buf = HeapAlloc(GetProcessHeap(), 0, size);
2677 if (buf)
2678 {
2679 ret = CertSerializeCertificateStoreElement(linked, 0, buf, &size);
2680 ok(ret, "CertSerializeCertificateStoreElement failed: %08x\n",
2681 GetLastError());
2682 /* The serialized linked certificate now contains the friendly
2683 * name property.
2684 */
2685 ok(size == sizeof(serializedCertWithFriendlyName),
2686 "Wrong size %d\n", size);
2687 ok(!memcmp(serializedCertWithFriendlyName, buf, size),
2688 "Unexpected serialized cert\n");
2689 HeapFree(GetProcessHeap(), 0, buf);
2690 }
2691 CertFreeCertificateContext(linked);
2692 compareStore(store2, "file store -> file store",
2693 serializedStoreWithCertWithFriendlyName,
2694 sizeof(serializedStoreWithCertWithFriendlyName), FALSE);
2695 }
2696 CertCloseStore(store2, 0);
2697 DeleteFileW(filename2);
2698
2699 CertFreeCertificateContext(source);
2700
2701 CertCloseStore(store1, 0);
2702 DeleteFileW(filename1);
2703
2704 /* Test adding a link to a system store (which is a collection store.) */
2705 store1 = CertOpenSystemStoreA(0, "My");
2706 source = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert,
2707 sizeof(bigCert));
2708 SetLastError(0xdeadbeef);
2709 ret = CertAddCertificateLinkToStore(store1, source, CERT_STORE_ADD_ALWAYS,
2710 &linked);
2711 ok(!ret && GetLastError() == E_INVALIDARG,
2712 "expected E_INVALIDARG, got %08x\n", GetLastError());
2713 CertFreeCertificateContext(source);
2714
2715 /* Test adding a link to a file store, where the linked certificate is
2716 * in a system store.
2717 */
2718 ret = CertAddEncodedCertificateToStore(store1, X509_ASN_ENCODING,
2719 bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, &source);
2720 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
2721 GetLastError());
2722 if (!GetTempFileNameW(szDot, szPrefix, 0, filename1))
2723 return;
2724
2725 DeleteFileW(filename1);
2726 file = CreateFileW(filename1, GENERIC_READ | GENERIC_WRITE, 0, NULL,
2727 CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
2728 if (file == INVALID_HANDLE_VALUE)
2729 return;
2730
2731 store2 = CertOpenStore(CERT_STORE_PROV_FILE, 0, 0,
2732 CERT_FILE_STORE_COMMIT_ENABLE_FLAG, file);
2733 ok(store2 != NULL, "CertOpenStore failed: %08x\n", GetLastError());
2734 CloseHandle(file);
2735
2736 ret = CertAddCertificateLinkToStore(store2, source, CERT_STORE_ADD_ALWAYS,
2737 &linked);
2738 ok(ret, "CertAddCertificateLinkToStore failed: %08x\n", GetLastError());
2739 if (ret)
2740 {
2741 ok(linked->hCertStore == store2, "unexpected store\n");
2742 ret = CertControlStore(store2, 0, CERT_STORE_CTRL_COMMIT, NULL);
2743 ok(ret, "CertControlStore failed: %d\n", ret);
2744 compareStore(store2, "file store -> system store",
2745 serializedStoreWithCertAndHash,
2746 sizeof(serializedStoreWithCertAndHash), TRUE);
2747 CertFreeCertificateContext(linked);
2748 }
2749
2750 CertCloseStore(store2, 0);
2751 DeleteFileW(filename1);
2752
2753 /* Test adding a link to a registry store, where the linked certificate is
2754 * in a system store.
2755 */
2756 store2 = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY, 0, 0,
2757 CERT_SYSTEM_STORE_CURRENT_USER, WineTestW);
2758 ok(store2 != NULL, "CertOpenStore failed: %08x\n", GetLastError());
2759 ret = CertAddCertificateLinkToStore(store2, source, CERT_STORE_ADD_ALWAYS,
2760 &linked);
2761 ok(ret, "CertAddCertificateLinkToStore failed: %08x\n", GetLastError());
2762 if (ret)
2763 {
2764 ok(linked->hCertStore == store2, "unexpected store\n");
2765 CertDeleteCertificateFromStore(linked);
2766 }
2767 CertCloseStore(store2, 0);
2768
2769 CertFreeCertificateContext(source);
2770 CertCloseStore(store1, 0);
2771
2772 delete_test_key();
2773 }
2774
2775 static DWORD countCertsInStore(HCERTSTORE store)
2776 {
2777 PCCERT_CONTEXT cert = NULL;
2778 DWORD certs = 0;
2779
2780 do {
2781 cert = CertEnumCertificatesInStore(store, cert);
2782 if (cert)
2783 certs++;
2784 } while (cert);
2785 return certs;
2786 }
2787
2788 static DWORD countCRLsInStore(HCERTSTORE store)
2789 {
2790 PCCRL_CONTEXT crl = NULL;
2791 DWORD crls = 0;
2792
2793 do {
2794 crl = CertEnumCRLsInStore(store, crl);
2795 if (crl)
2796 crls++;
2797 } while (crl);
2798 return crls;
2799 }
2800
2801 static void testEmptyStore(void)
2802 {
2803 const CERT_CONTEXT *cert, *cert2, *cert3;
2804 const CRL_CONTEXT *crl;
2805 const CTL_CONTEXT *ctl;
2806 HCERTSTORE store;
2807 BOOL res;
2808
2809 cert = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert, sizeof(bigCert));
2810 ok(cert != NULL, "CertCreateCertificateContext failed\n");
2811 ok(cert->hCertStore != NULL, "cert->hCertStore == NULL\n");
2812 if(!cert->hCertStore) {
2813 CertFreeCertificateContext(cert);
2814 return;
2815 }
2816
2817 test_store_is_empty(cert->hCertStore);
2818
2819 cert2 = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert2, sizeof(bigCert2));
2820 ok(cert2 != NULL, "CertCreateCertificateContext failed\n");
2821 ok(cert2->hCertStore == cert->hCertStore, "Unexpected hCertStore\n");
2822
2823 test_store_is_empty(cert2->hCertStore);
2824
2825 res = CertAddCertificateContextToStore(cert->hCertStore, cert2, CERT_STORE_ADD_NEW, &cert3);
2826 ok(res, "CertAddCertificateContextToStore failed\n");
2827 todo_wine
2828 ok(cert3 && cert3 != cert2, "Unexpected cert3\n");
2829 ok(cert3->hCertStore == cert->hCertStore, "Unexpected hCertStore\n");
2830
2831 test_store_is_empty(cert->hCertStore);
2832
2833 res = CertDeleteCertificateFromStore(cert3);
2834 ok(res, "CertDeleteCertificateContextFromStore failed\n");
2835 ok(cert3->hCertStore == cert->hCertStore, "Unexpected hCertStore\n");
2836
2837 store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0, CERT_STORE_CREATE_NEW_FLAG, NULL);
2838 ok(store != NULL, "CertOpenStore failed\n");
2839
2840 res = CertAddCertificateContextToStore(store, cert2, CERT_STORE_ADD_NEW, &cert3);
2841 ok(res, "CertAddCertificateContextToStore failed\n");
2842 ok(cert3 && cert3 != cert2, "Unexpected cert3\n");
2843 ok(cert3->hCertStore == store, "Unexpected hCertStore\n");
2844
2845 res = CertDeleteCertificateFromStore(cert3);
2846 ok(res, "CertDeleteCertificateContextFromStore failed\n");
2847 ok(cert3->hCertStore == store, "Unexpected hCertStore\n");
2848
2849 CertCloseStore(store, 0);
2850
2851 res = CertCloseStore(cert->hCertStore, CERT_CLOSE_STORE_CHECK_FLAG);
2852 ok(!res && GetLastError() == E_UNEXPECTED, "CertCloseStore returned: %x(%x)\n", res, GetLastError());
2853
2854 res = CertCloseStore(cert->hCertStore, 0);
2855 ok(!res && GetLastError() == E_UNEXPECTED, "CertCloseStore returned: %x(%x)\n", res, GetLastError());
2856
2857 CertFreeCertificateContext(cert2);
2858
2859 crl = CertCreateCRLContext(X509_ASN_ENCODING, signedCRL, sizeof(signedCRL));
2860 ok(crl != NULL, "CertCreateCRLContext failed\n");
2861 ok(crl->hCertStore == cert->hCertStore, "unexpected hCertStore\n");
2862
2863 CertFreeCRLContext(crl);
2864
2865 ctl = CertCreateCTLContext(X509_ASN_ENCODING, signedCTLWithCTLInnerContent, sizeof(signedCTLWithCTLInnerContent));
2866 ok(ctl != NULL, "CertCreateCTLContext failed\n");
2867 ok(ctl->hCertStore == cert->hCertStore, "unexpected hCertStore\n");
2868
2869 CertFreeCTLContext(ctl);
2870
2871 CertFreeCertificateContext(cert);
2872 }
2873
2874 static void testCloseStore(void)
2875 {
2876 const CERT_CONTEXT *cert;
2877 const CRL_CONTEXT *crl;
2878 const CTL_CONTEXT *ctl;
2879 HCERTSTORE store, store2;
2880 BOOL res;
2881
2882 store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0, CERT_STORE_CREATE_NEW_FLAG, NULL);
2883 ok(store != NULL, "CertOpenStore failed\n");
2884
2885 res = CertCloseStore(store, CERT_CLOSE_STORE_CHECK_FLAG);
2886 ok(res, "CertCloseStore failed\n");
2887
2888 store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0, CERT_STORE_CREATE_NEW_FLAG, NULL);
2889 ok(store != NULL, "CertOpenStore failed\n");
2890
2891 store2 = CertDuplicateStore(store);
2892 ok(store2 != NULL, "CertCloneStore failed\n");
2893 ok(store2 == store, "unexpected store2\n");
2894
2895 res = CertCloseStore(store, CERT_CLOSE_STORE_CHECK_FLAG);
2896 ok(!res && GetLastError() == CRYPT_E_PENDING_CLOSE, "CertCloseStore failed\n");
2897
2898 res = CertCloseStore(store2, CERT_CLOSE_STORE_CHECK_FLAG);
2899 ok(res, "CertCloseStore failed\n");
2900
2901 store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0, CERT_STORE_CREATE_NEW_FLAG, NULL);
2902 ok(store != NULL, "CertOpenStore failed\n");
2903
2904 res = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING, bigCert,
2905 sizeof(bigCert), CERT_STORE_ADD_ALWAYS, &cert);
2906 ok(res, "CertAddEncodedCertificateToStore failed\n");
2907
2908 /* There is still a reference from cert */
2909 res = CertCloseStore(store, CERT_CLOSE_STORE_CHECK_FLAG);
2910 ok(!res && GetLastError() == CRYPT_E_PENDING_CLOSE, "CertCloseStore failed\n");
2911
2912 res = CertFreeCertificateContext(cert);
2913 ok(res, "CertFreeCertificateContext failed\n");
2914
2915 store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0, CERT_STORE_CREATE_NEW_FLAG, NULL);
2916 ok(store != NULL, "CertOpenStore failed\n");
2917
2918 res = CertAddEncodedCRLToStore(store, X509_ASN_ENCODING, signedCRL,
2919 sizeof(signedCRL), CERT_STORE_ADD_ALWAYS, &crl);
2920 ok(res, "CertAddEncodedCRLToStore failed\n");
2921
2922 /* There is still a reference from CRL */
2923 res = CertCloseStore(store, CERT_CLOSE_STORE_CHECK_FLAG);
2924 ok(!res && GetLastError() == CRYPT_E_PENDING_CLOSE, "CertCloseStore failed\n");
2925
2926 res = CertFreeCRLContext(crl);
2927 ok(res, "CertFreeCRLContext failed\n");
2928
2929 store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0, CERT_STORE_CREATE_NEW_FLAG, NULL);
2930 ok(store != NULL, "CertOpenStore failed\n");
2931
2932 res = CertAddEncodedCTLToStore(store, X509_ASN_ENCODING, signedCTLWithCTLInnerContent,
2933 sizeof(signedCTLWithCTLInnerContent), CERT_STORE_ADD_ALWAYS, &ctl);
2934 ok(res, "CertAddEncodedCTLToStore failed\n");
2935
2936 /* There is still a reference from CTL */
2937 res = CertCloseStore(store, CERT_CLOSE_STORE_CHECK_FLAG);
2938 ok(!res && GetLastError() == CRYPT_E_PENDING_CLOSE, "CertCloseStore returned: %x(%u)\n", res, GetLastError());
2939
2940 res = CertFreeCTLContext(ctl);
2941 ok(res, "CertFreeCTLContext failed\n");
2942
2943 /* Add all kinds of contexts, then release external references and make sure that store is properly closed. */
2944 store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0, CERT_STORE_CREATE_NEW_FLAG, NULL);
2945 ok(store != NULL, "CertOpenStore failed\n");
2946
2947 res = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING, bigCert,
2948 sizeof(bigCert), CERT_STORE_ADD_ALWAYS, &cert);
2949 ok(res, "CertAddEncodedCertificateToStore failed\n");
2950
2951 res = CertAddEncodedCRLToStore(store, X509_ASN_ENCODING, signedCRL,
2952 sizeof(signedCRL), CERT_STORE_ADD_ALWAYS, &crl);
2953 ok(res, "CertAddEncodedCRLToStore failed\n");
2954
2955 res = CertAddEncodedCTLToStore(store, X509_ASN_ENCODING, signedCTLWithCTLInnerContent,
2956 sizeof(signedCTLWithCTLInnerContent), CERT_STORE_ADD_ALWAYS, &ctl);
2957 ok(res, "CertAddEncodedCTLToStore failed\n");
2958
2959 CertFreeCertificateContext(cert);
2960 CertFreeCRLContext(crl);
2961 CertFreeCTLContext(ctl);
2962
2963 res = CertCloseStore(store, CERT_CLOSE_STORE_CHECK_FLAG);
2964 ok(res, "CertCloseStore failed\n");
2965 }
2966
2967 static void test_I_UpdateStore(void)
2968 {
2969 HMODULE lib = GetModuleHandleA("crypt32");
2970 BOOL (WINAPI *pI_CertUpdatestore)(HCERTSTORE, HCERTSTORE, DWORD, DWORD) =
2971 (void *)GetProcAddress(lib, "I_CertUpdateStore");
2972 BOOL ret;
2973 HCERTSTORE store1, store2;
2974 PCCERT_CONTEXT cert;
2975 DWORD certs;
2976
2977 if (!pI_CertUpdatestore)
2978 {
2979 win_skip("No I_CertUpdateStore\n");
2980 return;
2981 }
2982 store1 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
2983 CERT_STORE_CREATE_NEW_FLAG, NULL);
2984 store2 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
2985 CERT_STORE_CREATE_NEW_FLAG, NULL);
2986
2987 /* Crash
2988 ret = pI_CertUpdatestore(NULL, NULL, 0, 0);
2989 ret = pI_CertUpdatestore(store1, NULL, 0, 0);
2990 ret = pI_CertUpdatestore(NULL, store2, 0, 0);
2991 */
2992 ret = pI_CertUpdatestore(store1, store2, 0, 0);
2993 ok(ret, "I_CertUpdateStore failed: %08x\n", GetLastError());
2994
2995 CertAddEncodedCertificateToStore(store2, X509_ASN_ENCODING, bigCert,
2996 sizeof(bigCert), CERT_STORE_ADD_ALWAYS, &cert);
2997 /* I_CertUpdateStore adds the contexts from store2 to store1 */
2998 ret = pI_CertUpdatestore(store1, store2, 0, 0);
2999 ok(ret, "I_CertUpdateStore failed: %08x\n", GetLastError());
3000 certs = countCertsInStore(store1);
3001 ok(certs == 1, "Expected 1 cert, got %d\n", certs);
3002 /* Calling it a second time has no effect */
3003 ret = pI_CertUpdatestore(store1, store2, 0, 0);
3004 ok(ret, "I_CertUpdateStore failed: %08x\n", GetLastError());
3005 certs = countCertsInStore(store1);
3006 ok(certs == 1, "Expected 1 cert, got %d\n", certs);
3007
3008 /* The last parameters to I_CertUpdateStore appear to be ignored */
3009 ret = pI_CertUpdatestore(store1, store2, 1, 0);
3010 ok(ret, "I_CertUpdateStore failed: %08x\n", GetLastError());
3011 ret = pI_CertUpdatestore(store1, store2, 0, 1);
3012 ok(ret, "I_CertUpdateStore failed: %08x\n", GetLastError());
3013
3014 CertAddEncodedCRLToStore(store2, X509_ASN_ENCODING, signedCRL,
3015 sizeof(signedCRL), CERT_STORE_ADD_ALWAYS, NULL);
3016
3017 /* I_CertUpdateStore also adds the CRLs from store2 to store1 */
3018 ret = pI_CertUpdatestore(store1, store2, 0, 0);
3019 ok(ret, "I_CertUpdateStore failed: %08x\n", GetLastError());
3020 certs = countCertsInStore(store1);
3021 ok(certs == 1, "Expected 1 cert, got %d\n", certs);
3022 certs = countCRLsInStore(store1);
3023 ok(certs == 1, "Expected 1 CRL, got %d\n", certs);
3024
3025 CertDeleteCertificateFromStore(cert);
3026 /* If a context is deleted from store2, I_CertUpdateStore deletes it
3027 * from store1
3028 */
3029 ret = pI_CertUpdatestore(store1, store2, 0, 0);
3030 ok(ret, "I_CertUpdateStore failed: %08x\n", GetLastError());
3031 certs = countCertsInStore(store1);
3032 ok(certs == 0, "Expected 0 certs, got %d\n", certs);
3033
3034 CertCloseStore(store1, 0);
3035 CertCloseStore(store2, 0);
3036 }
3037
3038 START_TEST(store)
3039 {
3040 /* various combinations of CertOpenStore */
3041 testMemStore();
3042 testCollectionStore();
3043 testStoresInCollection();
3044
3045 testRegStore();
3046 testRegStoreSavedCerts();
3047
3048 testSystemRegStore();
3049 testSystemStore();
3050 testFileStore();
3051 testFileNameStore();
3052 testMessageStore();
3053 testSerializedStore();
3054 testCloseStore();
3055
3056 testCertRegisterSystemStore();
3057
3058 testCertOpenSystemStore();
3059 testCertEnumSystemStore();
3060 testStoreProperty();
3061
3062 testAddSerialized();
3063 testAddCertificateLink();
3064
3065 testEmptyStore();
3066
3067 test_I_UpdateStore();
3068 }