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