wintrust: Fix memory leaks in tests.
[wine] / dlls / wintrust / tests / softpub.c
1 /*
2  * wintrust softpub functions tests
3  *
4  * Copyright 2007 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 #include <assert.h>
21 #include <stdio.h>
22 #include <stdarg.h>
23 #include <windef.h>
24 #include <winbase.h>
25 #include <winerror.h>
26 #include <wintrust.h>
27 #include <softpub.h>
28 #include <mssip.h>
29 #include <winuser.h>
30 #include "winnls.h"
31
32 #include "wine/test.h"
33
34 /* Just in case we're being built with borked headers, redefine function
35  * pointers to have the correct calling convention.
36  */
37 typedef void   *(WINAPI *SAFE_MEM_ALLOC)(DWORD);
38 typedef void    (WINAPI *SAFE_MEM_FREE)(void *);
39 typedef BOOL    (WINAPI *SAFE_ADD_STORE)(CRYPT_PROVIDER_DATA *,
40  HCERTSTORE);
41 typedef BOOL    (WINAPI *SAFE_ADD_SGNR)(CRYPT_PROVIDER_DATA *,
42  BOOL, DWORD, struct _CRYPT_PROVIDER_SGNR *);
43 typedef BOOL    (WINAPI *SAFE_ADD_CERT)(CRYPT_PROVIDER_DATA *,
44  DWORD, BOOL, DWORD, PCCERT_CONTEXT);
45 typedef BOOL    (WINAPI *SAFE_ADD_PRIVDATA)(CRYPT_PROVIDER_DATA *,
46  CRYPT_PROVIDER_PRIVDATA *);
47 typedef HRESULT (WINAPI *SAFE_PROVIDER_INIT_CALL)(CRYPT_PROVIDER_DATA *);
48 typedef HRESULT (WINAPI *SAFE_PROVIDER_OBJTRUST_CALL)(CRYPT_PROVIDER_DATA *);
49 typedef HRESULT (WINAPI *SAFE_PROVIDER_SIGTRUST_CALL)(CRYPT_PROVIDER_DATA *);
50 typedef HRESULT (WINAPI *SAFE_PROVIDER_CERTTRUST_CALL)(CRYPT_PROVIDER_DATA *);
51 typedef HRESULT (WINAPI *SAFE_PROVIDER_FINALPOLICY_CALL)(CRYPT_PROVIDER_DATA *);
52 typedef HRESULT (WINAPI *SAFE_PROVIDER_TESTFINALPOLICY_CALL)(
53  CRYPT_PROVIDER_DATA *);
54 typedef HRESULT (WINAPI *SAFE_PROVIDER_CLEANUP_CALL)(CRYPT_PROVIDER_DATA *);
55 typedef BOOL    (WINAPI *SAFE_PROVIDER_CERTCHKPOLICY_CALL)(
56  CRYPT_PROVIDER_DATA *, DWORD, BOOL, DWORD);
57
58 typedef struct _SAFE_PROVIDER_FUNCTIONS
59 {
60     DWORD                              cbStruct;
61     SAFE_MEM_ALLOC                     pfnAlloc;
62     SAFE_MEM_FREE                      pfnFree;
63     SAFE_ADD_STORE                     pfnAddStore2Chain;
64     SAFE_ADD_SGNR                      pfnAddSgnr2Chain;
65     SAFE_ADD_CERT                      pfnAddCert2Chain;
66     SAFE_ADD_PRIVDATA                  pfnAddPrivData2Chain;
67     SAFE_PROVIDER_INIT_CALL            pfnInitialize;
68     SAFE_PROVIDER_OBJTRUST_CALL        pfnObjectTrust;
69     SAFE_PROVIDER_SIGTRUST_CALL        pfnSignatureTrust;
70     SAFE_PROVIDER_CERTTRUST_CALL       pfnCertificateTrust;
71     SAFE_PROVIDER_FINALPOLICY_CALL     pfnFinalPolicy;
72     SAFE_PROVIDER_CERTCHKPOLICY_CALL   pfnCertCheckPolicy;
73     SAFE_PROVIDER_TESTFINALPOLICY_CALL pfnTestFinalPolicy;
74     struct _CRYPT_PROVUI_FUNCS        *psUIpfns;
75     SAFE_PROVIDER_CLEANUP_CALL         pfnCleanupPolicy;
76 } SAFE_PROVIDER_FUNCTIONS;
77
78 static const BYTE v1CertWithPubKey[] = {
79 0x30,0x81,0x95,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,
80 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
81 0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,
82 0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
83 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,
84 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
85 0x67,0x00,0x30,0x22,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
86 0x01,0x01,0x05,0x00,0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
87 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0xa3,0x16,0x30,0x14,0x30,0x12,0x06,
88 0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,
89 0x01,0x01 };
90
91 static void test_utils(SAFE_PROVIDER_FUNCTIONS *funcs)
92 {
93     CRYPT_PROVIDER_DATA data = { 0 };
94     HCERTSTORE store;
95     CRYPT_PROVIDER_SGNR sgnr = { 0 };
96     BOOL ret;
97
98     /* Crash
99     ret = funcs->pfnAddStore2Chain(NULL, NULL);
100     ret = funcs->pfnAddStore2Chain(&data, NULL);
101      */
102     store = CertOpenStore(CERT_STORE_PROV_MEMORY, X509_ASN_ENCODING, 0,
103      CERT_STORE_CREATE_NEW_FLAG, NULL);
104     if (store)
105     {
106         ret = funcs->pfnAddStore2Chain(&data, store);
107         ok(ret, "pfnAddStore2Chain failed: %08x\n", GetLastError());
108         ok(data.chStores == 1, "Expected 1 store, got %d\n", data.chStores);
109         ok(data.pahStores != NULL, "Expected pahStores to be allocated\n");
110         if (data.pahStores)
111         {
112             ok(data.pahStores[0] == store, "Unexpected store\n");
113             CertCloseStore(data.pahStores[0], 0);
114             funcs->pfnFree(data.pahStores);
115             data.pahStores = NULL;
116             data.chStores = 0;
117             CertCloseStore(store, 0);
118             store = NULL;
119         }
120     }
121     else
122         skip("CertOpenStore failed: %08x\n", GetLastError());
123
124     /* Crash
125     ret = funcs->pfnAddSgnr2Chain(NULL, FALSE, 0, NULL);
126     ret = funcs->pfnAddSgnr2Chain(&data, FALSE, 0, NULL);
127      */
128     ret = funcs->pfnAddSgnr2Chain(&data, FALSE, 0, &sgnr);
129     ok(ret, "pfnAddSgnr2Chain failed: %08x\n", GetLastError());
130     ok(data.csSigners == 1, "Expected 1 signer, got %d\n", data.csSigners);
131     ok(data.pasSigners != NULL, "Expected pasSigners to be allocated\n");
132     if (data.pasSigners)
133     {
134         PCCERT_CONTEXT cert;
135
136         ok(!memcmp(&data.pasSigners[0], &sgnr, sizeof(sgnr)),
137          "Unexpected data in signer\n");
138         /* Adds into the location specified by the index */
139         sgnr.cbStruct = sizeof(CRYPT_PROVIDER_SGNR);
140         sgnr.sftVerifyAsOf.dwLowDateTime = 0xdeadbeef;
141         ret = funcs->pfnAddSgnr2Chain(&data, FALSE, 1, &sgnr);
142         ok(ret, "pfnAddSgnr2Chain failed: %08x\n", GetLastError());
143         ok(data.csSigners == 2, "Expected 2 signers, got %d\n", data.csSigners);
144         ok(!memcmp(&data.pasSigners[1], &sgnr, sizeof(sgnr)),
145          "Unexpected data in signer\n");
146         /* This also adds, but the data aren't copied */
147         sgnr.cbStruct = sizeof(DWORD);
148         ret = funcs->pfnAddSgnr2Chain(&data, FALSE, 0, &sgnr);
149         ok(ret, "pfnAddSgnr2Chain failed: %08x\n", GetLastError());
150         ok(data.csSigners == 3, "Expected 3 signers, got %d\n", data.csSigners);
151         ok(data.pasSigners[0].cbStruct == 0, "Unexpected data size %d\n",
152          data.pasSigners[0].cbStruct);
153         ok(data.pasSigners[0].sftVerifyAsOf.dwLowDateTime == 0,
154          "Unexpected verify time %d\n",
155          data.pasSigners[0].sftVerifyAsOf.dwLowDateTime);
156         /* But too large a thing isn't added */
157         sgnr.cbStruct = sizeof(sgnr) + sizeof(DWORD);
158         SetLastError(0xdeadbeef);
159         ret = funcs->pfnAddSgnr2Chain(&data, FALSE, 0, &sgnr);
160         ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
161          "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
162
163         /* Crash
164         ret = funcs->pfnAddCert2Chain(NULL, 0, FALSE, 0, NULL);
165         ret = funcs->pfnAddCert2Chain(&data, 0, FALSE, 0, NULL);
166          */
167         cert = CertCreateCertificateContext(X509_ASN_ENCODING, v1CertWithPubKey,
168          sizeof(v1CertWithPubKey));
169         if (cert)
170         {
171             /* Notes on behavior that are hard to test:
172              * 1. If pasSigners is invalid, pfnAddCert2Chain crashes
173              * 2. An invalid signer index isn't checked.
174              */
175             ret = funcs->pfnAddCert2Chain(&data, 0, FALSE, 0, cert);
176             ok(ret, "pfnAddCert2Chain failed: %08x\n", GetLastError());
177             ok(data.pasSigners[0].csCertChain == 1, "Expected 1 cert, got %d\n",
178              data.pasSigners[0].csCertChain);
179             ok(data.pasSigners[0].pasCertChain != NULL,
180              "Expected pasCertChain to be allocated\n");
181             if (data.pasSigners[0].pasCertChain)
182             {
183                 ok(data.pasSigners[0].pasCertChain[0].pCert == cert,
184                  "Unexpected cert\n");
185                 CertFreeCertificateContext(
186                  data.pasSigners[0].pasCertChain[0].pCert);
187             }
188             CertFreeCertificateContext(cert);
189         }
190         else
191             skip("CertCreateCertificateContext failed: %08x\n", GetLastError());
192     }
193 }
194
195 static void testInitialize(SAFE_PROVIDER_FUNCTIONS *funcs, GUID *actionID)
196 {
197     HRESULT ret;
198     CRYPT_PROVIDER_DATA data = { 0 };
199     WINTRUST_DATA wintrust_data = { 0 };
200
201     if (!funcs->pfnInitialize)
202     {
203         skip("missing pfnInitialize\n");
204         return;
205     }
206
207     /* Crashes
208     ret = funcs->pfnInitialize(NULL);
209      */
210     memset(&data, 0, sizeof(data));
211     ret = funcs->pfnInitialize(&data);
212     ok(ret == S_FALSE, "Expected S_FALSE, got %08x\n", ret);
213     data.padwTrustStepErrors =
214      funcs->pfnAlloc(TRUSTERROR_MAX_STEPS * sizeof(DWORD));
215     /* Without wintrust data set, crashes when padwTrustStepErrors is set */
216     data.pWintrustData = &wintrust_data;
217     if (data.padwTrustStepErrors)
218     {
219         /* Apparently, cdwTrustStepErrors does not need to be set. */
220         ret = funcs->pfnInitialize(&data);
221         ok(ret == S_OK, "Expected S_OK, got %08x\n", ret);
222         data.cdwTrustStepErrors = 1;
223         ret = funcs->pfnInitialize(&data);
224         ok(ret == S_OK, "Expected S_OK, got %08x\n", ret);
225         memset(data.padwTrustStepErrors, 0xba,
226          TRUSTERROR_MAX_STEPS * sizeof(DWORD));
227         ret = funcs->pfnInitialize(&data);
228         ok(ret == S_FALSE, "Expected S_FALSE, got %08x\n", ret);
229         data.padwTrustStepErrors[TRUSTERROR_STEP_FINAL_WVTINIT] = 0;
230         ret = funcs->pfnInitialize(&data);
231         ok(ret == S_OK, "Expected S_OK, got %08x\n", ret);
232         funcs->pfnFree(data.padwTrustStepErrors);
233     }
234 }
235
236 static void getNotepadPath(WCHAR *notepadPathW, DWORD size)
237 {
238     static const CHAR notepad[] = "\\notepad.exe";
239     CHAR notepadPath[MAX_PATH];
240
241     /* Workaround missing W-functions for win9x */
242     GetWindowsDirectoryA(notepadPath, MAX_PATH);
243     lstrcatA(notepadPath, notepad);
244     MultiByteToWideChar(0, 0, notepadPath, -1, notepadPathW, size);
245 }
246
247 static void testObjTrust(SAFE_PROVIDER_FUNCTIONS *funcs, GUID *actionID)
248 {
249     HRESULT ret;
250     CRYPT_PROVIDER_DATA data = { 0 };
251     WINTRUST_DATA wintrust_data = { 0 };
252     WINTRUST_CERT_INFO certInfo = { sizeof(WINTRUST_CERT_INFO), 0 };
253     WINTRUST_FILE_INFO fileInfo = { sizeof(WINTRUST_FILE_INFO), 0 };
254
255     if (!funcs->pfnObjectTrust)
256     {
257         skip("missing pfnObjectTrust\n");
258         return;
259     }
260
261     /* Crashes
262     ret = funcs->pfnObjectTrust(NULL);
263      */
264     data.pWintrustData = &wintrust_data;
265     data.padwTrustStepErrors =
266      funcs->pfnAlloc(TRUSTERROR_MAX_STEPS * sizeof(DWORD));
267     if (data.padwTrustStepErrors)
268     {
269         WCHAR notepadPathW[MAX_PATH];
270         PROVDATA_SIP provDataSIP = { 0 };
271         static const GUID unknown = { 0xC689AAB8, 0x8E78, 0x11D0, { 0x8C,0x47,
272          0x00,0xC0,0x4F,0xC2,0x95,0xEE } };
273         static GUID bogusGuid = { 0xdeadbeef, 0xbaad, 0xf00d, { 0x00,0x00,0x00,
274          0x00,0x00,0x00,0x00,0x00 } };
275
276         ret = funcs->pfnObjectTrust(&data);
277         ok(ret == S_FALSE, "Expected S_FALSE, got %08x\n", ret);
278         ok(data.padwTrustStepErrors[TRUSTERROR_STEP_FINAL_OBJPROV] ==
279          ERROR_INVALID_PARAMETER,
280          "Expected ERROR_INVALID_PARAMETER, got %08x\n",
281          data.padwTrustStepErrors[TRUSTERROR_STEP_FINAL_OBJPROV]);
282         U(wintrust_data).pCert = &certInfo;
283         wintrust_data.dwUnionChoice = WTD_CHOICE_CERT;
284         ret = funcs->pfnObjectTrust(&data);
285         ok(ret == S_OK, "Expected S_OK, got %08x\n", ret);
286         certInfo.psCertContext = (PCERT_CONTEXT)CertCreateCertificateContext(
287          X509_ASN_ENCODING, v1CertWithPubKey, sizeof(v1CertWithPubKey));
288         ret = funcs->pfnObjectTrust(&data);
289         ok(ret == S_OK, "Expected S_OK, got %08x\n", ret);
290         CertFreeCertificateContext(certInfo.psCertContext);
291         certInfo.psCertContext = NULL;
292         wintrust_data.dwUnionChoice = WTD_CHOICE_FILE;
293         U(wintrust_data).pFile = NULL;
294         ret = funcs->pfnObjectTrust(&data);
295         ok(ret == S_FALSE, "Expected S_FALSE, got %08x\n", ret);
296         ok(data.padwTrustStepErrors[TRUSTERROR_STEP_FINAL_OBJPROV] ==
297          ERROR_INVALID_PARAMETER,
298          "Expected ERROR_INVALID_PARAMETER, got %08x\n",
299          data.padwTrustStepErrors[TRUSTERROR_STEP_FINAL_OBJPROV]);
300         U(wintrust_data).pFile = &fileInfo;
301         /* Crashes
302         ret = funcs->pfnObjectTrust(&data);
303          */
304         getNotepadPath(notepadPathW, MAX_PATH);
305         fileInfo.pcwszFilePath = notepadPathW;
306         /* pfnObjectTrust now crashes unless both pPDSip and psPfns are set */
307         U(data).pPDSip = &provDataSIP;
308         data.psPfns = (CRYPT_PROVIDER_FUNCTIONS *)funcs;
309         ret = funcs->pfnObjectTrust(&data);
310         ok(ret == S_FALSE, "Expected S_FALSE, got %08x\n", ret);
311         ok(data.padwTrustStepErrors[TRUSTERROR_STEP_FINAL_OBJPROV] ==
312          TRUST_E_NOSIGNATURE ||
313          data.padwTrustStepErrors[TRUSTERROR_STEP_FINAL_OBJPROV] ==
314          TRUST_E_SUBJECT_FORM_UNKNOWN,
315          "Expected TRUST_E_NOSIGNATURE or TRUST_E_SUBJECT_FORM_UNKNOWN, got %08x\n",
316          data.padwTrustStepErrors[TRUSTERROR_STEP_FINAL_OBJPROV]);
317         if (data.padwTrustStepErrors[TRUSTERROR_STEP_FINAL_OBJPROV] ==
318          TRUST_E_NOSIGNATURE)
319         {
320             ok(!memcmp(&provDataSIP.gSubject, &unknown, sizeof(unknown)),
321              "Unexpected subject GUID\n");
322             ok(provDataSIP.pSip != NULL, "Expected a SIP\n");
323             ok(provDataSIP.psSipSubjectInfo != NULL,
324              "Expected a subject info\n");
325         }
326         /* Specifying the GUID results in that GUID being the subject GUID */
327         fileInfo.pgKnownSubject = &bogusGuid;
328         ret = funcs->pfnObjectTrust(&data);
329         ok(ret == S_FALSE, "Expected S_FALSE, got %08x\n", ret);
330         ok(data.padwTrustStepErrors[TRUSTERROR_STEP_FINAL_OBJPROV] ==
331          TRUST_E_NOSIGNATURE ||
332          data.padwTrustStepErrors[TRUSTERROR_STEP_FINAL_OBJPROV] ==
333          TRUST_E_SUBJECT_FORM_UNKNOWN ||
334          data.padwTrustStepErrors[TRUSTERROR_STEP_FINAL_OBJPROV] ==
335          TRUST_E_PROVIDER_UNKNOWN,
336          "Expected TRUST_E_NOSIGNATURE or TRUST_E_SUBJECT_FORM_UNKNOWN or TRUST_E_PROVIDER_UNKNOWN, got %08x\n",
337          data.padwTrustStepErrors[TRUSTERROR_STEP_FINAL_OBJPROV]);
338         if (data.padwTrustStepErrors[TRUSTERROR_STEP_FINAL_OBJPROV] ==
339          TRUST_E_NOSIGNATURE)
340         {
341             ok(!memcmp(&provDataSIP.gSubject, &bogusGuid, sizeof(bogusGuid)),
342              "unexpected subject GUID\n");
343         }
344         /* Specifying a bogus GUID pointer crashes */
345         if (0)
346         {
347             fileInfo.pgKnownSubject = (GUID *)0xdeadbeef;
348             ret = funcs->pfnObjectTrust(&data);
349         }
350         funcs->pfnFree(data.padwTrustStepErrors);
351     }
352 }
353
354 static const BYTE selfSignedCert[] = {
355  0x30, 0x82, 0x01, 0x1f, 0x30, 0x81, 0xce, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02,
356  0x10, 0xeb, 0x0d, 0x57, 0x2a, 0x9c, 0x09, 0xba, 0xa4, 0x4a, 0xb7, 0x25, 0x49,
357  0xd9, 0x3e, 0xb5, 0x73, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1d,
358  0x05, 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03,
359  0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30,
360  0x1e, 0x17, 0x0d, 0x30, 0x36, 0x30, 0x36, 0x32, 0x39, 0x30, 0x35, 0x30, 0x30,
361  0x34, 0x36, 0x5a, 0x17, 0x0d, 0x30, 0x37, 0x30, 0x36, 0x32, 0x39, 0x31, 0x31,
362  0x30, 0x30, 0x34, 0x36, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03,
363  0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e,
364  0x67, 0x00, 0x30, 0x5c, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
365  0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x4b, 0x00, 0x30, 0x48, 0x02, 0x41,
366  0x00, 0xe2, 0x54, 0x3a, 0xa7, 0x83, 0xb1, 0x27, 0x14, 0x3e, 0x59, 0xbb, 0xb4,
367  0x53, 0xe6, 0x1f, 0xe7, 0x5d, 0xf1, 0x21, 0x68, 0xad, 0x85, 0x53, 0xdb, 0x6b,
368  0x1e, 0xeb, 0x65, 0x97, 0x03, 0x86, 0x60, 0xde, 0xf3, 0x6c, 0x38, 0x75, 0xe0,
369  0x4c, 0x61, 0xbb, 0xbc, 0x62, 0x17, 0xa9, 0xcd, 0x79, 0x3f, 0x21, 0x4e, 0x96,
370  0xcb, 0x0e, 0xdc, 0x61, 0x94, 0x30, 0x18, 0x10, 0x6b, 0xd0, 0x1c, 0x10, 0x79,
371  0x02, 0x03, 0x01, 0x00, 0x01, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02,
372  0x1d, 0x05, 0x00, 0x03, 0x41, 0x00, 0x25, 0x90, 0x53, 0x34, 0xd9, 0x56, 0x41,
373  0x5e, 0xdb, 0x7e, 0x01, 0x36, 0xec, 0x27, 0x61, 0x5e, 0xb7, 0x4d, 0x90, 0x66,
374  0xa2, 0xe1, 0x9d, 0x58, 0x76, 0xd4, 0x9c, 0xba, 0x2c, 0x84, 0xc6, 0x83, 0x7a,
375  0x22, 0x0d, 0x03, 0x69, 0x32, 0x1a, 0x6d, 0xcb, 0x0c, 0x15, 0xb3, 0x6b, 0xc7,
376  0x0a, 0x8c, 0xb4, 0x5c, 0x34, 0x78, 0xe0, 0x3c, 0x9c, 0xe9, 0xf3, 0x30, 0x9f,
377  0xa8, 0x76, 0x57, 0x92, 0x36 };
378
379 static void testCertTrust(SAFE_PROVIDER_FUNCTIONS *funcs, GUID *actionID)
380 {
381     CRYPT_PROVIDER_DATA data = { 0 };
382     CRYPT_PROVIDER_SGNR sgnr = { sizeof(sgnr), { 0 } };
383     HRESULT ret;
384
385     data.padwTrustStepErrors =
386      funcs->pfnAlloc(TRUSTERROR_MAX_STEPS * sizeof(DWORD));
387     if (!data.padwTrustStepErrors)
388     {
389         skip("pfnAlloc failed\n");
390         return;
391     }
392     ret = funcs->pfnCertificateTrust(&data);
393     ok(ret == S_FALSE, "Expected S_FALSE, got %08x\n", ret);
394     ok(data.padwTrustStepErrors[TRUSTERROR_STEP_FINAL_CERTPROV] ==
395      TRUST_E_NOSIGNATURE, "Expected TRUST_E_NOSIGNATURE, got %08x\n",
396      data.padwTrustStepErrors[TRUSTERROR_STEP_FINAL_CERTPROV]);
397     ret = funcs->pfnAddSgnr2Chain(&data, FALSE, 0, &sgnr);
398     if (ret)
399     {
400         PCCERT_CONTEXT cert;
401
402         /* An empty signer "succeeds," even though there's no cert */
403         ret = funcs->pfnCertificateTrust(&data);
404         ok(ret == S_OK, "Expected S_OK, got %08x\n", ret);
405         cert = CertCreateCertificateContext(X509_ASN_ENCODING, selfSignedCert,
406          sizeof(selfSignedCert));
407         if (cert)
408         {
409             WINTRUST_DATA wintrust_data = { 0 };
410
411             ret = funcs->pfnAddCert2Chain(&data, 0, FALSE, 0, cert);
412             /* If pWintrustData isn't set, crashes attempting to access
413              * pWintrustData->fdwRevocationChecks
414              */
415             data.pWintrustData = &wintrust_data;
416             /* If psPfns isn't set, crashes attempting to access
417              * psPfns->pfnCertCheckPolicy
418              */
419             data.psPfns = (CRYPT_PROVIDER_FUNCTIONS *)funcs;
420             ret = funcs->pfnCertificateTrust(&data);
421             ok(ret == S_OK, "Expected S_OK, got %08x\n", ret);
422             ok(data.csSigners == 1, "Unexpected number of signers %d\n",
423              data.csSigners);
424             ok(data.pasSigners[0].pChainContext != NULL,
425              "Expected a certificate chain\n");
426             ok(data.pasSigners[0].csCertChain == 1,
427              "Unexpected number of chain elements %d\n",
428              data.pasSigners[0].csCertChain);
429             /* pasSigners and pasSigners[0].pasCertChain are guaranteed to be
430              * initialized, see tests for pfnAddSgnr2Chain and pfnAddCert2Chain
431              */
432             ok(!data.pasSigners[0].pasCertChain[0].fTrustedRoot,
433              "Didn't expect cert to be trusted\n");
434             ok(data.pasSigners[0].pasCertChain[0].fSelfSigned,
435              "Expected cert to be self-signed\n");
436             ok(data.pasSigners[0].pasCertChain[0].dwConfidence ==
437              (CERT_CONFIDENCE_SIG | CERT_CONFIDENCE_TIMENEST),
438              "Expected CERT_CONFIDENCE_SIG | CERT_CONFIDENCE_TIMENEST, got %08x\n",
439              data.pasSigners[0].pasCertChain[0].dwConfidence);
440             CertFreeCertificateContext(
441              data.pasSigners[0].pasCertChain[0].pCert);
442             CertFreeCertificateChain(data.pasSigners[0].pChainContext);
443             CertFreeCertificateContext(cert);
444         }
445     }
446 }
447
448 static void test_provider_funcs(void)
449 {
450     static GUID generic_verify_v2 = WINTRUST_ACTION_GENERIC_VERIFY_V2;
451     SAFE_PROVIDER_FUNCTIONS funcs = { sizeof(SAFE_PROVIDER_FUNCTIONS), 0 };
452     BOOL ret;
453
454     ret = WintrustLoadFunctionPointers(&generic_verify_v2,
455      (CRYPT_PROVIDER_FUNCTIONS *)&funcs);
456     if (!ret)
457         skip("WintrustLoadFunctionPointers failed\n");
458     else
459     {
460         test_utils(&funcs);
461         testInitialize(&funcs, &generic_verify_v2);
462         testObjTrust(&funcs, &generic_verify_v2);
463         testCertTrust(&funcs, &generic_verify_v2);
464     }
465 }
466
467 static void test_wintrust(void)
468 {
469     static GUID generic_action_v2 = WINTRUST_ACTION_GENERIC_VERIFY_V2;
470     WINTRUST_DATA wtd;
471     WINTRUST_FILE_INFO file;
472     LONG r;
473     HRESULT hr;
474     WCHAR notepadPathW[MAX_PATH];
475
476     memset(&wtd, 0, sizeof(wtd));
477     wtd.cbStruct = sizeof(wtd);
478     wtd.dwUIChoice = WTD_UI_NONE;
479     wtd.fdwRevocationChecks = WTD_REVOKE_WHOLECHAIN;
480     wtd.dwUnionChoice = WTD_CHOICE_FILE;
481     U(wtd).pFile = &file;
482     wtd.dwStateAction = WTD_STATEACTION_VERIFY;
483     memset(&file, 0, sizeof(file));
484     file.cbStruct = sizeof(file);
485     getNotepadPath(notepadPathW, MAX_PATH);
486     file.pcwszFilePath = notepadPathW;
487     r = WinVerifyTrust(INVALID_HANDLE_VALUE, &generic_action_v2, &wtd);
488     ok(r == TRUST_E_NOSIGNATURE || r == CRYPT_E_FILE_ERROR,
489      "expected TRUST_E_NOSIGNATURE or CRYPT_E_FILE_ERROR, got %08x\n", r);
490     hr = WinVerifyTrustEx(INVALID_HANDLE_VALUE, &generic_action_v2, &wtd);
491     ok(hr == TRUST_E_NOSIGNATURE || r == CRYPT_E_FILE_ERROR,
492      "expected TRUST_E_NOSIGNATURE or CRYPT_E_FILE_ERROR, got %08x\n", hr);
493 }
494
495 static BOOL (WINAPI * pWTHelperGetKnownUsages)(DWORD action, PCCRYPT_OID_INFO **usages);
496
497 static void InitFunctionPtrs(void)
498 {
499     HMODULE hWintrust = GetModuleHandleA("wintrust.dll");
500
501 #define WINTRUST_GET_PROC(func) \
502     p ## func = (void*)GetProcAddress(hWintrust, #func); \
503     if(!p ## func) { \
504       trace("GetProcAddress(%s) failed\n", #func); \
505     }
506
507     WINTRUST_GET_PROC(WTHelperGetKnownUsages)
508
509 #undef WINTRUST_GET_PROC
510 }
511
512 static void test_get_known_usages(void)
513 {
514     BOOL ret;
515     PCCRYPT_OID_INFO *usages;
516
517     if (!pWTHelperGetKnownUsages)
518     {
519         skip("missing WTHelperGetKnownUsages\n");
520         return;
521     }
522     SetLastError(0xdeadbeef);
523     ret = pWTHelperGetKnownUsages(0, NULL);
524     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
525      "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
526     SetLastError(0xdeadbeef);
527     ret = pWTHelperGetKnownUsages(1, NULL);
528     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
529      "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
530     SetLastError(0xdeadbeef);
531     ret = pWTHelperGetKnownUsages(0, &usages);
532     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
533      "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
534     /* A value of 1 for the first parameter seems to imply the value is
535      * allocated
536      */
537     SetLastError(0xdeadbeef);
538     usages = NULL;
539     ret = pWTHelperGetKnownUsages(1, &usages);
540     ok(ret, "WTHelperGetKnownUsages failed: %d\n", GetLastError());
541     ok(usages != NULL, "expected a pointer\n");
542     if (ret && usages)
543     {
544         PCCRYPT_OID_INFO *ptr;
545
546         /* The returned usages are an array of PCCRYPT_OID_INFOs, terminated with a
547          * NULL pointer.
548          */
549         for (ptr = usages; *ptr; ptr++)
550         {
551             ok((*ptr)->cbSize == sizeof(CRYPT_OID_INFO) ||
552              (*ptr)->cbSize == (sizeof(CRYPT_OID_INFO) + 2 * sizeof(LPCWSTR)), /* Vista */
553              "unexpected size %d\n", (*ptr)->cbSize);
554             /* Each returned usage is in the CRYPT_ENHKEY_USAGE_OID_GROUP_ID group */
555             ok((*ptr)->dwGroupId == CRYPT_ENHKEY_USAGE_OID_GROUP_ID,
556              "expected group CRYPT_ENHKEY_USAGE_OID_GROUP_ID, got %d\n",
557              (*ptr)->dwGroupId);
558         }
559     }
560     /* A value of 2 for the second parameter seems to imply the value is freed
561      */
562     SetLastError(0xdeadbeef);
563     ret = pWTHelperGetKnownUsages(2, &usages);
564     ok(ret, "WTHelperGetKnownUsages failed: %d\n", GetLastError());
565     ok(usages == NULL, "expected pointer to be cleared\n");
566     SetLastError(0xdeadbeef);
567     usages = NULL;
568     ret = pWTHelperGetKnownUsages(2, &usages);
569     ok(ret, "WTHelperGetKnownUsages failed: %d\n", GetLastError());
570     SetLastError(0xdeadbeef);
571     ret = pWTHelperGetKnownUsages(2, NULL);
572     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
573      "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
574 }
575
576 START_TEST(softpub)
577 {
578     InitFunctionPtrs();
579     test_provider_funcs();
580     test_wintrust();
581     test_get_known_usages();
582 }