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