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