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