urlmon: Don't create stgmed_obj for binding to object.
[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
31 #include "wine/test.h"
32
33 /* Just in case we're being built with borked headers, redefine function
34  * pointers to have the correct calling convention.
35  */
36 typedef void   *(WINAPI *SAFE_MEM_ALLOC)(DWORD);
37 typedef void    (WINAPI *SAFE_MEM_FREE)(void *);
38 typedef BOOL    (WINAPI *SAFE_ADD_STORE)(CRYPT_PROVIDER_DATA *,
39  HCERTSTORE);
40 typedef BOOL    (WINAPI *SAFE_ADD_SGNR)(CRYPT_PROVIDER_DATA *,
41  BOOL, DWORD, struct _CRYPT_PROVIDER_SGNR *);
42 typedef BOOL    (WINAPI *SAFE_ADD_CERT)(CRYPT_PROVIDER_DATA *,
43  DWORD, BOOL, DWORD, PCCERT_CONTEXT);
44 typedef BOOL    (WINAPI *SAFE_ADD_PRIVDATA)(CRYPT_PROVIDER_DATA *,
45  CRYPT_PROVIDER_PRIVDATA *);
46 typedef HRESULT (WINAPI *SAFE_PROVIDER_INIT_CALL)(CRYPT_PROVIDER_DATA *);
47 typedef HRESULT (WINAPI *SAFE_PROVIDER_OBJTRUST_CALL)(CRYPT_PROVIDER_DATA *);
48 typedef HRESULT (WINAPI *SAFE_PROVIDER_SIGTRUST_CALL)(CRYPT_PROVIDER_DATA *);
49 typedef HRESULT (WINAPI *SAFE_PROVIDER_CERTTRUST_CALL)(CRYPT_PROVIDER_DATA *);
50 typedef HRESULT (WINAPI *SAFE_PROVIDER_FINALPOLICY_CALL)(CRYPT_PROVIDER_DATA *);
51 typedef HRESULT (WINAPI *SAFE_PROVIDER_TESTFINALPOLICY_CALL)(
52  CRYPT_PROVIDER_DATA *);
53 typedef HRESULT (WINAPI *SAFE_PROVIDER_CLEANUP_CALL)(CRYPT_PROVIDER_DATA *);
54 typedef BOOL    (WINAPI *SAFE_PROVIDER_CERTCHKPOLICY_CALL)(
55  CRYPT_PROVIDER_DATA *, DWORD, BOOL, DWORD);
56
57 typedef struct _SAFE_PROVIDER_FUNCTIONS
58 {
59     DWORD                              cbStruct;
60     SAFE_MEM_ALLOC                     pfnAlloc;
61     SAFE_MEM_FREE                      pfnFree;
62     SAFE_ADD_STORE                     pfnAddStore2Chain;
63     SAFE_ADD_SGNR                      pfnAddSgnr2Chain;
64     SAFE_ADD_CERT                      pfnAddCert2Chain;
65     SAFE_ADD_PRIVDATA                  pfnAddPrivData2Chain;
66     SAFE_PROVIDER_INIT_CALL            pfnInitialize;
67     SAFE_PROVIDER_OBJTRUST_CALL        pfnObjectTrust;
68     SAFE_PROVIDER_SIGTRUST_CALL        pfnSignatureTrust;
69     SAFE_PROVIDER_CERTTRUST_CALL       pfnCertificateTrust;
70     SAFE_PROVIDER_FINALPOLICY_CALL     pfnFinalPolicy;
71     SAFE_PROVIDER_CERTCHKPOLICY_CALL   pfnCertCheckPolicy;
72     SAFE_PROVIDER_TESTFINALPOLICY_CALL pfnTestFinalPolicy;
73     struct _CRYPT_PROVUI_FUNCS        *psUIpfns;
74     SAFE_PROVIDER_CLEANUP_CALL         pfnCleanupPolicy;
75 } SAFE_PROVIDER_FUNCTIONS;
76
77 static const BYTE v1CertWithPubKey[] = {
78 0x30,0x81,0x95,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,
79 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
80 0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,
81 0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
82 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,
83 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
84 0x67,0x00,0x30,0x22,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
85 0x01,0x01,0x05,0x00,0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
86 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0xa3,0x16,0x30,0x14,0x30,0x12,0x06,
87 0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,
88 0x01,0x01 };
89
90 static void test_utils(SAFE_PROVIDER_FUNCTIONS *funcs)
91 {
92     CRYPT_PROVIDER_DATA data = { 0 };
93     HCERTSTORE store;
94     CRYPT_PROVIDER_SGNR sgnr = { 0 };
95     BOOL ret;
96
97     /* Crash
98     ret = funcs->pfnAddStore2Chain(NULL, NULL);
99     ret = funcs->pfnAddStore2Chain(&data, NULL);
100      */
101     store = CertOpenStore(CERT_STORE_PROV_MEMORY, X509_ASN_ENCODING, 0,
102      CERT_STORE_CREATE_NEW_FLAG, NULL);
103     if (store)
104     {
105         ret = funcs->pfnAddStore2Chain(&data, store);
106         ok(ret, "pfnAddStore2Chain failed: %08x\n", GetLastError());
107         ok(data.chStores == 1, "Expected 1 store, got %d\n", data.chStores);
108         ok(data.pahStores != NULL, "Expected pahStores to be allocated\n");
109         if (data.pahStores)
110         {
111             ok(data.pahStores[0] == store, "Unexpected store\n");
112             CertCloseStore(data.pahStores[0], 0);
113             funcs->pfnFree(data.pahStores);
114             data.pahStores = NULL;
115             data.chStores = 0;
116             CertCloseStore(store, 0);
117             store = NULL;
118         }
119     }
120     else
121         skip("CertOpenStore failed: %08x\n", GetLastError());
122
123     /* Crash
124     ret = funcs->pfnAddSgnr2Chain(NULL, FALSE, 0, NULL);
125     ret = funcs->pfnAddSgnr2Chain(&data, FALSE, 0, NULL);
126      */
127     ret = funcs->pfnAddSgnr2Chain(&data, FALSE, 0, &sgnr);
128     ok(ret, "pfnAddSgnr2Chain failed: %08x\n", GetLastError());
129     ok(data.csSigners == 1, "Expected 1 signer, got %d\n", data.csSigners);
130     ok(data.pasSigners != NULL, "Expected pasSigners to be allocated\n");
131     if (data.pasSigners)
132     {
133         PCCERT_CONTEXT cert;
134
135         ok(!memcmp(&data.pasSigners[0], &sgnr, sizeof(sgnr)),
136          "Unexpected data in signer\n");
137         /* Adds into the location specified by the index */
138         sgnr.cbStruct = sizeof(CRYPT_PROVIDER_SGNR);
139         sgnr.sftVerifyAsOf.dwLowDateTime = 0xdeadbeef;
140         ret = funcs->pfnAddSgnr2Chain(&data, FALSE, 1, &sgnr);
141         ok(ret, "pfnAddSgnr2Chain failed: %08x\n", GetLastError());
142         ok(data.csSigners == 2, "Expected 2 signers, got %d\n", data.csSigners);
143         ok(!memcmp(&data.pasSigners[1], &sgnr, sizeof(sgnr)),
144          "Unexpected data in signer\n");
145         /* This also adds, but the data aren't copied */
146         sgnr.cbStruct = sizeof(DWORD);
147         ret = funcs->pfnAddSgnr2Chain(&data, FALSE, 0, &sgnr);
148         ok(ret, "pfnAddSgnr2Chain failed: %08x\n", GetLastError());
149         ok(data.csSigners == 3, "Expected 3 signers, got %d\n", data.csSigners);
150         ok(data.pasSigners[0].cbStruct == 0, "Unexpected data size %d\n",
151          data.pasSigners[0].cbStruct);
152         ok(data.pasSigners[0].sftVerifyAsOf.dwLowDateTime == 0,
153          "Unexpected verify time %d\n",
154          data.pasSigners[0].sftVerifyAsOf.dwLowDateTime);
155         /* But too large a thing isn't added */
156         sgnr.cbStruct = sizeof(sgnr) + sizeof(DWORD);
157         SetLastError(0xdeadbeef);
158         ret = funcs->pfnAddSgnr2Chain(&data, FALSE, 0, &sgnr);
159         ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
160          "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
161
162         /* Crash
163         ret = funcs->pfnAddCert2Chain(NULL, 0, FALSE, 0, NULL);
164         ret = funcs->pfnAddCert2Chain(&data, 0, FALSE, 0, NULL);
165          */
166         cert = CertCreateCertificateContext(X509_ASN_ENCODING, v1CertWithPubKey,
167          sizeof(v1CertWithPubKey));
168         if (cert)
169         {
170             /* Notes on behavior that are hard to test:
171              * 1. If pasSigners is invalid, pfnAddCert2Chain crashes
172              * 2. An invalid signer index isn't checked.
173              */
174             ret = funcs->pfnAddCert2Chain(&data, 0, FALSE, 0, cert);
175             ok(ret, "pfnAddCert2Chain failed: %08x\n", GetLastError());
176             ok(data.pasSigners[0].csCertChain == 1, "Expected 1 cert, got %d\n",
177              data.pasSigners[0].csCertChain);
178             ok(data.pasSigners[0].pasCertChain != NULL,
179              "Expected pasCertChain to be allocated\n");
180             if (data.pasSigners[0].pasCertChain)
181                 ok(data.pasSigners[0].pasCertChain[0].pCert == cert,
182                  "Unexpected cert\n");
183             CertFreeCertificateContext(cert);
184         }
185         else
186             skip("CertCreateCertificateContext failed: %08x\n", GetLastError());
187     }
188 }
189
190 static void testInitialize(SAFE_PROVIDER_FUNCTIONS *funcs, GUID *actionID)
191 {
192     HRESULT ret;
193     CRYPT_PROVIDER_DATA data = { 0 };
194     WINTRUST_DATA wintrust_data = { 0 };
195
196     if (!funcs->pfnInitialize)
197     {
198         skip("missing pfnInitialize\n");
199         return;
200     }
201
202     /* Crashes
203     ret = funcs->pfnInitialize(NULL);
204      */
205     memset(&data, 0, sizeof(data));
206     ret = funcs->pfnInitialize(&data);
207     ok(ret == S_FALSE, "Expected S_FALSE, got %08x\n", ret);
208     data.padwTrustStepErrors =
209      funcs->pfnAlloc(TRUSTERROR_MAX_STEPS * sizeof(DWORD));
210     /* Without wintrust data set, crashes when padwTrustStepErrors is set */
211     data.pWintrustData = &wintrust_data;
212     if (data.padwTrustStepErrors)
213     {
214         /* Apparently, cdwTrustStepErrors does not need to be set. */
215         ret = funcs->pfnInitialize(&data);
216         ok(ret == S_OK, "Expected S_OK, got %08x\n", ret);
217         data.cdwTrustStepErrors = 1;
218         ret = funcs->pfnInitialize(&data);
219         ok(ret == S_OK, "Expected S_OK, got %08x\n", ret);
220         memset(data.padwTrustStepErrors, 0xba,
221          TRUSTERROR_MAX_STEPS * sizeof(DWORD));
222         ret = funcs->pfnInitialize(&data);
223         ok(ret == S_FALSE, "Expected S_FALSE, got %08x\n", ret);
224         data.padwTrustStepErrors[TRUSTERROR_STEP_FINAL_WVTINIT] = 0;
225         ret = funcs->pfnInitialize(&data);
226         ok(ret == S_OK, "Expected S_OK, got %08x\n", ret);
227         funcs->pfnFree(data.padwTrustStepErrors);
228     }
229 }
230
231 static void testObjTrust(SAFE_PROVIDER_FUNCTIONS *funcs, GUID *actionID)
232 {
233     HRESULT ret;
234     CRYPT_PROVIDER_DATA data = { 0 };
235     WINTRUST_DATA wintrust_data = { 0 };
236     WINTRUST_CERT_INFO certInfo = { sizeof(WINTRUST_CERT_INFO), 0 };
237     WINTRUST_FILE_INFO fileInfo = { sizeof(WINTRUST_FILE_INFO), 0 };
238
239     if (!funcs->pfnObjectTrust)
240     {
241         skip("missing pfnObjectTrust\n");
242         return;
243     }
244
245     /* Crashes
246     ret = funcs->pfnObjectTrust(NULL);
247      */
248     data.pWintrustData = &wintrust_data;
249     data.padwTrustStepErrors =
250      funcs->pfnAlloc(TRUSTERROR_MAX_STEPS * sizeof(DWORD));
251     if (data.padwTrustStepErrors)
252     {
253         static const WCHAR notepad[] = { '\\','n','o','t','e','p','a','d','.',
254          'e','x','e',0 };
255         WCHAR notepadPath[MAX_PATH];
256         PROVDATA_SIP provDataSIP = { 0 };
257         static const GUID unknown = { 0xC689AAB8, 0x8E78, 0x11D0, { 0x8C,0x47,
258          0x00,0xC0,0x4F,0xC2,0x95,0xEE } };
259
260         ret = funcs->pfnObjectTrust(&data);
261         ok(ret == S_FALSE, "Expected S_FALSE, got %08x\n", ret);
262         ok(data.padwTrustStepErrors[TRUSTERROR_STEP_FINAL_OBJPROV] ==
263          ERROR_INVALID_PARAMETER,
264          "Expected ERROR_INVALID_PARAMETER, got %08x\n",
265          data.padwTrustStepErrors[TRUSTERROR_STEP_FINAL_OBJPROV]);
266         U(wintrust_data).pCert = &certInfo;
267         wintrust_data.dwUnionChoice = WTD_CHOICE_CERT;
268         ret = funcs->pfnObjectTrust(&data);
269         ok(ret == S_OK, "Expected S_OK, got %08x\n", ret);
270         certInfo.psCertContext = (PCERT_CONTEXT)CertCreateCertificateContext(
271          X509_ASN_ENCODING, v1CertWithPubKey, sizeof(v1CertWithPubKey));
272         ret = funcs->pfnObjectTrust(&data);
273         ok(ret == S_OK, "Expected S_OK, got %08x\n", ret);
274         CertFreeCertificateContext(certInfo.psCertContext);
275         certInfo.psCertContext = NULL;
276         wintrust_data.dwUnionChoice = WTD_CHOICE_FILE;
277         U(wintrust_data).pFile = NULL;
278         ret = funcs->pfnObjectTrust(&data);
279         ok(ret == S_FALSE, "Expected S_FALSE, got %08x\n", ret);
280         ok(data.padwTrustStepErrors[TRUSTERROR_STEP_FINAL_OBJPROV] ==
281          ERROR_INVALID_PARAMETER,
282          "Expected ERROR_INVALID_PARAMETER, got %08x\n",
283          data.padwTrustStepErrors[TRUSTERROR_STEP_FINAL_OBJPROV]);
284         U(wintrust_data).pFile = &fileInfo;
285         /* Crashes
286         ret = funcs->pfnObjectTrust(&data);
287          */
288         GetWindowsDirectoryW(notepadPath, MAX_PATH);
289         lstrcatW(notepadPath, notepad);
290         fileInfo.pcwszFilePath = notepadPath;
291         /* pfnObjectTrust now crashes unless both pPDSip and psPfns are set */
292         U(data).pPDSip = &provDataSIP;
293         data.psPfns = (CRYPT_PROVIDER_FUNCTIONS *)funcs;
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          TRUST_E_NOSIGNATURE, "Expected TRUST_E_NOSIGNATURE, got %08x\n",
298          data.padwTrustStepErrors[TRUSTERROR_STEP_FINAL_OBJPROV]);
299         ok(!memcmp(&provDataSIP.gSubject, &unknown, sizeof(unknown)),
300          "Unexpected subject GUID\n");
301         ok(provDataSIP.pSip != NULL, "Expected a SIP\n");
302         ok(provDataSIP.psSipSubjectInfo != NULL, "Expected a subject info\n");
303         funcs->pfnFree(data.padwTrustStepErrors);
304     }
305 }
306
307 static const BYTE selfSignedCert[] = {
308  0x30, 0x82, 0x01, 0x1f, 0x30, 0x81, 0xce, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02,
309  0x10, 0xeb, 0x0d, 0x57, 0x2a, 0x9c, 0x09, 0xba, 0xa4, 0x4a, 0xb7, 0x25, 0x49,
310  0xd9, 0x3e, 0xb5, 0x73, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1d,
311  0x05, 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03,
312  0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30,
313  0x1e, 0x17, 0x0d, 0x30, 0x36, 0x30, 0x36, 0x32, 0x39, 0x30, 0x35, 0x30, 0x30,
314  0x34, 0x36, 0x5a, 0x17, 0x0d, 0x30, 0x37, 0x30, 0x36, 0x32, 0x39, 0x31, 0x31,
315  0x30, 0x30, 0x34, 0x36, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03,
316  0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e,
317  0x67, 0x00, 0x30, 0x5c, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
318  0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x4b, 0x00, 0x30, 0x48, 0x02, 0x41,
319  0x00, 0xe2, 0x54, 0x3a, 0xa7, 0x83, 0xb1, 0x27, 0x14, 0x3e, 0x59, 0xbb, 0xb4,
320  0x53, 0xe6, 0x1f, 0xe7, 0x5d, 0xf1, 0x21, 0x68, 0xad, 0x85, 0x53, 0xdb, 0x6b,
321  0x1e, 0xeb, 0x65, 0x97, 0x03, 0x86, 0x60, 0xde, 0xf3, 0x6c, 0x38, 0x75, 0xe0,
322  0x4c, 0x61, 0xbb, 0xbc, 0x62, 0x17, 0xa9, 0xcd, 0x79, 0x3f, 0x21, 0x4e, 0x96,
323  0xcb, 0x0e, 0xdc, 0x61, 0x94, 0x30, 0x18, 0x10, 0x6b, 0xd0, 0x1c, 0x10, 0x79,
324  0x02, 0x03, 0x01, 0x00, 0x01, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02,
325  0x1d, 0x05, 0x00, 0x03, 0x41, 0x00, 0x25, 0x90, 0x53, 0x34, 0xd9, 0x56, 0x41,
326  0x5e, 0xdb, 0x7e, 0x01, 0x36, 0xec, 0x27, 0x61, 0x5e, 0xb7, 0x4d, 0x90, 0x66,
327  0xa2, 0xe1, 0x9d, 0x58, 0x76, 0xd4, 0x9c, 0xba, 0x2c, 0x84, 0xc6, 0x83, 0x7a,
328  0x22, 0x0d, 0x03, 0x69, 0x32, 0x1a, 0x6d, 0xcb, 0x0c, 0x15, 0xb3, 0x6b, 0xc7,
329  0x0a, 0x8c, 0xb4, 0x5c, 0x34, 0x78, 0xe0, 0x3c, 0x9c, 0xe9, 0xf3, 0x30, 0x9f,
330  0xa8, 0x76, 0x57, 0x92, 0x36 };
331
332 static void testCertTrust(SAFE_PROVIDER_FUNCTIONS *funcs, GUID *actionID)
333 {
334     CRYPT_PROVIDER_DATA data = { 0 };
335     CRYPT_PROVIDER_SGNR sgnr = { sizeof(sgnr), { 0 } };
336     HRESULT ret;
337
338     data.padwTrustStepErrors =
339      funcs->pfnAlloc(TRUSTERROR_MAX_STEPS * sizeof(DWORD));
340     if (!data.padwTrustStepErrors)
341     {
342         skip("pfnAlloc failed\n");
343         return;
344     }
345     ret = funcs->pfnCertificateTrust(&data);
346     ok(ret == S_FALSE, "Expected S_FALSE, got %08x\n", ret);
347     ok(data.padwTrustStepErrors[TRUSTERROR_STEP_FINAL_CERTPROV] ==
348      TRUST_E_NOSIGNATURE, "Expected TRUST_E_NOSIGNATURE, got %08x\n",
349      data.padwTrustStepErrors[TRUSTERROR_STEP_FINAL_CERTPROV]);
350     ret = funcs->pfnAddSgnr2Chain(&data, FALSE, 0, &sgnr);
351     if (ret)
352     {
353         PCCERT_CONTEXT cert;
354
355         /* An empty signer "succeeds," even though there's no cert */
356         ret = funcs->pfnCertificateTrust(&data);
357         ok(ret == S_OK, "Expected S_OK, got %08x\n", ret);
358         cert = CertCreateCertificateContext(X509_ASN_ENCODING, selfSignedCert,
359          sizeof(selfSignedCert));
360         if (cert)
361         {
362             WINTRUST_DATA wintrust_data = { 0 };
363
364             ret = funcs->pfnAddCert2Chain(&data, 0, FALSE, 0, cert);
365             /* If pWintrustData isn't set, crashes attempting to access
366              * pWintrustData->fdwRevocationChecks
367              */
368             data.pWintrustData = &wintrust_data;
369             /* If psPfns isn't set, crashes attempting to access
370              * psPfns->pfnCertCheckPolicy
371              */
372             data.psPfns = (CRYPT_PROVIDER_FUNCTIONS *)funcs;
373             ret = funcs->pfnCertificateTrust(&data);
374             ok(ret == S_OK, "Expected S_OK, got %08x\n", ret);
375             ok(data.csSigners == 1, "Unexpected number of signers %d\n",
376              data.csSigners);
377             ok(data.pasSigners[0].pChainContext != NULL,
378              "Expected a certificate chain\n");
379             ok(data.pasSigners[0].csCertChain == 1,
380              "Unexpected number of chain elements %d\n",
381              data.pasSigners[0].csCertChain);
382             /* pasSigners and pasSigners[0].pasCertChain are guaranteed to be
383              * initialized, see tests for pfnAddSgnr2Chain and pfnAddCert2Chain
384              */
385             ok(!data.pasSigners[0].pasCertChain[0].fTrustedRoot,
386              "Didn't expect cert to be trusted\n");
387             ok(data.pasSigners[0].pasCertChain[0].fSelfSigned,
388              "Expected cert to be self-signed\n");
389             ok(data.pasSigners[0].pasCertChain[0].dwConfidence ==
390              (CERT_CONFIDENCE_SIG | CERT_CONFIDENCE_TIMENEST),
391              "Expected CERT_CONFIDENCE_SIG | CERT_CONFIDENCE_TIMENEST, got %08x\n",
392              data.pasSigners[0].pasCertChain[0].dwConfidence);
393             CertFreeCertificateContext(cert);
394         }
395     }
396 }
397
398 START_TEST(softpub)
399 {
400     static GUID generic_verify_v2 = WINTRUST_ACTION_GENERIC_VERIFY_V2;
401     SAFE_PROVIDER_FUNCTIONS funcs = { sizeof(SAFE_PROVIDER_FUNCTIONS), 0 };
402     BOOL ret;
403
404     ret = WintrustLoadFunctionPointers(&generic_verify_v2,
405      (CRYPT_PROVIDER_FUNCTIONS *)&funcs);
406     if (!ret)
407         skip("WintrustLoadFunctionPointers failed\n");
408     else
409     {
410         test_utils(&funcs);
411         testInitialize(&funcs, &generic_verify_v2);
412         testObjTrust(&funcs, &generic_verify_v2);
413         testCertTrust(&funcs, &generic_verify_v2);
414     }
415 }