2 * Copyright 2001 Rein Klazes
3 * Copyright 2007 Juan Lang
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 #define WIN32_NO_STATUS
22 #define COM_NO_WINDOWS_H
28 #define NONAMELESSUNION
32 //#include "winerror.h"
34 //#include "guiddef.h"
35 //#include "wintrust.h"
41 #include <cryptuiapi.h>
42 //#include "wintrust_priv.h"
43 #include <wine/debug.h>
45 WINE_DEFAULT_DEBUG_CHANNEL(wintrust
);
48 /* Utility functions */
49 void * WINAPI
WINTRUST_Alloc(DWORD cb
)
51 return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, cb
);
54 static void* WINTRUST_ReAlloc(void *ptr
, DWORD cb
) __WINE_ALLOC_SIZE(2);
55 static void* WINTRUST_ReAlloc(void *ptr
, DWORD cb
)
57 return HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, ptr
, cb
);
60 void WINAPI
WINTRUST_Free(void *p
)
62 HeapFree(GetProcessHeap(), 0, p
);
65 /***********************************************************************
66 * DllMain (WINTRUST.@)
68 BOOL WINAPI
DllMain( HINSTANCE inst
, DWORD reason
, LPVOID reserved
)
72 case DLL_PROCESS_ATTACH
:
73 DisableThreadLibraryCalls( inst
);
79 /***********************************************************************
80 * TrustIsCertificateSelfSigned (WINTRUST.@)
82 BOOL WINAPI
TrustIsCertificateSelfSigned( PCCERT_CONTEXT cert
)
89 if ((ext
= CertFindExtension(szOID_AUTHORITY_KEY_IDENTIFIER2
,
90 cert
->pCertInfo
->cExtension
, cert
->pCertInfo
->rgExtension
)))
92 CERT_AUTHORITY_KEY_ID2_INFO
*info
;
94 ret
= CryptDecodeObjectEx(cert
->dwCertEncodingType
,
95 X509_AUTHORITY_KEY_ID2
, ext
->Value
.pbData
, ext
->Value
.cbData
,
96 CRYPT_DECODE_ALLOC_FLAG
| CRYPT_DECODE_NOCOPY_FLAG
, NULL
,
100 if (info
->AuthorityCertIssuer
.cAltEntry
&&
101 info
->AuthorityCertSerialNumber
.cbData
)
103 PCERT_ALT_NAME_ENTRY directoryName
= NULL
;
106 for (i
= 0; !directoryName
&&
107 i
< info
->AuthorityCertIssuer
.cAltEntry
; i
++)
108 if (info
->AuthorityCertIssuer
.rgAltEntry
[i
].dwAltNameChoice
109 == CERT_ALT_NAME_DIRECTORY_NAME
)
111 &info
->AuthorityCertIssuer
.rgAltEntry
[i
];
114 ret
= CertCompareCertificateName(cert
->dwCertEncodingType
,
115 &directoryName
->u
.DirectoryName
, &cert
->pCertInfo
->Issuer
)
116 && CertCompareIntegerBlob(&info
->AuthorityCertSerialNumber
,
117 &cert
->pCertInfo
->SerialNumber
);
121 FIXME("no supported name type in authority key id2\n");
125 else if (info
->KeyId
.cbData
)
127 ret
= CertGetCertificateContextProperty(cert
,
128 CERT_KEY_IDENTIFIER_PROP_ID
, NULL
, &size
);
129 if (ret
&& size
== info
->KeyId
.cbData
)
131 LPBYTE buf
= CryptMemAlloc(size
);
135 CertGetCertificateContextProperty(cert
,
136 CERT_KEY_IDENTIFIER_PROP_ID
, buf
, &size
);
137 ret
= !memcmp(buf
, info
->KeyId
.pbData
, size
);
149 else if ((ext
= CertFindExtension(szOID_AUTHORITY_KEY_IDENTIFIER
,
150 cert
->pCertInfo
->cExtension
, cert
->pCertInfo
->rgExtension
)))
152 CERT_AUTHORITY_KEY_ID_INFO
*info
;
154 ret
= CryptDecodeObjectEx(cert
->dwCertEncodingType
,
155 X509_AUTHORITY_KEY_ID
, ext
->Value
.pbData
, ext
->Value
.cbData
,
156 CRYPT_DECODE_ALLOC_FLAG
| CRYPT_DECODE_NOCOPY_FLAG
, NULL
,
160 if (info
->CertIssuer
.cbData
&& info
->CertSerialNumber
.cbData
)
162 ret
= CertCompareCertificateName(cert
->dwCertEncodingType
,
163 &info
->CertIssuer
, &cert
->pCertInfo
->Issuer
) &&
164 CertCompareIntegerBlob(&info
->CertSerialNumber
,
165 &cert
->pCertInfo
->SerialNumber
);
167 else if (info
->KeyId
.cbData
)
169 ret
= CertGetCertificateContextProperty(cert
,
170 CERT_KEY_IDENTIFIER_PROP_ID
, NULL
, &size
);
171 if (ret
&& size
== info
->KeyId
.cbData
)
173 LPBYTE buf
= CryptMemAlloc(size
);
177 CertGetCertificateContextProperty(cert
,
178 CERT_KEY_IDENTIFIER_PROP_ID
, buf
, &size
);
179 ret
= !memcmp(buf
, info
->KeyId
.pbData
, size
);
194 ret
= CertCompareCertificateName(cert
->dwCertEncodingType
,
195 &cert
->pCertInfo
->Subject
, &cert
->pCertInfo
->Issuer
);
199 typedef HRESULT (WINAPI
*wintrust_step_func
)(CRYPT_PROVIDER_DATA
*data
);
203 wintrust_step_func func
;
207 static DWORD
WINTRUST_ExecuteSteps(const struct wintrust_step
*steps
,
208 DWORD numSteps
, CRYPT_PROVIDER_DATA
*provData
)
210 DWORD i
, err
= ERROR_SUCCESS
;
212 for (i
= 0; !err
&& i
< numSteps
; i
++)
214 err
= steps
[i
].func(provData
);
216 err
= provData
->padwTrustStepErrors
[steps
[i
].error_index
];
221 static CRYPT_PROVIDER_DATA
*WINTRUST_AllocateProviderData(void)
223 CRYPT_PROVIDER_DATA
*provData
;
225 provData
= WINTRUST_Alloc(sizeof(CRYPT_PROVIDER_DATA
));
228 provData
->cbStruct
= sizeof(CRYPT_PROVIDER_DATA
);
230 provData
->padwTrustStepErrors
=
231 WINTRUST_Alloc(TRUSTERROR_MAX_STEPS
* sizeof(DWORD
));
232 if (!provData
->padwTrustStepErrors
)
234 provData
->cdwTrustStepErrors
= TRUSTERROR_MAX_STEPS
;
236 provData
->u
.pPDSip
= WINTRUST_Alloc(sizeof(PROVDATA_SIP
));
237 if (!provData
->u
.pPDSip
)
239 provData
->u
.pPDSip
->cbStruct
= sizeof(PROVDATA_SIP
);
241 provData
->psPfns
= WINTRUST_Alloc(sizeof(CRYPT_PROVIDER_FUNCTIONS
));
242 if (!provData
->psPfns
)
244 provData
->psPfns
->cbStruct
= sizeof(CRYPT_PROVIDER_FUNCTIONS
);
250 WINTRUST_Free(provData
->padwTrustStepErrors
);
251 WINTRUST_Free(provData
->u
.pPDSip
);
252 WINTRUST_Free(provData
->psPfns
);
253 WINTRUST_Free(provData
);
258 /* Adds trust steps for each function in psPfns. Assumes steps has at least
259 * 5 entries. Returns the number of steps added.
261 static DWORD
WINTRUST_AddTrustStepsFromFunctions(struct wintrust_step
*steps
,
262 const CRYPT_PROVIDER_FUNCTIONS
*psPfns
)
266 if (psPfns
->pfnInitialize
)
268 steps
[numSteps
].func
= psPfns
->pfnInitialize
;
269 steps
[numSteps
++].error_index
= TRUSTERROR_STEP_FINAL_WVTINIT
;
271 if (psPfns
->pfnObjectTrust
)
273 steps
[numSteps
].func
= psPfns
->pfnObjectTrust
;
274 steps
[numSteps
++].error_index
= TRUSTERROR_STEP_FINAL_OBJPROV
;
276 if (psPfns
->pfnSignatureTrust
)
278 steps
[numSteps
].func
= psPfns
->pfnSignatureTrust
;
279 steps
[numSteps
++].error_index
= TRUSTERROR_STEP_FINAL_SIGPROV
;
281 if (psPfns
->pfnCertificateTrust
)
283 steps
[numSteps
].func
= psPfns
->pfnCertificateTrust
;
284 steps
[numSteps
++].error_index
= TRUSTERROR_STEP_FINAL_CERTPROV
;
286 if (psPfns
->pfnFinalPolicy
)
288 steps
[numSteps
].func
= psPfns
->pfnFinalPolicy
;
289 steps
[numSteps
++].error_index
= TRUSTERROR_STEP_FINAL_POLICYPROV
;
294 static LONG
WINTRUST_DefaultVerify(HWND hwnd
, GUID
*actionID
,
297 DWORD err
= ERROR_SUCCESS
, numSteps
= 0;
298 CRYPT_PROVIDER_DATA
*provData
;
300 struct wintrust_step verifySteps
[5];
302 TRACE("(%p, %s, %p)\n", hwnd
, debugstr_guid(actionID
), data
);
304 provData
= WINTRUST_AllocateProviderData();
306 return ERROR_OUTOFMEMORY
;
308 ret
= WintrustLoadFunctionPointers(actionID
, provData
->psPfns
);
311 err
= GetLastError();
315 data
->hWVTStateData
= provData
;
316 provData
->pWintrustData
= data
;
317 if (hwnd
== INVALID_HANDLE_VALUE
)
318 provData
->hWndParent
= GetDesktopWindow();
320 provData
->hWndParent
= hwnd
;
321 provData
->pgActionID
= actionID
;
322 WintrustGetRegPolicyFlags(&provData
->dwRegPolicySettings
);
324 numSteps
= WINTRUST_AddTrustStepsFromFunctions(verifySteps
,
326 err
= WINTRUST_ExecuteSteps(verifySteps
, numSteps
, provData
);
332 WINTRUST_Free(provData
->padwTrustStepErrors
);
333 WINTRUST_Free(provData
->u
.pPDSip
);
334 WINTRUST_Free(provData
->psPfns
);
335 WINTRUST_Free(provData
);
338 TRACE("returning %08x\n", err
);
342 static LONG
WINTRUST_DefaultClose(HWND hwnd
, GUID
*actionID
,
345 DWORD err
= ERROR_SUCCESS
;
346 CRYPT_PROVIDER_DATA
*provData
= data
->hWVTStateData
;
348 TRACE("(%p, %s, %p)\n", hwnd
, debugstr_guid(actionID
), data
);
352 if (provData
->psPfns
->pfnCleanupPolicy
)
353 err
= provData
->psPfns
->pfnCleanupPolicy(provData
);
355 WINTRUST_Free(provData
->padwTrustStepErrors
);
356 WINTRUST_Free(provData
->u
.pPDSip
);
357 WINTRUST_Free(provData
->psPfns
);
358 WINTRUST_Free(provData
);
359 data
->hWVTStateData
= NULL
;
361 TRACE("returning %08x\n", err
);
365 static LONG
WINTRUST_DefaultVerifyAndClose(HWND hwnd
, GUID
*actionID
,
370 TRACE("(%p, %s, %p)\n", hwnd
, debugstr_guid(actionID
), data
);
372 err
= WINTRUST_DefaultVerify(hwnd
, actionID
, data
);
373 WINTRUST_DefaultClose(hwnd
, actionID
, data
);
374 TRACE("returning %08x\n", err
);
378 static LONG
WINTRUST_PublishedSoftware(HWND hwnd
, GUID
*actionID
,
381 WINTRUST_DATA wintrust_data
= { sizeof(wintrust_data
), 0 };
382 /* Undocumented: the published software action is passed a path,
383 * and pSIPClientData points to a WIN_TRUST_SUBJECT_FILE.
385 LPWIN_TRUST_SUBJECT_FILE subjectFile
= data
->pSIPClientData
;
386 WINTRUST_FILE_INFO fileInfo
= { sizeof(fileInfo
), 0 };
388 TRACE("subjectFile->hFile: %p\n", subjectFile
->hFile
);
389 TRACE("subjectFile->lpPath: %s\n", debugstr_w(subjectFile
->lpPath
));
390 fileInfo
.pcwszFilePath
= subjectFile
->lpPath
;
391 fileInfo
.hFile
= subjectFile
->hFile
;
392 wintrust_data
.u
.pFile
= &fileInfo
;
393 wintrust_data
.dwUnionChoice
= WTD_CHOICE_FILE
;
394 wintrust_data
.dwUIChoice
= WTD_UI_NONE
;
396 return WINTRUST_DefaultVerifyAndClose(hwnd
, actionID
, &wintrust_data
);
399 /* Sadly, the function to load the cert for the CERT_CERTIFICATE_ACTION_VERIFY
400 * action is not stored in the registry and is located in wintrust, not in
401 * cryptdlg along with the rest of the implementation (verified by running the
402 * action with a native wintrust.dll.)
404 static HRESULT WINAPI
WINTRUST_CertVerifyObjTrust(CRYPT_PROVIDER_DATA
*data
)
408 TRACE("(%p)\n", data
);
410 if (!data
->padwTrustStepErrors
)
413 switch (data
->pWintrustData
->dwUnionChoice
)
415 case WTD_CHOICE_BLOB
:
416 if (data
->pWintrustData
->u
.pBlob
&&
417 WVT_IS_CBSTRUCT_GT_MEMBEROFFSET(WINTRUST_BLOB_INFO
,
418 data
->pWintrustData
->u
.pBlob
->cbStruct
, pbMemObject
) &&
419 data
->pWintrustData
->u
.pBlob
->cbMemObject
==
420 sizeof(CERT_VERIFY_CERTIFICATE_TRUST
) &&
421 data
->pWintrustData
->u
.pBlob
->pbMemObject
)
423 CERT_VERIFY_CERTIFICATE_TRUST
*pCert
=
424 (CERT_VERIFY_CERTIFICATE_TRUST
*)
425 data
->pWintrustData
->u
.pBlob
->pbMemObject
;
427 if (pCert
->cbSize
== sizeof(CERT_VERIFY_CERTIFICATE_TRUST
) &&
430 CRYPT_PROVIDER_SGNR signer
= { sizeof(signer
), { 0 } };
434 /* Add a signer with nothing but the time to verify, so we can
437 GetSystemTime(&sysTime
);
438 SystemTimeToFileTime(&sysTime
, &signer
.sftVerifyAsOf
);
439 ret
= data
->psPfns
->pfnAddSgnr2Chain(data
, FALSE
, 0, &signer
);
442 ret
= data
->psPfns
->pfnAddCert2Chain(data
, 0, FALSE
, 0,
446 for (i
= 0; ret
&& i
< pCert
->cRootStores
; i
++)
447 ret
= data
->psPfns
->pfnAddStore2Chain(data
,
448 pCert
->rghstoreRoots
[i
]);
449 for (i
= 0; ret
&& i
< pCert
->cStores
; i
++)
450 ret
= data
->psPfns
->pfnAddStore2Chain(data
,
451 pCert
->rghstoreCAs
[i
]);
452 for (i
= 0; ret
&& i
< pCert
->cTrustStores
; i
++)
453 ret
= data
->psPfns
->pfnAddStore2Chain(data
,
454 pCert
->rghstoreTrust
[i
]);
458 SetLastError(ERROR_INVALID_PARAMETER
);
464 SetLastError(ERROR_INVALID_PARAMETER
);
469 FIXME("unimplemented for %d\n", data
->pWintrustData
->dwUnionChoice
);
470 SetLastError(ERROR_INVALID_PARAMETER
);
476 data
->padwTrustStepErrors
[TRUSTERROR_STEP_FINAL_OBJPROV
] =
478 TRACE("returning %d (%08x)\n", ret
? S_OK
: S_FALSE
,
479 data
->padwTrustStepErrors
[TRUSTERROR_STEP_FINAL_OBJPROV
]);
480 return ret
? S_OK
: S_FALSE
;
483 static LONG
WINTRUST_CertVerify(HWND hwnd
, GUID
*actionID
,
486 DWORD err
= ERROR_SUCCESS
, numSteps
= 0;
487 CRYPT_PROVIDER_DATA
*provData
;
489 struct wintrust_step verifySteps
[5];
491 TRACE("(%p, %s, %p)\n", hwnd
, debugstr_guid(actionID
), data
);
493 provData
= WINTRUST_AllocateProviderData();
495 return ERROR_OUTOFMEMORY
;
497 ret
= WintrustLoadFunctionPointers(actionID
, provData
->psPfns
);
500 err
= GetLastError();
503 if (!provData
->psPfns
->pfnObjectTrust
)
504 provData
->psPfns
->pfnObjectTrust
= WINTRUST_CertVerifyObjTrust
;
505 /* Not sure why, but native skips the policy check */
506 provData
->psPfns
->pfnCertCheckPolicy
= NULL
;
508 data
->hWVTStateData
= provData
;
509 provData
->pWintrustData
= data
;
510 if (hwnd
== INVALID_HANDLE_VALUE
)
511 provData
->hWndParent
= GetDesktopWindow();
513 provData
->hWndParent
= hwnd
;
514 provData
->pgActionID
= actionID
;
515 WintrustGetRegPolicyFlags(&provData
->dwRegPolicySettings
);
517 numSteps
= WINTRUST_AddTrustStepsFromFunctions(verifySteps
,
519 err
= WINTRUST_ExecuteSteps(verifySteps
, numSteps
, provData
);
525 WINTRUST_Free(provData
->padwTrustStepErrors
);
526 WINTRUST_Free(provData
->u
.pPDSip
);
527 WINTRUST_Free(provData
->psPfns
);
528 WINTRUST_Free(provData
);
531 TRACE("returning %08x\n", err
);
535 static LONG
WINTRUST_CertVerifyAndClose(HWND hwnd
, GUID
*actionID
,
540 TRACE("(%p, %s, %p)\n", hwnd
, debugstr_guid(actionID
), data
);
542 err
= WINTRUST_CertVerify(hwnd
, actionID
, data
);
543 WINTRUST_DefaultClose(hwnd
, actionID
, data
);
544 TRACE("returning %08x\n", err
);
548 static LONG
WINTRUST_CertActionVerify(HWND hwnd
, GUID
*actionID
,
552 LONG err
= ERROR_SUCCESS
;
554 if (WVT_ISINSTRUCT(WINTRUST_DATA
, data
->cbStruct
, dwStateAction
))
555 stateAction
= data
->dwStateAction
;
558 TRACE("no dwStateAction, assuming WTD_STATEACTION_IGNORE\n");
559 stateAction
= WTD_STATEACTION_IGNORE
;
563 case WTD_STATEACTION_IGNORE
:
564 err
= WINTRUST_CertVerifyAndClose(hwnd
, actionID
, data
);
566 case WTD_STATEACTION_VERIFY
:
567 err
= WINTRUST_CertVerify(hwnd
, actionID
, data
);
569 case WTD_STATEACTION_CLOSE
:
570 err
= WINTRUST_DefaultClose(hwnd
, actionID
, data
);
573 FIXME("unimplemented for %d\n", data
->dwStateAction
);
578 static void dump_file_info(WINTRUST_FILE_INFO
*pFile
)
580 TRACE("%p\n", pFile
);
583 TRACE("cbStruct: %d\n", pFile
->cbStruct
);
584 TRACE("pcwszFilePath: %s\n", debugstr_w(pFile
->pcwszFilePath
));
585 TRACE("hFile: %p\n", pFile
->hFile
);
586 TRACE("pgKnownSubject: %s\n", debugstr_guid(pFile
->pgKnownSubject
));
590 static void dump_catalog_info(WINTRUST_CATALOG_INFO
*catalog
)
592 TRACE("%p\n", catalog
);
595 TRACE("cbStruct: %d\n", catalog
->cbStruct
);
596 TRACE("dwCatalogVersion: %d\n", catalog
->dwCatalogVersion
);
597 TRACE("pcwszCatalogFilePath: %s\n",
598 debugstr_w(catalog
->pcwszCatalogFilePath
));
599 TRACE("pcwszMemberTag: %s\n", debugstr_w(catalog
->pcwszMemberTag
));
600 TRACE("pcwszMemberFilePath: %s\n",
601 debugstr_w(catalog
->pcwszMemberFilePath
));
602 TRACE("hMemberFile: %p\n", catalog
->hMemberFile
);
603 TRACE("pbCalculatedFileHash: %p\n", catalog
->pbCalculatedFileHash
);
604 TRACE("cbCalculatedFileHash: %d\n", catalog
->cbCalculatedFileHash
);
605 TRACE("pcCatalogContext: %p\n", catalog
->pcCatalogContext
);
609 static void dump_blob_info(WINTRUST_BLOB_INFO
*blob
)
614 TRACE("cbStruct: %d\n", blob
->cbStruct
);
615 TRACE("gSubject: %s\n", debugstr_guid(&blob
->gSubject
));
616 TRACE("pcwszDisplayName: %s\n", debugstr_w(blob
->pcwszDisplayName
));
617 TRACE("cbMemObject: %d\n", blob
->cbMemObject
);
618 TRACE("pbMemObject: %p\n", blob
->pbMemObject
);
619 TRACE("cbMemSignedMsg: %d\n", blob
->cbMemSignedMsg
);
620 TRACE("pbMemSignedMsg: %p\n", blob
->pbMemSignedMsg
);
624 static void dump_sgnr_info(WINTRUST_SGNR_INFO
*sgnr
)
629 TRACE("cbStruct: %d\n", sgnr
->cbStruct
);
630 TRACE("pcwszDisplayName: %s\n", debugstr_w(sgnr
->pcwszDisplayName
));
631 TRACE("psSignerInfo: %p\n", sgnr
->psSignerInfo
);
632 TRACE("chStores: %d\n", sgnr
->chStores
);
636 static void dump_cert_info(WINTRUST_CERT_INFO
*cert
)
641 TRACE("cbStruct: %d\n", cert
->cbStruct
);
642 TRACE("pcwszDisplayName: %s\n", debugstr_w(cert
->pcwszDisplayName
));
643 TRACE("psCertContext: %p\n", cert
->psCertContext
);
644 TRACE("chStores: %d\n", cert
->chStores
);
645 TRACE("dwFlags: %08x\n", cert
->dwFlags
);
646 TRACE("psftVerifyAsOf: %p\n", cert
->psftVerifyAsOf
);
650 static void dump_wintrust_data(WINTRUST_DATA
*data
)
655 TRACE("cbStruct: %d\n", data
->cbStruct
);
656 TRACE("pPolicyCallbackData: %p\n", data
->pPolicyCallbackData
);
657 TRACE("pSIPClientData: %p\n", data
->pSIPClientData
);
658 TRACE("dwUIChoice: %d\n", data
->dwUIChoice
);
659 TRACE("fdwRevocationChecks: %08x\n", data
->fdwRevocationChecks
);
660 TRACE("dwUnionChoice: %d\n", data
->dwUnionChoice
);
661 switch (data
->dwUnionChoice
)
663 case WTD_CHOICE_FILE
:
664 dump_file_info(data
->u
.pFile
);
666 case WTD_CHOICE_CATALOG
:
667 dump_catalog_info(data
->u
.pCatalog
);
669 case WTD_CHOICE_BLOB
:
670 dump_blob_info(data
->u
.pBlob
);
672 case WTD_CHOICE_SIGNER
:
673 dump_sgnr_info(data
->u
.pSgnr
);
675 case WTD_CHOICE_CERT
:
676 dump_cert_info(data
->u
.pCert
);
679 TRACE("dwStateAction: %d\n", data
->dwStateAction
);
680 TRACE("hWVTStateData: %p\n", data
->hWVTStateData
);
681 TRACE("pwszURLReference: %s\n", debugstr_w(data
->pwszURLReference
));
682 TRACE("dwProvFlags: %08x\n", data
->dwProvFlags
);
683 TRACE("dwUIContext: %d\n", data
->dwUIContext
);
687 /***********************************************************************
688 * WinVerifyTrust (WINTRUST.@)
690 * Verifies an object by calling the specified trust provider.
693 * hwnd [I] Handle to a caller window.
694 * ActionID [I] Pointer to a GUID that identifies the action to perform.
695 * ActionData [I] Information used by the trust provider to verify the object.
699 * Failure: A TRUST_E_* error code.
702 * Trust providers can be found at:
703 * HKLM\SOFTWARE\Microsoft\Cryptography\Providers\Trust\
705 LONG WINAPI
WinVerifyTrust( HWND hwnd
, GUID
*ActionID
, LPVOID ActionData
)
707 static const GUID unknown
= { 0xC689AAB8, 0x8E78, 0x11D0, { 0x8C,0x47,
708 0x00,0xC0,0x4F,0xC2,0x95,0xEE } };
709 static const GUID published_software
= WIN_SPUB_ACTION_PUBLISHED_SOFTWARE
;
710 static const GUID generic_verify_v2
= WINTRUST_ACTION_GENERIC_VERIFY_V2
;
711 static const GUID generic_cert_verify
= WINTRUST_ACTION_GENERIC_CERT_VERIFY
;
712 static const GUID generic_chain_verify
= WINTRUST_ACTION_GENERIC_CHAIN_VERIFY
;
713 static const GUID cert_action_verify
= CERT_CERTIFICATE_ACTION_VERIFY
;
714 LONG err
= ERROR_SUCCESS
;
715 WINTRUST_DATA
*actionData
= ActionData
;
717 TRACE("(%p, %s, %p)\n", hwnd
, debugstr_guid(ActionID
), ActionData
);
718 dump_wintrust_data(ActionData
);
720 /* Support for known old-style callers: */
721 if (IsEqualGUID(ActionID
, &published_software
))
722 err
= WINTRUST_PublishedSoftware(hwnd
, ActionID
, ActionData
);
723 else if (IsEqualGUID(ActionID
, &cert_action_verify
))
724 err
= WINTRUST_CertActionVerify(hwnd
, ActionID
, ActionData
);
729 /* Check known actions to warn of possible problems */
730 if (!IsEqualGUID(ActionID
, &unknown
) &&
731 !IsEqualGUID(ActionID
, &generic_verify_v2
) &&
732 !IsEqualGUID(ActionID
, &generic_cert_verify
) &&
733 !IsEqualGUID(ActionID
, &generic_chain_verify
))
734 WARN("unknown action %s, default behavior may not be right\n",
735 debugstr_guid(ActionID
));
736 if (WVT_ISINSTRUCT(WINTRUST_DATA
, actionData
->cbStruct
, dwStateAction
))
737 stateAction
= actionData
->dwStateAction
;
740 TRACE("no dwStateAction, assuming WTD_STATEACTION_IGNORE\n");
741 stateAction
= WTD_STATEACTION_IGNORE
;
745 case WTD_STATEACTION_IGNORE
:
746 err
= WINTRUST_DefaultVerifyAndClose(hwnd
, ActionID
, ActionData
);
748 case WTD_STATEACTION_VERIFY
:
749 err
= WINTRUST_DefaultVerify(hwnd
, ActionID
, ActionData
);
751 case WTD_STATEACTION_CLOSE
:
752 err
= WINTRUST_DefaultClose(hwnd
, ActionID
, ActionData
);
755 FIXME("unimplemented for %d\n", actionData
->dwStateAction
);
759 TRACE("returning %08x\n", err
);
763 /***********************************************************************
764 * WinVerifyTrustEx (WINTRUST.@)
766 HRESULT WINAPI
WinVerifyTrustEx( HWND hwnd
, GUID
*ActionID
,
767 WINTRUST_DATA
* ActionData
)
769 return WinVerifyTrust(hwnd
, ActionID
, ActionData
);
772 /***********************************************************************
773 * WTHelperGetProvSignerFromChain (WINTRUST.@)
775 CRYPT_PROVIDER_SGNR
* WINAPI
WTHelperGetProvSignerFromChain(
776 CRYPT_PROVIDER_DATA
*pProvData
, DWORD idxSigner
, BOOL fCounterSigner
,
777 DWORD idxCounterSigner
)
779 CRYPT_PROVIDER_SGNR
*sgnr
;
781 TRACE("(%p %d %d %d)\n", pProvData
, idxSigner
, fCounterSigner
,
784 if (idxSigner
>= pProvData
->csSigners
|| !pProvData
->pasSigners
)
786 sgnr
= &pProvData
->pasSigners
[idxSigner
];
789 if (idxCounterSigner
>= sgnr
->csCounterSigners
||
790 !sgnr
->pasCounterSigners
)
792 sgnr
= &sgnr
->pasCounterSigners
[idxCounterSigner
];
794 TRACE("returning %p\n", sgnr
);
798 /***********************************************************************
799 * WTHelperGetProvCertFromChain (WINTRUST.@)
801 CRYPT_PROVIDER_CERT
* WINAPI
WTHelperGetProvCertFromChain(
802 CRYPT_PROVIDER_SGNR
*pSgnr
, DWORD idxCert
)
804 CRYPT_PROVIDER_CERT
*cert
;
806 TRACE("(%p %d)\n", pSgnr
, idxCert
);
808 if (idxCert
>= pSgnr
->csCertChain
|| !pSgnr
->pasCertChain
)
810 cert
= &pSgnr
->pasCertChain
[idxCert
];
811 TRACE("returning %p\n", cert
);
815 CRYPT_PROVIDER_PRIVDATA
*WINAPI
WTHelperGetProvPrivateDataFromChain(
816 CRYPT_PROVIDER_DATA
* pProvData
,
819 CRYPT_PROVIDER_PRIVDATA
*privdata
= NULL
;
822 TRACE("(%p, %s)\n", pProvData
, debugstr_guid(pgProviderID
));
824 for (i
= 0; i
< pProvData
->csProvPrivData
; i
++)
825 if (IsEqualGUID(pgProviderID
, &pProvData
->pasProvPrivData
[i
].gProviderID
))
827 privdata
= &pProvData
->pasProvPrivData
[i
];
834 /***********************************************************************
835 * WTHelperProvDataFromStateData (WINTRUST.@)
837 CRYPT_PROVIDER_DATA
* WINAPI
WTHelperProvDataFromStateData(HANDLE hStateData
)
839 TRACE("%p\n", hStateData
);
843 /***********************************************************************
844 * WTHelperGetFileName(WINTRUST.@)
846 LPCWSTR WINAPI
WTHelperGetFileName(WINTRUST_DATA
*data
)
849 if (data
->dwUnionChoice
== WTD_CHOICE_FILE
)
850 return data
->u
.pFile
->pcwszFilePath
;
855 /***********************************************************************
856 * WTHelperGetFileHandle(WINTRUST.@)
858 HANDLE WINAPI
WTHelperGetFileHandle(WINTRUST_DATA
*data
)
861 if (data
->dwUnionChoice
== WTD_CHOICE_FILE
)
862 return data
->u
.pFile
->hFile
;
864 return INVALID_HANDLE_VALUE
;
867 static BOOL WINAPI
WINTRUST_enumUsages(PCCRYPT_OID_INFO pInfo
, void *pvArg
)
869 PCCRYPT_OID_INFO
**usages
= pvArg
;
876 *usages
= WINTRUST_Alloc(2 * sizeof(PCCRYPT_OID_INFO
));
880 PCCRYPT_OID_INFO
*ptr
;
882 /* Count the existing usages.
883 * FIXME: make sure the new usage doesn't duplicate any in the list?
885 for (cUsages
= 0, ptr
= *usages
; *ptr
; ptr
++, cUsages
++)
887 *usages
= WINTRUST_ReAlloc(*usages
,
888 (cUsages
+ 2) * sizeof(PCCRYPT_OID_INFO
));
892 (*usages
)[cUsages
] = pInfo
;
893 (*usages
)[cUsages
+ 1] = NULL
;
898 SetLastError(ERROR_OUTOFMEMORY
);
904 /***********************************************************************
905 * WTHelperGetKnownUsages(WINTRUST.@)
907 * Enumerates the known enhanced key usages as an array of PCCRYPT_OID_INFOs.
910 * action [In] 1 => allocate and return known usages, 2 => free previously
912 * usages [In/Out] If action == 1, *usages is set to an array of
913 * PCCRYPT_OID_INFO *. The array is terminated with a NULL
915 * If action == 2, *usages is freed.
918 * TRUE on success, FALSE on failure.
920 BOOL WINAPI
WTHelperGetKnownUsages(DWORD action
, PCCRYPT_OID_INFO
**usages
)
924 TRACE("(%d, %p)\n", action
, usages
);
928 SetLastError(ERROR_INVALID_PARAMETER
);
935 ret
= CryptEnumOIDInfo(CRYPT_ENHKEY_USAGE_OID_GROUP_ID
, 0, usages
,
936 WINTRUST_enumUsages
);
938 else if (action
== 2)
940 WINTRUST_Free(*usages
);
946 WARN("unknown action %d\n", action
);
947 SetLastError(ERROR_INVALID_PARAMETER
);
953 static const WCHAR Software_Publishing
[] = {
954 'S','o','f','t','w','a','r','e','\\',
955 'M','i','c','r','o','s','o','f','t','\\',
956 'W','i','n','d','o','w','s','\\',
957 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
958 'W','i','n','t','r','u','s','t','\\',
959 'T','r','u','s','t',' ','P','r','o','v','i','d','e','r','s','\\',
960 'S','o','f','t','w','a','r','e',' ',
961 'P','u','b','l','i','s','h','i','n','g',0 };
962 static const WCHAR State
[] = { 'S','t','a','t','e',0 };
964 /***********************************************************************
965 * WintrustGetRegPolicyFlags (WINTRUST.@)
967 void WINAPI
WintrustGetRegPolicyFlags( DWORD
* pdwPolicyFlags
)
972 TRACE("%p\n", pdwPolicyFlags
);
975 r
= RegCreateKeyExW(HKEY_CURRENT_USER
, Software_Publishing
, 0, NULL
, 0,
976 KEY_READ
, NULL
, &key
, NULL
);
979 DWORD size
= sizeof(DWORD
);
981 r
= RegQueryValueExW(key
, State
, NULL
, NULL
, (LPBYTE
)pdwPolicyFlags
,
986 /* Failed to query, create and return default value */
987 *pdwPolicyFlags
= WTPF_IGNOREREVOCATIONONTS
|
988 WTPF_OFFLINEOKNBU_COM
|
989 WTPF_OFFLINEOKNBU_IND
|
992 WintrustSetRegPolicyFlags(*pdwPolicyFlags
);
997 /***********************************************************************
998 * WintrustSetRegPolicyFlags (WINTRUST.@)
1000 BOOL WINAPI
WintrustSetRegPolicyFlags( DWORD dwPolicyFlags
)
1005 TRACE("%x\n", dwPolicyFlags
);
1007 r
= RegCreateKeyExW(HKEY_CURRENT_USER
, Software_Publishing
, 0,
1008 NULL
, 0, KEY_WRITE
, NULL
, &key
, NULL
);
1011 r
= RegSetValueExW(key
, State
, 0, REG_DWORD
, (LPBYTE
)&dwPolicyFlags
,
1015 if (r
) SetLastError(r
);
1016 return r
== ERROR_SUCCESS
;
1019 /* Utility functions */
1021 BOOL WINAPI
WINTRUST_AddStore(CRYPT_PROVIDER_DATA
*data
, HCERTSTORE store
)
1025 TRACE("(%p, %p)\n", data
, store
);
1028 data
->pahStores
= WINTRUST_ReAlloc(data
->pahStores
,
1029 (data
->chStores
+ 1) * sizeof(HCERTSTORE
));
1032 data
->pahStores
= WINTRUST_Alloc(sizeof(HCERTSTORE
));
1035 if (data
->pahStores
)
1037 data
->pahStores
[data
->chStores
++] = CertDuplicateStore(store
);
1041 SetLastError(ERROR_OUTOFMEMORY
);
1045 BOOL WINAPI
WINTRUST_AddSgnr(CRYPT_PROVIDER_DATA
*data
,
1046 BOOL fCounterSigner
, DWORD idxSigner
, CRYPT_PROVIDER_SGNR
*sgnr
)
1050 TRACE("(%p, %d, %d, %p)\n", data
, fCounterSigner
, idxSigner
, sgnr
);
1052 if (sgnr
->cbStruct
> sizeof(CRYPT_PROVIDER_SGNR
))
1054 SetLastError(ERROR_INVALID_PARAMETER
);
1059 FIXME("unimplemented for counter signers\n");
1060 SetLastError(ERROR_INVALID_PARAMETER
);
1063 if (data
->csSigners
)
1064 data
->pasSigners
= WINTRUST_ReAlloc(data
->pasSigners
,
1065 (data
->csSigners
+ 1) * sizeof(CRYPT_PROVIDER_SGNR
));
1068 data
->pasSigners
= WINTRUST_Alloc(sizeof(CRYPT_PROVIDER_SGNR
));
1069 data
->csSigners
= 0;
1071 if (data
->pasSigners
)
1073 if (idxSigner
< data
->csSigners
)
1074 memmove(&data
->pasSigners
[idxSigner
],
1075 &data
->pasSigners
[idxSigner
+ 1],
1076 (data
->csSigners
- idxSigner
) * sizeof(CRYPT_PROVIDER_SGNR
));
1078 if (sgnr
->cbStruct
== sizeof(CRYPT_PROVIDER_SGNR
))
1080 /* The PSDK says psSigner should be allocated using pfnAlloc, but
1081 * it doesn't say anything about ownership. Since callers are
1082 * internal, assume ownership is passed, and just store the
1085 memcpy(&data
->pasSigners
[idxSigner
], sgnr
,
1086 sizeof(CRYPT_PROVIDER_SGNR
));
1089 memset(&data
->pasSigners
[idxSigner
], 0,
1090 sizeof(CRYPT_PROVIDER_SGNR
));
1094 SetLastError(ERROR_OUTOFMEMORY
);
1098 BOOL WINAPI
WINTRUST_AddCert(CRYPT_PROVIDER_DATA
*data
, DWORD idxSigner
,
1099 BOOL fCounterSigner
, DWORD idxCounterSigner
, PCCERT_CONTEXT pCert2Add
)
1103 TRACE("(%p, %d, %d, %d, %p)\n", data
, idxSigner
, fCounterSigner
,
1104 idxSigner
, pCert2Add
);
1108 FIXME("unimplemented for counter signers\n");
1109 SetLastError(ERROR_INVALID_PARAMETER
);
1112 if (data
->pasSigners
[idxSigner
].csCertChain
)
1113 data
->pasSigners
[idxSigner
].pasCertChain
=
1114 WINTRUST_ReAlloc(data
->pasSigners
[idxSigner
].pasCertChain
,
1115 (data
->pasSigners
[idxSigner
].csCertChain
+ 1) *
1116 sizeof(CRYPT_PROVIDER_CERT
));
1119 data
->pasSigners
[idxSigner
].pasCertChain
=
1120 WINTRUST_Alloc(sizeof(CRYPT_PROVIDER_CERT
));
1121 data
->pasSigners
[idxSigner
].csCertChain
= 0;
1123 if (data
->pasSigners
[idxSigner
].pasCertChain
)
1125 CRYPT_PROVIDER_CERT
*cert
= &data
->pasSigners
[idxSigner
].pasCertChain
[
1126 data
->pasSigners
[idxSigner
].csCertChain
];
1128 cert
->cbStruct
= sizeof(CRYPT_PROVIDER_CERT
);
1129 cert
->pCert
= CertDuplicateCertificateContext(pCert2Add
);
1130 data
->pasSigners
[idxSigner
].csCertChain
++;
1134 SetLastError(ERROR_OUTOFMEMORY
);
1138 BOOL WINAPI
WINTRUST_AddPrivData(CRYPT_PROVIDER_DATA
*data
,
1139 CRYPT_PROVIDER_PRIVDATA
*pPrivData2Add
)
1143 TRACE("(%p, %p)\n", data
, pPrivData2Add
);
1145 if (pPrivData2Add
->cbStruct
> sizeof(CRYPT_PROVIDER_PRIVDATA
))
1147 SetLastError(ERROR_INVALID_PARAMETER
);
1148 WARN("invalid struct size\n");
1151 if (data
->csProvPrivData
)
1152 data
->pasProvPrivData
= WINTRUST_ReAlloc(data
->pasProvPrivData
,
1153 (data
->csProvPrivData
+ 1) * sizeof(CRYPT_PROVIDER_SGNR
));
1156 data
->pasProvPrivData
= WINTRUST_Alloc(sizeof(CRYPT_PROVIDER_SGNR
));
1157 data
->csProvPrivData
= 0;
1159 if (data
->pasProvPrivData
)
1163 for (i
= 0; i
< data
->csProvPrivData
; i
++)
1164 if (IsEqualGUID(&pPrivData2Add
->gProviderID
, &data
->pasProvPrivData
[i
]))
1167 data
->pasProvPrivData
[i
] = *pPrivData2Add
;
1168 if (i
== data
->csProvPrivData
)
1169 data
->csProvPrivData
++;
1172 SetLastError(ERROR_OUTOFMEMORY
);
1176 /***********************************************************************
1177 * OpenPersonalTrustDBDialog (WINTRUST.@)
1179 * Opens the certificate manager dialog, showing only the stores that
1180 * contain trusted software publishers.
1183 * hwnd [I] handle of parent window
1186 * TRUE if the dialog could be opened, FALSE if not.
1188 BOOL WINAPI
OpenPersonalTrustDBDialog(HWND hwnd
)
1190 CRYPTUI_CERT_MGR_STRUCT uiCertMgr
;
1192 uiCertMgr
.dwSize
= sizeof(uiCertMgr
);
1193 uiCertMgr
.hwndParent
= hwnd
;
1194 uiCertMgr
.dwFlags
= CRYPTUI_CERT_MGR_PUBLISHER_TAB
;
1195 uiCertMgr
.pwszTitle
= NULL
;
1196 uiCertMgr
.pszInitUsageOID
= NULL
;
1197 return CryptUIDlgCertMgr(&uiCertMgr
);
1200 /***********************************************************************
1201 * WTHelperCertCheckValidSignature
1203 HRESULT WINAPI
WTHelperCertCheckValidSignature(CRYPT_PROVIDER_DATA
*pProvData
)
1209 /***********************************************************************
1212 BOOL WINAPI
IsCatalogFile(HANDLE hFile
, WCHAR
*pwszFileName
)
1214 static const GUID catGUID
= { 0xDE351A43, 0x8E59, 0x11D0, { 0x8C,0x47,0x00,0xC0,0x4F,0xC2,0x95,0xEE }};
1217 TRACE("(%p, %s)\n", hFile
, debugstr_w(pwszFileName
));
1219 if (!CryptSIPRetrieveSubjectGuid(pwszFileName
, hFile
, &guid
))
1221 return IsEqualGUID(&guid
, &catGUID
);
1224 /***********************************************************************
1227 HRESULT WINAPI
FindCertsByIssuer(PCERT_CHAIN pCertChains
, DWORD
*pcbCertChains
,
1228 DWORD
*pcCertChains
, BYTE
* pbEncodedIssuerName
, DWORD cbEncodedIssuerName
,
1229 LPCWSTR pwszPurpose
, DWORD dwKeySpec
)
1231 FIXME("(%p, %p, %p, %p, %d, %s, %d): stub\n", pCertChains
, pcbCertChains
,
1232 pcCertChains
, pbEncodedIssuerName
, cbEncodedIssuerName
,
1233 debugstr_w(pwszPurpose
), dwKeySpec
);