wintrust/tests: Fix compilation on systems that don't support nameless unions.
[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                 ok(data.pasSigners[0].pasCertChain[0].pCert == cert,
183                  "Unexpected cert\n");
184             CertFreeCertificateContext(cert);
185         }
186         else
187             skip("CertCreateCertificateContext failed: %08x\n", GetLastError());
188     }
189 }
190
191 static void testInitialize(SAFE_PROVIDER_FUNCTIONS *funcs, GUID *actionID)
192 {
193     HRESULT ret;
194     CRYPT_PROVIDER_DATA data = { 0 };
195     WINTRUST_DATA wintrust_data = { 0 };
196
197     if (!funcs->pfnInitialize)
198     {
199         skip("missing pfnInitialize\n");
200         return;
201     }
202
203     /* Crashes
204     ret = funcs->pfnInitialize(NULL);
205      */
206     memset(&data, 0, sizeof(data));
207     ret = funcs->pfnInitialize(&data);
208     ok(ret == S_FALSE, "Expected S_FALSE, got %08x\n", ret);
209     data.padwTrustStepErrors =
210      funcs->pfnAlloc(TRUSTERROR_MAX_STEPS * sizeof(DWORD));
211     /* Without wintrust data set, crashes when padwTrustStepErrors is set */
212     data.pWintrustData = &wintrust_data;
213     if (data.padwTrustStepErrors)
214     {
215         /* Apparently, cdwTrustStepErrors does not need to be set. */
216         ret = funcs->pfnInitialize(&data);
217         ok(ret == S_OK, "Expected S_OK, got %08x\n", ret);
218         data.cdwTrustStepErrors = 1;
219         ret = funcs->pfnInitialize(&data);
220         ok(ret == S_OK, "Expected S_OK, got %08x\n", ret);
221         memset(data.padwTrustStepErrors, 0xba,
222          TRUSTERROR_MAX_STEPS * sizeof(DWORD));
223         ret = funcs->pfnInitialize(&data);
224         ok(ret == S_FALSE, "Expected S_FALSE, got %08x\n", ret);
225         data.padwTrustStepErrors[TRUSTERROR_STEP_FINAL_WVTINIT] = 0;
226         ret = funcs->pfnInitialize(&data);
227         ok(ret == S_OK, "Expected S_OK, got %08x\n", ret);
228         funcs->pfnFree(data.padwTrustStepErrors);
229     }
230 }
231
232 static void getNotepadPath(WCHAR *notepadPathW, DWORD size)
233 {
234     static const CHAR notepad[] = "\\notepad.exe";
235     CHAR notepadPath[MAX_PATH];
236
237     /* Workaround missing W-functions for win9x */
238     GetWindowsDirectoryA(notepadPath, MAX_PATH);
239     lstrcatA(notepadPath, notepad);
240     MultiByteToWideChar(0, 0, notepadPath, -1, notepadPathW, size);
241 }
242
243 static void testObjTrust(SAFE_PROVIDER_FUNCTIONS *funcs, GUID *actionID)
244 {
245     HRESULT ret;
246     CRYPT_PROVIDER_DATA data = { 0 };
247     WINTRUST_DATA wintrust_data = { 0 };
248     WINTRUST_CERT_INFO certInfo = { sizeof(WINTRUST_CERT_INFO), 0 };
249     WINTRUST_FILE_INFO fileInfo = { sizeof(WINTRUST_FILE_INFO), 0 };
250
251     if (!funcs->pfnObjectTrust)
252     {
253         skip("missing pfnObjectTrust\n");
254         return;
255     }
256
257     /* Crashes
258     ret = funcs->pfnObjectTrust(NULL);
259      */
260     data.pWintrustData = &wintrust_data;
261     data.padwTrustStepErrors =
262      funcs->pfnAlloc(TRUSTERROR_MAX_STEPS * sizeof(DWORD));
263     if (data.padwTrustStepErrors)
264     {
265         WCHAR notepadPathW[MAX_PATH];
266         PROVDATA_SIP provDataSIP = { 0 };
267         static const GUID unknown = { 0xC689AAB8, 0x8E78, 0x11D0, { 0x8C,0x47,
268          0x00,0xC0,0x4F,0xC2,0x95,0xEE } };
269
270         ret = funcs->pfnObjectTrust(&data);
271         ok(ret == S_FALSE, "Expected S_FALSE, got %08x\n", ret);
272         ok(data.padwTrustStepErrors[TRUSTERROR_STEP_FINAL_OBJPROV] ==
273          ERROR_INVALID_PARAMETER,
274          "Expected ERROR_INVALID_PARAMETER, got %08x\n",
275          data.padwTrustStepErrors[TRUSTERROR_STEP_FINAL_OBJPROV]);
276         U(wintrust_data).pCert = &certInfo;
277         wintrust_data.dwUnionChoice = WTD_CHOICE_CERT;
278         ret = funcs->pfnObjectTrust(&data);
279         ok(ret == S_OK, "Expected S_OK, got %08x\n", ret);
280         certInfo.psCertContext = (PCERT_CONTEXT)CertCreateCertificateContext(
281          X509_ASN_ENCODING, v1CertWithPubKey, sizeof(v1CertWithPubKey));
282         ret = funcs->pfnObjectTrust(&data);
283         ok(ret == S_OK, "Expected S_OK, got %08x\n", ret);
284         CertFreeCertificateContext(certInfo.psCertContext);
285         certInfo.psCertContext = NULL;
286         wintrust_data.dwUnionChoice = WTD_CHOICE_FILE;
287         U(wintrust_data).pFile = NULL;
288         ret = funcs->pfnObjectTrust(&data);
289         ok(ret == S_FALSE, "Expected S_FALSE, got %08x\n", ret);
290         ok(data.padwTrustStepErrors[TRUSTERROR_STEP_FINAL_OBJPROV] ==
291          ERROR_INVALID_PARAMETER,
292          "Expected ERROR_INVALID_PARAMETER, got %08x\n",
293          data.padwTrustStepErrors[TRUSTERROR_STEP_FINAL_OBJPROV]);
294         U(wintrust_data).pFile = &fileInfo;
295         /* Crashes
296         ret = funcs->pfnObjectTrust(&data);
297          */
298         getNotepadPath(notepadPathW, MAX_PATH);
299         fileInfo.pcwszFilePath = notepadPathW;
300         /* pfnObjectTrust now crashes unless both pPDSip and psPfns are set */
301         U(data).pPDSip = &provDataSIP;
302         data.psPfns = (CRYPT_PROVIDER_FUNCTIONS *)funcs;
303         ret = funcs->pfnObjectTrust(&data);
304         ok(ret == S_FALSE, "Expected S_FALSE, got %08x\n", ret);
305         ok(data.padwTrustStepErrors[TRUSTERROR_STEP_FINAL_OBJPROV] ==
306          TRUST_E_NOSIGNATURE, "Expected TRUST_E_NOSIGNATURE, got %08x\n",
307          data.padwTrustStepErrors[TRUSTERROR_STEP_FINAL_OBJPROV]);
308         ok(!memcmp(&provDataSIP.gSubject, &unknown, sizeof(unknown)),
309          "Unexpected subject GUID\n");
310         ok(provDataSIP.pSip != NULL, "Expected a SIP\n");
311         ok(provDataSIP.psSipSubjectInfo != NULL, "Expected a subject info\n");
312         funcs->pfnFree(data.padwTrustStepErrors);
313     }
314 }
315
316 static const BYTE selfSignedCert[] = {
317  0x30, 0x82, 0x01, 0x1f, 0x30, 0x81, 0xce, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02,
318  0x10, 0xeb, 0x0d, 0x57, 0x2a, 0x9c, 0x09, 0xba, 0xa4, 0x4a, 0xb7, 0x25, 0x49,
319  0xd9, 0x3e, 0xb5, 0x73, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1d,
320  0x05, 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03,
321  0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30,
322  0x1e, 0x17, 0x0d, 0x30, 0x36, 0x30, 0x36, 0x32, 0x39, 0x30, 0x35, 0x30, 0x30,
323  0x34, 0x36, 0x5a, 0x17, 0x0d, 0x30, 0x37, 0x30, 0x36, 0x32, 0x39, 0x31, 0x31,
324  0x30, 0x30, 0x34, 0x36, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03,
325  0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e,
326  0x67, 0x00, 0x30, 0x5c, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
327  0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x4b, 0x00, 0x30, 0x48, 0x02, 0x41,
328  0x00, 0xe2, 0x54, 0x3a, 0xa7, 0x83, 0xb1, 0x27, 0x14, 0x3e, 0x59, 0xbb, 0xb4,
329  0x53, 0xe6, 0x1f, 0xe7, 0x5d, 0xf1, 0x21, 0x68, 0xad, 0x85, 0x53, 0xdb, 0x6b,
330  0x1e, 0xeb, 0x65, 0x97, 0x03, 0x86, 0x60, 0xde, 0xf3, 0x6c, 0x38, 0x75, 0xe0,
331  0x4c, 0x61, 0xbb, 0xbc, 0x62, 0x17, 0xa9, 0xcd, 0x79, 0x3f, 0x21, 0x4e, 0x96,
332  0xcb, 0x0e, 0xdc, 0x61, 0x94, 0x30, 0x18, 0x10, 0x6b, 0xd0, 0x1c, 0x10, 0x79,
333  0x02, 0x03, 0x01, 0x00, 0x01, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02,
334  0x1d, 0x05, 0x00, 0x03, 0x41, 0x00, 0x25, 0x90, 0x53, 0x34, 0xd9, 0x56, 0x41,
335  0x5e, 0xdb, 0x7e, 0x01, 0x36, 0xec, 0x27, 0x61, 0x5e, 0xb7, 0x4d, 0x90, 0x66,
336  0xa2, 0xe1, 0x9d, 0x58, 0x76, 0xd4, 0x9c, 0xba, 0x2c, 0x84, 0xc6, 0x83, 0x7a,
337  0x22, 0x0d, 0x03, 0x69, 0x32, 0x1a, 0x6d, 0xcb, 0x0c, 0x15, 0xb3, 0x6b, 0xc7,
338  0x0a, 0x8c, 0xb4, 0x5c, 0x34, 0x78, 0xe0, 0x3c, 0x9c, 0xe9, 0xf3, 0x30, 0x9f,
339  0xa8, 0x76, 0x57, 0x92, 0x36 };
340
341 static void testCertTrust(SAFE_PROVIDER_FUNCTIONS *funcs, GUID *actionID)
342 {
343     CRYPT_PROVIDER_DATA data = { 0 };
344     CRYPT_PROVIDER_SGNR sgnr = { sizeof(sgnr), { 0 } };
345     HRESULT ret;
346
347     data.padwTrustStepErrors =
348      funcs->pfnAlloc(TRUSTERROR_MAX_STEPS * sizeof(DWORD));
349     if (!data.padwTrustStepErrors)
350     {
351         skip("pfnAlloc failed\n");
352         return;
353     }
354     ret = funcs->pfnCertificateTrust(&data);
355     ok(ret == S_FALSE, "Expected S_FALSE, got %08x\n", ret);
356     ok(data.padwTrustStepErrors[TRUSTERROR_STEP_FINAL_CERTPROV] ==
357      TRUST_E_NOSIGNATURE, "Expected TRUST_E_NOSIGNATURE, got %08x\n",
358      data.padwTrustStepErrors[TRUSTERROR_STEP_FINAL_CERTPROV]);
359     ret = funcs->pfnAddSgnr2Chain(&data, FALSE, 0, &sgnr);
360     if (ret)
361     {
362         PCCERT_CONTEXT cert;
363
364         /* An empty signer "succeeds," even though there's no cert */
365         ret = funcs->pfnCertificateTrust(&data);
366         ok(ret == S_OK, "Expected S_OK, got %08x\n", ret);
367         cert = CertCreateCertificateContext(X509_ASN_ENCODING, selfSignedCert,
368          sizeof(selfSignedCert));
369         if (cert)
370         {
371             WINTRUST_DATA wintrust_data = { 0 };
372
373             ret = funcs->pfnAddCert2Chain(&data, 0, FALSE, 0, cert);
374             /* If pWintrustData isn't set, crashes attempting to access
375              * pWintrustData->fdwRevocationChecks
376              */
377             data.pWintrustData = &wintrust_data;
378             /* If psPfns isn't set, crashes attempting to access
379              * psPfns->pfnCertCheckPolicy
380              */
381             data.psPfns = (CRYPT_PROVIDER_FUNCTIONS *)funcs;
382             ret = funcs->pfnCertificateTrust(&data);
383             ok(ret == S_OK, "Expected S_OK, got %08x\n", ret);
384             ok(data.csSigners == 1, "Unexpected number of signers %d\n",
385              data.csSigners);
386             ok(data.pasSigners[0].pChainContext != NULL,
387              "Expected a certificate chain\n");
388             ok(data.pasSigners[0].csCertChain == 1,
389              "Unexpected number of chain elements %d\n",
390              data.pasSigners[0].csCertChain);
391             /* pasSigners and pasSigners[0].pasCertChain are guaranteed to be
392              * initialized, see tests for pfnAddSgnr2Chain and pfnAddCert2Chain
393              */
394             ok(!data.pasSigners[0].pasCertChain[0].fTrustedRoot,
395              "Didn't expect cert to be trusted\n");
396             ok(data.pasSigners[0].pasCertChain[0].fSelfSigned,
397              "Expected cert to be self-signed\n");
398             ok(data.pasSigners[0].pasCertChain[0].dwConfidence ==
399              (CERT_CONFIDENCE_SIG | CERT_CONFIDENCE_TIMENEST),
400              "Expected CERT_CONFIDENCE_SIG | CERT_CONFIDENCE_TIMENEST, got %08x\n",
401              data.pasSigners[0].pasCertChain[0].dwConfidence);
402             CertFreeCertificateContext(cert);
403         }
404     }
405 }
406
407 static void test_provider_funcs(void)
408 {
409     static GUID generic_verify_v2 = WINTRUST_ACTION_GENERIC_VERIFY_V2;
410     SAFE_PROVIDER_FUNCTIONS funcs = { sizeof(SAFE_PROVIDER_FUNCTIONS), 0 };
411     BOOL ret;
412
413     ret = WintrustLoadFunctionPointers(&generic_verify_v2,
414      (CRYPT_PROVIDER_FUNCTIONS *)&funcs);
415     if (!ret)
416         skip("WintrustLoadFunctionPointers failed\n");
417     else
418     {
419         test_utils(&funcs);
420         testInitialize(&funcs, &generic_verify_v2);
421         testObjTrust(&funcs, &generic_verify_v2);
422         testCertTrust(&funcs, &generic_verify_v2);
423     }
424 }
425
426 static void test_wintrust(void)
427 {
428     static GUID generic_action_v2 = WINTRUST_ACTION_GENERIC_VERIFY_V2;
429     WINTRUST_DATA wtd;
430     WINTRUST_FILE_INFO file;
431     LONG r;
432     HRESULT hr;
433     WCHAR notepadPathW[MAX_PATH];
434
435     memset(&wtd, 0, sizeof(wtd));
436     wtd.cbStruct = sizeof(wtd);
437     wtd.dwUIChoice = WTD_UI_NONE;
438     wtd.fdwRevocationChecks = WTD_REVOKE_WHOLECHAIN;
439     wtd.dwUnionChoice = WTD_CHOICE_FILE;
440     U(wtd).pFile = &file;
441     wtd.dwStateAction = WTD_STATEACTION_VERIFY;
442     memset(&file, 0, sizeof(file));
443     file.cbStruct = sizeof(file);
444     getNotepadPath(notepadPathW, MAX_PATH);
445     file.pcwszFilePath = notepadPathW;
446     r = WinVerifyTrust(INVALID_HANDLE_VALUE, &generic_action_v2, &wtd);
447     ok(r == TRUST_E_NOSIGNATURE, "expected TRUST_E_NOSIGNATURE, got %08x\n", r);
448     hr = WinVerifyTrustEx(INVALID_HANDLE_VALUE, &generic_action_v2, &wtd);
449     ok(hr == TRUST_E_NOSIGNATURE, "expected TRUST_E_NOSIGNATURE, got %08x\n",
450      hr);
451 }
452
453 START_TEST(softpub)
454 {
455     test_provider_funcs();
456     test_wintrust();
457 }