crypt32/tests: Test an otherwise unused return value.
[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 compareFile(LPCWSTR filename, const BYTE *pb, DWORD cb)
281 {
282     HANDLE h;
283     BYTE buf[200];
284     BOOL ret;
285     DWORD cbRead = 0, totalRead = 0;
286
287     h = CreateFileW(filename, GENERIC_READ, 0, NULL, OPEN_EXISTING,
288      FILE_ATTRIBUTE_NORMAL, NULL);
289     if (h == INVALID_HANDLE_VALUE)
290         return;
291     do {
292         ret = ReadFile(h, buf, sizeof(buf), &cbRead, NULL);
293         if (ret && cbRead)
294         {
295             ok(totalRead + cbRead <= cb, "Expected total count %d, see %d\n",
296              cb, totalRead + cbRead);
297             ok(!memcmp(pb + totalRead, buf, cbRead),
298              "Unexpected data in file\n");
299             totalRead += cbRead;
300         }
301     } while (ret && cbRead);
302     CloseHandle(h);
303 }
304
305 static const BYTE serializedStoreWithCert[] = {
306  0x00,0x00,0x00,0x00,0x43,0x45,0x52,0x54,0x20,0x00,0x00,0x00,0x01,0x00,0x00,
307  0x00,0x7c,0x00,0x00,0x00,0x30,0x7a,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,
308  0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,
309  0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,
310  0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,
311  0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,
312  0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,
313  0x20,0x4c,0x61,0x6e,0x67,0x00,0x30,0x07,0x30,0x02,0x06,0x00,0x03,0x01,0x00,
314  0xa3,0x16,0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,
315  0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,
316  0x00,0x00,0x00,0x00,0x00,0x00 };
317
318 static void testCollectionStore(void)
319 {
320     HCERTSTORE store1, store2, collection, collection2;
321     PCCERT_CONTEXT context;
322     BOOL ret;
323     static const WCHAR szPrefix[] = { 'c','e','r',0 };
324     static const WCHAR szDot[] = { '.',0 };
325     WCHAR filename[MAX_PATH];
326     HANDLE file;
327
328     if (!pCertAddStoreToCollection)
329     {
330         win_skip("CertAddStoreToCollection() is not available\n");
331         return;
332     }
333
334     collection = CertOpenStore(CERT_STORE_PROV_COLLECTION, 0, 0,
335      CERT_STORE_CREATE_NEW_FLAG, NULL);
336
337     /* Try adding a cert to any empty collection */
338     ret = CertAddEncodedCertificateToStore(collection, X509_ASN_ENCODING,
339      bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, NULL);
340     ok(!ret && GetLastError() == E_ACCESSDENIED,
341      "Expected E_ACCESSDENIED, got %08x\n", GetLastError());
342
343     /* Create and add a cert to a memory store */
344     store1 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
345      CERT_STORE_CREATE_NEW_FLAG, NULL);
346     ret = CertAddEncodedCertificateToStore(store1, X509_ASN_ENCODING,
347      bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, NULL);
348     ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n", GetLastError());
349     /* Add the memory store to the collection, without allowing adding */
350     ret = pCertAddStoreToCollection(collection, store1, 0, 0);
351     ok(ret, "CertAddStoreToCollection failed: %08x\n", GetLastError());
352     /* Verify the cert is in the collection */
353     context = CertEnumCertificatesInStore(collection, NULL);
354     ok(context != NULL, "Expected a valid context\n");
355     if (context)
356     {
357         ok(context->hCertStore == collection, "Unexpected store\n");
358         CertFreeCertificateContext(context);
359     }
360     /* Check that adding to the collection isn't allowed */
361     ret = CertAddEncodedCertificateToStore(collection, X509_ASN_ENCODING,
362      bigCert2, sizeof(bigCert2), CERT_STORE_ADD_ALWAYS, NULL);
363     ok(!ret && GetLastError() == E_ACCESSDENIED,
364      "Expected E_ACCESSDENIED, got %08x\n", GetLastError());
365
366     /* Create a new memory store */
367     store2 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
368      CERT_STORE_CREATE_NEW_FLAG, NULL);
369     /* Try adding a store to a non-collection store */
370     ret = pCertAddStoreToCollection(store1, store2,
371      CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
372     ok(!ret && GetLastError() == E_INVALIDARG,
373      "Expected E_INVALIDARG, got %08x\n", GetLastError());
374     /* Try adding some bogus stores */
375     /* This crashes in Windows
376     ret = pCertAddStoreToCollection(0, store2,
377      CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
378      */
379     /* This "succeeds"... */
380     ret = pCertAddStoreToCollection(collection, 0,
381      CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
382     ok(ret, "CertAddStoreToCollection failed: %08x\n", GetLastError());
383     /* while this crashes.
384     ret = pCertAddStoreToCollection(collection, 1,
385      CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
386      */
387
388     /* Add it to the collection, this time allowing adding */
389     ret = pCertAddStoreToCollection(collection, store2,
390      CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
391     ok(ret, "CertAddStoreToCollection failed: %08x\n", GetLastError());
392     /* Check that adding to the collection is allowed */
393     ret = CertAddEncodedCertificateToStore(collection, X509_ASN_ENCODING,
394      bigCert2, sizeof(bigCert2), CERT_STORE_ADD_ALWAYS, NULL);
395     ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n", GetLastError());
396     /* Now check that it was actually added to store2 */
397     context = CertEnumCertificatesInStore(store2, NULL);
398     ok(context != NULL, "Expected a valid context\n");
399     if (context)
400     {
401         ok(context->hCertStore == store2, "Unexpected store\n");
402         CertFreeCertificateContext(context);
403     }
404     /* Check that the collection has both bigCert and bigCert2.  bigCert comes
405      * first because store1 was added first.
406      */
407     context = CertEnumCertificatesInStore(collection, NULL);
408     ok(context != NULL, "Expected a valid context\n");
409     if (context)
410     {
411         ok(context->hCertStore == collection, "Unexpected store\n");
412         ok(context->cbCertEncoded == sizeof(bigCert),
413          "Wrong size %d\n", context->cbCertEncoded);
414         ok(!memcmp(context->pbCertEncoded, bigCert, context->cbCertEncoded),
415          "Unexpected cert\n");
416         context = CertEnumCertificatesInStore(collection, context);
417         ok(context != NULL, "Expected a valid context\n");
418         if (context)
419         {
420             ok(context->hCertStore == collection, "Unexpected store\n");
421             ok(context->cbCertEncoded == sizeof(bigCert2),
422              "Wrong size %d\n", context->cbCertEncoded);
423             ok(!memcmp(context->pbCertEncoded, bigCert2,
424              context->cbCertEncoded), "Unexpected cert\n");
425             context = CertEnumCertificatesInStore(collection, context);
426             ok(!context, "Unexpected cert\n");
427         }
428     }
429     /* close store2, and check that the collection is unmodified */
430     CertCloseStore(store2, 0);
431     context = CertEnumCertificatesInStore(collection, NULL);
432     ok(context != NULL, "Expected a valid context\n");
433     if (context)
434     {
435         ok(context->hCertStore == collection, "Unexpected store\n");
436         ok(context->cbCertEncoded == sizeof(bigCert),
437          "Wrong size %d\n", context->cbCertEncoded);
438         ok(!memcmp(context->pbCertEncoded, bigCert, context->cbCertEncoded),
439          "Unexpected cert\n");
440         context = CertEnumCertificatesInStore(collection, context);
441         ok(context != NULL, "Expected a valid context\n");
442         if (context)
443         {
444             ok(context->hCertStore == collection, "Unexpected store\n");
445             ok(context->cbCertEncoded == sizeof(bigCert2),
446              "Wrong size %d\n", context->cbCertEncoded);
447             ok(!memcmp(context->pbCertEncoded, bigCert2,
448              context->cbCertEncoded), "Unexpected cert\n");
449             context = CertEnumCertificatesInStore(collection, context);
450             ok(!context, "Unexpected cert\n");
451         }
452     }
453
454     /* Adding a collection to a collection is legal */
455     collection2 = CertOpenStore(CERT_STORE_PROV_COLLECTION, 0, 0,
456      CERT_STORE_CREATE_NEW_FLAG, NULL);
457     ret = pCertAddStoreToCollection(collection2, collection,
458      CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
459     ok(ret, "CertAddStoreToCollection failed: %08x\n", GetLastError());
460     /* check the contents of collection2 */
461     context = CertEnumCertificatesInStore(collection2, NULL);
462     ok(context != NULL, "Expected a valid context\n");
463     if (context)
464     {
465         ok(context->hCertStore == collection2, "Unexpected store\n");
466         ok(context->cbCertEncoded == sizeof(bigCert),
467          "Wrong size %d\n", context->cbCertEncoded);
468         ok(!memcmp(context->pbCertEncoded, bigCert, context->cbCertEncoded),
469          "Unexpected cert\n");
470         context = CertEnumCertificatesInStore(collection2, context);
471         ok(context != NULL, "Expected a valid context\n");
472         if (context)
473         {
474             ok(context->hCertStore == collection2, "Unexpected store\n");
475             ok(context->cbCertEncoded == sizeof(bigCert2),
476              "Wrong size %d\n", context->cbCertEncoded);
477             ok(!memcmp(context->pbCertEncoded, bigCert2,
478              context->cbCertEncoded), "Unexpected cert\n");
479             context = CertEnumCertificatesInStore(collection2, context);
480             ok(!context, "Unexpected cert\n");
481         }
482     }
483
484     /* I'd like to test closing the collection in the middle of enumeration,
485      * but my tests have been inconsistent.  The first time calling
486      * CertEnumCertificatesInStore on a closed collection succeeded, while the
487      * second crashed.  So anything appears to be fair game.
488      * I'd also like to test removing a store from a collection in the middle
489      * of an enumeration, but my tests in Windows have been inconclusive.
490      * In one scenario it worked.  In another scenario, about a third of the
491      * time this leads to "random" crashes elsewhere in the code.  This
492      * probably means this is not allowed.
493      */
494
495     CertCloseStore(store1, 0);
496     CertCloseStore(collection, 0);
497     CertCloseStore(collection2, 0);
498
499     /* Add the same cert to two memory stores, then put them in a collection */
500     store1 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
501      CERT_STORE_CREATE_NEW_FLAG, NULL);
502     ok(store1 != 0, "CertOpenStore failed: %08x\n", GetLastError());
503     store2 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
504      CERT_STORE_CREATE_NEW_FLAG, NULL);
505     ok(store2 != 0, "CertOpenStore failed: %08x\n", GetLastError());
506
507     ret = CertAddEncodedCertificateToStore(store1, X509_ASN_ENCODING,
508      bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, NULL);
509     ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n", GetLastError());
510     ret = CertAddEncodedCertificateToStore(store2, X509_ASN_ENCODING,
511      bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, NULL);
512     ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n", GetLastError());
513     collection = CertOpenStore(CERT_STORE_PROV_COLLECTION, 0, 0,
514      CERT_STORE_CREATE_NEW_FLAG, NULL);
515     ok(collection != 0, "CertOpenStore failed: %08x\n", GetLastError());
516
517     ret = pCertAddStoreToCollection(collection, store1,
518      CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
519     ok(ret, "CertAddStoreToCollection failed: %08x\n", GetLastError());
520     ret = pCertAddStoreToCollection(collection, store2,
521      CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
522     ok(ret, "CertAddStoreToCollection failed: %08x\n", GetLastError());
523
524     /* Check that the collection has two copies of the same cert */
525     context = CertEnumCertificatesInStore(collection, NULL);
526     ok(context != NULL, "Expected a valid context\n");
527     if (context)
528     {
529         ok(context->hCertStore == collection, "Unexpected store\n");
530         ok(context->cbCertEncoded == sizeof(bigCert),
531          "Wrong size %d\n", context->cbCertEncoded);
532         ok(!memcmp(context->pbCertEncoded, bigCert, context->cbCertEncoded),
533          "Unexpected cert\n");
534         context = CertEnumCertificatesInStore(collection, context);
535         ok(context != NULL, "Expected a valid context\n");
536         if (context)
537         {
538             ok(context->hCertStore == collection, "Unexpected store\n");
539             ok(context->cbCertEncoded == sizeof(bigCert),
540              "Wrong size %d\n", context->cbCertEncoded);
541             ok(!memcmp(context->pbCertEncoded, bigCert, context->cbCertEncoded),
542              "Unexpected cert\n");
543             context = CertEnumCertificatesInStore(collection, context);
544             ok(context == NULL, "Unexpected cert\n");
545         }
546     }
547
548     /* The following would check whether I can delete an identical cert, rather
549      * than one enumerated from the store.  It crashes, so that means I must
550      * only call CertDeleteCertificateFromStore with contexts enumerated from
551      * the store.
552     context = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert,
553      sizeof(bigCert));
554     ok(context != NULL, "CertCreateCertificateContext failed: %08x\n",
555      GetLastError());
556     if (context)
557     {
558         ret = CertDeleteCertificateFromStore(collection, context);
559         printf("ret is %d, GetLastError is %08x\n", ret, GetLastError());
560         CertFreeCertificateContext(context);
561     }
562      */
563
564     /* Now check deleting from the collection. */
565     context = CertEnumCertificatesInStore(collection, NULL);
566     ok(context != NULL, "Expected a valid context\n");
567     if (context)
568     {
569         CertDeleteCertificateFromStore(context);
570         /* store1 should now be empty */
571         context = CertEnumCertificatesInStore(store1, NULL);
572         ok(!context, "Unexpected cert\n");
573         /* and there should be one certificate in the collection */
574         context = CertEnumCertificatesInStore(collection, NULL);
575         ok(context != NULL, "Expected a valid cert\n");
576         if (context)
577         {
578             ok(context->hCertStore == collection, "Unexpected store\n");
579             ok(context->cbCertEncoded == sizeof(bigCert),
580              "Wrong size %d\n", context->cbCertEncoded);
581             ok(!memcmp(context->pbCertEncoded, bigCert, context->cbCertEncoded),
582              "Unexpected cert\n");
583         }
584         context = CertEnumCertificatesInStore(collection, context);
585         ok(context == NULL, "Unexpected cert\n");
586     }
587
588     if (!pCertRemoveStoreFromCollection)
589     {
590         win_skip("CertRemoveStoreFromCollection() is not available\n");
591     }
592     else
593     {
594         /* Finally, test removing stores from the collection.  No return
595          *  value, so it's a bit funny to test.
596          */
597         /* This crashes
598          * pCertRemoveStoreFromCollection(NULL, NULL);
599          */
600         /* This "succeeds," no crash, no last error set */
601         SetLastError(0xdeadbeef);
602         pCertRemoveStoreFromCollection(store2, collection);
603         ok(GetLastError() == 0xdeadbeef,
604            "Didn't expect an error to be set: %08x\n", GetLastError());
605
606         /* After removing store2, the collection should be empty */
607         SetLastError(0xdeadbeef);
608         pCertRemoveStoreFromCollection(collection, store2);
609         ok(GetLastError() == 0xdeadbeef,
610            "Didn't expect an error to be set: %08x\n", GetLastError());
611         context = CertEnumCertificatesInStore(collection, NULL);
612         ok(!context, "Unexpected cert\n");
613     }
614
615     CertCloseStore(collection, 0);
616     CertCloseStore(store2, 0);
617     CertCloseStore(store1, 0);
618
619     /* Test adding certificates to and deleting certificates from collections.
620      */
621     store1 = CertOpenSystemStoreA(0, "My");
622     collection = CertOpenStore(CERT_STORE_PROV_COLLECTION, 0, 0,
623      CERT_STORE_CREATE_NEW_FLAG, NULL);
624
625     ret = CertAddEncodedCertificateToStore(store1, X509_ASN_ENCODING,
626      bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, &context);
627     ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n", GetLastError());
628     CertDeleteCertificateFromStore(context);
629
630     CertAddStoreToCollection(collection, store1,
631      CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
632
633     ret = CertAddEncodedCertificateToStore(collection, X509_ASN_ENCODING,
634      bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, &context);
635     ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n", GetLastError());
636     CertDeleteCertificateFromStore(context);
637
638     CertCloseStore(collection, 0);
639     CertCloseStore(store1, 0);
640
641     /* Test whether a collection store can be committed */
642     if (!pCertControlStore)
643     {
644         win_skip("CertControlStore() is not available\n");
645         return;
646     }
647     collection = CertOpenStore(CERT_STORE_PROV_COLLECTION, 0, 0,
648      CERT_STORE_CREATE_NEW_FLAG, NULL);
649
650     SetLastError(0xdeadbeef);
651     ret = pCertControlStore(collection, 0, CERT_STORE_CTRL_COMMIT, NULL);
652     ok(ret, "CertControlStore failed: %08x\n", GetLastError());
653
654     /* Adding a mem store that can't be committed prevents a successful commit.
655      */
656     store1 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
657      CERT_STORE_CREATE_NEW_FLAG, NULL);
658     pCertAddStoreToCollection(collection, store1, 0, 0);
659     SetLastError(0xdeadbeef);
660     ret = pCertControlStore(collection, 0, CERT_STORE_CTRL_COMMIT, NULL);
661     ok(!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED,
662      "expected ERROR_CALL_NOT_IMPLEMENTED, got %d\n", GetLastError());
663     pCertRemoveStoreFromCollection(collection, store1);
664     CertCloseStore(store1, 0);
665
666     /* Test adding a cert to a collection with a file store, committing the
667      * change to the collection, and comparing the resulting file.
668      */
669     if (!GetTempFileNameW(szDot, szPrefix, 0, filename))
670         return;
671
672     DeleteFileW(filename);
673     file = CreateFileW(filename, GENERIC_READ | GENERIC_WRITE, 0, NULL,
674      CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
675     if (file == INVALID_HANDLE_VALUE)
676         return;
677
678     store1 = CertOpenStore(CERT_STORE_PROV_FILE, 0, 0,
679      CERT_FILE_STORE_COMMIT_ENABLE_FLAG, file);
680     ok(store1 != NULL, "CertOpenStore failed: %08x\n", GetLastError());
681     CloseHandle(file);
682     pCertAddStoreToCollection(collection, store1,
683      CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
684     CertCloseStore(store1, 0);
685
686     ret = CertAddEncodedCertificateToStore(collection, X509_ASN_ENCODING,
687      bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, NULL);
688     ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
689      GetLastError());
690     ret = pCertControlStore(collection, 0, CERT_STORE_CTRL_COMMIT, NULL);
691     ok(ret, "CertControlStore failed: %d\n", ret);
692
693     CertCloseStore(collection, 0);
694
695     compareFile(filename, serializedStoreWithCert,
696      sizeof(serializedStoreWithCert));
697     DeleteFileW(filename);
698 }
699
700 /* Looks for the property with ID propID in the buffer buf.  Returns a pointer
701  * to its header if found, NULL if not.
702  */
703 static const struct CertPropIDHeader *findPropID(const BYTE *buf, DWORD size,
704  DWORD propID)
705 {
706     const struct CertPropIDHeader *ret = NULL;
707     BOOL failed = FALSE;
708
709     while (size && !ret && !failed)
710     {
711         if (size < sizeof(struct CertPropIDHeader))
712             failed = TRUE;
713         else
714         {
715             const struct CertPropIDHeader *hdr =
716              (const struct CertPropIDHeader *)buf;
717
718             size -= sizeof(struct CertPropIDHeader);
719             buf += sizeof(struct CertPropIDHeader);
720             if (size < hdr->cb)
721                 failed = TRUE;
722             else if (hdr->propID == propID)
723                 ret = hdr;
724             else
725             {
726                 buf += hdr->cb;
727                 size -= hdr->cb;
728             }
729         }
730     }
731     return ret;
732 }
733
734 typedef DWORD (WINAPI *SHDeleteKeyAFunc)(HKEY, LPCSTR);
735
736 static void testRegStore(void)
737 {
738     static const char tempKey[] = "Software\\Wine\\CryptTemp";
739     HCERTSTORE store;
740     LONG rc;
741     HKEY key = NULL;
742     DWORD disp, GLE;
743
744     store = CertOpenStore(CERT_STORE_PROV_REG, 0, 0, 0, NULL);
745     GLE = GetLastError();
746     ok(!store && (GLE == ERROR_INVALID_HANDLE || GLE == ERROR_BADKEY),
747      "Expected ERROR_INVALID_HANDLE or ERROR_BADKEY, got %d\n", GLE);
748     store = CertOpenStore(CERT_STORE_PROV_REG, 0, 0, 0, key);
749     GLE = GetLastError();
750     ok(!store && (GLE == ERROR_INVALID_HANDLE || GLE == ERROR_BADKEY),
751      "Expected ERROR_INVALID_HANDLE or ERROR_BADKEY, got %d\n", GLE);
752
753     /* Opening up any old key works.. */
754     key = HKEY_CURRENT_USER;
755     store = CertOpenStore(CERT_STORE_PROV_REG, 0, 0, 0, key);
756     /* Not sure if this is a bug in DuplicateHandle, marking todo_wine for now
757      */
758     todo_wine ok(store != 0, "CertOpenStore failed: %08x\n", GetLastError());
759     CertCloseStore(store, 0);
760
761     /* It looks like the remainder pretty much needs CertControlStore() */
762     if (!pCertControlStore)
763     {
764         win_skip("CertControlStore() is not available\n");
765         return;
766     }
767
768     rc = RegCreateKeyExA(HKEY_CURRENT_USER, tempKey, 0, NULL, 0, KEY_ALL_ACCESS,
769      NULL, &key, NULL);
770     ok(!rc, "RegCreateKeyExA failed: %d\n", rc);
771     if (key)
772     {
773         BOOL ret;
774         BYTE hash[20];
775         DWORD size, i;
776         static const char certificates[] = "Certificates\\";
777         char subKeyName[sizeof(certificates) + 20 * 2 + 1], *ptr;
778         HKEY subKey;
779         PCCERT_CONTEXT context;
780
781         store = CertOpenStore(CERT_STORE_PROV_REG, 0, 0, 0, key);
782         ok(store != 0, "CertOpenStore failed: %08x\n", GetLastError());
783         /* Add a certificate.  It isn't persisted right away, since it's only
784          * added to the cache..
785          */
786         ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
787          bigCert2, sizeof(bigCert2), CERT_STORE_ADD_ALWAYS, NULL);
788         ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
789          GetLastError());
790         /* so flush the cache to force a commit.. */
791         ret = pCertControlStore(store, 0, CERT_STORE_CTRL_COMMIT, NULL);
792         ok(ret, "CertControlStore failed: %08x\n", GetLastError());
793         /* and check that the expected subkey was written. */
794         size = sizeof(hash);
795         ret = CryptHashCertificate(0, 0, 0, bigCert2, sizeof(bigCert2),
796          hash, &size);
797         ok(ret, "CryptHashCertificate failed: %d\n", GetLastError());
798         strcpy(subKeyName, certificates);
799         for (i = 0, ptr = subKeyName + sizeof(certificates) - 1; i < size;
800          i++, ptr += 2)
801             sprintf(ptr, "%02X", hash[i]);
802         rc = RegCreateKeyExA(key, subKeyName, 0, NULL, 0, KEY_ALL_ACCESS, NULL,
803          &subKey, NULL);
804         ok(!rc, "RegCreateKeyExA failed: %d\n", rc);
805         if (subKey)
806         {
807             LPBYTE buf;
808
809             size = 0;
810             RegQueryValueExA(subKey, "Blob", NULL, NULL, NULL, &size);
811             buf = HeapAlloc(GetProcessHeap(), 0, size);
812             if (buf)
813             {
814                 rc = RegQueryValueExA(subKey, "Blob", NULL, NULL, buf, &size);
815                 ok(!rc, "RegQueryValueExA failed: %d\n", rc);
816                 if (!rc)
817                 {
818                     const struct CertPropIDHeader *hdr;
819
820                     /* Both the hash and the cert should be present */
821                     hdr = findPropID(buf, size, CERT_CERT_PROP_ID);
822                     ok(hdr != NULL, "Expected to find a cert property\n");
823                     if (hdr)
824                     {
825                         ok(hdr->cb == sizeof(bigCert2),
826                            "Wrong size %d of cert property\n", hdr->cb);
827                         ok(!memcmp((const BYTE *)hdr + sizeof(*hdr), bigCert2,
828                          hdr->cb), "Unexpected cert in cert property\n");
829                     }
830                     hdr = findPropID(buf, size, CERT_HASH_PROP_ID);
831                     ok(hdr != NULL, "Expected to find a hash property\n");
832                     if (hdr)
833                     {
834                         ok(hdr->cb == sizeof(hash),
835                            "Wrong size %d of hash property\n", hdr->cb);
836                         ok(!memcmp((const BYTE *)hdr + sizeof(*hdr), hash,
837                          hdr->cb), "Unexpected hash in cert property\n");
838                     }
839                 }
840                 HeapFree(GetProcessHeap(), 0, buf);
841             }
842             RegCloseKey(subKey);
843         }
844
845         /* Remove the existing context */
846         context = CertEnumCertificatesInStore(store, NULL);
847         ok(context != NULL, "Expected a cert context\n");
848         if (context)
849             CertDeleteCertificateFromStore(context);
850         ret = pCertControlStore(store, 0, CERT_STORE_CTRL_COMMIT, NULL);
851         ok(ret, "CertControlStore failed: %08x\n", GetLastError());
852
853         /* Add a serialized cert with a bogus hash directly to the registry */
854         memset(hash, 0, sizeof(hash));
855         strcpy(subKeyName, certificates);
856         for (i = 0, ptr = subKeyName + sizeof(certificates) - 1;
857          i < sizeof(hash); i++, ptr += 2)
858             sprintf(ptr, "%02X", hash[i]);
859         rc = RegCreateKeyExA(key, subKeyName, 0, NULL, 0, KEY_ALL_ACCESS, NULL,
860          &subKey, NULL);
861         ok(!rc, "RegCreateKeyExA failed: %d\n", rc);
862         if (subKey)
863         {
864             BYTE buf[sizeof(struct CertPropIDHeader) * 2 + sizeof(hash) +
865              sizeof(bigCert)], *ptr;
866             DWORD certCount = 0;
867             struct CertPropIDHeader *hdr;
868
869             hdr = (struct CertPropIDHeader *)buf;
870             hdr->propID = CERT_HASH_PROP_ID;
871             hdr->unknown1 = 1;
872             hdr->cb = sizeof(hash);
873             ptr = buf + sizeof(*hdr);
874             memcpy(ptr, hash, sizeof(hash));
875             ptr += sizeof(hash);
876             hdr = (struct CertPropIDHeader *)ptr;
877             hdr->propID = CERT_CERT_PROP_ID;
878             hdr->unknown1 = 1;
879             hdr->cb = sizeof(bigCert);
880             ptr += sizeof(*hdr);
881             memcpy(ptr, bigCert, sizeof(bigCert));
882
883             rc = RegSetValueExA(subKey, "Blob", 0, REG_BINARY, buf,
884              sizeof(buf));
885             ok(!rc, "RegSetValueExA failed: %d\n", rc);
886
887             ret = pCertControlStore(store, 0, CERT_STORE_CTRL_RESYNC, NULL);
888             ok(ret, "CertControlStore failed: %08x\n", GetLastError());
889
890             /* Make sure the bogus hash cert gets loaded. */
891             certCount = 0;
892             context = NULL;
893             do {
894                 context = CertEnumCertificatesInStore(store, context);
895                 if (context)
896                     certCount++;
897             } while (context != NULL);
898             ok(certCount == 1, "Expected 1 certificates, got %d\n", certCount);
899
900             RegCloseKey(subKey);
901         }
902
903         /* Add another serialized cert directly to the registry, this time
904          * under the correct key name (named with the correct hash value).
905          */
906         size = sizeof(hash);
907         ret = CryptHashCertificate(0, 0, 0, bigCert2,
908          sizeof(bigCert2), hash, &size);
909         ok(ret, "CryptHashCertificate failed: %d\n", GetLastError());
910         strcpy(subKeyName, certificates);
911         for (i = 0, ptr = subKeyName + sizeof(certificates) - 1;
912          i < sizeof(hash); i++, ptr += 2)
913             sprintf(ptr, "%02X", hash[i]);
914         rc = RegCreateKeyExA(key, subKeyName, 0, NULL, 0, KEY_ALL_ACCESS, NULL,
915          &subKey, NULL);
916         ok(!rc, "RegCreateKeyExA failed: %d\n", rc);
917         if (subKey)
918         {
919             BYTE buf[sizeof(struct CertPropIDHeader) * 2 + sizeof(hash) +
920              sizeof(bigCert2)], *ptr;
921             DWORD certCount = 0;
922             PCCERT_CONTEXT context;
923             struct CertPropIDHeader *hdr;
924
925             /* First try with a bogus hash... */
926             hdr = (struct CertPropIDHeader *)buf;
927             hdr->propID = CERT_HASH_PROP_ID;
928             hdr->unknown1 = 1;
929             hdr->cb = sizeof(hash);
930             ptr = buf + sizeof(*hdr);
931             memset(ptr, 0, sizeof(hash));
932             ptr += sizeof(hash);
933             hdr = (struct CertPropIDHeader *)ptr;
934             hdr->propID = CERT_CERT_PROP_ID;
935             hdr->unknown1 = 1;
936             hdr->cb = sizeof(bigCert2);
937             ptr += sizeof(*hdr);
938             memcpy(ptr, bigCert2, sizeof(bigCert2));
939
940             rc = RegSetValueExA(subKey, "Blob", 0, REG_BINARY, buf,
941              sizeof(buf));
942             ok(!rc, "RegSetValueExA failed: %d\n", rc);
943
944             ret = pCertControlStore(store, 0, CERT_STORE_CTRL_RESYNC, NULL);
945             ok(ret, "CertControlStore failed: %08x\n", GetLastError());
946
947             /* and make sure just one cert still gets loaded. */
948             certCount = 0;
949             context = NULL;
950             do {
951                 context = CertEnumCertificatesInStore(store, context);
952                 if (context)
953                     certCount++;
954             } while (context != NULL);
955             ok(certCount == 1 ||
956                broken(certCount == 2), /* win9x */
957                "Expected 1 certificates, got %d\n", certCount);
958
959             /* Try again with the correct hash... */
960             ptr = buf + sizeof(*hdr);
961             memcpy(ptr, hash, sizeof(hash));
962
963             rc = RegSetValueExA(subKey, "Blob", 0, REG_BINARY, buf,
964              sizeof(buf));
965             ok(!rc, "RegSetValueExA failed: %d\n", rc);
966
967             ret = pCertControlStore(store, 0, CERT_STORE_CTRL_RESYNC, NULL);
968             ok(ret, "CertControlStore failed: %08x\n", GetLastError());
969
970             /* and make sure two certs get loaded. */
971             certCount = 0;
972             context = NULL;
973             do {
974                 context = CertEnumCertificatesInStore(store, context);
975                 if (context)
976                     certCount++;
977             } while (context != NULL);
978             ok(certCount == 2, "Expected 2 certificates, got %d\n", certCount);
979
980             RegCloseKey(subKey);
981         }
982         CertCloseStore(store, 0);
983         /* Is delete allowed on a reg store? */
984         store = CertOpenStore(CERT_STORE_PROV_REG, 0, 0,
985          CERT_STORE_DELETE_FLAG, key);
986         ok(store == NULL, "Expected NULL return from CERT_STORE_DELETE_FLAG\n");
987         ok(GetLastError() == 0, "CertOpenStore failed: %08x\n",
988          GetLastError());
989
990         RegCloseKey(key);
991     }
992     /* The CertOpenStore with CERT_STORE_DELETE_FLAG above will delete the
993      * contents of the key, but not the key itself.
994      */
995     rc = RegCreateKeyExA(HKEY_CURRENT_USER, tempKey, 0, NULL, 0, KEY_ALL_ACCESS,
996      NULL, &key, &disp);
997     ok(!rc, "RegCreateKeyExA failed: %d\n", rc);
998     ok(disp == REG_OPENED_EXISTING_KEY,
999      "Expected REG_OPENED_EXISTING_KEY, got %d\n", disp);
1000     if (!rc)
1001     {
1002         RegCloseKey(key);
1003         rc = RegDeleteKeyA(HKEY_CURRENT_USER, tempKey);
1004         if (rc)
1005         {
1006             HMODULE shlwapi = LoadLibraryA("shlwapi");
1007
1008             /* Use shlwapi's SHDeleteKeyA to _really_ blow away the key,
1009              * otherwise subsequent tests will fail.
1010              */
1011             if (shlwapi)
1012             {
1013                 SHDeleteKeyAFunc pSHDeleteKeyA =
1014                  (SHDeleteKeyAFunc)GetProcAddress(shlwapi, "SHDeleteKeyA");
1015
1016                 if (pSHDeleteKeyA)
1017                     pSHDeleteKeyA(HKEY_CURRENT_USER, tempKey);
1018                 FreeLibrary(shlwapi);
1019             }
1020         }
1021     }
1022 }
1023
1024 static const char MyA[] = { 'M','y',0,0 };
1025 static const WCHAR MyW[] = { 'M','y',0 };
1026 static const WCHAR BogusW[] = { 'B','o','g','u','s',0 };
1027 static const WCHAR BogusPathW[] = { 'S','o','f','t','w','a','r','e','\\',
1028  'M','i','c','r','o','s','o','f','t','\\','S','y','s','t','e','m','C','e','r',
1029  't','i','f','i','c','a','t','e','s','\\','B','o','g','u','s',0 };
1030
1031 static void testSystemRegStore(void)
1032 {
1033     HCERTSTORE store, memStore;
1034
1035     /* Check with a UNICODE name */
1036     store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY, 0, 0,
1037      CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_OPEN_EXISTING_FLAG, MyW);
1038     /* Not all OSes support CERT_STORE_PROV_SYSTEM_REGISTRY, so don't continue
1039      * testing if they don't.
1040      */
1041     if (!store)
1042         return;
1043
1044     /* Check that it isn't a collection store */
1045     memStore = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
1046      CERT_STORE_CREATE_NEW_FLAG, NULL);
1047     if (memStore)
1048     {
1049         if (pCertAddStoreToCollection)
1050         {
1051             BOOL ret = pCertAddStoreToCollection(store, memStore, 0, 0);
1052             ok(!ret && GetLastError() == E_INVALIDARG,
1053                "Expected E_INVALIDARG, got %08x\n", GetLastError());
1054         }
1055         CertCloseStore(memStore, 0);
1056     }
1057     CertCloseStore(store, 0);
1058
1059     /* Check opening a bogus store */
1060     store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY, 0, 0,
1061      CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_OPEN_EXISTING_FLAG, BogusW);
1062     ok(!store && GetLastError() == ERROR_FILE_NOT_FOUND,
1063      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
1064     store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY, 0, 0,
1065      CERT_SYSTEM_STORE_CURRENT_USER, BogusW);
1066     ok(store != 0, "CertOpenStore failed: %08x\n", GetLastError());
1067     if (store)
1068         CertCloseStore(store, 0);
1069     /* Now check whether deleting is allowed */
1070     store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY, 0, 0,
1071      CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_DELETE_FLAG, BogusW);
1072     RegDeleteKeyW(HKEY_CURRENT_USER, BogusPathW);
1073
1074     store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY, 0, 0, 0, NULL);
1075     ok(!store && GetLastError() == E_INVALIDARG,
1076      "Expected E_INVALIDARG, got %08x\n", GetLastError());
1077     store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY, 0, 0,
1078      CERT_SYSTEM_STORE_LOCAL_MACHINE | CERT_SYSTEM_STORE_CURRENT_USER, MyA);
1079     ok(!store && GetLastError() == E_INVALIDARG,
1080      "Expected E_INVALIDARG, got %08x\n", GetLastError());
1081     store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY, 0, 0,
1082      CERT_SYSTEM_STORE_LOCAL_MACHINE | CERT_SYSTEM_STORE_CURRENT_USER, MyW);
1083     ok(!store && GetLastError() == E_INVALIDARG,
1084      "Expected E_INVALIDARG, got %08x\n", GetLastError());
1085     /* The name is expected to be UNICODE, check with an ASCII name */
1086     store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY, 0, 0,
1087      CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_OPEN_EXISTING_FLAG, MyA);
1088     ok(!store && GetLastError() == ERROR_FILE_NOT_FOUND,
1089      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
1090 }
1091
1092 static void testSystemStore(void)
1093 {
1094     static const WCHAR baskslashW[] = { '\\',0 };
1095     HCERTSTORE store;
1096     WCHAR keyName[MAX_PATH];
1097     HKEY key;
1098     LONG rc;
1099
1100     store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0, 0, NULL);
1101     ok(!store && GetLastError() == ERROR_FILE_NOT_FOUND,
1102      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
1103     store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0,
1104      CERT_SYSTEM_STORE_LOCAL_MACHINE | CERT_SYSTEM_STORE_CURRENT_USER, MyA);
1105     ok(!store && GetLastError() == ERROR_FILE_NOT_FOUND,
1106      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
1107     store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0,
1108      CERT_SYSTEM_STORE_LOCAL_MACHINE | CERT_SYSTEM_STORE_CURRENT_USER, MyW);
1109     ok(!store && GetLastError() == ERROR_FILE_NOT_FOUND,
1110      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
1111     /* The name is expected to be UNICODE, first check with an ASCII name */
1112     store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0,
1113      CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_OPEN_EXISTING_FLAG, MyA);
1114     ok(!store && GetLastError() == ERROR_FILE_NOT_FOUND,
1115      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
1116     /* Create the expected key */
1117     lstrcpyW(keyName, CERT_LOCAL_MACHINE_SYSTEM_STORE_REGPATH);
1118     lstrcatW(keyName, baskslashW);
1119     lstrcatW(keyName, MyW);
1120     rc = RegCreateKeyExW(HKEY_CURRENT_USER, keyName, 0, NULL, 0, KEY_READ,
1121      NULL, &key, NULL);
1122     ok(!rc, "RegCreateKeyEx failed: %d\n", rc);
1123     if (!rc)
1124         RegCloseKey(key);
1125     /* Check opening with a UNICODE name, specifying the create new flag */
1126     store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0,
1127      CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_CREATE_NEW_FLAG, MyW);
1128     ok(!store && GetLastError() == ERROR_FILE_EXISTS,
1129      "Expected ERROR_FILE_EXISTS, got %08x\n", GetLastError());
1130     /* Now check opening with a UNICODE name, this time opening existing */
1131     store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0,
1132      CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_OPEN_EXISTING_FLAG, MyW);
1133     ok(store != 0, "CertOpenStore failed: %08x\n", GetLastError());
1134     if (store)
1135     {
1136         HCERTSTORE memStore = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
1137          CERT_STORE_CREATE_NEW_FLAG, NULL);
1138
1139         /* Check that it's a collection store */
1140         if (memStore)
1141         {
1142             if (pCertAddStoreToCollection)
1143             {
1144                 BOOL ret = pCertAddStoreToCollection(store, memStore, 0, 0);
1145                 /* FIXME: this'll fail on NT4, but what error will it give? */
1146                 ok(ret, "CertAddStoreToCollection failed: %08x\n", GetLastError());
1147             }
1148             CertCloseStore(memStore, 0);
1149         }
1150         CertCloseStore(store, 0);
1151     }
1152
1153     /* Check opening a bogus store */
1154     store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0,
1155      CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_OPEN_EXISTING_FLAG, BogusW);
1156     ok((!store ||
1157      broken(store != 0)) && /* win9x */
1158      GetLastError() == ERROR_FILE_NOT_FOUND,
1159      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
1160     store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0,
1161      CERT_SYSTEM_STORE_CURRENT_USER, BogusW);
1162     ok(store != 0, "CertOpenStore failed: %08x\n", GetLastError());
1163     if (store)
1164         CertCloseStore(store, 0);
1165     /* Now check whether deleting is allowed */
1166     store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0,
1167      CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_DELETE_FLAG, BogusW);
1168     RegDeleteKeyW(HKEY_CURRENT_USER, BogusPathW);
1169 }
1170
1171 static const BYTE serializedStoreWithCertAndCRL[] = {
1172  0x00,0x00,0x00,0x00,0x43,0x45,0x52,0x54,0x20,0x00,0x00,0x00,0x01,0x00,0x00,
1173  0x00,0x7c,0x00,0x00,0x00,0x30,0x7a,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,
1174  0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,
1175  0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,
1176  0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,
1177  0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,
1178  0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,
1179  0x20,0x4c,0x61,0x6e,0x67,0x00,0x30,0x07,0x30,0x02,0x06,0x00,0x03,0x01,0x00,
1180  0xa3,0x16,0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,
1181  0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01,0x21,0x00,0x00,0x00,0x01,0x00,
1182  0x00,0x00,0x47,0x00,0x00,0x00,0x30,0x45,0x30,0x2c,0x30,0x02,0x06,0x00,0x30,
1183  0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,
1184  0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
1185  0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00,0x03,0x11,
1186  0x00,0x0f,0x0e,0x0d,0x0c,0x0b,0x0a,0x09,0x08,0x07,0x06,0x05,0x04,0x03,0x02,
1187  0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 };
1188
1189 static void testFileStore(void)
1190 {
1191     static const WCHAR szPrefix[] = { 'c','e','r',0 };
1192     static const WCHAR szDot[] = { '.',0 };
1193     WCHAR filename[MAX_PATH];
1194     HCERTSTORE store;
1195     BOOL ret;
1196     PCCERT_CONTEXT cert;
1197     HANDLE file;
1198
1199     if (!pCertControlStore)
1200     {
1201         win_skip("CertControlStore() is not available\n");
1202         return;
1203     }
1204
1205     store = CertOpenStore(CERT_STORE_PROV_FILE, 0, 0, 0, NULL);
1206     ok(!store && GetLastError() == ERROR_INVALID_HANDLE,
1207      "Expected ERROR_INVALID_HANDLE, got %08x\n", GetLastError());
1208
1209     if (!GetTempFileNameW(szDot, szPrefix, 0, filename))
1210        return;
1211  
1212     DeleteFileW(filename);
1213     file = CreateFileW(filename, GENERIC_READ | GENERIC_WRITE, 0, NULL,
1214      CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
1215     if (file == INVALID_HANDLE_VALUE)
1216         return;
1217
1218     store = CertOpenStore(CERT_STORE_PROV_FILE, 0, 0, CERT_STORE_DELETE_FLAG,
1219      file);
1220     ok(!store && GetLastError() == E_INVALIDARG,
1221      "Expected E_INVALIDARG, got %08x\n", GetLastError());
1222     store = CertOpenStore(CERT_STORE_PROV_FILE, 0, 0,
1223      CERT_FILE_STORE_COMMIT_ENABLE_FLAG | CERT_STORE_READONLY_FLAG, file);
1224     ok(!store && GetLastError() == E_INVALIDARG,
1225      "Expected E_INVALIDARG, got %08x\n", GetLastError());
1226
1227     /* A "read-only" file store.. */
1228     store = CertOpenStore(CERT_STORE_PROV_FILE, 0, 0,
1229      CERT_STORE_OPEN_EXISTING_FLAG | CERT_STORE_READONLY_FLAG, file);
1230     ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError());
1231     if (store)
1232     {
1233         DWORD size;
1234
1235         ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1236          bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, NULL);
1237         /* apparently allows adding certificates.. */
1238         ok(ret, "CertAddEncodedCertificateToStore failed: %d\n", ret);
1239         /* but not commits.. */
1240         ret = pCertControlStore(store, 0, CERT_STORE_CTRL_COMMIT, NULL);
1241         ok(!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED,
1242          "Expected ERROR_CALL_NOT_IMPLEMENTED, got %08x\n", GetLastError());
1243         /* It still has certs in memory.. */
1244         cert = CertEnumCertificatesInStore(store, NULL);
1245         ok(cert != NULL, "CertEnumCertificatesInStore failed: %08x\n",
1246          GetLastError());
1247         CertFreeCertificateContext(cert);
1248         /* but the file size is still 0. */
1249         size = GetFileSize(file, NULL);
1250         ok(size == 0, "Expected size 0, got %d\n", size);
1251         CertCloseStore(store, 0);
1252     }
1253
1254     /* The create new flag is allowed.. */
1255     store = CertOpenStore(CERT_STORE_PROV_FILE, 0, 0,
1256      CERT_STORE_CREATE_NEW_FLAG, file);
1257     ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError());
1258     if (store)
1259     {
1260         /* but without the commit enable flag, commits don't happen. */
1261         ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1262          bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, NULL);
1263         ok(ret, "CertAddEncodedCertificateToStore failed: %d\n", ret);
1264         ret = pCertControlStore(store, 0, CERT_STORE_CTRL_COMMIT, NULL);
1265         ok(!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED,
1266          "Expected ERROR_CALL_NOT_IMPLEMENTED, got %08x\n", GetLastError());
1267         CertCloseStore(store, 0);
1268     }
1269     /* as is the open existing flag. */
1270     store = CertOpenStore(CERT_STORE_PROV_FILE, 0, 0,
1271      CERT_STORE_OPEN_EXISTING_FLAG, file);
1272     ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError());
1273     if (store)
1274     {
1275         /* but without the commit enable flag, commits don't happen. */
1276         ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1277          bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, NULL);
1278         ok(ret, "CertAddEncodedCertificateToStore failed: %d\n", ret);
1279         ret = pCertControlStore(store, 0, CERT_STORE_CTRL_COMMIT, NULL);
1280         ok(!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED,
1281          "Expected ERROR_CALL_NOT_IMPLEMENTED, got %08x\n", GetLastError());
1282         CertCloseStore(store, 0);
1283     }
1284     store = CertOpenStore(CERT_STORE_PROV_FILE, 0, 0,
1285      CERT_FILE_STORE_COMMIT_ENABLE_FLAG, file);
1286     ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError());
1287     if (store)
1288     {
1289         CloseHandle(file);
1290         ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1291          bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, NULL);
1292         ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
1293          GetLastError());
1294         /* with commits enabled, commit is allowed */
1295         ret = pCertControlStore(store, 0, CERT_STORE_CTRL_COMMIT, NULL);
1296         ok(ret, "CertControlStore failed: %d\n", ret);
1297         compareFile(filename, serializedStoreWithCert,
1298          sizeof(serializedStoreWithCert));
1299         CertCloseStore(store, 0);
1300     }
1301     file = CreateFileW(filename, GENERIC_READ | GENERIC_WRITE, 0, NULL,
1302      OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
1303     if (file == INVALID_HANDLE_VALUE)
1304         return;
1305     store = CertOpenStore(CERT_STORE_PROV_FILE, 0, 0,
1306      CERT_FILE_STORE_COMMIT_ENABLE_FLAG, file);
1307     ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError());
1308     if (store)
1309     {
1310         CloseHandle(file);
1311         ret = CertAddEncodedCRLToStore(store, X509_ASN_ENCODING, signedCRL,
1312          sizeof(signedCRL), CERT_STORE_ADD_ALWAYS, NULL);
1313         ok(ret, "CertAddEncodedCRLToStore failed: %08x\n", GetLastError());
1314         CertCloseStore(store, 0);
1315         compareFile(filename, serializedStoreWithCertAndCRL,
1316          sizeof(serializedStoreWithCertAndCRL));
1317     }
1318
1319     DeleteFileW(filename);
1320 }
1321
1322 static BOOL initFileFromData(LPCWSTR filename, const BYTE *pb, DWORD cb)
1323 {
1324     HANDLE file = CreateFileW(filename, GENERIC_READ | GENERIC_WRITE, 0, NULL,
1325      CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
1326     BOOL ret;
1327
1328     if (file != INVALID_HANDLE_VALUE)
1329     {
1330         DWORD written;
1331
1332         ret = WriteFile(file, pb, cb, &written, NULL);
1333         CloseHandle(file);
1334     }
1335     else
1336         ret = FALSE;
1337     return ret;
1338 }
1339
1340 static const BYTE base64SPC[] =
1341 "MIICJQYJKoZIhvcNAQcCoIICFjCCAhICAQExADALBgkqhkiG9w0BBwGgggH6MIIB"
1342 "9jCCAV+gAwIBAgIQnP8+EF4opr9OxH7h4uBPWTANBgkqhkiG9w0BAQQFADAUMRIw"
1343 "EAYDVQQDEwlKdWFuIExhbmcwHhcNMDgxMjEyMTcxMDE0WhcNMzkxMjMxMjM1OTU5"
1344 "WjAUMRIwEAYDVQQDEwlKdWFuIExhbmcwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJ"
1345 "AoGBALCgNjyNvOic0FOfjxvi43HbM+D5joDkhiGSXe+gbZlf8f16k07kkObFEunz"
1346 "mdB5coscmA7gyqiWNN4ZUyr2cA3lCbnpGPA/0IblyyOcuGIFmmCzeZaVa5ZG6xZP"
1347 "K7L7o+73Qo6jXVbGhBGnMZ7Q9sAn6s2933olnStnejnqwV0NAgMBAAGjSTBHMEUG"
1348 "A1UdAQQ+MDyAEFKbKEdXYyx+CWKcV6vxM6ShFjAUMRIwEAYDVQQDEwlKdWFuIExh"
1349 "bmeCEJz/PhBeKKa/TsR+4eLgT1kwDQYJKoZIhvcNAQEEBQADgYEALpkgLgW3mEaK"
1350 "idPQ3iPJYLG0Ub1wraqEl9bd42hrhzIdcDzlQgxnm8/5cHYVxIF/C20x/HJplb1R"
1351 "G6U1ipFe/q8byWD/9JpiBKMGPi9YlUTgXHfS9d4S/QWO1h9Z7KeipBYhoslQpHXu"
1352 "y9bUr8Adqi6SzgHpCnMu53dxgxUD1r4xAA==";
1353 /* Same as base64SPC, but as a wide-char string */
1354 static const WCHAR utf16Base64SPC[] = {
1355 'M','I','I','C','J','Q','Y','J','K','o','Z','I','h','v','c','N','A',
1356 'Q','c','C','o','I','I','C','F','j','C','C','A','h','I','C','A','Q',
1357 'E','x','A','D','A','L','B','g','k','q','h','k','i','G','9','w','0',
1358 'B','B','w','G','g','g','g','H','6','M','I','I','B','9','j','C','C',
1359 'A','V','+','g','A','w','I','B','A','g','I','Q','n','P','8','+','E',
1360 'F','4','o','p','r','9','O','x','H','7','h','4','u','B','P','W','T',
1361 'A','N','B','g','k','q','h','k','i','G','9','w','0','B','A','Q','Q',
1362 'F','A','D','A','U','M','R','I','w','E','A','Y','D','V','Q','Q','D',
1363 'E','w','l','K','d','W','F','u','I','E','x','h','b','m','c','w','H',
1364 'h','c','N','M','D','g','x','M','j','E','y','M','T','c','x','M','D',
1365 'E','0','W','h','c','N','M','z','k','x','M','j','M','x','M','j','M',
1366 '1','O','T','U','5','W','j','A','U','M','R','I','w','E','A','Y','D',
1367 'V','Q','Q','D','E','w','l','K','d','W','F','u','I','E','x','h','b',
1368 'm','c','w','g','Z','8','w','D','Q','Y','J','K','o','Z','I','h','v',
1369 'c','N','A','Q','E','B','B','Q','A','D','g','Y','0','A','M','I','G',
1370 'J','A','o','G','B','A','L','C','g','N','j','y','N','v','O','i','c',
1371 '0','F','O','f','j','x','v','i','4','3','H','b','M','+','D','5','j',
1372 'o','D','k','h','i','G','S','X','e','+','g','b','Z','l','f','8','f',
1373 '1','6','k','0','7','k','k','O','b','F','E','u','n','z','m','d','B',
1374 '5','c','o','s','c','m','A','7','g','y','q','i','W','N','N','4','Z',
1375 'U','y','r','2','c','A','3','l','C','b','n','p','G','P','A','/','0',
1376 'I','b','l','y','y','O','c','u','G','I','F','m','m','C','z','e','Z',
1377 'a','V','a','5','Z','G','6','x','Z','P','K','7','L','7','o','+','7',
1378 '3','Q','o','6','j','X','V','b','G','h','B','G','n','M','Z','7','Q',
1379 '9','s','A','n','6','s','2','9','3','3','o','l','n','S','t','n','e',
1380 'j','n','q','w','V','0','N','A','g','M','B','A','A','G','j','S','T',
1381 'B','H','M','E','U','G','A','1','U','d','A','Q','Q','+','M','D','y',
1382 'A','E','F','K','b','K','E','d','X','Y','y','x','+','C','W','K','c',
1383 'V','6','v','x','M','6','S','h','F','j','A','U','M','R','I','w','E',
1384 'A','Y','D','V','Q','Q','D','E','w','l','K','d','W','F','u','I','E',
1385 'x','h','b','m','e','C','E','J','z','/','P','h','B','e','K','K','a',
1386 '/','T','s','R','+','4','e','L','g','T','1','k','w','D','Q','Y','J',
1387 'K','o','Z','I','h','v','c','N','A','Q','E','E','B','Q','A','D','g',
1388 'Y','E','A','L','p','k','g','L','g','W','3','m','E','a','K','i','d',
1389 'P','Q','3','i','P','J','Y','L','G','0','U','b','1','w','r','a','q',
1390 'E','l','9','b','d','4','2','h','r','h','z','I','d','c','D','z','l',
1391 'Q','g','x','n','m','8','/','5','c','H','Y','V','x','I','F','/','C',
1392 '2','0','x','/','H','J','p','l','b','1','R','G','6','U','1','i','p',
1393 'F','e','/','q','8','b','y','W','D','/','9','J','p','i','B','K','M',
1394 'G','P','i','9','Y','l','U','T','g','X','H','f','S','9','d','4','S',
1395 '/','Q','W','O','1','h','9','Z','7','K','e','i','p','B','Y','h','o',
1396 's','l','Q','p','H','X','u','y','9','b','U','r','8','A','d','q','i',
1397 '6','S','z','g','H','p','C','n','M','u','5','3','d','x','g','x','U',
1398 'D','1','r','4','x','A','A','=','=',0 };
1399
1400 static void testFileNameStore(void)
1401 {
1402     static const WCHAR szPrefix[] = { 'c','e','r',0 };
1403     static const WCHAR spcPrefix[] = { 's','p','c',0 };
1404     static const WCHAR szDot[] = { '.',0 };
1405     WCHAR filename[MAX_PATH];
1406     HCERTSTORE store;
1407     BOOL ret;
1408     DWORD GLE;
1409
1410     if (0)
1411     {
1412         /* Crashes on NT4 */
1413         store = CertOpenStore(CERT_STORE_PROV_FILENAME_W, 0, 0, 0, NULL);
1414         GLE = GetLastError();
1415         ok(!store && (GLE == ERROR_PATH_NOT_FOUND || GLE == ERROR_INVALID_PARAMETER),
1416          "Expected ERROR_PATH_NOT_FOUND or ERROR_INVALID_PARAMETER, got %08x\n",
1417          GLE);
1418     }
1419
1420     if (!GetTempFileNameW(szDot, szPrefix, 0, filename))
1421        return;
1422     DeleteFileW(filename);
1423
1424     /* The two flags are mutually exclusive */
1425     store = CertOpenStore(CERT_STORE_PROV_FILENAME_W, 0, 0,
1426      CERT_FILE_STORE_COMMIT_ENABLE_FLAG | CERT_STORE_READONLY_FLAG, filename);
1427     ok(!store && GetLastError() == E_INVALIDARG,
1428      "Expected E_INVALIDARG, got %08x\n", GetLastError());
1429
1430     /* In all of the following tests, the encoding type seems to be ignored */
1431     if (initFileFromData(filename, bigCert, sizeof(bigCert)))
1432     {
1433         PCCERT_CONTEXT cert;
1434         PCCRL_CONTEXT crl;
1435
1436         store = CertOpenStore(CERT_STORE_PROV_FILENAME_W, 0, 0,
1437          CERT_STORE_READONLY_FLAG, filename);
1438         ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError());
1439
1440         cert = CertEnumCertificatesInStore(store, NULL);
1441         ok(cert != NULL, "CertEnumCertificatesInStore failed: %08x\n",
1442          GetLastError());
1443         cert = CertEnumCertificatesInStore(store, cert);
1444         ok(!cert, "Expected only one cert\n");
1445         if (pCertEnumCRLsInStore)
1446         {
1447             crl = pCertEnumCRLsInStore(store, NULL);
1448             ok(!crl, "Expected no CRLs\n");
1449         }
1450
1451         CertCloseStore(store, 0);
1452         DeleteFileW(filename);
1453     }
1454     if (initFileFromData(filename, serializedStoreWithCert,
1455      sizeof(serializedStoreWithCert)))
1456     {
1457         PCCERT_CONTEXT cert;
1458         PCCRL_CONTEXT crl;
1459
1460         store = CertOpenStore(CERT_STORE_PROV_FILENAME_W, 0, 0,
1461          CERT_STORE_READONLY_FLAG, filename);
1462         ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError());
1463
1464         cert = CertEnumCertificatesInStore(store, NULL);
1465         ok(cert != NULL, "CertEnumCertificatesInStore failed: %08x\n",
1466          GetLastError());
1467         cert = CertEnumCertificatesInStore(store, cert);
1468         ok(!cert, "Expected only one cert\n");
1469         if (pCertEnumCRLsInStore)
1470         {
1471             crl = pCertEnumCRLsInStore(store, NULL);
1472             ok(!crl, "Expected no CRLs\n");
1473         }
1474
1475         CertCloseStore(store, 0);
1476         DeleteFileW(filename);
1477     }
1478     if (initFileFromData(filename, serializedStoreWithCertAndCRL,
1479      sizeof(serializedStoreWithCertAndCRL)))
1480     {
1481         PCCERT_CONTEXT cert;
1482         PCCRL_CONTEXT crl;
1483
1484         store = CertOpenStore(CERT_STORE_PROV_FILENAME_W, 0, 0,
1485          CERT_STORE_READONLY_FLAG, filename);
1486         ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError());
1487
1488         cert = CertEnumCertificatesInStore(store, NULL);
1489         ok(cert != NULL, "CertEnumCertificatesInStore failed: %08x\n",
1490          GetLastError());
1491         cert = CertEnumCertificatesInStore(store, cert);
1492         ok(!cert, "Expected only one cert\n");
1493         if (pCertEnumCRLsInStore)
1494         {
1495             crl = pCertEnumCRLsInStore(store, NULL);
1496             ok(crl != NULL, "CertEnumCRLsInStore failed: %08x\n", GetLastError());
1497             crl = pCertEnumCRLsInStore(store, crl);
1498             ok(!crl, "Expected only one CRL\n");
1499         }
1500
1501         CertCloseStore(store, 0);
1502         /* Don't delete it this time, the next test uses it */
1503     }
1504     /* Now that the file exists, we can open it read-only */
1505     store = CertOpenStore(CERT_STORE_PROV_FILENAME_W, 0, 0,
1506      CERT_STORE_READONLY_FLAG, filename);
1507     ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError());
1508     CertCloseStore(store, 0);
1509     DeleteFileW(filename);
1510
1511     store = CertOpenStore(CERT_STORE_PROV_FILENAME_W, 0, 0,
1512      CERT_FILE_STORE_COMMIT_ENABLE_FLAG | CERT_STORE_CREATE_NEW_FLAG, filename);
1513     ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError());
1514     if (store)
1515     {
1516         ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1517          bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, NULL);
1518         ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
1519          GetLastError());
1520         CertCloseStore(store, 0);
1521         compareFile(filename, serializedStoreWithCert,
1522          sizeof(serializedStoreWithCert));
1523     }
1524     store = CertOpenStore(CERT_STORE_PROV_FILENAME_W, 0, 0,
1525      CERT_FILE_STORE_COMMIT_ENABLE_FLAG, filename);
1526     ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError());
1527     if (store)
1528     {
1529         ret = CertAddEncodedCRLToStore(store, X509_ASN_ENCODING,
1530          signedCRL, sizeof(signedCRL), CERT_STORE_ADD_ALWAYS, NULL);
1531         ok(ret, "CertAddEncodedCRLToStore failed: %08x\n", GetLastError());
1532         CertCloseStore(store, 0);
1533         compareFile(filename, serializedStoreWithCertAndCRL,
1534          sizeof(serializedStoreWithCertAndCRL));
1535     }
1536     DeleteFileW(filename);
1537
1538     if (!GetTempFileNameW(szDot, spcPrefix, 0, filename))
1539        return;
1540     DeleteFileW(filename);
1541
1542     if (initFileFromData(filename, base64SPC, sizeof(base64SPC)))
1543     {
1544         PCCERT_CONTEXT cert;
1545         PCCRL_CONTEXT crl;
1546
1547         store = CertOpenStore(CERT_STORE_PROV_FILENAME_W, 0, 0,
1548          CERT_STORE_READONLY_FLAG, filename);
1549         ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError());
1550
1551         cert = CertEnumCertificatesInStore(store, NULL);
1552         ok(cert != NULL, "CertEnumCertificatesInStore failed: %08x\n",
1553          GetLastError());
1554         cert = CertEnumCertificatesInStore(store, cert);
1555         ok(!cert, "Expected only one cert\n");
1556         if (pCertEnumCRLsInStore)
1557         {
1558             crl = pCertEnumCRLsInStore(store, NULL);
1559             ok(!crl, "Expected no CRLs\n");
1560         }
1561
1562         CertCloseStore(store, 0);
1563         DeleteFileW(filename);
1564     }
1565     if (initFileFromData(filename, (BYTE *)utf16Base64SPC,
1566      sizeof(utf16Base64SPC)))
1567     {
1568         PCCERT_CONTEXT cert;
1569         PCCRL_CONTEXT crl;
1570
1571         store = CertOpenStore(CERT_STORE_PROV_FILENAME_W, 0, 0,
1572          CERT_STORE_READONLY_FLAG, filename);
1573         ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError());
1574
1575         cert = CertEnumCertificatesInStore(store, NULL);
1576         ok(cert != NULL, "CertEnumCertificatesInStore failed: %08x\n",
1577          GetLastError());
1578         cert = CertEnumCertificatesInStore(store, cert);
1579         ok(!cert, "Expected only one cert\n");
1580         if (pCertEnumCRLsInStore)
1581         {
1582             crl = pCertEnumCRLsInStore(store, NULL);
1583             ok(!crl, "Expected no CRLs\n");
1584         }
1585
1586         CertCloseStore(store, 0);
1587         DeleteFileW(filename);
1588     }
1589 }
1590
1591 static const BYTE signedContent[] = {
1592 0x30,0x81,0xb2,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,0xa0,
1593 0x81,0xa4,0x30,0x81,0xa1,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,
1594 0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x13,0x06,0x09,0x2a,0x86,
1595 0x48,0x86,0xf7,0x0d,0x01,0x07,0x01,0xa0,0x06,0x04,0x04,0x01,0x02,0x03,0x04,
1596 0x31,0x77,0x30,0x75,0x02,0x01,0x01,0x30,0x1a,0x30,0x15,0x31,0x13,0x30,0x11,
1597 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
1598 0x67,0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,
1599 0x02,0x05,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04,0x40,0x81,0xa6,0x70,
1600 0xb3,0xef,0x59,0xd1,0x66,0xd1,0x9b,0xc0,0x9a,0xb6,0x9a,0x5e,0x6d,0x6f,0x6d,
1601 0x0d,0x59,0xa9,0xaa,0x6e,0xe9,0x2c,0xa0,0x1e,0xee,0xc2,0x60,0xbc,0x59,0xbe,
1602 0x3f,0x63,0x06,0x8d,0xc9,0x11,0x1d,0x23,0x64,0x92,0xef,0x2e,0xfc,0x57,0x29,
1603 0xa4,0xaf,0xe0,0xee,0x93,0x19,0x39,0x51,0xe4,0x44,0xb8,0x0b,0x28,0xf4,0xa8,
1604 0x0d };
1605 static const BYTE signedWithCertAndCrlBareContent[] = {
1606 0x30,0x82,0x01,0x4f,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,0x86,
1607 0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x13,0x06,0x09,0x2a,0x86,0x48,
1608 0x86,0xf7,0x0d,0x01,0x07,0x01,0xa0,0x06,0x04,0x04,0x01,0x02,0x03,0x04,0xa0,
1609 0x7c,0x30,0x7a,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,
1610 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
1611 0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,
1612 0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
1613 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,
1614 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
1615 0x67,0x00,0x30,0x07,0x30,0x02,0x06,0x00,0x03,0x01,0x00,0xa3,0x16,0x30,0x14,
1616 0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,
1617 0x01,0xff,0x02,0x01,0x01,0xa1,0x2e,0x30,0x2c,0x30,0x02,0x06,0x00,0x30,0x15,
1618 0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,
1619 0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
1620 0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x31,0x77,0x30,0x75,0x02,0x01,0x01,
1621 0x30,0x1a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,
1622 0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x02,0x01,0x01,0x30,0x0c,
1623 0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x04,0x06,
1624 0x00,0x05,0x00,0x04,0x40,0x81,0xa6,0x70,0xb3,0xef,0x59,0xd1,0x66,0xd1,0x9b,
1625 0xc0,0x9a,0xb6,0x9a,0x5e,0x6d,0x6f,0x6d,0x0d,0x59,0xa9,0xaa,0x6e,0xe9,0x2c,
1626 0xa0,0x1e,0xee,0xc2,0x60,0xbc,0x59,0xbe,0x3f,0x63,0x06,0x8d,0xc9,0x11,0x1d,
1627 0x23,0x64,0x92,0xef,0x2e,0xfc,0x57,0x29,0xa4,0xaf,0xe0,0xee,0x93,0x19,0x39,
1628 0x51,0xe4,0x44,0xb8,0x0b,0x28,0xf4,0xa8,0x0d };
1629 static const BYTE hashContent[] = {
1630 0x30,0x47,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x05,0xa0,0x3a,
1631 0x30,0x38,0x02,0x01,0x00,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,
1632 0x02,0x05,0x05,0x00,0x30,0x13,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
1633 0x07,0x01,0xa0,0x06,0x04,0x04,0x01,0x02,0x03,0x04,0x04,0x10,0x08,0xd6,0xc0,
1634 0x5a,0x21,0x51,0x2a,0x79,0xa1,0xdf,0xeb,0x9d,0x2a,0x8f,0x26,0x2f };
1635 static const BYTE hashBareContent[] = {
1636 0x30,0x38,0x02,0x01,0x00,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,
1637 0x02,0x05,0x05,0x00,0x30,0x13,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
1638 0x07,0x01,0xa0,0x06,0x04,0x04,0x01,0x02,0x03,0x04,0x04,0x10,0x08,0xd6,0xc0,
1639 0x5a,0x21,0x51,0x2a,0x79,0xa1,0xdf,0xeb,0x9d,0x2a,0x8f,0x26,0x2f };
1640
1641 static void testMessageStore(void)
1642 {
1643     HCERTSTORE store;
1644     HCRYPTMSG msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL,
1645      NULL);
1646     CRYPT_DATA_BLOB blob = { sizeof(signedWithCertAndCrlBareContent),
1647      (LPBYTE)signedWithCertAndCrlBareContent };
1648     DWORD count, size;
1649     BOOL ret;
1650
1651     /* Crashes
1652     store = CertOpenStore(CERT_STORE_PROV_MSG, 0, 0, 0, NULL);
1653      */
1654     SetLastError(0xdeadbeef);
1655     store = CertOpenStore(CERT_STORE_PROV_MSG, 0, 0, 0, msg);
1656     ok(!store && GetLastError() == CRYPT_E_INVALID_MSG_TYPE,
1657      "Expected CRYPT_E_INVALID_MSG_TYPE, got %08x\n", GetLastError());
1658     CryptMsgUpdate(msg, signedContent, sizeof(signedContent), TRUE);
1659     store = CertOpenStore(CERT_STORE_PROV_MSG, 0, 0, 0, msg);
1660     ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError());
1661     if (store)
1662     {
1663         PCCERT_CONTEXT cert = NULL;
1664         PCCRL_CONTEXT crl = NULL;
1665
1666         count = 0;
1667         do {
1668             cert = CertEnumCertificatesInStore(store, cert);
1669             if (cert)
1670                 count++;
1671         } while (cert);
1672         ok(count == 0, "Expected 0 certificates, got %d\n", count);
1673
1674         if (pCertEnumCRLsInStore)
1675         {
1676             count = 0;
1677             do {
1678                 crl = pCertEnumCRLsInStore(store, crl);
1679                 if (crl)
1680                     count++;
1681             } while (crl);
1682             ok(count == 0, "Expected 0 CRLs, got %d\n", count);
1683         }
1684
1685         /* Can add certs to a message store */
1686         ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1687          bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, NULL);
1688         ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
1689          GetLastError());
1690         count = 0;
1691         do {
1692             cert = CertEnumCertificatesInStore(store, cert);
1693             if (cert)
1694                 count++;
1695         } while (cert);
1696         ok(count == 1, "Expected 1 certificate, got %d\n", count);
1697
1698         CertCloseStore(store, 0);
1699     }
1700     /* but the added certs weren't actually added to the message */
1701     size = sizeof(count);
1702     ret = CryptMsgGetParam(msg, CMSG_CERT_COUNT_PARAM, 0, &count, &size);
1703     ok(ret, "CryptMsgGetParam failed: %08x\n", GetLastError());
1704     ok(count == 0, "Expected 0 certificates, got %d\n", count);
1705     CryptMsgClose(msg);
1706
1707     /* Crashes
1708     store = CertOpenStore(CERT_STORE_PROV_PKCS7, 0, 0, 0, NULL);
1709      */
1710     store = CertOpenStore(CERT_STORE_PROV_PKCS7, 0, 0, 0, &blob);
1711     ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError());
1712     if (store)
1713     {
1714         DWORD count = 0;
1715         PCCERT_CONTEXT cert = NULL;
1716         PCCRL_CONTEXT crl = NULL;
1717
1718         do {
1719             cert = CertEnumCertificatesInStore(store, cert);
1720             if (cert)
1721                 count++;
1722         } while (cert);
1723         ok(count == 1, "Expected 1 certificate, got %d\n", count);
1724
1725         if (pCertEnumCRLsInStore)
1726         {
1727             count = 0;
1728             do {
1729                 crl = pCertEnumCRLsInStore(store, crl);
1730                 if (crl)
1731                     count++;
1732             } while (crl);
1733             ok(count == 1, "Expected 1 CRL, got %d\n", count);
1734         }
1735         CertCloseStore(store, 0);
1736     }
1737     /* Encoding appears to be ignored */
1738     store = CertOpenStore(CERT_STORE_PROV_PKCS7, X509_ASN_ENCODING, 0, 0,
1739      &blob);
1740     ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError());
1741     if (store)
1742         CertCloseStore(store, 0);
1743     /* Messages other than signed messages aren't allowed */
1744     blob.cbData = sizeof(hashContent);
1745     blob.pbData = (LPBYTE)hashContent;
1746     SetLastError(0xdeadbeef);
1747     store = CertOpenStore(CERT_STORE_PROV_PKCS7, 0, 0, 0, &blob);
1748     ok(!store && GetLastError() == CRYPT_E_INVALID_MSG_TYPE,
1749      "Expected CRYPT_E_INVALID_MSG_TYPE, got %08x\n", GetLastError());
1750     blob.cbData = sizeof(hashBareContent);
1751     blob.pbData = (LPBYTE)hashBareContent;
1752     SetLastError(0xdeadbeef);
1753     store = CertOpenStore(CERT_STORE_PROV_PKCS7, 0, 0, 0, &blob);
1754     ok(!store &&
1755      (GetLastError() == CRYPT_E_ASN1_BADTAG ||
1756       GetLastError() == OSS_DATA_ERROR), /* win9x */
1757      "Expected CRYPT_E_ASN1_BADTAG, got %08x\n", GetLastError());
1758 }
1759
1760 static void testCertOpenSystemStore(void)
1761 {
1762     HCERTSTORE store;
1763
1764     store = CertOpenSystemStoreW(0, NULL);
1765     ok(!store && GetLastError() == E_INVALIDARG,
1766      "Expected E_INVALIDARG, got %08x\n", GetLastError());
1767     /* This succeeds, and on WinXP at least, the Bogus key is created under
1768      * HKCU (but not under HKLM, even when run as an administrator.)
1769      */
1770     store = CertOpenSystemStoreW(0, BogusW);
1771     ok(store != 0, "CertOpenSystemStore failed: %08x\n", GetLastError());
1772     if (store)
1773         CertCloseStore(store, 0);
1774     /* Delete it so other tests succeed next time around */
1775     store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0,
1776      CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_DELETE_FLAG, BogusW);
1777     RegDeleteKeyW(HKEY_CURRENT_USER, BogusPathW);
1778 }
1779
1780 struct EnumSystemStoreInfo
1781 {
1782     BOOL  goOn;
1783     DWORD storeCount;
1784 };
1785
1786 static BOOL CALLBACK enumSystemStoreCB(const void *systemStore, DWORD dwFlags,
1787  PCERT_SYSTEM_STORE_INFO pStoreInfo, void *pvReserved, void *pvArg)
1788 {
1789     struct EnumSystemStoreInfo *info = pvArg;
1790
1791     info->storeCount++;
1792     return info->goOn;
1793 }
1794
1795 static void testCertEnumSystemStore(void)
1796 {
1797     BOOL ret;
1798     struct EnumSystemStoreInfo info = { FALSE, 0 };
1799
1800     if (!pCertEnumSystemStore)
1801     {
1802         win_skip("CertEnumSystemStore() is not available\n");
1803         return;
1804     }
1805
1806     SetLastError(0xdeadbeef);
1807     ret = pCertEnumSystemStore(0, NULL, NULL, NULL);
1808     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
1809      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
1810     /* Crashes
1811     ret = pCertEnumSystemStore(CERT_SYSTEM_STORE_LOCAL_MACHINE, NULL, NULL,
1812      NULL);
1813      */
1814
1815     SetLastError(0xdeadbeef);
1816     ret = pCertEnumSystemStore(CERT_SYSTEM_STORE_LOCAL_MACHINE, NULL, &info,
1817      enumSystemStoreCB);
1818     /* Callback returning FALSE stops enumeration */
1819     ok(!ret, "Expected CertEnumSystemStore to stop\n");
1820     ok(info.storeCount == 0 || info.storeCount == 1,
1821      "Expected 0 or 1 stores\n");
1822
1823     info.goOn = TRUE;
1824     info.storeCount = 0;
1825     ret = pCertEnumSystemStore(CERT_SYSTEM_STORE_LOCAL_MACHINE, NULL, &info,
1826      enumSystemStoreCB);
1827     ok(ret, "CertEnumSystemStore failed: %08x\n", GetLastError());
1828     /* There should always be at least My, Root, and CA stores */
1829     ok(info.storeCount == 0 || info.storeCount >= 3,
1830      "Expected at least 3 stores\n");
1831 }
1832
1833 static void testStoreProperty(void)
1834 {
1835     HCERTSTORE store;
1836     BOOL ret;
1837     DWORD propID, size = 0, state;
1838     CRYPT_DATA_BLOB blob;
1839
1840     if (!pCertGetStoreProperty || !pCertSetStoreProperty)
1841     {
1842         win_skip("CertGet/SetStoreProperty() is not available\n");
1843         return;
1844     }
1845
1846     /* Crash
1847     ret = pCertGetStoreProperty(NULL, 0, NULL, NULL);
1848     ret = pCertGetStoreProperty(NULL, 0, NULL, &size);
1849     ret = pCertGetStoreProperty(store, 0, NULL, NULL);
1850      */
1851
1852     store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
1853      CERT_STORE_CREATE_NEW_FLAG, NULL);
1854     /* Check a missing prop ID */
1855     SetLastError(0xdeadbeef);
1856     ret = pCertGetStoreProperty(store, 0, NULL, &size);
1857     ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
1858      "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
1859     /* Contrary to MSDN, CERT_ACCESS_STATE_PROP_ID is supported for stores.. */
1860     size = sizeof(state);
1861     ret = pCertGetStoreProperty(store, CERT_ACCESS_STATE_PROP_ID, &state, &size);
1862     ok(ret, "CertGetStoreProperty failed for CERT_ACCESS_STATE_PROP_ID: %08x\n",
1863      GetLastError());
1864     ok(!state, "Expected a non-persisted store\n");
1865     /* and CERT_STORE_LOCALIZED_NAME_PROP_ID isn't supported by default. */
1866     size = 0;
1867     ret = pCertGetStoreProperty(store, CERT_STORE_LOCALIZED_NAME_PROP_ID, NULL,
1868      &size);
1869     ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
1870      "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
1871     /* Delete an arbitrary property on a store */
1872     ret = pCertSetStoreProperty(store, CERT_FIRST_USER_PROP_ID, 0, NULL);
1873     ok(ret, "CertSetStoreProperty failed: %08x\n", GetLastError());
1874     /* Set an arbitrary property on a store */
1875     blob.pbData = (LPBYTE)&state;
1876     blob.cbData = sizeof(state);
1877     ret = pCertSetStoreProperty(store, CERT_FIRST_USER_PROP_ID, 0, &blob);
1878     ok(ret, "CertSetStoreProperty failed: %08x\n", GetLastError());
1879     /* Get an arbitrary property that's been set */
1880     ret = pCertGetStoreProperty(store, CERT_FIRST_USER_PROP_ID, NULL, &size);
1881     ok(ret, "CertGetStoreProperty failed: %08x\n", GetLastError());
1882     ok(size == sizeof(state), "Unexpected data size %d\n", size);
1883     ret = pCertGetStoreProperty(store, CERT_FIRST_USER_PROP_ID, &propID, &size);
1884     ok(ret, "CertGetStoreProperty failed: %08x\n", GetLastError());
1885     ok(propID == state, "CertGetStoreProperty got the wrong value\n");
1886     /* Delete it again */
1887     ret = pCertSetStoreProperty(store, CERT_FIRST_USER_PROP_ID, 0, NULL);
1888     ok(ret, "CertSetStoreProperty failed: %08x\n", GetLastError());
1889     /* And check that it's missing */
1890     SetLastError(0xdeadbeef);
1891     ret = pCertGetStoreProperty(store, CERT_FIRST_USER_PROP_ID, NULL, &size);
1892     ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
1893      "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
1894     CertCloseStore(store, 0);
1895
1896     /* Recheck on the My store.. */
1897     store = CertOpenSystemStoreW(0, MyW);
1898     size = sizeof(state);
1899     ret = pCertGetStoreProperty(store, CERT_ACCESS_STATE_PROP_ID, &state, &size);
1900     ok(ret, "CertGetStoreProperty failed for CERT_ACCESS_STATE_PROP_ID: %08x\n",
1901      GetLastError());
1902     ok(state, "Expected a persisted store\n");
1903     SetLastError(0xdeadbeef);
1904     size = 0;
1905     ret = pCertGetStoreProperty(store, CERT_STORE_LOCALIZED_NAME_PROP_ID, NULL,
1906      &size);
1907     ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
1908      "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
1909     CertCloseStore(store, 0);
1910 }
1911
1912 static void testAddSerialized(void)
1913 {
1914     BOOL ret;
1915     HCERTSTORE store;
1916     BYTE buf[sizeof(struct CertPropIDHeader) * 2 + 20 + sizeof(bigCert)] =
1917      { 0 };
1918     BYTE hash[20];
1919     struct CertPropIDHeader *hdr;
1920     PCCERT_CONTEXT context;
1921
1922     ret = CertAddSerializedElementToStore(0, NULL, 0, 0, 0, 0, NULL, NULL);
1923     ok(!ret && GetLastError() == ERROR_END_OF_MEDIA,
1924      "Expected ERROR_END_OF_MEDIA, got %08x\n", GetLastError());
1925
1926     store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
1927      CERT_STORE_CREATE_NEW_FLAG, NULL);
1928     ok(store != 0, "CertOpenStore failed: %08x\n", GetLastError());
1929
1930     ret = CertAddSerializedElementToStore(store, NULL, 0, 0, 0, 0, NULL, NULL);
1931     ok(!ret && GetLastError() == ERROR_END_OF_MEDIA,
1932      "Expected ERROR_END_OF_MEDIA, got %08x\n", GetLastError());
1933
1934     /* Test with an empty property */
1935     hdr = (struct CertPropIDHeader *)buf;
1936     hdr->propID = CERT_CERT_PROP_ID;
1937     hdr->unknown1 = 1;
1938     hdr->cb = 0;
1939     ret = CertAddSerializedElementToStore(store, buf, sizeof(buf), 0, 0, 0,
1940      NULL, NULL);
1941     ok(!ret && GetLastError() == E_INVALIDARG,
1942      "Expected E_INVALIDARG, got %08x\n", GetLastError());
1943     /* Test with a bad size in property header */
1944     hdr->cb = sizeof(bigCert) - 1;
1945     memcpy(buf + sizeof(struct CertPropIDHeader), bigCert, sizeof(bigCert));
1946     ret = CertAddSerializedElementToStore(store, buf, sizeof(buf), 0, 0, 0,
1947      NULL, NULL);
1948     ok(!ret && GetLastError() == E_INVALIDARG,
1949      "Expected E_INVALIDARG, got %08x\n", GetLastError());
1950     ret = CertAddSerializedElementToStore(store, buf,
1951      sizeof(struct CertPropIDHeader) + sizeof(bigCert), 0, 0, 0, NULL,
1952      NULL);
1953     ok(!ret && GetLastError() == E_INVALIDARG,
1954      "Expected E_INVALIDARG, got %08x\n", GetLastError());
1955     ret = CertAddSerializedElementToStore(store, buf,
1956      sizeof(struct CertPropIDHeader) + sizeof(bigCert), CERT_STORE_ADD_NEW,
1957      0, 0, NULL, NULL);
1958     ok(!ret && GetLastError() == E_INVALIDARG,
1959      "Expected E_INVALIDARG, got %08x\n", GetLastError());
1960     /* Kosher size in property header, but no context type */
1961     hdr->cb = sizeof(bigCert);
1962     ret = CertAddSerializedElementToStore(store, buf, sizeof(buf), 0, 0, 0,
1963      NULL, NULL);
1964     ok(!ret && GetLastError() == E_INVALIDARG,
1965      "Expected E_INVALIDARG, got %08x\n", GetLastError());
1966     ret = CertAddSerializedElementToStore(store, buf,
1967      sizeof(struct CertPropIDHeader) + sizeof(bigCert), 0, 0, 0, NULL,
1968      NULL);
1969     ok(!ret && GetLastError() == E_INVALIDARG,
1970      "Expected E_INVALIDARG, got %08x\n", GetLastError());
1971     ret = CertAddSerializedElementToStore(store, buf,
1972      sizeof(struct CertPropIDHeader) + sizeof(bigCert), CERT_STORE_ADD_NEW,
1973      0, 0, NULL, NULL);
1974     ok(!ret && GetLastError() == E_INVALIDARG,
1975      "Expected E_INVALIDARG, got %08x\n", GetLastError());
1976     /* With a bad context type */
1977     ret = CertAddSerializedElementToStore(store, buf, sizeof(buf), 0, 0, 
1978      CERT_STORE_CRL_CONTEXT_FLAG, NULL, NULL);
1979     ok(!ret && GetLastError() == E_INVALIDARG,
1980      "Expected E_INVALIDARG, got %08x\n", GetLastError());
1981     ret = CertAddSerializedElementToStore(store, buf,
1982      sizeof(struct CertPropIDHeader) + sizeof(bigCert), 0, 0, 
1983      CERT_STORE_CRL_CONTEXT_FLAG, NULL, NULL);
1984     ok(!ret && GetLastError() == E_INVALIDARG,
1985      "Expected E_INVALIDARG, got %08x\n", GetLastError());
1986     ret = CertAddSerializedElementToStore(store, buf,
1987      sizeof(struct CertPropIDHeader) + sizeof(bigCert), CERT_STORE_ADD_NEW,
1988      0, CERT_STORE_CRL_CONTEXT_FLAG, NULL, NULL);
1989     ok(!ret && GetLastError() == E_INVALIDARG,
1990      "Expected E_INVALIDARG, got %08x\n", GetLastError());
1991     /* Bad unknown field, good type */
1992     hdr->unknown1 = 2;
1993     ret = CertAddSerializedElementToStore(store, buf, sizeof(buf), 0, 0, 
1994      CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL, NULL);
1995     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
1996      "Expected ERROR_FILE_NOT_FOUND got %08x\n", GetLastError());
1997     ret = CertAddSerializedElementToStore(store, buf,
1998      sizeof(struct CertPropIDHeader) + sizeof(bigCert), 0, 0, 
1999      CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL, NULL);
2000     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2001      "Expected ERROR_FILE_NOT_FOUND got %08x\n", GetLastError());
2002     ret = CertAddSerializedElementToStore(store, buf,
2003      sizeof(struct CertPropIDHeader) + sizeof(bigCert), CERT_STORE_ADD_NEW,
2004      0, CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL, NULL);
2005     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2006      "Expected ERROR_FILE_NOT_FOUND got %08x\n", GetLastError());
2007     /* Most everything okay, but bad add disposition */
2008     hdr->unknown1 = 1;
2009     /* This crashes
2010     ret = CertAddSerializedElementToStore(store, buf, sizeof(buf), 0, 0, 
2011      CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL, NULL);
2012      * as does this
2013     ret = CertAddSerializedElementToStore(store, buf,
2014      sizeof(struct CertPropIDHeader) + sizeof(bigCert), 0, 0, 
2015      CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL, NULL);
2016      */
2017     /* Everything okay, but buffer's too big */
2018     ret = CertAddSerializedElementToStore(store, buf, sizeof(buf),
2019      CERT_STORE_ADD_NEW, 0, CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL, NULL);
2020     ok(ret, "CertAddSerializedElementToStore failed: %08x\n", GetLastError());
2021     /* Everything okay, check it's not re-added */
2022     ret = CertAddSerializedElementToStore(store, buf,
2023      sizeof(struct CertPropIDHeader) + sizeof(bigCert), CERT_STORE_ADD_NEW,
2024      0, CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL, NULL);
2025     ok(!ret && GetLastError() == CRYPT_E_EXISTS,
2026      "Expected CRYPT_E_EXISTS, got %08x\n", GetLastError());
2027
2028     context = CertEnumCertificatesInStore(store, NULL);
2029     ok(context != NULL, "Expected a cert\n");
2030     if (context)
2031         CertDeleteCertificateFromStore(context);
2032
2033     /* Try adding with a bogus hash.  Oddly enough, it succeeds, and the hash,
2034      * when queried, is the real hash rather than the bogus hash.
2035      */
2036     hdr = (struct CertPropIDHeader *)(buf + sizeof(struct CertPropIDHeader) +
2037      sizeof(bigCert));
2038     hdr->propID = CERT_HASH_PROP_ID;
2039     hdr->unknown1 = 1;
2040     hdr->cb = sizeof(hash);
2041     memset(hash, 0xc, sizeof(hash));
2042     memcpy((LPBYTE)hdr + sizeof(struct CertPropIDHeader), hash, sizeof(hash));
2043     ret = CertAddSerializedElementToStore(store, buf, sizeof(buf),
2044      CERT_STORE_ADD_NEW, 0, CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL,
2045      (const void **)&context);
2046     ok(ret, "CertAddSerializedElementToStore failed: %08x\n", GetLastError());
2047     if (context)
2048     {
2049         BYTE hashVal[20], realHash[20];
2050         DWORD size = sizeof(hashVal);
2051
2052         ret = CryptHashCertificate(0, 0, 0, bigCert, sizeof(bigCert),
2053          realHash, &size);
2054         ok(ret, "CryptHashCertificate failed: %08x\n", GetLastError());
2055         ret = CertGetCertificateContextProperty(context, CERT_HASH_PROP_ID,
2056          hashVal, &size);
2057         ok(ret, "CertGetCertificateContextProperty failed: %08x\n",
2058          GetLastError());
2059         ok(!memcmp(hashVal, realHash, size), "Unexpected hash\n");
2060         CertFreeCertificateContext(context);
2061     }
2062
2063     CertCloseStore(store, 0);
2064 }
2065
2066 static void compareStore(HCERTSTORE store, LPCSTR name, const BYTE *pb,
2067  DWORD cb, BOOL todo)
2068 {
2069     BOOL ret;
2070     CRYPT_DATA_BLOB blob = { 0, NULL };
2071
2072     ret = CertSaveStore(store, X509_ASN_ENCODING, CERT_STORE_SAVE_AS_STORE,
2073      CERT_STORE_SAVE_TO_MEMORY, &blob, 0);
2074     ok(ret, "CertSaveStore failed: %08x\n", GetLastError());
2075     if (todo)
2076         todo_wine
2077         ok(blob.cbData == cb, "%s: expected size %d, got %d\n", name, cb,
2078          blob.cbData);
2079     else
2080         ok(blob.cbData == cb, "%s: expected size %d, got %d\n", name, cb,
2081          blob.cbData);
2082     blob.pbData = HeapAlloc(GetProcessHeap(), 0, blob.cbData);
2083     if (blob.pbData)
2084     {
2085         ret = CertSaveStore(store, X509_ASN_ENCODING, CERT_STORE_SAVE_AS_STORE,
2086          CERT_STORE_SAVE_TO_MEMORY, &blob, 0);
2087         ok(ret, "CertSaveStore failed: %08x\n", GetLastError());
2088         if (todo)
2089             todo_wine
2090             ok(!memcmp(pb, blob.pbData, cb), "%s: unexpected value\n", name);
2091         else
2092             ok(!memcmp(pb, blob.pbData, cb), "%s: unexpected value\n", name);
2093         HeapFree(GetProcessHeap(), 0, blob.pbData);
2094     }
2095 }
2096
2097 static const BYTE serializedCertWithFriendlyName[] = {
2098 0x0b,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x12,0x00,0x00,0x00,0x57,0x00,0x69,
2099 0x00,0x6e,0x00,0x65,0x00,0x54,0x00,0x65,0x00,0x73,0x00,0x74,0x00,0x00,0x00,
2100 0x20,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x7c,0x00,0x00,0x00,0x30,0x7a,0x02,
2101 0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,
2102 0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x30,
2103 0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,
2104 0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,
2105 0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,
2106 0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x30,0x07,
2107 0x30,0x02,0x06,0x00,0x03,0x01,0x00,0xa3,0x16,0x30,0x14,0x30,0x12,0x06,0x03,
2108 0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,
2109 0x01 };
2110 static const BYTE serializedStoreWithCertWithFriendlyName[] = {
2111 0x00,0x00,0x00,0x00,0x43,0x45,0x52,0x54,0x0b,0x00,0x00,0x00,0x01,0x00,0x00,
2112 0x00,0x12,0x00,0x00,0x00,0x57,0x00,0x69,0x00,0x6e,0x00,0x65,0x00,0x54,0x00,
2113 0x65,0x00,0x73,0x00,0x74,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x01,0x00,0x00,
2114 0x00,0x7c,0x00,0x00,0x00,0x30,0x7a,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,
2115 0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,
2116 0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,
2117 0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,
2118 0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,
2119 0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,
2120 0x20,0x4c,0x61,0x6e,0x67,0x00,0x30,0x07,0x30,0x02,0x06,0x00,0x03,0x01,0x00,
2121 0xa3,0x16,0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,
2122 0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,
2123 0x00,0x00,0x00,0x00,0x00,0x00 };
2124 static const BYTE serializedStoreWithCertAndHash[] = {
2125 0x00,0x00,0x00,0x00,0x43,0x45,0x52,0x54,0x03,0x00,0x00,0x00,0x01,0x00,0x00,
2126 0x00,0x14,0x00,0x00,0x00,0x6e,0x30,0x90,0x71,0x5f,0xd9,0x23,0x56,0xeb,0xae,
2127 0x25,0x40,0xe6,0x22,0xda,0x19,0x26,0x02,0xa6,0x08,0x20,0x00,0x00,0x00,0x01,
2128 0x00,0x00,0x00,0x7c,0x00,0x00,0x00,0x30,0x7a,0x02,0x01,0x01,0x30,0x02,0x06,
2129 0x00,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,
2130 0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,
2131 0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,
2132 0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,
2133 0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,
2134 0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x30,0x07,0x30,0x02,0x06,0x00,0x03,
2135 0x01,0x00,0xa3,0x16,0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,
2136 0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01,0x00,0x00,0x00,0x00,
2137 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 };
2138
2139 static void testAddCertificateLink(void)
2140 {
2141     BOOL ret;
2142     HCERTSTORE store1, store2;
2143     PCCERT_CONTEXT source, linked;
2144     DWORD size;
2145     LPBYTE buf;
2146     CERT_NAME_BLOB blob;
2147     static const WCHAR szPrefix[] = { 'c','e','r',0 };
2148     static const WCHAR szDot[] = { '.',0 };
2149     static const WCHAR WineTestW[] = { 'W','i','n','e','T','e','s','t',0 };
2150     WCHAR filename1[MAX_PATH], filename2[MAX_PATH];
2151     HANDLE file;
2152
2153     if (0)
2154     {
2155         /* Crashes, i.e. the store is dereferenced without checking. */
2156         ret = CertAddCertificateLinkToStore(NULL, NULL, 0, NULL);
2157     }
2158
2159     /* Adding a certificate link to a store requires a valid add disposition */
2160     store1 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
2161      CERT_STORE_CREATE_NEW_FLAG, NULL);
2162     SetLastError(0xdeadbeef);
2163     ret = CertAddCertificateLinkToStore(store1, NULL, 0, NULL);
2164     ok(!ret && GetLastError() == E_INVALIDARG,
2165      "expected E_INVALIDARG, got %08x\n", GetLastError());
2166     source = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert,
2167      sizeof(bigCert));
2168     SetLastError(0xdeadbeef);
2169     ret = CertAddCertificateLinkToStore(store1, source, 0, NULL);
2170     ok(!ret && GetLastError() == E_INVALIDARG,
2171      "expected E_INVALIDARG, got %08x\n", GetLastError());
2172     ret = CertAddCertificateLinkToStore(store1, source, CERT_STORE_ADD_ALWAYS,
2173      NULL);
2174     ok(ret, "CertAddCertificateLinkToStore failed: %08x\n", GetLastError());
2175     if (0)
2176     {
2177         /* Crashes, i.e. the source certificate is dereferenced without
2178          * checking when a valid add disposition is given.
2179          */
2180         ret = CertAddCertificateLinkToStore(store1, NULL, CERT_STORE_ADD_ALWAYS,
2181          NULL);
2182     }
2183     CertCloseStore(store1, 0);
2184
2185     store1 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
2186      CERT_STORE_CREATE_NEW_FLAG, NULL);
2187     ret = CertAddCertificateLinkToStore(store1, source, CERT_STORE_ADD_ALWAYS,
2188      &linked);
2189     ok(ret, "CertAddCertificateLinkToStore failed: %08x\n", GetLastError());
2190     if (ret)
2191     {
2192         ok(linked->hCertStore == store1, "unexpected store");
2193         ret = CertSerializeCertificateStoreElement(linked, 0, NULL, &size);
2194         ok(ret, "CertSerializeCertificateStoreElement failed: %08x\n",
2195          GetLastError());
2196         buf = HeapAlloc(GetProcessHeap(), 0, size);
2197         if (buf)
2198         {
2199             ret = CertSerializeCertificateStoreElement(linked, 0, buf, &size);
2200             /* The serialized linked certificate is identical to the serialized
2201              * original certificate.
2202              */
2203             ok(size == sizeof(serializedCert), "Wrong size %d\n", size);
2204             ok(!memcmp(serializedCert, buf, size),
2205              "Unexpected serialized cert\n");
2206             HeapFree(GetProcessHeap(), 0, buf);
2207         }
2208         /* Set a friendly name on the source certificate... */
2209         blob.pbData = (LPBYTE)WineTestW;
2210         blob.cbData = sizeof(WineTestW);
2211         ret = CertSetCertificateContextProperty(source,
2212          CERT_FRIENDLY_NAME_PROP_ID, 0, &blob);
2213         ok(ret, "CertSetCertificateContextProperty failed: %08x\n",
2214          GetLastError());
2215         /* and the linked certificate has the same friendly name. */
2216         ret = CertGetCertificateContextProperty(linked,
2217          CERT_FRIENDLY_NAME_PROP_ID, NULL, &size);
2218         ok(ret, "CertGetCertificateContextProperty failed: %08x\n",
2219          GetLastError());
2220         buf = HeapAlloc(GetProcessHeap(), 0, size);
2221         if (buf)
2222         {
2223             ret = CertGetCertificateContextProperty(linked,
2224              CERT_FRIENDLY_NAME_PROP_ID, buf, &size);
2225             ok(!lstrcmpW((LPCWSTR)buf, WineTestW),
2226              "unexpected friendly name\n");
2227             HeapFree(GetProcessHeap(), 0, buf);
2228         }
2229         CertFreeCertificateContext(linked);
2230     }
2231     CertFreeCertificateContext(source);
2232     CertCloseStore(store1, 0);
2233
2234     /* Test adding a cert to a file store, committing the change to the store,
2235      * and creating a link to the resulting cert.
2236      */
2237     if (!GetTempFileNameW(szDot, szPrefix, 0, filename1))
2238        return;
2239
2240     DeleteFileW(filename1);
2241     file = CreateFileW(filename1, GENERIC_READ | GENERIC_WRITE, 0, NULL,
2242      CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
2243     if (file == INVALID_HANDLE_VALUE)
2244         return;
2245
2246     store1 = CertOpenStore(CERT_STORE_PROV_FILE, 0, 0,
2247      CERT_FILE_STORE_COMMIT_ENABLE_FLAG, file);
2248     ok(store1 != NULL, "CertOpenStore failed: %08x\n", GetLastError());
2249     CloseHandle(file);
2250
2251     ret = CertAddEncodedCertificateToStore(store1, X509_ASN_ENCODING,
2252      bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, &source);
2253     ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
2254      GetLastError());
2255
2256     /* Test adding a link to a memory store. */
2257     store2 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
2258      CERT_STORE_CREATE_NEW_FLAG, NULL);
2259     ret = CertAddCertificateLinkToStore(store2, source, CERT_STORE_ADD_ALWAYS,
2260      &linked);
2261     ok(ret, "CertAddCertificateLinkToStore failed: %08x\n", GetLastError());
2262     if (ret)
2263     {
2264         ok(linked->hCertStore == store2, "unexpected store");
2265         ret = CertSerializeCertificateStoreElement(linked, 0, NULL, &size);
2266         ok(ret, "CertSerializeCertificateStoreElement failed: %08x\n",
2267          GetLastError());
2268         buf = HeapAlloc(GetProcessHeap(), 0, size);
2269         if (buf)
2270         {
2271             ret = CertSerializeCertificateStoreElement(linked, 0, buf, &size);
2272             /* The serialized linked certificate is identical to the serialized
2273              * original certificate.
2274              */
2275             ok(size == sizeof(serializedCert), "Wrong size %d\n", size);
2276             ok(!memcmp(serializedCert, buf, size),
2277              "Unexpected serialized cert\n");
2278             HeapFree(GetProcessHeap(), 0, buf);
2279         }
2280         /* Set a friendly name on the source certificate... */
2281         blob.pbData = (LPBYTE)WineTestW;
2282         blob.cbData = sizeof(WineTestW);
2283         ret = CertSetCertificateContextProperty(source,
2284          CERT_FRIENDLY_NAME_PROP_ID, 0, &blob);
2285         ok(ret, "CertSetCertificateContextProperty failed: %08x\n",
2286          GetLastError());
2287         /* and the linked certificate has the same friendly name. */
2288         ret = CertGetCertificateContextProperty(linked,
2289          CERT_FRIENDLY_NAME_PROP_ID, NULL, &size);
2290         ok(ret, "CertGetCertificateContextProperty failed: %08x\n",
2291          GetLastError());
2292         buf = HeapAlloc(GetProcessHeap(), 0, size);
2293         if (buf)
2294         {
2295             ret = CertGetCertificateContextProperty(linked,
2296              CERT_FRIENDLY_NAME_PROP_ID, buf, &size);
2297             ok(!lstrcmpW((LPCWSTR)buf, WineTestW),
2298              "unexpected friendly name\n");
2299             HeapFree(GetProcessHeap(), 0, buf);
2300         }
2301         CertFreeCertificateContext(linked);
2302     }
2303     CertCloseStore(store2, 0);
2304
2305     if (!GetTempFileNameW(szDot, szPrefix, 0, filename2))
2306        return;
2307
2308     DeleteFileW(filename2);
2309     file = CreateFileW(filename2, GENERIC_READ | GENERIC_WRITE, 0, NULL,
2310      CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
2311     if (file == INVALID_HANDLE_VALUE)
2312         return;
2313
2314     store2 = CertOpenStore(CERT_STORE_PROV_FILE, 0, 0,
2315      CERT_FILE_STORE_COMMIT_ENABLE_FLAG, file);
2316     ok(store2 != NULL, "CertOpenStore failed: %08x\n", GetLastError());
2317     CloseHandle(file);
2318     /* Test adding a link to a file store. */
2319     ret = CertAddCertificateLinkToStore(store2, source, CERT_STORE_ADD_ALWAYS,
2320      &linked);
2321     ok(ret, "CertAddCertificateLinkToStore failed: %08x\n", GetLastError());
2322     if (ret)
2323     {
2324         ok(linked->hCertStore == store2, "unexpected store");
2325         ret = CertSerializeCertificateStoreElement(linked, 0, NULL, &size);
2326         ok(ret, "CertSerializeCertificateStoreElement failed: %08x\n",
2327          GetLastError());
2328         buf = HeapAlloc(GetProcessHeap(), 0, size);
2329         if (buf)
2330         {
2331             ret = CertSerializeCertificateStoreElement(linked, 0, buf, &size);
2332             ok(ret, "CertSerializeCertificateStoreElement failed: %08x\n",
2333              GetLastError());
2334             /* The serialized linked certificate now contains the friendly
2335              * name property.
2336              */
2337             ok(size == sizeof(serializedCertWithFriendlyName),
2338              "Wrong size %d\n", size);
2339             ok(!memcmp(serializedCertWithFriendlyName, buf, size),
2340              "Unexpected serialized cert\n");
2341             HeapFree(GetProcessHeap(), 0, buf);
2342         }
2343         CertFreeCertificateContext(linked);
2344         compareStore(store2, "file store -> file store",
2345          serializedStoreWithCertWithFriendlyName,
2346          sizeof(serializedStoreWithCertWithFriendlyName), FALSE);
2347     }
2348     CertCloseStore(store2, 0);
2349     DeleteFileW(filename2);
2350
2351     CertFreeCertificateContext(source);
2352
2353     CertCloseStore(store1, 0);
2354     DeleteFileW(filename1);
2355
2356     /* Test adding a link to a system store (which is a collection store.) */
2357     store1 = CertOpenSystemStoreA(0, "My");
2358     source = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert,
2359      sizeof(bigCert));
2360     SetLastError(0xdeadbeef);
2361     ret = CertAddCertificateLinkToStore(store1, source, CERT_STORE_ADD_ALWAYS,
2362      &linked);
2363     ok(!ret && GetLastError() == E_INVALIDARG,
2364      "expected E_INVALIDARG, got %08x\n", GetLastError());
2365     CertFreeCertificateContext(source);
2366
2367     /* Test adding a link to a file store, where the linked certificate is
2368      * in a system store.
2369      */
2370     ret = CertAddEncodedCertificateToStore(store1, X509_ASN_ENCODING,
2371      bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, &source);
2372     ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
2373      GetLastError());
2374     if (!GetTempFileNameW(szDot, szPrefix, 0, filename1))
2375        return;
2376
2377     DeleteFileW(filename1);
2378     file = CreateFileW(filename1, GENERIC_READ | GENERIC_WRITE, 0, NULL,
2379      CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
2380     if (file == INVALID_HANDLE_VALUE)
2381         return;
2382
2383     store2 = CertOpenStore(CERT_STORE_PROV_FILE, 0, 0,
2384      CERT_FILE_STORE_COMMIT_ENABLE_FLAG, file);
2385     ok(store2 != NULL, "CertOpenStore failed: %08x\n", GetLastError());
2386     CloseHandle(file);
2387
2388     ret = CertAddCertificateLinkToStore(store2, source, CERT_STORE_ADD_ALWAYS,
2389      &linked);
2390     ok(ret, "CertAddCertificateLinkToStore failed: %08x\n", GetLastError());
2391     if (ret)
2392     {
2393         ok(linked->hCertStore == store2, "unexpected store");
2394         ret = pCertControlStore(store2, 0, CERT_STORE_CTRL_COMMIT, NULL);
2395         ok(ret, "CertControlStore failed: %d\n", ret);
2396         compareStore(store2, "file store -> system store",
2397          serializedStoreWithCertAndHash,
2398          sizeof(serializedStoreWithCertAndHash), TRUE);
2399         CertFreeCertificateContext(linked);
2400     }
2401
2402     CertCloseStore(store2, 0);
2403     DeleteFileW(filename1);
2404
2405     /* Test adding a link to a registry store, where the linked certificate is
2406      * in a system store.
2407      */
2408     store2 = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY, 0, 0,
2409      CERT_SYSTEM_STORE_CURRENT_USER, WineTestW);
2410     ok(store2 != NULL, "CertOpenStore failed: %08x\n", GetLastError());
2411     ret = CertAddCertificateLinkToStore(store2, source, CERT_STORE_ADD_ALWAYS,
2412      &linked);
2413     ok(ret, "CertAddCertificateLinkToStore failed: %08x\n", GetLastError());
2414     if (ret)
2415     {
2416         ok(linked->hCertStore == store2, "unexpected store");
2417         CertDeleteCertificateFromStore(linked);
2418     }
2419     CertCloseStore(store2, 0);
2420
2421     CertFreeCertificateContext(source);
2422     CertCloseStore(store1, 0);
2423 }
2424
2425 static DWORD countCertsInStore(HCERTSTORE store)
2426 {
2427     PCCERT_CONTEXT cert = NULL;
2428     DWORD certs = 0;
2429
2430     do {
2431         cert = CertEnumCertificatesInStore(store, cert);
2432         if (cert)
2433             certs++;
2434     } while (cert);
2435     return certs;
2436 }
2437
2438 static DWORD countCRLsInStore(HCERTSTORE store)
2439 {
2440     PCCRL_CONTEXT crl = NULL;
2441     DWORD crls = 0;
2442
2443     do {
2444         crl = pCertEnumCRLsInStore(store, crl);
2445         if (crl)
2446             crls++;
2447     } while (crl);
2448     return crls;
2449 }
2450
2451 static void test_I_UpdateStore(void)
2452 {
2453     HMODULE lib = GetModuleHandleA("crypt32");
2454     BOOL (WINAPI *pI_CertUpdatestore)(HCERTSTORE, HCERTSTORE, DWORD, DWORD) =
2455      (void *)GetProcAddress(lib, "I_CertUpdateStore");
2456     BOOL ret;
2457     HCERTSTORE store1, store2;
2458     PCCERT_CONTEXT cert;
2459     DWORD certs;
2460
2461     if (!pI_CertUpdatestore)
2462     {
2463         win_skip("No I_CertUpdateStore\n");
2464         return;
2465     }
2466     store1 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
2467      CERT_STORE_CREATE_NEW_FLAG, NULL);
2468     store2 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
2469      CERT_STORE_CREATE_NEW_FLAG, NULL);
2470
2471     /* Crash
2472     ret = pI_CertUpdatestore(NULL, NULL, 0, 0);
2473     ret = pI_CertUpdatestore(store1, NULL, 0, 0);
2474     ret = pI_CertUpdatestore(NULL, store2, 0, 0);
2475      */
2476     ret = pI_CertUpdatestore(store1, store2, 0, 0);
2477     ok(ret, "I_CertUpdateStore failed: %08x\n", GetLastError());
2478
2479     CertAddEncodedCertificateToStore(store2, X509_ASN_ENCODING, bigCert,
2480      sizeof(bigCert), CERT_STORE_ADD_ALWAYS, &cert);
2481     /* I_CertUpdateStore adds the contexts from store2 to store1 */
2482     ret = pI_CertUpdatestore(store1, store2, 0, 0);
2483     ok(ret, "I_CertUpdateStore failed: %08x\n", GetLastError());
2484     certs = countCertsInStore(store1);
2485     ok(certs == 1, "Expected 1 cert, got %d\n", certs);
2486     /* Calling it a second time has no effect */
2487     ret = pI_CertUpdatestore(store1, store2, 0, 0);
2488     ok(ret, "I_CertUpdateStore failed: %08x\n", GetLastError());
2489     certs = countCertsInStore(store1);
2490     ok(certs == 1, "Expected 1 cert, got %d\n", certs);
2491
2492     /* The last parameters to I_CertUpdateStore appear to be ignored */
2493     ret = pI_CertUpdatestore(store1, store2, 1, 0);
2494     ok(ret, "I_CertUpdateStore failed: %08x\n", GetLastError());
2495     ret = pI_CertUpdatestore(store1, store2, 0, 1);
2496     ok(ret, "I_CertUpdateStore failed: %08x\n", GetLastError());
2497
2498     CertAddEncodedCRLToStore(store2, X509_ASN_ENCODING, signedCRL,
2499      sizeof(signedCRL), CERT_STORE_ADD_ALWAYS, NULL);
2500
2501     /* I_CertUpdateStore also adds the CRLs from store2 to store1 */
2502     ret = pI_CertUpdatestore(store1, store2, 0, 0);
2503     ok(ret, "I_CertUpdateStore failed: %08x\n", GetLastError());
2504     certs = countCertsInStore(store1);
2505     ok(certs == 1, "Expected 1 cert, got %d\n", certs);
2506     if (pCertEnumCRLsInStore)
2507     {
2508         certs = countCRLsInStore(store1);
2509         ok(certs == 1, "Expected 1 CRL, got %d\n", certs);
2510     }
2511
2512     CertDeleteCertificateFromStore(cert);
2513     /* If a context is deleted from store2, I_CertUpdateStore deletes it
2514      * from store1
2515      */
2516     ret = pI_CertUpdatestore(store1, store2, 0, 0);
2517     ok(ret, "I_CertUpdateStore failed: %08x\n", GetLastError());
2518     certs = countCertsInStore(store1);
2519     ok(certs == 0, "Expected 0 certs, got %d\n", certs);
2520
2521     CertCloseStore(store1, 0);
2522     CertCloseStore(store2, 0);
2523 }
2524
2525 START_TEST(store)
2526 {
2527     HMODULE hdll;
2528
2529     hdll = GetModuleHandleA("Crypt32.dll");
2530     pCertAddStoreToCollection = (void*)GetProcAddress(hdll, "CertAddStoreToCollection");
2531     pCertControlStore = (void*)GetProcAddress(hdll, "CertControlStore");
2532     pCertEnumCRLsInStore = (void*)GetProcAddress(hdll, "CertEnumCRLsInStore");
2533     pCertEnumSystemStore = (void*)GetProcAddress(hdll, "CertEnumSystemStore");
2534     pCertGetStoreProperty = (void*)GetProcAddress(hdll, "CertGetStoreProperty");
2535     pCertRemoveStoreFromCollection = (void*)GetProcAddress(hdll, "CertRemoveStoreFromCollection");
2536     pCertSetStoreProperty = (void*)GetProcAddress(hdll, "CertSetStoreProperty");
2537
2538     /* various combinations of CertOpenStore */
2539     testMemStore();
2540     testCollectionStore();
2541     testRegStore();
2542     testSystemRegStore();
2543     testSystemStore();
2544     testFileStore();
2545     testFileNameStore();
2546     testMessageStore();
2547
2548     testCertOpenSystemStore();
2549     testCertEnumSystemStore();
2550     testStoreProperty();
2551
2552     testAddSerialized();
2553     testAddCertificateLink();
2554
2555     test_I_UpdateStore();
2556 }