configure: Fixed a typo: code snippet outside AC_CHECK_HEADERS macro.
[wine] / dlls / crypt32 / tests / 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 <assert.h>
22 #include <stdio.h>
23 #include <stdarg.h>
24 #include <windef.h>
25 #include <winbase.h>
26 #include <winreg.h>
27 #include <winerror.h>
28 #include <wincrypt.h>
29
30 #include "wine/test.h"
31
32 /* The following aren't defined in wincrypt.h, as they're "reserved" */
33 #define CERT_CERT_PROP_ID 32
34 #define CERT_CRL_PROP_ID  33
35 #define CERT_CTL_PROP_ID  34
36
37 struct CertPropIDHeader
38 {
39     DWORD propID;
40     DWORD unknown1;
41     DWORD cb;
42 };
43
44 static const BYTE emptyCert[] = { 0x30, 0x00 };
45 static const BYTE bigCert[] = { 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
46  0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
47  0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x22,
48  0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30,
49  0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30,
50  0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30,
51  0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20,
52  0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01,
53  0x00, 0xa3, 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01,
54  0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
55 static const BYTE signedBigCert[] = {
56  0x30, 0x81, 0x93, 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06, 0x00, 0x30,
57  0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a,
58  0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x22, 0x18, 0x0f,
59  0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
60  0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30,
61  0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06,
62  0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61,
63  0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3,
64  0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff,
65  0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
66  0x00, 0x03, 0x11, 0x00, 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07,
67  0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00 };
68 static const BYTE serializedCert[] = { 0x20, 0x00, 0x00, 0x00,
69  0x01, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x30, 0x7a, 0x02, 0x01, 0x01,
70  0x30, 0x02, 0x06, 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55,
71  0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67,
72  0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31,
73  0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31,
74  0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15,
75  0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75,
76  0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06,
77  0x00, 0x03, 0x01, 0x00, 0xa3, 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55,
78  0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02,
79  0x01, 0x01 };
80 static const BYTE signedCRL[] = { 0x30, 0x45, 0x30, 0x2c, 0x30, 0x02, 0x06,
81  0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
82  0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18, 0x0f,
83  0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
84  0x30, 0x5a, 0x30, 0x02, 0x06, 0x00, 0x03, 0x11, 0x00, 0x0f, 0x0e, 0x0d, 0x0c,
85  0x0b, 0x0a, 0x09, 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00 };
86 static const BYTE bigCert2[] = { 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
87  0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
88  0x0a, 0x41, 0x6c, 0x65, 0x78, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x22,
89  0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30,
90  0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30,
91  0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30,
92  0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x41, 0x6c, 0x65, 0x78, 0x20,
93  0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01,
94  0x00, 0xa3, 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01,
95  0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
96
97 static void testMemStore(void)
98 {
99     HCERTSTORE store1, store2;
100     PCCERT_CONTEXT context;
101     BOOL ret;
102     DWORD GLE;
103
104     /* NULL provider */
105     store1 = CertOpenStore(0, 0, 0, 0, NULL);
106     ok(!store1 && GetLastError() == ERROR_FILE_NOT_FOUND,
107      "Expected ERROR_FILE_NOT_FOUND, got %d\n", GetLastError());
108     /* weird flags */
109     store1 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
110      CERT_STORE_DELETE_FLAG, NULL);
111     ok(!store1 && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED,
112      "Expected ERROR_CALL_NOT_IMPLEMENTED, got %d\n", GetLastError());
113
114     /* normal */
115     store1 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
116      CERT_STORE_CREATE_NEW_FLAG, NULL);
117     ok(store1 != NULL, "CertOpenStore failed: %d\n", GetLastError());
118     /* open existing doesn't */
119     store2 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
120      CERT_STORE_OPEN_EXISTING_FLAG, NULL);
121     ok(store2 != NULL, "CertOpenStore failed: %d\n", GetLastError());
122     ok(store1 != store2, "Expected different stores\n");
123
124     /* add a bogus (empty) cert */
125     context = NULL;
126     ret = CertAddEncodedCertificateToStore(store1, X509_ASN_ENCODING, emptyCert,
127      sizeof(emptyCert), CERT_STORE_ADD_ALWAYS, &context);
128     /* Windows returns CRYPT_E_ASN1_EOD or OSS_DATA_ERROR, but accept
129      * CRYPT_E_ASN1_CORRUPT as well (because matching errors is tough in this
130      * case)
131      */
132     GLE = GetLastError();
133     ok(!ret && (GLE == CRYPT_E_ASN1_EOD || GLE == CRYPT_E_ASN1_CORRUPT ||
134      GLE == OSS_DATA_ERROR),
135      "Expected CRYPT_E_ASN1_EOD or CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
136      GLE);
137     /* add a "signed" cert--the signature isn't a real signature, so this adds
138      * without any check of the signature's validity
139      */
140     ret = CertAddEncodedCertificateToStore(store1, X509_ASN_ENCODING,
141      signedBigCert, sizeof(signedBigCert), CERT_STORE_ADD_ALWAYS, &context);
142     ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n", GetLastError());
143     ok(context != NULL, "Expected a valid cert context\n");
144     if (context)
145     {
146         ok(context->cbCertEncoded == sizeof(signedBigCert),
147          "Wrong cert size %d\n", context->cbCertEncoded);
148         ok(!memcmp(context->pbCertEncoded, signedBigCert,
149          sizeof(signedBigCert)), "Unexpected encoded cert in context\n");
150         /* remove it, the rest of the tests will work on an unsigned cert */
151         ret = CertDeleteCertificateFromStore(context);
152         ok(ret, "CertDeleteCertificateFromStore failed: %08x\n",
153          GetLastError());
154     }
155     /* try adding a "signed" CRL as a cert */
156     ret = CertAddEncodedCertificateToStore(store1, X509_ASN_ENCODING,
157      signedCRL, sizeof(signedCRL), CERT_STORE_ADD_ALWAYS, &context);
158     GLE = GetLastError();
159     ok(!ret && (GLE == CRYPT_E_ASN1_BADTAG || GLE == CRYPT_E_ASN1_CORRUPT ||
160      GLE == OSS_DATA_ERROR),
161      "Expected CRYPT_E_ASN1_BADTAG or CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
162      GLE);
163     /* add a cert to store1 */
164     ret = CertAddEncodedCertificateToStore(store1, X509_ASN_ENCODING, bigCert,
165      sizeof(bigCert), CERT_STORE_ADD_ALWAYS, &context);
166     ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n", GetLastError());
167     ok(context != NULL, "Expected a valid cert context\n");
168     if (context)
169     {
170         DWORD size;
171         BYTE *buf;
172
173         ok(context->cbCertEncoded == sizeof(bigCert),
174          "Wrong cert size %d\n", context->cbCertEncoded);
175         ok(!memcmp(context->pbCertEncoded, bigCert, sizeof(bigCert)),
176          "Unexpected encoded cert in context\n");
177         ok(context->hCertStore == store1, "Unexpected store\n");
178
179         /* check serializing this element */
180         /* These crash
181         ret = CertSerializeCertificateStoreElement(NULL, 0, NULL, NULL);
182         ret = CertSerializeCertificateStoreElement(context, 0, NULL, NULL);
183         ret = CertSerializeCertificateStoreElement(NULL, 0, NULL, &size);
184          */
185         /* apparently flags are ignored */
186         ret = CertSerializeCertificateStoreElement(context, 1, NULL, &size);
187         ok(ret, "CertSerializeCertificateStoreElement failed: %08x\n",
188          GetLastError());
189         buf = HeapAlloc(GetProcessHeap(), 0, size);
190         if (buf)
191         {
192             ret = CertSerializeCertificateStoreElement(context, 0, buf, &size);
193             ok(size == sizeof(serializedCert), "Wrong size %d\n", size);
194             ok(!memcmp(serializedCert, buf, size),
195              "Unexpected serialized cert\n");
196             HeapFree(GetProcessHeap(), 0, buf);
197         }
198
199         ret = CertFreeCertificateContext(context);
200         ok(ret, "CertFreeCertificateContext failed: %08x\n", GetLastError());
201     }
202     /* verify the cert's in store1 */
203     context = CertEnumCertificatesInStore(store1, NULL);
204     ok(context != NULL, "Expected a valid context\n");
205     context = CertEnumCertificatesInStore(store1, context);
206     ok(!context && GetLastError() == CRYPT_E_NOT_FOUND,
207      "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
208     /* verify store2 (the "open existing" mem store) is still empty */
209     context = CertEnumCertificatesInStore(store2, NULL);
210     ok(!context, "Expected an empty store\n");
211     /* delete the cert from store1, and check it's empty */
212     context = CertEnumCertificatesInStore(store1, NULL);
213     if (context)
214     {
215         /* Deleting a bitwise copy crashes with an access to an uninitialized
216          * pointer, so a cert context has some special data out there in memory
217          * someplace
218         CERT_CONTEXT copy;
219         memcpy(&copy, context, sizeof(copy));
220         ret = CertDeleteCertificateFromStore(&copy);
221          */
222         PCCERT_CONTEXT copy = CertDuplicateCertificateContext(context);
223
224         ok(copy != NULL, "CertDuplicateCertificateContext failed: %08x\n",
225          GetLastError());
226         ret = CertDeleteCertificateFromStore(context);
227         ok(ret, "CertDeleteCertificateFromStore failed: %08x\n",
228          GetLastError());
229         /* try deleting a copy */
230         ret = CertDeleteCertificateFromStore(copy);
231         ok(ret, "CertDeleteCertificateFromStore failed: %08x\n",
232          GetLastError());
233         /* check that the store is empty */
234         context = CertEnumCertificatesInStore(store1, NULL);
235         ok(!context, "Expected an empty store\n");
236     }
237
238     /* close an empty store */
239     ret = CertCloseStore(NULL, 0);
240     ok(ret, "CertCloseStore failed: %d\n", GetLastError());
241     ret = CertCloseStore(store1, 0);
242     ok(ret, "CertCloseStore failed: %d\n", GetLastError());
243     ret = CertCloseStore(store2, 0);
244     ok(ret, "CertCloseStore failed: %d\n", GetLastError());
245
246     /* This seems nonsensical, but you can open a read-only mem store, only
247      * it isn't read-only
248      */
249     store1 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
250      CERT_STORE_READONLY_FLAG, NULL);
251     ok(store1 != NULL, "CertOpenStore failed: %d\n", GetLastError());
252     /* yep, this succeeds */
253     ret = CertAddEncodedCertificateToStore(store1, X509_ASN_ENCODING, bigCert,
254      sizeof(bigCert), CERT_STORE_ADD_ALWAYS, &context);
255     ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n", GetLastError());
256     ok(context != NULL, "Expected a valid cert context\n");
257     if (context)
258     {
259         ok(context->cbCertEncoded == sizeof(bigCert),
260          "Wrong cert size %d\n", context->cbCertEncoded);
261         ok(!memcmp(context->pbCertEncoded, bigCert, sizeof(bigCert)),
262          "Unexpected encoded cert in context\n");
263         ok(context->hCertStore == store1, "Unexpected store\n");
264         ret = CertDeleteCertificateFromStore(context);
265         ok(ret, "CertDeleteCertificateFromStore failed: %08x\n",
266          GetLastError());
267     }
268     CertCloseStore(store1, 0);
269 }
270
271 static void testCollectionStore(void)
272 {
273     HCERTSTORE store1, store2, collection, collection2;
274     PCCERT_CONTEXT context;
275     BOOL ret;
276
277     collection = CertOpenStore(CERT_STORE_PROV_COLLECTION, 0, 0,
278      CERT_STORE_CREATE_NEW_FLAG, NULL);
279
280     /* Try adding a cert to any empty collection */
281     ret = CertAddEncodedCertificateToStore(collection, X509_ASN_ENCODING,
282      bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, NULL);
283     ok(!ret && GetLastError() == E_ACCESSDENIED,
284      "Expected E_ACCESSDENIED, got %08x\n", GetLastError());
285
286     /* Create and add a cert to a memory store */
287     store1 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
288      CERT_STORE_CREATE_NEW_FLAG, NULL);
289     ret = CertAddEncodedCertificateToStore(store1, X509_ASN_ENCODING,
290      bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, NULL);
291     ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n", GetLastError());
292     /* Add the memory store to the collection, without allowing adding */
293     ret = CertAddStoreToCollection(collection, store1, 0, 0);
294     ok(ret, "CertAddStoreToCollection failed: %08x\n", GetLastError());
295     /* Verify the cert is in the collection */
296     context = CertEnumCertificatesInStore(collection, NULL);
297     ok(context != NULL, "Expected a valid context\n");
298     if (context)
299     {
300         ok(context->hCertStore == collection, "Unexpected store\n");
301         CertFreeCertificateContext(context);
302     }
303     /* Check that adding to the collection isn't allowed */
304     ret = CertAddEncodedCertificateToStore(collection, X509_ASN_ENCODING,
305      bigCert2, sizeof(bigCert2), CERT_STORE_ADD_ALWAYS, NULL);
306     ok(!ret && GetLastError() == E_ACCESSDENIED,
307      "Expected E_ACCESSDENIED, got %08x\n", GetLastError());
308
309     /* Create a new memory store */
310     store2 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
311      CERT_STORE_CREATE_NEW_FLAG, NULL);
312     /* Try adding a store to a non-collection store */
313     ret = CertAddStoreToCollection(store1, store2,
314      CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
315     ok(!ret && GetLastError() == E_INVALIDARG,
316      "Expected E_INVALIDARG, got %08x\n", GetLastError());
317     /* Try adding some bogus stores */
318     /* This crashes in Windows
319     ret = CertAddStoreToCollection(0, store2,
320      CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
321      */
322     /* This "succeeds"... */
323     ret = CertAddStoreToCollection(collection, 0,
324      CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
325     ok(ret, "CertAddStoreToCollection failed: %08x\n", GetLastError());
326     /* while this crashes.
327     ret = CertAddStoreToCollection(collection, 1,
328      CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
329      */
330
331     /* Add it to the collection, this time allowing adding */
332     ret = CertAddStoreToCollection(collection, store2,
333      CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
334     ok(ret, "CertAddStoreToCollection failed: %08x\n", GetLastError());
335     /* Check that adding to the collection is allowed */
336     ret = CertAddEncodedCertificateToStore(collection, X509_ASN_ENCODING,
337      bigCert2, sizeof(bigCert2), CERT_STORE_ADD_ALWAYS, NULL);
338     ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n", GetLastError());
339     /* Now check that it was actually added to store2 */
340     context = CertEnumCertificatesInStore(store2, NULL);
341     ok(context != NULL, "Expected a valid context\n");
342     if (context)
343     {
344         ok(context->hCertStore == store2, "Unexpected store\n");
345         CertFreeCertificateContext(context);
346     }
347     /* Check that the collection has both bigCert and bigCert2.  bigCert comes
348      * first because store1 was added first.
349      */
350     context = CertEnumCertificatesInStore(collection, NULL);
351     ok(context != NULL, "Expected a valid context\n");
352     if (context)
353     {
354         ok(context->hCertStore == collection, "Unexpected store\n");
355         ok(context->cbCertEncoded == sizeof(bigCert),
356          "Wrong size %d\n", context->cbCertEncoded);
357         ok(!memcmp(context->pbCertEncoded, bigCert, context->cbCertEncoded),
358          "Unexpected cert\n");
359         context = CertEnumCertificatesInStore(collection, context);
360         ok(context != NULL, "Expected a valid context\n");
361         if (context)
362         {
363             ok(context->hCertStore == collection, "Unexpected store\n");
364             ok(context->cbCertEncoded == sizeof(bigCert2),
365              "Wrong size %d\n", context->cbCertEncoded);
366             ok(!memcmp(context->pbCertEncoded, bigCert2,
367              context->cbCertEncoded), "Unexpected cert\n");
368             context = CertEnumCertificatesInStore(collection, context);
369             ok(!context, "Unexpected cert\n");
370         }
371     }
372     /* close store2, and check that the collection is unmodified */
373     CertCloseStore(store2, 0);
374     context = CertEnumCertificatesInStore(collection, NULL);
375     ok(context != NULL, "Expected a valid context\n");
376     if (context)
377     {
378         ok(context->hCertStore == collection, "Unexpected store\n");
379         ok(context->cbCertEncoded == sizeof(bigCert),
380          "Wrong size %d\n", context->cbCertEncoded);
381         ok(!memcmp(context->pbCertEncoded, bigCert, context->cbCertEncoded),
382          "Unexpected cert\n");
383         context = CertEnumCertificatesInStore(collection, context);
384         ok(context != NULL, "Expected a valid context\n");
385         if (context)
386         {
387             ok(context->hCertStore == collection, "Unexpected store\n");
388             ok(context->cbCertEncoded == sizeof(bigCert2),
389              "Wrong size %d\n", context->cbCertEncoded);
390             ok(!memcmp(context->pbCertEncoded, bigCert2,
391              context->cbCertEncoded), "Unexpected cert\n");
392             context = CertEnumCertificatesInStore(collection, context);
393             ok(!context, "Unexpected cert\n");
394         }
395     }
396
397     /* Adding a collection to a collection is legal */
398     collection2 = CertOpenStore(CERT_STORE_PROV_COLLECTION, 0, 0,
399      CERT_STORE_CREATE_NEW_FLAG, NULL);
400     ret = CertAddStoreToCollection(collection2, collection,
401      CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
402     ok(ret, "CertAddStoreToCollection failed: %08x\n", GetLastError());
403     /* check the contents of collection2 */
404     context = CertEnumCertificatesInStore(collection2, NULL);
405     ok(context != NULL, "Expected a valid context\n");
406     if (context)
407     {
408         ok(context->hCertStore == collection2, "Unexpected store\n");
409         ok(context->cbCertEncoded == sizeof(bigCert),
410          "Wrong size %d\n", context->cbCertEncoded);
411         ok(!memcmp(context->pbCertEncoded, bigCert, context->cbCertEncoded),
412          "Unexpected cert\n");
413         context = CertEnumCertificatesInStore(collection2, context);
414         ok(context != NULL, "Expected a valid context\n");
415         if (context)
416         {
417             ok(context->hCertStore == collection2, "Unexpected store\n");
418             ok(context->cbCertEncoded == sizeof(bigCert2),
419              "Wrong size %d\n", context->cbCertEncoded);
420             ok(!memcmp(context->pbCertEncoded, bigCert2,
421              context->cbCertEncoded), "Unexpected cert\n");
422             context = CertEnumCertificatesInStore(collection2, context);
423             ok(!context, "Unexpected cert\n");
424         }
425     }
426
427     /* I'd like to test closing the collection in the middle of enumeration,
428      * but my tests have been inconsistent.  The first time calling
429      * CertEnumCertificatesInStore on a closed collection succeeded, while the
430      * second crashed.  So anything appears to be fair game.
431      * I'd also like to test removing a store from a collection in the middle
432      * of an enumeration, but my tests in Windows have been inconclusive.
433      * In one scenario it worked.  In another scenario, about a third of the
434      * time this leads to "random" crashes elsewhere in the code.  This
435      * probably means this is not allowed.
436      */
437
438     CertCloseStore(store1, 0);
439     CertCloseStore(collection, 0);
440     CertCloseStore(collection2, 0);
441
442     /* Add the same cert to two memory stores, then put them in a collection */
443     store1 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
444      CERT_STORE_CREATE_NEW_FLAG, NULL);
445     ok(store1 != 0, "CertOpenStore failed: %08x\n", GetLastError());
446     store2 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
447      CERT_STORE_CREATE_NEW_FLAG, NULL);
448     ok(store2 != 0, "CertOpenStore failed: %08x\n", GetLastError());
449
450     ret = CertAddEncodedCertificateToStore(store1, X509_ASN_ENCODING,
451      bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, NULL);
452     ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n", GetLastError());
453     ret = CertAddEncodedCertificateToStore(store2, X509_ASN_ENCODING,
454      bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, NULL);
455     ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n", GetLastError());
456     collection = CertOpenStore(CERT_STORE_PROV_COLLECTION, 0, 0,
457      CERT_STORE_CREATE_NEW_FLAG, NULL);
458     ok(collection != 0, "CertOpenStore failed: %08x\n", GetLastError());
459
460     ret = CertAddStoreToCollection(collection, store1,
461      CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
462     ok(ret, "CertAddStoreToCollection failed: %08x\n", GetLastError());
463     ret = CertAddStoreToCollection(collection, store2,
464      CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
465     ok(ret, "CertAddStoreToCollection failed: %08x\n", GetLastError());
466
467     /* Check that the collection has two copies of the same cert */
468     context = CertEnumCertificatesInStore(collection, NULL);
469     ok(context != NULL, "Expected a valid context\n");
470     if (context)
471     {
472         ok(context->hCertStore == collection, "Unexpected store\n");
473         ok(context->cbCertEncoded == sizeof(bigCert),
474          "Wrong size %d\n", context->cbCertEncoded);
475         ok(!memcmp(context->pbCertEncoded, bigCert, context->cbCertEncoded),
476          "Unexpected cert\n");
477         context = CertEnumCertificatesInStore(collection, context);
478         ok(context != NULL, "Expected a valid context\n");
479         if (context)
480         {
481             ok(context->hCertStore == collection, "Unexpected store\n");
482             ok(context->cbCertEncoded == sizeof(bigCert),
483              "Wrong size %d\n", context->cbCertEncoded);
484             ok(!memcmp(context->pbCertEncoded, bigCert, context->cbCertEncoded),
485              "Unexpected cert\n");
486             context = CertEnumCertificatesInStore(collection, context);
487             ok(context == NULL, "Unexpected cert\n");
488         }
489     }
490
491     /* The following would check whether I can delete an identical cert, rather
492      * than one enumerated from the store.  It crashes, so that means I must
493      * only call CertDeleteCertificateFromStore with contexts enumerated from
494      * the store.
495     context = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert,
496      sizeof(bigCert));
497     ok(context != NULL, "CertCreateCertificateContext failed: %08x\n",
498      GetLastError());
499     if (context)
500     {
501         ret = CertDeleteCertificateFromStore(collection, context);
502         printf("ret is %d, GetLastError is %08x\n", ret, GetLastError());
503         CertFreeCertificateContext(context);
504     }
505      */
506
507     /* Now check deleting from the collection. */
508     context = CertEnumCertificatesInStore(collection, NULL);
509     ok(context != NULL, "Expected a valid context\n");
510     if (context)
511     {
512         CertDeleteCertificateFromStore(context);
513         /* store1 should now be empty */
514         context = CertEnumCertificatesInStore(store1, NULL);
515         ok(!context, "Unexpected cert\n");
516         /* and there should be one certificate in the collection */
517         context = CertEnumCertificatesInStore(collection, NULL);
518         ok(context != NULL, "Expected a valid cert\n");
519         if (context)
520         {
521             ok(context->hCertStore == collection, "Unexpected store\n");
522             ok(context->cbCertEncoded == sizeof(bigCert),
523              "Wrong size %d\n", context->cbCertEncoded);
524             ok(!memcmp(context->pbCertEncoded, bigCert, context->cbCertEncoded),
525              "Unexpected cert\n");
526         }
527         context = CertEnumCertificatesInStore(collection, context);
528         ok(context == NULL, "Unexpected cert\n");
529     }
530
531     /* Finally, test removing stores from the collection.  No return value, so
532      * it's a bit funny to test.
533      */
534     /* This crashes
535     CertRemoveStoreFromCollection(NULL, NULL);
536      */
537     /* This "succeeds," no crash, no last error set */
538     SetLastError(0xdeadbeef);
539     CertRemoveStoreFromCollection(store2, collection);
540     ok(GetLastError() == 0xdeadbeef,
541      "Didn't expect an error to be set: %08x\n", GetLastError());
542
543     /* After removing store2, the collection should be empty */
544     SetLastError(0xdeadbeef);
545     CertRemoveStoreFromCollection(collection, store2);
546     ok(GetLastError() == 0xdeadbeef,
547      "Didn't expect an error to be set: %08x\n", GetLastError());
548     context = CertEnumCertificatesInStore(collection, NULL);
549     ok(!context, "Unexpected cert\n");
550
551     CertCloseStore(collection, 0);
552     CertCloseStore(store2, 0);
553     CertCloseStore(store1, 0);
554 }
555
556 /* Looks for the property with ID propID in the buffer buf.  Returns a pointer
557  * to its header if found, NULL if not.
558  */
559 static const struct CertPropIDHeader *findPropID(const BYTE *buf, DWORD size,
560  DWORD propID)
561 {
562     const struct CertPropIDHeader *ret = NULL;
563     BOOL failed = FALSE;
564
565     while (size && !ret && !failed)
566     {
567         if (size < sizeof(struct CertPropIDHeader))
568             failed = TRUE;
569         else
570         {
571             const struct CertPropIDHeader *hdr =
572              (const struct CertPropIDHeader *)buf;
573
574             size -= sizeof(struct CertPropIDHeader);
575             buf += sizeof(struct CertPropIDHeader);
576             if (size < hdr->cb)
577                 failed = TRUE;
578             else if (hdr->propID == propID)
579                 ret = hdr;
580             else
581             {
582                 buf += hdr->cb;
583                 size -= hdr->cb;
584             }
585         }
586     }
587     return ret;
588 }
589
590 typedef DWORD (WINAPI *SHDeleteKeyAFunc)(HKEY, LPCSTR);
591
592 static void testRegStore(void)
593 {
594     static const char tempKey[] = "Software\\Wine\\CryptTemp";
595     HCERTSTORE store;
596     LONG rc;
597     HKEY key = NULL;
598     DWORD disp, GLE;
599
600     store = CertOpenStore(CERT_STORE_PROV_REG, 0, 0, 0, NULL);
601     GLE = GetLastError();
602     ok(!store && (GLE == ERROR_INVALID_HANDLE || GLE == ERROR_BADKEY),
603      "Expected ERROR_INVALID_HANDLE or ERROR_BADKEY, got %d\n", GLE);
604     store = CertOpenStore(CERT_STORE_PROV_REG, 0, 0, 0, key);
605     GLE = GetLastError();
606     ok(!store && (GLE == ERROR_INVALID_HANDLE || GLE == ERROR_BADKEY),
607      "Expected ERROR_INVALID_HANDLE or ERROR_BADKEY, got %d\n", GLE);
608
609     /* Opening up any old key works.. */
610     key = HKEY_CURRENT_USER;
611     store = CertOpenStore(CERT_STORE_PROV_REG, 0, 0, 0, key);
612     /* Not sure if this is a bug in DuplicateHandle, marking todo_wine for now
613      */
614     todo_wine ok(store != 0, "CertOpenStore failed: %08x\n", GetLastError());
615     CertCloseStore(store, 0);
616
617     rc = RegCreateKeyExA(HKEY_CURRENT_USER, tempKey, 0, NULL, 0, KEY_ALL_ACCESS,
618      NULL, &key, NULL);
619     ok(!rc, "RegCreateKeyExA failed: %d\n", rc);
620     if (key)
621     {
622         BOOL ret;
623         BYTE hash[20];
624         DWORD size, i;
625         static const char certificates[] = "Certificates\\";
626         char subKeyName[sizeof(certificates) + 20 * 2 + 1], *ptr;
627         HKEY subKey;
628         PCCERT_CONTEXT context;
629
630         store = CertOpenStore(CERT_STORE_PROV_REG, 0, 0, 0, key);
631         ok(store != 0, "CertOpenStore failed: %08x\n", GetLastError());
632         /* Add a certificate.  It isn't persisted right away, since it's only
633          * added to the cache..
634          */
635         ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
636          bigCert2, sizeof(bigCert2), CERT_STORE_ADD_ALWAYS, NULL);
637         ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
638          GetLastError());
639         /* so flush the cache to force a commit.. */
640         ret = CertControlStore(store, 0, CERT_STORE_CTRL_COMMIT, NULL);
641         ok(ret, "CertControlStore failed: %08x\n", GetLastError());
642         /* and check that the expected subkey was written. */
643         size = sizeof(hash);
644         ret = CryptHashCertificate(0, 0, 0, bigCert2, sizeof(bigCert2),
645          hash, &size);
646         ok(ret, "CryptHashCertificate failed: %d\n", GetLastError());
647         strcpy(subKeyName, certificates);
648         for (i = 0, ptr = subKeyName + sizeof(certificates) - 1; i < size;
649          i++, ptr += 2)
650             sprintf(ptr, "%02X", hash[i]);
651         rc = RegCreateKeyExA(key, subKeyName, 0, NULL, 0, KEY_ALL_ACCESS, NULL,
652          &subKey, NULL);
653         ok(!rc, "RegCreateKeyExA failed: %d\n", rc);
654         if (subKey)
655         {
656             LPBYTE buf;
657
658             size = 0;
659             RegQueryValueExA(subKey, "Blob", NULL, NULL, NULL, &size);
660             buf = HeapAlloc(GetProcessHeap(), 0, size);
661             if (buf)
662             {
663                 rc = RegQueryValueExA(subKey, "Blob", NULL, NULL, buf, &size);
664                 ok(!rc, "RegQueryValueExA failed: %d\n", rc);
665                 if (!rc)
666                 {
667                     const struct CertPropIDHeader *hdr;
668
669                     /* Both the hash and the cert should be present */
670                     hdr = findPropID(buf, size, CERT_CERT_PROP_ID);
671                     ok(hdr != NULL, "Expected to find a cert property\n");
672                     if (hdr)
673                     {
674                         ok(hdr->cb == sizeof(bigCert2),
675                            "Wrong size %d of cert property\n", hdr->cb);
676                         ok(!memcmp((const BYTE *)hdr + sizeof(*hdr), bigCert2,
677                          hdr->cb), "Unexpected cert in cert property\n");
678                     }
679                     hdr = findPropID(buf, size, CERT_HASH_PROP_ID);
680                     ok(hdr != NULL, "Expected to find a hash property\n");
681                     if (hdr)
682                     {
683                         ok(hdr->cb == sizeof(hash),
684                            "Wrong size %d of hash property\n", hdr->cb);
685                         ok(!memcmp((const BYTE *)hdr + sizeof(*hdr), hash,
686                          hdr->cb), "Unexpected hash in cert property\n");
687                     }
688                 }
689                 HeapFree(GetProcessHeap(), 0, buf);
690             }
691             RegCloseKey(subKey);
692         }
693
694         /* Remove the existing context */
695         context = CertEnumCertificatesInStore(store, NULL);
696         ok(context != NULL, "Expected a cert context\n");
697         if (context)
698             CertDeleteCertificateFromStore(context);
699         ret = CertControlStore(store, 0, CERT_STORE_CTRL_COMMIT, NULL);
700         ok(ret, "CertControlStore failed: %08x\n", GetLastError());
701
702         /* Add a serialized cert with a bogus hash directly to the registry */
703         memset(hash, 0, sizeof(hash));
704         strcpy(subKeyName, certificates);
705         for (i = 0, ptr = subKeyName + sizeof(certificates) - 1;
706          i < sizeof(hash); i++, ptr += 2)
707             sprintf(ptr, "%02X", hash[i]);
708         rc = RegCreateKeyExA(key, subKeyName, 0, NULL, 0, KEY_ALL_ACCESS, NULL,
709          &subKey, NULL);
710         ok(!rc, "RegCreateKeyExA failed: %d\n", rc);
711         if (subKey)
712         {
713             BYTE buf[sizeof(struct CertPropIDHeader) * 2 + sizeof(hash) +
714              sizeof(bigCert)], *ptr;
715             DWORD certCount = 0;
716             struct CertPropIDHeader *hdr;
717
718             hdr = (struct CertPropIDHeader *)buf;
719             hdr->propID = CERT_HASH_PROP_ID;
720             hdr->unknown1 = 1;
721             hdr->cb = sizeof(hash);
722             ptr = buf + sizeof(*hdr);
723             memcpy(ptr, hash, sizeof(hash));
724             ptr += sizeof(hash);
725             hdr = (struct CertPropIDHeader *)ptr;
726             hdr->propID = CERT_CERT_PROP_ID;
727             hdr->unknown1 = 1;
728             hdr->cb = sizeof(bigCert);
729             ptr += sizeof(*hdr);
730             memcpy(ptr, bigCert, sizeof(bigCert));
731
732             rc = RegSetValueExA(subKey, "Blob", 0, REG_BINARY, buf,
733              sizeof(buf));
734             ok(!rc, "RegSetValueExA failed: %d\n", rc);
735
736             ret = CertControlStore(store, 0, CERT_STORE_CTRL_RESYNC, NULL);
737             ok(ret, "CertControlStore failed: %08x\n", GetLastError());
738
739             /* Make sure the bogus hash cert gets loaded. */
740             certCount = 0;
741             context = NULL;
742             do {
743                 context = CertEnumCertificatesInStore(store, context);
744                 if (context)
745                     certCount++;
746             } while (context != NULL);
747             ok(certCount == 1, "Expected 1 certificates, got %d\n", certCount);
748
749             RegCloseKey(subKey);
750         }
751
752         /* Add another serialized cert directly to the registry, this time
753          * under the correct key name (named with the correct hash value).
754          */
755         size = sizeof(hash);
756         ret = CryptHashCertificate(0, 0, 0, bigCert2,
757          sizeof(bigCert2), hash, &size);
758         ok(ret, "CryptHashCertificate failed: %d\n", GetLastError());
759         strcpy(subKeyName, certificates);
760         for (i = 0, ptr = subKeyName + sizeof(certificates) - 1;
761          i < sizeof(hash); i++, ptr += 2)
762             sprintf(ptr, "%02X", hash[i]);
763         rc = RegCreateKeyExA(key, subKeyName, 0, NULL, 0, KEY_ALL_ACCESS, NULL,
764          &subKey, NULL);
765         ok(!rc, "RegCreateKeyExA failed: %d\n", rc);
766         if (subKey)
767         {
768             BYTE buf[sizeof(struct CertPropIDHeader) * 2 + sizeof(hash) +
769              sizeof(bigCert2)], *ptr;
770             DWORD certCount = 0;
771             PCCERT_CONTEXT context;
772             struct CertPropIDHeader *hdr;
773
774             /* First try with a bogus hash... */
775             hdr = (struct CertPropIDHeader *)buf;
776             hdr->propID = CERT_HASH_PROP_ID;
777             hdr->unknown1 = 1;
778             hdr->cb = sizeof(hash);
779             ptr = buf + sizeof(*hdr);
780             memset(ptr, 0, sizeof(hash));
781             ptr += sizeof(hash);
782             hdr = (struct CertPropIDHeader *)ptr;
783             hdr->propID = CERT_CERT_PROP_ID;
784             hdr->unknown1 = 1;
785             hdr->cb = sizeof(bigCert2);
786             ptr += sizeof(*hdr);
787             memcpy(ptr, bigCert2, sizeof(bigCert2));
788
789             rc = RegSetValueExA(subKey, "Blob", 0, REG_BINARY, buf,
790              sizeof(buf));
791             ok(!rc, "RegSetValueExA failed: %d\n", rc);
792
793             ret = CertControlStore(store, 0, CERT_STORE_CTRL_RESYNC, NULL);
794             ok(ret, "CertControlStore failed: %08x\n", GetLastError());
795
796             /* and make sure just one cert still gets loaded. */
797             certCount = 0;
798             context = NULL;
799             do {
800                 context = CertEnumCertificatesInStore(store, context);
801                 if (context)
802                     certCount++;
803             } while (context != NULL);
804             ok(certCount == 1, "Expected 1 certificates, got %d\n", certCount);
805
806             /* Try again with the correct hash... */
807             ptr = buf + sizeof(*hdr);
808             memcpy(ptr, hash, sizeof(hash));
809
810             rc = RegSetValueExA(subKey, "Blob", 0, REG_BINARY, buf,
811              sizeof(buf));
812             ok(!rc, "RegSetValueExA failed: %d\n", rc);
813
814             ret = CertControlStore(store, 0, CERT_STORE_CTRL_RESYNC, NULL);
815             ok(ret, "CertControlStore failed: %08x\n", GetLastError());
816
817             /* and make sure two certs get loaded. */
818             certCount = 0;
819             context = NULL;
820             do {
821                 context = CertEnumCertificatesInStore(store, context);
822                 if (context)
823                     certCount++;
824             } while (context != NULL);
825             ok(certCount == 2, "Expected 2 certificates, got %d\n", certCount);
826
827             RegCloseKey(subKey);
828         }
829         CertCloseStore(store, 0);
830         /* Is delete allowed on a reg store? */
831         store = CertOpenStore(CERT_STORE_PROV_REG, 0, 0,
832          CERT_STORE_DELETE_FLAG, key);
833         ok(store == NULL, "Expected NULL return from CERT_STORE_DELETE_FLAG\n");
834         ok(GetLastError() == 0, "CertOpenStore failed: %08x\n",
835          GetLastError());
836
837         RegCloseKey(key);
838     }
839     /* The CertOpenStore with CERT_STORE_DELETE_FLAG above will delete the
840      * contents of the key, but not the key itself.
841      */
842     rc = RegCreateKeyExA(HKEY_CURRENT_USER, tempKey, 0, NULL, 0, KEY_ALL_ACCESS,
843      NULL, &key, &disp);
844     ok(!rc, "RegCreateKeyExA failed: %d\n", rc);
845     ok(disp == REG_OPENED_EXISTING_KEY,
846      "Expected REG_OPENED_EXISTING_KEY, got %d\n", disp);
847     if (!rc)
848     {
849         RegCloseKey(key);
850         rc = RegDeleteKeyA(HKEY_CURRENT_USER, tempKey);
851         if (rc)
852         {
853             HMODULE shlwapi = LoadLibraryA("shlwapi");
854
855             /* Use shlwapi's SHDeleteKeyA to _really_ blow away the key,
856              * otherwise subsequent tests will fail.
857              */
858             if (shlwapi)
859             {
860                 SHDeleteKeyAFunc pSHDeleteKeyA =
861                  (SHDeleteKeyAFunc)GetProcAddress(shlwapi, "SHDeleteKeyA");
862
863                 if (pSHDeleteKeyA)
864                     pSHDeleteKeyA(HKEY_CURRENT_USER, tempKey);
865                 FreeLibrary(shlwapi);
866             }
867         }
868     }
869 }
870
871 static const char MyA[] = { 'M','y',0,0 };
872 static const WCHAR MyW[] = { 'M','y',0 };
873 static const WCHAR BogusW[] = { 'B','o','g','u','s',0 };
874 static const WCHAR BogusPathW[] = { 'S','o','f','t','w','a','r','e','\\',
875  'M','i','c','r','o','s','o','f','t','\\','S','y','s','t','e','m','C','e','r',
876  't','i','f','i','c','a','t','e','s','\\','B','o','g','u','s',0 };
877
878 static void testSystemRegStore(void)
879 {
880     HCERTSTORE store, memStore;
881
882     /* Check with a UNICODE name */
883     store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY, 0, 0,
884      CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_OPEN_EXISTING_FLAG, MyW);
885     /* Not all OSes support CERT_STORE_PROV_SYSTEM_REGISTRY, so don't continue
886      * testing if they don't.
887      */
888     if (!store)
889         return;
890
891     /* Check that it isn't a collection store */
892     memStore = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
893      CERT_STORE_CREATE_NEW_FLAG, NULL);
894     if (memStore)
895     {
896         BOOL ret = CertAddStoreToCollection(store, memStore, 0, 0);
897
898         ok(!ret && GetLastError() == E_INVALIDARG,
899          "Expected E_INVALIDARG, got %08x\n", GetLastError());
900         CertCloseStore(memStore, 0);
901     }
902     CertCloseStore(store, 0);
903
904     /* Check opening a bogus store */
905     store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY, 0, 0,
906      CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_OPEN_EXISTING_FLAG, BogusW);
907     ok(!store && GetLastError() == ERROR_FILE_NOT_FOUND,
908      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
909     store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY, 0, 0,
910      CERT_SYSTEM_STORE_CURRENT_USER, BogusW);
911     ok(store != 0, "CertOpenStore failed: %08x\n", GetLastError());
912     if (store)
913         CertCloseStore(store, 0);
914     /* Now check whether deleting is allowed */
915     store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY, 0, 0,
916      CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_DELETE_FLAG, BogusW);
917     RegDeleteKeyW(HKEY_CURRENT_USER, BogusPathW);
918
919     store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY, 0, 0, 0, NULL);
920     ok(!store && GetLastError() == E_INVALIDARG,
921      "Expected E_INVALIDARG, got %08x\n", GetLastError());
922     store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY, 0, 0,
923      CERT_SYSTEM_STORE_LOCAL_MACHINE | CERT_SYSTEM_STORE_CURRENT_USER, MyA);
924     ok(!store && GetLastError() == E_INVALIDARG,
925      "Expected E_INVALIDARG, got %08x\n", GetLastError());
926     store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY, 0, 0,
927      CERT_SYSTEM_STORE_LOCAL_MACHINE | CERT_SYSTEM_STORE_CURRENT_USER, MyW);
928     ok(!store && GetLastError() == E_INVALIDARG,
929      "Expected E_INVALIDARG, got %08x\n", GetLastError());
930     /* The name is expected to be UNICODE, check with an ASCII name */
931     store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY, 0, 0,
932      CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_OPEN_EXISTING_FLAG, MyA);
933     ok(!store && GetLastError() == ERROR_FILE_NOT_FOUND,
934      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
935 }
936
937 static void testSystemStore(void)
938 {
939     static const WCHAR baskslashW[] = { '\\',0 };
940     HCERTSTORE store;
941     WCHAR keyName[MAX_PATH];
942     HKEY key;
943     LONG rc;
944
945     store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0, 0, NULL);
946     ok(!store && GetLastError() == ERROR_FILE_NOT_FOUND,
947      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
948     store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0,
949      CERT_SYSTEM_STORE_LOCAL_MACHINE | CERT_SYSTEM_STORE_CURRENT_USER, MyA);
950     ok(!store && GetLastError() == ERROR_FILE_NOT_FOUND,
951      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
952     store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0,
953      CERT_SYSTEM_STORE_LOCAL_MACHINE | CERT_SYSTEM_STORE_CURRENT_USER, MyW);
954     ok(!store && GetLastError() == ERROR_FILE_NOT_FOUND,
955      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
956     /* The name is expected to be UNICODE, first check with an ASCII name */
957     store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0,
958      CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_OPEN_EXISTING_FLAG, MyA);
959     ok(!store && GetLastError() == ERROR_FILE_NOT_FOUND,
960      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
961     /* Create the expected key */
962     lstrcpyW(keyName, CERT_LOCAL_MACHINE_SYSTEM_STORE_REGPATH);
963     lstrcatW(keyName, baskslashW);
964     lstrcatW(keyName, MyW);
965     rc = RegCreateKeyExW(HKEY_CURRENT_USER, keyName, 0, NULL, 0, KEY_READ,
966      NULL, &key, NULL);
967     ok(!rc, "RegCreateKeyEx failed: %d\n", rc);
968     if (!rc)
969         RegCloseKey(key);
970     /* Check opening with a UNICODE name, specifying the create new flag */
971     store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0,
972      CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_CREATE_NEW_FLAG, MyW);
973     ok(!store && GetLastError() == ERROR_FILE_EXISTS,
974      "Expected ERROR_FILE_EXISTS, got %08x\n", GetLastError());
975     /* Now check opening with a UNICODE name, this time opening existing */
976     store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0,
977      CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_OPEN_EXISTING_FLAG, MyW);
978     ok(store != 0, "CertOpenStore failed: %08x\n", GetLastError());
979     if (store)
980     {
981         HCERTSTORE memStore = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
982          CERT_STORE_CREATE_NEW_FLAG, NULL);
983
984         /* Check that it's a collection store */
985         if (memStore)
986         {
987             BOOL ret = CertAddStoreToCollection(store, memStore, 0, 0);
988
989             /* FIXME: this'll fail on NT4, but what error will it give? */
990             ok(ret, "CertAddStoreToCollection failed: %08x\n", GetLastError());
991             CertCloseStore(memStore, 0);
992         }
993         CertCloseStore(store, 0);
994     }
995
996     /* Check opening a bogus store */
997     store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0,
998      CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_OPEN_EXISTING_FLAG, BogusW);
999     ok(!store && GetLastError() == ERROR_FILE_NOT_FOUND,
1000      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
1001     store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0,
1002      CERT_SYSTEM_STORE_CURRENT_USER, BogusW);
1003     ok(store != 0, "CertOpenStore failed: %08x\n", GetLastError());
1004     if (store)
1005         CertCloseStore(store, 0);
1006     /* Now check whether deleting is allowed */
1007     store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0,
1008      CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_DELETE_FLAG, BogusW);
1009     RegDeleteKeyW(HKEY_CURRENT_USER, BogusPathW);
1010 }
1011
1012 static const BYTE serializedStoreWithCert[] = {
1013  0x00,0x00,0x00,0x00,0x43,0x45,0x52,0x54,0x20,0x00,0x00,0x00,0x01,0x00,0x00,
1014  0x00,0x7c,0x00,0x00,0x00,0x30,0x7a,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,
1015  0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,
1016  0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,
1017  0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,
1018  0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,
1019  0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,
1020  0x20,0x4c,0x61,0x6e,0x67,0x00,0x30,0x07,0x30,0x02,0x06,0x00,0x03,0x01,0x00,
1021  0xa3,0x16,0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,
1022  0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,
1023  0x00,0x00,0x00,0x00,0x00,0x00 };
1024 static const BYTE serializedStoreWithCertAndCRL[] = {
1025  0x00,0x00,0x00,0x00,0x43,0x45,0x52,0x54,0x20,0x00,0x00,0x00,0x01,0x00,0x00,
1026  0x00,0x7c,0x00,0x00,0x00,0x30,0x7a,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,
1027  0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,
1028  0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,
1029  0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,
1030  0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,
1031  0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,
1032  0x20,0x4c,0x61,0x6e,0x67,0x00,0x30,0x07,0x30,0x02,0x06,0x00,0x03,0x01,0x00,
1033  0xa3,0x16,0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,
1034  0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01,0x21,0x00,0x00,0x00,0x01,0x00,
1035  0x00,0x00,0x47,0x00,0x00,0x00,0x30,0x45,0x30,0x2c,0x30,0x02,0x06,0x00,0x30,
1036  0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,
1037  0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
1038  0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00,0x03,0x11,
1039  0x00,0x0f,0x0e,0x0d,0x0c,0x0b,0x0a,0x09,0x08,0x07,0x06,0x05,0x04,0x03,0x02,
1040  0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 };
1041
1042 static void compareFile(LPCWSTR filename, const BYTE *pb, DWORD cb)
1043 {
1044     HANDLE h;
1045     BYTE buf[200];
1046     BOOL ret;
1047     DWORD cbRead = 0, totalRead = 0;
1048
1049     h = CreateFileW(filename, GENERIC_READ, 0, NULL, OPEN_EXISTING,
1050      FILE_ATTRIBUTE_NORMAL, NULL);
1051     if (h == INVALID_HANDLE_VALUE)
1052         return;
1053     do {
1054         ret = ReadFile(h, buf, sizeof(buf), &cbRead, NULL);
1055         if (ret && cbRead)
1056         {
1057             ok(totalRead + cbRead <= cb, "Expected total count %d, see %d\n",
1058              cb, totalRead + cbRead);
1059             ok(!memcmp(pb + totalRead, buf, cbRead),
1060              "Unexpected data in file\n");
1061             totalRead += cbRead;
1062         }
1063     } while (ret && cbRead);
1064     CloseHandle(h);
1065 }
1066
1067 static void testFileStore(void)
1068 {
1069     static const WCHAR szPrefix[] = { 'c','e','r',0 };
1070     static const WCHAR szDot[] = { '.',0 };
1071     WCHAR filename[MAX_PATH];
1072     HCERTSTORE store;
1073     BOOL ret;
1074     PCCERT_CONTEXT cert;
1075     HANDLE file;
1076  
1077     store = CertOpenStore(CERT_STORE_PROV_FILE, 0, 0, 0, NULL);
1078     ok(!store && GetLastError() == ERROR_INVALID_HANDLE,
1079      "Expected ERROR_INVALID_HANDLE, got %08x\n", GetLastError());
1080
1081     if (!GetTempFileNameW(szDot, szPrefix, 0, filename))
1082        return;
1083  
1084     DeleteFileW(filename);
1085     file = CreateFileW(filename, GENERIC_READ | GENERIC_WRITE, 0, NULL,
1086      CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
1087     if (file == INVALID_HANDLE_VALUE)
1088         return;
1089
1090     store = CertOpenStore(CERT_STORE_PROV_FILE, 0, 0, CERT_STORE_DELETE_FLAG,
1091      file);
1092     ok(!store && GetLastError() == E_INVALIDARG,
1093      "Expected E_INVALIDARG, got %08x\n", GetLastError());
1094     store = CertOpenStore(CERT_STORE_PROV_FILE, 0, 0,
1095      CERT_FILE_STORE_COMMIT_ENABLE_FLAG | CERT_STORE_READONLY_FLAG, file);
1096     ok(!store && GetLastError() == E_INVALIDARG,
1097      "Expected E_INVALIDARG, got %08x\n", GetLastError());
1098
1099     /* A "read-only" file store.. */
1100     store = CertOpenStore(CERT_STORE_PROV_FILE, 0, 0,
1101      CERT_STORE_OPEN_EXISTING_FLAG | CERT_STORE_READONLY_FLAG, file);
1102     ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError());
1103     if (store)
1104     {
1105         DWORD size;
1106
1107         ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1108          bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, NULL);
1109         /* apparently allows adding certificates.. */
1110         ok(ret, "CertAddEncodedCertificateToStore failed: %d\n", ret);
1111         /* but not commits.. */
1112         ret = CertControlStore(store, 0, CERT_STORE_CTRL_COMMIT, NULL);
1113         ok(!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED,
1114          "Expected ERROR_CALL_NOT_IMPLEMENTED, got %08x\n", GetLastError());
1115         /* It still has certs in memory.. */
1116         cert = CertEnumCertificatesInStore(store, NULL);
1117         ok(cert != NULL, "CertEnumCertificatesInStore failed: %08x\n",
1118          GetLastError());
1119         CertFreeCertificateContext(cert);
1120         /* but the file size is still 0. */
1121         size = GetFileSize(file, NULL);
1122         ok(size == 0, "Expected size 0, got %d\n", size);
1123         CertCloseStore(store, 0);
1124     }
1125
1126     /* The create new flag is allowed.. */
1127     store = CertOpenStore(CERT_STORE_PROV_FILE, 0, 0,
1128      CERT_STORE_CREATE_NEW_FLAG, file);
1129     ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError());
1130     if (store)
1131     {
1132         /* but without the commit enable flag, commits don't happen. */
1133         ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1134          bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, NULL);
1135         ok(ret, "CertAddEncodedCertificateToStore failed: %d\n", ret);
1136         ret = CertControlStore(store, 0, CERT_STORE_CTRL_COMMIT, NULL);
1137         ok(!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED,
1138          "Expected ERROR_CALL_NOT_IMPLEMENTED, got %08x\n", GetLastError());
1139         CertCloseStore(store, 0);
1140     }
1141     /* as is the open existing flag. */
1142     store = CertOpenStore(CERT_STORE_PROV_FILE, 0, 0,
1143      CERT_STORE_OPEN_EXISTING_FLAG, file);
1144     ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError());
1145     if (store)
1146     {
1147         /* but without the commit enable flag, commits don't happen. */
1148         ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1149          bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, NULL);
1150         ok(ret, "CertAddEncodedCertificateToStore failed: %d\n", ret);
1151         ret = CertControlStore(store, 0, CERT_STORE_CTRL_COMMIT, NULL);
1152         ok(!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED,
1153          "Expected ERROR_CALL_NOT_IMPLEMENTED, got %08x\n", GetLastError());
1154         CertCloseStore(store, 0);
1155     }
1156     store = CertOpenStore(CERT_STORE_PROV_FILE, 0, 0,
1157      CERT_FILE_STORE_COMMIT_ENABLE_FLAG, file);
1158     ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError());
1159     if (store)
1160     {
1161         CloseHandle(file);
1162         ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1163          bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, NULL);
1164         ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
1165          GetLastError());
1166         /* with commits enabled, commit is allowed */
1167         ret = CertControlStore(store, 0, CERT_STORE_CTRL_COMMIT, NULL);
1168         ok(ret, "CertControlStore failed: %d\n", ret);
1169         compareFile(filename, serializedStoreWithCert,
1170          sizeof(serializedStoreWithCert));
1171         CertCloseStore(store, 0);
1172     }
1173     file = CreateFileW(filename, GENERIC_READ | GENERIC_WRITE, 0, NULL,
1174      OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
1175     if (file == INVALID_HANDLE_VALUE)
1176         return;
1177     store = CertOpenStore(CERT_STORE_PROV_FILE, 0, 0,
1178      CERT_FILE_STORE_COMMIT_ENABLE_FLAG, file);
1179     ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError());
1180     if (store)
1181     {
1182         CloseHandle(file);
1183         ret = CertAddEncodedCRLToStore(store, X509_ASN_ENCODING, signedCRL,
1184          sizeof(signedCRL), CERT_STORE_ADD_ALWAYS, NULL);
1185         ok(ret, "CertAddEncodedCRLToStore failed: %08x\n", GetLastError());
1186         CertCloseStore(store, 0);
1187         compareFile(filename, serializedStoreWithCertAndCRL,
1188          sizeof(serializedStoreWithCertAndCRL));
1189     }
1190
1191     DeleteFileW(filename);
1192 }
1193
1194 static BOOL initFileFromData(LPCWSTR filename, const BYTE *pb, DWORD cb)
1195 {
1196     HANDLE file = CreateFileW(filename, GENERIC_READ | GENERIC_WRITE, 0, NULL,
1197      CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
1198     BOOL ret;
1199
1200     if (file != INVALID_HANDLE_VALUE)
1201     {
1202         DWORD written;
1203
1204         ret = WriteFile(file, pb, cb, &written, NULL);
1205         CloseHandle(file);
1206     }
1207     else
1208         ret = FALSE;
1209     return ret;
1210 }
1211 static void testFileNameStore(void)
1212 {
1213     static const WCHAR szPrefix[] = { 'c','e','r',0 };
1214     static const WCHAR szDot[] = { '.',0 };
1215     WCHAR filename[MAX_PATH];
1216     HCERTSTORE store;
1217     BOOL ret;
1218     DWORD GLE;
1219
1220     store = CertOpenStore(CERT_STORE_PROV_FILENAME_W, 0, 0, 0, NULL);
1221     GLE = GetLastError();
1222     ok(!store && (GLE == ERROR_PATH_NOT_FOUND || GLE == ERROR_INVALID_PARAMETER),
1223      "Expected ERROR_PATH_NOT_FOUND or ERROR_INVALID_PARAMETER, got %08x\n",
1224      GLE);
1225
1226     if (!GetTempFileNameW(szDot, szPrefix, 0, filename))
1227        return;
1228     DeleteFileW(filename);
1229
1230     /* The two flags are mutually exclusive */
1231     store = CertOpenStore(CERT_STORE_PROV_FILENAME_W, 0, 0,
1232      CERT_FILE_STORE_COMMIT_ENABLE_FLAG | CERT_STORE_READONLY_FLAG, filename);
1233     ok(!store && GetLastError() == E_INVALIDARG,
1234      "Expected E_INVALIDARG, got %08x\n", GetLastError());
1235
1236     /* In all of the following tests, the encoding type seems to be ignored */
1237     if (initFileFromData(filename, bigCert, sizeof(bigCert)))
1238     {
1239         PCCERT_CONTEXT cert;
1240         PCCRL_CONTEXT crl;
1241
1242         store = CertOpenStore(CERT_STORE_PROV_FILENAME_W, 0, 0,
1243          CERT_STORE_READONLY_FLAG, filename);
1244         ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError());
1245
1246         cert = CertEnumCertificatesInStore(store, NULL);
1247         ok(cert != NULL, "CertEnumCertificatesInStore failed: %08x\n",
1248          GetLastError());
1249         cert = CertEnumCertificatesInStore(store, cert);
1250         ok(!cert, "Expected only one cert\n");
1251         crl = CertEnumCRLsInStore(store, NULL);
1252         ok(!crl, "Expected no CRLs\n");
1253
1254         CertCloseStore(store, 0);
1255         DeleteFileW(filename);
1256     }
1257     if (initFileFromData(filename, serializedStoreWithCert,
1258      sizeof(serializedStoreWithCert)))
1259     {
1260         PCCERT_CONTEXT cert;
1261         PCCRL_CONTEXT crl;
1262
1263         store = CertOpenStore(CERT_STORE_PROV_FILENAME_W, 0, 0,
1264          CERT_STORE_READONLY_FLAG, filename);
1265         ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError());
1266
1267         cert = CertEnumCertificatesInStore(store, NULL);
1268         ok(cert != NULL, "CertEnumCertificatesInStore failed: %08x\n",
1269          GetLastError());
1270         cert = CertEnumCertificatesInStore(store, cert);
1271         ok(!cert, "Expected only one cert\n");
1272         crl = CertEnumCRLsInStore(store, NULL);
1273         ok(!crl, "Expected no CRLs\n");
1274
1275         CertCloseStore(store, 0);
1276         DeleteFileW(filename);
1277     }
1278     if (initFileFromData(filename, serializedStoreWithCertAndCRL,
1279      sizeof(serializedStoreWithCertAndCRL)))
1280     {
1281         PCCERT_CONTEXT cert;
1282         PCCRL_CONTEXT crl;
1283
1284         store = CertOpenStore(CERT_STORE_PROV_FILENAME_W, 0, 0,
1285          CERT_STORE_READONLY_FLAG, filename);
1286         ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError());
1287
1288         cert = CertEnumCertificatesInStore(store, NULL);
1289         ok(cert != NULL, "CertEnumCertificatesInStore failed: %08x\n",
1290          GetLastError());
1291         cert = CertEnumCertificatesInStore(store, cert);
1292         ok(!cert, "Expected only one cert\n");
1293         crl = CertEnumCRLsInStore(store, NULL);
1294         ok(crl != NULL, "CertEnumCRLsInStore failed: %08x\n", GetLastError());
1295         crl = CertEnumCRLsInStore(store, crl);
1296         ok(!crl, "Expected only one CRL\n");
1297
1298         CertCloseStore(store, 0);
1299         /* Don't delete it this time, the next test uses it */
1300     }
1301     /* Now that the file exists, we can open it read-only */
1302     store = CertOpenStore(CERT_STORE_PROV_FILENAME_W, 0, 0,
1303      CERT_STORE_READONLY_FLAG, filename);
1304     ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError());
1305     CertCloseStore(store, 0);
1306     DeleteFileW(filename);
1307
1308     store = CertOpenStore(CERT_STORE_PROV_FILENAME_W, 0, 0,
1309      CERT_FILE_STORE_COMMIT_ENABLE_FLAG | CERT_STORE_CREATE_NEW_FLAG, filename);
1310     ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError());
1311     if (store)
1312     {
1313         ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1314          bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, NULL);
1315         ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
1316          GetLastError());
1317         CertCloseStore(store, 0);
1318         compareFile(filename, serializedStoreWithCert,
1319          sizeof(serializedStoreWithCert));
1320     }
1321     store = CertOpenStore(CERT_STORE_PROV_FILENAME_W, 0, 0,
1322      CERT_FILE_STORE_COMMIT_ENABLE_FLAG, filename);
1323     ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError());
1324     if (store)
1325     {
1326         ret = CertAddEncodedCRLToStore(store, X509_ASN_ENCODING,
1327          signedCRL, sizeof(signedCRL), CERT_STORE_ADD_ALWAYS, NULL);
1328         ok(ret, "CertAddEncodedCRLToStore failed: %08x\n", GetLastError());
1329         CertCloseStore(store, 0);
1330         compareFile(filename, serializedStoreWithCertAndCRL,
1331          sizeof(serializedStoreWithCertAndCRL));
1332     }
1333     DeleteFileW(filename);
1334 }
1335
1336 static const BYTE signedContent[] = {
1337 0x30,0x81,0xb2,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,0xa0,
1338 0x81,0xa4,0x30,0x81,0xa1,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,
1339 0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x13,0x06,0x09,0x2a,0x86,
1340 0x48,0x86,0xf7,0x0d,0x01,0x07,0x01,0xa0,0x06,0x04,0x04,0x01,0x02,0x03,0x04,
1341 0x31,0x77,0x30,0x75,0x02,0x01,0x01,0x30,0x1a,0x30,0x15,0x31,0x13,0x30,0x11,
1342 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
1343 0x67,0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,
1344 0x02,0x05,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04,0x40,0x81,0xa6,0x70,
1345 0xb3,0xef,0x59,0xd1,0x66,0xd1,0x9b,0xc0,0x9a,0xb6,0x9a,0x5e,0x6d,0x6f,0x6d,
1346 0x0d,0x59,0xa9,0xaa,0x6e,0xe9,0x2c,0xa0,0x1e,0xee,0xc2,0x60,0xbc,0x59,0xbe,
1347 0x3f,0x63,0x06,0x8d,0xc9,0x11,0x1d,0x23,0x64,0x92,0xef,0x2e,0xfc,0x57,0x29,
1348 0xa4,0xaf,0xe0,0xee,0x93,0x19,0x39,0x51,0xe4,0x44,0xb8,0x0b,0x28,0xf4,0xa8,
1349 0x0d };
1350 static const BYTE signedWithCertAndCrlBareContent[] = {
1351 0x30,0x82,0x01,0x4f,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,0x86,
1352 0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x13,0x06,0x09,0x2a,0x86,0x48,
1353 0x86,0xf7,0x0d,0x01,0x07,0x01,0xa0,0x06,0x04,0x04,0x01,0x02,0x03,0x04,0xa0,
1354 0x7c,0x30,0x7a,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,
1355 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
1356 0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,
1357 0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
1358 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,
1359 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
1360 0x67,0x00,0x30,0x07,0x30,0x02,0x06,0x00,0x03,0x01,0x00,0xa3,0x16,0x30,0x14,
1361 0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,
1362 0x01,0xff,0x02,0x01,0x01,0xa1,0x2e,0x30,0x2c,0x30,0x02,0x06,0x00,0x30,0x15,
1363 0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,
1364 0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
1365 0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x31,0x77,0x30,0x75,0x02,0x01,0x01,
1366 0x30,0x1a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,
1367 0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x02,0x01,0x01,0x30,0x0c,
1368 0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x04,0x06,
1369 0x00,0x05,0x00,0x04,0x40,0x81,0xa6,0x70,0xb3,0xef,0x59,0xd1,0x66,0xd1,0x9b,
1370 0xc0,0x9a,0xb6,0x9a,0x5e,0x6d,0x6f,0x6d,0x0d,0x59,0xa9,0xaa,0x6e,0xe9,0x2c,
1371 0xa0,0x1e,0xee,0xc2,0x60,0xbc,0x59,0xbe,0x3f,0x63,0x06,0x8d,0xc9,0x11,0x1d,
1372 0x23,0x64,0x92,0xef,0x2e,0xfc,0x57,0x29,0xa4,0xaf,0xe0,0xee,0x93,0x19,0x39,
1373 0x51,0xe4,0x44,0xb8,0x0b,0x28,0xf4,0xa8,0x0d };
1374 static const BYTE hashContent[] = {
1375 0x30,0x47,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x05,0xa0,0x3a,
1376 0x30,0x38,0x02,0x01,0x00,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,
1377 0x02,0x05,0x05,0x00,0x30,0x13,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
1378 0x07,0x01,0xa0,0x06,0x04,0x04,0x01,0x02,0x03,0x04,0x04,0x10,0x08,0xd6,0xc0,
1379 0x5a,0x21,0x51,0x2a,0x79,0xa1,0xdf,0xeb,0x9d,0x2a,0x8f,0x26,0x2f };
1380 static const BYTE hashBareContent[] = {
1381 0x30,0x38,0x02,0x01,0x00,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,
1382 0x02,0x05,0x05,0x00,0x30,0x13,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
1383 0x07,0x01,0xa0,0x06,0x04,0x04,0x01,0x02,0x03,0x04,0x04,0x10,0x08,0xd6,0xc0,
1384 0x5a,0x21,0x51,0x2a,0x79,0xa1,0xdf,0xeb,0x9d,0x2a,0x8f,0x26,0x2f };
1385
1386 static void testMessageStore(void)
1387 {
1388     HCERTSTORE store;
1389     HCRYPTMSG msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL,
1390      NULL);
1391     CRYPT_DATA_BLOB blob = { sizeof(signedWithCertAndCrlBareContent),
1392      (LPBYTE)signedWithCertAndCrlBareContent };
1393     DWORD count, size;
1394     BOOL ret;
1395
1396     /* Crashes
1397     store = CertOpenStore(CERT_STORE_PROV_MSG, 0, 0, 0, NULL);
1398      */
1399     SetLastError(0xdeadbeef);
1400     store = CertOpenStore(CERT_STORE_PROV_MSG, 0, 0, 0, msg);
1401     ok(!store && GetLastError() == CRYPT_E_INVALID_MSG_TYPE,
1402      "Expected CRYPT_E_INVALID_MSG_TYPE, got %08x\n", GetLastError());
1403     CryptMsgUpdate(msg, signedContent, sizeof(signedContent), TRUE);
1404     store = CertOpenStore(CERT_STORE_PROV_MSG, 0, 0, 0, msg);
1405     ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError());
1406     if (store)
1407     {
1408         PCCERT_CONTEXT cert = NULL;
1409         PCCRL_CONTEXT crl = NULL;
1410
1411         count = 0;
1412         do {
1413             cert = CertEnumCertificatesInStore(store, cert);
1414             if (cert)
1415                 count++;
1416         } while (cert);
1417         ok(count == 0, "Expected 0 certificates, got %d\n", count);
1418
1419         count = 0;
1420         do {
1421             crl = CertEnumCRLsInStore(store, crl);
1422             if (crl)
1423                 count++;
1424         } while (crl);
1425         ok(count == 0, "Expected 0 CRLs, got %d\n", count);
1426
1427         /* Can add certs to a message store */
1428         ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1429          bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, NULL);
1430         ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
1431          GetLastError());
1432         count = 0;
1433         do {
1434             cert = CertEnumCertificatesInStore(store, cert);
1435             if (cert)
1436                 count++;
1437         } while (cert);
1438         ok(count == 1, "Expected 1 certificate, got %d\n", count);
1439
1440         CertCloseStore(store, 0);
1441     }
1442     /* but the added certs weren't actually added to the message */
1443     size = sizeof(count);
1444     ret = CryptMsgGetParam(msg, CMSG_CERT_COUNT_PARAM, 0, &count, &size);
1445     ok(ret, "CryptMsgGetParam failed: %08x\n", GetLastError());
1446     ok(count == 0, "Expected 0 certificates, got %d\n", count);
1447     CryptMsgClose(msg);
1448
1449     /* Crashes
1450     store = CertOpenStore(CERT_STORE_PROV_PKCS7, 0, 0, 0, NULL);
1451      */
1452     store = CertOpenStore(CERT_STORE_PROV_PKCS7, 0, 0, 0, &blob);
1453     ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError());
1454     if (store)
1455     {
1456         DWORD count = 0;
1457         PCCERT_CONTEXT cert = NULL;
1458         PCCRL_CONTEXT crl = NULL;
1459
1460         do {
1461             cert = CertEnumCertificatesInStore(store, cert);
1462             if (cert)
1463                 count++;
1464         } while (cert);
1465         ok(count == 1, "Expected 1 certificate, got %d\n", count);
1466
1467         count = 0;
1468         do {
1469             crl = CertEnumCRLsInStore(store, crl);
1470             if (crl)
1471                 count++;
1472         } while (crl);
1473         ok(count == 1, "Expected 1 CRL, got %d\n", count);
1474         CertCloseStore(store, 0);
1475     }
1476     /* Encoding appears to be ignored */
1477     store = CertOpenStore(CERT_STORE_PROV_PKCS7, X509_ASN_ENCODING, 0, 0,
1478      &blob);
1479     ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError());
1480     if (store)
1481         CertCloseStore(store, 0);
1482     /* Messages other than signed messages aren't allowed */
1483     blob.cbData = sizeof(hashContent);
1484     blob.pbData = (LPBYTE)hashContent;
1485     SetLastError(0xdeadbeef);
1486     store = CertOpenStore(CERT_STORE_PROV_PKCS7, 0, 0, 0, &blob);
1487     ok(!store && GetLastError() == CRYPT_E_INVALID_MSG_TYPE,
1488      "Expected CRYPT_E_INVALID_MSG_TYPE, got %08x\n", GetLastError());
1489     blob.cbData = sizeof(hashBareContent);
1490     blob.pbData = (LPBYTE)hashBareContent;
1491     SetLastError(0xdeadbeef);
1492     store = CertOpenStore(CERT_STORE_PROV_PKCS7, 0, 0, 0, &blob);
1493     ok(!store && GetLastError() == CRYPT_E_ASN1_BADTAG,
1494      "Expected CRYPT_E_ASN1_BADTAG, got %08x\n", GetLastError());
1495 }
1496
1497 static void testCertOpenSystemStore(void)
1498 {
1499     HCERTSTORE store;
1500
1501     store = CertOpenSystemStoreW(0, NULL);
1502     ok(!store && GetLastError() == E_INVALIDARG,
1503      "Expected E_INVALIDARG, got %08x\n", GetLastError());
1504     /* This succeeds, and on WinXP at least, the Bogus key is created under
1505      * HKCU (but not under HKLM, even when run as an administrator.)
1506      */
1507     store = CertOpenSystemStoreW(0, BogusW);
1508     ok(store != 0, "CertOpenSystemStore failed: %08x\n", GetLastError());
1509     if (store)
1510         CertCloseStore(store, 0);
1511     /* Delete it so other tests succeed next time around */
1512     store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0,
1513      CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_DELETE_FLAG, BogusW);
1514     RegDeleteKeyW(HKEY_CURRENT_USER, BogusPathW);
1515 }
1516
1517 struct EnumSystemStoreInfo
1518 {
1519     BOOL  goOn;
1520     DWORD storeCount;
1521 };
1522
1523 static BOOL CALLBACK enumSystemStoreCB(const void *systemStore, DWORD dwFlags,
1524  PCERT_SYSTEM_STORE_INFO pStoreInfo, void *pvReserved, void *pvArg)
1525 {
1526     struct EnumSystemStoreInfo *info = (struct EnumSystemStoreInfo *)pvArg;
1527
1528     info->storeCount++;
1529     return info->goOn;
1530 }
1531
1532 static void testCertEnumSystemStore(void)
1533 {
1534     BOOL ret;
1535     struct EnumSystemStoreInfo info = { FALSE, 0 };
1536
1537     SetLastError(0xdeadbeef);
1538     ret = CertEnumSystemStore(0, NULL, NULL, NULL);
1539     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
1540      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
1541     /* Crashes
1542     ret = CertEnumSystemStore(CERT_SYSTEM_STORE_LOCAL_MACHINE, NULL, NULL,
1543      NULL);
1544      */
1545
1546     SetLastError(0xdeadbeef);
1547     ret = CertEnumSystemStore(CERT_SYSTEM_STORE_LOCAL_MACHINE, NULL, &info,
1548      enumSystemStoreCB);
1549     /* Callback returning FALSE stops enumeration */
1550     ok(!ret, "Expected CertEnumSystemStore to stop\n");
1551     ok(info.storeCount == 0 || info.storeCount == 1,
1552      "Expected 0 or 1 stores\n");
1553
1554     info.goOn = TRUE;
1555     info.storeCount = 0;
1556     ret = CertEnumSystemStore(CERT_SYSTEM_STORE_LOCAL_MACHINE, NULL, &info,
1557      enumSystemStoreCB);
1558     ok(ret, "CertEnumSystemStore failed: %08x\n", GetLastError());
1559     /* There should always be at least My, Root, and CA stores */
1560     ok(info.storeCount == 0 || info.storeCount >= 3,
1561      "Expected at least 3 stores\n");
1562 }
1563
1564 static void testStoreProperty(void)
1565 {
1566     HCERTSTORE store;
1567     BOOL ret;
1568     DWORD propID, size = 0, state;
1569     CRYPT_DATA_BLOB blob;
1570
1571     /* Crash
1572     ret = CertGetStoreProperty(NULL, 0, NULL, NULL);
1573     ret = CertGetStoreProperty(NULL, 0, NULL, &size);
1574     ret = CertGetStoreProperty(store, 0, NULL, NULL);
1575      */
1576
1577     store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
1578      CERT_STORE_CREATE_NEW_FLAG, NULL);
1579     /* Check a missing prop ID */
1580     SetLastError(0xdeadbeef);
1581     ret = CertGetStoreProperty(store, 0, NULL, &size);
1582     ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
1583      "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
1584     /* Contrary to MSDN, CERT_ACCESS_STATE_PROP_ID is supported for stores.. */
1585     size = sizeof(state);
1586     ret = CertGetStoreProperty(store, CERT_ACCESS_STATE_PROP_ID, &state, &size);
1587     ok(ret, "CertGetStoreProperty failed for CERT_ACCESS_STATE_PROP_ID: %08x\n",
1588      GetLastError());
1589     ok(!state, "Expected a non-persisted store\n");
1590     /* and CERT_STORE_LOCALIZED_NAME_PROP_ID isn't supported by default. */
1591     size = 0;
1592     ret = CertGetStoreProperty(store, CERT_STORE_LOCALIZED_NAME_PROP_ID, NULL,
1593      &size);
1594     ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
1595      "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
1596     /* Delete an arbitrary property on a store */
1597     ret = CertSetStoreProperty(store, CERT_FIRST_USER_PROP_ID, 0, NULL);
1598     ok(ret, "CertSetStoreProperty failed: %08x\n", GetLastError());
1599     /* Set an arbitrary property on a store */
1600     blob.pbData = (LPBYTE)&state;
1601     blob.cbData = sizeof(state);
1602     ret = CertSetStoreProperty(store, CERT_FIRST_USER_PROP_ID, 0, &blob);
1603     ok(ret, "CertSetStoreProperty failed: %08x\n", GetLastError());
1604     /* Get an arbitrary property that's been set */
1605     ret = CertGetStoreProperty(store, CERT_FIRST_USER_PROP_ID, NULL, &size);
1606     ok(ret, "CertGetStoreProperty failed: %08x\n", GetLastError());
1607     ok(size == sizeof(state), "Unexpected data size %d\n", size);
1608     ret = CertGetStoreProperty(store, CERT_FIRST_USER_PROP_ID, &propID, &size);
1609     ok(ret, "CertGetStoreProperty failed: %08x\n", GetLastError());
1610     ok(propID == state, "CertGetStoreProperty got the wrong value\n");
1611     /* Delete it again */
1612     ret = CertSetStoreProperty(store, CERT_FIRST_USER_PROP_ID, 0, NULL);
1613     ok(ret, "CertSetStoreProperty failed: %08x\n", GetLastError());
1614     /* And check that it's missing */
1615     SetLastError(0xdeadbeef);
1616     ret = CertGetStoreProperty(store, CERT_FIRST_USER_PROP_ID, NULL, &size);
1617     ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
1618      "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
1619     CertCloseStore(store, 0);
1620
1621     /* Recheck on the My store.. */
1622     store = CertOpenSystemStoreW(0, MyW);
1623     size = sizeof(state);
1624     ret = CertGetStoreProperty(store, CERT_ACCESS_STATE_PROP_ID, &state, &size);
1625     ok(ret, "CertGetStoreProperty failed for CERT_ACCESS_STATE_PROP_ID: %08x\n",
1626      GetLastError());
1627     ok(state, "Expected a persisted store\n");
1628     SetLastError(0xdeadbeef);
1629     size = 0;
1630     ret = CertGetStoreProperty(store, CERT_STORE_LOCALIZED_NAME_PROP_ID, NULL,
1631      &size);
1632     ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
1633      "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
1634     CertCloseStore(store, 0);
1635 }
1636
1637 static void testAddSerialized(void)
1638 {
1639     BOOL ret;
1640     HCERTSTORE store;
1641     BYTE buf[sizeof(struct CertPropIDHeader) * 2 + 20 + sizeof(bigCert)] =
1642      { 0 };
1643     BYTE hash[20];
1644     struct CertPropIDHeader *hdr;
1645     PCCERT_CONTEXT context;
1646
1647     ret = CertAddSerializedElementToStore(0, NULL, 0, 0, 0, 0, NULL, NULL);
1648     ok(!ret && GetLastError() == ERROR_END_OF_MEDIA,
1649      "Expected ERROR_END_OF_MEDIA, got %08x\n", GetLastError());
1650
1651     store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
1652      CERT_STORE_CREATE_NEW_FLAG, NULL);
1653     ok(store != 0, "CertOpenStore failed: %08x\n", GetLastError());
1654
1655     ret = CertAddSerializedElementToStore(store, NULL, 0, 0, 0, 0, NULL, NULL);
1656     ok(!ret && GetLastError() == ERROR_END_OF_MEDIA,
1657      "Expected ERROR_END_OF_MEDIA, got %08x\n", GetLastError());
1658
1659     /* Test with an empty property */
1660     hdr = (struct CertPropIDHeader *)buf;
1661     hdr->propID = CERT_CERT_PROP_ID;
1662     hdr->unknown1 = 1;
1663     hdr->cb = 0;
1664     ret = CertAddSerializedElementToStore(store, buf, sizeof(buf), 0, 0, 0,
1665      NULL, NULL);
1666     ok(!ret && GetLastError() == E_INVALIDARG,
1667      "Expected E_INVALIDARG, got %08x\n", GetLastError());
1668     /* Test with a bad size in property header */
1669     hdr->cb = sizeof(bigCert) - 1;
1670     memcpy(buf + sizeof(struct CertPropIDHeader), bigCert, sizeof(bigCert));
1671     ret = CertAddSerializedElementToStore(store, buf, sizeof(buf), 0, 0, 0,
1672      NULL, NULL);
1673     ok(!ret && GetLastError() == E_INVALIDARG,
1674      "Expected E_INVALIDARG, got %08x\n", GetLastError());
1675     ret = CertAddSerializedElementToStore(store, buf,
1676      sizeof(struct CertPropIDHeader) + sizeof(bigCert), 0, 0, 0, NULL,
1677      NULL);
1678     ok(!ret && GetLastError() == E_INVALIDARG,
1679      "Expected E_INVALIDARG, got %08x\n", GetLastError());
1680     ret = CertAddSerializedElementToStore(store, buf,
1681      sizeof(struct CertPropIDHeader) + sizeof(bigCert), CERT_STORE_ADD_NEW,
1682      0, 0, NULL, NULL);
1683     ok(!ret && GetLastError() == E_INVALIDARG,
1684      "Expected E_INVALIDARG, got %08x\n", GetLastError());
1685     /* Kosher size in property header, but no context type */
1686     hdr->cb = sizeof(bigCert);
1687     ret = CertAddSerializedElementToStore(store, buf, sizeof(buf), 0, 0, 0,
1688      NULL, NULL);
1689     ok(!ret && GetLastError() == E_INVALIDARG,
1690      "Expected E_INVALIDARG, got %08x\n", GetLastError());
1691     ret = CertAddSerializedElementToStore(store, buf,
1692      sizeof(struct CertPropIDHeader) + sizeof(bigCert), 0, 0, 0, NULL,
1693      NULL);
1694     ok(!ret && GetLastError() == E_INVALIDARG,
1695      "Expected E_INVALIDARG, got %08x\n", GetLastError());
1696     ret = CertAddSerializedElementToStore(store, buf,
1697      sizeof(struct CertPropIDHeader) + sizeof(bigCert), CERT_STORE_ADD_NEW,
1698      0, 0, NULL, NULL);
1699     ok(!ret && GetLastError() == E_INVALIDARG,
1700      "Expected E_INVALIDARG, got %08x\n", GetLastError());
1701     /* With a bad context type */
1702     ret = CertAddSerializedElementToStore(store, buf, sizeof(buf), 0, 0, 
1703      CERT_STORE_CRL_CONTEXT_FLAG, NULL, NULL);
1704     ok(!ret && GetLastError() == E_INVALIDARG,
1705      "Expected E_INVALIDARG, got %08x\n", GetLastError());
1706     ret = CertAddSerializedElementToStore(store, buf,
1707      sizeof(struct CertPropIDHeader) + sizeof(bigCert), 0, 0, 
1708      CERT_STORE_CRL_CONTEXT_FLAG, NULL, NULL);
1709     ok(!ret && GetLastError() == E_INVALIDARG,
1710      "Expected E_INVALIDARG, got %08x\n", GetLastError());
1711     ret = CertAddSerializedElementToStore(store, buf,
1712      sizeof(struct CertPropIDHeader) + sizeof(bigCert), CERT_STORE_ADD_NEW,
1713      0, CERT_STORE_CRL_CONTEXT_FLAG, NULL, NULL);
1714     ok(!ret && GetLastError() == E_INVALIDARG,
1715      "Expected E_INVALIDARG, got %08x\n", GetLastError());
1716     /* Bad unknown field, good type */
1717     hdr->unknown1 = 2;
1718     ret = CertAddSerializedElementToStore(store, buf, sizeof(buf), 0, 0, 
1719      CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL, NULL);
1720     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
1721      "Expected ERROR_FILE_NOT_FOUND got %08x\n", GetLastError());
1722     ret = CertAddSerializedElementToStore(store, buf,
1723      sizeof(struct CertPropIDHeader) + sizeof(bigCert), 0, 0, 
1724      CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL, NULL);
1725     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
1726      "Expected ERROR_FILE_NOT_FOUND got %08x\n", GetLastError());
1727     ret = CertAddSerializedElementToStore(store, buf,
1728      sizeof(struct CertPropIDHeader) + sizeof(bigCert), CERT_STORE_ADD_NEW,
1729      0, CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL, NULL);
1730     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
1731      "Expected ERROR_FILE_NOT_FOUND got %08x\n", GetLastError());
1732     /* Most everything okay, but bad add disposition */
1733     hdr->unknown1 = 1;
1734     /* This crashes
1735     ret = CertAddSerializedElementToStore(store, buf, sizeof(buf), 0, 0, 
1736      CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL, NULL);
1737      * as does this
1738     ret = CertAddSerializedElementToStore(store, buf,
1739      sizeof(struct CertPropIDHeader) + sizeof(bigCert), 0, 0, 
1740      CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL, NULL);
1741      */
1742     /* Everything okay, but buffer's too big */
1743     ret = CertAddSerializedElementToStore(store, buf, sizeof(buf),
1744      CERT_STORE_ADD_NEW, 0, CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL, NULL);
1745     ok(ret, "CertAddSerializedElementToStore failed: %08x\n", GetLastError());
1746     /* Everything okay, check it's not re-added */
1747     ret = CertAddSerializedElementToStore(store, buf,
1748      sizeof(struct CertPropIDHeader) + sizeof(bigCert), CERT_STORE_ADD_NEW,
1749      0, CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL, NULL);
1750     ok(!ret && GetLastError() == CRYPT_E_EXISTS,
1751      "Expected CRYPT_E_EXISTS, got %08x\n", GetLastError());
1752
1753     context = CertEnumCertificatesInStore(store, NULL);
1754     ok(context != NULL, "Expected a cert\n");
1755     if (context)
1756         CertDeleteCertificateFromStore(context);
1757
1758     /* Try adding with a bogus hash.  Oddly enough, it succeeds, and the hash,
1759      * when queried, is the real hash rather than the bogus hash.
1760      */
1761     hdr = (struct CertPropIDHeader *)(buf + sizeof(struct CertPropIDHeader) +
1762      sizeof(bigCert));
1763     hdr->propID = CERT_HASH_PROP_ID;
1764     hdr->unknown1 = 1;
1765     hdr->cb = sizeof(hash);
1766     memset(hash, 0xc, sizeof(hash));
1767     memcpy((LPBYTE)hdr + sizeof(struct CertPropIDHeader), hash, sizeof(hash));
1768     ret = CertAddSerializedElementToStore(store, buf, sizeof(buf),
1769      CERT_STORE_ADD_NEW, 0, CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL,
1770      (const void **)&context);
1771     ok(ret, "CertAddSerializedElementToStore failed: %08x\n", GetLastError());
1772     if (context)
1773     {
1774         BYTE hashVal[20], realHash[20];
1775         DWORD size = sizeof(hashVal);
1776
1777         ret = CryptHashCertificate(0, 0, 0, bigCert, sizeof(bigCert),
1778          realHash, &size);
1779         ok(ret, "CryptHashCertificate failed: %08x\n", GetLastError());
1780         ret = CertGetCertificateContextProperty(context, CERT_HASH_PROP_ID,
1781          hashVal, &size);
1782         ok(ret, "CertGetCertificateContextProperty failed: %08x\n",
1783          GetLastError());
1784         ok(!memcmp(hashVal, realHash, size), "Unexpected hash\n");
1785         CertFreeCertificateContext(context);
1786     }
1787
1788     CertCloseStore(store, 0);
1789 }
1790
1791 static DWORD countCertsInStore(HCERTSTORE store)
1792 {
1793     PCCERT_CONTEXT cert = NULL;
1794     DWORD certs = 0;
1795
1796     do {
1797         cert = CertEnumCertificatesInStore(store, cert);
1798         if (cert)
1799             certs++;
1800     } while (cert);
1801     return certs;
1802 }
1803
1804 static DWORD countCRLsInStore(HCERTSTORE store)
1805 {
1806     PCCRL_CONTEXT crl = NULL;
1807     DWORD crls = 0;
1808
1809     do {
1810         crl = CertEnumCRLsInStore(store, crl);
1811         if (crl)
1812             crls++;
1813     } while (crl);
1814     return crls;
1815 }
1816
1817 static void test_I_UpdateStore(void)
1818 {
1819     HMODULE lib = GetModuleHandleA("crypt32");
1820     BOOL (WINAPI *pI_CertUpdatestore)(HCERTSTORE, HCERTSTORE, DWORD, DWORD) =
1821      (void *)GetProcAddress(lib, "I_CertUpdateStore");
1822     BOOL ret;
1823     HCERTSTORE store1, store2;
1824     PCCERT_CONTEXT cert;
1825     DWORD certs;
1826
1827     if (!pI_CertUpdatestore)
1828     {
1829         skip("No I_CertUpdateStore\n");
1830         return;
1831     }
1832     store1 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
1833      CERT_STORE_CREATE_NEW_FLAG, NULL);
1834     store2 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
1835      CERT_STORE_CREATE_NEW_FLAG, NULL);
1836
1837     /* Crash
1838     ret = pI_CertUpdatestore(NULL, NULL, 0, 0);
1839     ret = pI_CertUpdatestore(store1, NULL, 0, 0);
1840     ret = pI_CertUpdatestore(NULL, store2, 0, 0);
1841      */
1842     ret = pI_CertUpdatestore(store1, store2, 0, 0);
1843     ok(ret, "I_CertUpdateStore failed: %08x\n", GetLastError());
1844
1845     CertAddEncodedCertificateToStore(store2, X509_ASN_ENCODING, bigCert,
1846      sizeof(bigCert), CERT_STORE_ADD_ALWAYS, &cert);
1847     /* I_CertUpdateStore adds the contexts from store2 to store1 */
1848     ret = pI_CertUpdatestore(store1, store2, 0, 0);
1849     ok(ret, "I_CertUpdateStore failed: %08x\n", GetLastError());
1850     certs = countCertsInStore(store1);
1851     ok(certs == 1, "Expected 1 cert, got %d\n", certs);
1852     /* Calling it a second time has no effect */
1853     ret = pI_CertUpdatestore(store1, store2, 0, 0);
1854     ok(ret, "I_CertUpdateStore failed: %08x\n", GetLastError());
1855     certs = countCertsInStore(store1);
1856     ok(certs == 1, "Expected 1 cert, got %d\n", certs);
1857
1858     /* The last parameters to I_CertUpdateStore appear to be ignored */
1859     ret = pI_CertUpdatestore(store1, store2, 1, 0);
1860     ok(ret, "I_CertUpdateStore failed: %08x\n", GetLastError());
1861     ret = pI_CertUpdatestore(store1, store2, 0, 1);
1862     ok(ret, "I_CertUpdateStore failed: %08x\n", GetLastError());
1863
1864     CertAddEncodedCRLToStore(store2, X509_ASN_ENCODING, signedCRL,
1865      sizeof(signedCRL), CERT_STORE_ADD_ALWAYS, NULL);
1866
1867     /* I_CertUpdateStore also adds the CRLs from store2 to store1 */
1868     ret = pI_CertUpdatestore(store1, store2, 0, 0);
1869     ok(ret, "I_CertUpdateStore failed: %08x\n", GetLastError());
1870     certs = countCertsInStore(store1);
1871     ok(certs == 1, "Expected 1 cert, got %d\n", certs);
1872     certs = countCRLsInStore(store1);
1873     ok(certs == 1, "Expected 1 CRL, got %d\n", certs);
1874
1875     CertDeleteCertificateFromStore(cert);
1876     /* If a context is deleted from store2, I_CertUpdateStore delets it
1877      * from store1
1878      */
1879     ret = pI_CertUpdatestore(store1, store2, 0, 0);
1880     ok(ret, "I_CertUpdateStore failed: %08x\n", GetLastError());
1881     certs = countCertsInStore(store1);
1882     ok(certs == 0, "Expected 0 certs, got %d\n", certs);
1883
1884     CertFreeCertificateContext(cert);
1885     CertCloseStore(store1, 0);
1886     CertCloseStore(store2, 0);
1887 }
1888
1889 START_TEST(store)
1890 {
1891     /* various combinations of CertOpenStore */
1892     testMemStore();
1893     testCollectionStore();
1894     testRegStore();
1895     testSystemRegStore();
1896     testSystemStore();
1897     testFileStore();
1898     testFileNameStore();
1899     testMessageStore();
1900
1901     testCertOpenSystemStore();
1902     testCertEnumSystemStore();
1903     testStoreProperty();
1904
1905     testAddSerialized();
1906
1907     test_I_UpdateStore();
1908 }