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