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