[CRYPT32_WINETEST] Sync with Wine Staging 2.9. CORE-13362
[reactos.git] / 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 <shlobj.h>
27 #include <shlwapi.h>
28 #include <winreg.h>
29 //#include <winerror.h>
30 #include <wincrypt.h>
31
32 #include <wine/test.h>
33
34 /* The following aren't defined in wincrypt.h, as they're "reserved" */
35 #define CERT_CERT_PROP_ID 32
36 #define CERT_CRL_PROP_ID 33
37 #define CERT_CTL_PROP_ID 34
38
39 struct CertPropIDHeader
40 {
41 DWORD propID;
42 DWORD unknown1;
43 DWORD cb;
44 };
45
46 static const BYTE emptyCert[] = { 0x30, 0x00 };
47 static const BYTE bigCert[] = { 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
48 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
49 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x22,
50 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30,
51 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30,
52 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30,
53 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20,
54 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01,
55 0x00, 0xa3, 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01,
56 0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
57 static const BYTE signedBigCert[] = {
58 0x30, 0x81, 0x93, 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06, 0x00, 0x30,
59 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a,
60 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x22, 0x18, 0x0f,
61 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
62 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30,
63 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06,
64 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61,
65 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3,
66 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff,
67 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
68 0x00, 0x03, 0x11, 0x00, 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07,
69 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00 };
70 static const BYTE serializedCert[] = { 0x20, 0x00, 0x00, 0x00,
71 0x01, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x30, 0x7a, 0x02, 0x01, 0x01,
72 0x30, 0x02, 0x06, 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55,
73 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67,
74 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31,
75 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31,
76 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15,
77 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75,
78 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06,
79 0x00, 0x03, 0x01, 0x00, 0xa3, 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55,
80 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02,
81 0x01, 0x01 };
82 static const BYTE signedCRL[] = { 0x30, 0x45, 0x30, 0x2c, 0x30, 0x02, 0x06,
83 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
84 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18, 0x0f,
85 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
86 0x30, 0x5a, 0x30, 0x02, 0x06, 0x00, 0x03, 0x11, 0x00, 0x0f, 0x0e, 0x0d, 0x0c,
87 0x0b, 0x0a, 0x09, 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00 };
88 static const BYTE bigCert2[] = { 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
89 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
90 0x0a, 0x41, 0x6c, 0x65, 0x78, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x22,
91 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30,
92 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30,
93 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30,
94 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x41, 0x6c, 0x65, 0x78, 0x20,
95 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01,
96 0x00, 0xa3, 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01,
97 0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
98 static const BYTE signedCTLWithCTLInnerContent[] = {
99 0x30,0x82,0x01,0x0f,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,
100 0xa0,0x82,0x01,0x00,0x30,0x81,0xfd,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,
101 0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x30,0x06,0x09,
102 0x2b,0x06,0x01,0x04,0x01,0x82,0x37,0x0a,0x01,0xa0,0x23,0x30,0x21,0x30,0x00,
103 0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,
104 0x30,0x5a,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,
105 0x00,0x31,0x81,0xb5,0x30,0x81,0xb2,0x02,0x01,0x01,0x30,0x1a,0x30,0x15,0x31,
106 0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,
107 0x4c,0x61,0x6e,0x67,0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,
108 0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0xa0,0x3b,0x30,0x18,0x06,0x09,0x2a,0x86,
109 0x48,0x86,0xf7,0x0d,0x01,0x09,0x03,0x31,0x0b,0x06,0x09,0x2b,0x06,0x01,0x04,
110 0x01,0x82,0x37,0x0a,0x01,0x30,0x1f,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,
111 0x01,0x09,0x04,0x31,0x12,0x04,0x10,0x54,0x71,0xbc,0xe1,0x56,0x31,0xa2,0xf9,
112 0x65,0x70,0x34,0xf8,0xe2,0xe9,0xb4,0xf4,0x30,0x04,0x06,0x00,0x05,0x00,0x04,
113 0x40,0x2f,0x1b,0x9f,0x5a,0x4a,0x15,0x73,0xfa,0xb1,0x93,0x3d,0x09,0x52,0xdf,
114 0x6b,0x98,0x4b,0x13,0x5e,0xe7,0xbf,0x65,0xf4,0x9c,0xc2,0xb1,0x77,0x09,0xb1,
115 0x66,0x4d,0x72,0x0d,0xb1,0x1a,0x50,0x20,0xe0,0x57,0xa2,0x39,0xc7,0xcd,0x7f,
116 0x8e,0xe7,0x5f,0x76,0x2b,0xd1,0x6a,0x82,0xb3,0x30,0x25,0x61,0xf6,0x25,0x23,
117 0x57,0x6c,0x0b,0x47,0xb8 };
118
119 static BOOL (WINAPI *pCertControlStore)(HCERTSTORE,DWORD,DWORD,void const*);
120 static PCCRL_CONTEXT (WINAPI *pCertEnumCRLsInStore)(HCERTSTORE,PCCRL_CONTEXT);
121 static BOOL (WINAPI *pCertEnumSystemStore)(DWORD,void*,void*,PFN_CERT_ENUM_SYSTEM_STORE);
122 static BOOL (WINAPI *pCertGetStoreProperty)(HCERTSTORE,DWORD,void*,DWORD*);
123 static void (WINAPI *pCertRemoveStoreFromCollection)(HCERTSTORE,HCERTSTORE);
124 static BOOL (WINAPI *pCertSetStoreProperty)(HCERTSTORE,DWORD,DWORD,const void*);
125 static BOOL (WINAPI *pCertAddCertificateLinkToStore)(HCERTSTORE,PCCERT_CONTEXT,DWORD,PCCERT_CONTEXT*);
126 static BOOL (WINAPI *pCertRegisterSystemStore)(const void*,DWORD,void*,void*);
127 static BOOL (WINAPI *pCertUnregisterSystemStore)(const void*,DWORD);
128
129 #define test_store_is_empty(store) _test_store_is_empty(__LINE__,store)
130 static void _test_store_is_empty(unsigned line, HCERTSTORE store)
131 {
132 const CERT_CONTEXT *cert;
133
134 cert = CertEnumCertificatesInStore(store, NULL);
135 ok_(__FILE__,line)(!cert && GetLastError() == CRYPT_E_NOT_FOUND, "store is not empty\n");
136 }
137
138 static void testMemStore(void)
139 {
140 HCERTSTORE store1, store2;
141 PCCERT_CONTEXT context;
142 BOOL ret;
143 DWORD GLE;
144
145 /* NULL provider */
146 store1 = CertOpenStore(0, 0, 0, 0, NULL);
147 ok(!store1 && GetLastError() == ERROR_FILE_NOT_FOUND,
148 "Expected ERROR_FILE_NOT_FOUND, got %d\n", GetLastError());
149 /* weird flags */
150 store1 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
151 CERT_STORE_DELETE_FLAG, NULL);
152 ok(!store1 && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED,
153 "Expected ERROR_CALL_NOT_IMPLEMENTED, got %d\n", GetLastError());
154
155 /* normal */
156 store1 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
157 CERT_STORE_CREATE_NEW_FLAG, NULL);
158 ok(store1 != NULL, "CertOpenStore failed: %d\n", GetLastError());
159 /* open existing doesn't */
160 store2 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
161 CERT_STORE_OPEN_EXISTING_FLAG, NULL);
162 ok(store2 != NULL, "CertOpenStore failed: %d\n", GetLastError());
163 ok(store1 != store2, "Expected different stores\n");
164
165 /* add a bogus (empty) cert */
166 context = NULL;
167 ret = CertAddEncodedCertificateToStore(store1, X509_ASN_ENCODING, emptyCert,
168 sizeof(emptyCert), CERT_STORE_ADD_ALWAYS, &context);
169 /* Windows returns CRYPT_E_ASN1_EOD or OSS_DATA_ERROR, but accept
170 * CRYPT_E_ASN1_CORRUPT as well (because matching errors is tough in this
171 * case)
172 */
173 GLE = GetLastError();
174 ok(!ret && (GLE == CRYPT_E_ASN1_EOD || GLE == CRYPT_E_ASN1_CORRUPT ||
175 GLE == OSS_DATA_ERROR),
176 "Expected CRYPT_E_ASN1_EOD or CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
177 GLE);
178 /* add a "signed" cert--the signature isn't a real signature, so this adds
179 * without any check of the signature's validity
180 */
181 ret = CertAddEncodedCertificateToStore(store1, X509_ASN_ENCODING,
182 signedBigCert, sizeof(signedBigCert), CERT_STORE_ADD_ALWAYS, &context);
183 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n", GetLastError());
184 ok(context != NULL, "Expected a valid cert context\n");
185 if (context)
186 {
187 ok(context->cbCertEncoded == sizeof(signedBigCert),
188 "Wrong cert size %d\n", context->cbCertEncoded);
189 ok(!memcmp(context->pbCertEncoded, signedBigCert,
190 sizeof(signedBigCert)), "Unexpected encoded cert in context\n");
191 /* remove it, the rest of the tests will work on an unsigned cert */
192 ret = CertDeleteCertificateFromStore(context);
193 ok(ret, "CertDeleteCertificateFromStore failed: %08x\n",
194 GetLastError());
195 }
196 /* try adding a "signed" CRL as a cert */
197 ret = CertAddEncodedCertificateToStore(store1, X509_ASN_ENCODING,
198 signedCRL, sizeof(signedCRL), CERT_STORE_ADD_ALWAYS, &context);
199 GLE = GetLastError();
200 ok(!ret && (GLE == CRYPT_E_ASN1_BADTAG || GLE == CRYPT_E_ASN1_CORRUPT ||
201 GLE == OSS_DATA_ERROR),
202 "Expected CRYPT_E_ASN1_BADTAG or CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
203 GLE);
204 /* add a cert to store1 */
205 ret = CertAddEncodedCertificateToStore(store1, X509_ASN_ENCODING, bigCert,
206 sizeof(bigCert), CERT_STORE_ADD_ALWAYS, &context);
207 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n", GetLastError());
208 ok(context != NULL, "Expected a valid cert context\n");
209 if (context)
210 {
211 DWORD size;
212 BYTE *buf;
213
214 ok(context->cbCertEncoded == sizeof(bigCert),
215 "Wrong cert size %d\n", context->cbCertEncoded);
216 ok(!memcmp(context->pbCertEncoded, bigCert, sizeof(bigCert)),
217 "Unexpected encoded cert in context\n");
218 ok(context->hCertStore == store1, "Unexpected store\n");
219
220 /* check serializing this element */
221 /* These crash
222 ret = CertSerializeCertificateStoreElement(NULL, 0, NULL, NULL);
223 ret = CertSerializeCertificateStoreElement(context, 0, NULL, NULL);
224 ret = CertSerializeCertificateStoreElement(NULL, 0, NULL, &size);
225 */
226 /* apparently flags are ignored */
227 ret = CertSerializeCertificateStoreElement(context, 1, NULL, &size);
228 ok(ret, "CertSerializeCertificateStoreElement failed: %08x\n",
229 GetLastError());
230 buf = HeapAlloc(GetProcessHeap(), 0, size);
231 if (buf)
232 {
233 ret = CertSerializeCertificateStoreElement(context, 0, buf, &size);
234 ok(ret, "CertSerializeCertificateStoreElement failed: %08x\n", GetLastError());
235 ok(size == sizeof(serializedCert), "Wrong size %d\n", size);
236 ok(!memcmp(serializedCert, buf, size),
237 "Unexpected serialized cert\n");
238 HeapFree(GetProcessHeap(), 0, buf);
239 }
240
241 ret = CertFreeCertificateContext(context);
242 ok(ret, "CertFreeCertificateContext failed: %08x\n", GetLastError());
243 }
244 /* verify the cert's in store1 */
245 context = CertEnumCertificatesInStore(store1, NULL);
246 ok(context != NULL, "Expected a valid context\n");
247 context = CertEnumCertificatesInStore(store1, context);
248 ok(!context && GetLastError() == CRYPT_E_NOT_FOUND,
249 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
250 /* verify store2 (the "open existing" mem store) is still empty */
251 context = CertEnumCertificatesInStore(store2, NULL);
252 ok(!context, "Expected an empty store\n");
253 /* delete the cert from store1, and check it's empty */
254 context = CertEnumCertificatesInStore(store1, NULL);
255 if (context)
256 {
257 /* Deleting a bitwise copy crashes with an access to an uninitialized
258 * pointer, so a cert context has some special data out there in memory
259 * someplace
260 CERT_CONTEXT copy;
261 memcpy(&copy, context, sizeof(copy));
262 ret = CertDeleteCertificateFromStore(&copy);
263 */
264 PCCERT_CONTEXT copy = CertDuplicateCertificateContext(context);
265
266 ok(copy != NULL, "CertDuplicateCertificateContext failed: %08x\n",
267 GetLastError());
268 ret = CertDeleteCertificateFromStore(context);
269 ok(ret, "CertDeleteCertificateFromStore failed: %08x\n",
270 GetLastError());
271 /* try deleting a copy */
272 ret = CertDeleteCertificateFromStore(copy);
273 ok(ret, "CertDeleteCertificateFromStore failed: %08x\n",
274 GetLastError());
275 /* check that the store is empty */
276 context = CertEnumCertificatesInStore(store1, NULL);
277 ok(!context, "Expected an empty store\n");
278 }
279
280 /* close an empty store */
281 ret = CertCloseStore(NULL, 0);
282 ok(ret, "CertCloseStore failed: %d\n", GetLastError());
283 ret = CertCloseStore(store1, 0);
284 ok(ret, "CertCloseStore failed: %d\n", GetLastError());
285 ret = CertCloseStore(store2, 0);
286 ok(ret, "CertCloseStore failed: %d\n", GetLastError());
287
288 /* This seems nonsensical, but you can open a read-only mem store, only
289 * it isn't read-only
290 */
291 store1 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
292 CERT_STORE_READONLY_FLAG, NULL);
293 ok(store1 != NULL, "CertOpenStore failed: %d\n", GetLastError());
294 /* yep, this succeeds */
295 ret = CertAddEncodedCertificateToStore(store1, X509_ASN_ENCODING, bigCert,
296 sizeof(bigCert), CERT_STORE_ADD_ALWAYS, &context);
297 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n", GetLastError());
298 ok(context != NULL, "Expected a valid cert context\n");
299 if (context)
300 {
301 ok(context->cbCertEncoded == sizeof(bigCert),
302 "Wrong cert size %d\n", context->cbCertEncoded);
303 ok(!memcmp(context->pbCertEncoded, bigCert, sizeof(bigCert)),
304 "Unexpected encoded cert in context\n");
305 ok(context->hCertStore == store1, "Unexpected store\n");
306 ret = CertDeleteCertificateFromStore(context);
307 ok(ret, "CertDeleteCertificateFromStore failed: %08x\n",
308 GetLastError());
309 }
310 CertCloseStore(store1, 0);
311 }
312
313 static void compareStore(HCERTSTORE store, LPCSTR name, const BYTE *pb,
314 DWORD cb, BOOL todo)
315 {
316 BOOL ret;
317 CRYPT_DATA_BLOB blob = { 0, NULL };
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(blob.cbData == cb, "%s: expected size %d, got %d\n", name, cb,
324 blob.cbData);
325 blob.pbData = HeapAlloc(GetProcessHeap(), 0, blob.cbData);
326 if (blob.pbData)
327 {
328 ret = CertSaveStore(store, X509_ASN_ENCODING, CERT_STORE_SAVE_AS_STORE,
329 CERT_STORE_SAVE_TO_MEMORY, &blob, 0);
330 ok(ret, "CertSaveStore failed: %08x\n", GetLastError());
331 todo_wine_if (todo)
332 ok(!memcmp(pb, blob.pbData, cb), "%s: unexpected value\n", name);
333 HeapFree(GetProcessHeap(), 0, blob.pbData);
334 }
335 }
336
337 static const BYTE serializedStoreWithCert[] = {
338 0x00,0x00,0x00,0x00,0x43,0x45,0x52,0x54,0x20,0x00,0x00,0x00,0x01,0x00,0x00,
339 0x00,0x7c,0x00,0x00,0x00,0x30,0x7a,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,
340 0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,
341 0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,
342 0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,
343 0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,
344 0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,
345 0x20,0x4c,0x61,0x6e,0x67,0x00,0x30,0x07,0x30,0x02,0x06,0x00,0x03,0x01,0x00,
346 0xa3,0x16,0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,
347 0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,
348 0x00,0x00,0x00,0x00,0x00,0x00 };
349
350 static const struct
351 {
352 HKEY key;
353 DWORD cert_store;
354 BOOL appdata_file;
355 WCHAR store_name[16];
356 const WCHAR *base_reg_path;
357 } reg_store_saved_certs[] = {
358 { HKEY_LOCAL_MACHINE, CERT_SYSTEM_STORE_LOCAL_MACHINE, FALSE,
359 {'R','O','O','T',0}, CERT_LOCAL_MACHINE_SYSTEM_STORE_REGPATH },
360 { HKEY_LOCAL_MACHINE, CERT_SYSTEM_STORE_LOCAL_MACHINE, FALSE,
361 {'M','Y',0}, CERT_LOCAL_MACHINE_SYSTEM_STORE_REGPATH },
362 { HKEY_LOCAL_MACHINE, CERT_SYSTEM_STORE_LOCAL_MACHINE, FALSE,
363 {'C','A',0}, CERT_LOCAL_MACHINE_SYSTEM_STORE_REGPATH },
364 /* Adding to HKCU\Root triggers safety warning. */
365 { HKEY_CURRENT_USER, CERT_SYSTEM_STORE_CURRENT_USER, TRUE,
366 {'M','Y',0}, CERT_LOCAL_MACHINE_SYSTEM_STORE_REGPATH },
367 { HKEY_CURRENT_USER, CERT_SYSTEM_STORE_CURRENT_USER, FALSE,
368 {'C','A',0}, CERT_LOCAL_MACHINE_SYSTEM_STORE_REGPATH }
369 };
370
371 /* Testing whether system stores are available for adding new certs
372 * and checking directly in the registry whether they are actually saved or deleted.
373 * Windows treats HKCU\My (at least) as a special case and uses AppData directory
374 * for storing certs, not registry.
375 */
376 static void testRegStoreSavedCerts(void)
377 {
378 static const WCHAR fmt[] =
379 { '%','s','\\','%','s','\\','%','s','\\','%','s',0},
380 ms_certs[] =
381 { '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},
382 certs[] =
383 {'C','e','r','t','i','f','i','c','a','t','e','s',0},
384 bigCert_hash[] = {
385 '6','E','3','0','9','0','7','1','5','F','D','9','2','3',
386 '5','6','E','B','A','E','2','5','4','0','E','6','2','2',
387 'D','A','1','9','2','6','0','2','A','6','0','8',0};
388 PCCERT_CONTEXT cert1, cert2;
389 HCERTSTORE store;
390 HANDLE cert_file;
391 HRESULT pathres;
392 WCHAR key_name[MAX_PATH], appdata_path[MAX_PATH];
393 HKEY key;
394 BOOL ret;
395 DWORD res,i;
396
397 for (i = 0; i < sizeof(reg_store_saved_certs) / sizeof(reg_store_saved_certs[0]); i++)
398 {
399 DWORD err;
400
401 store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY_W,0,0,
402 reg_store_saved_certs[i].cert_store, reg_store_saved_certs[i].store_name);
403
404 err = GetLastError();
405 if (!store)
406 {
407 ok (err == ERROR_ACCESS_DENIED, "Failed to create store at %d (%08x)\n", i, err);
408 skip("Insufficient privileges for the test %d\n", i);
409 continue;
410 }
411 ok (store!=NULL, "Failed to open the store at %d, %x\n", i, GetLastError());
412 cert1 = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert, sizeof(bigCert));
413 ok (cert1 != NULL, "Create cert context failed at %d, %x\n", i, GetLastError());
414 ret = CertAddCertificateContextToStore(store, cert1, CERT_STORE_ADD_REPLACE_EXISTING, NULL);
415 /* Addittional skip per Win7, it allows opening HKLM store, but disallows adding certs */
416 err = GetLastError();
417 if (!ret)
418 {
419 ok (err == ERROR_ACCESS_DENIED, "Failed to add certificate to store at %d (%08x)\n", i, err);
420 skip("Insufficient privileges for the test %d\n", i);
421 continue;
422 }
423 ok (ret, "Adding to the store failed at %d, %x\n", i, err);
424 CertFreeCertificateContext(cert1);
425 CertCloseStore(store, 0);
426
427 wsprintfW(key_name, fmt, reg_store_saved_certs[i].base_reg_path,
428 reg_store_saved_certs[i].store_name, certs, bigCert_hash);
429
430 if (!reg_store_saved_certs[i].appdata_file)
431 {
432 res = RegOpenKeyExW(reg_store_saved_certs[i].key, key_name, 0, KEY_ALL_ACCESS, &key);
433 ok (!res, "The cert hasn't been saved at %d, %x\n", i, GetLastError());
434 if (!res) RegCloseKey(key);
435 } else
436 {
437 pathres = SHGetFolderPathW(NULL, CSIDL_APPDATA, NULL, 0, appdata_path);
438 ok (pathres == S_OK,
439 "Failed to get app data path at %d (%x)\n", pathres, GetLastError());
440 if (pathres == S_OK)
441 {
442 PathAppendW(appdata_path, ms_certs);
443 PathAppendW(appdata_path, reg_store_saved_certs[i].store_name);
444 PathAppendW(appdata_path, certs);
445 PathAppendW(appdata_path, bigCert_hash);
446
447 cert_file = CreateFileW(appdata_path, GENERIC_READ, 0, NULL,
448 OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
449 todo_wine ok (cert_file != INVALID_HANDLE_VALUE,
450 "Cert was not saved in AppData at %d (%x)\n", i, GetLastError());
451 CloseHandle(cert_file);
452 }
453 }
454
455 /* deleting cert from store */
456 store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY_W,0,0,
457 reg_store_saved_certs[i].cert_store, reg_store_saved_certs[i].store_name);
458 ok (store!=NULL, "Failed to open the store at %d, %x\n", i, GetLastError());
459
460 cert1 = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert, sizeof(bigCert));
461 ok (cert1 != NULL, "Create cert context failed at %d, %x\n", i, GetLastError());
462
463 cert2 = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
464 CERT_FIND_EXISTING, cert1, NULL);
465 ok (cert2 != NULL, "Failed to find cert in the store at %d, %x\n", i, GetLastError());
466
467 ret = CertDeleteCertificateFromStore(cert2);
468 ok (ret, "Failed to delete certificate from store at %d, %x\n", i, GetLastError());
469
470 CertFreeCertificateContext(cert1);
471 CertFreeCertificateContext(cert2);
472 CertCloseStore(store, 0);
473
474 res = RegOpenKeyExW(reg_store_saved_certs[i].key, key_name, 0, KEY_ALL_ACCESS, &key);
475 ok (res, "The cert's registry entry should be absent at %i, %x\n", i, GetLastError());
476 if (!res) RegCloseKey(key);
477
478 if (reg_store_saved_certs[i].appdata_file)
479 {
480 cert_file = CreateFileW(appdata_path, GENERIC_READ, 0, NULL,
481 OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
482 ok (cert_file == INVALID_HANDLE_VALUE,
483 "Cert should have been absent in AppData %d\n", i);
484
485 CloseHandle(cert_file);
486 }
487 }
488 }
489
490 /**
491 * This test checks that certificate falls into correct store of a collection
492 * depending on the access flags and priorities.
493 */
494 static void testStoresInCollection(void)
495 {
496 PCCERT_CONTEXT cert1, cert2, tcert1;
497 HCERTSTORE collection, ro_store, rw_store, rw_store_2, tstore;
498 static const WCHAR WineTestRO_W[] = { 'W','i','n','e','T','e','s','t','_','R','O',0 },
499 WineTestRW_W[] = { 'W','i','n','e','T','e','s','t','_','R','W',0 },
500 WineTestRW2_W[]= { 'W','i','n','e','T','e','s','t','_','R','W','2',0 };
501 BOOL ret;
502
503 collection = CertOpenStore(CERT_STORE_PROV_COLLECTION, 0, 0,
504 CERT_STORE_CREATE_NEW_FLAG, NULL);
505 ok(collection != NULL, "Failed to init collection store, last error %x\n", GetLastError());
506 /* Add read-only store to collection with very high priority*/
507 ro_store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY_W, 0, 0,
508 CERT_SYSTEM_STORE_CURRENT_USER, WineTestRO_W);
509 ok(ro_store != NULL, "Failed to init ro store %x\n", GetLastError());
510
511 ret = CertAddStoreToCollection(collection, ro_store, 0, 1000);
512 ok (ret, "Failed to add read-only store to collection %x\n", GetLastError());
513
514 cert1 = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert, sizeof(bigCert));
515 ok (cert1 != NULL, "Create cert context failed %x\n", GetLastError());
516 ret = CertAddCertificateContextToStore(collection, cert1, CERT_STORE_ADD_ALWAYS, NULL);
517 ok (!ret, "Added cert to collection with single read-only store %x\n", GetLastError());
518
519 /* Add read-write store to collection with the lowest priority*/
520 rw_store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY_W, 0, 0,
521 CERT_SYSTEM_STORE_CURRENT_USER, WineTestRW_W);
522 ok (rw_store != NULL, "Failed to open rw store %x\n", GetLastError());
523 ret = CertAddStoreToCollection(collection, rw_store, CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
524 ok (ret, "Failed to add rw store to collection %x\n", GetLastError());
525 /** Adding certificate to collection should fall into rw store,
526 * even though prioirty of the ro_store is higher */
527 ret = CertAddCertificateContextToStore(collection, cert1, CERT_STORE_ADD_REPLACE_EXISTING, NULL);
528 ok (ret, "Failed to add cert to the collection %x\n", GetLastError());
529
530 tcert1 = CertEnumCertificatesInStore(ro_store, NULL);
531 ok (!tcert1, "Read-only ro_store contains cert\n");
532
533 tcert1 = CertEnumCertificatesInStore(rw_store, NULL);
534 ok (cert1 && tcert1->cbCertEncoded == cert1->cbCertEncoded,
535 "Unexpected cert in the rw store\n");
536 CertFreeCertificateContext(tcert1);
537
538 tcert1 = CertEnumCertificatesInStore(collection, NULL);
539 ok (tcert1 && tcert1->cbCertEncoded == cert1->cbCertEncoded,
540 "Unexpected cert in the collection\n");
541 CertFreeCertificateContext(tcert1);
542
543 /** adding one more rw store with higher priority*/
544 rw_store_2 = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY_W, 0, 0,
545 CERT_SYSTEM_STORE_CURRENT_USER, WineTestRW2_W);
546 ok (rw_store_2 != NULL, "Failed to init second rw store %x\n", GetLastError());
547 ret = CertAddStoreToCollection(collection, rw_store_2, CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 50);
548 ok (ret, "Failed to add rw_store_2 to collection %x\n",GetLastError());
549
550 cert2 = CertCreateCertificateContext(X509_ASN_ENCODING, signedBigCert, sizeof(signedBigCert));
551 ok (cert2 != NULL, "Failed to create cert context %x\n", GetLastError());
552 ret = CertAddCertificateContextToStore(collection, cert2, CERT_STORE_ADD_REPLACE_EXISTING, NULL);
553 ok (ret, "Failed to add cert3 to the store %x\n",GetLastError());
554
555 /** checking certificates in the stores */
556 tcert1 = CertEnumCertificatesInStore(ro_store, 0);
557 ok (tcert1 == NULL, "Read-only store not empty\n");
558
559 tcert1 = CertEnumCertificatesInStore(rw_store, NULL);
560 ok (tcert1 && tcert1->cbCertEncoded == cert1->cbCertEncoded,
561 "Unexpected cert in the rw_store\n");
562 CertFreeCertificateContext(tcert1);
563
564 tcert1 = CertEnumCertificatesInStore(rw_store_2, NULL);
565 ok (tcert1 && tcert1->cbCertEncoded == cert2->cbCertEncoded,
566 "Unexpected cert in the rw_store_2\n");
567 CertFreeCertificateContext(tcert1);
568
569 /** checking certificates in the collection */
570 tcert1 = CertEnumCertificatesInStore(collection, NULL);
571 ok (tcert1 && tcert1->cbCertEncoded == cert2->cbCertEncoded,
572 "cert2 expected in the collection got %p, %x\n",tcert1, GetLastError());
573 tcert1 = CertEnumCertificatesInStore(collection, tcert1);
574 ok (tcert1 && tcert1->cbCertEncoded == cert1->cbCertEncoded,
575 "cert1 expected in the collection got %p, %x\n",tcert1, GetLastError());
576 tcert1 = CertEnumCertificatesInStore(collection, tcert1);
577 ok (tcert1==NULL,"Unexpected cert in the collection %p %x\n",tcert1, GetLastError());
578
579 /* checking whether certs had been saved */
580 tstore = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY_W,0,0,
581 CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_OPEN_EXISTING_FLAG, WineTestRW_W);
582 ok (tstore!=NULL, "Failed to open existing rw store\n");
583 tcert1 = CertEnumCertificatesInStore(tstore, NULL);
584 todo_wine
585 ok(tcert1 && tcert1->cbCertEncoded == cert1->cbCertEncoded, "cert1 wasn't saved\n");
586 CertFreeCertificateContext(tcert1);
587 CertCloseStore(tstore,0);
588
589 tstore = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY_W,0,0,
590 CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_OPEN_EXISTING_FLAG, WineTestRW2_W);
591 ok (tstore!=NULL, "Failed to open existing rw2 store\n");
592 tcert1 = CertEnumCertificatesInStore(tstore, NULL);
593 todo_wine
594 ok (tcert1 && tcert1->cbCertEncoded == cert2->cbCertEncoded, "cert2 wasn't saved\n");
595 CertFreeCertificateContext(tcert1);
596 CertCloseStore(tstore,0);
597
598 CertCloseStore(collection,0);
599 CertCloseStore(ro_store,0);
600 CertCloseStore(rw_store,0);
601 CertCloseStore(rw_store_2,0);
602
603 /* reopening registry stores to check whether certs had been saved */
604 rw_store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY_W,0,0,
605 CERT_SYSTEM_STORE_CURRENT_USER, WineTestRW_W);
606 tcert1 = CertEnumCertificatesInStore(rw_store, NULL);
607 ok (tcert1 && tcert1->cbCertEncoded == cert1->cbCertEncoded,
608 "Unexpected cert in store %p\n", tcert1);
609 CertFreeCertificateContext(tcert1);
610 CertCloseStore(rw_store,0);
611
612 rw_store_2 = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY_W,0,0,
613 CERT_SYSTEM_STORE_CURRENT_USER, WineTestRW2_W);
614 tcert1 = CertEnumCertificatesInStore(rw_store_2, NULL);
615 ok (tcert1 && tcert1->cbCertEncoded == cert2->cbCertEncoded,
616 "Unexpected cert in store %p\n", tcert1);
617 CertFreeCertificateContext(tcert1);
618 CertCloseStore(rw_store_2,0);
619
620 CertFreeCertificateContext(cert1);
621 CertFreeCertificateContext(cert2);
622 CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY_W,0,0,
623 CERT_STORE_DELETE_FLAG|CERT_SYSTEM_STORE_CURRENT_USER,WineTestRO_W);
624 CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY_W,0,0,
625 CERT_STORE_DELETE_FLAG|CERT_SYSTEM_STORE_CURRENT_USER,WineTestRW_W);
626 CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY_W,0,0,
627 CERT_STORE_DELETE_FLAG|CERT_SYSTEM_STORE_CURRENT_USER,WineTestRW2_W);
628
629 }
630
631 static void testCollectionStore(void)
632 {
633 HCERTSTORE store1, store2, collection, collection2;
634 PCCERT_CONTEXT context;
635 BOOL ret;
636 static const WCHAR szPrefix[] = { 'c','e','r',0 };
637 static const WCHAR szDot[] = { '.',0 };
638 WCHAR filename[MAX_PATH];
639 HANDLE file;
640
641 collection = CertOpenStore(CERT_STORE_PROV_COLLECTION, 0, 0,
642 CERT_STORE_CREATE_NEW_FLAG, NULL);
643
644 /* Try adding a cert to any empty collection */
645 ret = CertAddEncodedCertificateToStore(collection, X509_ASN_ENCODING,
646 bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, NULL);
647 ok(!ret && GetLastError() == E_ACCESSDENIED,
648 "Expected E_ACCESSDENIED, got %08x\n", GetLastError());
649
650 /* Create and add a cert to a memory store */
651 store1 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
652 CERT_STORE_CREATE_NEW_FLAG, NULL);
653 ret = CertAddEncodedCertificateToStore(store1, X509_ASN_ENCODING,
654 bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, NULL);
655 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n", GetLastError());
656 /* Add the memory store to the collection, without allowing adding */
657 ret = CertAddStoreToCollection(collection, store1, 0, 0);
658 ok(ret, "CertAddStoreToCollection failed: %08x\n", GetLastError());
659 /* Verify the cert is in the collection */
660 context = CertEnumCertificatesInStore(collection, NULL);
661 ok(context != NULL, "Expected a valid context\n");
662 if (context)
663 {
664 ok(context->hCertStore == collection, "Unexpected store\n");
665 CertFreeCertificateContext(context);
666 }
667 /* Check that adding to the collection isn't allowed */
668 ret = CertAddEncodedCertificateToStore(collection, X509_ASN_ENCODING,
669 bigCert2, sizeof(bigCert2), CERT_STORE_ADD_ALWAYS, NULL);
670 ok(!ret && GetLastError() == E_ACCESSDENIED,
671 "Expected E_ACCESSDENIED, got %08x\n", GetLastError());
672
673 /* Create a new memory store */
674 store2 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
675 CERT_STORE_CREATE_NEW_FLAG, NULL);
676 /* Try adding a store to a non-collection store */
677 ret = CertAddStoreToCollection(store1, store2,
678 CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
679 ok(!ret && GetLastError() == E_INVALIDARG,
680 "Expected E_INVALIDARG, got %08x\n", GetLastError());
681 /* Try adding some bogus stores */
682 /* This crashes in Windows
683 ret = pCertAddStoreToCollection(0, store2,
684 CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
685 */
686 /* This "succeeds"... */
687 ret = CertAddStoreToCollection(collection, 0,
688 CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
689 ok(ret, "CertAddStoreToCollection failed: %08x\n", GetLastError());
690 /* while this crashes.
691 ret = pCertAddStoreToCollection(collection, 1,
692 CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
693 */
694
695 /* Add it to the collection, this time allowing adding */
696 ret = CertAddStoreToCollection(collection, store2,
697 CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
698 ok(ret, "CertAddStoreToCollection failed: %08x\n", GetLastError());
699 /* Check that adding to the collection is allowed */
700 ret = CertAddEncodedCertificateToStore(collection, X509_ASN_ENCODING,
701 bigCert2, sizeof(bigCert2), CERT_STORE_ADD_ALWAYS, NULL);
702 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n", GetLastError());
703 /* Now check that it was actually added to store2 */
704 context = CertEnumCertificatesInStore(store2, NULL);
705 ok(context != NULL, "Expected a valid context\n");
706 if (context)
707 {
708 ok(context->hCertStore == store2, "Unexpected store\n");
709 CertFreeCertificateContext(context);
710 }
711 /* Check that the collection has both bigCert and bigCert2. bigCert comes
712 * first because store1 was added first.
713 */
714 context = CertEnumCertificatesInStore(collection, NULL);
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(bigCert),
720 "Wrong size %d\n", context->cbCertEncoded);
721 ok(!memcmp(context->pbCertEncoded, bigCert, context->cbCertEncoded),
722 "Unexpected cert\n");
723 context = CertEnumCertificatesInStore(collection, context);
724 ok(context != NULL, "Expected a valid context\n");
725 if (context)
726 {
727 ok(context->hCertStore == collection, "Unexpected store\n");
728 ok(context->cbCertEncoded == sizeof(bigCert2),
729 "Wrong size %d\n", context->cbCertEncoded);
730 ok(!memcmp(context->pbCertEncoded, bigCert2,
731 context->cbCertEncoded), "Unexpected cert\n");
732 context = CertEnumCertificatesInStore(collection, context);
733 ok(!context, "Unexpected cert\n");
734 }
735 }
736 /* close store2, and check that the collection is unmodified */
737 CertCloseStore(store2, 0);
738 context = CertEnumCertificatesInStore(collection, NULL);
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(bigCert),
744 "Wrong size %d\n", context->cbCertEncoded);
745 ok(!memcmp(context->pbCertEncoded, bigCert, context->cbCertEncoded),
746 "Unexpected cert\n");
747 context = CertEnumCertificatesInStore(collection, context);
748 ok(context != NULL, "Expected a valid context\n");
749 if (context)
750 {
751 ok(context->hCertStore == collection, "Unexpected store\n");
752 ok(context->cbCertEncoded == sizeof(bigCert2),
753 "Wrong size %d\n", context->cbCertEncoded);
754 ok(!memcmp(context->pbCertEncoded, bigCert2,
755 context->cbCertEncoded), "Unexpected cert\n");
756 context = CertEnumCertificatesInStore(collection, context);
757 ok(!context, "Unexpected cert\n");
758 }
759 }
760
761 /* Adding a collection to a collection is legal */
762 collection2 = CertOpenStore(CERT_STORE_PROV_COLLECTION, 0, 0,
763 CERT_STORE_CREATE_NEW_FLAG, NULL);
764 ret = CertAddStoreToCollection(collection2, collection,
765 CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
766 ok(ret, "CertAddStoreToCollection failed: %08x\n", GetLastError());
767 /* check the contents of collection2 */
768 context = CertEnumCertificatesInStore(collection2, NULL);
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(bigCert),
774 "Wrong size %d\n", context->cbCertEncoded);
775 ok(!memcmp(context->pbCertEncoded, bigCert, context->cbCertEncoded),
776 "Unexpected cert\n");
777 context = CertEnumCertificatesInStore(collection2, context);
778 ok(context != NULL, "Expected a valid context\n");
779 if (context)
780 {
781 ok(context->hCertStore == collection2, "Unexpected store\n");
782 ok(context->cbCertEncoded == sizeof(bigCert2),
783 "Wrong size %d\n", context->cbCertEncoded);
784 ok(!memcmp(context->pbCertEncoded, bigCert2,
785 context->cbCertEncoded), "Unexpected cert\n");
786 context = CertEnumCertificatesInStore(collection2, context);
787 ok(!context, "Unexpected cert\n");
788 }
789 }
790
791 /* I'd like to test closing the collection in the middle of enumeration,
792 * but my tests have been inconsistent. The first time calling
793 * CertEnumCertificatesInStore on a closed collection succeeded, while the
794 * second crashed. So anything appears to be fair game.
795 * I'd also like to test removing a store from a collection in the middle
796 * of an enumeration, but my tests in Windows have been inconclusive.
797 * In one scenario it worked. In another scenario, about a third of the
798 * time this leads to "random" crashes elsewhere in the code. This
799 * probably means this is not allowed.
800 */
801
802 CertCloseStore(store1, 0);
803 CertCloseStore(collection, 0);
804 CertCloseStore(collection2, 0);
805
806 /* Add the same cert to two memory stores, then put them in a collection */
807 store1 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
808 CERT_STORE_CREATE_NEW_FLAG, NULL);
809 ok(store1 != 0, "CertOpenStore failed: %08x\n", GetLastError());
810 store2 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
811 CERT_STORE_CREATE_NEW_FLAG, NULL);
812 ok(store2 != 0, "CertOpenStore failed: %08x\n", GetLastError());
813
814 ret = CertAddEncodedCertificateToStore(store1, X509_ASN_ENCODING,
815 bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, NULL);
816 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n", GetLastError());
817 ret = CertAddEncodedCertificateToStore(store2, X509_ASN_ENCODING,
818 bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, NULL);
819 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n", GetLastError());
820 collection = CertOpenStore(CERT_STORE_PROV_COLLECTION, 0, 0,
821 CERT_STORE_CREATE_NEW_FLAG, NULL);
822 ok(collection != 0, "CertOpenStore failed: %08x\n", GetLastError());
823
824 ret = CertAddStoreToCollection(collection, store1, CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
825 ok(ret, "CertAddStoreToCollection failed: %08x\n", GetLastError());
826 ret = CertAddStoreToCollection(collection, store2, CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
827 ok(ret, "CertAddStoreToCollection failed: %08x\n", GetLastError());
828
829 /* Check that the collection has two copies of the same cert */
830 context = CertEnumCertificatesInStore(collection, NULL);
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, "Expected a valid context\n");
841 if (context)
842 {
843 ok(context->hCertStore == collection, "Unexpected store\n");
844 ok(context->cbCertEncoded == sizeof(bigCert),
845 "Wrong size %d\n", context->cbCertEncoded);
846 ok(!memcmp(context->pbCertEncoded, bigCert, context->cbCertEncoded),
847 "Unexpected cert\n");
848 context = CertEnumCertificatesInStore(collection, context);
849 ok(context == NULL, "Unexpected cert\n");
850 }
851 }
852
853 /* The following would check whether I can delete an identical cert, rather
854 * than one enumerated from the store. It crashes, so that means I must
855 * only call CertDeleteCertificateFromStore with contexts enumerated from
856 * the store.
857 context = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert,
858 sizeof(bigCert));
859 ok(context != NULL, "CertCreateCertificateContext failed: %08x\n",
860 GetLastError());
861 if (context)
862 {
863 ret = CertDeleteCertificateFromStore(collection, context);
864 printf("ret is %d, GetLastError is %08x\n", ret, GetLastError());
865 CertFreeCertificateContext(context);
866 }
867 */
868
869 /* Now check deleting from the collection. */
870 context = CertEnumCertificatesInStore(collection, NULL);
871 ok(context != NULL, "Expected a valid context\n");
872 if (context)
873 {
874 CertDeleteCertificateFromStore(context);
875 /* store1 should now be empty */
876 context = CertEnumCertificatesInStore(store1, NULL);
877 ok(!context, "Unexpected cert\n");
878 /* and there should be one certificate in the collection */
879 context = CertEnumCertificatesInStore(collection, NULL);
880 ok(context != NULL, "Expected a valid cert\n");
881 if (context)
882 {
883 ok(context->hCertStore == collection, "Unexpected store\n");
884 ok(context->cbCertEncoded == sizeof(bigCert),
885 "Wrong size %d\n", context->cbCertEncoded);
886 ok(!memcmp(context->pbCertEncoded, bigCert, context->cbCertEncoded),
887 "Unexpected cert\n");
888 }
889 context = CertEnumCertificatesInStore(collection, context);
890 ok(context == NULL, "Unexpected cert\n");
891 }
892
893 if (!pCertRemoveStoreFromCollection)
894 {
895 win_skip("CertRemoveStoreFromCollection() is not available\n");
896 }
897 else
898 {
899 /* Finally, test removing stores from the collection. No return
900 * value, so it's a bit funny to test.
901 */
902 /* This crashes
903 * pCertRemoveStoreFromCollection(NULL, NULL);
904 */
905 /* This "succeeds," no crash, no last error set */
906 SetLastError(0xdeadbeef);
907 pCertRemoveStoreFromCollection(store2, collection);
908 ok(GetLastError() == 0xdeadbeef,
909 "Didn't expect an error to be set: %08x\n", GetLastError());
910
911 /* After removing store2, the collection should be empty */
912 SetLastError(0xdeadbeef);
913 pCertRemoveStoreFromCollection(collection, store2);
914 ok(GetLastError() == 0xdeadbeef,
915 "Didn't expect an error to be set: %08x\n", GetLastError());
916 context = CertEnumCertificatesInStore(collection, NULL);
917 ok(!context, "Unexpected cert\n");
918 }
919
920 CertCloseStore(collection, 0);
921 CertCloseStore(store2, 0);
922 CertCloseStore(store1, 0);
923
924 /* Test adding certificates to and deleting certificates from collections.
925 */
926 store1 = CertOpenSystemStoreA(0, "My");
927 collection = CertOpenStore(CERT_STORE_PROV_COLLECTION, 0, 0,
928 CERT_STORE_CREATE_NEW_FLAG, NULL);
929
930 ret = CertAddEncodedCertificateToStore(store1, X509_ASN_ENCODING,
931 bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, &context);
932 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n", GetLastError());
933 CertDeleteCertificateFromStore(context);
934
935 CertAddStoreToCollection(collection, store1, CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
936
937 ret = CertAddEncodedCertificateToStore(collection, X509_ASN_ENCODING,
938 bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, &context);
939 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n", GetLastError());
940 CertDeleteCertificateFromStore(context);
941
942 CertCloseStore(collection, 0);
943 CertCloseStore(store1, 0);
944
945 /* Test whether a collection store can be committed */
946 if (!pCertControlStore)
947 {
948 win_skip("CertControlStore() is not available\n");
949 return;
950 }
951 collection = CertOpenStore(CERT_STORE_PROV_COLLECTION, 0, 0,
952 CERT_STORE_CREATE_NEW_FLAG, NULL);
953
954 SetLastError(0xdeadbeef);
955 ret = pCertControlStore(collection, 0, CERT_STORE_CTRL_COMMIT, NULL);
956 ok(ret, "CertControlStore failed: %08x\n", GetLastError());
957
958 /* Adding a mem store that can't be committed prevents a successful commit.
959 */
960 store1 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
961 CERT_STORE_CREATE_NEW_FLAG, NULL);
962 CertAddStoreToCollection(collection, store1, 0, 0);
963 SetLastError(0xdeadbeef);
964 ret = pCertControlStore(collection, 0, CERT_STORE_CTRL_COMMIT, NULL);
965 ok(!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED,
966 "expected ERROR_CALL_NOT_IMPLEMENTED, got %d\n", GetLastError());
967 pCertRemoveStoreFromCollection(collection, store1);
968 CertCloseStore(store1, 0);
969
970 /* Test adding a cert to a collection with a file store, committing the
971 * change to the collection, and comparing the resulting file.
972 */
973 if (!GetTempFileNameW(szDot, szPrefix, 0, filename))
974 return;
975
976 DeleteFileW(filename);
977 file = CreateFileW(filename, GENERIC_READ | GENERIC_WRITE, 0, NULL,
978 CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
979 if (file == INVALID_HANDLE_VALUE)
980 return;
981
982 store1 = CertOpenStore(CERT_STORE_PROV_FILE, 0, 0,
983 CERT_FILE_STORE_COMMIT_ENABLE_FLAG, file);
984 ok(store1 != NULL, "CertOpenStore failed: %08x\n", GetLastError());
985 CloseHandle(file);
986 CertAddStoreToCollection(collection, store1, CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
987 CertCloseStore(store1, 0);
988
989 ret = CertAddEncodedCertificateToStore(collection, X509_ASN_ENCODING,
990 bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, NULL);
991 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
992 GetLastError());
993 ret = pCertControlStore(collection, 0, CERT_STORE_CTRL_COMMIT, NULL);
994 ok(ret, "CertControlStore failed: %d\n", ret);
995 compareStore(collection, "serialized store with cert",
996 serializedStoreWithCert, sizeof(serializedStoreWithCert), FALSE);
997 CertCloseStore(collection, 0);
998
999 DeleteFileW(filename);
1000 }
1001
1002 /* Looks for the property with ID propID in the buffer buf. Returns a pointer
1003 * to its header if found, NULL if not.
1004 */
1005 static const struct CertPropIDHeader *findPropID(const BYTE *buf, DWORD size,
1006 DWORD propID)
1007 {
1008 const struct CertPropIDHeader *ret = NULL;
1009 BOOL failed = FALSE;
1010
1011 while (size && !ret && !failed)
1012 {
1013 if (size < sizeof(struct CertPropIDHeader))
1014 failed = TRUE;
1015 else
1016 {
1017 const struct CertPropIDHeader *hdr =
1018 (const struct CertPropIDHeader *)buf;
1019
1020 size -= sizeof(struct CertPropIDHeader);
1021 buf += sizeof(struct CertPropIDHeader);
1022 if (size < hdr->cb)
1023 failed = TRUE;
1024 else if (hdr->propID == propID)
1025 ret = hdr;
1026 else
1027 {
1028 buf += hdr->cb;
1029 size -= hdr->cb;
1030 }
1031 }
1032 }
1033 return ret;
1034 }
1035
1036 static void testRegStore(void)
1037 {
1038 static const char tempKey[] = "Software\\Wine\\CryptTemp";
1039 HCERTSTORE store;
1040 LONG rc;
1041 HKEY key = NULL;
1042 DWORD disp, GLE;
1043
1044 store = CertOpenStore(CERT_STORE_PROV_REG, 0, 0, 0, NULL);
1045 GLE = GetLastError();
1046 ok(!store && (GLE == ERROR_INVALID_HANDLE || GLE == ERROR_BADKEY),
1047 "Expected ERROR_INVALID_HANDLE or ERROR_BADKEY, got %d\n", GLE);
1048 store = CertOpenStore(CERT_STORE_PROV_REG, 0, 0, 0, key);
1049 GLE = GetLastError();
1050 ok(!store && (GLE == ERROR_INVALID_HANDLE || GLE == ERROR_BADKEY),
1051 "Expected ERROR_INVALID_HANDLE or ERROR_BADKEY, got %d\n", GLE);
1052
1053 /* Opening up any old key works.. */
1054 key = HKEY_CURRENT_USER;
1055 store = CertOpenStore(CERT_STORE_PROV_REG, 0, 0, 0, key);
1056 /* Not sure if this is a bug in DuplicateHandle, marking todo_wine for now
1057 */
1058 todo_wine ok(store != 0, "CertOpenStore failed: %08x\n", GetLastError());
1059 CertCloseStore(store, 0);
1060
1061 /* It looks like the remainder pretty much needs CertControlStore() */
1062 if (!pCertControlStore)
1063 {
1064 win_skip("CertControlStore() is not available\n");
1065 return;
1066 }
1067
1068 rc = RegCreateKeyExA(HKEY_CURRENT_USER, tempKey, 0, NULL, 0, KEY_ALL_ACCESS,
1069 NULL, &key, NULL);
1070 ok(!rc, "RegCreateKeyExA failed: %d\n", rc);
1071 if (key)
1072 {
1073 BOOL ret;
1074 BYTE hash[20];
1075 DWORD size, i;
1076 static const char certificates[] = "Certificates\\";
1077 char subKeyName[sizeof(certificates) + 20 * 2 + 1], *ptr;
1078 HKEY subKey;
1079 PCCERT_CONTEXT context;
1080
1081 store = CertOpenStore(CERT_STORE_PROV_REG, 0, 0, 0, key);
1082 ok(store != 0, "CertOpenStore failed: %08x\n", GetLastError());
1083 /* Add a certificate. It isn't persisted right away, since it's only
1084 * added to the cache..
1085 */
1086 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1087 bigCert2, sizeof(bigCert2), CERT_STORE_ADD_ALWAYS, NULL);
1088 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
1089 GetLastError());
1090 /* so flush the cache to force a commit.. */
1091 ret = pCertControlStore(store, 0, CERT_STORE_CTRL_COMMIT, NULL);
1092 ok(ret, "CertControlStore failed: %08x\n", GetLastError());
1093 /* and check that the expected subkey was written. */
1094 size = sizeof(hash);
1095 ret = CryptHashCertificate(0, 0, 0, bigCert2, sizeof(bigCert2),
1096 hash, &size);
1097 ok(ret, "CryptHashCertificate failed: %d\n", GetLastError());
1098 strcpy(subKeyName, certificates);
1099 for (i = 0, ptr = subKeyName + sizeof(certificates) - 1; i < size;
1100 i++, ptr += 2)
1101 sprintf(ptr, "%02X", hash[i]);
1102 rc = RegCreateKeyExA(key, subKeyName, 0, NULL, 0, KEY_ALL_ACCESS, NULL,
1103 &subKey, NULL);
1104 ok(!rc, "RegCreateKeyExA failed: %d\n", rc);
1105 if (subKey)
1106 {
1107 LPBYTE buf;
1108
1109 size = 0;
1110 RegQueryValueExA(subKey, "Blob", NULL, NULL, NULL, &size);
1111 buf = HeapAlloc(GetProcessHeap(), 0, size);
1112 if (buf)
1113 {
1114 rc = RegQueryValueExA(subKey, "Blob", NULL, NULL, buf, &size);
1115 ok(!rc, "RegQueryValueExA failed: %d\n", rc);
1116 if (!rc)
1117 {
1118 const struct CertPropIDHeader *hdr;
1119
1120 /* Both the hash and the cert should be present */
1121 hdr = findPropID(buf, size, CERT_CERT_PROP_ID);
1122 ok(hdr != NULL, "Expected to find a cert property\n");
1123 if (hdr)
1124 {
1125 ok(hdr->cb == sizeof(bigCert2),
1126 "Wrong size %d of cert property\n", hdr->cb);
1127 ok(!memcmp((const BYTE *)hdr + sizeof(*hdr), bigCert2,
1128 hdr->cb), "Unexpected cert in cert property\n");
1129 }
1130 hdr = findPropID(buf, size, CERT_HASH_PROP_ID);
1131 ok(hdr != NULL, "Expected to find a hash property\n");
1132 if (hdr)
1133 {
1134 ok(hdr->cb == sizeof(hash),
1135 "Wrong size %d of hash property\n", hdr->cb);
1136 ok(!memcmp((const BYTE *)hdr + sizeof(*hdr), hash,
1137 hdr->cb), "Unexpected hash in cert property\n");
1138 }
1139 }
1140 HeapFree(GetProcessHeap(), 0, buf);
1141 }
1142 RegCloseKey(subKey);
1143 }
1144
1145 /* Remove the existing context */
1146 context = CertEnumCertificatesInStore(store, NULL);
1147 ok(context != NULL, "Expected a cert context\n");
1148 if (context)
1149 CertDeleteCertificateFromStore(context);
1150 ret = pCertControlStore(store, 0, CERT_STORE_CTRL_COMMIT, NULL);
1151 ok(ret, "CertControlStore failed: %08x\n", GetLastError());
1152
1153 /* Add a serialized cert with a bogus hash directly to the registry */
1154 memset(hash, 0, sizeof(hash));
1155 strcpy(subKeyName, certificates);
1156 for (i = 0, ptr = subKeyName + sizeof(certificates) - 1;
1157 i < sizeof(hash); i++, ptr += 2)
1158 sprintf(ptr, "%02X", hash[i]);
1159 rc = RegCreateKeyExA(key, subKeyName, 0, NULL, 0, KEY_ALL_ACCESS, NULL,
1160 &subKey, NULL);
1161 ok(!rc, "RegCreateKeyExA failed: %d\n", rc);
1162 if (subKey)
1163 {
1164 BYTE buf[sizeof(struct CertPropIDHeader) * 2 + sizeof(hash) +
1165 sizeof(bigCert)], *ptr;
1166 DWORD certCount = 0;
1167 struct CertPropIDHeader *hdr;
1168
1169 hdr = (struct CertPropIDHeader *)buf;
1170 hdr->propID = CERT_HASH_PROP_ID;
1171 hdr->unknown1 = 1;
1172 hdr->cb = sizeof(hash);
1173 ptr = buf + sizeof(*hdr);
1174 memcpy(ptr, hash, sizeof(hash));
1175 ptr += sizeof(hash);
1176 hdr = (struct CertPropIDHeader *)ptr;
1177 hdr->propID = CERT_CERT_PROP_ID;
1178 hdr->unknown1 = 1;
1179 hdr->cb = sizeof(bigCert);
1180 ptr += sizeof(*hdr);
1181 memcpy(ptr, bigCert, sizeof(bigCert));
1182
1183 rc = RegSetValueExA(subKey, "Blob", 0, REG_BINARY, buf,
1184 sizeof(buf));
1185 ok(!rc, "RegSetValueExA failed: %d\n", rc);
1186
1187 ret = pCertControlStore(store, 0, CERT_STORE_CTRL_RESYNC, NULL);
1188 ok(ret, "CertControlStore failed: %08x\n", GetLastError());
1189
1190 /* Make sure the bogus hash cert gets loaded. */
1191 certCount = 0;
1192 context = NULL;
1193 do {
1194 context = CertEnumCertificatesInStore(store, context);
1195 if (context)
1196 certCount++;
1197 } while (context != NULL);
1198 ok(certCount == 1, "Expected 1 certificates, got %d\n", certCount);
1199
1200 RegCloseKey(subKey);
1201 }
1202
1203 /* Add another serialized cert directly to the registry, this time
1204 * under the correct key name (named with the correct hash value).
1205 */
1206 size = sizeof(hash);
1207 ret = CryptHashCertificate(0, 0, 0, bigCert2,
1208 sizeof(bigCert2), hash, &size);
1209 ok(ret, "CryptHashCertificate failed: %d\n", GetLastError());
1210 strcpy(subKeyName, certificates);
1211 for (i = 0, ptr = subKeyName + sizeof(certificates) - 1;
1212 i < sizeof(hash); i++, ptr += 2)
1213 sprintf(ptr, "%02X", hash[i]);
1214 rc = RegCreateKeyExA(key, subKeyName, 0, NULL, 0, KEY_ALL_ACCESS, NULL,
1215 &subKey, NULL);
1216 ok(!rc, "RegCreateKeyExA failed: %d\n", rc);
1217 if (subKey)
1218 {
1219 BYTE buf[sizeof(struct CertPropIDHeader) * 2 + sizeof(hash) +
1220 sizeof(bigCert2)], *ptr;
1221 DWORD certCount = 0;
1222 PCCERT_CONTEXT context;
1223 struct CertPropIDHeader *hdr;
1224
1225 /* First try with a bogus hash... */
1226 hdr = (struct CertPropIDHeader *)buf;
1227 hdr->propID = CERT_HASH_PROP_ID;
1228 hdr->unknown1 = 1;
1229 hdr->cb = sizeof(hash);
1230 ptr = buf + sizeof(*hdr);
1231 memset(ptr, 0, sizeof(hash));
1232 ptr += sizeof(hash);
1233 hdr = (struct CertPropIDHeader *)ptr;
1234 hdr->propID = CERT_CERT_PROP_ID;
1235 hdr->unknown1 = 1;
1236 hdr->cb = sizeof(bigCert2);
1237 ptr += sizeof(*hdr);
1238 memcpy(ptr, bigCert2, sizeof(bigCert2));
1239
1240 rc = RegSetValueExA(subKey, "Blob", 0, REG_BINARY, buf,
1241 sizeof(buf));
1242 ok(!rc, "RegSetValueExA failed: %d\n", rc);
1243
1244 ret = pCertControlStore(store, 0, CERT_STORE_CTRL_RESYNC, NULL);
1245 ok(ret, "CertControlStore failed: %08x\n", GetLastError());
1246
1247 /* and make sure just one cert still gets loaded. */
1248 certCount = 0;
1249 context = NULL;
1250 do {
1251 context = CertEnumCertificatesInStore(store, context);
1252 if (context)
1253 certCount++;
1254 } while (context != NULL);
1255 ok(certCount == 1 ||
1256 broken(certCount == 2) /* NT4 */ ,
1257 "Expected 1 certificates, got %d\n", certCount);
1258
1259 /* Try again with the correct hash... */
1260 ptr = buf + sizeof(*hdr);
1261 memcpy(ptr, hash, sizeof(hash));
1262
1263 rc = RegSetValueExA(subKey, "Blob", 0, REG_BINARY, buf,
1264 sizeof(buf));
1265 ok(!rc, "RegSetValueExA failed: %d\n", rc);
1266
1267 ret = pCertControlStore(store, 0, CERT_STORE_CTRL_RESYNC, NULL);
1268 ok(ret, "CertControlStore failed: %08x\n", GetLastError());
1269
1270 /* and make sure two certs get loaded. */
1271 certCount = 0;
1272 context = NULL;
1273 do {
1274 context = CertEnumCertificatesInStore(store, context);
1275 if (context)
1276 certCount++;
1277 } while (context != NULL);
1278 ok(certCount == 2, "Expected 2 certificates, got %d\n", certCount);
1279
1280 RegCloseKey(subKey);
1281 }
1282 CertCloseStore(store, 0);
1283 /* Is delete allowed on a reg store? */
1284 store = CertOpenStore(CERT_STORE_PROV_REG, 0, 0,
1285 CERT_STORE_DELETE_FLAG, key);
1286 ok(store == NULL, "Expected NULL return from CERT_STORE_DELETE_FLAG\n");
1287 ok(GetLastError() == 0, "CertOpenStore failed: %08x\n",
1288 GetLastError());
1289
1290 RegCloseKey(key);
1291 }
1292 /* The CertOpenStore with CERT_STORE_DELETE_FLAG above will delete the
1293 * contents of the key, but not the key itself.
1294 */
1295 rc = RegCreateKeyExA(HKEY_CURRENT_USER, tempKey, 0, NULL, 0, KEY_ALL_ACCESS,
1296 NULL, &key, &disp);
1297 ok(!rc, "RegCreateKeyExA failed: %d\n", rc);
1298 ok(disp == REG_OPENED_EXISTING_KEY,
1299 "Expected REG_OPENED_EXISTING_KEY, got %d\n", disp);
1300 if (!rc)
1301 {
1302 RegCloseKey(key);
1303 rc = RegDeleteKeyA(HKEY_CURRENT_USER, tempKey);
1304 if (rc)
1305 {
1306 HMODULE shlwapi = LoadLibraryA("shlwapi");
1307
1308 /* Use shlwapi's SHDeleteKeyA to _really_ blow away the key,
1309 * otherwise subsequent tests will fail.
1310 */
1311 if (shlwapi)
1312 {
1313 DWORD (WINAPI *pSHDeleteKeyA)(HKEY, LPCSTR);
1314
1315 pSHDeleteKeyA = (void*)GetProcAddress(shlwapi, "SHDeleteKeyA");
1316 if (pSHDeleteKeyA)
1317 pSHDeleteKeyA(HKEY_CURRENT_USER, tempKey);
1318 FreeLibrary(shlwapi);
1319 }
1320 }
1321 }
1322 }
1323
1324 static const char MyA[] = { 'M','y',0,0 };
1325 static const WCHAR MyW[] = { 'M','y',0 };
1326 static const WCHAR BogusW[] = { 'B','o','g','u','s',0 };
1327 static const WCHAR BogusPathW[] = { 'S','o','f','t','w','a','r','e','\\',
1328 'M','i','c','r','o','s','o','f','t','\\','S','y','s','t','e','m','C','e','r',
1329 't','i','f','i','c','a','t','e','s','\\','B','o','g','u','s',0 };
1330
1331 static void testSystemRegStore(void)
1332 {
1333 HCERTSTORE store, memStore;
1334
1335 /* Check with a UNICODE name */
1336 store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY, 0, 0,
1337 CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_OPEN_EXISTING_FLAG, MyW);
1338 /* Not all OSes support CERT_STORE_PROV_SYSTEM_REGISTRY, so don't continue
1339 * testing if they don't.
1340 */
1341 if (!store)
1342 return;
1343
1344 /* Check that it isn't a collection store */
1345 memStore = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
1346 CERT_STORE_CREATE_NEW_FLAG, NULL);
1347 if (memStore)
1348 {
1349 BOOL ret = CertAddStoreToCollection(store, memStore, 0, 0);
1350 ok(!ret && GetLastError() == E_INVALIDARG, "Expected E_INVALIDARG, got %08x\n", GetLastError());
1351 CertCloseStore(memStore, 0);
1352 }
1353 CertCloseStore(store, 0);
1354
1355 /* Check opening a bogus store */
1356 store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY, 0, 0,
1357 CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_OPEN_EXISTING_FLAG, BogusW);
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_REGISTRY, 0, 0,
1361 CERT_SYSTEM_STORE_CURRENT_USER, BogusW);
1362 ok(store != 0, "CertOpenStore failed: %08x\n", GetLastError());
1363 if (store)
1364 CertCloseStore(store, 0);
1365 /* Now check whether deleting is allowed */
1366 store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY, 0, 0,
1367 CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_DELETE_FLAG, BogusW);
1368 ok(!store, "CertOpenStore failed: %08x\n", GetLastError());
1369 RegDeleteKeyW(HKEY_CURRENT_USER, BogusPathW);
1370
1371 store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY, 0, 0, 0, NULL);
1372 ok(!store && GetLastError() == E_INVALIDARG,
1373 "Expected E_INVALIDARG, got %08x\n", GetLastError());
1374 store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY, 0, 0,
1375 CERT_SYSTEM_STORE_LOCAL_MACHINE | CERT_SYSTEM_STORE_CURRENT_USER, MyA);
1376 ok(!store && GetLastError() == E_INVALIDARG,
1377 "Expected E_INVALIDARG, got %08x\n", GetLastError());
1378 store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY, 0, 0,
1379 CERT_SYSTEM_STORE_LOCAL_MACHINE | CERT_SYSTEM_STORE_CURRENT_USER, MyW);
1380 ok(!store && GetLastError() == E_INVALIDARG,
1381 "Expected E_INVALIDARG, got %08x\n", GetLastError());
1382 /* The name is expected to be UNICODE, check with an ASCII name */
1383 store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY, 0, 0,
1384 CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_OPEN_EXISTING_FLAG, MyA);
1385 ok(!store && GetLastError() == ERROR_FILE_NOT_FOUND,
1386 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
1387 }
1388
1389 static void testSystemStore(void)
1390 {
1391 static const WCHAR baskslashW[] = { '\\',0 };
1392 HCERTSTORE store;
1393 WCHAR keyName[MAX_PATH];
1394 HKEY key;
1395 LONG rc;
1396
1397 store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0, 0, NULL);
1398 ok(!store && GetLastError() == ERROR_FILE_NOT_FOUND,
1399 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
1400 store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0,
1401 CERT_SYSTEM_STORE_LOCAL_MACHINE | CERT_SYSTEM_STORE_CURRENT_USER, MyA);
1402 ok(!store && GetLastError() == ERROR_FILE_NOT_FOUND,
1403 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
1404 store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0,
1405 CERT_SYSTEM_STORE_LOCAL_MACHINE | CERT_SYSTEM_STORE_CURRENT_USER, MyW);
1406 ok(!store && GetLastError() == ERROR_FILE_NOT_FOUND,
1407 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
1408 /* The name is expected to be UNICODE, first check with an ASCII name */
1409 store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0,
1410 CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_OPEN_EXISTING_FLAG, MyA);
1411 ok(!store && GetLastError() == ERROR_FILE_NOT_FOUND,
1412 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
1413 /* Create the expected key */
1414 lstrcpyW(keyName, CERT_LOCAL_MACHINE_SYSTEM_STORE_REGPATH);
1415 lstrcatW(keyName, baskslashW);
1416 lstrcatW(keyName, MyW);
1417 rc = RegCreateKeyExW(HKEY_CURRENT_USER, keyName, 0, NULL, 0, KEY_READ,
1418 NULL, &key, NULL);
1419 ok(!rc, "RegCreateKeyEx failed: %d\n", rc);
1420 if (!rc)
1421 RegCloseKey(key);
1422 /* Check opening with a UNICODE name, specifying the create new flag */
1423 store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0,
1424 CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_CREATE_NEW_FLAG, MyW);
1425 ok(!store && GetLastError() == ERROR_FILE_EXISTS,
1426 "Expected ERROR_FILE_EXISTS, got %08x\n", GetLastError());
1427 /* Now check opening with a UNICODE name, this time opening existing */
1428 store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0,
1429 CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_OPEN_EXISTING_FLAG, MyW);
1430 ok(store != 0, "CertOpenStore failed: %08x\n", GetLastError());
1431 if (store)
1432 {
1433 HCERTSTORE memStore = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
1434 CERT_STORE_CREATE_NEW_FLAG, NULL);
1435
1436 /* Check that it's a collection store */
1437 if (memStore)
1438 {
1439 BOOL ret = CertAddStoreToCollection(store, memStore, 0, 0);
1440 /* FIXME: this'll fail on NT4, but what error will it give? */
1441 ok(ret, "CertAddStoreToCollection failed: %08x\n", GetLastError());
1442 CertCloseStore(memStore, 0);
1443 }
1444 CertCloseStore(store, 0);
1445 }
1446
1447 /* Check opening a bogus store */
1448 store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0,
1449 CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_OPEN_EXISTING_FLAG, BogusW);
1450 ok(!store, "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
1451 store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0,
1452 CERT_SYSTEM_STORE_CURRENT_USER, BogusW);
1453 ok(store != 0, "CertOpenStore failed: %08x\n", GetLastError());
1454 if (store)
1455 CertCloseStore(store, 0);
1456 /* Now check whether deleting is allowed */
1457 store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0,
1458 CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_DELETE_FLAG, BogusW);
1459 ok(!store, "Didn't expect a store to be returned when deleting\n");
1460 RegDeleteKeyW(HKEY_CURRENT_USER, BogusPathW);
1461 }
1462
1463 static const BYTE serializedStoreWithCertAndCRL[] = {
1464 0x00,0x00,0x00,0x00,0x43,0x45,0x52,0x54,0x20,0x00,0x00,0x00,0x01,0x00,0x00,
1465 0x00,0x7c,0x00,0x00,0x00,0x30,0x7a,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,
1466 0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,
1467 0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,
1468 0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,
1469 0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,
1470 0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,
1471 0x20,0x4c,0x61,0x6e,0x67,0x00,0x30,0x07,0x30,0x02,0x06,0x00,0x03,0x01,0x00,
1472 0xa3,0x16,0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,
1473 0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01,0x21,0x00,0x00,0x00,0x01,0x00,
1474 0x00,0x00,0x47,0x00,0x00,0x00,0x30,0x45,0x30,0x2c,0x30,0x02,0x06,0x00,0x30,
1475 0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,
1476 0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
1477 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00,0x03,0x11,
1478 0x00,0x0f,0x0e,0x0d,0x0c,0x0b,0x0a,0x09,0x08,0x07,0x06,0x05,0x04,0x03,0x02,
1479 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 };
1480
1481 static void testFileStore(void)
1482 {
1483 static const WCHAR szPrefix[] = { 'c','e','r',0 };
1484 static const WCHAR szDot[] = { '.',0 };
1485 WCHAR filename[MAX_PATH];
1486 HCERTSTORE store;
1487 BOOL ret;
1488 PCCERT_CONTEXT cert;
1489 HANDLE file;
1490
1491 if (!pCertControlStore)
1492 {
1493 win_skip("CertControlStore() is not available\n");
1494 return;
1495 }
1496
1497 store = CertOpenStore(CERT_STORE_PROV_FILE, 0, 0, 0, NULL);
1498 ok(!store && GetLastError() == ERROR_INVALID_HANDLE,
1499 "Expected ERROR_INVALID_HANDLE, got %08x\n", GetLastError());
1500
1501 if (!GetTempFileNameW(szDot, szPrefix, 0, filename))
1502 return;
1503
1504 DeleteFileW(filename);
1505 file = CreateFileW(filename, GENERIC_READ | GENERIC_WRITE, 0, NULL,
1506 CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
1507 if (file == INVALID_HANDLE_VALUE)
1508 return;
1509
1510 store = CertOpenStore(CERT_STORE_PROV_FILE, 0, 0, CERT_STORE_DELETE_FLAG,
1511 file);
1512 ok(!store && GetLastError() == E_INVALIDARG,
1513 "Expected E_INVALIDARG, got %08x\n", GetLastError());
1514 store = CertOpenStore(CERT_STORE_PROV_FILE, 0, 0,
1515 CERT_FILE_STORE_COMMIT_ENABLE_FLAG | CERT_STORE_READONLY_FLAG, file);
1516 ok(!store && GetLastError() == E_INVALIDARG,
1517 "Expected E_INVALIDARG, got %08x\n", GetLastError());
1518
1519 /* A "read-only" file store.. */
1520 store = CertOpenStore(CERT_STORE_PROV_FILE, 0, 0,
1521 CERT_STORE_OPEN_EXISTING_FLAG | CERT_STORE_READONLY_FLAG, file);
1522 ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError());
1523 if (store)
1524 {
1525 DWORD size;
1526
1527 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1528 bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, NULL);
1529 /* apparently allows adding certificates.. */
1530 ok(ret, "CertAddEncodedCertificateToStore failed: %d\n", ret);
1531 /* but not commits.. */
1532 ret = pCertControlStore(store, 0, CERT_STORE_CTRL_COMMIT, NULL);
1533 ok(!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED,
1534 "Expected ERROR_CALL_NOT_IMPLEMENTED, got %08x\n", GetLastError());
1535 /* It still has certs in memory.. */
1536 cert = CertEnumCertificatesInStore(store, NULL);
1537 ok(cert != NULL, "CertEnumCertificatesInStore failed: %08x\n",
1538 GetLastError());
1539 CertFreeCertificateContext(cert);
1540 /* but the file size is still 0. */
1541 size = GetFileSize(file, NULL);
1542 ok(size == 0, "Expected size 0, got %d\n", size);
1543 CertCloseStore(store, 0);
1544 }
1545
1546 /* The create new flag is allowed.. */
1547 store = CertOpenStore(CERT_STORE_PROV_FILE, 0, 0,
1548 CERT_STORE_CREATE_NEW_FLAG, file);
1549 ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError());
1550 if (store)
1551 {
1552 /* but without the commit enable flag, commits don't happen. */
1553 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1554 bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, NULL);
1555 ok(ret, "CertAddEncodedCertificateToStore failed: %d\n", ret);
1556 ret = pCertControlStore(store, 0, CERT_STORE_CTRL_COMMIT, NULL);
1557 ok(!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED,
1558 "Expected ERROR_CALL_NOT_IMPLEMENTED, got %08x\n", GetLastError());
1559 CertCloseStore(store, 0);
1560 }
1561 /* as is the open existing flag. */
1562 store = CertOpenStore(CERT_STORE_PROV_FILE, 0, 0,
1563 CERT_STORE_OPEN_EXISTING_FLAG, file);
1564 ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError());
1565 if (store)
1566 {
1567 /* but without the commit enable flag, commits don't happen. */
1568 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1569 bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, NULL);
1570 ok(ret, "CertAddEncodedCertificateToStore failed: %d\n", ret);
1571 ret = pCertControlStore(store, 0, CERT_STORE_CTRL_COMMIT, NULL);
1572 ok(!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED,
1573 "Expected ERROR_CALL_NOT_IMPLEMENTED, got %08x\n", GetLastError());
1574 CertCloseStore(store, 0);
1575 }
1576 store = CertOpenStore(CERT_STORE_PROV_FILE, 0, 0,
1577 CERT_FILE_STORE_COMMIT_ENABLE_FLAG, file);
1578 ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError());
1579 if (store)
1580 {
1581 CloseHandle(file);
1582 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1583 bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, NULL);
1584 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
1585 GetLastError());
1586 /* with commits enabled, commit is allowed */
1587 ret = pCertControlStore(store, 0, CERT_STORE_CTRL_COMMIT, NULL);
1588 ok(ret, "CertControlStore failed: %d\n", ret);
1589 compareStore(store, "serialized store with cert",
1590 serializedStoreWithCert, sizeof(serializedStoreWithCert), FALSE);
1591 CertCloseStore(store, 0);
1592 }
1593 file = CreateFileW(filename, GENERIC_READ | GENERIC_WRITE, 0, NULL,
1594 OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
1595 if (file == INVALID_HANDLE_VALUE)
1596 return;
1597 store = CertOpenStore(CERT_STORE_PROV_FILE, 0, 0,
1598 CERT_FILE_STORE_COMMIT_ENABLE_FLAG, file);
1599 ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError());
1600 if (store)
1601 {
1602 CloseHandle(file);
1603 ret = CertAddEncodedCRLToStore(store, X509_ASN_ENCODING, signedCRL,
1604 sizeof(signedCRL), CERT_STORE_ADD_ALWAYS, NULL);
1605 ok(ret, "CertAddEncodedCRLToStore failed: %08x\n", GetLastError());
1606 compareStore(store, "serialized store with cert and CRL",
1607 serializedStoreWithCertAndCRL, sizeof(serializedStoreWithCertAndCRL),
1608 FALSE);
1609 CertCloseStore(store, 0);
1610 }
1611
1612 DeleteFileW(filename);
1613 }
1614
1615 static BOOL initFileFromData(LPCWSTR filename, const BYTE *pb, DWORD cb)
1616 {
1617 HANDLE file = CreateFileW(filename, GENERIC_READ | GENERIC_WRITE, 0, NULL,
1618 CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
1619 BOOL ret;
1620
1621 if (file != INVALID_HANDLE_VALUE)
1622 {
1623 DWORD written;
1624
1625 ret = WriteFile(file, pb, cb, &written, NULL);
1626 CloseHandle(file);
1627 }
1628 else
1629 ret = FALSE;
1630 return ret;
1631 }
1632
1633 static const BYTE base64SPC[] =
1634 "MIICJQYJKoZIhvcNAQcCoIICFjCCAhICAQExADALBgkqhkiG9w0BBwGgggH6MIIB"
1635 "9jCCAV+gAwIBAgIQnP8+EF4opr9OxH7h4uBPWTANBgkqhkiG9w0BAQQFADAUMRIw"
1636 "EAYDVQQDEwlKdWFuIExhbmcwHhcNMDgxMjEyMTcxMDE0WhcNMzkxMjMxMjM1OTU5"
1637 "WjAUMRIwEAYDVQQDEwlKdWFuIExhbmcwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJ"
1638 "AoGBALCgNjyNvOic0FOfjxvi43HbM+D5joDkhiGSXe+gbZlf8f16k07kkObFEunz"
1639 "mdB5coscmA7gyqiWNN4ZUyr2cA3lCbnpGPA/0IblyyOcuGIFmmCzeZaVa5ZG6xZP"
1640 "K7L7o+73Qo6jXVbGhBGnMZ7Q9sAn6s2933olnStnejnqwV0NAgMBAAGjSTBHMEUG"
1641 "A1UdAQQ+MDyAEFKbKEdXYyx+CWKcV6vxM6ShFjAUMRIwEAYDVQQDEwlKdWFuIExh"
1642 "bmeCEJz/PhBeKKa/TsR+4eLgT1kwDQYJKoZIhvcNAQEEBQADgYEALpkgLgW3mEaK"
1643 "idPQ3iPJYLG0Ub1wraqEl9bd42hrhzIdcDzlQgxnm8/5cHYVxIF/C20x/HJplb1R"
1644 "G6U1ipFe/q8byWD/9JpiBKMGPi9YlUTgXHfS9d4S/QWO1h9Z7KeipBYhoslQpHXu"
1645 "y9bUr8Adqi6SzgHpCnMu53dxgxUD1r4xAA==";
1646 /* Same as base64SPC, but as a wide-char string */
1647 static const WCHAR utf16Base64SPC[] = {
1648 'M','I','I','C','J','Q','Y','J','K','o','Z','I','h','v','c','N','A',
1649 'Q','c','C','o','I','I','C','F','j','C','C','A','h','I','C','A','Q',
1650 'E','x','A','D','A','L','B','g','k','q','h','k','i','G','9','w','0',
1651 'B','B','w','G','g','g','g','H','6','M','I','I','B','9','j','C','C',
1652 'A','V','+','g','A','w','I','B','A','g','I','Q','n','P','8','+','E',
1653 'F','4','o','p','r','9','O','x','H','7','h','4','u','B','P','W','T',
1654 'A','N','B','g','k','q','h','k','i','G','9','w','0','B','A','Q','Q',
1655 'F','A','D','A','U','M','R','I','w','E','A','Y','D','V','Q','Q','D',
1656 'E','w','l','K','d','W','F','u','I','E','x','h','b','m','c','w','H',
1657 'h','c','N','M','D','g','x','M','j','E','y','M','T','c','x','M','D',
1658 'E','0','W','h','c','N','M','z','k','x','M','j','M','x','M','j','M',
1659 '1','O','T','U','5','W','j','A','U','M','R','I','w','E','A','Y','D',
1660 'V','Q','Q','D','E','w','l','K','d','W','F','u','I','E','x','h','b',
1661 'm','c','w','g','Z','8','w','D','Q','Y','J','K','o','Z','I','h','v',
1662 'c','N','A','Q','E','B','B','Q','A','D','g','Y','0','A','M','I','G',
1663 'J','A','o','G','B','A','L','C','g','N','j','y','N','v','O','i','c',
1664 '0','F','O','f','j','x','v','i','4','3','H','b','M','+','D','5','j',
1665 'o','D','k','h','i','G','S','X','e','+','g','b','Z','l','f','8','f',
1666 '1','6','k','0','7','k','k','O','b','F','E','u','n','z','m','d','B',
1667 '5','c','o','s','c','m','A','7','g','y','q','i','W','N','N','4','Z',
1668 'U','y','r','2','c','A','3','l','C','b','n','p','G','P','A','/','0',
1669 'I','b','l','y','y','O','c','u','G','I','F','m','m','C','z','e','Z',
1670 'a','V','a','5','Z','G','6','x','Z','P','K','7','L','7','o','+','7',
1671 '3','Q','o','6','j','X','V','b','G','h','B','G','n','M','Z','7','Q',
1672 '9','s','A','n','6','s','2','9','3','3','o','l','n','S','t','n','e',
1673 'j','n','q','w','V','0','N','A','g','M','B','A','A','G','j','S','T',
1674 'B','H','M','E','U','G','A','1','U','d','A','Q','Q','+','M','D','y',
1675 'A','E','F','K','b','K','E','d','X','Y','y','x','+','C','W','K','c',
1676 'V','6','v','x','M','6','S','h','F','j','A','U','M','R','I','w','E',
1677 'A','Y','D','V','Q','Q','D','E','w','l','K','d','W','F','u','I','E',
1678 'x','h','b','m','e','C','E','J','z','/','P','h','B','e','K','K','a',
1679 '/','T','s','R','+','4','e','L','g','T','1','k','w','D','Q','Y','J',
1680 'K','o','Z','I','h','v','c','N','A','Q','E','E','B','Q','A','D','g',
1681 'Y','E','A','L','p','k','g','L','g','W','3','m','E','a','K','i','d',
1682 'P','Q','3','i','P','J','Y','L','G','0','U','b','1','w','r','a','q',
1683 'E','l','9','b','d','4','2','h','r','h','z','I','d','c','D','z','l',
1684 'Q','g','x','n','m','8','/','5','c','H','Y','V','x','I','F','/','C',
1685 '2','0','x','/','H','J','p','l','b','1','R','G','6','U','1','i','p',
1686 'F','e','/','q','8','b','y','W','D','/','9','J','p','i','B','K','M',
1687 'G','P','i','9','Y','l','U','T','g','X','H','f','S','9','d','4','S',
1688 '/','Q','W','O','1','h','9','Z','7','K','e','i','p','B','Y','h','o',
1689 's','l','Q','p','H','X','u','y','9','b','U','r','8','A','d','q','i',
1690 '6','S','z','g','H','p','C','n','M','u','5','3','d','x','g','x','U',
1691 'D','1','r','4','x','A','A','=','=',0 };
1692
1693 static void testFileNameStore(void)
1694 {
1695 static const WCHAR szPrefix[] = { 'c','e','r',0 };
1696 static const WCHAR spcPrefix[] = { 's','p','c',0 };
1697 static const WCHAR szDot[] = { '.',0 };
1698 WCHAR filename[MAX_PATH];
1699 HCERTSTORE store;
1700 BOOL ret;
1701 DWORD GLE;
1702
1703 if (0)
1704 {
1705 /* Crashes on NT4 */
1706 store = CertOpenStore(CERT_STORE_PROV_FILENAME_W, 0, 0, 0, NULL);
1707 GLE = GetLastError();
1708 ok(!store && (GLE == ERROR_PATH_NOT_FOUND || GLE == ERROR_INVALID_PARAMETER),
1709 "Expected ERROR_PATH_NOT_FOUND or ERROR_INVALID_PARAMETER, got %08x\n",
1710 GLE);
1711 }
1712
1713 if (!GetTempFileNameW(szDot, szPrefix, 0, filename))
1714 return;
1715 DeleteFileW(filename);
1716
1717 /* The two flags are mutually exclusive */
1718 store = CertOpenStore(CERT_STORE_PROV_FILENAME_W, 0, 0,
1719 CERT_FILE_STORE_COMMIT_ENABLE_FLAG | CERT_STORE_READONLY_FLAG, filename);
1720 ok(!store && GetLastError() == E_INVALIDARG,
1721 "Expected E_INVALIDARG, got %08x\n", GetLastError());
1722
1723 /* In all of the following tests, the encoding type seems to be ignored */
1724 if (initFileFromData(filename, bigCert, sizeof(bigCert)))
1725 {
1726 PCCERT_CONTEXT cert;
1727 PCCRL_CONTEXT crl;
1728
1729 store = CertOpenStore(CERT_STORE_PROV_FILENAME_W, 0, 0,
1730 CERT_STORE_READONLY_FLAG, filename);
1731 ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError());
1732
1733 cert = CertEnumCertificatesInStore(store, NULL);
1734 ok(cert != NULL, "CertEnumCertificatesInStore failed: %08x\n",
1735 GetLastError());
1736 cert = CertEnumCertificatesInStore(store, cert);
1737 ok(!cert, "Expected only one cert\n");
1738 if (pCertEnumCRLsInStore)
1739 {
1740 crl = pCertEnumCRLsInStore(store, NULL);
1741 ok(!crl, "Expected no CRLs\n");
1742 }
1743
1744 CertCloseStore(store, 0);
1745 DeleteFileW(filename);
1746 }
1747 if (initFileFromData(filename, serializedStoreWithCert,
1748 sizeof(serializedStoreWithCert)))
1749 {
1750 PCCERT_CONTEXT cert;
1751 PCCRL_CONTEXT crl;
1752
1753 store = CertOpenStore(CERT_STORE_PROV_FILENAME_W, 0, 0,
1754 CERT_STORE_READONLY_FLAG, filename);
1755 ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError());
1756
1757 cert = CertEnumCertificatesInStore(store, NULL);
1758 ok(cert != NULL, "CertEnumCertificatesInStore failed: %08x\n",
1759 GetLastError());
1760 cert = CertEnumCertificatesInStore(store, cert);
1761 ok(!cert, "Expected only one cert\n");
1762 if (pCertEnumCRLsInStore)
1763 {
1764 crl = pCertEnumCRLsInStore(store, NULL);
1765 ok(!crl, "Expected no CRLs\n");
1766 }
1767
1768 CertCloseStore(store, 0);
1769 DeleteFileW(filename);
1770 }
1771 if (initFileFromData(filename, serializedStoreWithCertAndCRL,
1772 sizeof(serializedStoreWithCertAndCRL)))
1773 {
1774 PCCERT_CONTEXT cert;
1775 PCCRL_CONTEXT crl;
1776
1777 store = CertOpenStore(CERT_STORE_PROV_FILENAME_W, 0, 0,
1778 CERT_STORE_READONLY_FLAG, filename);
1779 ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError());
1780
1781 cert = CertEnumCertificatesInStore(store, NULL);
1782 ok(cert != NULL, "CertEnumCertificatesInStore failed: %08x\n",
1783 GetLastError());
1784 cert = CertEnumCertificatesInStore(store, cert);
1785 ok(!cert, "Expected only one cert\n");
1786 if (pCertEnumCRLsInStore)
1787 {
1788 crl = pCertEnumCRLsInStore(store, NULL);
1789 ok(crl != NULL, "CertEnumCRLsInStore failed: %08x\n", GetLastError());
1790 crl = pCertEnumCRLsInStore(store, crl);
1791 ok(!crl, "Expected only one CRL\n");
1792 }
1793
1794 CertCloseStore(store, 0);
1795 /* Don't delete it this time, the next test uses it */
1796 }
1797 /* Now that the file exists, we can open it read-only */
1798 store = CertOpenStore(CERT_STORE_PROV_FILENAME_W, 0, 0,
1799 CERT_STORE_READONLY_FLAG, filename);
1800 ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError());
1801 CertCloseStore(store, 0);
1802 DeleteFileW(filename);
1803
1804 store = CertOpenStore(CERT_STORE_PROV_FILENAME_W, 0, 0,
1805 CERT_FILE_STORE_COMMIT_ENABLE_FLAG | CERT_STORE_CREATE_NEW_FLAG, filename);
1806 ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError());
1807 if (store)
1808 {
1809 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1810 bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, NULL);
1811 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
1812 GetLastError());
1813 compareStore(store, "serialized store with cert",
1814 serializedStoreWithCert, sizeof(serializedStoreWithCert), FALSE);
1815 CertCloseStore(store, 0);
1816 }
1817 store = CertOpenStore(CERT_STORE_PROV_FILENAME_W, 0, 0,
1818 CERT_FILE_STORE_COMMIT_ENABLE_FLAG, filename);
1819 ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError());
1820 if (store)
1821 {
1822 ret = CertAddEncodedCRLToStore(store, X509_ASN_ENCODING,
1823 signedCRL, sizeof(signedCRL), CERT_STORE_ADD_ALWAYS, NULL);
1824 ok(ret, "CertAddEncodedCRLToStore failed: %08x\n", GetLastError());
1825 compareStore(store, "serialized store with cert and CRL",
1826 serializedStoreWithCertAndCRL, sizeof(serializedStoreWithCertAndCRL),
1827 FALSE);
1828 CertCloseStore(store, 0);
1829 }
1830 DeleteFileW(filename);
1831
1832 if (!GetTempFileNameW(szDot, spcPrefix, 0, filename))
1833 return;
1834 DeleteFileW(filename);
1835
1836 if (initFileFromData(filename, base64SPC, sizeof(base64SPC)))
1837 {
1838 PCCERT_CONTEXT cert;
1839 PCCRL_CONTEXT crl;
1840
1841 store = CertOpenStore(CERT_STORE_PROV_FILENAME_W, 0, 0,
1842 CERT_STORE_READONLY_FLAG, filename);
1843 ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError());
1844
1845 cert = CertEnumCertificatesInStore(store, NULL);
1846 ok(cert != NULL, "CertEnumCertificatesInStore failed: %08x\n",
1847 GetLastError());
1848 cert = CertEnumCertificatesInStore(store, cert);
1849 ok(!cert, "Expected only one cert\n");
1850 if (pCertEnumCRLsInStore)
1851 {
1852 crl = pCertEnumCRLsInStore(store, NULL);
1853 ok(!crl, "Expected no CRLs\n");
1854 }
1855
1856 CertCloseStore(store, 0);
1857 DeleteFileW(filename);
1858 }
1859 if (initFileFromData(filename, (BYTE *)utf16Base64SPC,
1860 sizeof(utf16Base64SPC)))
1861 {
1862 PCCERT_CONTEXT cert;
1863 PCCRL_CONTEXT crl;
1864
1865 store = CertOpenStore(CERT_STORE_PROV_FILENAME_W, 0, 0,
1866 CERT_STORE_READONLY_FLAG, filename);
1867 ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError());
1868
1869 cert = CertEnumCertificatesInStore(store, NULL);
1870 ok(cert != NULL, "CertEnumCertificatesInStore failed: %08x\n",
1871 GetLastError());
1872 cert = CertEnumCertificatesInStore(store, cert);
1873 ok(!cert, "Expected only one cert\n");
1874 if (pCertEnumCRLsInStore)
1875 {
1876 crl = pCertEnumCRLsInStore(store, NULL);
1877 ok(!crl, "Expected no CRLs\n");
1878 }
1879
1880 CertCloseStore(store, 0);
1881 DeleteFileW(filename);
1882 }
1883 }
1884
1885 static const BYTE signedContent[] = {
1886 0x30,0x81,0xb2,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,0xa0,
1887 0x81,0xa4,0x30,0x81,0xa1,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,
1888 0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x13,0x06,0x09,0x2a,0x86,
1889 0x48,0x86,0xf7,0x0d,0x01,0x07,0x01,0xa0,0x06,0x04,0x04,0x01,0x02,0x03,0x04,
1890 0x31,0x77,0x30,0x75,0x02,0x01,0x01,0x30,0x1a,0x30,0x15,0x31,0x13,0x30,0x11,
1891 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
1892 0x67,0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,
1893 0x02,0x05,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04,0x40,0x81,0xa6,0x70,
1894 0xb3,0xef,0x59,0xd1,0x66,0xd1,0x9b,0xc0,0x9a,0xb6,0x9a,0x5e,0x6d,0x6f,0x6d,
1895 0x0d,0x59,0xa9,0xaa,0x6e,0xe9,0x2c,0xa0,0x1e,0xee,0xc2,0x60,0xbc,0x59,0xbe,
1896 0x3f,0x63,0x06,0x8d,0xc9,0x11,0x1d,0x23,0x64,0x92,0xef,0x2e,0xfc,0x57,0x29,
1897 0xa4,0xaf,0xe0,0xee,0x93,0x19,0x39,0x51,0xe4,0x44,0xb8,0x0b,0x28,0xf4,0xa8,
1898 0x0d };
1899 static const BYTE signedWithCertAndCrlBareContent[] = {
1900 0x30,0x82,0x01,0x4f,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,0x86,
1901 0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x13,0x06,0x09,0x2a,0x86,0x48,
1902 0x86,0xf7,0x0d,0x01,0x07,0x01,0xa0,0x06,0x04,0x04,0x01,0x02,0x03,0x04,0xa0,
1903 0x7c,0x30,0x7a,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,
1904 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
1905 0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,
1906 0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
1907 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,
1908 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
1909 0x67,0x00,0x30,0x07,0x30,0x02,0x06,0x00,0x03,0x01,0x00,0xa3,0x16,0x30,0x14,
1910 0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,
1911 0x01,0xff,0x02,0x01,0x01,0xa1,0x2e,0x30,0x2c,0x30,0x02,0x06,0x00,0x30,0x15,
1912 0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,
1913 0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
1914 0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x31,0x77,0x30,0x75,0x02,0x01,0x01,
1915 0x30,0x1a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,
1916 0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x02,0x01,0x01,0x30,0x0c,
1917 0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x04,0x06,
1918 0x00,0x05,0x00,0x04,0x40,0x81,0xa6,0x70,0xb3,0xef,0x59,0xd1,0x66,0xd1,0x9b,
1919 0xc0,0x9a,0xb6,0x9a,0x5e,0x6d,0x6f,0x6d,0x0d,0x59,0xa9,0xaa,0x6e,0xe9,0x2c,
1920 0xa0,0x1e,0xee,0xc2,0x60,0xbc,0x59,0xbe,0x3f,0x63,0x06,0x8d,0xc9,0x11,0x1d,
1921 0x23,0x64,0x92,0xef,0x2e,0xfc,0x57,0x29,0xa4,0xaf,0xe0,0xee,0x93,0x19,0x39,
1922 0x51,0xe4,0x44,0xb8,0x0b,0x28,0xf4,0xa8,0x0d };
1923 static const BYTE hashContent[] = {
1924 0x30,0x47,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x05,0xa0,0x3a,
1925 0x30,0x38,0x02,0x01,0x00,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,
1926 0x02,0x05,0x05,0x00,0x30,0x13,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
1927 0x07,0x01,0xa0,0x06,0x04,0x04,0x01,0x02,0x03,0x04,0x04,0x10,0x08,0xd6,0xc0,
1928 0x5a,0x21,0x51,0x2a,0x79,0xa1,0xdf,0xeb,0x9d,0x2a,0x8f,0x26,0x2f };
1929 static const BYTE hashBareContent[] = {
1930 0x30,0x38,0x02,0x01,0x00,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,
1931 0x02,0x05,0x05,0x00,0x30,0x13,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
1932 0x07,0x01,0xa0,0x06,0x04,0x04,0x01,0x02,0x03,0x04,0x04,0x10,0x08,0xd6,0xc0,
1933 0x5a,0x21,0x51,0x2a,0x79,0xa1,0xdf,0xeb,0x9d,0x2a,0x8f,0x26,0x2f };
1934
1935 static void testMessageStore(void)
1936 {
1937 HCERTSTORE store;
1938 HCRYPTMSG msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL,
1939 NULL);
1940 CRYPT_DATA_BLOB blob = { sizeof(signedWithCertAndCrlBareContent),
1941 (LPBYTE)signedWithCertAndCrlBareContent };
1942 DWORD count, size;
1943 BOOL ret;
1944
1945 /* Crashes
1946 store = CertOpenStore(CERT_STORE_PROV_MSG, 0, 0, 0, NULL);
1947 */
1948 SetLastError(0xdeadbeef);
1949 store = CertOpenStore(CERT_STORE_PROV_MSG, 0, 0, 0, msg);
1950 ok(!store && GetLastError() == CRYPT_E_INVALID_MSG_TYPE,
1951 "Expected CRYPT_E_INVALID_MSG_TYPE, got %08x\n", GetLastError());
1952 CryptMsgUpdate(msg, signedContent, sizeof(signedContent), TRUE);
1953 store = CertOpenStore(CERT_STORE_PROV_MSG, 0, 0, 0, msg);
1954 ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError());
1955 if (store)
1956 {
1957 PCCERT_CONTEXT cert = NULL;
1958 PCCRL_CONTEXT crl = NULL;
1959
1960 count = 0;
1961 do {
1962 cert = CertEnumCertificatesInStore(store, cert);
1963 if (cert)
1964 count++;
1965 } while (cert);
1966 ok(count == 0, "Expected 0 certificates, got %d\n", count);
1967
1968 if (pCertEnumCRLsInStore)
1969 {
1970 count = 0;
1971 do {
1972 crl = pCertEnumCRLsInStore(store, crl);
1973 if (crl)
1974 count++;
1975 } while (crl);
1976 ok(count == 0, "Expected 0 CRLs, got %d\n", count);
1977 }
1978
1979 /* Can add certs to a message store */
1980 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1981 bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, NULL);
1982 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
1983 GetLastError());
1984 count = 0;
1985 do {
1986 cert = CertEnumCertificatesInStore(store, cert);
1987 if (cert)
1988 count++;
1989 } while (cert);
1990 ok(count == 1, "Expected 1 certificate, got %d\n", count);
1991
1992 CertCloseStore(store, 0);
1993 }
1994 /* but the added certs weren't actually added to the message */
1995 size = sizeof(count);
1996 ret = CryptMsgGetParam(msg, CMSG_CERT_COUNT_PARAM, 0, &count, &size);
1997 ok(ret, "CryptMsgGetParam failed: %08x\n", GetLastError());
1998 ok(count == 0, "Expected 0 certificates, got %d\n", count);
1999 CryptMsgClose(msg);
2000
2001 /* Crashes
2002 store = CertOpenStore(CERT_STORE_PROV_PKCS7, 0, 0, 0, NULL);
2003 */
2004 store = CertOpenStore(CERT_STORE_PROV_PKCS7, 0, 0, 0, &blob);
2005 ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError());
2006 if (store)
2007 {
2008 DWORD count = 0;
2009 PCCERT_CONTEXT cert = NULL;
2010 PCCRL_CONTEXT crl = NULL;
2011
2012 do {
2013 cert = CertEnumCertificatesInStore(store, cert);
2014 if (cert)
2015 count++;
2016 } while (cert);
2017 ok(count == 1, "Expected 1 certificate, got %d\n", count);
2018
2019 if (pCertEnumCRLsInStore)
2020 {
2021 count = 0;
2022 do {
2023 crl = pCertEnumCRLsInStore(store, crl);
2024 if (crl)
2025 count++;
2026 } while (crl);
2027 ok(count == 1, "Expected 1 CRL, got %d\n", count);
2028 }
2029 CertCloseStore(store, 0);
2030 }
2031 /* Encoding appears to be ignored */
2032 store = CertOpenStore(CERT_STORE_PROV_PKCS7, X509_ASN_ENCODING, 0, 0,
2033 &blob);
2034 ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError());
2035 if (store)
2036 CertCloseStore(store, 0);
2037 /* Messages other than signed messages aren't allowed */
2038 blob.cbData = sizeof(hashContent);
2039 blob.pbData = (LPBYTE)hashContent;
2040 SetLastError(0xdeadbeef);
2041 store = CertOpenStore(CERT_STORE_PROV_PKCS7, 0, 0, 0, &blob);
2042 ok(!store && GetLastError() == CRYPT_E_INVALID_MSG_TYPE,
2043 "Expected CRYPT_E_INVALID_MSG_TYPE, got %08x\n", GetLastError());
2044 blob.cbData = sizeof(hashBareContent);
2045 blob.pbData = (LPBYTE)hashBareContent;
2046 SetLastError(0xdeadbeef);
2047 store = CertOpenStore(CERT_STORE_PROV_PKCS7, 0, 0, 0, &blob);
2048 ok(!store &&
2049 (GetLastError() == CRYPT_E_ASN1_BADTAG ||
2050 broken(GetLastError() == OSS_DATA_ERROR)), /* NT4 */
2051 "Expected CRYPT_E_ASN1_BADTAG, got %08x\n", GetLastError());
2052 }
2053
2054 static void testSerializedStore(void)
2055 {
2056 HCERTSTORE store;
2057 CRYPT_DATA_BLOB blob;
2058
2059 if (0)
2060 {
2061 /* Crash */
2062 store = CertOpenStore(CERT_STORE_PROV_SERIALIZED, 0, 0, 0, NULL);
2063 store = CertOpenStore(CERT_STORE_PROV_SERIALIZED, 0, 0,
2064 CERT_STORE_DELETE_FLAG, NULL);
2065 }
2066 blob.cbData = sizeof(serializedStoreWithCert);
2067 blob.pbData = (BYTE *)serializedStoreWithCert;
2068 store = CertOpenStore(CERT_STORE_PROV_SERIALIZED, 0, 0,
2069 CERT_STORE_DELETE_FLAG, &blob);
2070 ok(!store && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED,
2071 "Expected ERROR_CALL_NOT_IMPLEMENTED, got %08x\n", GetLastError());
2072 store = CertOpenStore(CERT_STORE_PROV_SERIALIZED, 0, 0, 0, &blob);
2073 ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError());
2074 if (store)
2075 {
2076 PCCERT_CONTEXT cert;
2077 PCCRL_CONTEXT crl;
2078
2079 cert = CertEnumCertificatesInStore(store, NULL);
2080 ok(cert != NULL, "CertEnumCertificatesInStore failed: %08x\n",
2081 GetLastError());
2082 cert = CertEnumCertificatesInStore(store, cert);
2083 ok(!cert, "Expected only one cert\n");
2084 if (pCertEnumCRLsInStore)
2085 {
2086 crl = pCertEnumCRLsInStore(store, NULL);
2087 ok(!crl, "Expected no CRLs\n");
2088 }
2089 CertCloseStore(store, 0);
2090 }
2091 blob.cbData = sizeof(serializedStoreWithCertAndCRL);
2092 blob.pbData = (BYTE *)serializedStoreWithCertAndCRL;
2093 store = CertOpenStore(CERT_STORE_PROV_SERIALIZED, 0, 0, 0, &blob);
2094 ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError());
2095 if (store)
2096 {
2097 PCCERT_CONTEXT cert;
2098 PCCRL_CONTEXT crl;
2099
2100 cert = CertEnumCertificatesInStore(store, NULL);
2101 ok(cert != NULL, "CertEnumCertificatesInStore failed: %08x\n",
2102 GetLastError());
2103 cert = CertEnumCertificatesInStore(store, cert);
2104 ok(!cert, "Expected only one cert\n");
2105 if (pCertEnumCRLsInStore)
2106 {
2107 crl = pCertEnumCRLsInStore(store, NULL);
2108 ok(crl != NULL, "CertEnumCRLsInStore failed: %08x\n",
2109 GetLastError());
2110 crl = pCertEnumCRLsInStore(store, crl);
2111 ok(!crl, "Expected only one CRL\n");
2112 }
2113 CertCloseStore(store, 0);
2114 }
2115 }
2116
2117 static void testCertOpenSystemStore(void)
2118 {
2119 HCERTSTORE store;
2120
2121 store = CertOpenSystemStoreW(0, NULL);
2122 ok(!store && GetLastError() == E_INVALIDARG,
2123 "Expected E_INVALIDARG, got %08x\n", GetLastError());
2124 /* This succeeds, and on WinXP at least, the Bogus key is created under
2125 * HKCU (but not under HKLM, even when run as an administrator.)
2126 */
2127 store = CertOpenSystemStoreW(0, BogusW);
2128 ok(store != 0, "CertOpenSystemStore failed: %08x\n", GetLastError());
2129 if (store)
2130 CertCloseStore(store, 0);
2131 /* Delete it so other tests succeed next time around */
2132 CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0,
2133 CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_DELETE_FLAG, BogusW);
2134 RegDeleteKeyW(HKEY_CURRENT_USER, BogusPathW);
2135 }
2136
2137 static const struct
2138 {
2139 DWORD cert_store;
2140 BOOL expected;
2141 BOOL todo;
2142 } reg_system_store_test_data[] = {
2143 { CERT_SYSTEM_STORE_CURRENT_USER, TRUE, 0},
2144 /* Following tests could require administrator privileges and thus could be skipped */
2145 { CERT_SYSTEM_STORE_CURRENT_SERVICE, TRUE, 1},
2146 { CERT_SYSTEM_STORE_LOCAL_MACHINE, TRUE, 0},
2147 { CERT_SYSTEM_STORE_LOCAL_MACHINE_GROUP_POLICY, TRUE, 0},
2148 { CERT_SYSTEM_STORE_CURRENT_USER_GROUP_POLICY, TRUE, 0},
2149 { CERT_SYSTEM_STORE_LOCAL_MACHINE_ENTERPRISE, TRUE, 1}
2150 };
2151
2152 static void testCertRegisterSystemStore(void)
2153 {
2154 BOOL ret, cur_flag;
2155 DWORD err = 0;
2156 HCERTSTORE hstore;
2157 static const WCHAR WineTestW[] = {'W','i','n','e','T','e','s','t',0};
2158 const CERT_CONTEXT *cert, *cert2;
2159 unsigned int i;
2160
2161 if (!pCertRegisterSystemStore || !pCertUnregisterSystemStore)
2162 {
2163 win_skip("CertRegisterSystemStore() or CertUnregisterSystemStore() is not available\n");
2164 return;
2165 }
2166
2167 for (i = 0; i < sizeof(reg_system_store_test_data) / sizeof(reg_system_store_test_data[0]); i++) {
2168 cur_flag = reg_system_store_test_data[i].cert_store;
2169 ret = pCertRegisterSystemStore(WineTestW, cur_flag, NULL, NULL);
2170 if (!ret)
2171 {
2172 err = GetLastError();
2173 if (err == ERROR_ACCESS_DENIED)
2174 {
2175 win_skip("Insufficient privileges for the flag %08x test\n", cur_flag);
2176 continue;
2177 }
2178 }
2179 todo_wine_if (reg_system_store_test_data[i].todo)
2180 ok (ret == reg_system_store_test_data[i].expected,
2181 "Store registration (dwFlags=%08x) failed, last error %x\n", cur_flag, err);
2182 if (!ret)
2183 {
2184 skip("Nothing to test without registered store at %08x\n", cur_flag);
2185 continue;
2186 }
2187
2188 hstore = CertOpenStore(CERT_STORE_PROV_SYSTEM_W, 0, 0, CERT_STORE_OPEN_EXISTING_FLAG | cur_flag, WineTestW);
2189 ok (hstore != NULL, "Opening just registered store at %08x failed, last error %x\n", cur_flag, GetLastError());
2190
2191 cert = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert, sizeof(bigCert));
2192 ok (cert != NULL, "Failed creating cert at %08x, last error: %x\n", cur_flag, GetLastError());
2193 if (cert)
2194 {
2195 ret = CertAddCertificateContextToStore(hstore, cert, CERT_STORE_ADD_NEW, NULL);
2196 ok (ret, "Failed to add cert at %08x, last error: %x\n", cur_flag, GetLastError());
2197
2198 cert2 = CertEnumCertificatesInStore(hstore, NULL);
2199 ok (cert2 != NULL && cert2->cbCertEncoded == cert->cbCertEncoded,
2200 "Unexpected cert encoded size at %08x, last error: %x\n", cur_flag, GetLastError());
2201
2202 ret = CertDeleteCertificateFromStore(cert2);
2203 ok (ret, "Failed to delete certificate from the new store at %08x, last error: %x\n", cur_flag, GetLastError());
2204
2205 CertFreeCertificateContext(cert);
2206 }
2207
2208 ret = CertCloseStore(hstore, 0);
2209 ok (ret, "CertCloseStore failed at %08x, last error %x\n", cur_flag, GetLastError());
2210
2211 ret = pCertUnregisterSystemStore(WineTestW, cur_flag );
2212 todo_wine_if (reg_system_store_test_data[i].todo)
2213 ok( ret == reg_system_store_test_data[i].expected,
2214 "Unregistering failed at %08x, last error %d\n", cur_flag, GetLastError());
2215 }
2216
2217 }
2218
2219 struct EnumSystemStoreInfo
2220 {
2221 BOOL goOn;
2222 DWORD storeCount;
2223 };
2224
2225 static BOOL CALLBACK enumSystemStoreCB(const void *systemStore, DWORD dwFlags,
2226 PCERT_SYSTEM_STORE_INFO pStoreInfo, void *pvReserved, void *pvArg)
2227 {
2228 struct EnumSystemStoreInfo *info = pvArg;
2229
2230 info->storeCount++;
2231 return info->goOn;
2232 }
2233
2234 static void testCertEnumSystemStore(void)
2235 {
2236 BOOL ret;
2237 struct EnumSystemStoreInfo info = { FALSE, 0 };
2238
2239 if (!pCertEnumSystemStore)
2240 {
2241 win_skip("CertEnumSystemStore() is not available\n");
2242 return;
2243 }
2244
2245 SetLastError(0xdeadbeef);
2246 ret = pCertEnumSystemStore(0, NULL, NULL, NULL);
2247 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2248 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2249 /* Crashes
2250 ret = pCertEnumSystemStore(CERT_SYSTEM_STORE_LOCAL_MACHINE, NULL, NULL,
2251 NULL);
2252 */
2253
2254 SetLastError(0xdeadbeef);
2255 ret = pCertEnumSystemStore(CERT_SYSTEM_STORE_LOCAL_MACHINE, NULL, &info,
2256 enumSystemStoreCB);
2257 /* Callback returning FALSE stops enumeration */
2258 ok(!ret, "Expected CertEnumSystemStore to stop\n");
2259 ok(info.storeCount == 0 || info.storeCount == 1,
2260 "Expected 0 or 1 stores\n");
2261
2262 info.goOn = TRUE;
2263 info.storeCount = 0;
2264 ret = pCertEnumSystemStore(CERT_SYSTEM_STORE_LOCAL_MACHINE, NULL, &info,
2265 enumSystemStoreCB);
2266 ok(ret, "CertEnumSystemStore failed: %08x\n", GetLastError());
2267 /* There should always be at least My, Root, and CA stores */
2268 ok(info.storeCount == 0 || info.storeCount >= 3,
2269 "Expected at least 3 stores\n");
2270 }
2271
2272 static void testStoreProperty(void)
2273 {
2274 HCERTSTORE store;
2275 BOOL ret;
2276 DWORD propID, size = 0, state;
2277 CRYPT_DATA_BLOB blob;
2278
2279 if (!pCertGetStoreProperty || !pCertSetStoreProperty)
2280 {
2281 win_skip("CertGet/SetStoreProperty() is not available\n");
2282 return;
2283 }
2284
2285 /* Crash
2286 ret = pCertGetStoreProperty(NULL, 0, NULL, NULL);
2287 ret = pCertGetStoreProperty(NULL, 0, NULL, &size);
2288 ret = pCertGetStoreProperty(store, 0, NULL, NULL);
2289 */
2290
2291 store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
2292 CERT_STORE_CREATE_NEW_FLAG, NULL);
2293 /* Check a missing prop ID */
2294 SetLastError(0xdeadbeef);
2295 ret = pCertGetStoreProperty(store, 0, NULL, &size);
2296 ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
2297 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
2298 /* Contrary to MSDN, CERT_ACCESS_STATE_PROP_ID is supported for stores.. */
2299 size = sizeof(state);
2300 ret = pCertGetStoreProperty(store, CERT_ACCESS_STATE_PROP_ID, &state, &size);
2301 ok(ret, "CertGetStoreProperty failed for CERT_ACCESS_STATE_PROP_ID: %08x\n",
2302 GetLastError());
2303 ok(!state, "Expected a non-persisted store\n");
2304 /* and CERT_STORE_LOCALIZED_NAME_PROP_ID isn't supported by default. */
2305 size = 0;
2306 ret = pCertGetStoreProperty(store, CERT_STORE_LOCALIZED_NAME_PROP_ID, NULL,
2307 &size);
2308 ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
2309 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
2310 /* Delete an arbitrary property on a store */
2311 ret = pCertSetStoreProperty(store, CERT_FIRST_USER_PROP_ID, 0, NULL);
2312 ok(ret, "CertSetStoreProperty failed: %08x\n", GetLastError());
2313 /* Set an arbitrary property on a store */
2314 blob.pbData = (LPBYTE)&state;
2315 blob.cbData = sizeof(state);
2316 ret = pCertSetStoreProperty(store, CERT_FIRST_USER_PROP_ID, 0, &blob);
2317 ok(ret, "CertSetStoreProperty failed: %08x\n", GetLastError());
2318 /* Get an arbitrary property that's been set */
2319 ret = pCertGetStoreProperty(store, CERT_FIRST_USER_PROP_ID, NULL, &size);
2320 ok(ret, "CertGetStoreProperty failed: %08x\n", GetLastError());
2321 ok(size == sizeof(state), "Unexpected data size %d\n", size);
2322 ret = pCertGetStoreProperty(store, CERT_FIRST_USER_PROP_ID, &propID, &size);
2323 ok(ret, "CertGetStoreProperty failed: %08x\n", GetLastError());
2324 ok(propID == state, "CertGetStoreProperty got the wrong value\n");
2325 /* Delete it again */
2326 ret = pCertSetStoreProperty(store, CERT_FIRST_USER_PROP_ID, 0, NULL);
2327 ok(ret, "CertSetStoreProperty failed: %08x\n", GetLastError());
2328 /* And check that it's missing */
2329 SetLastError(0xdeadbeef);
2330 ret = pCertGetStoreProperty(store, CERT_FIRST_USER_PROP_ID, NULL, &size);
2331 ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
2332 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
2333 CertCloseStore(store, 0);
2334
2335 /* Recheck on the My store.. */
2336 store = CertOpenSystemStoreW(0, MyW);
2337 size = sizeof(state);
2338 ret = pCertGetStoreProperty(store, CERT_ACCESS_STATE_PROP_ID, &state, &size);
2339 ok(ret, "CertGetStoreProperty failed for CERT_ACCESS_STATE_PROP_ID: %08x\n",
2340 GetLastError());
2341 ok(state, "Expected a persisted store\n");
2342 SetLastError(0xdeadbeef);
2343 size = 0;
2344 ret = pCertGetStoreProperty(store, CERT_STORE_LOCALIZED_NAME_PROP_ID, NULL,
2345 &size);
2346 ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
2347 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
2348 CertCloseStore(store, 0);
2349 }
2350
2351 static void testAddSerialized(void)
2352 {
2353 BOOL ret;
2354 HCERTSTORE store;
2355 BYTE buf[sizeof(struct CertPropIDHeader) * 2 + 20 + sizeof(bigCert)] =
2356 { 0 };
2357 BYTE hash[20];
2358 struct CertPropIDHeader *hdr;
2359 PCCERT_CONTEXT context;
2360
2361 ret = CertAddSerializedElementToStore(0, NULL, 0, 0, 0, 0, NULL, NULL);
2362 ok(!ret && GetLastError() == ERROR_END_OF_MEDIA,
2363 "Expected ERROR_END_OF_MEDIA, got %08x\n", GetLastError());
2364
2365 store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
2366 CERT_STORE_CREATE_NEW_FLAG, NULL);
2367 ok(store != 0, "CertOpenStore failed: %08x\n", GetLastError());
2368
2369 ret = CertAddSerializedElementToStore(store, NULL, 0, 0, 0, 0, NULL, NULL);
2370 ok(!ret && GetLastError() == ERROR_END_OF_MEDIA,
2371 "Expected ERROR_END_OF_MEDIA, got %08x\n", GetLastError());
2372
2373 /* Test with an empty property */
2374 hdr = (struct CertPropIDHeader *)buf;
2375 hdr->propID = CERT_CERT_PROP_ID;
2376 hdr->unknown1 = 1;
2377 hdr->cb = 0;
2378 ret = CertAddSerializedElementToStore(store, buf, sizeof(buf), 0, 0, 0,
2379 NULL, NULL);
2380 ok(!ret && GetLastError() == E_INVALIDARG,
2381 "Expected E_INVALIDARG, got %08x\n", GetLastError());
2382 /* Test with a bad size in property header */
2383 hdr->cb = sizeof(bigCert) - 1;
2384 memcpy(buf + sizeof(struct CertPropIDHeader), bigCert, sizeof(bigCert));
2385 ret = CertAddSerializedElementToStore(store, buf, sizeof(buf), 0, 0,