comctl32: We can now store binary files in the repository.
[wine] / dlls / wintrust / softpub.c
1 /*
2  * Copyright 2007 Juan Lang
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17  */
18 #include <stdarg.h>
19
20 #define NONAMELESSUNION
21
22 #include "windef.h"
23 #include "winbase.h"
24 #include "wintrust.h"
25 #include "mssip.h"
26 #include "wine/debug.h"
27
28 WINE_DEFAULT_DEBUG_CHANNEL(wintrust);
29
30 HRESULT WINAPI SoftpubInitialize(CRYPT_PROVIDER_DATA *data)
31 {
32     HRESULT ret = S_FALSE;
33
34     TRACE("(%p)\n", data);
35
36     if (data->padwTrustStepErrors &&
37      !data->padwTrustStepErrors[TRUSTERROR_STEP_FINAL_WVTINIT])
38         ret = S_OK;
39     TRACE("returning %08x\n", ret);
40     return ret;
41 }
42
43 /* Assumes data->pWintrustData->u.pFile exists.  Makes sure a file handle is
44  * open for the file.
45  */
46 static BOOL SOFTPUB_OpenFile(CRYPT_PROVIDER_DATA *data)
47 {
48     BOOL ret = TRUE;
49
50     /* PSDK implies that all values should be initialized to NULL, so callers
51      * typically have hFile as NULL rather than INVALID_HANDLE_VALUE.  Check
52      * for both.
53      */
54     if (!data->pWintrustData->u.pFile->hFile ||
55      data->pWintrustData->u.pFile->hFile == INVALID_HANDLE_VALUE)
56     {
57         data->pWintrustData->u.pFile->hFile =
58             CreateFileW(data->pWintrustData->u.pFile->pcwszFilePath, GENERIC_READ,
59           FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
60         if (data->pWintrustData->u.pFile->hFile != INVALID_HANDLE_VALUE)
61             data->fOpenedFile = TRUE;
62         else
63             ret = FALSE;
64     }
65     TRACE("returning %d\n", ret);
66     return ret;
67 }
68
69 /* Assumes data->pWintrustData->u.pFile exists.  Sets data->pPDSip->gSubject to
70  * the file's subject GUID.
71  */
72 static BOOL SOFTPUB_GetFileSubject(CRYPT_PROVIDER_DATA *data)
73 {
74     BOOL ret;
75
76     if (!data->pWintrustData->u.pFile->pgKnownSubject)
77     {
78         ret = CryptSIPRetrieveSubjectGuid(
79          data->pWintrustData->u.pFile->pcwszFilePath,
80          data->pWintrustData->u.pFile->hFile,
81          &data->u.pPDSip->gSubject);
82     }
83     else
84     {
85         memcpy(&data->u.pPDSip->gSubject,
86          data->pWintrustData->u.pFile->pgKnownSubject, sizeof(GUID));
87         ret = TRUE;
88     }
89     TRACE("returning %d\n", ret);
90     return ret;
91 }
92
93 /* Assumes data->u.pPDSip exists, and its gSubject member set.
94  * Allocates data->u.pPDSip->pSip and loads it, if possible.
95  */
96 static BOOL SOFTPUB_GetSIP(CRYPT_PROVIDER_DATA *data)
97 {
98     BOOL ret;
99
100     data->u.pPDSip->pSip = data->psPfns->pfnAlloc(sizeof(SIP_DISPATCH_INFO));
101     if (data->u.pPDSip->pSip)
102         ret = CryptSIPLoad(&data->u.pPDSip->gSubject, 0, data->u.pPDSip->pSip);
103     else
104     {
105         SetLastError(ERROR_OUTOFMEMORY);
106         ret = FALSE;
107     }
108     TRACE("returning %d\n", ret);
109     return ret;
110 }
111
112 /* Assumes data->u.pPDSip has been loaded, and data->u.pPDSip->pSip allocated.
113  * Calls data->u.pPDSip->pSip->pfGet to construct data->hMsg.
114  */
115 static BOOL SOFTPUB_GetMessageFromFile(CRYPT_PROVIDER_DATA *data)
116 {
117     BOOL ret;
118     LPBYTE buf = NULL;
119     DWORD size = 0;
120
121     data->u.pPDSip->psSipSubjectInfo =
122      data->psPfns->pfnAlloc(sizeof(SIP_SUBJECTINFO));
123     if (!data->u.pPDSip->psSipSubjectInfo)
124     {
125         SetLastError(ERROR_OUTOFMEMORY);
126         return FALSE;
127     }
128
129     data->u.pPDSip->psSipSubjectInfo->cbSize = sizeof(SIP_SUBJECTINFO);
130     data->u.pPDSip->psSipSubjectInfo->pgSubjectType = &data->u.pPDSip->gSubject;
131     data->u.pPDSip->psSipSubjectInfo->hFile = data->pWintrustData->u.pFile->hFile;
132     data->u.pPDSip->psSipSubjectInfo->pwsFileName =
133      data->pWintrustData->u.pFile->pcwszFilePath;
134     data->u.pPDSip->psSipSubjectInfo->hProv = data->hProv;
135     ret = data->u.pPDSip->pSip->pfGet(data->u.pPDSip->psSipSubjectInfo,
136      &data->dwEncoding, 0, &size, 0);
137     if (!ret)
138     {
139         SetLastError(TRUST_E_NOSIGNATURE);
140         return FALSE;
141     }
142
143     buf = data->psPfns->pfnAlloc(size);
144     if (!buf)
145     {
146         SetLastError(ERROR_OUTOFMEMORY);
147         return FALSE;
148     }
149
150     ret = data->u.pPDSip->pSip->pfGet(data->u.pPDSip->psSipSubjectInfo,
151      &data->dwEncoding, 0, &size, buf);
152     if (ret)
153     {
154         data->hMsg = CryptMsgOpenToDecode(data->dwEncoding, 0, 0, data->hProv,
155          NULL, NULL);
156         if (data->hMsg)
157             ret = CryptMsgUpdate(data->hMsg, buf, size, TRUE);
158     }
159
160     data->psPfns->pfnFree(buf);
161     TRACE("returning %d\n", ret);
162     return ret;
163 }
164
165 static BOOL SOFTPUB_CreateStoreFromMessage(CRYPT_PROVIDER_DATA *data)
166 {
167     BOOL ret = FALSE;
168     HCERTSTORE store;
169
170     store = CertOpenStore(CERT_STORE_PROV_MSG, data->dwEncoding,
171      data->hProv, CERT_STORE_NO_CRYPT_RELEASE_FLAG, data->hMsg);
172     if (store)
173     {
174         ret = data->psPfns->pfnAddStore2Chain(data, store);
175         CertCloseStore(store, 0);
176     }
177     TRACE("returning %d\n", ret);
178     return ret;
179 }
180
181 static DWORD SOFTPUB_DecodeInnerContent(CRYPT_PROVIDER_DATA *data)
182 {
183     BOOL ret;
184     DWORD size;
185     LPBYTE buf = NULL;
186
187     ret = CryptMsgGetParam(data->hMsg, CMSG_INNER_CONTENT_TYPE_PARAM, 0, NULL,
188      &size);
189     if (!ret)
190         goto error;
191     buf = data->psPfns->pfnAlloc(size);
192     if (!buf)
193     {
194         SetLastError(ERROR_OUTOFMEMORY);
195         ret = FALSE;
196         goto error;
197     }
198     ret = CryptMsgGetParam(data->hMsg, CMSG_INNER_CONTENT_TYPE_PARAM, 0, buf,
199      &size);
200     if (!ret)
201         goto error;
202     if (!strcmp((LPCSTR)buf, SPC_INDIRECT_DATA_OBJID))
203     {
204         data->psPfns->pfnFree(buf);
205         buf = NULL;
206         ret = CryptMsgGetParam(data->hMsg, CMSG_CONTENT_PARAM, 0, NULL, &size);
207         if (!ret)
208             goto error;
209         buf = data->psPfns->pfnAlloc(size);
210         if (!buf)
211         {
212             SetLastError(ERROR_OUTOFMEMORY);
213             ret = FALSE;
214             goto error;
215         }
216         ret = CryptMsgGetParam(data->hMsg, CMSG_CONTENT_PARAM, 0, buf, &size);
217         if (!ret)
218             goto error;
219         ret = CryptDecodeObject(data->dwEncoding,
220          SPC_INDIRECT_DATA_CONTENT_STRUCT, buf, size, 0, NULL, &size);
221         if (!ret)
222             goto error;
223         data->u.pPDSip->psIndirectData = data->psPfns->pfnAlloc(size);
224         if (!data->u.pPDSip->psIndirectData)
225         {
226             SetLastError(ERROR_OUTOFMEMORY);
227             ret = FALSE;
228             goto error;
229         }
230         ret = CryptDecodeObject(data->dwEncoding,
231          SPC_INDIRECT_DATA_CONTENT_STRUCT, buf, size, 0,
232          data->u.pPDSip->psIndirectData, &size);
233     }
234     else
235     {
236         FIXME("unimplemented for OID %s\n", (LPCSTR)buf);
237         SetLastError(TRUST_E_SUBJECT_FORM_UNKNOWN);
238         ret = FALSE;
239     }
240
241 error:
242     TRACE("returning %d\n", ret);
243     return ret;
244 }
245
246 HRESULT WINAPI SoftpubLoadMessage(CRYPT_PROVIDER_DATA *data)
247 {
248     BOOL ret;
249
250     TRACE("(%p)\n", data);
251
252     if (!data->padwTrustStepErrors)
253         return S_FALSE;
254
255     switch (data->pWintrustData->dwUnionChoice)
256     {
257     case WTD_CHOICE_CERT:
258         /* Do nothing!?  See the tests */
259         ret = TRUE;
260         break;
261     case WTD_CHOICE_FILE:
262         if (!data->pWintrustData->u.pFile)
263         {
264             SetLastError(ERROR_INVALID_PARAMETER);
265             ret = FALSE;
266             goto error;
267         }
268         ret = SOFTPUB_OpenFile(data);
269         if (!ret)
270             goto error;
271         ret = SOFTPUB_GetFileSubject(data);
272         if (!ret)
273             goto error;
274         ret = SOFTPUB_GetSIP(data);
275         if (!ret)
276             goto error;
277         ret = SOFTPUB_GetMessageFromFile(data);
278         if (!ret)
279             goto error;
280         ret = SOFTPUB_CreateStoreFromMessage(data);
281         if (!ret)
282             goto error;
283         ret = SOFTPUB_DecodeInnerContent(data);
284         break;
285     default:
286         FIXME("unimplemented for %d\n", data->pWintrustData->dwUnionChoice);
287         SetLastError(ERROR_INVALID_PARAMETER);
288         ret = FALSE;
289     }
290
291 error:
292     if (!ret)
293         data->padwTrustStepErrors[TRUSTERROR_STEP_FINAL_OBJPROV] =
294          GetLastError();
295     return ret ? S_OK : S_FALSE;
296 }
297
298 static CMSG_SIGNER_INFO *WINTRUST_GetSigner(CRYPT_PROVIDER_DATA *data,
299  DWORD signerIdx)
300 {
301     BOOL ret;
302     CMSG_SIGNER_INFO *signerInfo = NULL;
303     DWORD size;
304
305     ret = CryptMsgGetParam(data->hMsg, CMSG_SIGNER_INFO_PARAM, signerIdx,
306      NULL, &size);
307     if (ret)
308     {
309         signerInfo = data->psPfns->pfnAlloc(size);
310         if (signerInfo)
311         {
312             ret = CryptMsgGetParam(data->hMsg, CMSG_SIGNER_INFO_PARAM,
313              signerIdx, signerInfo, &size);
314             if (!ret)
315             {
316                 data->psPfns->pfnFree(signerInfo);
317                 signerInfo = NULL;
318             }
319         }
320         else
321             SetLastError(ERROR_OUTOFMEMORY);
322     }
323     return signerInfo;
324 }
325
326 static BOOL WINTRUST_SaveSigner(CRYPT_PROVIDER_DATA *data, DWORD signerIdx)
327 {
328     BOOL ret;
329     CMSG_SIGNER_INFO *signerInfo = WINTRUST_GetSigner(data, signerIdx);
330
331     if (signerInfo)
332     {
333         CRYPT_PROVIDER_SGNR sgnr = { sizeof(sgnr), { 0 } };
334
335         sgnr.psSigner = signerInfo;
336         ret = data->psPfns->pfnAddSgnr2Chain(data, FALSE, signerIdx, &sgnr);
337     }
338     else
339         ret = FALSE;
340     return ret;
341 }
342
343 static CERT_INFO *WINTRUST_GetSignerCertInfo(CRYPT_PROVIDER_DATA *data,
344  DWORD signerIdx)
345 {
346     BOOL ret;
347     CERT_INFO *certInfo = NULL;
348     DWORD size;
349
350     ret = CryptMsgGetParam(data->hMsg, CMSG_SIGNER_CERT_INFO_PARAM, signerIdx,
351      NULL, &size);
352     if (ret)
353     {
354         certInfo = data->psPfns->pfnAlloc(size);
355         if (certInfo)
356         {
357             ret = CryptMsgGetParam(data->hMsg, CMSG_SIGNER_CERT_INFO_PARAM,
358              signerIdx, certInfo, &size);
359             if (!ret)
360             {
361                 data->psPfns->pfnFree(certInfo);
362                 certInfo = NULL;
363             }
364         }
365         else
366             SetLastError(ERROR_OUTOFMEMORY);
367     }
368     return certInfo;
369 }
370
371 static BOOL WINTRUST_VerifySigner(CRYPT_PROVIDER_DATA *data, DWORD signerIdx)
372 {
373     BOOL ret;
374     CERT_INFO *certInfo = WINTRUST_GetSignerCertInfo(data, signerIdx);
375
376     if (certInfo)
377     {
378         PCCERT_CONTEXT subject = CertGetSubjectCertificateFromStore(
379          data->pahStores[0], data->dwEncoding, certInfo);
380
381         if (subject)
382         {
383             CMSG_CTRL_VERIFY_SIGNATURE_EX_PARA para = { sizeof(para), 0,
384              signerIdx, CMSG_VERIFY_SIGNER_CERT, (LPVOID)subject };
385
386             ret = CryptMsgControl(data->hMsg, 0, CMSG_CTRL_VERIFY_SIGNATURE_EX,
387              &para);
388             if (!ret)
389                 SetLastError(TRUST_E_CERT_SIGNATURE);
390             else
391                 data->psPfns->pfnAddCert2Chain(data, signerIdx, FALSE, 0,
392                  subject);
393             CertFreeCertificateContext(subject);
394         }
395         else
396         {
397             SetLastError(TRUST_E_NO_SIGNER_CERT);
398             ret = FALSE;
399         }
400         data->psPfns->pfnFree(certInfo);
401     }
402     else
403         ret = FALSE;
404     return ret;
405 }
406
407 HRESULT WINAPI SoftpubLoadSignature(CRYPT_PROVIDER_DATA *data)
408 {
409     BOOL ret;
410     DWORD signerCount, size;
411
412     TRACE("(%p)\n", data);
413
414     if (!data->padwTrustStepErrors)
415         return S_FALSE;
416
417     size = sizeof(signerCount);
418     ret = CryptMsgGetParam(data->hMsg, CMSG_SIGNER_COUNT_PARAM, 0,
419      &signerCount, &size);
420     if (ret)
421     {
422         DWORD i;
423
424         for (i = 0; ret && i < signerCount; i++)
425         {
426             if ((ret = WINTRUST_SaveSigner(data, i)))
427                 ret = WINTRUST_VerifySigner(data, i);
428         }
429     }
430     else
431         SetLastError(TRUST_E_NOSIGNATURE);
432     if (!ret)
433         data->padwTrustStepErrors[TRUSTERROR_STEP_FINAL_OBJPROV] =
434          GetLastError();
435     return ret ? S_OK : S_FALSE;
436 }
437
438 BOOL WINAPI SoftpubCheckCert(CRYPT_PROVIDER_DATA *data, DWORD idxSigner,
439  BOOL fCounterSignerChain, DWORD idxCounterSigner)
440 {
441     BOOL ret;
442
443     TRACE("(%p, %d, %d, %d)\n", data, idxSigner, fCounterSignerChain,
444      idxCounterSigner);
445
446     if (fCounterSignerChain)
447     {
448         FIXME("unimplemented for counter signers\n");
449         ret = FALSE;
450     }
451     else
452     {
453         PCERT_SIMPLE_CHAIN simpleChain =
454          data->pasSigners[idxSigner].pChainContext->rgpChain[0];
455         DWORD i;
456
457         ret = TRUE;
458         for (i = 0; i < simpleChain->cElement; i++)
459         {
460             /* Set confidence */
461             data->pasSigners[idxSigner].pasCertChain[i].dwConfidence = 0;
462             /* The last element in the chain doesn't have an issuer, so it
463              * can't have a valid time (with respect to its issuer)
464              */
465             if (i != simpleChain->cElement - 1 &&
466              !(simpleChain->rgpElement[i]->TrustStatus.dwErrorStatus &
467              CERT_TRUST_IS_NOT_TIME_VALID))
468                 data->pasSigners[idxSigner].pasCertChain[i].dwConfidence
469                  |= CERT_CONFIDENCE_TIME;
470             if (!(simpleChain->rgpElement[i]->TrustStatus.dwErrorStatus &
471              CERT_TRUST_IS_NOT_TIME_NESTED))
472                 data->pasSigners[idxSigner].pasCertChain[i].dwConfidence
473                  |= CERT_CONFIDENCE_TIMENEST;
474             if (!(simpleChain->rgpElement[i]->TrustStatus.dwErrorStatus &
475              CERT_TRUST_IS_NOT_SIGNATURE_VALID))
476                 data->pasSigners[idxSigner].pasCertChain[i].dwConfidence
477                  |= CERT_CONFIDENCE_SIG;
478             /* Set additional flags */
479             if (!(simpleChain->rgpElement[i]->TrustStatus.dwErrorStatus &
480              CERT_TRUST_IS_UNTRUSTED_ROOT))
481                 data->pasSigners[idxSigner].pasCertChain[i].fTrustedRoot = TRUE;
482             if (simpleChain->rgpElement[i]->TrustStatus.dwInfoStatus &
483              CERT_TRUST_IS_SELF_SIGNED)
484                 data->pasSigners[idxSigner].pasCertChain[i].fSelfSigned = TRUE;
485             if (simpleChain->rgpElement[i]->TrustStatus.dwErrorStatus &
486              CERT_TRUST_IS_CYCLIC)
487                 data->pasSigners[idxSigner].pasCertChain[i].fIsCyclic = TRUE;
488         }
489     }
490     return ret;
491 }
492
493 static BOOL WINTRUST_CopyChain(CRYPT_PROVIDER_DATA *data, DWORD signerIdx)
494 {
495     BOOL ret;
496     PCERT_SIMPLE_CHAIN simpleChain =
497      data->pasSigners[signerIdx].pChainContext->rgpChain[0];
498     DWORD i;
499
500     data->pasSigners[signerIdx].pasCertChain[0].pChainElement =
501      simpleChain->rgpElement[0];
502     ret = TRUE;
503     for (i = 1; ret && i < simpleChain->cElement; i++)
504     {
505         ret = data->psPfns->pfnAddCert2Chain(data, signerIdx, FALSE, 0,
506          simpleChain->rgpElement[i]->pCertContext);
507         if (ret)
508             data->pasSigners[signerIdx].pasCertChain[i].pChainElement =
509              simpleChain->rgpElement[i];
510     }
511     return ret;
512 }
513
514 HRESULT WINAPI WintrustCertificateTrust(CRYPT_PROVIDER_DATA *data)
515 {
516     BOOL ret;
517
518     if (!data->csSigners)
519     {
520         ret = FALSE;
521         SetLastError(TRUST_E_NOSIGNATURE);
522     }
523     else
524     {
525         DWORD i;
526
527         ret = TRUE;
528         for (i = 0; i < data->csSigners; i++)
529         {
530             CERT_CHAIN_PARA chainPara = { sizeof(chainPara), { 0 } };
531             DWORD flags;
532
533             if (data->pRequestUsage)
534                 memcpy(&chainPara.RequestedUsage, data->pRequestUsage,
535                  sizeof(CERT_USAGE_MATCH));
536             if (data->dwProvFlags & CPD_REVOCATION_CHECK_END_CERT)
537                 flags = CERT_CHAIN_REVOCATION_CHECK_END_CERT;
538             else if (data->dwProvFlags & CPD_REVOCATION_CHECK_CHAIN)
539                 flags = CERT_CHAIN_REVOCATION_CHECK_CHAIN;
540             else if (data->dwProvFlags & CPD_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT)
541                 flags = CERT_CHAIN_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT;
542             else
543                 flags = 0;
544             /* Expect the end certificate for each signer to be the only
545              * cert in the chain:
546              */
547             if (data->pasSigners[i].csCertChain)
548             {
549                 /* Create a certificate chain for each signer */
550                 ret = CertGetCertificateChain(NULL,
551                  data->pasSigners[i].pasCertChain[0].pCert,
552                  NULL, /* FIXME: use data->pasSigners[i].sftVerifyAsOf? */
553                  data->chStores ? data->pahStores[0] : NULL,
554                  &chainPara, flags, NULL, &data->pasSigners[i].pChainContext);
555                 if (ret)
556                 {
557                     if (data->pasSigners[i].pChainContext->cChain != 1)
558                     {
559                         FIXME("unimplemented for more than 1 simple chain\n");
560                         ret = FALSE;
561                     }
562                     else
563                     {
564                         if ((ret = WINTRUST_CopyChain(data, i)))
565                             ret = data->psPfns->pfnCertCheckPolicy(data, i,
566                              FALSE, 0);
567                     }
568                 }
569             }
570         }
571     }
572     if (!ret)
573         data->padwTrustStepErrors[TRUSTERROR_STEP_FINAL_CERTPROV] =
574          GetLastError();
575     return ret ? S_OK : S_FALSE;
576 }
577
578 HRESULT WINAPI SoftpubAuthenticode(CRYPT_PROVIDER_DATA *data)
579 {
580     BOOL ret;
581     CERT_CHAIN_POLICY_STATUS policyStatus = { sizeof(policyStatus), 0 };
582
583     if (data->pWintrustData->dwUIChoice != WTD_UI_NONE)
584         FIXME("unimplemented for UI choice %d\n",
585          data->pWintrustData->dwUIChoice);
586     if (!data->csSigners)
587     {
588         ret = FALSE;
589         policyStatus.dwError = TRUST_E_NOSIGNATURE;
590     }
591     else
592     {
593         DWORD i;
594
595         ret = TRUE;
596         for (i = 0; ret && i < data->csSigners; i++)
597         {
598             CERT_CHAIN_POLICY_PARA policyPara = { sizeof(policyPara), 0 };
599
600             if (data->dwRegPolicySettings & WTPF_TRUSTTEST)
601                 policyPara.dwFlags |= CERT_CHAIN_POLICY_TRUST_TESTROOT_FLAG;
602             if (data->dwRegPolicySettings & WTPF_TESTCANBEVALID)
603                 policyPara.dwFlags |= CERT_CHAIN_POLICY_ALLOW_TESTROOT_FLAG;
604             if (data->dwRegPolicySettings & WTPF_IGNOREEXPIRATION)
605                 policyPara.dwFlags |=
606                  CERT_CHAIN_POLICY_IGNORE_NOT_TIME_VALID_FLAG |
607                  CERT_CHAIN_POLICY_IGNORE_CTL_NOT_TIME_VALID_FLAG |
608                  CERT_CHAIN_POLICY_IGNORE_NOT_TIME_NESTED_FLAG;
609             if (data->dwRegPolicySettings & WTPF_IGNOREREVOKATION)
610                 policyPara.dwFlags |=
611                  CERT_CHAIN_POLICY_IGNORE_END_REV_UNKNOWN_FLAG |
612                  CERT_CHAIN_POLICY_IGNORE_CTL_SIGNER_REV_UNKNOWN_FLAG |
613                  CERT_CHAIN_POLICY_IGNORE_CA_REV_UNKNOWN_FLAG |
614                  CERT_CHAIN_POLICY_IGNORE_ROOT_REV_UNKNOWN_FLAG;
615             CertVerifyCertificateChainPolicy(CERT_CHAIN_POLICY_AUTHENTICODE,
616              data->pasSigners[i].pChainContext, &policyPara, &policyStatus);
617             if (policyStatus.dwError != NO_ERROR)
618                 ret = FALSE;
619         }
620     }
621     if (!ret)
622         data->padwTrustStepErrors[TRUSTERROR_STEP_FINAL_POLICYPROV] =
623          policyStatus.dwError;
624     return ret ? S_OK : S_FALSE;
625 }
626
627 HRESULT WINAPI SoftpubCleanup(CRYPT_PROVIDER_DATA *data)
628 {
629     DWORD i, j;
630
631     for (i = 0; i < data->csSigners; i++)
632     {
633         for (j = 0; j < data->pasSigners[i].csCertChain; j++)
634             CertFreeCertificateContext(data->pasSigners[i].pasCertChain[j].pCert);
635         data->psPfns->pfnFree(data->pasSigners[i].pasCertChain);
636         data->psPfns->pfnFree(data->pasSigners[i].psSigner);
637         CertFreeCertificateChain(data->pasSigners[i].pChainContext);
638     }
639     data->psPfns->pfnFree(data->pasSigners);
640
641     for (i = 0; i < data->chStores; i++)
642         CertCloseStore(data->pahStores[i], 0);
643     data->psPfns->pfnFree(data->pahStores);
644
645     if (data->u.pPDSip)
646     {
647         data->psPfns->pfnFree(data->u.pPDSip->pSip);
648         data->psPfns->pfnFree(data->u.pPDSip->pCATSip);
649         data->psPfns->pfnFree(data->u.pPDSip->psSipSubjectInfo);
650         data->psPfns->pfnFree(data->u.pPDSip->psSipCATSubjectInfo);
651         data->psPfns->pfnFree(data->u.pPDSip->psIndirectData);
652     }
653
654     CryptMsgClose(data->hMsg);
655
656     if (data->fOpenedFile)
657         CloseHandle(data->pWintrustData->u.pFile->hFile);
658
659     return S_OK;
660 }