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