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