mshtml: Add tests for get_scrollLeft.
[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 static void testFileNameStore(void)
1255 {
1256     static const WCHAR szPrefix[] = { 'c','e','r',0 };
1257     static const WCHAR szDot[] = { '.',0 };
1258     WCHAR filename[MAX_PATH];
1259     HCERTSTORE store;
1260     BOOL ret;
1261     DWORD GLE;
1262
1263     store = CertOpenStore(CERT_STORE_PROV_FILENAME_W, 0, 0, 0, NULL);
1264     GLE = GetLastError();
1265     ok(!store && (GLE == ERROR_PATH_NOT_FOUND || GLE == ERROR_INVALID_PARAMETER),
1266      "Expected ERROR_PATH_NOT_FOUND or ERROR_INVALID_PARAMETER, got %08x\n",
1267      GLE);
1268
1269     if (!GetTempFileNameW(szDot, szPrefix, 0, filename))
1270        return;
1271     DeleteFileW(filename);
1272
1273     /* The two flags are mutually exclusive */
1274     store = CertOpenStore(CERT_STORE_PROV_FILENAME_W, 0, 0,
1275      CERT_FILE_STORE_COMMIT_ENABLE_FLAG | CERT_STORE_READONLY_FLAG, filename);
1276     ok(!store && GetLastError() == E_INVALIDARG,
1277      "Expected E_INVALIDARG, got %08x\n", GetLastError());
1278
1279     /* In all of the following tests, the encoding type seems to be ignored */
1280     if (initFileFromData(filename, bigCert, sizeof(bigCert)))
1281     {
1282         PCCERT_CONTEXT cert;
1283         PCCRL_CONTEXT crl;
1284
1285         store = CertOpenStore(CERT_STORE_PROV_FILENAME_W, 0, 0,
1286          CERT_STORE_READONLY_FLAG, filename);
1287         ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError());
1288
1289         cert = CertEnumCertificatesInStore(store, NULL);
1290         ok(cert != NULL, "CertEnumCertificatesInStore failed: %08x\n",
1291          GetLastError());
1292         cert = CertEnumCertificatesInStore(store, cert);
1293         ok(!cert, "Expected only one cert\n");
1294         if (pCertEnumCRLsInStore)
1295         {
1296             crl = pCertEnumCRLsInStore(store, NULL);
1297             ok(!crl, "Expected no CRLs\n");
1298         }
1299
1300         CertCloseStore(store, 0);
1301         DeleteFileW(filename);
1302     }
1303     if (initFileFromData(filename, serializedStoreWithCert,
1304      sizeof(serializedStoreWithCert)))
1305     {
1306         PCCERT_CONTEXT cert;
1307         PCCRL_CONTEXT crl;
1308
1309         store = CertOpenStore(CERT_STORE_PROV_FILENAME_W, 0, 0,
1310          CERT_STORE_READONLY_FLAG, filename);
1311         ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError());
1312
1313         cert = CertEnumCertificatesInStore(store, NULL);
1314         ok(cert != NULL, "CertEnumCertificatesInStore failed: %08x\n",
1315          GetLastError());
1316         cert = CertEnumCertificatesInStore(store, cert);
1317         ok(!cert, "Expected only one cert\n");
1318         if (pCertEnumCRLsInStore)
1319         {
1320             crl = pCertEnumCRLsInStore(store, NULL);
1321             ok(!crl, "Expected no CRLs\n");
1322         }
1323
1324         CertCloseStore(store, 0);
1325         DeleteFileW(filename);
1326     }
1327     if (initFileFromData(filename, serializedStoreWithCertAndCRL,
1328      sizeof(serializedStoreWithCertAndCRL)))
1329     {
1330         PCCERT_CONTEXT cert;
1331         PCCRL_CONTEXT crl;
1332
1333         store = CertOpenStore(CERT_STORE_PROV_FILENAME_W, 0, 0,
1334          CERT_STORE_READONLY_FLAG, filename);
1335         ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError());
1336
1337         cert = CertEnumCertificatesInStore(store, NULL);
1338         ok(cert != NULL, "CertEnumCertificatesInStore failed: %08x\n",
1339          GetLastError());
1340         cert = CertEnumCertificatesInStore(store, cert);
1341         ok(!cert, "Expected only one cert\n");
1342         if (pCertEnumCRLsInStore)
1343         {
1344             crl = pCertEnumCRLsInStore(store, NULL);
1345             ok(crl != NULL, "CertEnumCRLsInStore failed: %08x\n", GetLastError());
1346             crl = pCertEnumCRLsInStore(store, crl);
1347             ok(!crl, "Expected only one CRL\n");
1348         }
1349
1350         CertCloseStore(store, 0);
1351         /* Don't delete it this time, the next test uses it */
1352     }
1353     /* Now that the file exists, we can open it read-only */
1354     store = CertOpenStore(CERT_STORE_PROV_FILENAME_W, 0, 0,
1355      CERT_STORE_READONLY_FLAG, filename);
1356     ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError());
1357     CertCloseStore(store, 0);
1358     DeleteFileW(filename);
1359
1360     store = CertOpenStore(CERT_STORE_PROV_FILENAME_W, 0, 0,
1361      CERT_FILE_STORE_COMMIT_ENABLE_FLAG | CERT_STORE_CREATE_NEW_FLAG, filename);
1362     ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError());
1363     if (store)
1364     {
1365         ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1366          bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, NULL);
1367         ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
1368          GetLastError());
1369         CertCloseStore(store, 0);
1370         compareFile(filename, serializedStoreWithCert,
1371          sizeof(serializedStoreWithCert));
1372     }
1373     store = CertOpenStore(CERT_STORE_PROV_FILENAME_W, 0, 0,
1374      CERT_FILE_STORE_COMMIT_ENABLE_FLAG, filename);
1375     ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError());
1376     if (store)
1377     {
1378         ret = CertAddEncodedCRLToStore(store, X509_ASN_ENCODING,
1379          signedCRL, sizeof(signedCRL), CERT_STORE_ADD_ALWAYS, NULL);
1380         ok(ret, "CertAddEncodedCRLToStore failed: %08x\n", GetLastError());
1381         CertCloseStore(store, 0);
1382         compareFile(filename, serializedStoreWithCertAndCRL,
1383          sizeof(serializedStoreWithCertAndCRL));
1384     }
1385     DeleteFileW(filename);
1386 }
1387
1388 static const BYTE signedContent[] = {
1389 0x30,0x81,0xb2,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,0xa0,
1390 0x81,0xa4,0x30,0x81,0xa1,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,
1391 0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x13,0x06,0x09,0x2a,0x86,
1392 0x48,0x86,0xf7,0x0d,0x01,0x07,0x01,0xa0,0x06,0x04,0x04,0x01,0x02,0x03,0x04,
1393 0x31,0x77,0x30,0x75,0x02,0x01,0x01,0x30,0x1a,0x30,0x15,0x31,0x13,0x30,0x11,
1394 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
1395 0x67,0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,
1396 0x02,0x05,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04,0x40,0x81,0xa6,0x70,
1397 0xb3,0xef,0x59,0xd1,0x66,0xd1,0x9b,0xc0,0x9a,0xb6,0x9a,0x5e,0x6d,0x6f,0x6d,
1398 0x0d,0x59,0xa9,0xaa,0x6e,0xe9,0x2c,0xa0,0x1e,0xee,0xc2,0x60,0xbc,0x59,0xbe,
1399 0x3f,0x63,0x06,0x8d,0xc9,0x11,0x1d,0x23,0x64,0x92,0xef,0x2e,0xfc,0x57,0x29,
1400 0xa4,0xaf,0xe0,0xee,0x93,0x19,0x39,0x51,0xe4,0x44,0xb8,0x0b,0x28,0xf4,0xa8,
1401 0x0d };
1402 static const BYTE signedWithCertAndCrlBareContent[] = {
1403 0x30,0x82,0x01,0x4f,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,0x86,
1404 0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x13,0x06,0x09,0x2a,0x86,0x48,
1405 0x86,0xf7,0x0d,0x01,0x07,0x01,0xa0,0x06,0x04,0x04,0x01,0x02,0x03,0x04,0xa0,
1406 0x7c,0x30,0x7a,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,
1407 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
1408 0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,
1409 0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
1410 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,
1411 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
1412 0x67,0x00,0x30,0x07,0x30,0x02,0x06,0x00,0x03,0x01,0x00,0xa3,0x16,0x30,0x14,
1413 0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,
1414 0x01,0xff,0x02,0x01,0x01,0xa1,0x2e,0x30,0x2c,0x30,0x02,0x06,0x00,0x30,0x15,
1415 0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,
1416 0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
1417 0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x31,0x77,0x30,0x75,0x02,0x01,0x01,
1418 0x30,0x1a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,
1419 0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x02,0x01,0x01,0x30,0x0c,
1420 0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x04,0x06,
1421 0x00,0x05,0x00,0x04,0x40,0x81,0xa6,0x70,0xb3,0xef,0x59,0xd1,0x66,0xd1,0x9b,
1422 0xc0,0x9a,0xb6,0x9a,0x5e,0x6d,0x6f,0x6d,0x0d,0x59,0xa9,0xaa,0x6e,0xe9,0x2c,
1423 0xa0,0x1e,0xee,0xc2,0x60,0xbc,0x59,0xbe,0x3f,0x63,0x06,0x8d,0xc9,0x11,0x1d,
1424 0x23,0x64,0x92,0xef,0x2e,0xfc,0x57,0x29,0xa4,0xaf,0xe0,0xee,0x93,0x19,0x39,
1425 0x51,0xe4,0x44,0xb8,0x0b,0x28,0xf4,0xa8,0x0d };
1426 static const BYTE hashContent[] = {
1427 0x30,0x47,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x05,0xa0,0x3a,
1428 0x30,0x38,0x02,0x01,0x00,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,
1429 0x02,0x05,0x05,0x00,0x30,0x13,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
1430 0x07,0x01,0xa0,0x06,0x04,0x04,0x01,0x02,0x03,0x04,0x04,0x10,0x08,0xd6,0xc0,
1431 0x5a,0x21,0x51,0x2a,0x79,0xa1,0xdf,0xeb,0x9d,0x2a,0x8f,0x26,0x2f };
1432 static const BYTE hashBareContent[] = {
1433 0x30,0x38,0x02,0x01,0x00,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,
1434 0x02,0x05,0x05,0x00,0x30,0x13,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
1435 0x07,0x01,0xa0,0x06,0x04,0x04,0x01,0x02,0x03,0x04,0x04,0x10,0x08,0xd6,0xc0,
1436 0x5a,0x21,0x51,0x2a,0x79,0xa1,0xdf,0xeb,0x9d,0x2a,0x8f,0x26,0x2f };
1437
1438 static void testMessageStore(void)
1439 {
1440     HCERTSTORE store;
1441     HCRYPTMSG msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL,
1442      NULL);
1443     CRYPT_DATA_BLOB blob = { sizeof(signedWithCertAndCrlBareContent),
1444      (LPBYTE)signedWithCertAndCrlBareContent };
1445     DWORD count, size;
1446     BOOL ret;
1447
1448     /* Crashes
1449     store = CertOpenStore(CERT_STORE_PROV_MSG, 0, 0, 0, NULL);
1450      */
1451     SetLastError(0xdeadbeef);
1452     store = CertOpenStore(CERT_STORE_PROV_MSG, 0, 0, 0, msg);
1453     ok(!store && GetLastError() == CRYPT_E_INVALID_MSG_TYPE,
1454      "Expected CRYPT_E_INVALID_MSG_TYPE, got %08x\n", GetLastError());
1455     CryptMsgUpdate(msg, signedContent, sizeof(signedContent), TRUE);
1456     store = CertOpenStore(CERT_STORE_PROV_MSG, 0, 0, 0, msg);
1457     ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError());
1458     if (store)
1459     {
1460         PCCERT_CONTEXT cert = NULL;
1461         PCCRL_CONTEXT crl = NULL;
1462
1463         count = 0;
1464         do {
1465             cert = CertEnumCertificatesInStore(store, cert);
1466             if (cert)
1467                 count++;
1468         } while (cert);
1469         ok(count == 0, "Expected 0 certificates, got %d\n", count);
1470
1471         if (pCertEnumCRLsInStore)
1472         {
1473             count = 0;
1474             do {
1475                 crl = pCertEnumCRLsInStore(store, crl);
1476                 if (crl)
1477                     count++;
1478             } while (crl);
1479             ok(count == 0, "Expected 0 CRLs, got %d\n", count);
1480         }
1481
1482         /* Can add certs to a message store */
1483         ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1484          bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, NULL);
1485         ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
1486          GetLastError());
1487         count = 0;
1488         do {
1489             cert = CertEnumCertificatesInStore(store, cert);
1490             if (cert)
1491                 count++;
1492         } while (cert);
1493         ok(count == 1, "Expected 1 certificate, got %d\n", count);
1494
1495         CertCloseStore(store, 0);
1496     }
1497     /* but the added certs weren't actually added to the message */
1498     size = sizeof(count);
1499     ret = CryptMsgGetParam(msg, CMSG_CERT_COUNT_PARAM, 0, &count, &size);
1500     ok(ret, "CryptMsgGetParam failed: %08x\n", GetLastError());
1501     ok(count == 0, "Expected 0 certificates, got %d\n", count);
1502     CryptMsgClose(msg);
1503
1504     /* Crashes
1505     store = CertOpenStore(CERT_STORE_PROV_PKCS7, 0, 0, 0, NULL);
1506      */
1507     store = CertOpenStore(CERT_STORE_PROV_PKCS7, 0, 0, 0, &blob);
1508     ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError());
1509     if (store)
1510     {
1511         DWORD count = 0;
1512         PCCERT_CONTEXT cert = NULL;
1513         PCCRL_CONTEXT crl = NULL;
1514
1515         do {
1516             cert = CertEnumCertificatesInStore(store, cert);
1517             if (cert)
1518                 count++;
1519         } while (cert);
1520         ok(count == 1, "Expected 1 certificate, got %d\n", count);
1521
1522         if (pCertEnumCRLsInStore)
1523         {
1524             count = 0;
1525             do {
1526                 crl = pCertEnumCRLsInStore(store, crl);
1527                 if (crl)
1528                     count++;
1529             } while (crl);
1530             ok(count == 1, "Expected 1 CRL, got %d\n", count);
1531         }
1532         CertCloseStore(store, 0);
1533     }
1534     /* Encoding appears to be ignored */
1535     store = CertOpenStore(CERT_STORE_PROV_PKCS7, X509_ASN_ENCODING, 0, 0,
1536      &blob);
1537     ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError());
1538     if (store)
1539         CertCloseStore(store, 0);
1540     /* Messages other than signed messages aren't allowed */
1541     blob.cbData = sizeof(hashContent);
1542     blob.pbData = (LPBYTE)hashContent;
1543     SetLastError(0xdeadbeef);
1544     store = CertOpenStore(CERT_STORE_PROV_PKCS7, 0, 0, 0, &blob);
1545     ok(!store && GetLastError() == CRYPT_E_INVALID_MSG_TYPE,
1546      "Expected CRYPT_E_INVALID_MSG_TYPE, got %08x\n", GetLastError());
1547     blob.cbData = sizeof(hashBareContent);
1548     blob.pbData = (LPBYTE)hashBareContent;
1549     SetLastError(0xdeadbeef);
1550     store = CertOpenStore(CERT_STORE_PROV_PKCS7, 0, 0, 0, &blob);
1551     ok(!store &&
1552      (GetLastError() == CRYPT_E_ASN1_BADTAG ||
1553       GetLastError() == OSS_DATA_ERROR), /* win9x */
1554      "Expected CRYPT_E_ASN1_BADTAG, got %08x\n", GetLastError());
1555 }
1556
1557 static void testCertOpenSystemStore(void)
1558 {
1559     HCERTSTORE store;
1560
1561     store = CertOpenSystemStoreW(0, NULL);
1562     ok(!store && GetLastError() == E_INVALIDARG,
1563      "Expected E_INVALIDARG, got %08x\n", GetLastError());
1564     /* This succeeds, and on WinXP at least, the Bogus key is created under
1565      * HKCU (but not under HKLM, even when run as an administrator.)
1566      */
1567     store = CertOpenSystemStoreW(0, BogusW);
1568     ok(store != 0, "CertOpenSystemStore failed: %08x\n", GetLastError());
1569     if (store)
1570         CertCloseStore(store, 0);
1571     /* Delete it so other tests succeed next time around */
1572     store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0,
1573      CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_DELETE_FLAG, BogusW);
1574     RegDeleteKeyW(HKEY_CURRENT_USER, BogusPathW);
1575 }
1576
1577 struct EnumSystemStoreInfo
1578 {
1579     BOOL  goOn;
1580     DWORD storeCount;
1581 };
1582
1583 static BOOL CALLBACK enumSystemStoreCB(const void *systemStore, DWORD dwFlags,
1584  PCERT_SYSTEM_STORE_INFO pStoreInfo, void *pvReserved, void *pvArg)
1585 {
1586     struct EnumSystemStoreInfo *info = (struct EnumSystemStoreInfo *)pvArg;
1587
1588     info->storeCount++;
1589     return info->goOn;
1590 }
1591
1592 static void testCertEnumSystemStore(void)
1593 {
1594     BOOL ret;
1595     struct EnumSystemStoreInfo info = { FALSE, 0 };
1596
1597     if (!pCertEnumSystemStore)
1598     {
1599         skip("CertEnumSystemStore() is not available\n");
1600         return;
1601     }
1602
1603     SetLastError(0xdeadbeef);
1604     ret = pCertEnumSystemStore(0, NULL, NULL, NULL);
1605     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
1606      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
1607     /* Crashes
1608     ret = pCertEnumSystemStore(CERT_SYSTEM_STORE_LOCAL_MACHINE, NULL, NULL,
1609      NULL);
1610      */
1611
1612     SetLastError(0xdeadbeef);
1613     ret = pCertEnumSystemStore(CERT_SYSTEM_STORE_LOCAL_MACHINE, NULL, &info,
1614      enumSystemStoreCB);
1615     /* Callback returning FALSE stops enumeration */
1616     ok(!ret, "Expected CertEnumSystemStore to stop\n");
1617     ok(info.storeCount == 0 || info.storeCount == 1,
1618      "Expected 0 or 1 stores\n");
1619
1620     info.goOn = TRUE;
1621     info.storeCount = 0;
1622     ret = pCertEnumSystemStore(CERT_SYSTEM_STORE_LOCAL_MACHINE, NULL, &info,
1623      enumSystemStoreCB);
1624     ok(ret, "CertEnumSystemStore failed: %08x\n", GetLastError());
1625     /* There should always be at least My, Root, and CA stores */
1626     ok(info.storeCount == 0 || info.storeCount >= 3,
1627      "Expected at least 3 stores\n");
1628 }
1629
1630 static void testStoreProperty(void)
1631 {
1632     HCERTSTORE store;
1633     BOOL ret;
1634     DWORD propID, size = 0, state;
1635     CRYPT_DATA_BLOB blob;
1636
1637     if (!pCertGetStoreProperty || !pCertSetStoreProperty)
1638     {
1639         skip("CertGet/SetStoreProperty() is not available\n");
1640         return;
1641     }
1642
1643     /* Crash
1644     ret = pCertGetStoreProperty(NULL, 0, NULL, NULL);
1645     ret = pCertGetStoreProperty(NULL, 0, NULL, &size);
1646     ret = pCertGetStoreProperty(store, 0, NULL, NULL);
1647      */
1648
1649     store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
1650      CERT_STORE_CREATE_NEW_FLAG, NULL);
1651     /* Check a missing prop ID */
1652     SetLastError(0xdeadbeef);
1653     ret = pCertGetStoreProperty(store, 0, NULL, &size);
1654     ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
1655      "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
1656     /* Contrary to MSDN, CERT_ACCESS_STATE_PROP_ID is supported for stores.. */
1657     size = sizeof(state);
1658     ret = pCertGetStoreProperty(store, CERT_ACCESS_STATE_PROP_ID, &state, &size);
1659     ok(ret, "CertGetStoreProperty failed for CERT_ACCESS_STATE_PROP_ID: %08x\n",
1660      GetLastError());
1661     ok(!state, "Expected a non-persisted store\n");
1662     /* and CERT_STORE_LOCALIZED_NAME_PROP_ID isn't supported by default. */
1663     size = 0;
1664     ret = pCertGetStoreProperty(store, CERT_STORE_LOCALIZED_NAME_PROP_ID, NULL,
1665      &size);
1666     ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
1667      "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
1668     /* Delete an arbitrary property on a store */
1669     ret = pCertSetStoreProperty(store, CERT_FIRST_USER_PROP_ID, 0, NULL);
1670     ok(ret, "CertSetStoreProperty failed: %08x\n", GetLastError());
1671     /* Set an arbitrary property on a store */
1672     blob.pbData = (LPBYTE)&state;
1673     blob.cbData = sizeof(state);
1674     ret = pCertSetStoreProperty(store, CERT_FIRST_USER_PROP_ID, 0, &blob);
1675     ok(ret, "CertSetStoreProperty failed: %08x\n", GetLastError());
1676     /* Get an arbitrary property that's been set */
1677     ret = pCertGetStoreProperty(store, CERT_FIRST_USER_PROP_ID, NULL, &size);
1678     ok(ret, "CertGetStoreProperty failed: %08x\n", GetLastError());
1679     ok(size == sizeof(state), "Unexpected data size %d\n", size);
1680     ret = pCertGetStoreProperty(store, CERT_FIRST_USER_PROP_ID, &propID, &size);
1681     ok(ret, "CertGetStoreProperty failed: %08x\n", GetLastError());
1682     ok(propID == state, "CertGetStoreProperty got the wrong value\n");
1683     /* Delete it again */
1684     ret = pCertSetStoreProperty(store, CERT_FIRST_USER_PROP_ID, 0, NULL);
1685     ok(ret, "CertSetStoreProperty failed: %08x\n", GetLastError());
1686     /* And check that it's missing */
1687     SetLastError(0xdeadbeef);
1688     ret = pCertGetStoreProperty(store, CERT_FIRST_USER_PROP_ID, NULL, &size);
1689     ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
1690      "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
1691     CertCloseStore(store, 0);
1692
1693     /* Recheck on the My store.. */
1694     store = CertOpenSystemStoreW(0, MyW);
1695     size = sizeof(state);
1696     ret = pCertGetStoreProperty(store, CERT_ACCESS_STATE_PROP_ID, &state, &size);
1697     ok(ret, "CertGetStoreProperty failed for CERT_ACCESS_STATE_PROP_ID: %08x\n",
1698      GetLastError());
1699     ok(state, "Expected a persisted store\n");
1700     SetLastError(0xdeadbeef);
1701     size = 0;
1702     ret = pCertGetStoreProperty(store, CERT_STORE_LOCALIZED_NAME_PROP_ID, NULL,
1703      &size);
1704     ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
1705      "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
1706     CertCloseStore(store, 0);
1707 }
1708
1709 static void testAddSerialized(void)
1710 {
1711     BOOL ret;
1712     HCERTSTORE store;
1713     BYTE buf[sizeof(struct CertPropIDHeader) * 2 + 20 + sizeof(bigCert)] =
1714      { 0 };
1715     BYTE hash[20];
1716     struct CertPropIDHeader *hdr;
1717     PCCERT_CONTEXT context;
1718
1719     ret = CertAddSerializedElementToStore(0, NULL, 0, 0, 0, 0, NULL, NULL);
1720     ok(!ret && GetLastError() == ERROR_END_OF_MEDIA,
1721      "Expected ERROR_END_OF_MEDIA, got %08x\n", GetLastError());
1722
1723     store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
1724      CERT_STORE_CREATE_NEW_FLAG, NULL);
1725     ok(store != 0, "CertOpenStore failed: %08x\n", GetLastError());
1726
1727     ret = CertAddSerializedElementToStore(store, NULL, 0, 0, 0, 0, NULL, NULL);
1728     ok(!ret && GetLastError() == ERROR_END_OF_MEDIA,
1729      "Expected ERROR_END_OF_MEDIA, got %08x\n", GetLastError());
1730
1731     /* Test with an empty property */
1732     hdr = (struct CertPropIDHeader *)buf;
1733     hdr->propID = CERT_CERT_PROP_ID;
1734     hdr->unknown1 = 1;
1735     hdr->cb = 0;
1736     ret = CertAddSerializedElementToStore(store, buf, sizeof(buf), 0, 0, 0,
1737      NULL, NULL);
1738     ok(!ret && GetLastError() == E_INVALIDARG,
1739      "Expected E_INVALIDARG, got %08x\n", GetLastError());
1740     /* Test with a bad size in property header */
1741     hdr->cb = sizeof(bigCert) - 1;
1742     memcpy(buf + sizeof(struct CertPropIDHeader), bigCert, sizeof(bigCert));
1743     ret = CertAddSerializedElementToStore(store, buf, sizeof(buf), 0, 0, 0,
1744      NULL, NULL);
1745     ok(!ret && GetLastError() == E_INVALIDARG,
1746      "Expected E_INVALIDARG, got %08x\n", GetLastError());
1747     ret = CertAddSerializedElementToStore(store, buf,
1748      sizeof(struct CertPropIDHeader) + sizeof(bigCert), 0, 0, 0, NULL,
1749      NULL);
1750     ok(!ret && GetLastError() == E_INVALIDARG,
1751      "Expected E_INVALIDARG, got %08x\n", GetLastError());
1752     ret = CertAddSerializedElementToStore(store, buf,
1753      sizeof(struct CertPropIDHeader) + sizeof(bigCert), CERT_STORE_ADD_NEW,
1754      0, 0, NULL, NULL);
1755     ok(!ret && GetLastError() == E_INVALIDARG,
1756      "Expected E_INVALIDARG, got %08x\n", GetLastError());
1757     /* Kosher size in property header, but no context type */
1758     hdr->cb = sizeof(bigCert);
1759     ret = CertAddSerializedElementToStore(store, buf, sizeof(buf), 0, 0, 0,
1760      NULL, NULL);
1761     ok(!ret && GetLastError() == E_INVALIDARG,
1762      "Expected E_INVALIDARG, got %08x\n", GetLastError());
1763     ret = CertAddSerializedElementToStore(store, buf,
1764      sizeof(struct CertPropIDHeader) + sizeof(bigCert), 0, 0, 0, NULL,
1765      NULL);
1766     ok(!ret && GetLastError() == E_INVALIDARG,
1767      "Expected E_INVALIDARG, got %08x\n", GetLastError());
1768     ret = CertAddSerializedElementToStore(store, buf,
1769      sizeof(struct CertPropIDHeader) + sizeof(bigCert), CERT_STORE_ADD_NEW,
1770      0, 0, NULL, NULL);
1771     ok(!ret && GetLastError() == E_INVALIDARG,
1772      "Expected E_INVALIDARG, got %08x\n", GetLastError());
1773     /* With a bad context type */
1774     ret = CertAddSerializedElementToStore(store, buf, sizeof(buf), 0, 0, 
1775      CERT_STORE_CRL_CONTEXT_FLAG, NULL, NULL);
1776     ok(!ret && GetLastError() == E_INVALIDARG,
1777      "Expected E_INVALIDARG, got %08x\n", GetLastError());
1778     ret = CertAddSerializedElementToStore(store, buf,
1779      sizeof(struct CertPropIDHeader) + sizeof(bigCert), 0, 0, 
1780      CERT_STORE_CRL_CONTEXT_FLAG, NULL, NULL);
1781     ok(!ret && GetLastError() == E_INVALIDARG,
1782      "Expected E_INVALIDARG, got %08x\n", GetLastError());
1783     ret = CertAddSerializedElementToStore(store, buf,
1784      sizeof(struct CertPropIDHeader) + sizeof(bigCert), CERT_STORE_ADD_NEW,
1785      0, CERT_STORE_CRL_CONTEXT_FLAG, NULL, NULL);
1786     ok(!ret && GetLastError() == E_INVALIDARG,
1787      "Expected E_INVALIDARG, got %08x\n", GetLastError());
1788     /* Bad unknown field, good type */
1789     hdr->unknown1 = 2;
1790     ret = CertAddSerializedElementToStore(store, buf, sizeof(buf), 0, 0, 
1791      CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL, NULL);
1792     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
1793      "Expected ERROR_FILE_NOT_FOUND got %08x\n", GetLastError());
1794     ret = CertAddSerializedElementToStore(store, buf,
1795      sizeof(struct CertPropIDHeader) + sizeof(bigCert), 0, 0, 
1796      CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL, NULL);
1797     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
1798      "Expected ERROR_FILE_NOT_FOUND got %08x\n", GetLastError());
1799     ret = CertAddSerializedElementToStore(store, buf,
1800      sizeof(struct CertPropIDHeader) + sizeof(bigCert), CERT_STORE_ADD_NEW,
1801      0, CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL, NULL);
1802     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
1803      "Expected ERROR_FILE_NOT_FOUND got %08x\n", GetLastError());
1804     /* Most everything okay, but bad add disposition */
1805     hdr->unknown1 = 1;
1806     /* This crashes
1807     ret = CertAddSerializedElementToStore(store, buf, sizeof(buf), 0, 0, 
1808      CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL, NULL);
1809      * as does this
1810     ret = CertAddSerializedElementToStore(store, buf,
1811      sizeof(struct CertPropIDHeader) + sizeof(bigCert), 0, 0, 
1812      CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL, NULL);
1813      */
1814     /* Everything okay, but buffer's too big */
1815     ret = CertAddSerializedElementToStore(store, buf, sizeof(buf),
1816      CERT_STORE_ADD_NEW, 0, CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL, NULL);
1817     ok(ret, "CertAddSerializedElementToStore failed: %08x\n", GetLastError());
1818     /* Everything okay, check it's not re-added */
1819     ret = CertAddSerializedElementToStore(store, buf,
1820      sizeof(struct CertPropIDHeader) + sizeof(bigCert), CERT_STORE_ADD_NEW,
1821      0, CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL, NULL);
1822     ok(!ret && GetLastError() == CRYPT_E_EXISTS,
1823      "Expected CRYPT_E_EXISTS, got %08x\n", GetLastError());
1824
1825     context = CertEnumCertificatesInStore(store, NULL);
1826     ok(context != NULL, "Expected a cert\n");
1827     if (context)
1828         CertDeleteCertificateFromStore(context);
1829
1830     /* Try adding with a bogus hash.  Oddly enough, it succeeds, and the hash,
1831      * when queried, is the real hash rather than the bogus hash.
1832      */
1833     hdr = (struct CertPropIDHeader *)(buf + sizeof(struct CertPropIDHeader) +
1834      sizeof(bigCert));
1835     hdr->propID = CERT_HASH_PROP_ID;
1836     hdr->unknown1 = 1;
1837     hdr->cb = sizeof(hash);
1838     memset(hash, 0xc, sizeof(hash));
1839     memcpy((LPBYTE)hdr + sizeof(struct CertPropIDHeader), hash, sizeof(hash));
1840     ret = CertAddSerializedElementToStore(store, buf, sizeof(buf),
1841      CERT_STORE_ADD_NEW, 0, CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL,
1842      (const void **)&context);
1843     ok(ret, "CertAddSerializedElementToStore failed: %08x\n", GetLastError());
1844     if (context)
1845     {
1846         BYTE hashVal[20], realHash[20];
1847         DWORD size = sizeof(hashVal);
1848
1849         ret = CryptHashCertificate(0, 0, 0, bigCert, sizeof(bigCert),
1850          realHash, &size);
1851         ok(ret, "CryptHashCertificate failed: %08x\n", GetLastError());
1852         ret = CertGetCertificateContextProperty(context, CERT_HASH_PROP_ID,
1853          hashVal, &size);
1854         ok(ret, "CertGetCertificateContextProperty failed: %08x\n",
1855          GetLastError());
1856         ok(!memcmp(hashVal, realHash, size), "Unexpected hash\n");
1857         CertFreeCertificateContext(context);
1858     }
1859
1860     CertCloseStore(store, 0);
1861 }
1862
1863 static DWORD countCertsInStore(HCERTSTORE store)
1864 {
1865     PCCERT_CONTEXT cert = NULL;
1866     DWORD certs = 0;
1867
1868     do {
1869         cert = CertEnumCertificatesInStore(store, cert);
1870         if (cert)
1871             certs++;
1872     } while (cert);
1873     return certs;
1874 }
1875
1876 static DWORD countCRLsInStore(HCERTSTORE store)
1877 {
1878     PCCRL_CONTEXT crl = NULL;
1879     DWORD crls = 0;
1880
1881     do {
1882         crl = pCertEnumCRLsInStore(store, crl);
1883         if (crl)
1884             crls++;
1885     } while (crl);
1886     return crls;
1887 }
1888
1889 static void test_I_UpdateStore(void)
1890 {
1891     HMODULE lib = GetModuleHandleA("crypt32");
1892     BOOL (WINAPI *pI_CertUpdatestore)(HCERTSTORE, HCERTSTORE, DWORD, DWORD) =
1893      (void *)GetProcAddress(lib, "I_CertUpdateStore");
1894     BOOL ret;
1895     HCERTSTORE store1, store2;
1896     PCCERT_CONTEXT cert;
1897     DWORD certs;
1898
1899     if (!pI_CertUpdatestore)
1900     {
1901         skip("No I_CertUpdateStore\n");
1902         return;
1903     }
1904     store1 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
1905      CERT_STORE_CREATE_NEW_FLAG, NULL);
1906     store2 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
1907      CERT_STORE_CREATE_NEW_FLAG, NULL);
1908
1909     /* Crash
1910     ret = pI_CertUpdatestore(NULL, NULL, 0, 0);
1911     ret = pI_CertUpdatestore(store1, NULL, 0, 0);
1912     ret = pI_CertUpdatestore(NULL, store2, 0, 0);
1913      */
1914     ret = pI_CertUpdatestore(store1, store2, 0, 0);
1915     ok(ret, "I_CertUpdateStore failed: %08x\n", GetLastError());
1916
1917     CertAddEncodedCertificateToStore(store2, X509_ASN_ENCODING, bigCert,
1918      sizeof(bigCert), CERT_STORE_ADD_ALWAYS, &cert);
1919     /* I_CertUpdateStore adds the contexts from store2 to store1 */
1920     ret = pI_CertUpdatestore(store1, store2, 0, 0);
1921     ok(ret, "I_CertUpdateStore failed: %08x\n", GetLastError());
1922     certs = countCertsInStore(store1);
1923     ok(certs == 1, "Expected 1 cert, got %d\n", certs);
1924     /* Calling it a second time has no effect */
1925     ret = pI_CertUpdatestore(store1, store2, 0, 0);
1926     ok(ret, "I_CertUpdateStore failed: %08x\n", GetLastError());
1927     certs = countCertsInStore(store1);
1928     ok(certs == 1, "Expected 1 cert, got %d\n", certs);
1929
1930     /* The last parameters to I_CertUpdateStore appear to be ignored */
1931     ret = pI_CertUpdatestore(store1, store2, 1, 0);
1932     ok(ret, "I_CertUpdateStore failed: %08x\n", GetLastError());
1933     ret = pI_CertUpdatestore(store1, store2, 0, 1);
1934     ok(ret, "I_CertUpdateStore failed: %08x\n", GetLastError());
1935
1936     CertAddEncodedCRLToStore(store2, X509_ASN_ENCODING, signedCRL,
1937      sizeof(signedCRL), CERT_STORE_ADD_ALWAYS, NULL);
1938
1939     /* I_CertUpdateStore also adds the CRLs from store2 to store1 */
1940     ret = pI_CertUpdatestore(store1, store2, 0, 0);
1941     ok(ret, "I_CertUpdateStore failed: %08x\n", GetLastError());
1942     certs = countCertsInStore(store1);
1943     ok(certs == 1, "Expected 1 cert, got %d\n", certs);
1944     if (pCertEnumCRLsInStore)
1945     {
1946         certs = countCRLsInStore(store1);
1947         ok(certs == 1, "Expected 1 CRL, got %d\n", certs);
1948     }
1949
1950     CertDeleteCertificateFromStore(cert);
1951     /* If a context is deleted from store2, I_CertUpdateStore deletes it
1952      * from store1
1953      */
1954     ret = pI_CertUpdatestore(store1, store2, 0, 0);
1955     ok(ret, "I_CertUpdateStore failed: %08x\n", GetLastError());
1956     certs = countCertsInStore(store1);
1957     ok(certs == 0, "Expected 0 certs, got %d\n", certs);
1958
1959     CertFreeCertificateContext(cert);
1960     CertCloseStore(store1, 0);
1961     CertCloseStore(store2, 0);
1962 }
1963
1964 START_TEST(store)
1965 {
1966     HMODULE hdll;
1967
1968     hdll = GetModuleHandleA("Crypt32.dll");
1969     pCertAddStoreToCollection = (void*)GetProcAddress(hdll, "CertAddStoreToCollection");
1970     pCertControlStore = (void*)GetProcAddress(hdll, "CertControlStore");
1971     pCertEnumCRLsInStore = (void*)GetProcAddress(hdll, "CertEnumCRLsInStore");
1972     pCertEnumSystemStore = (void*)GetProcAddress(hdll, "CertEnumSystemStore");
1973     pCertGetStoreProperty = (void*)GetProcAddress(hdll, "CertGetStoreProperty");
1974     pCertRemoveStoreFromCollection = (void*)GetProcAddress(hdll, "CertRemoveStoreFromCollection");
1975     pCertSetStoreProperty = (void*)GetProcAddress(hdll, "CertSetStoreProperty");
1976
1977     /* various combinations of CertOpenStore */
1978     testMemStore();
1979     testCollectionStore();
1980     testRegStore();
1981     testSystemRegStore();
1982     testSystemStore();
1983     testFileStore();
1984     testFileNameStore();
1985     testMessageStore();
1986
1987     testCertOpenSystemStore();
1988     testCertEnumSystemStore();
1989     testStoreProperty();
1990
1991     testAddSerialized();
1992
1993     test_I_UpdateStore();
1994 }