msvcr71: Add _vscprintf and _vscwprintf.
[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 ||
307          data.padwTrustStepErrors[TRUSTERROR_STEP_FINAL_OBJPROV] ==
308          TRUST_E_SUBJECT_FORM_UNKNOWN,
309          "Expected TRUST_E_NOSIGNATURE or TRUST_E_SUBJECT_FORM_UNKNOWN, got %08x\n",
310          data.padwTrustStepErrors[TRUSTERROR_STEP_FINAL_OBJPROV]);
311         if (data.padwTrustStepErrors[TRUSTERROR_STEP_FINAL_OBJPROV] ==
312          TRUST_E_NOSIGNATURE)
313         {
314             ok(!memcmp(&provDataSIP.gSubject, &unknown, sizeof(unknown)),
315              "Unexpected subject GUID\n");
316             ok(provDataSIP.pSip != NULL, "Expected a SIP\n");
317             ok(provDataSIP.psSipSubjectInfo != NULL,
318              "Expected a subject info\n");
319         }
320         funcs->pfnFree(data.padwTrustStepErrors);
321     }
322 }
323
324 static const BYTE selfSignedCert[] = {
325  0x30, 0x82, 0x01, 0x1f, 0x30, 0x81, 0xce, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02,
326  0x10, 0xeb, 0x0d, 0x57, 0x2a, 0x9c, 0x09, 0xba, 0xa4, 0x4a, 0xb7, 0x25, 0x49,
327  0xd9, 0x3e, 0xb5, 0x73, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1d,
328  0x05, 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03,
329  0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30,
330  0x1e, 0x17, 0x0d, 0x30, 0x36, 0x30, 0x36, 0x32, 0x39, 0x30, 0x35, 0x30, 0x30,
331  0x34, 0x36, 0x5a, 0x17, 0x0d, 0x30, 0x37, 0x30, 0x36, 0x32, 0x39, 0x31, 0x31,
332  0x30, 0x30, 0x34, 0x36, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03,
333  0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e,
334  0x67, 0x00, 0x30, 0x5c, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
335  0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x4b, 0x00, 0x30, 0x48, 0x02, 0x41,
336  0x00, 0xe2, 0x54, 0x3a, 0xa7, 0x83, 0xb1, 0x27, 0x14, 0x3e, 0x59, 0xbb, 0xb4,
337  0x53, 0xe6, 0x1f, 0xe7, 0x5d, 0xf1, 0x21, 0x68, 0xad, 0x85, 0x53, 0xdb, 0x6b,
338  0x1e, 0xeb, 0x65, 0x97, 0x03, 0x86, 0x60, 0xde, 0xf3, 0x6c, 0x38, 0x75, 0xe0,
339  0x4c, 0x61, 0xbb, 0xbc, 0x62, 0x17, 0xa9, 0xcd, 0x79, 0x3f, 0x21, 0x4e, 0x96,
340  0xcb, 0x0e, 0xdc, 0x61, 0x94, 0x30, 0x18, 0x10, 0x6b, 0xd0, 0x1c, 0x10, 0x79,
341  0x02, 0x03, 0x01, 0x00, 0x01, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02,
342  0x1d, 0x05, 0x00, 0x03, 0x41, 0x00, 0x25, 0x90, 0x53, 0x34, 0xd9, 0x56, 0x41,
343  0x5e, 0xdb, 0x7e, 0x01, 0x36, 0xec, 0x27, 0x61, 0x5e, 0xb7, 0x4d, 0x90, 0x66,
344  0xa2, 0xe1, 0x9d, 0x58, 0x76, 0xd4, 0x9c, 0xba, 0x2c, 0x84, 0xc6, 0x83, 0x7a,
345  0x22, 0x0d, 0x03, 0x69, 0x32, 0x1a, 0x6d, 0xcb, 0x0c, 0x15, 0xb3, 0x6b, 0xc7,
346  0x0a, 0x8c, 0xb4, 0x5c, 0x34, 0x78, 0xe0, 0x3c, 0x9c, 0xe9, 0xf3, 0x30, 0x9f,
347  0xa8, 0x76, 0x57, 0x92, 0x36 };
348
349 static void testCertTrust(SAFE_PROVIDER_FUNCTIONS *funcs, GUID *actionID)
350 {
351     CRYPT_PROVIDER_DATA data = { 0 };
352     CRYPT_PROVIDER_SGNR sgnr = { sizeof(sgnr), { 0 } };
353     HRESULT ret;
354
355     data.padwTrustStepErrors =
356      funcs->pfnAlloc(TRUSTERROR_MAX_STEPS * sizeof(DWORD));
357     if (!data.padwTrustStepErrors)
358     {
359         skip("pfnAlloc failed\n");
360         return;
361     }
362     ret = funcs->pfnCertificateTrust(&data);
363     ok(ret == S_FALSE, "Expected S_FALSE, got %08x\n", ret);
364     ok(data.padwTrustStepErrors[TRUSTERROR_STEP_FINAL_CERTPROV] ==
365      TRUST_E_NOSIGNATURE, "Expected TRUST_E_NOSIGNATURE, got %08x\n",
366      data.padwTrustStepErrors[TRUSTERROR_STEP_FINAL_CERTPROV]);
367     ret = funcs->pfnAddSgnr2Chain(&data, FALSE, 0, &sgnr);
368     if (ret)
369     {
370         PCCERT_CONTEXT cert;
371
372         /* An empty signer "succeeds," even though there's no cert */
373         ret = funcs->pfnCertificateTrust(&data);
374         ok(ret == S_OK, "Expected S_OK, got %08x\n", ret);
375         cert = CertCreateCertificateContext(X509_ASN_ENCODING, selfSignedCert,
376          sizeof(selfSignedCert));
377         if (cert)
378         {
379             WINTRUST_DATA wintrust_data = { 0 };
380
381             ret = funcs->pfnAddCert2Chain(&data, 0, FALSE, 0, cert);
382             /* If pWintrustData isn't set, crashes attempting to access
383              * pWintrustData->fdwRevocationChecks
384              */
385             data.pWintrustData = &wintrust_data;
386             /* If psPfns isn't set, crashes attempting to access
387              * psPfns->pfnCertCheckPolicy
388              */
389             data.psPfns = (CRYPT_PROVIDER_FUNCTIONS *)funcs;
390             ret = funcs->pfnCertificateTrust(&data);
391             ok(ret == S_OK, "Expected S_OK, got %08x\n", ret);
392             ok(data.csSigners == 1, "Unexpected number of signers %d\n",
393              data.csSigners);
394             ok(data.pasSigners[0].pChainContext != NULL,
395              "Expected a certificate chain\n");
396             ok(data.pasSigners[0].csCertChain == 1,
397              "Unexpected number of chain elements %d\n",
398              data.pasSigners[0].csCertChain);
399             /* pasSigners and pasSigners[0].pasCertChain are guaranteed to be
400              * initialized, see tests for pfnAddSgnr2Chain and pfnAddCert2Chain
401              */
402             ok(!data.pasSigners[0].pasCertChain[0].fTrustedRoot,
403              "Didn't expect cert to be trusted\n");
404             ok(data.pasSigners[0].pasCertChain[0].fSelfSigned,
405              "Expected cert to be self-signed\n");
406             ok(data.pasSigners[0].pasCertChain[0].dwConfidence ==
407              (CERT_CONFIDENCE_SIG | CERT_CONFIDENCE_TIMENEST),
408              "Expected CERT_CONFIDENCE_SIG | CERT_CONFIDENCE_TIMENEST, got %08x\n",
409              data.pasSigners[0].pasCertChain[0].dwConfidence);
410             CertFreeCertificateContext(cert);
411         }
412     }
413 }
414
415 static void test_provider_funcs(void)
416 {
417     static GUID generic_verify_v2 = WINTRUST_ACTION_GENERIC_VERIFY_V2;
418     SAFE_PROVIDER_FUNCTIONS funcs = { sizeof(SAFE_PROVIDER_FUNCTIONS), 0 };
419     BOOL ret;
420
421     ret = WintrustLoadFunctionPointers(&generic_verify_v2,
422      (CRYPT_PROVIDER_FUNCTIONS *)&funcs);
423     if (!ret)
424         skip("WintrustLoadFunctionPointers failed\n");
425     else
426     {
427         test_utils(&funcs);
428         testInitialize(&funcs, &generic_verify_v2);
429         testObjTrust(&funcs, &generic_verify_v2);
430         testCertTrust(&funcs, &generic_verify_v2);
431     }
432 }
433
434 static void test_wintrust(void)
435 {
436     static GUID generic_action_v2 = WINTRUST_ACTION_GENERIC_VERIFY_V2;
437     WINTRUST_DATA wtd;
438     WINTRUST_FILE_INFO file;
439     LONG r;
440     HRESULT hr;
441     WCHAR notepadPathW[MAX_PATH];
442
443     memset(&wtd, 0, sizeof(wtd));
444     wtd.cbStruct = sizeof(wtd);
445     wtd.dwUIChoice = WTD_UI_NONE;
446     wtd.fdwRevocationChecks = WTD_REVOKE_WHOLECHAIN;
447     wtd.dwUnionChoice = WTD_CHOICE_FILE;
448     U(wtd).pFile = &file;
449     wtd.dwStateAction = WTD_STATEACTION_VERIFY;
450     memset(&file, 0, sizeof(file));
451     file.cbStruct = sizeof(file);
452     getNotepadPath(notepadPathW, MAX_PATH);
453     file.pcwszFilePath = notepadPathW;
454     r = WinVerifyTrust(INVALID_HANDLE_VALUE, &generic_action_v2, &wtd);
455     ok(r == TRUST_E_NOSIGNATURE || r == CRYPT_E_FILE_ERROR,
456      "expected TRUST_E_NOSIGNATURE or CRYPT_E_FILE_ERROR, got %08x\n", r);
457     hr = WinVerifyTrustEx(INVALID_HANDLE_VALUE, &generic_action_v2, &wtd);
458     ok(hr == TRUST_E_NOSIGNATURE || r == CRYPT_E_FILE_ERROR,
459      "expected TRUST_E_NOSIGNATURE or CRYPT_E_FILE_ERROR, got %08x\n", hr);
460 }
461
462 static BOOL (WINAPI * pWTHelperGetKnownUsages)(DWORD action, PCCRYPT_OID_INFO **usages);
463
464 static void InitFunctionPtrs(void)
465 {
466     HMODULE hWintrust = GetModuleHandleA("wintrust.dll");
467
468 #define WINTRUST_GET_PROC(func) \
469     p ## func = (void*)GetProcAddress(hWintrust, #func); \
470     if(!p ## func) { \
471       trace("GetProcAddress(%s) failed\n", #func); \
472     }
473
474     WINTRUST_GET_PROC(WTHelperGetKnownUsages)
475
476 #undef WINTRUST_GET_PROC
477 }
478
479 static void test_get_known_usages(void)
480 {
481     BOOL ret;
482     PCCRYPT_OID_INFO *usages;
483
484     if (!pWTHelperGetKnownUsages)
485     {
486         skip("missing WTHelperGetKnownUsages\n");
487         return;
488     }
489     SetLastError(0xdeadbeef);
490     ret = pWTHelperGetKnownUsages(0, NULL);
491     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
492      "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
493     SetLastError(0xdeadbeef);
494     ret = pWTHelperGetKnownUsages(1, NULL);
495     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
496      "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
497     SetLastError(0xdeadbeef);
498     ret = pWTHelperGetKnownUsages(0, &usages);
499     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
500      "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
501     /* A value of 1 for the first parameter seems to imply the value is
502      * allocated
503      */
504     SetLastError(0xdeadbeef);
505     usages = NULL;
506     ret = pWTHelperGetKnownUsages(1, &usages);
507     ok(ret, "WTHelperGetKnownUsages failed: %d\n", GetLastError());
508     ok(usages != NULL, "expected a pointer\n");
509     if (ret && usages)
510     {
511         PCCRYPT_OID_INFO *ptr;
512
513         /* The returned usages are an array of PCCRYPT_OID_INFOs, terminated with a
514          * NULL pointer.
515          */
516         for (ptr = usages; *ptr; ptr++)
517         {
518             ok((*ptr)->cbSize == sizeof(CRYPT_OID_INFO) ||
519              (*ptr)->cbSize == (sizeof(CRYPT_OID_INFO) + 2 * sizeof(LPCWSTR)), /* Vista */
520              "unexpected size %d\n", (*ptr)->cbSize);
521             /* Each returned usage is in the CRYPT_ENHKEY_USAGE_OID_GROUP_ID group */
522             ok((*ptr)->dwGroupId == CRYPT_ENHKEY_USAGE_OID_GROUP_ID,
523              "expected group CRYPT_ENHKEY_USAGE_OID_GROUP_ID, got %d\n",
524              (*ptr)->dwGroupId);
525         }
526     }
527     /* A value of 2 for the second parameter seems to imply the value is freed
528      */
529     SetLastError(0xdeadbeef);
530     ret = pWTHelperGetKnownUsages(2, &usages);
531     ok(ret, "WTHelperGetKnownUsages failed: %d\n", GetLastError());
532     ok(usages == NULL, "expected pointer to be cleared\n");
533     SetLastError(0xdeadbeef);
534     usages = NULL;
535     ret = pWTHelperGetKnownUsages(2, &usages);
536     ok(ret, "WTHelperGetKnownUsages failed: %d\n", GetLastError());
537     SetLastError(0xdeadbeef);
538     ret = pWTHelperGetKnownUsages(2, NULL);
539     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
540      "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
541 }
542
543 START_TEST(softpub)
544 {
545     InitFunctionPtrs();
546     test_provider_funcs();
547     test_wintrust();
548     test_get_known_usages();
549 }