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 <stdio.h>
22 #include <stdarg.h>
23 
24 #include <windef.h>
25 #include <winbase.h>
26 #include <winuser.h>
27 #include <shlobj.h>
28 #include <shlwapi.h>
29 #include <winreg.h>
30 #include <winerror.h>
31 #include <wincrypt.h>
32 
33 #include "wine/test.h"
34 
35 /* The following aren't defined in wincrypt.h, as they're "reserved" */
36 #define CERT_CERT_PROP_ID 32
37 #define CERT_CRL_PROP_ID  33
38 #define CERT_CTL_PROP_ID  34
39 
40 struct CertPropIDHeader
41 {
42     DWORD propID;
43     DWORD unknown1;
44     DWORD cb;
45 };
46 
47 static const BYTE emptyCert[] = { 0x30, 0x00 };
48 static const BYTE bigCert[] = { 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
49  0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
50  0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x22,
51  0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30,
52  0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30,
53  0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30,
54  0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20,
55  0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01,
56  0x00, 0xa3, 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01,
57  0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
58 static const BYTE signedBigCert[] = {
59  0x30, 0x81, 0x93, 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06, 0x00, 0x30,
60  0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a,
61  0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x22, 0x18, 0x0f,
62  0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
63  0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30,
64  0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06,
65  0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61,
66  0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3,
67  0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff,
68  0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
69  0x00, 0x03, 0x11, 0x00, 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07,
70  0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00 };
71 static const BYTE serializedCert[] = { 0x20, 0x00, 0x00, 0x00,
72  0x01, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x30, 0x7a, 0x02, 0x01, 0x01,
73  0x30, 0x02, 0x06, 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55,
74  0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67,
75  0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31,
76  0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31,
77  0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15,
78  0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75,
79  0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06,
80  0x00, 0x03, 0x01, 0x00, 0xa3, 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55,
81  0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02,
82  0x01, 0x01 };
83 static const BYTE signedCRL[] = { 0x30, 0x45, 0x30, 0x2c, 0x30, 0x02, 0x06,
84  0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
85  0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18, 0x0f,
86  0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
87  0x30, 0x5a, 0x30, 0x02, 0x06, 0x00, 0x03, 0x11, 0x00, 0x0f, 0x0e, 0x0d, 0x0c,
88  0x0b, 0x0a, 0x09, 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00 };
89 static const BYTE bigCert2[] = { 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
90  0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
91  0x0a, 0x41, 0x6c, 0x65, 0x78, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x22,
92  0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30,
93  0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30,
94  0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30,
95  0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x41, 0x6c, 0x65, 0x78, 0x20,
96  0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01,
97  0x00, 0xa3, 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01,
98  0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
99 static const BYTE signedCTLWithCTLInnerContent[] = {
100 0x30,0x82,0x01,0x0f,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,
101 0xa0,0x82,0x01,0x00,0x30,0x81,0xfd,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,
102 0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x30,0x06,0x09,
103 0x2b,0x06,0x01,0x04,0x01,0x82,0x37,0x0a,0x01,0xa0,0x23,0x30,0x21,0x30,0x00,
104 0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,
105 0x30,0x5a,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,
106 0x00,0x31,0x81,0xb5,0x30,0x81,0xb2,0x02,0x01,0x01,0x30,0x1a,0x30,0x15,0x31,
107 0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,
108 0x4c,0x61,0x6e,0x67,0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,
109 0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0xa0,0x3b,0x30,0x18,0x06,0x09,0x2a,0x86,
110 0x48,0x86,0xf7,0x0d,0x01,0x09,0x03,0x31,0x0b,0x06,0x09,0x2b,0x06,0x01,0x04,
111 0x01,0x82,0x37,0x0a,0x01,0x30,0x1f,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,
112 0x01,0x09,0x04,0x31,0x12,0x04,0x10,0x54,0x71,0xbc,0xe1,0x56,0x31,0xa2,0xf9,
113 0x65,0x70,0x34,0xf8,0xe2,0xe9,0xb4,0xf4,0x30,0x04,0x06,0x00,0x05,0x00,0x04,
114 0x40,0x2f,0x1b,0x9f,0x5a,0x4a,0x15,0x73,0xfa,0xb1,0x93,0x3d,0x09,0x52,0xdf,
115 0x6b,0x98,0x4b,0x13,0x5e,0xe7,0xbf,0x65,0xf4,0x9c,0xc2,0xb1,0x77,0x09,0xb1,
116 0x66,0x4d,0x72,0x0d,0xb1,0x1a,0x50,0x20,0xe0,0x57,0xa2,0x39,0xc7,0xcd,0x7f,
117 0x8e,0xe7,0x5f,0x76,0x2b,0xd1,0x6a,0x82,0xb3,0x30,0x25,0x61,0xf6,0x25,0x23,
118 0x57,0x6c,0x0b,0x47,0xb8 };
119 
120 #define test_store_is_empty(store) _test_store_is_empty(__LINE__,store)
121 static void _test_store_is_empty(unsigned line, HCERTSTORE store)
122 {
123     const CERT_CONTEXT *cert;
124 
125     cert = CertEnumCertificatesInStore(store, NULL);
126     ok_(__FILE__,line)(!cert && GetLastError() == CRYPT_E_NOT_FOUND, "store is not empty\n");
127 }
128 
129 static void testMemStore(void)
130 {
131     HCERTSTORE store1, store2;
132     PCCERT_CONTEXT context;
133     BOOL ret;
134     DWORD GLE;
135 
136     /* NULL provider */
137     store1 = CertOpenStore(0, 0, 0, 0, NULL);
138     ok(!store1 && GetLastError() == ERROR_FILE_NOT_FOUND,
139      "Expected ERROR_FILE_NOT_FOUND, got %d\n", GetLastError());
140     /* weird flags */
141     store1 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
142      CERT_STORE_DELETE_FLAG, NULL);
143     ok(!store1 && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED,
144      "Expected ERROR_CALL_NOT_IMPLEMENTED, got %d\n", GetLastError());
145 
146     /* normal */
147     store1 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
148      CERT_STORE_CREATE_NEW_FLAG, NULL);
149     ok(store1 != NULL, "CertOpenStore failed: %d\n", GetLastError());
150     /* open existing doesn't */
151     store2 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
152      CERT_STORE_OPEN_EXISTING_FLAG, NULL);
153     ok(store2 != NULL, "CertOpenStore failed: %d\n", GetLastError());
154     ok(store1 != store2, "Expected different stores\n");
155 
156     /* add a bogus (empty) cert */
157     context = NULL;
158     ret = CertAddEncodedCertificateToStore(store1, X509_ASN_ENCODING, emptyCert,
159      sizeof(emptyCert), CERT_STORE_ADD_ALWAYS, &context);
160     /* Windows returns CRYPT_E_ASN1_EOD or OSS_DATA_ERROR, but accept
161      * CRYPT_E_ASN1_CORRUPT as well (because matching errors is tough in this
162      * case)
163      */
164     GLE = GetLastError();
165     ok(!ret && (GLE == CRYPT_E_ASN1_EOD || GLE == CRYPT_E_ASN1_CORRUPT ||
166      GLE == OSS_DATA_ERROR),
167      "Expected CRYPT_E_ASN1_EOD or CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
168      GLE);
169     /* add a "signed" cert--the signature isn't a real signature, so this adds
170      * without any check of the signature's validity
171      */
172     ret = CertAddEncodedCertificateToStore(store1, X509_ASN_ENCODING,
173      signedBigCert, sizeof(signedBigCert), CERT_STORE_ADD_ALWAYS, &context);
174     ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n", GetLastError());
175     ok(context != NULL, "Expected a valid cert context\n");
176     if (context)
177     {
178         ok(context->cbCertEncoded == sizeof(signedBigCert),
179          "Wrong cert size %d\n", context->cbCertEncoded);
180         ok(!memcmp(context->pbCertEncoded, signedBigCert,
181          sizeof(signedBigCert)), "Unexpected encoded cert in context\n");
182         /* remove it, the rest of the tests will work on an unsigned cert */
183         ret = CertDeleteCertificateFromStore(context);
184         ok(ret, "CertDeleteCertificateFromStore failed: %08x\n",
185          GetLastError());
186     }
187     /* try adding a "signed" CRL as a cert */
188     ret = CertAddEncodedCertificateToStore(store1, X509_ASN_ENCODING,
189      signedCRL, sizeof(signedCRL), CERT_STORE_ADD_ALWAYS, &context);
190     GLE = GetLastError();
191     ok(!ret && (GLE == CRYPT_E_ASN1_BADTAG || GLE == CRYPT_E_ASN1_CORRUPT ||
192      GLE == OSS_DATA_ERROR),
193      "Expected CRYPT_E_ASN1_BADTAG or CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
194      GLE);
195     /* add a cert to store1 */
196     ret = CertAddEncodedCertificateToStore(store1, X509_ASN_ENCODING, bigCert,
197      sizeof(bigCert), CERT_STORE_ADD_ALWAYS, &context);
198     ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n", GetLastError());
199     ok(context != NULL, "Expected a valid cert context\n");
200     if (context)
201     {
202         DWORD size;
203         BYTE *buf;
204 
205         ok(context->cbCertEncoded == sizeof(bigCert),
206          "Wrong cert size %d\n", context->cbCertEncoded);
207         ok(!memcmp(context->pbCertEncoded, bigCert, sizeof(bigCert)),
208          "Unexpected encoded cert in context\n");
209         ok(context->hCertStore == store1, "Unexpected store\n");
210 
211         /* check serializing this element */
212         /* These crash
213         ret = CertSerializeCertificateStoreElement(NULL, 0, NULL, NULL);
214         ret = CertSerializeCertificateStoreElement(context, 0, NULL, NULL);
215         ret = CertSerializeCertificateStoreElement(NULL, 0, NULL, &size);
216          */
217         /* apparently flags are ignored */
218         ret = CertSerializeCertificateStoreElement(context, 1, NULL, &size);
219         ok(ret, "CertSerializeCertificateStoreElement failed: %08x\n",
220          GetLastError());
221         buf = HeapAlloc(GetProcessHeap(), 0, size);
222         if (buf)
223         {
224             ret = CertSerializeCertificateStoreElement(context, 0, buf, &size);
225             ok(ret, "CertSerializeCertificateStoreElement failed: %08x\n", GetLastError());
226             ok(size == sizeof(serializedCert), "Wrong size %d\n", size);
227             ok(!memcmp(serializedCert, buf, size),
228              "Unexpected serialized cert\n");
229             HeapFree(GetProcessHeap(), 0, buf);
230         }
231 
232         ret = CertFreeCertificateContext(context);
233         ok(ret, "CertFreeCertificateContext failed: %08x\n", GetLastError());
234     }
235     /* verify the cert's in store1 */
236     context = CertEnumCertificatesInStore(store1, NULL);
237     ok(context != NULL, "Expected a valid context\n");
238     context = CertEnumCertificatesInStore(store1, context);
239     ok(!context && GetLastError() == CRYPT_E_NOT_FOUND,
240      "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
241     /* verify store2 (the "open existing" mem store) is still empty */
242     context = CertEnumCertificatesInStore(store2, NULL);
243     ok(!context, "Expected an empty store\n");
244     /* delete the cert from store1, and check it's empty */
245     context = CertEnumCertificatesInStore(store1, NULL);
246     if (context)
247     {
248         /* Deleting a bitwise copy crashes with an access to an uninitialized
249          * pointer, so a cert context has some special data out there in memory
250          * someplace
251         CERT_CONTEXT copy;
252         memcpy(&copy, context, sizeof(copy));
253         ret = CertDeleteCertificateFromStore(&copy);
254          */
255         PCCERT_CONTEXT copy = CertDuplicateCertificateContext(context);
256 
257         ok(copy != NULL, "CertDuplicateCertificateContext failed: %08x\n",
258          GetLastError());
259         ret = CertDeleteCertificateFromStore(context);
260         ok(ret, "CertDeleteCertificateFromStore failed: %08x\n",
261          GetLastError());
262         /* try deleting a copy */
263         ret = CertDeleteCertificateFromStore(copy);
264         ok(ret, "CertDeleteCertificateFromStore failed: %08x\n",
265          GetLastError());
266         /* check that the store is empty */
267         context = CertEnumCertificatesInStore(store1, NULL);
268         ok(!context, "Expected an empty store\n");
269     }
270 
271     /* close an empty store */
272     ret = CertCloseStore(NULL, 0);
273     ok(ret, "CertCloseStore failed: %d\n", GetLastError());
274     ret = CertCloseStore(store1, 0);
275     ok(ret, "CertCloseStore failed: %d\n", GetLastError());
276     ret = CertCloseStore(store2, 0);
277     ok(ret, "CertCloseStore failed: %d\n", GetLastError());
278 
279     /* This seems nonsensical, but you can open a read-only mem store, only
280      * it isn't read-only
281      */
282     store1 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
283      CERT_STORE_READONLY_FLAG, NULL);
284     ok(store1 != NULL, "CertOpenStore failed: %d\n", GetLastError());
285     /* yep, this succeeds */
286     ret = CertAddEncodedCertificateToStore(store1, X509_ASN_ENCODING, bigCert,
287      sizeof(bigCert), CERT_STORE_ADD_ALWAYS, &context);
288     ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n", GetLastError());
289     ok(context != NULL, "Expected a valid cert context\n");
290     if (context)
291     {
292         ok(context->cbCertEncoded == sizeof(bigCert),
293          "Wrong cert size %d\n", context->cbCertEncoded);
294         ok(!memcmp(context->pbCertEncoded, bigCert, sizeof(bigCert)),
295          "Unexpected encoded cert in context\n");
296         ok(context->hCertStore == store1, "Unexpected store\n");
297         ret = CertDeleteCertificateFromStore(context);
298         ok(ret, "CertDeleteCertificateFromStore failed: %08x\n",
299          GetLastError());
300     }
301     CertCloseStore(store1, 0);
302 }
303 
304 static void compareStore(HCERTSTORE store, LPCSTR name, const BYTE *pb,
305  DWORD cb, BOOL todo)
306 {
307     BOOL ret;
308     CRYPT_DATA_BLOB blob = { 0, NULL };
309 
310     ret = CertSaveStore(store, X509_ASN_ENCODING, CERT_STORE_SAVE_AS_STORE,
311      CERT_STORE_SAVE_TO_MEMORY, &blob, 0);
312     ok(ret, "CertSaveStore failed: %08x\n", GetLastError());
313     todo_wine_if (todo)
314         ok(blob.cbData == cb, "%s: expected size %d, got %d\n", name, cb,
315          blob.cbData);
316     blob.pbData = HeapAlloc(GetProcessHeap(), 0, blob.cbData);
317     if (blob.pbData)
318     {
319         ret = CertSaveStore(store, X509_ASN_ENCODING, CERT_STORE_SAVE_AS_STORE,
320          CERT_STORE_SAVE_TO_MEMORY, &blob, 0);
321         ok(ret, "CertSaveStore failed: %08x\n", GetLastError());
322         todo_wine_if (todo)
323             ok(!memcmp(pb, blob.pbData, cb), "%s: unexpected value\n", name);
324         HeapFree(GetProcessHeap(), 0, blob.pbData);
325     }
326 }
327 
328 static const BYTE serializedStoreWithCert[] = {
329  0x00,0x00,0x00,0x00,0x43,0x45,0x52,0x54,0x20,0x00,0x00,0x00,0x01,0x00,0x00,
330  0x00,0x7c,0x00,0x00,0x00,0x30,0x7a,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,
331  0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,
332  0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,
333  0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,
334  0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,
335  0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,
336  0x20,0x4c,0x61,0x6e,0x67,0x00,0x30,0x07,0x30,0x02,0x06,0x00,0x03,0x01,0x00,
337  0xa3,0x16,0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,
338  0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,
339  0x00,0x00,0x00,0x00,0x00,0x00 };
340 
341 static const struct
342 {
343     HKEY key;
344     DWORD cert_store;
345     BOOL appdata_file;
346     WCHAR store_name[16];
347     const WCHAR *base_reg_path;
348 } reg_store_saved_certs[] = {
349     { HKEY_LOCAL_MACHINE, CERT_SYSTEM_STORE_LOCAL_MACHINE, FALSE,
350         {'R','O','O','T',0}, CERT_LOCAL_MACHINE_SYSTEM_STORE_REGPATH },
351     { HKEY_LOCAL_MACHINE, CERT_SYSTEM_STORE_LOCAL_MACHINE, FALSE,
352         {'M','Y',0}, CERT_LOCAL_MACHINE_SYSTEM_STORE_REGPATH },
353     { HKEY_LOCAL_MACHINE, CERT_SYSTEM_STORE_LOCAL_MACHINE, FALSE,
354         {'C','A',0}, CERT_LOCAL_MACHINE_SYSTEM_STORE_REGPATH },
355     /* Adding to HKCU\Root triggers safety warning. */
356     { HKEY_CURRENT_USER, CERT_SYSTEM_STORE_CURRENT_USER, TRUE,
357         {'M','Y',0}, CERT_LOCAL_MACHINE_SYSTEM_STORE_REGPATH },
358     { HKEY_CURRENT_USER, CERT_SYSTEM_STORE_CURRENT_USER, FALSE,
359         {'C','A',0}, CERT_LOCAL_MACHINE_SYSTEM_STORE_REGPATH }
360 };
361 
362 /* Testing whether system stores are available for adding new certs
363  * and checking directly in the registry whether they are actually saved or deleted.
364  * Windows treats HKCU\My (at least) as a special case and uses AppData directory
365  * for storing certs, not registry.
366  */
367 static void testRegStoreSavedCerts(void)
368 {
369     static const WCHAR fmt[] =
370         { '%','s','\\','%','s','\\','%','s','\\','%','s',0},
371     ms_certs[] =
372         { 'M','i','c','r','o','s','o','f','t','\\','S','y','s','t','e','m','C','e','r','t','i','f','i','c','a','t','e','s',0},
373     certs[] =
374         {'C','e','r','t','i','f','i','c','a','t','e','s',0},
375     bigCert_hash[] = {
376         '6','E','3','0','9','0','7','1','5','F','D','9','2','3',
377         '5','6','E','B','A','E','2','5','4','0','E','6','2','2',
378         'D','A','1','9','2','6','0','2','A','6','0','8',0};
379     PCCERT_CONTEXT cert1, cert2;
380     HCERTSTORE store;
381     HANDLE cert_file;
382     HRESULT pathres;
383     WCHAR key_name[MAX_PATH], appdata_path[MAX_PATH];
384     HKEY key;
385     BOOL ret;
386     DWORD res,i;
387 
388     for (i = 0; i < ARRAY_SIZE(reg_store_saved_certs); i++)
389     {
390         DWORD err;
391 
392         store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY_W,0,0,
393             reg_store_saved_certs[i].cert_store, reg_store_saved_certs[i].store_name);
394 
395         err = GetLastError();
396         if (!store)
397         {
398             ok (err == ERROR_ACCESS_DENIED, "Failed to create store at %d (%08x)\n", i, err);
399             skip("Insufficient privileges for the test %d\n", i);
400             continue;
401         }
402         ok (store!=NULL, "Failed to open the store at %d, %x\n", i, GetLastError());
403         cert1 = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert, sizeof(bigCert));
404         ok (cert1 != NULL, "Create cert context failed at %d, %x\n", i, GetLastError());
405         ret = CertAddCertificateContextToStore(store, cert1, CERT_STORE_ADD_REPLACE_EXISTING, NULL);
406         /* Addittional skip per Win7, it allows opening HKLM store, but disallows adding certs */
407         err = GetLastError();
408         if (!ret)
409         {
410             ok (err == ERROR_ACCESS_DENIED, "Failed to add certificate to store at %d (%08x)\n", i, err);
411             skip("Insufficient privileges for the test %d\n", i);
412             continue;
413         }
414         ok (ret, "Adding to the store failed at %d, %x\n", i, err);
415         CertFreeCertificateContext(cert1);
416         CertCloseStore(store, 0);
417 
418         wsprintfW(key_name, fmt, reg_store_saved_certs[i].base_reg_path,
419             reg_store_saved_certs[i].store_name, certs, bigCert_hash);
420 
421         if (!reg_store_saved_certs[i].appdata_file)
422         {
423             res = RegOpenKeyExW(reg_store_saved_certs[i].key, key_name, 0, KEY_ALL_ACCESS, &key);
424             ok (!res, "The cert hasn't been saved at %d, %x\n", i, GetLastError());
425             if (!res) RegCloseKey(key);
426         } else
427         {
428             pathres = SHGetFolderPathW(NULL, CSIDL_APPDATA, NULL, 0, appdata_path);
429             ok (pathres == S_OK,
430                 "Failed to get app data path at %d (%x)\n", pathres, GetLastError());
431             if (pathres == S_OK)
432             {
433                 PathAppendW(appdata_path, ms_certs);
434                 PathAppendW(appdata_path, reg_store_saved_certs[i].store_name);
435                 PathAppendW(appdata_path, certs);
436                 PathAppendW(appdata_path, bigCert_hash);
437 
438                 cert_file = CreateFileW(appdata_path, GENERIC_READ, 0, NULL,
439                     OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
440                 todo_wine ok (cert_file != INVALID_HANDLE_VALUE,
441                         "Cert was not saved in AppData at %d (%x)\n", i, GetLastError());
442                 CloseHandle(cert_file);
443             }
444         }
445 
446         /* deleting cert from store */
447         store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY_W,0,0,
448             reg_store_saved_certs[i].cert_store, reg_store_saved_certs[i].store_name);
449         ok (store!=NULL, "Failed to open the store at %d, %x\n", i, GetLastError());
450 
451         cert1 = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert, sizeof(bigCert));
452         ok (cert1 != NULL, "Create cert context failed at %d, %x\n", i, GetLastError());
453 
454         cert2 = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
455             CERT_FIND_EXISTING, cert1, NULL);
456         ok (cert2 != NULL, "Failed to find cert in the store at %d, %x\n", i, GetLastError());
457 
458         ret = CertDeleteCertificateFromStore(cert2);
459         ok (ret, "Failed to delete certificate from store at %d, %x\n", i, GetLastError());
460 
461         CertFreeCertificateContext(cert1);
462         CertFreeCertificateContext(cert2);
463         CertCloseStore(store, 0);
464 
465         res = RegOpenKeyExW(reg_store_saved_certs[i].key, key_name, 0, KEY_ALL_ACCESS, &key);
466         ok (res, "The cert's registry entry should be absent at %i, %x\n", i, GetLastError());
467         if (!res) RegCloseKey(key);
468 
469         if (reg_store_saved_certs[i].appdata_file)
470         {
471             cert_file = CreateFileW(appdata_path, GENERIC_READ, 0, NULL,
472                 OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
473             ok (cert_file == INVALID_HANDLE_VALUE,
474                 "Cert should have been absent in AppData %d\n", i);
475 
476             CloseHandle(cert_file);
477         }
478     }
479 }
480 
481 /**
482  * This test checks that certificate falls into correct store of a collection
483  * depending on the access flags and priorities.
484  */
485 static void testStoresInCollection(void)
486 {
487     PCCERT_CONTEXT cert1, cert2, tcert1;
488     HCERTSTORE collection, ro_store, rw_store, rw_store_2, tstore;
489     static const WCHAR WineTestRO_W[] = { 'W','i','n','e','T','e','s','t','_','R','O',0 },
490                        WineTestRW_W[] = { 'W','i','n','e','T','e','s','t','_','R','W',0 },
491                        WineTestRW2_W[]= { 'W','i','n','e','T','e','s','t','_','R','W','2',0 };
492     BOOL ret;
493 
494     collection = CertOpenStore(CERT_STORE_PROV_COLLECTION, 0, 0,
495         CERT_STORE_CREATE_NEW_FLAG, NULL);
496     ok(collection != NULL, "Failed to init collection store, last error %x\n", GetLastError());
497     /* Add read-only store to collection with very high priority*/
498     ro_store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY_W, 0, 0,
499         CERT_SYSTEM_STORE_CURRENT_USER, WineTestRO_W);
500     ok(ro_store != NULL, "Failed to init ro store %x\n", GetLastError());
501 
502     ret = CertAddStoreToCollection(collection, ro_store, 0, 1000);
503     ok (ret, "Failed to add read-only store to collection %x\n", GetLastError());
504 
505     cert1 = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert, sizeof(bigCert));
506     ok (cert1 != NULL, "Create cert context failed %x\n", GetLastError());
507     ret = CertAddCertificateContextToStore(collection, cert1, CERT_STORE_ADD_ALWAYS, NULL);
508     ok (!ret, "Added cert to collection with single read-only store %x\n", GetLastError());
509 
510     /* Add read-write store to collection with the lowest priority*/
511     rw_store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY_W, 0, 0,
512         CERT_SYSTEM_STORE_CURRENT_USER, WineTestRW_W);
513     ok (rw_store != NULL, "Failed to open rw store %x\n", GetLastError());
514     ret = CertAddStoreToCollection(collection, rw_store, CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
515     ok (ret, "Failed to add rw store to collection %x\n", GetLastError());
516     /** Adding certificate to collection should fall into rw store,
517      *  even though prioirty of the ro_store is higher */
518     ret = CertAddCertificateContextToStore(collection, cert1, CERT_STORE_ADD_REPLACE_EXISTING, NULL);
519     ok (ret, "Failed to add cert to the collection %x\n", GetLastError());
520 
521     tcert1 = CertEnumCertificatesInStore(ro_store, NULL);
522     ok (!tcert1, "Read-only ro_store contains cert\n");
523 
524     tcert1 = CertEnumCertificatesInStore(rw_store, NULL);
525     ok (cert1 && tcert1->cbCertEncoded == cert1->cbCertEncoded,
526         "Unexpected cert in the rw store\n");
527     CertFreeCertificateContext(tcert1);
528 
529     tcert1 = CertEnumCertificatesInStore(collection, NULL);
530     ok (tcert1 && tcert1->cbCertEncoded == cert1->cbCertEncoded,
531         "Unexpected cert in the collection\n");
532     CertFreeCertificateContext(tcert1);
533 
534     /** adding one more rw store with higher priority*/
535     rw_store_2 = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY_W, 0, 0,
536         CERT_SYSTEM_STORE_CURRENT_USER, WineTestRW2_W);
537     ok (rw_store_2 != NULL, "Failed to init second rw store %x\n", GetLastError());
538     ret = CertAddStoreToCollection(collection, rw_store_2, CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 50);
539     ok (ret, "Failed to add rw_store_2 to collection %x\n",GetLastError());
540 
541     cert2 = CertCreateCertificateContext(X509_ASN_ENCODING, signedBigCert, sizeof(signedBigCert));
542     ok (cert2 != NULL, "Failed to create cert context %x\n", GetLastError());
543     ret = CertAddCertificateContextToStore(collection, cert2, CERT_STORE_ADD_REPLACE_EXISTING, NULL);
544     ok (ret, "Failed to add cert2 to the store %x\n",GetLastError());
545 
546     /** checking certificates in the stores */
547     tcert1 = CertEnumCertificatesInStore(ro_store, 0);
548     ok (tcert1 == NULL, "Read-only store not empty\n");
549 
550     tcert1 = CertEnumCertificatesInStore(rw_store, NULL);
551     ok (tcert1 && tcert1->cbCertEncoded == cert1->cbCertEncoded,
552         "Unexpected cert in the rw_store\n");
553     CertFreeCertificateContext(tcert1);
554 
555     tcert1 = CertEnumCertificatesInStore(rw_store_2, NULL);
556     ok (tcert1 && tcert1->cbCertEncoded == cert2->cbCertEncoded,
557         "Unexpected cert in the rw_store_2\n");
558     CertFreeCertificateContext(tcert1);
559 
560     /** checking certificates in the collection */
561     tcert1 = CertEnumCertificatesInStore(collection, NULL);
562     ok (tcert1 && tcert1->cbCertEncoded == cert2->cbCertEncoded,
563         "cert2 expected in the collection got %p, %x\n",tcert1, GetLastError());
564     tcert1 = CertEnumCertificatesInStore(collection, tcert1);
565     ok (tcert1 && tcert1->cbCertEncoded == cert1->cbCertEncoded,
566         "cert1 expected in the collection got %p, %x\n",tcert1, GetLastError());
567     tcert1 = CertEnumCertificatesInStore(collection, tcert1);
568     ok (tcert1==NULL,"Unexpected cert in the collection %p %x\n",tcert1, GetLastError());
569 
570     /* checking whether certs had been saved */
571     tstore = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY_W,0,0,
572         CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_OPEN_EXISTING_FLAG, WineTestRW_W);
573     ok (tstore!=NULL, "Failed to open existing rw store\n");
574     tcert1 = CertEnumCertificatesInStore(tstore, NULL);
575     todo_wine
576         ok(tcert1 && tcert1->cbCertEncoded == cert1->cbCertEncoded, "cert1 wasn't saved\n");
577     CertFreeCertificateContext(tcert1);
578     CertCloseStore(tstore,0);
579 
580     tstore = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY_W,0,0,
581         CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_OPEN_EXISTING_FLAG, WineTestRW2_W);
582     ok (tstore!=NULL, "Failed to open existing rw2 store\n");
583     tcert1 = CertEnumCertificatesInStore(tstore, NULL);
584     todo_wine
585         ok (tcert1 && tcert1->cbCertEncoded == cert2->cbCertEncoded, "cert2 wasn't saved\n");
586     CertFreeCertificateContext(tcert1);
587     CertCloseStore(tstore,0);
588 
589     CertCloseStore(collection,0);
590     CertCloseStore(ro_store,0);
591     CertCloseStore(rw_store,0);
592     CertCloseStore(rw_store_2,0);
593 
594     /* reopening registry stores to check whether certs had been saved */
595     rw_store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY_W,0,0,
596         CERT_SYSTEM_STORE_CURRENT_USER, WineTestRW_W);
597     tcert1 = CertEnumCertificatesInStore(rw_store, NULL);
598     ok (tcert1 && tcert1->cbCertEncoded == cert1->cbCertEncoded,
599         "Unexpected cert in store %p\n", tcert1);
600     CertFreeCertificateContext(tcert1);
601     CertCloseStore(rw_store,0);
602 
603     rw_store_2 = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY_W,0,0,
604         CERT_SYSTEM_STORE_CURRENT_USER, WineTestRW2_W);
605     tcert1 = CertEnumCertificatesInStore(rw_store_2, NULL);
606     ok (tcert1 && tcert1->cbCertEncoded == cert2->cbCertEncoded,
607         "Unexpected cert in store %p\n", tcert1);
608     CertFreeCertificateContext(tcert1);
609     CertCloseStore(rw_store_2,0);
610 
611     CertFreeCertificateContext(cert1);
612     CertFreeCertificateContext(cert2);
613     CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY_W,0,0,
614         CERT_STORE_DELETE_FLAG|CERT_SYSTEM_STORE_CURRENT_USER,WineTestRO_W);
615     CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY_W,0,0,
616         CERT_STORE_DELETE_FLAG|CERT_SYSTEM_STORE_CURRENT_USER,WineTestRW_W);
617     CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY_W,0,0,
618         CERT_STORE_DELETE_FLAG|CERT_SYSTEM_STORE_CURRENT_USER,WineTestRW2_W);
619 
620 }
621 
622 static void testCollectionStore(void)
623 {
624     HCERTSTORE store1, store2, collection, collection2;
625     PCCERT_CONTEXT context;
626     BOOL ret;
627     static const WCHAR szPrefix[] = { 'c','e','r',0 };
628     static const WCHAR szDot[] = { '.',0 };
629     WCHAR filename[MAX_PATH];
630     HANDLE file;
631 
632     collection = CertOpenStore(CERT_STORE_PROV_COLLECTION, 0, 0,
633      CERT_STORE_CREATE_NEW_FLAG, NULL);
634 
635     /* Try adding a cert to any empty collection */
636     ret = CertAddEncodedCertificateToStore(collection, X509_ASN_ENCODING,
637      bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, NULL);
638     ok(!ret && GetLastError() == E_ACCESSDENIED,
639      "Expected E_ACCESSDENIED, got %08x\n", GetLastError());
640 
641     /* Create and add a cert to a memory store */
642     store1 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
643      CERT_STORE_CREATE_NEW_FLAG, NULL);
644     ret = CertAddEncodedCertificateToStore(store1, X509_ASN_ENCODING,
645      bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, NULL);
646     ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n", GetLastError());
647     /* Add the memory store to the collection, without allowing adding */
648     ret = CertAddStoreToCollection(collection, store1, 0, 0);
649     ok(ret, "CertAddStoreToCollection failed: %08x\n", GetLastError());
650     /* Verify the cert is in the collection */
651     context = CertEnumCertificatesInStore(collection, NULL);
652     ok(context != NULL, "Expected a valid context\n");
653     if (context)
654     {
655         ok(context->hCertStore == collection, "Unexpected store\n");
656         CertFreeCertificateContext(context);
657     }
658     /* Check that adding to the collection isn't allowed */
659     ret = CertAddEncodedCertificateToStore(collection, X509_ASN_ENCODING,
660      bigCert2, sizeof(bigCert2), CERT_STORE_ADD_ALWAYS, NULL);
661     ok(!ret && GetLastError() == E_ACCESSDENIED,
662      "Expected E_ACCESSDENIED, got %08x\n", GetLastError());
663 
664     /* Create a new memory store */
665     store2 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
666      CERT_STORE_CREATE_NEW_FLAG, NULL);
667     /* Try adding a store to a non-collection store */
668     ret = CertAddStoreToCollection(store1, store2,
669      CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
670     ok(!ret && GetLastError() == E_INVALIDARG,
671      "Expected E_INVALIDARG, got %08x\n", GetLastError());
672     /* Try adding some bogus stores */
673     /* This crashes in Windows
674     ret = pCertAddStoreToCollection(0, store2,
675      CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
676      */
677     /* This "succeeds"... */
678     ret = CertAddStoreToCollection(collection, 0,
679      CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
680     ok(ret, "CertAddStoreToCollection failed: %08x\n", GetLastError());
681     /* while this crashes.
682     ret = pCertAddStoreToCollection(collection, 1,
683      CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
684      */
685 
686     /* Add it to the collection, this time allowing adding */
687     ret = CertAddStoreToCollection(collection, store2,
688      CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
689     ok(ret, "CertAddStoreToCollection failed: %08x\n", GetLastError());
690     /* Check that adding to the collection is allowed */
691     ret = CertAddEncodedCertificateToStore(collection, X509_ASN_ENCODING,
692      bigCert2, sizeof(bigCert2), CERT_STORE_ADD_ALWAYS, NULL);
693     ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n", GetLastError());
694     /* Now check that it was actually added to store2 */
695     context = CertEnumCertificatesInStore(store2, NULL);
696     ok(context != NULL, "Expected a valid context\n");
697     if (context)
698     {
699         ok(context->hCertStore == store2, "Unexpected store\n");
700         CertFreeCertificateContext(context);
701     }
702     /* Check that the collection has both bigCert and bigCert2.  bigCert comes
703      * first because store1 was added first.
704      */
705     context = CertEnumCertificatesInStore(collection, NULL);
706     ok(context != NULL, "Expected a valid context\n");
707     if (context)
708     {
709         ok(context->hCertStore == collection, "Unexpected store\n");
710         ok(context->cbCertEncoded == sizeof(bigCert),
711          "Wrong size %d\n", context->cbCertEncoded);
712         ok(!memcmp(context->pbCertEncoded, bigCert, context->cbCertEncoded),
713          "Unexpected cert\n");
714         context = CertEnumCertificatesInStore(collection, context);
715         ok(context != NULL, "Expected a valid context\n");
716         if (context)
717         {
718             ok(context->hCertStore == collection, "Unexpected store\n");
719             ok(context->cbCertEncoded == sizeof(bigCert2),
720              "Wrong size %d\n", context->cbCertEncoded);
721             ok(!memcmp(context->pbCertEncoded, bigCert2,
722              context->cbCertEncoded), "Unexpected cert\n");
723             context = CertEnumCertificatesInStore(collection, context);
724             ok(!context, "Unexpected cert\n");
725         }
726     }
727     /* close store2, and check that the collection is unmodified */
728     CertCloseStore(store2, 0);
729     context = CertEnumCertificatesInStore(collection, NULL);
730     ok(context != NULL, "Expected a valid context\n");
731     if (context)
732     {
733         ok(context->hCertStore == collection, "Unexpected store\n");
734         ok(context->cbCertEncoded == sizeof(bigCert),
735          "Wrong size %d\n", context->cbCertEncoded);
736         ok(!memcmp(context->pbCertEncoded, bigCert, context->cbCertEncoded),
737          "Unexpected cert\n");
738         context = CertEnumCertificatesInStore(collection, context);
739         ok(context != NULL, "Expected a valid context\n");
740         if (context)
741         {
742             ok(context->hCertStore == collection, "Unexpected store\n");
743             ok(context->cbCertEncoded == sizeof(bigCert2),
744              "Wrong size %d\n", context->cbCertEncoded);
745             ok(!memcmp(context->pbCertEncoded, bigCert2,
746              context->cbCertEncoded), "Unexpected cert\n");
747             context = CertEnumCertificatesInStore(collection, context);
748             ok(!context, "Unexpected cert\n");
749         }
750     }
751 
752     /* Adding a collection to a collection is legal */
753     collection2 = CertOpenStore(CERT_STORE_PROV_COLLECTION, 0, 0,
754      CERT_STORE_CREATE_NEW_FLAG, NULL);
755     ret = CertAddStoreToCollection(collection2, collection,
756      CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
757     ok(ret, "CertAddStoreToCollection failed: %08x\n", GetLastError());
758     /* check the contents of collection2 */
759     context = CertEnumCertificatesInStore(collection2, NULL);
760     ok(context != NULL, "Expected a valid context\n");
761     if (context)
762     {
763         ok(context->hCertStore == collection2, "Unexpected store\n");
764         ok(context->cbCertEncoded == sizeof(bigCert),
765          "Wrong size %d\n", context->cbCertEncoded);
766         ok(!memcmp(context->pbCertEncoded, bigCert, context->cbCertEncoded),
767          "Unexpected cert\n");
768         context = CertEnumCertificatesInStore(collection2, context);
769         ok(context != NULL, "Expected a valid context\n");
770         if (context)
771         {
772             ok(context->hCertStore == collection2, "Unexpected store\n");
773             ok(context->cbCertEncoded == sizeof(bigCert2),
774              "Wrong size %d\n", context->cbCertEncoded);
775             ok(!memcmp(context->pbCertEncoded, bigCert2,
776              context->cbCertEncoded), "Unexpected cert\n");
777             context = CertEnumCertificatesInStore(collection2, context);
778             ok(!context, "Unexpected cert\n");
779         }
780     }
781 
782     /* I'd like to test closing the collection in the middle of enumeration,
783      * but my tests have been inconsistent.  The first time calling
784      * CertEnumCertificatesInStore on a closed collection succeeded, while the
785      * second crashed.  So anything appears to be fair game.
786      * I'd also like to test removing a store from a collection in the middle
787      * of an enumeration, but my tests in Windows have been inconclusive.
788      * In one scenario it worked.  In another scenario, about a third of the
789      * time this leads to "random" crashes elsewhere in the code.  This
790      * probably means this is not allowed.
791      */
792 
793     CertCloseStore(store1, 0);
794     CertCloseStore(collection, 0);
795     CertCloseStore(collection2, 0);
796 
797     /* Add the same cert to two memory stores, then put them in a collection */
798     store1 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
799      CERT_STORE_CREATE_NEW_FLAG, NULL);
800     ok(store1 != 0, "CertOpenStore failed: %08x\n", GetLastError());
801     store2 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
802      CERT_STORE_CREATE_NEW_FLAG, NULL);
803     ok(store2 != 0, "CertOpenStore failed: %08x\n", GetLastError());
804 
805     ret = CertAddEncodedCertificateToStore(store1, X509_ASN_ENCODING,
806      bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, NULL);
807     ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n", GetLastError());
808     ret = CertAddEncodedCertificateToStore(store2, X509_ASN_ENCODING,
809      bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, NULL);
810     ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n", GetLastError());
811     collection = CertOpenStore(CERT_STORE_PROV_COLLECTION, 0, 0,
812      CERT_STORE_CREATE_NEW_FLAG, NULL);
813     ok(collection != 0, "CertOpenStore failed: %08x\n", GetLastError());
814 
815     ret = CertAddStoreToCollection(collection, store1, CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
816     ok(ret, "CertAddStoreToCollection failed: %08x\n", GetLastError());
817     ret = CertAddStoreToCollection(collection, store2, CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
818     ok(ret, "CertAddStoreToCollection failed: %08x\n", GetLastError());
819 
820     /* Check that the collection has two copies of the same cert */
821     context = CertEnumCertificatesInStore(collection, NULL);
822     ok(context != NULL, "Expected a valid context\n");
823     if (context)
824     {
825         ok(context->hCertStore == collection, "Unexpected store\n");
826         ok(context->cbCertEncoded == sizeof(bigCert),
827          "Wrong size %d\n", context->cbCertEncoded);
828         ok(!memcmp(context->pbCertEncoded, bigCert, context->cbCertEncoded),
829          "Unexpected cert\n");
830         context = CertEnumCertificatesInStore(collection, context);
831         ok(context != NULL, "Expected a valid context\n");
832         if (context)
833         {
834             ok(context->hCertStore == collection, "Unexpected store\n");
835             ok(context->cbCertEncoded == sizeof(bigCert),
836              "Wrong size %d\n", context->cbCertEncoded);
837             ok(!memcmp(context->pbCertEncoded, bigCert, context->cbCertEncoded),
838              "Unexpected cert\n");
839             context = CertEnumCertificatesInStore(collection, context);
840             ok(context == NULL, "Unexpected cert\n");
841         }
842     }
843 
844     /* The following would check whether I can delete an identical cert, rather
845      * than one enumerated from the store.  It crashes, so that means I must
846      * only call CertDeleteCertificateFromStore with contexts enumerated from
847      * the store.
848     context = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert,
849      sizeof(bigCert));
850     ok(context != NULL, "CertCreateCertificateContext failed: %08x\n",
851      GetLastError());
852     if (context)
853     {
854         ret = CertDeleteCertificateFromStore(collection, context);
855         printf("ret is %d, GetLastError is %08x\n", ret, GetLastError());
856         CertFreeCertificateContext(context);
857     }
858      */
859 
860     /* Now check deleting from the collection. */
861     context = CertEnumCertificatesInStore(collection, NULL);
862     ok(context != NULL, "Expected a valid context\n");
863     if (context)
864     {
865         CertDeleteCertificateFromStore(context);
866         /* store1 should now be empty */
867         context = CertEnumCertificatesInStore(store1, NULL);
868         ok(!context, "Unexpected cert\n");
869         /* and there should be one certificate in the collection */
870         context = CertEnumCertificatesInStore(collection, NULL);
871         ok(context != NULL, "Expected a valid cert\n");
872         if (context)
873         {
874             ok(context->hCertStore == collection, "Unexpected store\n");
875             ok(context->cbCertEncoded == sizeof(bigCert),
876              "Wrong size %d\n", context->cbCertEncoded);
877             ok(!memcmp(context->pbCertEncoded, bigCert, context->cbCertEncoded),
878              "Unexpected cert\n");
879         }
880         context = CertEnumCertificatesInStore(collection, context);
881         ok(context == NULL, "Unexpected cert\n");
882     }
883 
884     /* Finally, test removing stores from the collection.  No return
885      *  value, so it's a bit funny to test.
886      */
887     /* This crashes
888      * CertRemoveStoreFromCollection(NULL, NULL);
889      */
890     /* This "succeeds," no crash, no last error set */
891     SetLastError(0xdeadbeef);
892     CertRemoveStoreFromCollection(store2, collection);
893     ok(GetLastError() == 0xdeadbeef,
894        "Didn't expect an error to be set: %08x\n", GetLastError());
895 
896     /* After removing store2, the collection should be empty */
897     SetLastError(0xdeadbeef);
898     CertRemoveStoreFromCollection(collection, store2);
899     ok(GetLastError() == 0xdeadbeef,
900        "Didn't expect an error to be set: %08x\n", GetLastError());
901     context = CertEnumCertificatesInStore(collection, NULL);
902     ok(!context, "Unexpected cert\n");
903 
904     CertCloseStore(collection, 0);
905     CertCloseStore(store2, 0);
906     CertCloseStore(store1, 0);
907 
908     /* Test adding certificates to and deleting certificates from collections.
909      */
910     store1 = CertOpenSystemStoreA(0, "My");
911     collection = CertOpenStore(CERT_STORE_PROV_COLLECTION, 0, 0,
912      CERT_STORE_CREATE_NEW_FLAG, NULL);
913 
914     ret = CertAddEncodedCertificateToStore(store1, X509_ASN_ENCODING,
915      bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, &context);
916     ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n", GetLastError());
917     CertDeleteCertificateFromStore(context);
918 
919     CertAddStoreToCollection(collection, store1, CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
920 
921     ret = CertAddEncodedCertificateToStore(collection, X509_ASN_ENCODING,
922      bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, &context);
923     ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n", GetLastError());
924     CertDeleteCertificateFromStore(context);
925 
926     CertCloseStore(collection, 0);
927     CertCloseStore(store1, 0);
928 
929     /* Test whether a collection store can be committed */
930     collection = CertOpenStore(CERT_STORE_PROV_COLLECTION, 0, 0,
931      CERT_STORE_CREATE_NEW_FLAG, NULL);
932 
933     SetLastError(0xdeadbeef);
934     ret = CertControlStore(collection, 0, CERT_STORE_CTRL_COMMIT, NULL);
935     ok(ret, "CertControlStore failed: %08x\n", GetLastError());
936 
937     /* Adding a mem store that can't be committed prevents a successful commit.
938      */
939     store1 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
940      CERT_STORE_CREATE_NEW_FLAG, NULL);
941     CertAddStoreToCollection(collection, store1, 0, 0);
942     SetLastError(0xdeadbeef);
943     ret = CertControlStore(collection, 0, CERT_STORE_CTRL_COMMIT, NULL);
944     ok(!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED,
945      "expected ERROR_CALL_NOT_IMPLEMENTED, got %d\n", GetLastError());
946     CertRemoveStoreFromCollection(collection, store1);
947     CertCloseStore(store1, 0);
948 
949     /* Test adding a cert to a collection with a file store, committing the
950      * change to the collection, and comparing the resulting file.
951      */
952     if (!GetTempFileNameW(szDot, szPrefix, 0, filename))
953         return;
954 
955     DeleteFileW(filename);
956     file = CreateFileW(filename, GENERIC_READ | GENERIC_WRITE, 0, NULL,
957      CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
958     if (file == INVALID_HANDLE_VALUE)
959         return;
960 
961     store1 = CertOpenStore(CERT_STORE_PROV_FILE, 0, 0,
962      CERT_FILE_STORE_COMMIT_ENABLE_FLAG, file);
963     ok(store1 != NULL, "CertOpenStore failed: %08x\n", GetLastError());
964     CloseHandle(file);
965     CertAddStoreToCollection(collection, store1, CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
966     CertCloseStore(store1, 0);
967 
968     ret = CertAddEncodedCertificateToStore(collection, X509_ASN_ENCODING,
969      bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, NULL);
970     ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
971      GetLastError());
972     ret = CertControlStore(collection, 0, CERT_STORE_CTRL_COMMIT, NULL);
973     ok(ret, "CertControlStore failed: %d\n", ret);
974     compareStore(collection, "serialized store with cert",
975      serializedStoreWithCert, sizeof(serializedStoreWithCert), FALSE);
976     CertCloseStore(collection, 0);
977 
978     DeleteFileW(filename);
979 }
980 
981 /* Looks for the property with ID propID in the buffer buf.  Returns a pointer
982  * to its header if found, NULL if not.
983  */
984 static const struct CertPropIDHeader *findPropID(const BYTE *buf, DWORD size,
985  DWORD propID)
986 {
987     const struct CertPropIDHeader *ret = NULL;
988     BOOL failed = FALSE;
989 
990     while (size && !ret && !failed)
991     {
992         if (size < sizeof(struct CertPropIDHeader))
993             failed = TRUE;
994         else
995         {
996             const struct CertPropIDHeader *hdr =
997              (const struct CertPropIDHeader *)buf;
998 
999             size -= sizeof(struct CertPropIDHeader);
1000             buf += sizeof(struct CertPropIDHeader);
1001             if (size < hdr->cb)
1002                 failed = TRUE;
1003             else if (hdr->propID == propID)
1004                 ret = hdr;
1005             else
1006             {
1007                 buf += hdr->cb;
1008                 size -= hdr->cb;
1009             }
1010         }
1011     }
1012     return ret;
1013 }
1014 
1015 static void testRegStore(void)
1016 {
1017     static const char tempKey[] = "Software\\Wine\\CryptTemp";
1018     HCERTSTORE store;
1019     LONG rc;
1020     HKEY key = NULL;
1021     DWORD disp, GLE;
1022 
1023     store = CertOpenStore(CERT_STORE_PROV_REG, 0, 0, 0, NULL);
1024     GLE = GetLastError();
1025     ok(!store && (GLE == ERROR_INVALID_HANDLE || GLE == ERROR_BADKEY),
1026      "Expected ERROR_INVALID_HANDLE or ERROR_BADKEY, got %d\n", GLE);
1027     store = CertOpenStore(CERT_STORE_PROV_REG, 0, 0, 0, key);
1028     GLE = GetLastError();
1029     ok(!store && (GLE == ERROR_INVALID_HANDLE || GLE == ERROR_BADKEY),
1030      "Expected ERROR_INVALID_HANDLE or ERROR_BADKEY, got %d\n", GLE);
1031 
1032     /* Opening up any old key works.. */
1033     key = HKEY_CURRENT_USER;
1034     store = CertOpenStore(CERT_STORE_PROV_REG, 0, 0, 0, key);
1035     /* Not sure if this is a bug in DuplicateHandle, marking todo_wine for now
1036      */
1037     todo_wine ok(store != 0, "CertOpenStore failed: %08x\n", GetLastError());
1038     CertCloseStore(store, 0);
1039 
1040     rc = RegCreateKeyExA(HKEY_CURRENT_USER, tempKey, 0, NULL, 0, KEY_ALL_ACCESS,
1041      NULL, &key, NULL);
1042     ok(!rc, "RegCreateKeyExA failed: %d\n", rc);
1043     if (key)
1044     {
1045         BOOL ret;
1046         BYTE hash[20];
1047         DWORD size, i;
1048         static const char certificates[] = "Certificates\\";
1049         char subKeyName[sizeof(certificates) + 20 * 2 + 1], *ptr;
1050         HKEY subKey;
1051         PCCERT_CONTEXT context;
1052 
1053         store = CertOpenStore(CERT_STORE_PROV_REG, 0, 0, 0, key);
1054         ok(store != 0, "CertOpenStore failed: %08x\n", GetLastError());
1055         /* Add a certificate.  It isn't persisted right away, since it's only
1056          * added to the cache..
1057          */
1058         ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1059          bigCert2, sizeof(bigCert2), CERT_STORE_ADD_ALWAYS, NULL);
1060         ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
1061          GetLastError());
1062         /* so flush the cache to force a commit.. */
1063         ret = CertControlStore(store, 0, CERT_STORE_CTRL_COMMIT, NULL);
1064         ok(ret, "CertControlStore failed: %08x\n", GetLastError());
1065         /* and check that the expected subkey was written. */
1066         size = sizeof(hash);
1067         ret = CryptHashCertificate(0, 0, 0, bigCert2, sizeof(bigCert2),
1068          hash, &size);
1069         ok(ret, "CryptHashCertificate failed: %d\n", GetLastError());
1070         strcpy(subKeyName, certificates);
1071         for (i = 0, ptr = subKeyName + sizeof(certificates) - 1; i < size;
1072          i++, ptr += 2)
1073             sprintf(ptr, "%02X", hash[i]);
1074         rc = RegCreateKeyExA(key, subKeyName, 0, NULL, 0, KEY_ALL_ACCESS, NULL,
1075          &subKey, NULL);
1076         ok(!rc, "RegCreateKeyExA failed: %d\n", rc);
1077         if (subKey)
1078         {
1079             LPBYTE buf;
1080 
1081             size = 0;
1082             RegQueryValueExA(subKey, "Blob", NULL, NULL, NULL, &size);
1083             buf = HeapAlloc(GetProcessHeap(), 0, size);
1084             if (buf)
1085             {
1086                 rc = RegQueryValueExA(subKey, "Blob", NULL, NULL, buf, &size);
1087                 ok(!rc, "RegQueryValueExA failed: %d\n", rc);
1088                 if (!rc)
1089                 {
1090                     const struct CertPropIDHeader *hdr;
1091 
1092                     /* Both the hash and the cert should be present */
1093                     hdr = findPropID(buf, size, CERT_CERT_PROP_ID);
1094                     ok(hdr != NULL, "Expected to find a cert property\n");
1095                     if (hdr)
1096                     {
1097                         ok(hdr->cb == sizeof(bigCert2),
1098                            "Wrong size %d of cert property\n", hdr->cb);
1099                         ok(!memcmp((const BYTE *)hdr + sizeof(*hdr), bigCert2,
1100                          hdr->cb), "Unexpected cert in cert property\n");
1101                     }
1102                     hdr = findPropID(buf, size, CERT_HASH_PROP_ID);
1103                     ok(hdr != NULL, "Expected to find a hash property\n");
1104                     if (hdr)
1105                     {
1106                         ok(hdr->cb == sizeof(hash),
1107                            "Wrong size %d of hash property\n", hdr->cb);
1108                         ok(!memcmp((const BYTE *)hdr + sizeof(*hdr), hash,
1109                          hdr->cb), "Unexpected hash in cert property\n");
1110                     }
1111                 }
1112                 HeapFree(GetProcessHeap(), 0, buf);
1113             }
1114             RegCloseKey(subKey);
1115         }
1116 
1117         /* Remove the existing context */
1118         context = CertEnumCertificatesInStore(store, NULL);
1119         ok(context != NULL, "Expected a cert context\n");
1120         if (context)
1121             CertDeleteCertificateFromStore(context);
1122         ret = CertControlStore(store, 0, CERT_STORE_CTRL_COMMIT, NULL);
1123         ok(ret, "CertControlStore failed: %08x\n", GetLastError());
1124 
1125         /* Add a serialized cert with a bogus hash directly to the registry */
1126         memset(hash, 0, sizeof(hash));
1127         strcpy(subKeyName, certificates);
1128         for (i = 0, ptr = subKeyName + sizeof(certificates) - 1;
1129          i < sizeof(hash); i++, ptr += 2)
1130             sprintf(ptr, "%02X", hash[i]);
1131         rc = RegCreateKeyExA(key, subKeyName, 0, NULL, 0, KEY_ALL_ACCESS, NULL,
1132          &subKey, NULL);
1133         ok(!rc, "RegCreateKeyExA failed: %d\n", rc);
1134         if (subKey)
1135         {
1136             BYTE buf[sizeof(struct CertPropIDHeader) * 2 + sizeof(hash) +
1137              sizeof(bigCert)], *ptr;
1138             DWORD certCount = 0;
1139             struct CertPropIDHeader *hdr;
1140 
1141             hdr = (struct CertPropIDHeader *)buf;
1142             hdr->propID = CERT_HASH_PROP_ID;
1143             hdr->unknown1 = 1;
1144             hdr->cb = sizeof(hash);
1145             ptr = buf + sizeof(*hdr);
1146             memcpy(ptr, hash, sizeof(hash));
1147             ptr += sizeof(hash);
1148             hdr = (struct CertPropIDHeader *)ptr;
1149             hdr->propID = CERT_CERT_PROP_ID;
1150             hdr->unknown1 = 1;
1151             hdr->cb = sizeof(bigCert);
1152             ptr += sizeof(*hdr);
1153             memcpy(ptr, bigCert, sizeof(bigCert));
1154 
1155             rc = RegSetValueExA(subKey, "Blob", 0, REG_BINARY, buf,
1156              sizeof(buf));
1157             ok(!rc, "RegSetValueExA failed: %d\n", rc);
1158 
1159             ret = CertControlStore(store, 0, CERT_STORE_CTRL_RESYNC, NULL);
1160             ok(ret, "CertControlStore failed: %08x\n", GetLastError());
1161 
1162             /* Make sure the bogus hash cert gets loaded. */
1163             certCount = 0;
1164             context = NULL;
1165             do {
1166                 context = CertEnumCertificatesInStore(store, context);
1167                 if (context)
1168                     certCount++;
1169             } while (context != NULL);
1170             ok(certCount == 1, "Expected 1 certificates, got %d\n", certCount);
1171 
1172             RegCloseKey(subKey);
1173         }
1174 
1175         /* Add another serialized cert directly to the registry, this time
1176          * under the correct key name (named with the correct hash value).
1177          */
1178         size = sizeof(hash);
1179         ret = CryptHashCertificate(0, 0, 0, bigCert2,
1180          sizeof(bigCert2), hash, &size);
1181         ok(ret, "CryptHashCertificate failed: %d\n", GetLastError());
1182         strcpy(subKeyName, certificates);
1183         for (i = 0, ptr = subKeyName + sizeof(certificates) - 1;
1184          i < sizeof(hash); i++, ptr += 2)
1185             sprintf(ptr, "%02X", hash[i]);
1186         rc = RegCreateKeyExA(key, subKeyName, 0, NULL, 0, KEY_ALL_ACCESS, NULL,
1187          &subKey, NULL);
1188         ok(!rc, "RegCreateKeyExA failed: %d\n", rc);
1189         if (subKey)
1190         {
1191             BYTE buf[sizeof(struct CertPropIDHeader) * 2 + sizeof(hash) +
1192              sizeof(bigCert2)], *ptr;
1193             DWORD certCount = 0;
1194             PCCERT_CONTEXT context;
1195             struct CertPropIDHeader *hdr;
1196 
1197             /* First try with a bogus hash... */
1198             hdr = (struct CertPropIDHeader *)buf;
1199             hdr->propID = CERT_HASH_PROP_ID;
1200             hdr->unknown1 = 1;
1201             hdr->cb = sizeof(hash);
1202             ptr = buf + sizeof(*hdr);
1203             memset(ptr, 0, sizeof(hash));
1204             ptr += sizeof(hash);
1205             hdr = (struct CertPropIDHeader *)ptr;
1206             hdr->propID = CERT_CERT_PROP_ID;
1207             hdr->unknown1 = 1;
1208             hdr->cb = sizeof(bigCert2);
1209             ptr += sizeof(*hdr);
1210             memcpy(ptr, bigCert2, sizeof(bigCert2));
1211 
1212             rc = RegSetValueExA(subKey, "Blob", 0, REG_BINARY, buf,
1213              sizeof(buf));
1214             ok(!rc, "RegSetValueExA failed: %d\n", rc);
1215 
1216             ret = CertControlStore(store, 0, CERT_STORE_CTRL_RESYNC, NULL);
1217             ok(ret, "CertControlStore failed: %08x\n", GetLastError());
1218 
1219             /* and make sure just one cert still gets loaded. */
1220             certCount = 0;
1221             context = NULL;
1222             do {
1223                 context = CertEnumCertificatesInStore(store, context);
1224                 if (context)
1225                     certCount++;
1226             } while (context != NULL);
1227             ok(certCount == 1, "Expected 1 certificate, got %d\n", certCount);
1228 
1229             /* Try again with the correct hash... */
1230             ptr = buf + sizeof(*hdr);
1231             memcpy(ptr, hash, sizeof(hash));
1232 
1233             rc = RegSetValueExA(subKey, "Blob", 0, REG_BINARY, buf,
1234              sizeof(buf));
1235             ok(!rc, "RegSetValueExA failed: %d\n", rc);
1236 
1237             ret = CertControlStore(store, 0, CERT_STORE_CTRL_RESYNC, NULL);
1238             ok(ret, "CertControlStore failed: %08x\n", GetLastError());
1239 
1240             /* and make sure two certs get loaded. */
1241             certCount = 0;
1242             context = NULL;
1243             do {
1244                 context = CertEnumCertificatesInStore(store, context);
1245                 if (context)
1246                     certCount++;
1247             } while (context != NULL);
1248             ok(certCount == 2, "Expected 2 certificates, got %d\n", certCount);
1249 
1250             RegCloseKey(subKey);
1251         }
1252         CertCloseStore(store, 0);
1253         /* Is delete allowed on a reg store? */
1254         store = CertOpenStore(CERT_STORE_PROV_REG, 0, 0,
1255          CERT_STORE_DELETE_FLAG, key);
1256         ok(store == NULL, "Expected NULL return from CERT_STORE_DELETE_FLAG\n");
1257         ok(GetLastError() == 0, "CertOpenStore failed: %08x\n",
1258          GetLastError());
1259 
1260         RegCloseKey(key);
1261     }
1262     /* The CertOpenStore with CERT_STORE_DELETE_FLAG above will delete the
1263      * contents of the key, but not the key itself.
1264      */
1265     rc = RegCreateKeyExA(HKEY_CURRENT_USER, tempKey, 0, NULL, 0, KEY_ALL_ACCESS,
1266      NULL, &key, &disp);
1267     ok(!rc, "RegCreateKeyExA failed: %d\n", rc);
1268     ok(disp == REG_OPENED_EXISTING_KEY,
1269      "Expected REG_OPENED_EXISTING_KEY, got %d\n", disp);
1270     if (!rc)
1271     {
1272         RegCloseKey(key);
1273         rc = RegDeleteKeyA(HKEY_CURRENT_USER, tempKey);
1274         if (rc)
1275         {
1276             /* Use shlwapi's SHDeleteKeyA to _really_ blow away the key,
1277              * otherwise subsequent tests will fail.
1278              */
1279             SHDeleteKeyA(HKEY_CURRENT_USER, tempKey);
1280         }
1281     }
1282 }
1283 
1284 static const char MyA[] = { 'M','y',0,0 };
1285 static const WCHAR MyW[] = { 'M','y',0 };
1286 static const WCHAR BogusW[] = { 'B','o','g','u','s',0 };
1287 static const WCHAR BogusPathW[] = { 'S','o','f','t','w','a','r','e','\\',
1288  'M','i','c','r','o','s','o','f','t','\\','S','y','s','t','e','m','C','e','r',
1289  't','i','f','i','c','a','t','e','s','\\','B','o','g','u','s',0 };
1290 
1291 static void testSystemRegStore(void)
1292 {
1293     HCERTSTORE store, memStore;
1294 
1295     /* Check with a UNICODE name */
1296     store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY, 0, 0,
1297      CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_OPEN_EXISTING_FLAG, MyW);
1298     /* Not all OSes support CERT_STORE_PROV_SYSTEM_REGISTRY, so don't continue
1299      * testing if they don't.
1300      */
1301     if (!store)
1302         return;
1303 
1304     /* Check that it isn't a collection store */
1305     memStore = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
1306      CERT_STORE_CREATE_NEW_FLAG, NULL);
1307     if (memStore)
1308     {
1309         BOOL ret = CertAddStoreToCollection(store, memStore, 0, 0);
1310         ok(!ret && GetLastError() == E_INVALIDARG, "Expected E_INVALIDARG, got %08x\n", GetLastError());
1311         CertCloseStore(memStore, 0);
1312     }
1313     CertCloseStore(store, 0);
1314 
1315     /* Check opening a bogus store */
1316     store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY, 0, 0,
1317      CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_OPEN_EXISTING_FLAG, BogusW);
1318     ok(!store && GetLastError() == ERROR_FILE_NOT_FOUND,
1319      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
1320     store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY, 0, 0,
1321      CERT_SYSTEM_STORE_CURRENT_USER, BogusW);
1322     ok(store != 0, "CertOpenStore failed: %08x\n", GetLastError());
1323     if (store)
1324         CertCloseStore(store, 0);
1325     /* Now check whether deleting is allowed */
1326     store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY, 0, 0,
1327      CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_DELETE_FLAG, BogusW);
1328     ok(!store, "CertOpenStore failed: %08x\n", GetLastError());
1329     RegDeleteKeyW(HKEY_CURRENT_USER, BogusPathW);
1330 
1331     store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY, 0, 0, 0, NULL);
1332     ok(!store && GetLastError() == E_INVALIDARG,
1333      "Expected E_INVALIDARG, got %08x\n", GetLastError());
1334     store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY, 0, 0,
1335      CERT_SYSTEM_STORE_LOCAL_MACHINE | CERT_SYSTEM_STORE_CURRENT_USER, MyA);
1336     ok(!store && GetLastError() == E_INVALIDARG,
1337      "Expected E_INVALIDARG, got %08x\n", GetLastError());
1338     store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY, 0, 0,
1339      CERT_SYSTEM_STORE_LOCAL_MACHINE | CERT_SYSTEM_STORE_CURRENT_USER, MyW);
1340     ok(!store && GetLastError() == E_INVALIDARG,
1341      "Expected E_INVALIDARG, got %08x\n", GetLastError());
1342     /* The name is expected to be UNICODE, check with an ASCII name */
1343     store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY, 0, 0,
1344      CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_OPEN_EXISTING_FLAG, MyA);
1345     ok(!store && GetLastError() == ERROR_FILE_NOT_FOUND,
1346      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
1347 }
1348 
1349 static void testSystemStore(void)
1350 {
1351     static const WCHAR baskslashW[] = { '\\',0 };
1352     HCERTSTORE store;
1353     WCHAR keyName[MAX_PATH];
1354     HKEY key;
1355     LONG rc;
1356 
1357     store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0, 0, NULL);
1358     ok(!store && GetLastError() == ERROR_FILE_NOT_FOUND,
1359      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
1360     store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0,
1361      CERT_SYSTEM_STORE_LOCAL_MACHINE | CERT_SYSTEM_STORE_CURRENT_USER, MyA);
1362     ok(!store && GetLastError() == ERROR_FILE_NOT_FOUND,
1363      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
1364     store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0,
1365      CERT_SYSTEM_STORE_LOCAL_MACHINE | CERT_SYSTEM_STORE_CURRENT_USER, MyW);
1366     ok(!store && GetLastError() == ERROR_FILE_NOT_FOUND,
1367      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
1368     /* The name is expected to be UNICODE, first check with an ASCII name */
1369     store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0,
1370      CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_OPEN_EXISTING_FLAG, MyA);
1371     ok(!store && GetLastError() == ERROR_FILE_NOT_FOUND,
1372      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
1373     /* Create the expected key */
1374     lstrcpyW(keyName, CERT_LOCAL_MACHINE_SYSTEM_STORE_REGPATH);
1375     lstrcatW(keyName, baskslashW);
1376     lstrcatW(keyName, MyW);
1377     rc = RegCreateKeyExW(HKEY_CURRENT_USER, keyName, 0, NULL, 0, KEY_READ,
1378      NULL, &key, NULL);
1379     ok(!rc, "RegCreateKeyEx failed: %d\n", rc);
1380     if (!rc)
1381         RegCloseKey(key);
1382     /* Check opening with a UNICODE name, specifying the create new flag */
1383     store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0,
1384      CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_CREATE_NEW_FLAG, MyW);
1385     ok(!store && GetLastError() == ERROR_FILE_EXISTS,
1386      "Expected ERROR_FILE_EXISTS, got %08x\n", GetLastError());
1387     /* Now check opening with a UNICODE name, this time opening existing */
1388     store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0,
1389      CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_OPEN_EXISTING_FLAG, MyW);
1390     ok(store != 0, "CertOpenStore failed: %08x\n", GetLastError());
1391     if (store)
1392     {
1393         HCERTSTORE memStore = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
1394          CERT_STORE_CREATE_NEW_FLAG, NULL);
1395 
1396         /* Check that it's a collection store */
1397         if (memStore)
1398         {
1399             BOOL ret = CertAddStoreToCollection(store, memStore, 0, 0);
1400             ok(ret, "CertAddStoreToCollection failed: %08x\n", GetLastError());
1401             CertCloseStore(memStore, 0);
1402         }
1403         CertCloseStore(store, 0);
1404     }
1405 
1406     /* Check opening a bogus store */
1407     store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0,
1408      CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_OPEN_EXISTING_FLAG, BogusW);
1409     ok(!store, "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
1410     store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0,
1411      CERT_SYSTEM_STORE_CURRENT_USER, BogusW);
1412     ok(store != 0, "CertOpenStore failed: %08x\n", GetLastError());
1413     if (store)
1414         CertCloseStore(store, 0);
1415     /* Now check whether deleting is allowed */
1416     store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0,
1417      CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_DELETE_FLAG, BogusW);
1418     ok(!store, "Didn't expect a store to be returned when deleting\n");
1419     RegDeleteKeyW(HKEY_CURRENT_USER, BogusPathW);
1420 }
1421 
1422 static const BYTE serializedStoreWithCertAndCRL[] = {
1423  0x00,0x00,0x00,0x00,0x43,0x45,0x52,0x54,0x20,0x00,0x00,0x00,0x01,0x00,0x00,
1424  0x00,0x7c,0x00,0x00,0x00,0x30,0x7a,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,
1425  0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,
1426  0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,
1427  0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,
1428  0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,
1429  0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,
1430  0x20,0x4c,0x61,0x6e,0x67,0x00,0x30,0x07,0x30,0x02,0x06,0x00,0x03,0x01,0x00,
1431  0xa3,0x16,0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,
1432  0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01,0x21,0x00,0x00,0x00,0x01,0x00,
1433  0x00,0x00,0x47,0x00,0x00,0x00,0x30,0x45,0x30,0x2c,0x30,0x02,0x06,0x00,0x30,
1434  0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,
1435  0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
1436  0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00,0x03,0x11,
1437  0x00,0x0f,0x0e,0x0d,0x0c,0x0b,0x0a,0x09,0x08,0x07,0x06,0x05,0x04,0x03,0x02,
1438  0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 };
1439 
1440 static void testFileStore(void)
1441 {
1442     static const WCHAR szPrefix[] = { 'c','e','r',0 };
1443     static const WCHAR szDot[] = { '.',0 };
1444     WCHAR filename[MAX_PATH];
1445     HCERTSTORE store;
1446     BOOL ret;
1447     PCCERT_CONTEXT cert;
1448     HANDLE file;
1449 
1450     store = CertOpenStore(CERT_STORE_PROV_FILE, 0, 0, 0, NULL);
1451     ok(!store && GetLastError() == ERROR_INVALID_HANDLE,
1452      "Expected ERROR_INVALID_HANDLE, got %08x\n", GetLastError());
1453 
1454     if (!GetTempFileNameW(szDot, szPrefix, 0, filename))
1455        return;
1456 
1457     DeleteFileW(filename);
1458     file = CreateFileW(filename, GENERIC_READ | GENERIC_WRITE, 0, NULL,
1459      CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
1460     if (file == INVALID_HANDLE_VALUE)
1461         return;
1462 
1463     store = CertOpenStore(CERT_STORE_PROV_FILE, 0, 0, CERT_STORE_DELETE_FLAG,
1464      file);
1465     ok(!store && GetLastError() == E_INVALIDARG,
1466      "Expected E_INVALIDARG, got %08x\n", GetLastError());
1467     store = CertOpenStore(CERT_STORE_PROV_FILE, 0, 0,
1468      CERT_FILE_STORE_COMMIT_ENABLE_FLAG | CERT_STORE_READONLY_FLAG, file);
1469     ok(!store && GetLastError() == E_INVALIDARG,
1470      "Expected E_INVALIDARG, got %08x\n", GetLastError());
1471 
1472     /* A "read-only" file store.. */
1473     store = CertOpenStore(CERT_STORE_PROV_FILE, 0, 0,
1474      CERT_STORE_OPEN_EXISTING_FLAG | CERT_STORE_READONLY_FLAG, file);
1475     ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError());
1476     if (store)
1477     {
1478         DWORD size;
1479 
1480         ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1481          bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, NULL);
1482         /* apparently allows adding certificates.. */
1483         ok(ret, "CertAddEncodedCertificateToStore failed: %d\n", ret);
1484         /* but not commits.. */
1485         ret = CertControlStore(store, 0, CERT_STORE_CTRL_COMMIT, NULL);
1486         ok(!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED,
1487          "Expected ERROR_CALL_NOT_IMPLEMENTED, got %08x\n", GetLastError());
1488         /* It still has certs in memory.. */
1489         cert = CertEnumCertificatesInStore(store, NULL);
1490         ok(cert != NULL, "CertEnumCertificatesInStore failed: %08x\n",
1491          GetLastError());
1492         CertFreeCertificateContext(cert);
1493         /* but the file size is still 0. */
1494         size = GetFileSize(file, NULL);
1495         ok(size == 0, "Expected size 0, got %d\n", size);
1496         CertCloseStore(store, 0);
1497     }
1498 
1499     /* The create new flag is allowed.. */
1500     store = CertOpenStore(CERT_STORE_PROV_FILE, 0, 0,
1501      CERT_STORE_CREATE_NEW_FLAG, file);
1502     ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError());
1503     if (store)
1504     {
1505         /* but without the commit enable flag, commits don't happen. */
1506         ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1507          bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, NULL);
1508         ok(ret, "CertAddEncodedCertificateToStore failed: %d\n", ret);
1509         ret = CertControlStore(store, 0, CERT_STORE_CTRL_COMMIT, NULL);
1510         ok(!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED,
1511          "Expected ERROR_CALL_NOT_IMPLEMENTED, got %08x\n", GetLastError());
1512         CertCloseStore(store, 0);
1513     }
1514     /* as is the open existing flag. */
1515     store = CertOpenStore(CERT_STORE_PROV_FILE, 0, 0,
1516      CERT_STORE_OPEN_EXISTING_FLAG, file);
1517     ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError());
1518     if (store)
1519     {
1520         /* but without the commit enable flag, commits don't happen. */
1521         ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1522          bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, NULL);
1523         ok(ret, "CertAddEncodedCertificateToStore failed: %d\n", ret);
1524         ret = CertControlStore(store, 0, CERT_STORE_CTRL_COMMIT, NULL);
1525         ok(!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED,
1526          "Expected ERROR_CALL_NOT_IMPLEMENTED, got %08x\n", GetLastError());
1527         CertCloseStore(store, 0);
1528     }
1529     store = CertOpenStore(CERT_STORE_PROV_FILE, 0, 0,
1530      CERT_FILE_STORE_COMMIT_ENABLE_FLAG, file);
1531     ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError());
1532     if (store)
1533     {
1534         CloseHandle(file);
1535         ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1536          bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, NULL);
1537         ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
1538          GetLastError());
1539         /* with commits enabled, commit is allowed */
1540         ret = CertControlStore(store, 0, CERT_STORE_CTRL_COMMIT, NULL);
1541         ok(ret, "CertControlStore failed: %d\n", ret);
1542         compareStore(store, "serialized store with cert",
1543          serializedStoreWithCert, sizeof(serializedStoreWithCert), FALSE);
1544         CertCloseStore(store, 0);
1545     }
1546     file = CreateFileW(filename, GENERIC_READ | GENERIC_WRITE, 0, NULL,
1547      OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
1548     if (file == INVALID_HANDLE_VALUE)
1549         return;
1550     store = CertOpenStore(CERT_STORE_PROV_FILE, 0, 0,
1551      CERT_FILE_STORE_COMMIT_ENABLE_FLAG, file);
1552     ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError());
1553     if (store)
1554     {
1555         CloseHandle(file);
1556         ret = CertAddEncodedCRLToStore(store, X509_ASN_ENCODING, signedCRL,
1557          sizeof(signedCRL), CERT_STORE_ADD_ALWAYS, NULL);
1558         ok(ret, "CertAddEncodedCRLToStore failed: %08x\n", GetLastError());
1559         compareStore(store, "serialized store with cert and CRL",
1560          serializedStoreWithCertAndCRL, sizeof(serializedStoreWithCertAndCRL),
1561          FALSE);
1562         CertCloseStore(store, 0);
1563     }
1564 
1565     DeleteFileW(filename);
1566 }
1567 
1568 static BOOL initFileFromData(LPCWSTR filename, const BYTE *pb, DWORD cb)
1569 {
1570     HANDLE file = CreateFileW(filename, GENERIC_READ | GENERIC_WRITE, 0, NULL,
1571      CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
1572     BOOL ret;
1573 
1574     if (file != INVALID_HANDLE_VALUE)
1575     {
1576         DWORD written;
1577 
1578         ret = WriteFile(file, pb, cb, &written, NULL);
1579         CloseHandle(file);
1580     }
1581     else
1582         ret = FALSE;
1583     return ret;
1584 }
1585 
1586 static const BYTE base64SPC[] =
1587 "MIICJQYJKoZIhvcNAQcCoIICFjCCAhICAQExADALBgkqhkiG9w0BBwGgggH6MIIB"
1588 "9jCCAV+gAwIBAgIQnP8+EF4opr9OxH7h4uBPWTANBgkqhkiG9w0BAQQFADAUMRIw"
1589 "EAYDVQQDEwlKdWFuIExhbmcwHhcNMDgxMjEyMTcxMDE0WhcNMzkxMjMxMjM1OTU5"
1590 "WjAUMRIwEAYDVQQDEwlKdWFuIExhbmcwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJ"
1591 "AoGBALCgNjyNvOic0FOfjxvi43HbM+D5joDkhiGSXe+gbZlf8f16k07kkObFEunz"
1592 "mdB5coscmA7gyqiWNN4ZUyr2cA3lCbnpGPA/0IblyyOcuGIFmmCzeZaVa5ZG6xZP"
1593 "K7L7o+73Qo6jXVbGhBGnMZ7Q9sAn6s2933olnStnejnqwV0NAgMBAAGjSTBHMEUG"
1594 "A1UdAQQ+MDyAEFKbKEdXYyx+CWKcV6vxM6ShFjAUMRIwEAYDVQQDEwlKdWFuIExh"
1595 "bmeCEJz/PhBeKKa/TsR+4eLgT1kwDQYJKoZIhvcNAQEEBQADgYEALpkgLgW3mEaK"
1596 "idPQ3iPJYLG0Ub1wraqEl9bd42hrhzIdcDzlQgxnm8/5cHYVxIF/C20x/HJplb1R"
1597 "G6U1ipFe/q8byWD/9JpiBKMGPi9YlUTgXHfS9d4S/QWO1h9Z7KeipBYhoslQpHXu"
1598 "y9bUr8Adqi6SzgHpCnMu53dxgxUD1r4xAA==";
1599 /* Same as base64SPC, but as a wide-char string */
1600 static const WCHAR utf16Base64SPC[] = {
1601 'M','I','I','C','J','Q','Y','J','K','o','Z','I','h','v','c','N','A',
1602 'Q','c','C','o','I','I','C','F','j','C','C','A','h','I','C','A','Q',
1603 'E','x','A','D','A','L','B','g','k','q','h','k','i','G','9','w','0',
1604 'B','B','w','G','g','g','g','H','6','M','I','I','B','9','j','C','C',
1605 'A','V','+','g','A','w','I','B','A','g','I','Q','n','P','8','+','E',
1606 'F','4','o','p','r','9','O','x','H','7','h','4','u','B','P','W','T',
1607 'A','N','B','g','k','q','h','k','i','G','9','w','0','B','A','Q','Q',
1608 'F','A','D','A','U','M','R','I','w','E','A','Y','D','V','Q','Q','D',
1609 'E','w','l','K','d','W','F','u','I','E','x','h','b','m','c','w','H',
1610 'h','c','N','M','D','g','x','M','j','E','y','M','T','c','x','M','D',
1611 'E','0','W','h','c','N','M','z','k','x','M','j','M','x','M','j','M',
1612 '1','O','T','U','5','W','j','A','U','M','R','I','w','E','A','Y','D',
1613 'V','Q','Q','D','E','w','l','K','d','W','F','u','I','E','x','h','b',
1614 'm','c','w','g','Z','8','w','D','Q','Y','J','K','o','Z','I','h','v',
1615 'c','N','A','Q','E','B','B','Q','A','D','g','Y','0','A','M','I','G',
1616 'J','A','o','G','B','A','L','C','g','N','j','y','N','v','O','i','c',
1617 '0','F','O','f','j','x','v','i','4','3','H','b','M','+','D','5','j',
1618 'o','D','k','h','i','G','S','X','e','+','g','b','Z','l','f','8','f',
1619 '1','6','k','0','7','k','k','O','b','F','E','u','n','z','m','d','B',
1620 '5','c','o','s','c','m','A','7','g','y','q','i','W','N','N','4','Z',
1621 'U','y','r','2','c','A','3','l','C','b','n','p','G','P','A','/','0',
1622 'I','b','l','y','y','O','c','u','G','I','F','m','m','C','z','e','Z',
1623 'a','V','a','5','Z','G','6','x','Z','P','K','7','L','7','o','+','7',
1624 '3','Q','o','6','j','X','V','b','G','h','B','G','n','M','Z','7','Q',
1625 '9','s','A','n','6','s','2','9','3','3','o','l','n','S','t','n','e',
1626 'j','n','q','w','V','0','N','A','g','M','B','A','A','G','j','S','T',
1627 'B','H','M','E','U','G','A','1','U','d','A','Q','Q','+','M','D','y',
1628 'A','E','F','K','b','K','E','d','X','Y','y','x','+','C','W','K','c',
1629 'V','6','v','x','M','6','S','h','F','j','A','U','M','R','I','w','E',
1630 'A','Y','D','V','Q','Q','D','E','w','l','K','d','W','F','u','I','E',
1631 'x','h','b','m','e','C','E','J','z','/','P','h','B','e','K','K','a',
1632 '/','T','s','R','+','4','e','L','g','T','1','k','w','D','Q','Y','J',
1633 'K','o','Z','I','h','v','c','N','A','Q','E','E','B','Q','A','D','g',
1634 'Y','E','A','L','p','k','g','L','g','W','3','m','E','a','K','i','d',
1635 'P','Q','3','i','P','J','Y','L','G','0','U','b','1','w','r','a','q',
1636 'E','l','9','b','d','4','2','h','r','h','z','I','d','c','D','z','l',
1637 'Q','g','x','n','m','8','/','5','c','H','Y','V','x','I','F','/','C',
1638 '2','0','x','/','H','J','p','l','b','1','R','G','6','U','1','i','p',
1639 'F','e','/','q','8','b','y','W','D','/','9','J','p','i','B','K','M',
1640 'G','P','i','9','Y','l','U','T','g','X','H','f','S','9','d','4','S',
1641 '/','Q','W','O','1','h','9','Z','7','K','e','i','p','B','Y','h','o',
1642 's','l','Q','p','H','X','u','y','9','b','U','r','8','A','d','q','i',
1643 '6','S','z','g','H','p','C','n','M','u','5','3','d','x','g','x','U',
1644 'D','1','r','4','x','A','A','=','=',0 };
1645 
1646 static void testFileNameStore(void)
1647 {
1648     static const WCHAR szPrefix[] = { 'c','e','r',0 };
1649     static const WCHAR spcPrefix[] = { 's','p','c',0 };
1650     static const WCHAR szDot[] = { '.',0 };
1651     WCHAR filename[MAX_PATH];
1652     HCERTSTORE store;
1653     BOOL ret;
1654     DWORD GLE;
1655 
1656     store = CertOpenStore(CERT_STORE_PROV_FILENAME_W, 0, 0, 0, NULL);
1657     GLE = GetLastError();
1658     ok(!store && (GLE == ERROR_PATH_NOT_FOUND || GLE == ERROR_INVALID_PARAMETER),
1659      "Expected ERROR_PATH_NOT_FOUND or ERROR_INVALID_PARAMETER, got %08x\n",
1660      GLE);
1661 
1662     if (!GetTempFileNameW(szDot, szPrefix, 0, filename))
1663        return;
1664     DeleteFileW(filename);
1665 
1666     /* The two flags are mutually exclusive */
1667     store = CertOpenStore(CERT_STORE_PROV_FILENAME_W, 0, 0,
1668      CERT_FILE_STORE_COMMIT_ENABLE_FLAG | CERT_STORE_READONLY_FLAG, filename);
1669     ok(!store && GetLastError() == E_INVALIDARG,
1670      "Expected E_INVALIDARG, got %08x\n", GetLastError());
1671 
1672     /* In all of the following tests, the encoding type seems to be ignored */
1673     if (initFileFromData(filename, bigCert, sizeof(bigCert)))
1674     {
1675         PCCERT_CONTEXT cert;
1676         PCCRL_CONTEXT crl;
1677 
1678         store = CertOpenStore(CERT_STORE_PROV_FILENAME_W, 0, 0,
1679          CERT_STORE_READONLY_FLAG, filename);
1680         ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError());
1681 
1682         cert = CertEnumCertificatesInStore(store, NULL);
1683         ok(cert != NULL, "CertEnumCertificatesInStore failed: %08x\n",
1684          GetLastError());
1685         cert = CertEnumCertificatesInStore(store, cert);
1686         ok(!cert, "Expected only one cert\n");
1687         crl = CertEnumCRLsInStore(store, NULL);
1688         ok(!crl, "Expected no CRLs\n");
1689 
1690         CertCloseStore(store, 0);
1691         DeleteFileW(filename);
1692     }
1693     if (initFileFromData(filename, serializedStoreWithCert,
1694      sizeof(serializedStoreWithCert)))
1695     {
1696         PCCERT_CONTEXT cert;
1697         PCCRL_CONTEXT crl;
1698 
1699         store = CertOpenStore(CERT_STORE_PROV_FILENAME_W, 0, 0,
1700          CERT_STORE_READONLY_FLAG, filename);
1701         ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError());
1702 
1703         cert = CertEnumCertificatesInStore(store, NULL);
1704         ok(cert != NULL, "CertEnumCertificatesInStore failed: %08x\n",
1705          GetLastError());
1706         cert = CertEnumCertificatesInStore(store, cert);
1707         ok(!cert, "Expected only one cert\n");
1708         crl = CertEnumCRLsInStore(store, NULL);
1709         ok(!crl, "Expected no CRLs\n");
1710 
1711         CertCloseStore(store, 0);
1712         DeleteFileW(filename);
1713     }
1714     if (initFileFromData(filename, serializedStoreWithCertAndCRL,
1715      sizeof(serializedStoreWithCertAndCRL)))
1716     {
1717         PCCERT_CONTEXT cert;
1718         PCCRL_CONTEXT crl;
1719 
1720         store = CertOpenStore(CERT_STORE_PROV_FILENAME_W, 0, 0,
1721          CERT_STORE_READONLY_FLAG, filename);
1722         ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError());
1723 
1724         cert = CertEnumCertificatesInStore(store, NULL);
1725         ok(cert != NULL, "CertEnumCertificatesInStore failed: %08x\n",
1726          GetLastError());
1727         cert = CertEnumCertificatesInStore(store, cert);
1728         ok(!cert, "Expected only one cert\n");
1729         crl = CertEnumCRLsInStore(store, NULL);
1730         ok(crl != NULL, "CertEnumCRLsInStore failed: %08x\n", GetLastError());
1731         crl = CertEnumCRLsInStore(store, crl);
1732         ok(!crl, "Expected only one CRL\n");
1733 
1734         CertCloseStore(store, 0);
1735         /* Don't delete it this time, the next test uses it */
1736     }
1737     /* Now that the file exists, we can open it read-only */
1738     store = CertOpenStore(CERT_STORE_PROV_FILENAME_W, 0, 0,
1739      CERT_STORE_READONLY_FLAG, filename);
1740     ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError());
1741     CertCloseStore(store, 0);
1742     DeleteFileW(filename);
1743 
1744     store = CertOpenStore(CERT_STORE_PROV_FILENAME_W, 0, 0,
1745      CERT_FILE_STORE_COMMIT_ENABLE_FLAG | CERT_STORE_CREATE_NEW_FLAG, filename);
1746     ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError());
1747     if (store)
1748     {
1749         ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1750          bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, NULL);
1751         ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
1752          GetLastError());
1753         compareStore(store, "serialized store with cert",
1754          serializedStoreWithCert, sizeof(serializedStoreWithCert), FALSE);
1755         CertCloseStore(store, 0);
1756     }
1757     store = CertOpenStore(CERT_STORE_PROV_FILENAME_W, 0, 0,
1758      CERT_FILE_STORE_COMMIT_ENABLE_FLAG, filename);
1759     ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError());
1760     if (store)
1761     {
1762         ret = CertAddEncodedCRLToStore(store, X509_ASN_ENCODING,
1763          signedCRL, sizeof(signedCRL), CERT_STORE_ADD_ALWAYS, NULL);
1764         ok(ret, "CertAddEncodedCRLToStore failed: %08x\n", GetLastError());
1765         compareStore(store, "serialized store with cert and CRL",
1766          serializedStoreWithCertAndCRL, sizeof(serializedStoreWithCertAndCRL),
1767          FALSE);
1768         CertCloseStore(store, 0);
1769     }
1770     DeleteFileW(filename);
1771 
1772     if (!GetTempFileNameW(szDot, spcPrefix, 0, filename))
1773        return;
1774     DeleteFileW(filename);
1775 
1776     if (initFileFromData(filename, base64SPC, sizeof(base64SPC)))
1777     {
1778         PCCERT_CONTEXT cert;
1779         PCCRL_CONTEXT crl;
1780 
1781         store = CertOpenStore(CERT_STORE_PROV_FILENAME_W, 0, 0,
1782          CERT_STORE_READONLY_FLAG, filename);
1783         ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError());
1784 
1785         cert = CertEnumCertificatesInStore(store, NULL);
1786         ok(cert != NULL, "CertEnumCertificatesInStore failed: %08x\n",
1787          GetLastError());
1788         cert = CertEnumCertificatesInStore(store, cert);
1789         ok(!cert, "Expected only one cert\n");
1790         crl = CertEnumCRLsInStore(store, NULL);
1791         ok(!crl, "Expected no CRLs\n");
1792 
1793         CertCloseStore(store, 0);
1794         DeleteFileW(filename);
1795     }
1796     if (initFileFromData(filename, (BYTE *)utf16Base64SPC,
1797      sizeof(utf16Base64SPC)))
1798     {
1799         PCCERT_CONTEXT cert;
1800         PCCRL_CONTEXT crl;
1801 
1802         store = CertOpenStore(CERT_STORE_PROV_FILENAME_W, 0, 0,
1803          CERT_STORE_READONLY_FLAG, filename);
1804         ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError());
1805 
1806         cert = CertEnumCertificatesInStore(store, NULL);
1807         ok(cert != NULL, "CertEnumCertificatesInStore failed: %08x\n",
1808          GetLastError());
1809         cert = CertEnumCertificatesInStore(store, cert);
1810         ok(!cert, "Expected only one cert\n");
1811         crl = CertEnumCRLsInStore(store, NULL);
1812         ok(!crl, "Expected no CRLs\n");
1813 
1814         CertCloseStore(store, 0);
1815         DeleteFileW(filename);
1816     }
1817 }
1818 
1819 static const BYTE signedContent[] = {
1820 0x30,0x81,0xb2,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,0xa0,
1821 0x81,0xa4,0x30,0x81,0xa1,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,
1822 0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x13,0x06,0x09,0x2a,0x86,
1823 0x48,0x86,0xf7,0x0d,0x01,0x07,0x01,0xa0,0x06,0x04,0x04,0x01,0x02,0x03,0x04,
1824 0x31,0x77,0x30,0x75,0x02,0x01,0x01,0x30,0x1a,0x30,0x15,0x31,0x13,0x30,0x11,
1825 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
1826 0x67,0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,
1827 0x02,0x05,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04,0x40,0x81,0xa6,0x70,
1828 0xb3,0xef,0x59,0xd1,0x66,0xd1,0x9b,0xc0,0x9a,0xb6,0x9a,0x5e,0x6d,0x6f,0x6d,
1829 0x0d,0x59,0xa9,0xaa,0x6e,0xe9,0x2c,0xa0,0x1e,0xee,0xc2,0x60,0xbc,0x59,0xbe,
1830 0x3f,0x63,0x06,0x8d,0xc9,0x11,0x1d,0x23,0x64,0x92,0xef,0x2e,0xfc,0x57,0x29,
1831 0xa4,0xaf,0xe0,0xee,0x93,0x19,0x39,0x51,0xe4,0x44,0xb8,0x0b,0x28,0xf4,0xa8,
1832 0x0d };
1833 static const BYTE signedWithCertAndCrlBareContent[] = {
1834 0x30,0x82,0x01,0x4f,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,0x86,
1835 0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x13,0x06,0x09,0x2a,0x86,0x48,
1836 0x86,0xf7,0x0d,0x01,0x07,0x01,0xa0,0x06,0x04,0x04,0x01,0x02,0x03,0x04,0xa0,
1837 0x7c,0x30,0x7a,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,
1838 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
1839 0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,
1840 0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
1841 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,
1842 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
1843 0x67,0x00,0x30,0x07,0x30,0x02,0x06,0x00,0x03,0x01,0x00,0xa3,0x16,0x30,0x14,
1844 0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,
1845 0x01,0xff,0x02,0x01,0x01,0xa1,0x2e,0x30,0x2c,0x30,0x02,0x06,0x00,0x30,0x15,
1846 0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,
1847 0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
1848 0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x31,0x77,0x30,0x75,0x02,0x01,0x01,
1849 0x30,0x1a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,
1850 0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x02,0x01,0x01,0x30,0x0c,
1851 0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x04,0x06,
1852 0x00,0x05,0x00,0x04,0x40,0x81,0xa6,0x70,0xb3,0xef,0x59,0xd1,0x66,0xd1,0x9b,
1853 0xc0,0x9a,0xb6,0x9a,0x5e,0x6d,0x6f,0x6d,0x0d,0x59,0xa9,0xaa,0x6e,0xe9,0x2c,
1854 0xa0,0x1e,0xee,0xc2,0x60,0xbc,0x59,0xbe,0x3f,0x63,0x06,0x8d,0xc9,0x11,0x1d,
1855 0x23,0x64,0x92,0xef,0x2e,0xfc,0x57,0x29,0xa4,0xaf,0xe0,0xee,0x93,0x19,0x39,
1856 0x51,0xe4,0x44,0xb8,0x0b,0x28,0xf4,0xa8,0x0d };
1857 static const BYTE hashContent[] = {
1858 0x30,0x47,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x05,0xa0,0x3a,
1859 0x30,0x38,0x02,0x01,0x00,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,
1860 0x02,0x05,0x05,0x00,0x30,0x13,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
1861 0x07,0x01,0xa0,0x06,0x04,0x04,0x01,0x02,0x03,0x04,0x04,0x10,0x08,0xd6,0xc0,
1862 0x5a,0x21,0x51,0x2a,0x79,0xa1,0xdf,0xeb,0x9d,0x2a,0x8f,0x26,0x2f };
1863 static const BYTE hashBareContent[] = {
1864 0x30,0x38,0x02,0x01,0x00,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,
1865 0x02,0x05,0x05,0x00,0x30,0x13,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
1866 0x07,0x01,0xa0,0x06,0x04,0x04,0x01,0x02,0x03,0x04,0x04,0x10,0x08,0xd6,0xc0,
1867 0x5a,0x21,0x51,0x2a,0x79,0xa1,0xdf,0xeb,0x9d,0x2a,0x8f,0x26,0x2f };
1868 
1869 static void testMessageStore(void)
1870 {
1871     HCERTSTORE store;
1872     HCRYPTMSG msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL,
1873      NULL);
1874     CRYPT_DATA_BLOB blob = { sizeof(signedWithCertAndCrlBareContent),
1875      (LPBYTE)signedWithCertAndCrlBareContent };
1876     DWORD count, size;
1877     BOOL ret;
1878 
1879     /* Crashes
1880     store = CertOpenStore(CERT_STORE_PROV_MSG, 0, 0, 0, NULL);
1881      */
1882     SetLastError(0xdeadbeef);
1883     store = CertOpenStore(CERT_STORE_PROV_MSG, 0, 0, 0, msg);
1884     ok(!store && GetLastError() == CRYPT_E_INVALID_MSG_TYPE,
1885      "Expected CRYPT_E_INVALID_MSG_TYPE, got %08x\n", GetLastError());
1886     CryptMsgUpdate(msg, signedContent, sizeof(signedContent), TRUE);
1887     store = CertOpenStore(CERT_STORE_PROV_MSG, 0, 0, 0, msg);
1888     ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError());
1889     if (store)
1890     {
1891         PCCERT_CONTEXT cert = NULL;
1892         PCCRL_CONTEXT crl = NULL;
1893 
1894         count = 0;
1895         do {
1896             cert = CertEnumCertificatesInStore(store, cert);
1897             if (cert)
1898                 count++;
1899         } while (cert);
1900         ok(count == 0, "Expected 0 certificates, got %d\n", count);
1901 
1902         count = 0;
1903         do {
1904             crl = CertEnumCRLsInStore(store, crl);
1905             if (crl)
1906                 count++;
1907         } while (crl);
1908         ok(count == 0, "Expected 0 CRLs, got %d\n", count);
1909 
1910         /* Can add certs to a message store */
1911         ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1912          bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, NULL);
1913         ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
1914          GetLastError());
1915         count = 0;
1916         do {
1917             cert = CertEnumCertificatesInStore(store, cert);
1918             if (cert)
1919                 count++;
1920         } while (cert);
1921         ok(count == 1, "Expected 1 certificate, got %d\n", count);
1922 
1923         CertCloseStore(store, 0);
1924     }
1925     /* but the added certs weren't actually added to the message */
1926     size = sizeof(count);
1927     ret = CryptMsgGetParam(msg, CMSG_CERT_COUNT_PARAM, 0, &count, &size);
1928     ok(ret, "CryptMsgGetParam failed: %08x\n", GetLastError());
1929     ok(count == 0, "Expected 0 certificates, got %d\n", count);
1930     CryptMsgClose(msg);
1931 
1932     /* Crashes
1933     store = CertOpenStore(CERT_STORE_PROV_PKCS7, 0, 0, 0, NULL);
1934      */
1935     store = CertOpenStore(CERT_STORE_PROV_PKCS7, 0, 0, 0, &blob);
1936     ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError());
1937     if (store)
1938     {
1939         DWORD count = 0;
1940         PCCERT_CONTEXT cert = NULL;
1941         PCCRL_CONTEXT crl = NULL;
1942 
1943         do {
1944             cert = CertEnumCertificatesInStore(store, cert);
1945             if (cert)
1946                 count++;
1947         } while (cert);
1948         ok(count == 1, "Expected 1 certificate, got %d\n", count);
1949 
1950         count = 0;
1951         do {
1952             crl = CertEnumCRLsInStore(store, crl);
1953             if (crl)
1954                 count++;
1955         } while (crl);
1956         ok(count == 1, "Expected 1 CRL, got %d\n", count);
1957 
1958         CertCloseStore(store, 0);
1959     }
1960     /* Encoding appears to be ignored */
1961     store = CertOpenStore(CERT_STORE_PROV_PKCS7, X509_ASN_ENCODING, 0, 0,
1962      &blob);
1963     ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError());
1964     if (store)
1965         CertCloseStore(store, 0);
1966     /* Messages other than signed messages aren't allowed */
1967     blob.cbData = sizeof(hashContent);
1968     blob.pbData = (LPBYTE)hashContent;
1969     SetLastError(0xdeadbeef);
1970     store = CertOpenStore(CERT_STORE_PROV_PKCS7, 0, 0, 0, &blob);
1971     ok(!store && GetLastError() == CRYPT_E_INVALID_MSG_TYPE,
1972      "Expected CRYPT_E_INVALID_MSG_TYPE, got %08x\n", GetLastError());
1973     blob.cbData = sizeof(hashBareContent);
1974     blob.pbData = (LPBYTE)hashBareContent;
1975     SetLastError(0xdeadbeef);
1976     store = CertOpenStore(CERT_STORE_PROV_PKCS7, 0, 0, 0, &blob);
1977     ok(!store && GetLastError() == CRYPT_E_ASN1_BADTAG,
1978      "Expected CRYPT_E_ASN1_BADTAG, got %08x\n", GetLastError());
1979 }
1980 
1981 static void testSerializedStore(void)
1982 {
1983     HCERTSTORE store;
1984     CRYPT_DATA_BLOB blob;
1985 
1986     if (0)
1987     {
1988         /* Crash */
1989         store = CertOpenStore(CERT_STORE_PROV_SERIALIZED, 0, 0, 0, NULL);
1990         store = CertOpenStore(CERT_STORE_PROV_SERIALIZED, 0, 0,
1991          CERT_STORE_DELETE_FLAG, NULL);
1992     }
1993     blob.cbData = sizeof(serializedStoreWithCert);
1994     blob.pbData = (BYTE *)serializedStoreWithCert;
1995     store = CertOpenStore(CERT_STORE_PROV_SERIALIZED, 0, 0,
1996      CERT_STORE_DELETE_FLAG, &blob);
1997     ok(!store && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED,
1998      "Expected ERROR_CALL_NOT_IMPLEMENTED, got %08x\n", GetLastError());
1999     store = CertOpenStore(CERT_STORE_PROV_SERIALIZED, 0, 0, 0, &blob);
2000     ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError());
2001     if (store)
2002     {
2003         PCCERT_CONTEXT cert;
2004         PCCRL_CONTEXT crl;
2005 
2006         cert = CertEnumCertificatesInStore(store, NULL);
2007         ok(cert != NULL, "CertEnumCertificatesInStore failed: %08x\n",
2008          GetLastError());
2009         cert = CertEnumCertificatesInStore(store, cert);
2010         ok(!cert, "Expected only one cert\n");
2011         crl = CertEnumCRLsInStore(store, NULL);
2012         ok(!crl, "Expected no CRLs\n");
2013 
2014         CertCloseStore(store, 0);
2015     }
2016     blob.cbData = sizeof(serializedStoreWithCertAndCRL);
2017     blob.pbData = (BYTE *)serializedStoreWithCertAndCRL;
2018     store = CertOpenStore(CERT_STORE_PROV_SERIALIZED, 0, 0, 0, &blob);
2019     ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError());
2020     if (store)
2021     {
2022         PCCERT_CONTEXT cert;
2023         PCCRL_CONTEXT crl;
2024 
2025         cert = CertEnumCertificatesInStore(store, NULL);
2026         ok(cert != NULL, "CertEnumCertificatesInStore failed: %08x\n",
2027          GetLastError());
2028         cert = CertEnumCertificatesInStore(store, cert);
2029         ok(!cert, "Expected only one cert\n");
2030         crl = CertEnumCRLsInStore(store, NULL);
2031         ok(crl != NULL, "CertEnumCRLsInStore failed: %08x\n",
2032          GetLastError());
2033         crl = CertEnumCRLsInStore(store, crl);
2034         ok(!crl, "Expected only one CRL\n");
2035 
2036         CertCloseStore(store, 0);
2037     }
2038 }
2039 
2040 static void testCertOpenSystemStore(void)
2041 {
2042     HCERTSTORE store;
2043 
2044     store = CertOpenSystemStoreW(0, NULL);
2045     ok(!store && GetLastError() == E_INVALIDARG,
2046      "Expected E_INVALIDARG, got %08x\n", GetLastError());
2047     /* This succeeds, and on WinXP at least, the Bogus key is created under
2048      * HKCU (but not under HKLM, even when run as an administrator.)
2049      */
2050     store = CertOpenSystemStoreW(0, BogusW);
2051     ok(store != 0, "CertOpenSystemStore failed: %08x\n", GetLastError());
2052     if (store)
2053         CertCloseStore(store, 0);
2054     /* Delete it so other tests succeed next time around */
2055     CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0,
2056      CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_DELETE_FLAG, BogusW);
2057     RegDeleteKeyW(HKEY_CURRENT_USER, BogusPathW);
2058 }
2059 
2060 static const struct
2061 {
2062     DWORD cert_store;
2063     BOOL expected;
2064     BOOL todo;
2065 } reg_system_store_test_data[] = {
2066     { CERT_SYSTEM_STORE_CURRENT_USER,  TRUE, 0},
2067     /* Following tests could require administrator privileges and thus could be skipped */
2068     { CERT_SYSTEM_STORE_CURRENT_SERVICE, TRUE, 1},
2069     { CERT_SYSTEM_STORE_LOCAL_MACHINE, TRUE, 0},
2070     { CERT_SYSTEM_STORE_LOCAL_MACHINE_GROUP_POLICY, TRUE, 0},
2071     { CERT_SYSTEM_STORE_CURRENT_USER_GROUP_POLICY, TRUE, 0},
2072     { CERT_SYSTEM_STORE_LOCAL_MACHINE_ENTERPRISE, TRUE, 1}
2073 };
2074 
2075 static void testCertRegisterSystemStore(void)
2076 {
2077     BOOL ret, cur_flag;
2078     DWORD err = 0;
2079     HCERTSTORE hstore;
2080     static const WCHAR WineTestW[] = {'W','i','n','e','T','e','s','t',0};
2081     const CERT_CONTEXT *cert, *cert2;
2082     unsigned int i;
2083 
2084     for (i = 0; i < ARRAY_SIZE(reg_system_store_test_data); i++) {
2085         cur_flag = reg_system_store_test_data[i].cert_store;
2086         ret = CertRegisterSystemStore(WineTestW, cur_flag, NULL, NULL);
2087         if (!ret)
2088         {
2089             err = GetLastError();
2090             if (err == ERROR_ACCESS_DENIED)
2091             {
2092                 win_skip("Insufficient privileges for the flag %08x test\n", cur_flag);
2093                 continue;
2094             }
2095         }
2096         todo_wine_if (reg_system_store_test_data[i].todo)
2097             ok (ret == reg_system_store_test_data[i].expected,
2098                 "Store registration (dwFlags=%08x) failed, last error %x\n", cur_flag, err);
2099         if (!ret)
2100         {
2101             skip("Nothing to test without registered store at %08x\n", cur_flag);
2102             continue;
2103         }
2104 
2105         hstore = CertOpenStore(CERT_STORE_PROV_SYSTEM_W, 0, 0, CERT_STORE_OPEN_EXISTING_FLAG | cur_flag, WineTestW);
2106         ok (hstore != NULL, "Opening just registered store at %08x failed, last error %x\n", cur_flag, GetLastError());
2107 
2108         cert = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert, sizeof(bigCert));
2109         ok (cert != NULL, "Failed creating cert at %08x, last error: %x\n", cur_flag, GetLastError());
2110         if (cert)
2111         {
2112             ret = CertAddCertificateContextToStore(hstore, cert, CERT_STORE_ADD_NEW, NULL);
2113             ok (ret, "Failed to add cert at %08x, last error: %x\n", cur_flag, GetLastError());
2114 
2115             cert2 = CertEnumCertificatesInStore(hstore, NULL);
2116             ok (cert2 != NULL && cert2->cbCertEncoded == cert->cbCertEncoded,
2117                 "Unexpected cert encoded size at %08x, last error: %x\n", cur_flag, GetLastError());
2118 
2119             ret = CertDeleteCertificateFromStore(cert2);
2120             ok (ret, "Failed to delete certificate from the new store at %08x, last error: %x\n", cur_flag, GetLastError());
2121 
2122             CertFreeCertificateContext(cert);
2123         }
2124 
2125         ret = CertCloseStore(hstore, 0);
2126         ok (ret, "CertCloseStore failed at %08x, last error %x\n", cur_flag, GetLastError());
2127 
2128         ret = CertUnregisterSystemStore(WineTestW, cur_flag );
2129         todo_wine_if (reg_system_store_test_data[i].todo)
2130             ok( ret == reg_system_store_test_data[i].expected,
2131                 "Unregistering failed at %08x, last error %d\n", cur_flag, GetLastError());
2132      }
2133 
2134 }
2135 
2136 struct EnumSystemStoreInfo
2137 {
2138     BOOL  goOn;
2139     DWORD storeCount;
2140 };
2141 
2142 static BOOL CALLBACK enumSystemStoreCB(const void *systemStore, DWORD dwFlags,
2143  PCERT_SYSTEM_STORE_INFO pStoreInfo, void *pvReserved, void *pvArg)
2144 {
2145     struct EnumSystemStoreInfo *info = pvArg;
2146 
2147     info->storeCount++;
2148     return info->goOn;
2149 }
2150 
2151 static void testCertEnumSystemStore(void)
2152 {
2153     BOOL ret;
2154     struct EnumSystemStoreInfo info = { FALSE, 0 };
2155 
2156     SetLastError(0xdeadbeef);
2157     ret = CertEnumSystemStore(0, NULL, NULL, NULL);
2158     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2159      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2160     /* Crashes
2161     ret = CertEnumSystemStore(CERT_SYSTEM_STORE_LOCAL_MACHINE, NULL, NULL,
2162      NULL);
2163      */
2164 
2165     SetLastError(0xdeadbeef);
2166     ret = CertEnumSystemStore(CERT_SYSTEM_STORE_LOCAL_MACHINE, NULL, &info,
2167      enumSystemStoreCB);
2168     /* Callback returning FALSE stops enumeration */
2169     ok(!ret, "Expected CertEnumSystemStore to stop\n");
2170     ok(info.storeCount == 0 || info.storeCount == 1,
2171      "Expected 0 or 1 stores\n");
2172 
2173     info.goOn = TRUE;
2174     info.storeCount = 0;
2175     ret = CertEnumSystemStore(CERT_SYSTEM_STORE_LOCAL_MACHINE, NULL, &info,
2176      enumSystemStoreCB);
2177     ok(ret, "CertEnumSystemStore failed: %08x\n", GetLastError());
2178     /* There should always be at least My, Root, and CA stores */
2179     ok(info.storeCount == 0 || info.storeCount >= 3,
2180      "Expected at least 3 stores\n");
2181 }
2182 
2183 static void testStoreProperty(void)
2184 {
2185     HCERTSTORE store;
2186     BOOL ret;
2187     DWORD propID, size = 0, state;
2188     CRYPT_DATA_BLOB blob;
2189 
2190     /* Crash
2191     ret = CertGetStoreProperty(NULL, 0, NULL, NULL);
2192     ret = CertGetStoreProperty(NULL, 0, NULL, &size);
2193     ret = CertGetStoreProperty(store, 0, NULL, NULL);
2194      */
2195 
2196     store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
2197      CERT_STORE_CREATE_NEW_FLAG, NULL);
2198     /* Check a missing prop ID */
2199     SetLastError(0xdeadbeef);
2200     ret = CertGetStoreProperty(store, 0, NULL, &size);
2201     ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
2202      "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
2203     /* Contrary to MSDN, CERT_ACCESS_STATE_PROP_ID is supported for stores.. */
2204     size = sizeof(state);
2205     ret = CertGetStoreProperty(store, CERT_ACCESS_STATE_PROP_ID, &state, &size);
2206     ok(ret, "CertGetStoreProperty failed for CERT_ACCESS_STATE_PROP_ID: %08x\n",
2207      GetLastError());
2208     ok(!state, "Expected a non-persisted store\n");
2209     /* and CERT_STORE_LOCALIZED_NAME_PROP_ID isn't supported by default. */
2210     size = 0;
2211     ret = CertGetStoreProperty(store, CERT_STORE_LOCALIZED_NAME_PROP_ID, NULL,
2212      &size);
2213     ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
2214      "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
2215     /* Delete an arbitrary property on a store */
2216     ret = CertSetStoreProperty(store, CERT_FIRST_USER_PROP_ID, 0, NULL);
2217     ok(ret, "CertSetStoreProperty failed: %08x\n", GetLastError());
2218     /* Set an arbitrary property on a store */
2219     blob.pbData = (LPBYTE)&state;
2220     blob.cbData = sizeof(state);
2221     ret = CertSetStoreProperty(store, CERT_FIRST_USER_PROP_ID, 0, &blob);
2222     ok(ret, "CertSetStoreProperty failed: %08x\n", GetLastError());
2223     /* Get an arbitrary property that's been set */
2224     ret = CertGetStoreProperty(store, CERT_FIRST_USER_PROP_ID, NULL, &size);
2225     ok(ret, "CertGetStoreProperty failed: %08x\n", GetLastError());
2226     ok(size == sizeof(state), "Unexpected data size %d\n", size);
2227     ret = CertGetStoreProperty(store, CERT_FIRST_USER_PROP_ID, &propID, &size);
2228     ok(ret, "CertGetStoreProperty failed: %08x\n", GetLastError());
2229     ok(propID == state, "CertGetStoreProperty got the wrong value\n");
2230     /* Delete it again */
2231     ret = CertSetStoreProperty(store, CERT_FIRST_USER_PROP_ID, 0, NULL);
2232     ok(ret, "CertSetStoreProperty failed: %08x\n", GetLastError());
2233     /* And check that it's missing */
2234     SetLastError(0xdeadbeef);
2235     ret = CertGetStoreProperty(store, CERT_FIRST_USER_PROP_ID, NULL, &size);
2236     ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
2237      "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
2238     CertCloseStore(store, 0);
2239 
2240     /* Recheck on the My store.. */
2241     store = CertOpenSystemStoreW(0, MyW);
2242     size = sizeof(state);
2243     ret = CertGetStoreProperty(store, CERT_ACCESS_STATE_PROP_ID, &state, &size);
2244     ok(ret, "CertGetStoreProperty failed for CERT_ACCESS_STATE_PROP_ID: %08x\n",
2245      GetLastError());
2246     ok(state, "Expected a persisted store\n");
2247     SetLastError(0xdeadbeef);
2248     size = 0;
2249     ret = CertGetStoreProperty(store, CERT_STORE_LOCALIZED_NAME_PROP_ID, NULL,
2250      &size);
2251     ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
2252      "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
2253     CertCloseStore(store, 0);
2254 }
2255 
2256 static void testAddSerialized(void)
2257 {
2258     BOOL ret;
2259     HCERTSTORE store;
2260     BYTE buf[sizeof(struct CertPropIDHeader) * 2 + 20 + sizeof(bigCert)] =
2261      { 0 };
2262     BYTE hash[20];
2263     struct CertPropIDHeader *hdr;
2264     PCCERT_CONTEXT context;
2265 
2266     ret = CertAddSerializedElementToStore(0, NULL, 0, 0, 0, 0, NULL, NULL);
2267     ok(!ret && GetLastError() == ERROR_END_OF_MEDIA,
2268      "Expected ERROR_END_OF_MEDIA, got %08x\n", GetLastError());
2269 
2270     store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
2271      CERT_STORE_CREATE_NEW_FLAG, NULL);
2272     ok(store != 0, "CertOpenStore failed: %08x\n", GetLastError());
2273 
2274     ret = CertAddSerializedElementToStore(store, NULL, 0, 0, 0, 0, NULL, NULL);
2275     ok(!ret && GetLastError() == ERROR_END_OF_MEDIA,
2276      "Expected ERROR_END_OF_MEDIA, got %08x\n", GetLastError());
2277 
2278     /* Test with an empty property */
2279     hdr = (struct CertPropIDHeader *)buf;
2280     hdr->propID = CERT_CERT_PROP_ID;
2281     hdr->unknown1 = 1;
2282     hdr->cb = 0;
2283     ret = CertAddSerializedElementToStore(store, buf, sizeof(buf), 0, 0, 0,
2284      NULL, NULL);
2285     ok(!ret && GetLastError() == E_INVALIDARG,
2286      "Expected E_INVALIDARG, got %08x\n", GetLastError());
2287     /* Test with a bad size in property header */
2288     hdr->cb = sizeof(bigCert) - 1;
2289     memcpy(buf + sizeof(struct CertPropIDHeader), bigCert, sizeof(bigCert));
2290     ret = CertAddSerializedElementToStore(store, buf, sizeof(buf), 0, 0, 0,
2291      NULL, NULL);
2292     ok(!ret && GetLastError() == E_INVALIDARG,
2293      "Expected E_INVALIDARG, got %08x\n", GetLastError());
2294     ret = CertAddSerializedElementToStore(store, buf,
2295      sizeof(struct CertPropIDHeader) + sizeof(bigCert), 0, 0, 0, NULL,
2296      NULL);
2297     ok(!ret && GetLastError() == E_INVALIDARG,
2298      "Expected E_INVALIDARG, got %08x\n", GetLastError());
2299     ret = CertAddSerializedElementToStore(store, buf,
2300      sizeof(struct CertPropIDHeader) + sizeof(bigCert), CERT_STORE_ADD_NEW,
2301      0, 0, NULL, NULL);
2302     ok(!ret && GetLastError() == E_INVALIDARG,
2303      "Expected E_INVALIDARG, got %08x\n", GetLastError());
2304     /* Kosher size in property header, but no context type */
2305     hdr->cb = sizeof(bigCert);
2306     ret = CertAddSerializedElementToStore(store, buf, sizeof(buf), 0, 0, 0,
2307      NULL, NULL);
2308     ok(!ret && GetLastError() == E_INVALIDARG,
2309      "Expected E_INVALIDARG, got %08x\n", GetLastError());
2310     ret = CertAddSerializedElementToStore(store, buf,
2311      sizeof(struct CertPropIDHeader) + sizeof(bigCert), 0, 0, 0, NULL,
2312      NULL);
2313     ok(!ret && GetLastError() == E_INVALIDARG,
2314      "Expected E_INVALIDARG, got %08x\n", GetLastError());
2315     ret = CertAddSerializedElementToStore(store, buf,
2316      sizeof(struct CertPropIDHeader) + sizeof(bigCert), CERT_STORE_ADD_NEW,
2317      0, 0, NULL, NULL);
2318     ok(!ret && GetLastError() == E_INVALIDARG,
2319      "Expected E_INVALIDARG, got %08x\n", GetLastError());
2320     /* With a bad context type */
2321     ret = CertAddSerializedElementToStore(store, buf, sizeof(buf), 0, 0,
2322      CERT_STORE_CRL_CONTEXT_FLAG, NULL, NULL);
2323     ok(!ret && GetLastError() == E_INVALIDARG,
2324      "Expected E_INVALIDARG, got %08x\n", GetLastError());
2325     ret = CertAddSerializedElementToStore(store, buf,
2326      sizeof(struct CertPropIDHeader) + sizeof(bigCert), 0, 0,
2327      CERT_STORE_CRL_CONTEXT_FLAG, NULL, NULL);
2328     ok(!ret && GetLastError() == E_INVALIDARG,
2329      "Expected E_INVALIDARG, got %08x\n", GetLastError());
2330     ret = CertAddSerializedElementToStore(store, buf,
2331      sizeof(struct CertPropIDHeader) + sizeof(bigCert), CERT_STORE_ADD_NEW,
2332      0, CERT_STORE_CRL_CONTEXT_FLAG, NULL, NULL);
2333     ok(!ret && GetLastError() == E_INVALIDARG,
2334      "Expected E_INVALIDARG, got %08x\n", GetLastError());
2335     /* Bad unknown field, good type */
2336     hdr->unknown1 = 2;
2337     ret = CertAddSerializedElementToStore(store, buf, sizeof(buf), 0, 0,
2338      CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL, NULL);
2339     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2340      "Expected ERROR_FILE_NOT_FOUND got %08x\n", GetLastError());
2341     ret = CertAddSerializedElementToStore(store, buf,
2342      sizeof(struct CertPropIDHeader) + sizeof(bigCert), 0, 0,
2343      CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL, NULL);
2344     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2345      "Expected ERROR_FILE_NOT_FOUND got %08x\n", GetLastError());
2346     ret = CertAddSerializedElementToStore(store, buf,
2347      sizeof(struct CertPropIDHeader) + sizeof(bigCert), CERT_STORE_ADD_NEW,
2348      0, CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL, NULL);
2349     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2350      "Expected ERROR_FILE_NOT_FOUND got %08x\n", GetLastError());
2351     /* Most everything okay, but bad add disposition */
2352     hdr->unknown1 = 1;
2353     /* This crashes
2354     ret = CertAddSerializedElementToStore(store, buf, sizeof(buf), 0, 0,
2355      CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL, NULL);
2356      * as does this
2357     ret = CertAddSerializedElementToStore(store, buf,
2358      sizeof(struct CertPropIDHeader) + sizeof(bigCert), 0, 0,
2359      CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL, NULL);
2360      */
2361     /* Everything okay, but buffer's too big */
2362     ret = CertAddSerializedElementToStore(store, buf, sizeof(buf),
2363      CERT_STORE_ADD_NEW, 0, CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL, NULL);
2364     ok(ret, "CertAddSerializedElementToStore failed: %08x\n", GetLastError());
2365     /* Everything okay, check it's not re-added */
2366     ret = CertAddSerializedElementToStore(store, buf,
2367      sizeof(struct CertPropIDHeader) + sizeof(bigCert), CERT_STORE_ADD_NEW,
2368      0, CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL, NULL);
2369     ok(!ret && GetLastError() == CRYPT_E_EXISTS,
2370      "Expected CRYPT_E_EXISTS, got %08x\n", GetLastError());
2371 
2372     context = CertEnumCertificatesInStore(store, NULL);
2373     ok(context != NULL, "Expected a cert\n");
2374     if (context)
2375         CertDeleteCertificateFromStore(context);
2376 
2377     /* Try adding with a bogus hash.  Oddly enough, it succeeds, and the hash,
2378      * when queried, is the real hash rather than the bogus hash.
2379      */
2380     hdr = (struct CertPropIDHeader *)(buf + sizeof(struct CertPropIDHeader) +
2381      sizeof(bigCert));
2382     hdr->propID = CERT_HASH_PROP_ID;
2383     hdr->unknown1 = 1;
2384     hdr->cb = sizeof(hash);
2385     memset(hash, 0xc, sizeof(hash));
2386     memcpy((LPBYTE)hdr + sizeof(struct CertPropIDHeader), hash, sizeof(hash));
2387     ret = CertAddSerializedElementToStore(store, buf, sizeof(buf),
2388      CERT_STORE_ADD_NEW, 0, CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL,
2389      (const void **)&context);
2390     ok(ret, "CertAddSerializedElementToStore failed: %08x\n", GetLastError());
2391     if (context)
2392     {
2393         BYTE hashVal[20], realHash[20];
2394         DWORD size = sizeof(hashVal);
2395 
2396         ret = CryptHashCertificate(0, 0, 0, bigCert, sizeof(bigCert),
2397          realHash, &size);
2398         ok(ret, "CryptHashCertificate failed: %08x\n", GetLastError());
2399         ret = CertGetCertificateContextProperty(context, CERT_HASH_PROP_ID,
2400          hashVal, &size);
2401         ok(ret, "CertGetCertificateContextProperty failed: %08x\n",
2402          GetLastError());
2403         ok(!memcmp(hashVal, realHash, size), "Unexpected hash\n");
2404         CertFreeCertificateContext(context);
2405     }
2406 
2407     CertCloseStore(store, 0);
2408 }
2409 
2410 static const BYTE serializedCertWithFriendlyName[] = {
2411 0x0b,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x12,0x00,0x00,0x00,0x57,0x00,0x69,
2412 0x00,0x6e,0x00,0x65,0x00,0x54,0x00,0x65,0x00,0x73,0x00,0x74,0x00,0x00,0x00,
2413 0x20,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x7c,0x00,0x00,0x00,0x30,0x7a,0x02,
2414 0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,
2415 0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x30,
2416 0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,
2417 0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,
2418 0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,
2419 0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x30,0x07,
2420 0x30,0x02,0x06,0x00,0x03,0x01,0x00,0xa3,0x16,0x30,0x14,0x30,0x12,0x06,0x03,
2421 0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,
2422 0x01 };
2423 static const BYTE serializedStoreWithCertWithFriendlyName[] = {
2424 0x00,0x00,0x00,0x00,0x43,0x45,0x52,0x54,0x0b,0x00,0x00,0x00,0x01,0x00,0x00,
2425 0x00,0x12,0x00,0x00,0x00,0x57,0x00,0x69,0x00,0x6e,0x00,0x65,0x00,0x54,0x00,
2426 0x65,0x00,0x73,0x00,0x74,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x01,0x00,0x00,
2427 0x00,0x7c,0x00,0x00,0x00,0x30,0x7a,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,
2428 0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,
2429 0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,
2430 0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,
2431 0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,
2432 0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,
2433 0x20,0x4c,0x61,0x6e,0x67,0x00,0x30,0x07,0x30,0x02,0x06,0x00,0x03,0x01,0x00,
2434 0xa3,0x16,0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,
2435 0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,
2436 0x00,0x00,0x00,0x00,0x00,0x00 };
2437 static const BYTE serializedStoreWithCertAndHash[] = {
2438 0x00,0x00,0x00,0x00,0x43,0x45,0x52,0x54,0x03,0x00,0x00,0x00,0x01,0x00,0x00,
2439 0x00,0x14,0x00,0x00,0x00,0x6e,0x30,0x90,0x71,0x5f,0xd9,0x23,0x56,0xeb,0xae,
2440 0x25,0x40,0xe6,0x22,0xda,0x19,0x26,0x02,0xa6,0x08,0x20,0x00,0x00,0x00,0x01,
2441 0x00,0x00,0x00,0x7c,0x00,0x00,0x00,0x30,0x7a,0x02,0x01,0x01,0x30,0x02,0x06,
2442 0x00,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,
2443 0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,
2444 0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,
2445 0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,
2446 0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,
2447 0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x30,0x07,0x30,0x02,0x06,0x00,0x03,
2448 0x01,0x00,0xa3,0x16,0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,
2449 0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01,0x00,0x00,0x00,0x00,
2450 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 };
2451 
2452 static void delete_test_key(void)
2453 {
2454     HKEY root_key, test_key;
2455     static const WCHAR SysCertW[] = {'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\',
2456         'S','y','s','t','e','m','C','e','r','t','i','f','i','c','a','t','e','s',0};
2457     static const WCHAR WineTestW[] = {'W','i','n','e','T','e','s','t',0};
2458     WCHAR subkey_name[32];
2459     DWORD num_subkeys, subkey_name_len;
2460     int idx;
2461 
2462     if (RegOpenKeyExW(HKEY_CURRENT_USER, SysCertW, 0, KEY_READ, &root_key))
2463         return;
2464     if (RegOpenKeyExW(root_key, WineTestW, 0, KEY_READ, &test_key))
2465     {
2466         RegCloseKey(root_key);
2467         return;
2468     }
2469     RegQueryInfoKeyW(test_key, NULL, NULL, NULL, &num_subkeys, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
2470     for (idx = num_subkeys; idx-- > 0;)
2471     {
2472         subkey_name_len = ARRAY_SIZE(subkey_name);
2473         RegEnumKeyExW(test_key, idx, subkey_name, &subkey_name_len, NULL, NULL, NULL, NULL);
2474         RegDeleteKeyW(test_key, subkey_name);
2475     }
2476     RegCloseKey(test_key);
2477     RegDeleteKeyW(root_key, WineTestW);
2478     RegCloseKey(root_key);
2479 }
2480 
2481 static void testAddCertificateLink(void)
2482 {
2483     BOOL ret;
2484     HCERTSTORE store1, store2;
2485     PCCERT_CONTEXT source, linked;
2486     DWORD size;
2487     LPBYTE buf;
2488     CERT_NAME_BLOB blob;
2489     static const WCHAR szPrefix[] = { 'c','e','r',0 };
2490     static const WCHAR szDot[] = { '.',0 };
2491     static const WCHAR WineTestW[] = { 'W','i','n','e','T','e','s','t',0 };
2492     WCHAR filename1[MAX_PATH], filename2[MAX_PATH];
2493     HANDLE file;
2494 
2495     if (0)
2496     {
2497         /* Crashes, i.e. the store is dereferenced without checking. */
2498         ret = CertAddCertificateLinkToStore(NULL, NULL, 0, NULL);
2499     }
2500 
2501     /* Adding a certificate link to a store requires a valid add disposition */
2502     store1 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
2503      CERT_STORE_CREATE_NEW_FLAG, NULL);
2504     SetLastError(0xdeadbeef);
2505     ret = CertAddCertificateLinkToStore(store1, NULL, 0, NULL);
2506     ok(!ret && GetLastError() == E_INVALIDARG,
2507      "expected E_INVALIDARG, got %08x\n", GetLastError());
2508     source = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert,
2509      sizeof(bigCert));
2510     SetLastError(0xdeadbeef);
2511     ret = CertAddCertificateLinkToStore(store1, source, 0, NULL);
2512     ok(!ret && GetLastError() == E_INVALIDARG,
2513      "expected E_INVALIDARG, got %08x\n", GetLastError());
2514     ret = CertAddCertificateLinkToStore(store1, source, CERT_STORE_ADD_ALWAYS,
2515      NULL);
2516     ok(ret, "CertAddCertificateLinkToStore failed: %08x\n", GetLastError());
2517     if (0)
2518     {
2519         /* Crashes, i.e. the source certificate is dereferenced without
2520          * checking when a valid add disposition is given.
2521          */
2522         ret = CertAddCertificateLinkToStore(store1, NULL, CERT_STORE_ADD_ALWAYS,
2523          NULL);
2524     }
2525     CertCloseStore(store1, 0);
2526 
2527     store1 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
2528      CERT_STORE_CREATE_NEW_FLAG, NULL);
2529     ret = CertAddCertificateLinkToStore(store1, source, CERT_STORE_ADD_ALWAYS,
2530      &linked);
2531     ok(ret, "CertAddCertificateLinkToStore failed: %08x\n", GetLastError());
2532     if (ret)
2533     {
2534         ok(linked->hCertStore == store1, "unexpected store\n");
2535         ret = CertSerializeCertificateStoreElement(linked, 0, NULL, &size);
2536         ok(ret, "CertSerializeCertificateStoreElement failed: %08x\n",
2537          GetLastError());
2538         buf = HeapAlloc(GetProcessHeap(), 0, size);
2539         if (buf)
2540         {
2541             ret = CertSerializeCertificateStoreElement(linked, 0, buf, &size);
2542             ok(ret, "CertSerializeCertificateStoreElement failed: %08x\n",
2543              GetLastError());
2544             /* The serialized linked certificate is identical to the serialized
2545              * original certificate.
2546              */
2547             ok(size == sizeof(serializedCert), "Wrong size %d\n", size);
2548             ok(!memcmp(serializedCert, buf, size),
2549              "Unexpected serialized cert\n");
2550             HeapFree(GetProcessHeap(), 0, buf);
2551         }
2552         /* Set a friendly name on the source certificate... */
2553         blob.pbData = (LPBYTE)WineTestW;
2554         blob.cbData = sizeof(WineTestW);
2555         ret = CertSetCertificateContextProperty(source,
2556          CERT_FRIENDLY_NAME_PROP_ID, 0, &blob);
2557         ok(ret, "CertSetCertificateContextProperty failed: %08x\n",
2558          GetLastError());
2559         /* and the linked certificate has the same friendly name. */
2560         ret = CertGetCertificateContextProperty(linked,
2561          CERT_FRIENDLY_NAME_PROP_ID, NULL, &size);
2562         ok(ret, "CertGetCertificateContextProperty failed: %08x\n",
2563          GetLastError());
2564         buf = HeapAlloc(GetProcessHeap(), 0, size);
2565         if (buf)
2566         {
2567             ret = CertGetCertificateContextProperty(linked,
2568              CERT_FRIENDLY_NAME_PROP_ID, buf, &size);
2569             ok(ret, "CertGetCertificateContextProperty failed: %08x\n",
2570              GetLastError());
2571             ok(!lstrcmpW((LPCWSTR)buf, WineTestW),
2572              "unexpected friendly name\n");
2573             HeapFree(GetProcessHeap(), 0, buf);
2574         }
2575         CertFreeCertificateContext(linked);
2576     }
2577     CertFreeCertificateContext(source);
2578     CertCloseStore(store1, 0);
2579 
2580     /* Test adding a cert to a file store, committing the change to the store,
2581      * and creating a link to the resulting cert.
2582      */
2583     if (!GetTempFileNameW(szDot, szPrefix, 0, filename1))
2584        return;
2585 
2586     DeleteFileW(filename1);
2587     file = CreateFileW(filename1, GENERIC_READ | GENERIC_WRITE, 0, NULL,
2588      CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
2589     if (file == INVALID_HANDLE_VALUE)
2590         return;
2591 
2592     store1 = CertOpenStore(CERT_STORE_PROV_FILE, 0, 0,
2593      CERT_FILE_STORE_COMMIT_ENABLE_FLAG, file);
2594     ok(store1 != NULL, "CertOpenStore failed: %08x\n", GetLastError());
2595     CloseHandle(file);
2596 
2597     ret = CertAddEncodedCertificateToStore(store1, X509_ASN_ENCODING,
2598      bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, &source);
2599     ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
2600      GetLastError());
2601 
2602     /* Test adding a link to a memory store. */
2603     store2 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
2604      CERT_STORE_CREATE_NEW_FLAG, NULL);
2605     ret = CertAddCertificateLinkToStore(store2, source, CERT_STORE_ADD_ALWAYS,
2606      &linked);
2607     ok(ret, "CertAddCertificateLinkToStore failed: %08x\n", GetLastError());
2608     if (ret)
2609     {
2610         ok(linked->hCertStore == store2, "unexpected store\n");
2611         ret = CertSerializeCertificateStoreElement(linked, 0, NULL, &size);
2612         ok(ret, "CertSerializeCertificateStoreElement failed: %08x\n",
2613          GetLastError());
2614         buf = HeapAlloc(GetProcessHeap(), 0, size);
2615         if (buf)
2616         {
2617             ret = CertSerializeCertificateStoreElement(linked, 0, buf, &size);
2618             /* The serialized linked certificate is identical to the serialized
2619              * original certificate.
2620              */
2621             ok(ret, "CertSerializeCertificateStoreElement failed: %08x\n", GetLastError());
2622             ok(size == sizeof(serializedCert), "Wrong size %d\n", size);
2623             ok(!memcmp(serializedCert, buf, size),
2624              "Unexpected serialized cert\n");
2625             HeapFree(GetProcessHeap(), 0, buf);
2626         }
2627         /* Set a friendly name on the source certificate... */
2628         blob.pbData = (LPBYTE)WineTestW;
2629         blob.cbData = sizeof(WineTestW);
2630         ret = CertSetCertificateContextProperty(source,
2631          CERT_FRIENDLY_NAME_PROP_ID, 0, &blob);
2632         ok(ret, "CertSetCertificateContextProperty failed: %08x\n",
2633          GetLastError());
2634         /* and the linked certificate has the same friendly name. */
2635         ret = CertGetCertificateContextProperty(linked,
2636          CERT_FRIENDLY_NAME_PROP_ID, NULL, &size);
2637         ok(ret, "CertGetCertificateContextProperty failed: %08x\n",
2638          GetLastError());
2639         buf = HeapAlloc(GetProcessHeap(), 0, size);
2640         if (buf)
2641         {
2642             ret = CertGetCertificateContextProperty(linked,
2643              CERT_FRIENDLY_NAME_PROP_ID, buf, &size);
2644             ok(ret, "CertGetCertificateContextProperty failed: %08x\n", GetLastError());
2645             ok(!lstrcmpW((LPCWSTR)buf, WineTestW),
2646              "unexpected friendly name\n");
2647             HeapFree(GetProcessHeap(), 0, buf);
2648         }
2649         CertFreeCertificateContext(linked);
2650     }
2651     CertCloseStore(store2, 0);
2652 
2653     if (!GetTempFileNameW(szDot, szPrefix, 0, filename2))
2654        return;
2655 
2656     DeleteFileW(filename2);
2657     file = CreateFileW(filename2, GENERIC_READ | GENERIC_WRITE, 0, NULL,
2658      CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
2659     if (file == INVALID_HANDLE_VALUE)
2660         return;
2661 
2662     store2 = CertOpenStore(CERT_STORE_PROV_FILE, 0, 0,
2663      CERT_FILE_STORE_COMMIT_ENABLE_FLAG, file);
2664     ok(store2 != NULL, "CertOpenStore failed: %08x\n", GetLastError());
2665     CloseHandle(file);
2666     /* Test adding a link to a file store. */
2667     ret = CertAddCertificateLinkToStore(store2, source, CERT_STORE_ADD_ALWAYS,
2668      &linked);
2669     ok(ret, "CertAddCertificateLinkToStore failed: %08x\n", GetLastError());
2670     if (ret)
2671     {
2672         ok(linked->hCertStore == store2, "unexpected store\n");
2673         ret = CertSerializeCertificateStoreElement(linked, 0, NULL, &size);
2674         ok(ret, "CertSerializeCertificateStoreElement failed: %08x\n",
2675          GetLastError());
2676         buf = HeapAlloc(GetProcessHeap(), 0, size);
2677         if (buf)
2678         {
2679             ret = CertSerializeCertificateStoreElement(linked, 0, buf, &size);
2680             ok(ret, "CertSerializeCertificateStoreElement failed: %08x\n",
2681              GetLastError());
2682             /* The serialized linked certificate now contains the friendly
2683              * name property.
2684              */
2685             ok(size == sizeof(serializedCertWithFriendlyName),
2686              "Wrong size %d\n", size);
2687             ok(!memcmp(serializedCertWithFriendlyName, buf, size),
2688              "Unexpected serialized cert\n");
2689             HeapFree(GetProcessHeap(), 0, buf);
2690         }
2691         CertFreeCertificateContext(linked);
2692         compareStore(store2, "file store -> file store",
2693          serializedStoreWithCertWithFriendlyName,
2694          sizeof(serializedStoreWithCertWithFriendlyName), FALSE);
2695     }
2696     CertCloseStore(store2, 0);
2697     DeleteFileW(filename2);
2698 
2699     CertFreeCertificateContext(source);
2700 
2701     CertCloseStore(store1, 0);
2702     DeleteFileW(filename1);
2703 
2704     /* Test adding a link to a system store (which is a collection store.) */
2705     store1 = CertOpenSystemStoreA(0, "My");
2706     source = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert,
2707      sizeof(bigCert));
2708     SetLastError(0xdeadbeef);
2709     ret = CertAddCertificateLinkToStore(store1, source, CERT_STORE_ADD_ALWAYS,
2710      &linked);
2711     ok(!ret && GetLastError() == E_INVALIDARG,
2712      "expected E_INVALIDARG, got %08x\n", GetLastError());
2713     CertFreeCertificateContext(source);
2714 
2715     /* Test adding a link to a file store, where the linked certificate is
2716      * in a system store.
2717      */
2718     ret = CertAddEncodedCertificateToStore(store1, X509_ASN_ENCODING,
2719      bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, &source);
2720     ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
2721      GetLastError());
2722     if (!GetTempFileNameW(szDot, szPrefix, 0, filename1))
2723        return;
2724 
2725     DeleteFileW(filename1);
2726     file = CreateFileW(filename1, GENERIC_READ | GENERIC_WRITE, 0, NULL,
2727      CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
2728     if (file == INVALID_HANDLE_VALUE)
2729         return;
2730 
2731     store2 = CertOpenStore(CERT_STORE_PROV_FILE, 0, 0,
2732      CERT_FILE_STORE_COMMIT_ENABLE_FLAG, file);
2733     ok(store2 != NULL, "CertOpenStore failed: %08x\n", GetLastError());
2734     CloseHandle(file);
2735 
2736     ret = CertAddCertificateLinkToStore(store2, source, CERT_STORE_ADD_ALWAYS,
2737      &linked);
2738     ok(ret, "CertAddCertificateLinkToStore failed: %08x\n", GetLastError());
2739     if (ret)
2740     {
2741         ok(linked->hCertStore == store2, "unexpected store\n");
2742         ret = CertControlStore(store2, 0, CERT_STORE_CTRL_COMMIT, NULL);
2743         ok(ret, "CertControlStore failed: %d\n", ret);
2744         compareStore(store2, "file store -> system store",
2745          serializedStoreWithCertAndHash,
2746          sizeof(serializedStoreWithCertAndHash), TRUE);
2747         CertFreeCertificateContext(linked);
2748     }
2749 
2750     CertCloseStore(store2, 0);
2751     DeleteFileW(filename1);
2752 
2753     /* Test adding a link to a registry store, where the linked certificate is
2754      * in a system store.
2755      */
2756     store2 = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY, 0, 0,
2757      CERT_SYSTEM_STORE_CURRENT_USER, WineTestW);
2758     ok(store2 != NULL, "CertOpenStore failed: %08x\n", GetLastError());
2759     ret = CertAddCertificateLinkToStore(store2, source, CERT_STORE_ADD_ALWAYS,
2760      &linked);
2761     ok(ret, "CertAddCertificateLinkToStore failed: %08x\n", GetLastError());
2762     if (ret)
2763     {
2764         ok(linked->hCertStore == store2, "unexpected store\n");
2765         CertDeleteCertificateFromStore(linked);
2766     }
2767     CertCloseStore(store2, 0);
2768 
2769     CertFreeCertificateContext(source);
2770     CertCloseStore(store1, 0);
2771 
2772     delete_test_key();
2773 }
2774 
2775 static DWORD countCertsInStore(HCERTSTORE store)
2776 {
2777     PCCERT_CONTEXT cert = NULL;
2778     DWORD certs = 0;
2779 
2780     do {
2781         cert = CertEnumCertificatesInStore(store, cert);
2782         if (cert)
2783             certs++;
2784     } while (cert);
2785     return certs;
2786 }
2787 
2788 static DWORD countCRLsInStore(HCERTSTORE store)
2789 {
2790     PCCRL_CONTEXT crl = NULL;
2791     DWORD crls = 0;
2792 
2793     do {
2794         crl = CertEnumCRLsInStore(store, crl);
2795         if (crl)
2796             crls++;
2797     } while (crl);
2798     return crls;
2799 }
2800 
2801 static void testEmptyStore(void)
2802 {
2803     const CERT_CONTEXT *cert, *cert2, *cert3;
2804     const CRL_CONTEXT *crl;
2805     const CTL_CONTEXT *ctl;
2806     HCERTSTORE store;
2807     BOOL res;
2808 
2809     cert = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert, sizeof(bigCert));
2810     ok(cert != NULL, "CertCreateCertificateContext failed\n");
2811     ok(cert->hCertStore != NULL, "cert->hCertStore == NULL\n");
2812     if(!cert->hCertStore) {
2813         CertFreeCertificateContext(cert);
2814         return;
2815     }
2816 
2817     test_store_is_empty(cert->hCertStore);
2818 
2819     cert2 = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert2, sizeof(bigCert2));
2820     ok(cert2 != NULL, "CertCreateCertificateContext failed\n");
2821     ok(cert2->hCertStore == cert->hCertStore, "Unexpected hCertStore\n");
2822 
2823     test_store_is_empty(cert2->hCertStore);
2824 
2825     res = CertAddCertificateContextToStore(cert->hCertStore, cert2, CERT_STORE_ADD_NEW, &cert3);
2826     ok(res, "CertAddCertificateContextToStore failed\n");
2827     todo_wine
2828     ok(cert3 && cert3 != cert2, "Unexpected cert3\n");
2829     ok(cert3->hCertStore == cert->hCertStore, "Unexpected hCertStore\n");
2830 
2831     test_store_is_empty(cert->hCertStore);
2832 
2833     res = CertDeleteCertificateFromStore(cert3);
2834     ok(res, "CertDeleteCertificateContextFromStore failed\n");
2835     ok(cert3->hCertStore == cert->hCertStore, "Unexpected hCertStore\n");
2836 
2837     CertFreeCertificateContext(cert3);
2838 
2839     store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0, CERT_STORE_CREATE_NEW_FLAG, NULL);
2840     ok(store != NULL, "CertOpenStore failed\n");
2841 
2842     res = CertAddCertificateContextToStore(store, cert2, CERT_STORE_ADD_NEW, &cert3);
2843     ok(res, "CertAddCertificateContextToStore failed\n");
2844     ok(cert3 && cert3 != cert2, "Unexpected cert3\n");
2845     ok(cert3->hCertStore == store, "Unexpected hCertStore\n");
2846 
2847     res = CertDeleteCertificateFromStore(cert3);
2848     ok(res, "CertDeleteCertificateContextFromStore failed\n");
2849     ok(cert3->hCertStore == store, "Unexpected hCertStore\n");
2850 
2851     CertCloseStore(store, 0);
2852     CertFreeCertificateContext(cert3);
2853 
2854     res = CertCloseStore(cert->hCertStore, CERT_CLOSE_STORE_CHECK_FLAG);
2855     ok(!res && GetLastError() == E_UNEXPECTED, "CertCloseStore returned: %x(%x)\n", res, GetLastError());
2856 
2857     res = CertCloseStore(cert->hCertStore, 0);
2858     ok(!res && GetLastError() == E_UNEXPECTED, "CertCloseStore returned: %x(%x)\n", res, GetLastError());
2859 
2860     CertFreeCertificateContext(cert2);
2861 
2862     crl = CertCreateCRLContext(X509_ASN_ENCODING, signedCRL, sizeof(signedCRL));
2863     ok(crl != NULL, "CertCreateCRLContext failed\n");
2864     ok(crl->hCertStore == cert->hCertStore, "unexpected hCertStore\n");
2865 
2866     CertFreeCRLContext(crl);
2867 
2868     ctl = CertCreateCTLContext(X509_ASN_ENCODING, signedCTLWithCTLInnerContent, sizeof(signedCTLWithCTLInnerContent));
2869     ok(ctl != NULL, "CertCreateCTLContext failed\n");
2870     ok(ctl->hCertStore == cert->hCertStore, "unexpected hCertStore\n");
2871 
2872     CertFreeCTLContext(ctl);
2873 
2874     CertFreeCertificateContext(cert);
2875 }
2876 
2877 static void testCloseStore(void)
2878 {
2879     const CERT_CONTEXT *cert;
2880     const CRL_CONTEXT *crl;
2881     const CTL_CONTEXT *ctl;
2882     HCERTSTORE store, store2;
2883     BOOL res;
2884 
2885     store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0, CERT_STORE_CREATE_NEW_FLAG, NULL);
2886     ok(store != NULL, "CertOpenStore failed\n");
2887 
2888     res = CertCloseStore(store, CERT_CLOSE_STORE_CHECK_FLAG);
2889     ok(res, "CertCloseStore failed\n");
2890 
2891     store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0, CERT_STORE_CREATE_NEW_FLAG, NULL);
2892     ok(store != NULL, "CertOpenStore failed\n");
2893 
2894     store2 = CertDuplicateStore(store);
2895     ok(store2 != NULL, "CertCloneStore failed\n");
2896     ok(store2 == store, "unexpected store2\n");
2897 
2898     res = CertCloseStore(store, CERT_CLOSE_STORE_CHECK_FLAG);
2899     ok(!res && GetLastError() == CRYPT_E_PENDING_CLOSE, "CertCloseStore failed\n");
2900 
2901     res = CertCloseStore(store2, CERT_CLOSE_STORE_CHECK_FLAG);
2902     ok(res, "CertCloseStore failed\n");
2903 
2904     store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0, CERT_STORE_CREATE_NEW_FLAG, NULL);
2905     ok(store != NULL, "CertOpenStore failed\n");
2906 
2907     res = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING, bigCert,
2908      sizeof(bigCert), CERT_STORE_ADD_ALWAYS, &cert);
2909     ok(res, "CertAddEncodedCertificateToStore failed\n");
2910 
2911     /* There is still a reference from cert */
2912     res = CertCloseStore(store, CERT_CLOSE_STORE_CHECK_FLAG);
2913     ok(!res && GetLastError() == CRYPT_E_PENDING_CLOSE, "CertCloseStore failed\n");
2914 
2915     res = CertFreeCertificateContext(cert);
2916     ok(res, "CertFreeCertificateContext failed\n");
2917 
2918     store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0, CERT_STORE_CREATE_NEW_FLAG, NULL);
2919     ok(store != NULL, "CertOpenStore failed\n");
2920 
2921     res = CertAddEncodedCRLToStore(store, X509_ASN_ENCODING, signedCRL,
2922      sizeof(signedCRL), CERT_STORE_ADD_ALWAYS, &crl);
2923     ok(res, "CertAddEncodedCRLToStore failed\n");
2924 
2925     /* There is still a reference from CRL */
2926     res = CertCloseStore(store, CERT_CLOSE_STORE_CHECK_FLAG);
2927     ok(!res && GetLastError() == CRYPT_E_PENDING_CLOSE, "CertCloseStore failed\n");
2928 
2929     res = CertFreeCRLContext(crl);
2930     ok(res, "CertFreeCRLContext failed\n");
2931 
2932     store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0, CERT_STORE_CREATE_NEW_FLAG, NULL);
2933     ok(store != NULL, "CertOpenStore failed\n");
2934 
2935     res = CertAddEncodedCTLToStore(store, X509_ASN_ENCODING, signedCTLWithCTLInnerContent,
2936      sizeof(signedCTLWithCTLInnerContent), CERT_STORE_ADD_ALWAYS, &ctl);
2937     ok(res, "CertAddEncodedCTLToStore failed\n");
2938 
2939     /* There is still a reference from CTL */
2940     res = CertCloseStore(store, CERT_CLOSE_STORE_CHECK_FLAG);
2941     ok(!res && GetLastError() == CRYPT_E_PENDING_CLOSE, "CertCloseStore returned: %x(%u)\n", res, GetLastError());
2942 
2943     res = CertFreeCTLContext(ctl);
2944     ok(res, "CertFreeCTLContext failed\n");
2945 
2946     /* Add all kinds of contexts, then release external references and make sure that store is properly closed. */
2947     store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0, CERT_STORE_CREATE_NEW_FLAG, NULL);
2948     ok(store != NULL, "CertOpenStore failed\n");
2949 
2950     res = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING, bigCert,
2951      sizeof(bigCert), CERT_STORE_ADD_ALWAYS, &cert);
2952     ok(res, "CertAddEncodedCertificateToStore failed\n");
2953 
2954     res = CertAddEncodedCRLToStore(store, X509_ASN_ENCODING, signedCRL,
2955      sizeof(signedCRL), CERT_STORE_ADD_ALWAYS, &crl);
2956     ok(res, "CertAddEncodedCRLToStore failed\n");
2957 
2958     res = CertAddEncodedCTLToStore(store, X509_ASN_ENCODING, signedCTLWithCTLInnerContent,
2959      sizeof(signedCTLWithCTLInnerContent), CERT_STORE_ADD_ALWAYS, &ctl);
2960     ok(res, "CertAddEncodedCTLToStore failed\n");
2961 
2962     CertFreeCertificateContext(cert);
2963     CertFreeCRLContext(crl);
2964     CertFreeCTLContext(ctl);
2965 
2966     res = CertCloseStore(store, CERT_CLOSE_STORE_CHECK_FLAG);
2967     ok(res, "CertCloseStore failed\n");
2968 }
2969 
2970 static void test_I_UpdateStore(void)
2971 {
2972     HMODULE lib = GetModuleHandleA("crypt32");
2973     BOOL (WINAPI *pI_CertUpdatestore)(HCERTSTORE, HCERTSTORE, DWORD, DWORD) =
2974      (void *)GetProcAddress(lib, "I_CertUpdateStore");
2975     BOOL ret;
2976     HCERTSTORE store1, store2;
2977     PCCERT_CONTEXT cert;
2978     DWORD certs;
2979 
2980     if (!pI_CertUpdatestore)
2981     {
2982         win_skip("No I_CertUpdateStore\n");
2983         return;
2984     }
2985     store1 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
2986      CERT_STORE_CREATE_NEW_FLAG, NULL);
2987     store2 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
2988      CERT_STORE_CREATE_NEW_FLAG, NULL);
2989 
2990     /* Crash
2991     ret = pI_CertUpdatestore(NULL, NULL, 0, 0);
2992     ret = pI_CertUpdatestore(store1, NULL, 0, 0);
2993     ret = pI_CertUpdatestore(NULL, store2, 0, 0);
2994      */
2995     ret = pI_CertUpdatestore(store1, store2, 0, 0);
2996     ok(ret, "I_CertUpdateStore failed: %08x\n", GetLastError());
2997 
2998     CertAddEncodedCertificateToStore(store2, X509_ASN_ENCODING, bigCert,
2999      sizeof(bigCert), CERT_STORE_ADD_ALWAYS, &cert);
3000     /* I_CertUpdateStore adds the contexts from store2 to store1 */
3001     ret = pI_CertUpdatestore(store1, store2, 0, 0);
3002     ok(ret, "I_CertUpdateStore failed: %08x\n", GetLastError());
3003     certs = countCertsInStore(store1);
3004     ok(certs == 1, "Expected 1 cert, got %d\n", certs);
3005     /* Calling it a second time has no effect */
3006     ret = pI_CertUpdatestore(store1, store2, 0, 0);
3007     ok(ret, "I_CertUpdateStore failed: %08x\n", GetLastError());
3008     certs = countCertsInStore(store1);
3009     ok(certs == 1, "Expected 1 cert, got %d\n", certs);
3010 
3011     /* The last parameters to I_CertUpdateStore appear to be ignored */
3012     ret = pI_CertUpdatestore(store1, store2, 1, 0);
3013     ok(ret, "I_CertUpdateStore failed: %08x\n", GetLastError());
3014     ret = pI_CertUpdatestore(store1, store2, 0, 1);
3015     ok(ret, "I_CertUpdateStore failed: %08x\n", GetLastError());
3016 
3017     CertAddEncodedCRLToStore(store2, X509_ASN_ENCODING, signedCRL,
3018      sizeof(signedCRL), CERT_STORE_ADD_ALWAYS, NULL);
3019 
3020     /* I_CertUpdateStore also adds the CRLs from store2 to store1 */
3021     ret = pI_CertUpdatestore(store1, store2, 0, 0);
3022     ok(ret, "I_CertUpdateStore failed: %08x\n", GetLastError());
3023     certs = countCertsInStore(store1);
3024     ok(certs == 1, "Expected 1 cert, got %d\n", certs);
3025     certs = countCRLsInStore(store1);
3026     ok(certs == 1, "Expected 1 CRL, got %d\n", certs);
3027 
3028     CertDeleteCertificateFromStore(cert);
3029     /* If a context is deleted from store2, I_CertUpdateStore deletes it
3030      * from store1
3031      */
3032     ret = pI_CertUpdatestore(store1, store2, 0, 0);
3033     ok(ret, "I_CertUpdateStore failed: %08x\n", GetLastError());
3034     certs = countCertsInStore(store1);
3035     ok(certs == 0, "Expected 0 certs, got %d\n", certs);
3036 
3037     CertCloseStore(store1, 0);
3038     CertCloseStore(store2, 0);
3039 }
3040 
3041 START_TEST(store)
3042 {
3043     /* various combinations of CertOpenStore */
3044     testMemStore();
3045     testCollectionStore();
3046     testStoresInCollection();
3047 
3048     testRegStore();
3049     testRegStoreSavedCerts();
3050 
3051     testSystemRegStore();
3052     testSystemStore();
3053     testFileStore();
3054     testFileNameStore();
3055     testMessageStore();
3056     testSerializedStore();
3057     testCloseStore();
3058 
3059     testCertRegisterSystemStore();
3060 
3061     testCertOpenSystemStore();
3062     testCertEnumSystemStore();
3063     testStoreProperty();
3064 
3065     testAddSerialized();
3066     testAddCertificateLink();
3067 
3068     testEmptyStore();
3069 
3070     test_I_UpdateStore();
3071 }
3072