ws2_32: WS_getaddrinfo TRACE message can crash Wine.
[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, "Expected 1 certificates, got %d\n", certCount);
834
835             /* Try again with the correct hash... */
836             ptr = buf + sizeof(*hdr);
837             memcpy(ptr, hash, sizeof(hash));
838
839             rc = RegSetValueExA(subKey, "Blob", 0, REG_BINARY, buf,
840              sizeof(buf));
841             ok(!rc, "RegSetValueExA failed: %d\n", rc);
842
843             ret = pCertControlStore(store, 0, CERT_STORE_CTRL_RESYNC, NULL);
844             ok(ret, "CertControlStore failed: %08x\n", GetLastError());
845
846             /* and make sure two certs get loaded. */
847             certCount = 0;
848             context = NULL;
849             do {
850                 context = CertEnumCertificatesInStore(store, context);
851                 if (context)
852                     certCount++;
853             } while (context != NULL);
854             ok(certCount == 2, "Expected 2 certificates, got %d\n", certCount);
855
856             RegCloseKey(subKey);
857         }
858         CertCloseStore(store, 0);
859         /* Is delete allowed on a reg store? */
860         store = CertOpenStore(CERT_STORE_PROV_REG, 0, 0,
861          CERT_STORE_DELETE_FLAG, key);
862         ok(store == NULL, "Expected NULL return from CERT_STORE_DELETE_FLAG\n");
863         ok(GetLastError() == 0, "CertOpenStore failed: %08x\n",
864          GetLastError());
865
866         RegCloseKey(key);
867     }
868     /* The CertOpenStore with CERT_STORE_DELETE_FLAG above will delete the
869      * contents of the key, but not the key itself.
870      */
871     rc = RegCreateKeyExA(HKEY_CURRENT_USER, tempKey, 0, NULL, 0, KEY_ALL_ACCESS,
872      NULL, &key, &disp);
873     ok(!rc, "RegCreateKeyExA failed: %d\n", rc);
874     ok(disp == REG_OPENED_EXISTING_KEY,
875      "Expected REG_OPENED_EXISTING_KEY, got %d\n", disp);
876     if (!rc)
877     {
878         RegCloseKey(key);
879         rc = RegDeleteKeyA(HKEY_CURRENT_USER, tempKey);
880         if (rc)
881         {
882             HMODULE shlwapi = LoadLibraryA("shlwapi");
883
884             /* Use shlwapi's SHDeleteKeyA to _really_ blow away the key,
885              * otherwise subsequent tests will fail.
886              */
887             if (shlwapi)
888             {
889                 SHDeleteKeyAFunc pSHDeleteKeyA =
890                  (SHDeleteKeyAFunc)GetProcAddress(shlwapi, "SHDeleteKeyA");
891
892                 if (pSHDeleteKeyA)
893                     pSHDeleteKeyA(HKEY_CURRENT_USER, tempKey);
894                 FreeLibrary(shlwapi);
895             }
896         }
897     }
898 }
899
900 static const char MyA[] = { 'M','y',0,0 };
901 static const WCHAR MyW[] = { 'M','y',0 };
902 static const WCHAR BogusW[] = { 'B','o','g','u','s',0 };
903 static const WCHAR BogusPathW[] = { 'S','o','f','t','w','a','r','e','\\',
904  'M','i','c','r','o','s','o','f','t','\\','S','y','s','t','e','m','C','e','r',
905  't','i','f','i','c','a','t','e','s','\\','B','o','g','u','s',0 };
906
907 static void testSystemRegStore(void)
908 {
909     HCERTSTORE store, memStore;
910
911     /* Check with a UNICODE name */
912     store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY, 0, 0,
913      CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_OPEN_EXISTING_FLAG, MyW);
914     /* Not all OSes support CERT_STORE_PROV_SYSTEM_REGISTRY, so don't continue
915      * testing if they don't.
916      */
917     if (!store)
918         return;
919
920     /* Check that it isn't a collection store */
921     memStore = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
922      CERT_STORE_CREATE_NEW_FLAG, NULL);
923     if (memStore)
924     {
925         if (pCertAddStoreToCollection)
926         {
927             BOOL ret = pCertAddStoreToCollection(store, memStore, 0, 0);
928             ok(!ret && GetLastError() == E_INVALIDARG,
929                "Expected E_INVALIDARG, got %08x\n", GetLastError());
930         }
931         CertCloseStore(memStore, 0);
932     }
933     CertCloseStore(store, 0);
934
935     /* Check opening a bogus store */
936     store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY, 0, 0,
937      CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_OPEN_EXISTING_FLAG, BogusW);
938     ok(!store && GetLastError() == ERROR_FILE_NOT_FOUND,
939      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
940     store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY, 0, 0,
941      CERT_SYSTEM_STORE_CURRENT_USER, BogusW);
942     ok(store != 0, "CertOpenStore failed: %08x\n", GetLastError());
943     if (store)
944         CertCloseStore(store, 0);
945     /* Now check whether deleting is allowed */
946     store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY, 0, 0,
947      CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_DELETE_FLAG, BogusW);
948     RegDeleteKeyW(HKEY_CURRENT_USER, BogusPathW);
949
950     store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY, 0, 0, 0, NULL);
951     ok(!store && GetLastError() == E_INVALIDARG,
952      "Expected E_INVALIDARG, got %08x\n", GetLastError());
953     store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY, 0, 0,
954      CERT_SYSTEM_STORE_LOCAL_MACHINE | CERT_SYSTEM_STORE_CURRENT_USER, MyA);
955     ok(!store && GetLastError() == E_INVALIDARG,
956      "Expected E_INVALIDARG, got %08x\n", GetLastError());
957     store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY, 0, 0,
958      CERT_SYSTEM_STORE_LOCAL_MACHINE | CERT_SYSTEM_STORE_CURRENT_USER, MyW);
959     ok(!store && GetLastError() == E_INVALIDARG,
960      "Expected E_INVALIDARG, got %08x\n", GetLastError());
961     /* The name is expected to be UNICODE, check with an ASCII name */
962     store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY, 0, 0,
963      CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_OPEN_EXISTING_FLAG, MyA);
964     ok(!store && GetLastError() == ERROR_FILE_NOT_FOUND,
965      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
966 }
967
968 static void testSystemStore(void)
969 {
970     static const WCHAR baskslashW[] = { '\\',0 };
971     HCERTSTORE store;
972     WCHAR keyName[MAX_PATH];
973     HKEY key;
974     LONG rc;
975
976     store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0, 0, NULL);
977     ok(!store && GetLastError() == ERROR_FILE_NOT_FOUND,
978      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
979     store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0,
980      CERT_SYSTEM_STORE_LOCAL_MACHINE | CERT_SYSTEM_STORE_CURRENT_USER, MyA);
981     ok(!store && GetLastError() == ERROR_FILE_NOT_FOUND,
982      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
983     store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0,
984      CERT_SYSTEM_STORE_LOCAL_MACHINE | CERT_SYSTEM_STORE_CURRENT_USER, MyW);
985     ok(!store && GetLastError() == ERROR_FILE_NOT_FOUND,
986      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
987     /* The name is expected to be UNICODE, first check with an ASCII name */
988     store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0,
989      CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_OPEN_EXISTING_FLAG, MyA);
990     ok(!store && GetLastError() == ERROR_FILE_NOT_FOUND,
991      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
992     /* Create the expected key */
993     lstrcpyW(keyName, CERT_LOCAL_MACHINE_SYSTEM_STORE_REGPATH);
994     lstrcatW(keyName, baskslashW);
995     lstrcatW(keyName, MyW);
996     rc = RegCreateKeyExW(HKEY_CURRENT_USER, keyName, 0, NULL, 0, KEY_READ,
997      NULL, &key, NULL);
998     ok(!rc, "RegCreateKeyEx failed: %d\n", rc);
999     if (!rc)
1000         RegCloseKey(key);
1001     /* Check opening with a UNICODE name, specifying the create new flag */
1002     store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0,
1003      CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_CREATE_NEW_FLAG, MyW);
1004     ok(!store && GetLastError() == ERROR_FILE_EXISTS,
1005      "Expected ERROR_FILE_EXISTS, got %08x\n", GetLastError());
1006     /* Now check opening with a UNICODE name, this time opening existing */
1007     store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0,
1008      CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_OPEN_EXISTING_FLAG, MyW);
1009     ok(store != 0, "CertOpenStore failed: %08x\n", GetLastError());
1010     if (store)
1011     {
1012         HCERTSTORE memStore = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
1013          CERT_STORE_CREATE_NEW_FLAG, NULL);
1014
1015         /* Check that it's a collection store */
1016         if (memStore)
1017         {
1018             if (pCertAddStoreToCollection)
1019             {
1020                 BOOL ret = pCertAddStoreToCollection(store, memStore, 0, 0);
1021                 /* FIXME: this'll fail on NT4, but what error will it give? */
1022                 ok(ret, "CertAddStoreToCollection failed: %08x\n", GetLastError());
1023             }
1024             CertCloseStore(memStore, 0);
1025         }
1026         CertCloseStore(store, 0);
1027     }
1028
1029     /* Check opening a bogus store */
1030     store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0,
1031      CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_OPEN_EXISTING_FLAG, BogusW);
1032     ok(!store && GetLastError() == ERROR_FILE_NOT_FOUND,
1033      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
1034     store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0,
1035      CERT_SYSTEM_STORE_CURRENT_USER, BogusW);
1036     ok(store != 0, "CertOpenStore failed: %08x\n", GetLastError());
1037     if (store)
1038         CertCloseStore(store, 0);
1039     /* Now check whether deleting is allowed */
1040     store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0,
1041      CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_DELETE_FLAG, BogusW);
1042     RegDeleteKeyW(HKEY_CURRENT_USER, BogusPathW);
1043 }
1044
1045 static const BYTE serializedStoreWithCert[] = {
1046  0x00,0x00,0x00,0x00,0x43,0x45,0x52,0x54,0x20,0x00,0x00,0x00,0x01,0x00,0x00,
1047  0x00,0x7c,0x00,0x00,0x00,0x30,0x7a,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,
1048  0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,
1049  0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,
1050  0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,
1051  0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,
1052  0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,
1053  0x20,0x4c,0x61,0x6e,0x67,0x00,0x30,0x07,0x30,0x02,0x06,0x00,0x03,0x01,0x00,
1054  0xa3,0x16,0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,
1055  0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,
1056  0x00,0x00,0x00,0x00,0x00,0x00 };
1057 static const BYTE serializedStoreWithCertAndCRL[] = {
1058  0x00,0x00,0x00,0x00,0x43,0x45,0x52,0x54,0x20,0x00,0x00,0x00,0x01,0x00,0x00,
1059  0x00,0x7c,0x00,0x00,0x00,0x30,0x7a,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,
1060  0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,
1061  0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,
1062  0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,
1063  0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,
1064  0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,
1065  0x20,0x4c,0x61,0x6e,0x67,0x00,0x30,0x07,0x30,0x02,0x06,0x00,0x03,0x01,0x00,
1066  0xa3,0x16,0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,
1067  0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01,0x21,0x00,0x00,0x00,0x01,0x00,
1068  0x00,0x00,0x47,0x00,0x00,0x00,0x30,0x45,0x30,0x2c,0x30,0x02,0x06,0x00,0x30,
1069  0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,
1070  0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
1071  0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00,0x03,0x11,
1072  0x00,0x0f,0x0e,0x0d,0x0c,0x0b,0x0a,0x09,0x08,0x07,0x06,0x05,0x04,0x03,0x02,
1073  0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 };
1074
1075 static void compareFile(LPCWSTR filename, const BYTE *pb, DWORD cb)
1076 {
1077     HANDLE h;
1078     BYTE buf[200];
1079     BOOL ret;
1080     DWORD cbRead = 0, totalRead = 0;
1081
1082     h = CreateFileW(filename, GENERIC_READ, 0, NULL, OPEN_EXISTING,
1083      FILE_ATTRIBUTE_NORMAL, NULL);
1084     if (h == INVALID_HANDLE_VALUE)
1085         return;
1086     do {
1087         ret = ReadFile(h, buf, sizeof(buf), &cbRead, NULL);
1088         if (ret && cbRead)
1089         {
1090             ok(totalRead + cbRead <= cb, "Expected total count %d, see %d\n",
1091              cb, totalRead + cbRead);
1092             ok(!memcmp(pb + totalRead, buf, cbRead),
1093              "Unexpected data in file\n");
1094             totalRead += cbRead;
1095         }
1096     } while (ret && cbRead);
1097     CloseHandle(h);
1098 }
1099
1100 static void testFileStore(void)
1101 {
1102     static const WCHAR szPrefix[] = { 'c','e','r',0 };
1103     static const WCHAR szDot[] = { '.',0 };
1104     WCHAR filename[MAX_PATH];
1105     HCERTSTORE store;
1106     BOOL ret;
1107     PCCERT_CONTEXT cert;
1108     HANDLE file;
1109
1110     if (!pCertControlStore)
1111     {
1112         skip("CertControlStore() is not available\n");
1113         return;
1114     }
1115
1116     store = CertOpenStore(CERT_STORE_PROV_FILE, 0, 0, 0, NULL);
1117     ok(!store && GetLastError() == ERROR_INVALID_HANDLE,
1118      "Expected ERROR_INVALID_HANDLE, got %08x\n", GetLastError());
1119
1120     if (!GetTempFileNameW(szDot, szPrefix, 0, filename))
1121        return;
1122  
1123     DeleteFileW(filename);
1124     file = CreateFileW(filename, GENERIC_READ | GENERIC_WRITE, 0, NULL,
1125      CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
1126     if (file == INVALID_HANDLE_VALUE)
1127         return;
1128
1129     store = CertOpenStore(CERT_STORE_PROV_FILE, 0, 0, CERT_STORE_DELETE_FLAG,
1130      file);
1131     ok(!store && GetLastError() == E_INVALIDARG,
1132      "Expected E_INVALIDARG, got %08x\n", GetLastError());
1133     store = CertOpenStore(CERT_STORE_PROV_FILE, 0, 0,
1134      CERT_FILE_STORE_COMMIT_ENABLE_FLAG | CERT_STORE_READONLY_FLAG, file);
1135     ok(!store && GetLastError() == E_INVALIDARG,
1136      "Expected E_INVALIDARG, got %08x\n", GetLastError());
1137
1138     /* A "read-only" file store.. */
1139     store = CertOpenStore(CERT_STORE_PROV_FILE, 0, 0,
1140      CERT_STORE_OPEN_EXISTING_FLAG | CERT_STORE_READONLY_FLAG, file);
1141     ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError());
1142     if (store)
1143     {
1144         DWORD size;
1145
1146         ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1147          bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, NULL);
1148         /* apparently allows adding certificates.. */
1149         ok(ret, "CertAddEncodedCertificateToStore failed: %d\n", ret);
1150         /* but not commits.. */
1151         ret = pCertControlStore(store, 0, CERT_STORE_CTRL_COMMIT, NULL);
1152         ok(!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED,
1153          "Expected ERROR_CALL_NOT_IMPLEMENTED, got %08x\n", GetLastError());
1154         /* It still has certs in memory.. */
1155         cert = CertEnumCertificatesInStore(store, NULL);
1156         ok(cert != NULL, "CertEnumCertificatesInStore failed: %08x\n",
1157          GetLastError());
1158         CertFreeCertificateContext(cert);
1159         /* but the file size is still 0. */
1160         size = GetFileSize(file, NULL);
1161         ok(size == 0, "Expected size 0, got %d\n", size);
1162         CertCloseStore(store, 0);
1163     }
1164
1165     /* The create new flag is allowed.. */
1166     store = CertOpenStore(CERT_STORE_PROV_FILE, 0, 0,
1167      CERT_STORE_CREATE_NEW_FLAG, file);
1168     ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError());
1169     if (store)
1170     {
1171         /* but without the commit enable flag, commits don't happen. */
1172         ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1173          bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, NULL);
1174         ok(ret, "CertAddEncodedCertificateToStore failed: %d\n", ret);
1175         ret = pCertControlStore(store, 0, CERT_STORE_CTRL_COMMIT, NULL);
1176         ok(!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED,
1177          "Expected ERROR_CALL_NOT_IMPLEMENTED, got %08x\n", GetLastError());
1178         CertCloseStore(store, 0);
1179     }
1180     /* as is the open existing flag. */
1181     store = CertOpenStore(CERT_STORE_PROV_FILE, 0, 0,
1182      CERT_STORE_OPEN_EXISTING_FLAG, file);
1183     ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError());
1184     if (store)
1185     {
1186         /* but without the commit enable flag, commits don't happen. */
1187         ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1188          bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, NULL);
1189         ok(ret, "CertAddEncodedCertificateToStore failed: %d\n", ret);
1190         ret = pCertControlStore(store, 0, CERT_STORE_CTRL_COMMIT, NULL);
1191         ok(!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED,
1192          "Expected ERROR_CALL_NOT_IMPLEMENTED, got %08x\n", GetLastError());
1193         CertCloseStore(store, 0);
1194     }
1195     store = CertOpenStore(CERT_STORE_PROV_FILE, 0, 0,
1196      CERT_FILE_STORE_COMMIT_ENABLE_FLAG, file);
1197     ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError());
1198     if (store)
1199     {
1200         CloseHandle(file);
1201         ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1202          bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, NULL);
1203         ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
1204          GetLastError());
1205         /* with commits enabled, commit is allowed */
1206         ret = pCertControlStore(store, 0, CERT_STORE_CTRL_COMMIT, NULL);
1207         ok(ret, "CertControlStore failed: %d\n", ret);
1208         compareFile(filename, serializedStoreWithCert,
1209          sizeof(serializedStoreWithCert));
1210         CertCloseStore(store, 0);
1211     }
1212     file = CreateFileW(filename, GENERIC_READ | GENERIC_WRITE, 0, NULL,
1213      OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
1214     if (file == INVALID_HANDLE_VALUE)
1215         return;
1216     store = CertOpenStore(CERT_STORE_PROV_FILE, 0, 0,
1217      CERT_FILE_STORE_COMMIT_ENABLE_FLAG, file);
1218     ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError());
1219     if (store)
1220     {
1221         CloseHandle(file);
1222         ret = CertAddEncodedCRLToStore(store, X509_ASN_ENCODING, signedCRL,
1223          sizeof(signedCRL), CERT_STORE_ADD_ALWAYS, NULL);
1224         ok(ret, "CertAddEncodedCRLToStore failed: %08x\n", GetLastError());
1225         CertCloseStore(store, 0);
1226         compareFile(filename, serializedStoreWithCertAndCRL,
1227          sizeof(serializedStoreWithCertAndCRL));
1228     }
1229
1230     DeleteFileW(filename);
1231 }
1232
1233 static BOOL initFileFromData(LPCWSTR filename, const BYTE *pb, DWORD cb)
1234 {
1235     HANDLE file = CreateFileW(filename, GENERIC_READ | GENERIC_WRITE, 0, NULL,
1236      CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
1237     BOOL ret;
1238
1239     if (file != INVALID_HANDLE_VALUE)
1240     {
1241         DWORD written;
1242
1243         ret = WriteFile(file, pb, cb, &written, NULL);
1244         CloseHandle(file);
1245     }
1246     else
1247         ret = FALSE;
1248     return ret;
1249 }
1250 static void testFileNameStore(void)
1251 {
1252     static const WCHAR szPrefix[] = { 'c','e','r',0 };
1253     static const WCHAR szDot[] = { '.',0 };
1254     WCHAR filename[MAX_PATH];
1255     HCERTSTORE store;
1256     BOOL ret;
1257     DWORD GLE;
1258
1259     store = CertOpenStore(CERT_STORE_PROV_FILENAME_W, 0, 0, 0, NULL);
1260     GLE = GetLastError();
1261     ok(!store && (GLE == ERROR_PATH_NOT_FOUND || GLE == ERROR_INVALID_PARAMETER),
1262      "Expected ERROR_PATH_NOT_FOUND or ERROR_INVALID_PARAMETER, got %08x\n",
1263      GLE);
1264
1265     if (!GetTempFileNameW(szDot, szPrefix, 0, filename))
1266        return;
1267     DeleteFileW(filename);
1268
1269     /* The two flags are mutually exclusive */
1270     store = CertOpenStore(CERT_STORE_PROV_FILENAME_W, 0, 0,
1271      CERT_FILE_STORE_COMMIT_ENABLE_FLAG | CERT_STORE_READONLY_FLAG, filename);
1272     ok(!store && GetLastError() == E_INVALIDARG,
1273      "Expected E_INVALIDARG, got %08x\n", GetLastError());
1274
1275     /* In all of the following tests, the encoding type seems to be ignored */
1276     if (initFileFromData(filename, bigCert, sizeof(bigCert)))
1277     {
1278         PCCERT_CONTEXT cert;
1279         PCCRL_CONTEXT crl;
1280
1281         store = CertOpenStore(CERT_STORE_PROV_FILENAME_W, 0, 0,
1282          CERT_STORE_READONLY_FLAG, filename);
1283         ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError());
1284
1285         cert = CertEnumCertificatesInStore(store, NULL);
1286         ok(cert != NULL, "CertEnumCertificatesInStore failed: %08x\n",
1287          GetLastError());
1288         cert = CertEnumCertificatesInStore(store, cert);
1289         ok(!cert, "Expected only one cert\n");
1290         if (pCertEnumCRLsInStore)
1291         {
1292             crl = pCertEnumCRLsInStore(store, NULL);
1293             ok(!crl, "Expected no CRLs\n");
1294         }
1295
1296         CertCloseStore(store, 0);
1297         DeleteFileW(filename);
1298     }
1299     if (initFileFromData(filename, serializedStoreWithCert,
1300      sizeof(serializedStoreWithCert)))
1301     {
1302         PCCERT_CONTEXT cert;
1303         PCCRL_CONTEXT crl;
1304
1305         store = CertOpenStore(CERT_STORE_PROV_FILENAME_W, 0, 0,
1306          CERT_STORE_READONLY_FLAG, filename);
1307         ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError());
1308
1309         cert = CertEnumCertificatesInStore(store, NULL);
1310         ok(cert != NULL, "CertEnumCertificatesInStore failed: %08x\n",
1311          GetLastError());
1312         cert = CertEnumCertificatesInStore(store, cert);
1313         ok(!cert, "Expected only one cert\n");
1314         if (pCertEnumCRLsInStore)
1315         {
1316             crl = pCertEnumCRLsInStore(store, NULL);
1317             ok(!crl, "Expected no CRLs\n");
1318         }
1319
1320         CertCloseStore(store, 0);
1321         DeleteFileW(filename);
1322     }
1323     if (initFileFromData(filename, serializedStoreWithCertAndCRL,
1324      sizeof(serializedStoreWithCertAndCRL)))
1325     {
1326         PCCERT_CONTEXT cert;
1327         PCCRL_CONTEXT crl;
1328
1329         store = CertOpenStore(CERT_STORE_PROV_FILENAME_W, 0, 0,
1330          CERT_STORE_READONLY_FLAG, filename);
1331         ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError());
1332
1333         cert = CertEnumCertificatesInStore(store, NULL);
1334         ok(cert != NULL, "CertEnumCertificatesInStore failed: %08x\n",
1335          GetLastError());
1336         cert = CertEnumCertificatesInStore(store, cert);
1337         ok(!cert, "Expected only one cert\n");
1338         if (pCertEnumCRLsInStore)
1339         {
1340             crl = pCertEnumCRLsInStore(store, NULL);
1341             ok(crl != NULL, "CertEnumCRLsInStore failed: %08x\n", GetLastError());
1342             crl = pCertEnumCRLsInStore(store, crl);
1343             ok(!crl, "Expected only one CRL\n");
1344         }
1345
1346         CertCloseStore(store, 0);
1347         /* Don't delete it this time, the next test uses it */
1348     }
1349     /* Now that the file exists, we can open it read-only */
1350     store = CertOpenStore(CERT_STORE_PROV_FILENAME_W, 0, 0,
1351      CERT_STORE_READONLY_FLAG, filename);
1352     ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError());
1353     CertCloseStore(store, 0);
1354     DeleteFileW(filename);
1355
1356     store = CertOpenStore(CERT_STORE_PROV_FILENAME_W, 0, 0,
1357      CERT_FILE_STORE_COMMIT_ENABLE_FLAG | CERT_STORE_CREATE_NEW_FLAG, filename);
1358     ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError());
1359     if (store)
1360     {
1361         ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1362          bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, NULL);
1363         ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
1364          GetLastError());
1365         CertCloseStore(store, 0);
1366         compareFile(filename, serializedStoreWithCert,
1367          sizeof(serializedStoreWithCert));
1368     }
1369     store = CertOpenStore(CERT_STORE_PROV_FILENAME_W, 0, 0,
1370      CERT_FILE_STORE_COMMIT_ENABLE_FLAG, filename);
1371     ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError());
1372     if (store)
1373     {
1374         ret = CertAddEncodedCRLToStore(store, X509_ASN_ENCODING,
1375          signedCRL, sizeof(signedCRL), CERT_STORE_ADD_ALWAYS, NULL);
1376         ok(ret, "CertAddEncodedCRLToStore failed: %08x\n", GetLastError());
1377         CertCloseStore(store, 0);
1378         compareFile(filename, serializedStoreWithCertAndCRL,
1379          sizeof(serializedStoreWithCertAndCRL));
1380     }
1381     DeleteFileW(filename);
1382 }
1383
1384 static const BYTE signedContent[] = {
1385 0x30,0x81,0xb2,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,0xa0,
1386 0x81,0xa4,0x30,0x81,0xa1,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,
1387 0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x13,0x06,0x09,0x2a,0x86,
1388 0x48,0x86,0xf7,0x0d,0x01,0x07,0x01,0xa0,0x06,0x04,0x04,0x01,0x02,0x03,0x04,
1389 0x31,0x77,0x30,0x75,0x02,0x01,0x01,0x30,0x1a,0x30,0x15,0x31,0x13,0x30,0x11,
1390 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
1391 0x67,0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,
1392 0x02,0x05,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04,0x40,0x81,0xa6,0x70,
1393 0xb3,0xef,0x59,0xd1,0x66,0xd1,0x9b,0xc0,0x9a,0xb6,0x9a,0x5e,0x6d,0x6f,0x6d,
1394 0x0d,0x59,0xa9,0xaa,0x6e,0xe9,0x2c,0xa0,0x1e,0xee,0xc2,0x60,0xbc,0x59,0xbe,
1395 0x3f,0x63,0x06,0x8d,0xc9,0x11,0x1d,0x23,0x64,0x92,0xef,0x2e,0xfc,0x57,0x29,
1396 0xa4,0xaf,0xe0,0xee,0x93,0x19,0x39,0x51,0xe4,0x44,0xb8,0x0b,0x28,0xf4,0xa8,
1397 0x0d };
1398 static const BYTE signedWithCertAndCrlBareContent[] = {
1399 0x30,0x82,0x01,0x4f,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,0x86,
1400 0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x13,0x06,0x09,0x2a,0x86,0x48,
1401 0x86,0xf7,0x0d,0x01,0x07,0x01,0xa0,0x06,0x04,0x04,0x01,0x02,0x03,0x04,0xa0,
1402 0x7c,0x30,0x7a,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,
1403 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
1404 0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,
1405 0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
1406 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,
1407 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
1408 0x67,0x00,0x30,0x07,0x30,0x02,0x06,0x00,0x03,0x01,0x00,0xa3,0x16,0x30,0x14,
1409 0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,
1410 0x01,0xff,0x02,0x01,0x01,0xa1,0x2e,0x30,0x2c,0x30,0x02,0x06,0x00,0x30,0x15,
1411 0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,
1412 0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
1413 0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x31,0x77,0x30,0x75,0x02,0x01,0x01,
1414 0x30,0x1a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,
1415 0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x02,0x01,0x01,0x30,0x0c,
1416 0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x04,0x06,
1417 0x00,0x05,0x00,0x04,0x40,0x81,0xa6,0x70,0xb3,0xef,0x59,0xd1,0x66,0xd1,0x9b,
1418 0xc0,0x9a,0xb6,0x9a,0x5e,0x6d,0x6f,0x6d,0x0d,0x59,0xa9,0xaa,0x6e,0xe9,0x2c,
1419 0xa0,0x1e,0xee,0xc2,0x60,0xbc,0x59,0xbe,0x3f,0x63,0x06,0x8d,0xc9,0x11,0x1d,
1420 0x23,0x64,0x92,0xef,0x2e,0xfc,0x57,0x29,0xa4,0xaf,0xe0,0xee,0x93,0x19,0x39,
1421 0x51,0xe4,0x44,0xb8,0x0b,0x28,0xf4,0xa8,0x0d };
1422 static const BYTE hashContent[] = {
1423 0x30,0x47,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x05,0xa0,0x3a,
1424 0x30,0x38,0x02,0x01,0x00,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,
1425 0x02,0x05,0x05,0x00,0x30,0x13,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
1426 0x07,0x01,0xa0,0x06,0x04,0x04,0x01,0x02,0x03,0x04,0x04,0x10,0x08,0xd6,0xc0,
1427 0x5a,0x21,0x51,0x2a,0x79,0xa1,0xdf,0xeb,0x9d,0x2a,0x8f,0x26,0x2f };
1428 static const BYTE hashBareContent[] = {
1429 0x30,0x38,0x02,0x01,0x00,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,
1430 0x02,0x05,0x05,0x00,0x30,0x13,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
1431 0x07,0x01,0xa0,0x06,0x04,0x04,0x01,0x02,0x03,0x04,0x04,0x10,0x08,0xd6,0xc0,
1432 0x5a,0x21,0x51,0x2a,0x79,0xa1,0xdf,0xeb,0x9d,0x2a,0x8f,0x26,0x2f };
1433
1434 static void testMessageStore(void)
1435 {
1436     HCERTSTORE store;
1437     HCRYPTMSG msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL,
1438      NULL);
1439     CRYPT_DATA_BLOB blob = { sizeof(signedWithCertAndCrlBareContent),
1440      (LPBYTE)signedWithCertAndCrlBareContent };
1441     DWORD count, size;
1442     BOOL ret;
1443
1444     /* Crashes
1445     store = CertOpenStore(CERT_STORE_PROV_MSG, 0, 0, 0, NULL);
1446      */
1447     SetLastError(0xdeadbeef);
1448     store = CertOpenStore(CERT_STORE_PROV_MSG, 0, 0, 0, msg);
1449     ok(!store && GetLastError() == CRYPT_E_INVALID_MSG_TYPE,
1450      "Expected CRYPT_E_INVALID_MSG_TYPE, got %08x\n", GetLastError());
1451     CryptMsgUpdate(msg, signedContent, sizeof(signedContent), TRUE);
1452     store = CertOpenStore(CERT_STORE_PROV_MSG, 0, 0, 0, msg);
1453     ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError());
1454     if (store)
1455     {
1456         PCCERT_CONTEXT cert = NULL;
1457         PCCRL_CONTEXT crl = NULL;
1458
1459         count = 0;
1460         do {
1461             cert = CertEnumCertificatesInStore(store, cert);
1462             if (cert)
1463                 count++;
1464         } while (cert);
1465         ok(count == 0, "Expected 0 certificates, got %d\n", count);
1466
1467         if (pCertEnumCRLsInStore)
1468         {
1469             count = 0;
1470             do {
1471                 crl = pCertEnumCRLsInStore(store, crl);
1472                 if (crl)
1473                     count++;
1474             } while (crl);
1475             ok(count == 0, "Expected 0 CRLs, got %d\n", count);
1476         }
1477
1478         /* Can add certs to a message store */
1479         ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1480          bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, NULL);
1481         ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
1482          GetLastError());
1483         count = 0;
1484         do {
1485             cert = CertEnumCertificatesInStore(store, cert);
1486             if (cert)
1487                 count++;
1488         } while (cert);
1489         ok(count == 1, "Expected 1 certificate, got %d\n", count);
1490
1491         CertCloseStore(store, 0);
1492     }
1493     /* but the added certs weren't actually added to the message */
1494     size = sizeof(count);
1495     ret = CryptMsgGetParam(msg, CMSG_CERT_COUNT_PARAM, 0, &count, &size);
1496     ok(ret, "CryptMsgGetParam failed: %08x\n", GetLastError());
1497     ok(count == 0, "Expected 0 certificates, got %d\n", count);
1498     CryptMsgClose(msg);
1499
1500     /* Crashes
1501     store = CertOpenStore(CERT_STORE_PROV_PKCS7, 0, 0, 0, NULL);
1502      */
1503     store = CertOpenStore(CERT_STORE_PROV_PKCS7, 0, 0, 0, &blob);
1504     ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError());
1505     if (store)
1506     {
1507         DWORD count = 0;
1508         PCCERT_CONTEXT cert = NULL;
1509         PCCRL_CONTEXT crl = NULL;
1510
1511         do {
1512             cert = CertEnumCertificatesInStore(store, cert);
1513             if (cert)
1514                 count++;
1515         } while (cert);
1516         ok(count == 1, "Expected 1 certificate, got %d\n", count);
1517
1518         if (pCertEnumCRLsInStore)
1519         {
1520             count = 0;
1521             do {
1522                 crl = pCertEnumCRLsInStore(store, crl);
1523                 if (crl)
1524                     count++;
1525             } while (crl);
1526             ok(count == 1, "Expected 1 CRL, got %d\n", count);
1527         }
1528         CertCloseStore(store, 0);
1529     }
1530     /* Encoding appears to be ignored */
1531     store = CertOpenStore(CERT_STORE_PROV_PKCS7, X509_ASN_ENCODING, 0, 0,
1532      &blob);
1533     ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError());
1534     if (store)
1535         CertCloseStore(store, 0);
1536     /* Messages other than signed messages aren't allowed */
1537     blob.cbData = sizeof(hashContent);
1538     blob.pbData = (LPBYTE)hashContent;
1539     SetLastError(0xdeadbeef);
1540     store = CertOpenStore(CERT_STORE_PROV_PKCS7, 0, 0, 0, &blob);
1541     ok(!store && GetLastError() == CRYPT_E_INVALID_MSG_TYPE,
1542      "Expected CRYPT_E_INVALID_MSG_TYPE, got %08x\n", GetLastError());
1543     blob.cbData = sizeof(hashBareContent);
1544     blob.pbData = (LPBYTE)hashBareContent;
1545     SetLastError(0xdeadbeef);
1546     store = CertOpenStore(CERT_STORE_PROV_PKCS7, 0, 0, 0, &blob);
1547     ok(!store && GetLastError() == CRYPT_E_ASN1_BADTAG,
1548      "Expected CRYPT_E_ASN1_BADTAG, got %08x\n", GetLastError());
1549 }
1550
1551 static void testCertOpenSystemStore(void)
1552 {
1553     HCERTSTORE store;
1554
1555     store = CertOpenSystemStoreW(0, NULL);
1556     ok(!store && GetLastError() == E_INVALIDARG,
1557      "Expected E_INVALIDARG, got %08x\n", GetLastError());
1558     /* This succeeds, and on WinXP at least, the Bogus key is created under
1559      * HKCU (but not under HKLM, even when run as an administrator.)
1560      */
1561     store = CertOpenSystemStoreW(0, BogusW);
1562     ok(store != 0, "CertOpenSystemStore failed: %08x\n", GetLastError());
1563     if (store)
1564         CertCloseStore(store, 0);
1565     /* Delete it so other tests succeed next time around */
1566     store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0,
1567      CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_DELETE_FLAG, BogusW);
1568     RegDeleteKeyW(HKEY_CURRENT_USER, BogusPathW);
1569 }
1570
1571 struct EnumSystemStoreInfo
1572 {
1573     BOOL  goOn;
1574     DWORD storeCount;
1575 };
1576
1577 static BOOL CALLBACK enumSystemStoreCB(const void *systemStore, DWORD dwFlags,
1578  PCERT_SYSTEM_STORE_INFO pStoreInfo, void *pvReserved, void *pvArg)
1579 {
1580     struct EnumSystemStoreInfo *info = (struct EnumSystemStoreInfo *)pvArg;
1581
1582     info->storeCount++;
1583     return info->goOn;
1584 }
1585
1586 static void testCertEnumSystemStore(void)
1587 {
1588     BOOL ret;
1589     struct EnumSystemStoreInfo info = { FALSE, 0 };
1590
1591     if (!pCertEnumSystemStore)
1592     {
1593         skip("CertEnumSystemStore() is not available\n");
1594         return;
1595     }
1596
1597     SetLastError(0xdeadbeef);
1598     ret = pCertEnumSystemStore(0, NULL, NULL, NULL);
1599     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
1600      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
1601     /* Crashes
1602     ret = pCertEnumSystemStore(CERT_SYSTEM_STORE_LOCAL_MACHINE, NULL, NULL,
1603      NULL);
1604      */
1605
1606     SetLastError(0xdeadbeef);
1607     ret = pCertEnumSystemStore(CERT_SYSTEM_STORE_LOCAL_MACHINE, NULL, &info,
1608      enumSystemStoreCB);
1609     /* Callback returning FALSE stops enumeration */
1610     ok(!ret, "Expected CertEnumSystemStore to stop\n");
1611     ok(info.storeCount == 0 || info.storeCount == 1,
1612      "Expected 0 or 1 stores\n");
1613
1614     info.goOn = TRUE;
1615     info.storeCount = 0;
1616     ret = pCertEnumSystemStore(CERT_SYSTEM_STORE_LOCAL_MACHINE, NULL, &info,
1617      enumSystemStoreCB);
1618     ok(ret, "CertEnumSystemStore failed: %08x\n", GetLastError());
1619     /* There should always be at least My, Root, and CA stores */
1620     ok(info.storeCount == 0 || info.storeCount >= 3,
1621      "Expected at least 3 stores\n");
1622 }
1623
1624 static void testStoreProperty(void)
1625 {
1626     HCERTSTORE store;
1627     BOOL ret;
1628     DWORD propID, size = 0, state;
1629     CRYPT_DATA_BLOB blob;
1630
1631     if (!pCertGetStoreProperty || !pCertSetStoreProperty)
1632     {
1633         skip("CertGet/SetStoreProperty() is not available\n");
1634         return;
1635     }
1636
1637     /* Crash
1638     ret = pCertGetStoreProperty(NULL, 0, NULL, NULL);
1639     ret = pCertGetStoreProperty(NULL, 0, NULL, &size);
1640     ret = pCertGetStoreProperty(store, 0, NULL, NULL);
1641      */
1642
1643     store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
1644      CERT_STORE_CREATE_NEW_FLAG, NULL);
1645     /* Check a missing prop ID */
1646     SetLastError(0xdeadbeef);
1647     ret = pCertGetStoreProperty(store, 0, NULL, &size);
1648     ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
1649      "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
1650     /* Contrary to MSDN, CERT_ACCESS_STATE_PROP_ID is supported for stores.. */
1651     size = sizeof(state);
1652     ret = pCertGetStoreProperty(store, CERT_ACCESS_STATE_PROP_ID, &state, &size);
1653     ok(ret, "CertGetStoreProperty failed for CERT_ACCESS_STATE_PROP_ID: %08x\n",
1654      GetLastError());
1655     ok(!state, "Expected a non-persisted store\n");
1656     /* and CERT_STORE_LOCALIZED_NAME_PROP_ID isn't supported by default. */
1657     size = 0;
1658     ret = pCertGetStoreProperty(store, CERT_STORE_LOCALIZED_NAME_PROP_ID, NULL,
1659      &size);
1660     ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
1661      "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
1662     /* Delete an arbitrary property on a store */
1663     ret = pCertSetStoreProperty(store, CERT_FIRST_USER_PROP_ID, 0, NULL);
1664     ok(ret, "CertSetStoreProperty failed: %08x\n", GetLastError());
1665     /* Set an arbitrary property on a store */
1666     blob.pbData = (LPBYTE)&state;
1667     blob.cbData = sizeof(state);
1668     ret = pCertSetStoreProperty(store, CERT_FIRST_USER_PROP_ID, 0, &blob);
1669     ok(ret, "CertSetStoreProperty failed: %08x\n", GetLastError());
1670     /* Get an arbitrary property that's been set */
1671     ret = pCertGetStoreProperty(store, CERT_FIRST_USER_PROP_ID, NULL, &size);
1672     ok(ret, "CertGetStoreProperty failed: %08x\n", GetLastError());
1673     ok(size == sizeof(state), "Unexpected data size %d\n", size);
1674     ret = pCertGetStoreProperty(store, CERT_FIRST_USER_PROP_ID, &propID, &size);
1675     ok(ret, "CertGetStoreProperty failed: %08x\n", GetLastError());
1676     ok(propID == state, "CertGetStoreProperty got the wrong value\n");
1677     /* Delete it again */
1678     ret = pCertSetStoreProperty(store, CERT_FIRST_USER_PROP_ID, 0, NULL);
1679     ok(ret, "CertSetStoreProperty failed: %08x\n", GetLastError());
1680     /* And check that it's missing */
1681     SetLastError(0xdeadbeef);
1682     ret = pCertGetStoreProperty(store, CERT_FIRST_USER_PROP_ID, NULL, &size);
1683     ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
1684      "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
1685     CertCloseStore(store, 0);
1686
1687     /* Recheck on the My store.. */
1688     store = CertOpenSystemStoreW(0, MyW);
1689     size = sizeof(state);
1690     ret = pCertGetStoreProperty(store, CERT_ACCESS_STATE_PROP_ID, &state, &size);
1691     ok(ret, "CertGetStoreProperty failed for CERT_ACCESS_STATE_PROP_ID: %08x\n",
1692      GetLastError());
1693     ok(state, "Expected a persisted store\n");
1694     SetLastError(0xdeadbeef);
1695     size = 0;
1696     ret = pCertGetStoreProperty(store, CERT_STORE_LOCALIZED_NAME_PROP_ID, NULL,
1697      &size);
1698     ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
1699      "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
1700     CertCloseStore(store, 0);
1701 }
1702
1703 static void testAddSerialized(void)
1704 {
1705     BOOL ret;
1706     HCERTSTORE store;
1707     BYTE buf[sizeof(struct CertPropIDHeader) * 2 + 20 + sizeof(bigCert)] =
1708      { 0 };
1709     BYTE hash[20];
1710     struct CertPropIDHeader *hdr;
1711     PCCERT_CONTEXT context;
1712
1713     ret = CertAddSerializedElementToStore(0, NULL, 0, 0, 0, 0, NULL, NULL);
1714     ok(!ret && GetLastError() == ERROR_END_OF_MEDIA,
1715      "Expected ERROR_END_OF_MEDIA, got %08x\n", GetLastError());
1716
1717     store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
1718      CERT_STORE_CREATE_NEW_FLAG, NULL);
1719     ok(store != 0, "CertOpenStore failed: %08x\n", GetLastError());
1720
1721     ret = CertAddSerializedElementToStore(store, NULL, 0, 0, 0, 0, NULL, NULL);
1722     ok(!ret && GetLastError() == ERROR_END_OF_MEDIA,
1723      "Expected ERROR_END_OF_MEDIA, got %08x\n", GetLastError());
1724
1725     /* Test with an empty property */
1726     hdr = (struct CertPropIDHeader *)buf;
1727     hdr->propID = CERT_CERT_PROP_ID;
1728     hdr->unknown1 = 1;
1729     hdr->cb = 0;
1730     ret = CertAddSerializedElementToStore(store, buf, sizeof(buf), 0, 0, 0,
1731      NULL, NULL);
1732     ok(!ret && GetLastError() == E_INVALIDARG,
1733      "Expected E_INVALIDARG, got %08x\n", GetLastError());
1734     /* Test with a bad size in property header */
1735     hdr->cb = sizeof(bigCert) - 1;
1736     memcpy(buf + sizeof(struct CertPropIDHeader), bigCert, sizeof(bigCert));
1737     ret = CertAddSerializedElementToStore(store, buf, sizeof(buf), 0, 0, 0,
1738      NULL, NULL);
1739     ok(!ret && GetLastError() == E_INVALIDARG,
1740      "Expected E_INVALIDARG, got %08x\n", GetLastError());
1741     ret = CertAddSerializedElementToStore(store, buf,
1742      sizeof(struct CertPropIDHeader) + sizeof(bigCert), 0, 0, 0, NULL,
1743      NULL);
1744     ok(!ret && GetLastError() == E_INVALIDARG,
1745      "Expected E_INVALIDARG, got %08x\n", GetLastError());
1746     ret = CertAddSerializedElementToStore(store, buf,
1747      sizeof(struct CertPropIDHeader) + sizeof(bigCert), CERT_STORE_ADD_NEW,
1748      0, 0, NULL, NULL);
1749     ok(!ret && GetLastError() == E_INVALIDARG,
1750      "Expected E_INVALIDARG, got %08x\n", GetLastError());
1751     /* Kosher size in property header, but no context type */
1752     hdr->cb = sizeof(bigCert);
1753     ret = CertAddSerializedElementToStore(store, buf, sizeof(buf), 0, 0, 0,
1754      NULL, NULL);
1755     ok(!ret && GetLastError() == E_INVALIDARG,
1756      "Expected E_INVALIDARG, got %08x\n", GetLastError());
1757     ret = CertAddSerializedElementToStore(store, buf,
1758      sizeof(struct CertPropIDHeader) + sizeof(bigCert), 0, 0, 0, NULL,
1759      NULL);
1760     ok(!ret && GetLastError() == E_INVALIDARG,
1761      "Expected E_INVALIDARG, got %08x\n", GetLastError());
1762     ret = CertAddSerializedElementToStore(store, buf,
1763      sizeof(struct CertPropIDHeader) + sizeof(bigCert), CERT_STORE_ADD_NEW,
1764      0, 0, NULL, NULL);
1765     ok(!ret && GetLastError() == E_INVALIDARG,
1766      "Expected E_INVALIDARG, got %08x\n", GetLastError());
1767     /* With a bad context type */
1768     ret = CertAddSerializedElementToStore(store, buf, sizeof(buf), 0, 0, 
1769      CERT_STORE_CRL_CONTEXT_FLAG, NULL, NULL);
1770     ok(!ret && GetLastError() == E_INVALIDARG,
1771      "Expected E_INVALIDARG, got %08x\n", GetLastError());
1772     ret = CertAddSerializedElementToStore(store, buf,
1773      sizeof(struct CertPropIDHeader) + sizeof(bigCert), 0, 0, 
1774      CERT_STORE_CRL_CONTEXT_FLAG, NULL, NULL);
1775     ok(!ret && GetLastError() == E_INVALIDARG,
1776      "Expected E_INVALIDARG, got %08x\n", GetLastError());
1777     ret = CertAddSerializedElementToStore(store, buf,
1778      sizeof(struct CertPropIDHeader) + sizeof(bigCert), CERT_STORE_ADD_NEW,
1779      0, CERT_STORE_CRL_CONTEXT_FLAG, NULL, NULL);
1780     ok(!ret && GetLastError() == E_INVALIDARG,
1781      "Expected E_INVALIDARG, got %08x\n", GetLastError());
1782     /* Bad unknown field, good type */
1783     hdr->unknown1 = 2;
1784     ret = CertAddSerializedElementToStore(store, buf, sizeof(buf), 0, 0, 
1785      CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL, NULL);
1786     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
1787      "Expected ERROR_FILE_NOT_FOUND got %08x\n", GetLastError());
1788     ret = CertAddSerializedElementToStore(store, buf,
1789      sizeof(struct CertPropIDHeader) + sizeof(bigCert), 0, 0, 
1790      CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL, NULL);
1791     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
1792      "Expected ERROR_FILE_NOT_FOUND got %08x\n", GetLastError());
1793     ret = CertAddSerializedElementToStore(store, buf,
1794      sizeof(struct CertPropIDHeader) + sizeof(bigCert), CERT_STORE_ADD_NEW,
1795      0, CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL, NULL);
1796     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
1797      "Expected ERROR_FILE_NOT_FOUND got %08x\n", GetLastError());
1798     /* Most everything okay, but bad add disposition */
1799     hdr->unknown1 = 1;
1800     /* This crashes
1801     ret = CertAddSerializedElementToStore(store, buf, sizeof(buf), 0, 0, 
1802      CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL, NULL);
1803      * as does this
1804     ret = CertAddSerializedElementToStore(store, buf,
1805      sizeof(struct CertPropIDHeader) + sizeof(bigCert), 0, 0, 
1806      CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL, NULL);
1807      */
1808     /* Everything okay, but buffer's too big */
1809     ret = CertAddSerializedElementToStore(store, buf, sizeof(buf),
1810      CERT_STORE_ADD_NEW, 0, CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL, NULL);
1811     ok(ret, "CertAddSerializedElementToStore failed: %08x\n", GetLastError());
1812     /* Everything okay, check it's not re-added */
1813     ret = CertAddSerializedElementToStore(store, buf,
1814      sizeof(struct CertPropIDHeader) + sizeof(bigCert), CERT_STORE_ADD_NEW,
1815      0, CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL, NULL);
1816     ok(!ret && GetLastError() == CRYPT_E_EXISTS,
1817      "Expected CRYPT_E_EXISTS, got %08x\n", GetLastError());
1818
1819     context = CertEnumCertificatesInStore(store, NULL);
1820     ok(context != NULL, "Expected a cert\n");
1821     if (context)
1822         CertDeleteCertificateFromStore(context);
1823
1824     /* Try adding with a bogus hash.  Oddly enough, it succeeds, and the hash,
1825      * when queried, is the real hash rather than the bogus hash.
1826      */
1827     hdr = (struct CertPropIDHeader *)(buf + sizeof(struct CertPropIDHeader) +
1828      sizeof(bigCert));
1829     hdr->propID = CERT_HASH_PROP_ID;
1830     hdr->unknown1 = 1;
1831     hdr->cb = sizeof(hash);
1832     memset(hash, 0xc, sizeof(hash));
1833     memcpy((LPBYTE)hdr + sizeof(struct CertPropIDHeader), hash, sizeof(hash));
1834     ret = CertAddSerializedElementToStore(store, buf, sizeof(buf),
1835      CERT_STORE_ADD_NEW, 0, CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL,
1836      (const void **)&context);
1837     ok(ret, "CertAddSerializedElementToStore failed: %08x\n", GetLastError());
1838     if (context)
1839     {
1840         BYTE hashVal[20], realHash[20];
1841         DWORD size = sizeof(hashVal);
1842
1843         ret = CryptHashCertificate(0, 0, 0, bigCert, sizeof(bigCert),
1844          realHash, &size);
1845         ok(ret, "CryptHashCertificate failed: %08x\n", GetLastError());
1846         ret = CertGetCertificateContextProperty(context, CERT_HASH_PROP_ID,
1847          hashVal, &size);
1848         ok(ret, "CertGetCertificateContextProperty failed: %08x\n",
1849          GetLastError());
1850         ok(!memcmp(hashVal, realHash, size), "Unexpected hash\n");
1851         CertFreeCertificateContext(context);
1852     }
1853
1854     CertCloseStore(store, 0);
1855 }
1856
1857 static DWORD countCertsInStore(HCERTSTORE store)
1858 {
1859     PCCERT_CONTEXT cert = NULL;
1860     DWORD certs = 0;
1861
1862     do {
1863         cert = CertEnumCertificatesInStore(store, cert);
1864         if (cert)
1865             certs++;
1866     } while (cert);
1867     return certs;
1868 }
1869
1870 static DWORD countCRLsInStore(HCERTSTORE store)
1871 {
1872     PCCRL_CONTEXT crl = NULL;
1873     DWORD crls = 0;
1874
1875     do {
1876         crl = pCertEnumCRLsInStore(store, crl);
1877         if (crl)
1878             crls++;
1879     } while (crl);
1880     return crls;
1881 }
1882
1883 static void test_I_UpdateStore(void)
1884 {
1885     HMODULE lib = GetModuleHandleA("crypt32");
1886     BOOL (WINAPI *pI_CertUpdatestore)(HCERTSTORE, HCERTSTORE, DWORD, DWORD) =
1887      (void *)GetProcAddress(lib, "I_CertUpdateStore");
1888     BOOL ret;
1889     HCERTSTORE store1, store2;
1890     PCCERT_CONTEXT cert;
1891     DWORD certs;
1892
1893     if (!pI_CertUpdatestore)
1894     {
1895         skip("No I_CertUpdateStore\n");
1896         return;
1897     }
1898     store1 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
1899      CERT_STORE_CREATE_NEW_FLAG, NULL);
1900     store2 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
1901      CERT_STORE_CREATE_NEW_FLAG, NULL);
1902
1903     /* Crash
1904     ret = pI_CertUpdatestore(NULL, NULL, 0, 0);
1905     ret = pI_CertUpdatestore(store1, NULL, 0, 0);
1906     ret = pI_CertUpdatestore(NULL, store2, 0, 0);
1907      */
1908     ret = pI_CertUpdatestore(store1, store2, 0, 0);
1909     ok(ret, "I_CertUpdateStore failed: %08x\n", GetLastError());
1910
1911     CertAddEncodedCertificateToStore(store2, X509_ASN_ENCODING, bigCert,
1912      sizeof(bigCert), CERT_STORE_ADD_ALWAYS, &cert);
1913     /* I_CertUpdateStore adds the contexts from store2 to store1 */
1914     ret = pI_CertUpdatestore(store1, store2, 0, 0);
1915     ok(ret, "I_CertUpdateStore failed: %08x\n", GetLastError());
1916     certs = countCertsInStore(store1);
1917     ok(certs == 1, "Expected 1 cert, got %d\n", certs);
1918     /* Calling it a second time has no effect */
1919     ret = pI_CertUpdatestore(store1, store2, 0, 0);
1920     ok(ret, "I_CertUpdateStore failed: %08x\n", GetLastError());
1921     certs = countCertsInStore(store1);
1922     ok(certs == 1, "Expected 1 cert, got %d\n", certs);
1923
1924     /* The last parameters to I_CertUpdateStore appear to be ignored */
1925     ret = pI_CertUpdatestore(store1, store2, 1, 0);
1926     ok(ret, "I_CertUpdateStore failed: %08x\n", GetLastError());
1927     ret = pI_CertUpdatestore(store1, store2, 0, 1);
1928     ok(ret, "I_CertUpdateStore failed: %08x\n", GetLastError());
1929
1930     CertAddEncodedCRLToStore(store2, X509_ASN_ENCODING, signedCRL,
1931      sizeof(signedCRL), CERT_STORE_ADD_ALWAYS, NULL);
1932
1933     /* I_CertUpdateStore also adds the CRLs from store2 to store1 */
1934     ret = pI_CertUpdatestore(store1, store2, 0, 0);
1935     ok(ret, "I_CertUpdateStore failed: %08x\n", GetLastError());
1936     certs = countCertsInStore(store1);
1937     ok(certs == 1, "Expected 1 cert, got %d\n", certs);
1938     if (pCertEnumCRLsInStore)
1939     {
1940         certs = countCRLsInStore(store1);
1941         ok(certs == 1, "Expected 1 CRL, got %d\n", certs);
1942     }
1943
1944     CertDeleteCertificateFromStore(cert);
1945     /* If a context is deleted from store2, I_CertUpdateStore deletes it
1946      * from store1
1947      */
1948     ret = pI_CertUpdatestore(store1, store2, 0, 0);
1949     ok(ret, "I_CertUpdateStore failed: %08x\n", GetLastError());
1950     certs = countCertsInStore(store1);
1951     ok(certs == 0, "Expected 0 certs, got %d\n", certs);
1952
1953     CertFreeCertificateContext(cert);
1954     CertCloseStore(store1, 0);
1955     CertCloseStore(store2, 0);
1956 }
1957
1958 START_TEST(store)
1959 {
1960     HMODULE hdll;
1961
1962     hdll = GetModuleHandleA("Crypt32.dll");
1963     pCertAddStoreToCollection = (void*)GetProcAddress(hdll, "CertAddStoreToCollection");
1964     pCertControlStore = (void*)GetProcAddress(hdll, "CertControlStore");
1965     pCertEnumCRLsInStore = (void*)GetProcAddress(hdll, "CertEnumCRLsInStore");
1966     pCertEnumSystemStore = (void*)GetProcAddress(hdll, "CertEnumSystemStore");
1967     pCertGetStoreProperty = (void*)GetProcAddress(hdll, "CertGetStoreProperty");
1968     pCertRemoveStoreFromCollection = (void*)GetProcAddress(hdll, "CertRemoveStoreFromCollection");
1969     pCertSetStoreProperty = (void*)GetProcAddress(hdll, "CertSetStoreProperty");
1970
1971     /* various combinations of CertOpenStore */
1972     testMemStore();
1973     testCollectionStore();
1974     testRegStore();
1975     testSystemRegStore();
1976     testSystemStore();
1977     testFileStore();
1978     testFileNameStore();
1979     testMessageStore();
1980
1981     testCertOpenSystemStore();
1982     testCertEnumSystemStore();
1983     testStoreProperty();
1984
1985     testAddSerialized();
1986
1987     test_I_UpdateStore();
1988 }