| /* | |
| * Copyright 2008 Maarten Lankhorst | |
| * | |
| * This library is free software; you can redistribute it and/or | |
| * modify it under the terms of the GNU Lesser General Public | |
| * License as published by the Free Software Foundation; either | |
| * version 2.1 of the License, or (at your option) any later version. | |
| * | |
| * This library is distributed in the hope that it will be useful, | |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
| * Lesser General Public License for more details. | |
| * | |
| * You should have received a copy of the GNU Lesser General Public | |
| * License along with this library; if not, write to the Free Software | |
| * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA | |
| */ | |
| #define NONAMELESSUNION | |
| #include "config.h" | |
| #include <stdarg.h> | |
| #include "windef.h" | |
| #include "winbase.h" | |
| #include "winnls.h" | |
| #include "winreg.h" | |
| #include "wincrypt.h" | |
| #include "wintrust.h" | |
| #include "winuser.h" | |
| #include "objbase.h" | |
| #include "cryptdlg.h" | |
| #include "cryptuiapi.h" | |
| #include "cryptres.h" | |
| #include "wine/unicode.h" | |
| #include "wine/debug.h" | |
| WINE_DEFAULT_DEBUG_CHANNEL(cryptdlg); | |
| static HINSTANCE hInstance; | |
| BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) | |
| { | |
| TRACE("(0x%p, %d, %p)\n", hinstDLL, fdwReason, lpvReserved); | |
| switch (fdwReason) | |
| { | |
| case DLL_WINE_PREATTACH: | |
| return FALSE; /* prefer native version */ | |
| case DLL_PROCESS_ATTACH: | |
| DisableThreadLibraryCalls(hinstDLL); | |
| hInstance = hinstDLL; | |
| break; | |
| } | |
| return TRUE; | |
| } | |
| /*********************************************************************** | |
| * GetFriendlyNameOfCertA (CRYPTDLG.@) | |
| */ | |
| DWORD WINAPI GetFriendlyNameOfCertA(PCCERT_CONTEXT pccert, LPSTR pchBuffer, | |
| DWORD cchBuffer) | |
| { | |
| return CertGetNameStringA(pccert, CERT_NAME_FRIENDLY_DISPLAY_TYPE, 0, NULL, | |
| pchBuffer, cchBuffer); | |
| } | |
| /*********************************************************************** | |
| * GetFriendlyNameOfCertW (CRYPTDLG.@) | |
| */ | |
| DWORD WINAPI GetFriendlyNameOfCertW(PCCERT_CONTEXT pccert, LPWSTR pchBuffer, | |
| DWORD cchBuffer) | |
| { | |
| return CertGetNameStringW(pccert, CERT_NAME_FRIENDLY_DISPLAY_TYPE, 0, NULL, | |
| pchBuffer, cchBuffer); | |
| } | |
| /*********************************************************************** | |
| * CertTrustInit (CRYPTDLG.@) | |
| */ | |
| HRESULT WINAPI CertTrustInit(CRYPT_PROVIDER_DATA *pProvData) | |
| { | |
| HRESULT ret = S_FALSE; | |
| TRACE("(%p)\n", pProvData); | |
| if (pProvData->padwTrustStepErrors && | |
| !pProvData->padwTrustStepErrors[TRUSTERROR_STEP_FINAL_WVTINIT]) | |
| ret = S_OK; | |
| TRACE("returning %08x\n", ret); | |
| return ret; | |
| } | |
| /*********************************************************************** | |
| * CertTrustCertPolicy (CRYPTDLG.@) | |
| */ | |
| BOOL WINAPI CertTrustCertPolicy(CRYPT_PROVIDER_DATA *pProvData, DWORD idxSigner, BOOL fCounterSignerChain, DWORD idxCounterSigner) | |
| { | |
| FIXME("(%p, %d, %s, %d)\n", pProvData, idxSigner, fCounterSignerChain ? "TRUE" : "FALSE", idxCounterSigner); | |
| return FALSE; | |
| } | |
| /*********************************************************************** | |
| * CertTrustCleanup (CRYPTDLG.@) | |
| */ | |
| HRESULT WINAPI CertTrustCleanup(CRYPT_PROVIDER_DATA *pProvData) | |
| { | |
| FIXME("(%p)\n", pProvData); | |
| return E_NOTIMPL; | |
| } | |
| static BOOL CRYPTDLG_CheckOnlineCRL(void) | |
| { | |
| static const WCHAR policyFlagsKey[] = { 'S','o','f','t','w','a','r','e', | |
| '\\','M','i','c','r','o','s','o','f','t','\\','C','r','y','p','t','o','g', | |
| 'r','a','p','h','y','\\','{','7','8','0','1','e','b','d','0','-','c','f', | |
| '4','b','-','1','1','d','0','-','8','5','1','f','-','0','0','6','0','9', | |
| '7','9','3','8','7','e','a','}',0 }; | |
| static const WCHAR policyFlags[] = { 'P','o','l','i','c','y','F','l','a', | |
| 'g','s',0 }; | |
| HKEY key; | |
| BOOL ret = FALSE; | |
| if (!RegOpenKeyExW(HKEY_LOCAL_MACHINE, policyFlagsKey, 0, KEY_READ, &key)) | |
| { | |
| DWORD type, flags, size = sizeof(flags); | |
| if (!RegQueryValueExW(key, policyFlags, NULL, &type, (BYTE *)&flags, | |
| &size) && type == REG_DWORD) | |
| { | |
| /* The flag values aren't defined in any header I'm aware of, but | |
| * this value is well documented on the net. | |
| */ | |
| if (flags & 0x00010000) | |
| ret = TRUE; | |
| } | |
| RegCloseKey(key); | |
| } | |
| return ret; | |
| } | |
| /* Returns TRUE if pCert is not in the Disallowed system store, or FALSE if it | |
| * is. | |
| */ | |
| static BOOL CRYPTDLG_IsCertAllowed(PCCERT_CONTEXT pCert) | |
| { | |
| BOOL ret; | |
| BYTE hash[20]; | |
| DWORD size = sizeof(hash); | |
| if ((ret = CertGetCertificateContextProperty(pCert, | |
| CERT_SIGNATURE_HASH_PROP_ID, hash, &size))) | |
| { | |
| static const WCHAR disallowedW[] = | |
| { 'D','i','s','a','l','l','o','w','e','d',0 }; | |
| HCERTSTORE disallowed = CertOpenStore(CERT_STORE_PROV_SYSTEM_W, | |
| X509_ASN_ENCODING, 0, CERT_SYSTEM_STORE_CURRENT_USER, disallowedW); | |
| if (disallowed) | |
| { | |
| PCCERT_CONTEXT found = CertFindCertificateInStore(disallowed, | |
| X509_ASN_ENCODING, 0, CERT_FIND_SIGNATURE_HASH, hash, NULL); | |
| if (found) | |
| { | |
| ret = FALSE; | |
| CertFreeCertificateContext(found); | |
| } | |
| CertCloseStore(disallowed, 0); | |
| } | |
| } | |
| return ret; | |
| } | |
| static DWORD CRYPTDLG_TrustStatusToConfidence(DWORD errorStatus) | |
| { | |
| DWORD confidence = 0; | |
| confidence = 0; | |
| if (!(errorStatus & CERT_TRUST_IS_NOT_SIGNATURE_VALID)) | |
| confidence |= CERT_CONFIDENCE_SIG; | |
| if (!(errorStatus & CERT_TRUST_IS_NOT_TIME_VALID)) | |
| confidence |= CERT_CONFIDENCE_TIME; | |
| if (!(errorStatus & CERT_TRUST_IS_NOT_TIME_NESTED)) | |
| confidence |= CERT_CONFIDENCE_TIMENEST; | |
| return confidence; | |
| } | |
| static BOOL CRYPTDLG_CopyChain(CRYPT_PROVIDER_DATA *data, | |
| PCCERT_CHAIN_CONTEXT chain) | |
| { | |
| BOOL ret; | |
| CRYPT_PROVIDER_SGNR signer; | |
| PCERT_SIMPLE_CHAIN simpleChain = chain->rgpChain[0]; | |
| DWORD i; | |
| memset(&signer, 0, sizeof(signer)); | |
| signer.cbStruct = sizeof(signer); | |
| ret = data->psPfns->pfnAddSgnr2Chain(data, FALSE, 0, &signer); | |
| if (ret) | |
| { | |
| CRYPT_PROVIDER_SGNR *sgnr = WTHelperGetProvSignerFromChain(data, 0, | |
| FALSE, 0); | |
| if (sgnr) | |
| { | |
| sgnr->dwError = simpleChain->TrustStatus.dwErrorStatus; | |
| sgnr->pChainContext = CertDuplicateCertificateChain(chain); | |
| } | |
| else | |
| ret = FALSE; | |
| for (i = 0; ret && i < simpleChain->cElement; i++) | |
| { | |
| ret = data->psPfns->pfnAddCert2Chain(data, 0, FALSE, 0, | |
| simpleChain->rgpElement[i]->pCertContext); | |
| if (ret) | |
| { | |
| CRYPT_PROVIDER_CERT *cert; | |
| if ((cert = WTHelperGetProvCertFromChain(sgnr, i))) | |
| { | |
| CERT_CHAIN_ELEMENT *element = simpleChain->rgpElement[i]; | |
| cert->dwConfidence = CRYPTDLG_TrustStatusToConfidence( | |
| element->TrustStatus.dwErrorStatus); | |
| cert->dwError = element->TrustStatus.dwErrorStatus; | |
| cert->pChainElement = element; | |
| } | |
| else | |
| ret = FALSE; | |
| } | |
| } | |
| } | |
| return ret; | |
| } | |
| static CERT_VERIFY_CERTIFICATE_TRUST *CRYPTDLG_GetVerifyData( | |
| CRYPT_PROVIDER_DATA *data) | |
| { | |
| CERT_VERIFY_CERTIFICATE_TRUST *pCert = NULL; | |
| /* This should always be true, but just in case the calling function is | |
| * called directly: | |
| */ | |
| if (data->pWintrustData->dwUnionChoice == WTD_CHOICE_BLOB && | |
| data->pWintrustData->u.pBlob && data->pWintrustData->u.pBlob->cbMemObject == | |
| sizeof(CERT_VERIFY_CERTIFICATE_TRUST) && | |
| data->pWintrustData->u.pBlob->pbMemObject) | |
| pCert = (CERT_VERIFY_CERTIFICATE_TRUST *) | |
| data->pWintrustData->u.pBlob->pbMemObject; | |
| return pCert; | |
| } | |
| static HCERTCHAINENGINE CRYPTDLG_MakeEngine(CERT_VERIFY_CERTIFICATE_TRUST *cert) | |
| { | |
| HCERTCHAINENGINE engine = NULL; | |
| HCERTSTORE root = NULL, trust = NULL; | |
| DWORD i; | |
| if (cert->cRootStores) | |
| { | |
| root = CertOpenStore(CERT_STORE_PROV_COLLECTION, 0, 0, | |
| CERT_STORE_CREATE_NEW_FLAG, NULL); | |
| if (root) | |
| { | |
| for (i = 0; i < cert->cRootStores; i++) | |
| CertAddStoreToCollection(root, cert->rghstoreRoots[i], 0, 0); | |
| } | |
| } | |
| if (cert->cTrustStores) | |
| { | |
| trust = CertOpenStore(CERT_STORE_PROV_COLLECTION, 0, 0, | |
| CERT_STORE_CREATE_NEW_FLAG, NULL); | |
| if (trust) | |
| { | |
| for (i = 0; i < cert->cTrustStores; i++) | |
| CertAddStoreToCollection(trust, cert->rghstoreTrust[i], 0, 0); | |
| } | |
| } | |
| if (cert->cRootStores || cert->cStores || cert->cTrustStores) | |
| { | |
| CERT_CHAIN_ENGINE_CONFIG config; | |
| memset(&config, 0, sizeof(config)); | |
| config.cbSize = sizeof(config); | |
| config.hRestrictedRoot = root; | |
| config.hRestrictedTrust = trust; | |
| config.cAdditionalStore = cert->cStores; | |
| config.rghAdditionalStore = cert->rghstoreCAs; | |
| config.hRestrictedRoot = root; | |
| CertCreateCertificateChainEngine(&config, &engine); | |
| CertCloseStore(root, 0); | |
| CertCloseStore(trust, 0); | |
| } | |
| return engine; | |
| } | |
| /*********************************************************************** | |
| * CertTrustFinalPolicy (CRYPTDLG.@) | |
| */ | |
| HRESULT WINAPI CertTrustFinalPolicy(CRYPT_PROVIDER_DATA *data) | |
| { | |
| BOOL ret; | |
| DWORD err = S_OK; | |
| CERT_VERIFY_CERTIFICATE_TRUST *pCert = CRYPTDLG_GetVerifyData(data); | |
| TRACE("(%p)\n", data); | |
| if (data->pWintrustData->dwUIChoice != WTD_UI_NONE) | |
| FIXME("unimplemented for UI choice %d\n", | |
| data->pWintrustData->dwUIChoice); | |
| if (pCert) | |
| { | |
| DWORD flags = 0; | |
| CERT_CHAIN_PARA chainPara; | |
| HCERTCHAINENGINE engine; | |
| memset(&chainPara, 0, sizeof(chainPara)); | |
| chainPara.cbSize = sizeof(chainPara); | |
| if (CRYPTDLG_CheckOnlineCRL()) | |
| flags |= CERT_CHAIN_REVOCATION_CHECK_END_CERT; | |
| engine = CRYPTDLG_MakeEngine(pCert); | |
| GetSystemTimeAsFileTime(&data->sftSystemTime); | |
| ret = CRYPTDLG_IsCertAllowed(pCert->pccert); | |
| if (ret) | |
| { | |
| PCCERT_CHAIN_CONTEXT chain; | |
| ret = CertGetCertificateChain(engine, pCert->pccert, | |
| &data->sftSystemTime, NULL, &chainPara, flags, NULL, &chain); | |
| if (ret) | |
| { | |
| if (chain->cChain != 1) | |
| { | |
| FIXME("unimplemented for more than 1 simple chain\n"); | |
| err = TRUST_E_SUBJECT_FORM_UNKNOWN; | |
| ret = FALSE; | |
| } | |
| else if ((ret = CRYPTDLG_CopyChain(data, chain))) | |
| { | |
| if (CertVerifyTimeValidity(&data->sftSystemTime, | |
| pCert->pccert->pCertInfo)) | |
| { | |
| ret = FALSE; | |
| err = CERT_E_EXPIRED; | |
| } | |
| } | |
| else | |
| err = TRUST_E_SYSTEM_ERROR; | |
| CertFreeCertificateChain(chain); | |
| } | |
| else | |
| err = TRUST_E_SUBJECT_NOT_TRUSTED; | |
| } | |
| CertFreeCertificateChainEngine(engine); | |
| } | |
| else | |
| { | |
| ret = FALSE; | |
| err = TRUST_E_NOSIGNATURE; | |
| } | |
| /* Oddly, native doesn't set the error in the trust step error location, | |
| * probably because this action is more advisory than anything else. | |
| * Instead it stores it as the final error, but the function "succeeds" in | |
| * any case. | |
| */ | |
| if (!ret) | |
| data->dwFinalError = err; | |
| TRACE("returning %d (%08x)\n", S_OK, data->dwFinalError); | |
| return S_OK; | |
| } | |
| /*********************************************************************** | |
| * CertViewPropertiesA (CRYPTDLG.@) | |
| */ | |
| BOOL WINAPI CertViewPropertiesA(CERT_VIEWPROPERTIES_STRUCT_A *info) | |
| { | |
| CERT_VIEWPROPERTIES_STRUCT_W infoW; | |
| LPWSTR title = NULL; | |
| BOOL ret; | |
| TRACE("(%p)\n", info); | |
| memcpy(&infoW, info, sizeof(infoW)); | |
| if (info->szTitle) | |
| { | |
| int len = MultiByteToWideChar(CP_ACP, 0, info->szTitle, -1, NULL, 0); | |
| title = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); | |
| if (title) | |
| { | |
| MultiByteToWideChar(CP_ACP, 0, info->szTitle, -1, title, len); | |
| infoW.szTitle = title; | |
| } | |
| else | |
| { | |
| ret = FALSE; | |
| goto error; | |
| } | |
| } | |
| ret = CertViewPropertiesW(&infoW); | |
| HeapFree(GetProcessHeap(), 0, title); | |
| error: | |
| return ret; | |
| } | |
| /*********************************************************************** | |
| * CertViewPropertiesW (CRYPTDLG.@) | |
| */ | |
| BOOL WINAPI CertViewPropertiesW(CERT_VIEWPROPERTIES_STRUCT_W *info) | |
| { | |
| static GUID cert_action_verify = CERT_CERTIFICATE_ACTION_VERIFY; | |
| CERT_VERIFY_CERTIFICATE_TRUST trust; | |
| WINTRUST_BLOB_INFO blob; | |
| WINTRUST_DATA wtd; | |
| LONG err; | |
| BOOL ret; | |
| TRACE("(%p)\n", info); | |
| memset(&trust, 0, sizeof(trust)); | |
| trust.cbSize = sizeof(trust); | |
| trust.pccert = info->pCertContext; | |
| trust.cRootStores = info->cRootStores; | |
| trust.rghstoreRoots = info->rghstoreRoots; | |
| trust.cStores = info->cStores; | |
| trust.rghstoreCAs = info->rghstoreCAs; | |
| trust.cTrustStores = info->cTrustStores; | |
| trust.rghstoreTrust = info->rghstoreTrust; | |
| memset(&blob, 0, sizeof(blob)); | |
| blob.cbStruct = sizeof(blob); | |
| blob.cbMemObject = sizeof(trust); | |
| blob.pbMemObject = (BYTE *)&trust; | |
| memset(&wtd, 0, sizeof(wtd)); | |
| wtd.cbStruct = sizeof(wtd); | |
| wtd.dwUIChoice = WTD_UI_NONE; | |
| wtd.dwUnionChoice = WTD_CHOICE_BLOB; | |
| wtd.u.pBlob = &blob; | |
| wtd.dwStateAction = WTD_STATEACTION_VERIFY; | |
| err = WinVerifyTrust(NULL, &cert_action_verify, &wtd); | |
| if (err == ERROR_SUCCESS) | |
| { | |
| CRYPTUI_VIEWCERTIFICATE_STRUCTW uiInfo; | |
| BOOL propsChanged = FALSE; | |
| memset(&uiInfo, 0, sizeof(uiInfo)); | |
| uiInfo.dwSize = sizeof(uiInfo); | |
| uiInfo.hwndParent = info->hwndParent; | |
| uiInfo.dwFlags = | |
| CRYPTUI_DISABLE_ADDTOSTORE | CRYPTUI_ENABLE_EDITPROPERTIES; | |
| uiInfo.szTitle = info->szTitle; | |
| uiInfo.pCertContext = info->pCertContext; | |
| uiInfo.cPurposes = info->cArrayPurposes; | |
| uiInfo.rgszPurposes = (LPCSTR *)info->arrayPurposes; | |
| uiInfo.u.hWVTStateData = wtd.hWVTStateData; | |
| uiInfo.fpCryptProviderDataTrustedUsage = TRUE; | |
| uiInfo.cPropSheetPages = info->cArrayPropSheetPages; | |
| uiInfo.rgPropSheetPages = info->arrayPropSheetPages; | |
| uiInfo.nStartPage = info->nStartPage; | |
| ret = CryptUIDlgViewCertificateW(&uiInfo, &propsChanged); | |
| wtd.dwStateAction = WTD_STATEACTION_CLOSE; | |
| WinVerifyTrust(NULL, &cert_action_verify, &wtd); | |
| } | |
| else | |
| ret = FALSE; | |
| return ret; | |
| } | |
| static BOOL CRYPT_FormatHexString(const BYTE *pbEncoded, DWORD cbEncoded, | |
| WCHAR *str, DWORD *pcchStr) | |
| { | |
| BOOL ret; | |
| DWORD charsNeeded; | |
| if (cbEncoded) | |
| charsNeeded = (cbEncoded * 3); | |
| else | |
| charsNeeded = 1; | |
| if (!str) | |
| { | |
| *pcchStr = charsNeeded; | |
| ret = TRUE; | |
| } | |
| else if (*pcchStr < charsNeeded) | |
| { | |
| *pcchStr = charsNeeded; | |
| SetLastError(ERROR_MORE_DATA); | |
| ret = FALSE; | |
| } | |
| else | |
| { | |
| static const WCHAR fmt[] = { '%','0','2','x',' ',0 }; | |
| static const WCHAR endFmt[] = { '%','0','2','x',0 }; | |
| DWORD i; | |
| LPWSTR ptr = str; | |
| *pcchStr = charsNeeded; | |
| if (cbEncoded) | |
| { | |
| for (i = 0; i < cbEncoded; i++) | |
| { | |
| if (i < cbEncoded - 1) | |
| ptr += sprintfW(ptr, fmt, pbEncoded[i]); | |
| else | |
| ptr += sprintfW(ptr, endFmt, pbEncoded[i]); | |
| } | |
| } | |
| else | |
| *ptr = 0; | |
| ret = TRUE; | |
| } | |
| return ret; | |
| } | |
| static const WCHAR indent[] = { ' ',' ',' ',' ',' ',0 }; | |
| static const WCHAR colonCrlf[] = { ':','\r','\n',0 }; | |
| static const WCHAR colonSpace[] = { ':',' ',0 }; | |
| static const WCHAR crlf[] = { '\r','\n',0 }; | |
| static const WCHAR commaSep[] = { ',',' ',0 }; | |
| static BOOL CRYPT_FormatCPS(DWORD dwCertEncodingType, | |
| DWORD dwFormatStrType, const BYTE *pbEncoded, DWORD cbEncoded, | |
| WCHAR *str, DWORD *pcchStr) | |
| { | |
| BOOL ret; | |
| DWORD size, charsNeeded = 1; | |
| CERT_NAME_VALUE *cpsValue; | |
| if ((ret = CryptDecodeObjectEx(dwCertEncodingType, X509_UNICODE_ANY_STRING, | |
| pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL, &cpsValue, &size))) | |
| { | |
| LPCWSTR sep; | |
| DWORD sepLen; | |
| if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE) | |
| sep = crlf; | |
| else | |
| sep = commaSep; | |
| sepLen = strlenW(sep); | |
| if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE) | |
| { | |
| charsNeeded += 3 * strlenW(indent); | |
| if (str && *pcchStr >= charsNeeded) | |
| { | |
| strcpyW(str, indent); | |
| str += strlenW(indent); | |
| strcpyW(str, indent); | |
| str += strlenW(indent); | |
| strcpyW(str, indent); | |
| str += strlenW(indent); | |
| } | |
| } | |
| charsNeeded += cpsValue->Value.cbData / sizeof(WCHAR); | |
| if (str && *pcchStr >= charsNeeded) | |
| { | |
| strcpyW(str, (LPWSTR)cpsValue->Value.pbData); | |
| str += cpsValue->Value.cbData / sizeof(WCHAR); | |
| } | |
| charsNeeded += sepLen; | |
| if (str && *pcchStr >= charsNeeded) | |
| { | |
| strcpyW(str, sep); | |
| str += sepLen; | |
| } | |
| LocalFree(cpsValue); | |
| if (!str) | |
| *pcchStr = charsNeeded; | |
| else if (*pcchStr < charsNeeded) | |
| { | |
| *pcchStr = charsNeeded; | |
| SetLastError(ERROR_MORE_DATA); | |
| ret = FALSE; | |
| } | |
| else | |
| *pcchStr = charsNeeded; | |
| } | |
| return ret; | |
| } | |
| static BOOL CRYPT_FormatUserNotice(DWORD dwCertEncodingType, | |
| DWORD dwFormatStrType, const BYTE *pbEncoded, DWORD cbEncoded, | |
| WCHAR *str, DWORD *pcchStr) | |
| { | |
| BOOL ret; | |
| DWORD size, charsNeeded = 1; | |
| CERT_POLICY_QUALIFIER_USER_NOTICE *notice; | |
| if ((ret = CryptDecodeObjectEx(dwCertEncodingType, | |
| X509_PKIX_POLICY_QUALIFIER_USERNOTICE, pbEncoded, cbEncoded, | |
| CRYPT_DECODE_ALLOC_FLAG, NULL, ¬ice, &size))) | |
| { | |
| static const WCHAR numFmt[] = { '%','d',0 }; | |
| CERT_POLICY_QUALIFIER_NOTICE_REFERENCE *pNoticeRef = | |
| notice->pNoticeReference; | |
| LPCWSTR headingSep, sep; | |
| DWORD headingSepLen, sepLen; | |
| LPWSTR noticeRef, organization, noticeNum, noticeText; | |
| DWORD noticeRefLen, organizationLen, noticeNumLen, noticeTextLen; | |
| WCHAR noticeNumStr[11]; | |
| noticeRefLen = LoadStringW(hInstance, IDS_NOTICE_REF, | |
| (LPWSTR)¬iceRef, 0); | |
| organizationLen = LoadStringW(hInstance, IDS_ORGANIZATION, | |
| (LPWSTR)&organization, 0); | |
| noticeNumLen = LoadStringW(hInstance, IDS_NOTICE_NUM, | |
| (LPWSTR)¬iceNum, 0); | |
| noticeTextLen = LoadStringW(hInstance, IDS_NOTICE_TEXT, | |
| (LPWSTR)¬iceText, 0); | |
| if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE) | |
| { | |
| headingSep = colonCrlf; | |
| sep = crlf; | |
| } | |
| else | |
| { | |
| headingSep = colonSpace; | |
| sep = commaSep; | |
| } | |
| sepLen = strlenW(sep); | |
| headingSepLen = strlenW(headingSep); | |
| if (pNoticeRef) | |
| { | |
| DWORD k; | |
| LPCSTR src; | |
| if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE) | |
| { | |
| charsNeeded += 3 * strlenW(indent); | |
| if (str && *pcchStr >= charsNeeded) | |
| { | |
| strcpyW(str, indent); | |
| str += strlenW(indent); | |
| strcpyW(str, indent); | |
| str += strlenW(indent); | |
| strcpyW(str, indent); | |
| str += strlenW(indent); | |
| } | |
| } | |
| charsNeeded += noticeRefLen; | |
| if (str && *pcchStr >= charsNeeded) | |
| { | |
| memcpy(str, noticeRef, noticeRefLen * sizeof(WCHAR)); | |
| str += noticeRefLen; | |
| } | |
| charsNeeded += headingSepLen; | |
| if (str && *pcchStr >= charsNeeded) | |
| { | |
| strcpyW(str, headingSep); | |
| str += headingSepLen; | |
| } | |
| if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE) | |
| { | |
| charsNeeded += 4 * strlenW(indent); | |
| if (str && *pcchStr >= charsNeeded) | |
| { | |
| strcpyW(str, indent); | |
| str += strlenW(indent); | |
| strcpyW(str, indent); | |
| str += strlenW(indent); | |
| strcpyW(str, indent); | |
| str += strlenW(indent); | |
| strcpyW(str, indent); | |
| str += strlenW(indent); | |
| } | |
| } | |
| charsNeeded += organizationLen; | |
| if (str && *pcchStr >= charsNeeded) | |
| { | |
| memcpy(str, organization, organizationLen * sizeof(WCHAR)); | |
| str += organizationLen; | |
| } | |
| charsNeeded += strlen(pNoticeRef->pszOrganization); | |
| if (str && *pcchStr >= charsNeeded) | |
| for (src = pNoticeRef->pszOrganization; src && *src; | |
| src++, str++) | |
| *str = *src; | |
| charsNeeded += sepLen; | |
| if (str && *pcchStr >= charsNeeded) | |
| { | |
| strcpyW(str, sep); | |
| str += sepLen; | |
| } | |
| for (k = 0; k < pNoticeRef->cNoticeNumbers; k++) | |
| { | |
| if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE) | |
| { | |
| charsNeeded += 4 * strlenW(indent); | |
| if (str && *pcchStr >= charsNeeded) | |
| { | |
| strcpyW(str, indent); | |
| str += strlenW(indent); | |
| strcpyW(str, indent); | |
| str += strlenW(indent); | |
| strcpyW(str, indent); | |
| str += strlenW(indent); | |
| strcpyW(str, indent); | |
| str += strlenW(indent); | |
| } | |
| } | |
| charsNeeded += noticeNumLen; | |
| if (str && *pcchStr >= charsNeeded) | |
| { | |
| memcpy(str, noticeNum, noticeNumLen * sizeof(WCHAR)); | |
| str += noticeNumLen; | |
| } | |
| sprintfW(noticeNumStr, numFmt, k + 1); | |
| charsNeeded += strlenW(noticeNumStr); | |
| if (str && *pcchStr >= charsNeeded) | |
| { | |
| strcpyW(str, noticeNumStr); | |
| str += strlenW(noticeNumStr); | |
| } | |
| charsNeeded += sepLen; | |
| if (str && *pcchStr >= charsNeeded) | |
| { | |
| strcpyW(str, sep); | |
| str += sepLen; | |
| } | |
| } | |
| } | |
| if (notice->pszDisplayText) | |
| { | |
| if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE) | |
| { | |
| charsNeeded += 3 * strlenW(indent); | |
| if (str && *pcchStr >= charsNeeded) | |
| { | |
| strcpyW(str, indent); | |
| str += strlenW(indent); | |
| strcpyW(str, indent); | |
| str += strlenW(indent); | |
| strcpyW(str, indent); | |
| str += strlenW(indent); | |
| } | |
| } | |
| charsNeeded += noticeTextLen; | |
| if (str && *pcchStr >= charsNeeded) | |
| { | |
| memcpy(str, noticeText, noticeTextLen * sizeof(WCHAR)); | |
| str += noticeTextLen; | |
| } | |
| charsNeeded += strlenW(notice->pszDisplayText); | |
| if (str && *pcchStr >= charsNeeded) | |
| { | |
| strcpyW(str, notice->pszDisplayText); | |
| str += strlenW(notice->pszDisplayText); | |
| } | |
| charsNeeded += sepLen; | |
| if (str && *pcchStr >= charsNeeded) | |
| { | |
| strcpyW(str, sep); | |
| str += sepLen; | |
| } | |
| } | |
| LocalFree(notice); | |
| if (!str) | |
| *pcchStr = charsNeeded; | |
| else if (*pcchStr < charsNeeded) | |
| { | |
| *pcchStr = charsNeeded; | |
| SetLastError(ERROR_MORE_DATA); | |
| ret = FALSE; | |
| } | |
| else | |
| *pcchStr = charsNeeded; | |
| } | |
| return ret; | |
| } | |
| /*********************************************************************** | |
| * FormatVerisignExtension (CRYPTDLG.@) | |
| */ | |
| BOOL WINAPI FormatVerisignExtension(DWORD dwCertEncodingType, | |
| DWORD dwFormatType, DWORD dwFormatStrType, void *pFormatStruct, | |
| LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, void *pbFormat, | |
| DWORD *pcbFormat) | |
| { | |
| CERT_POLICIES_INFO *policies; | |
| DWORD size; | |
| BOOL ret = FALSE; | |
| if (!cbEncoded) | |
| { | |
| SetLastError(E_INVALIDARG); | |
| return FALSE; | |
| } | |
| if ((ret = CryptDecodeObjectEx(dwCertEncodingType, X509_CERT_POLICIES, | |
| pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL, &policies, &size))) | |
| { | |
| static const WCHAR numFmt[] = { '%','d',0 }; | |
| DWORD charsNeeded = 1; /* space for NULL terminator */ | |
| LPCWSTR headingSep, sep; | |
| DWORD headingSepLen, sepLen; | |
| WCHAR policyNum[11], policyQualifierNum[11]; | |
| LPWSTR certPolicy, policyId, policyQualifierInfo, policyQualifierId; | |
| LPWSTR cps, userNotice, qualifier; | |
| DWORD certPolicyLen, policyIdLen, policyQualifierInfoLen; | |
| DWORD policyQualifierIdLen, cpsLen, userNoticeLen, qualifierLen; | |
| DWORD i; | |
| LPWSTR str = pbFormat; | |
| certPolicyLen = LoadStringW(hInstance, IDS_CERT_POLICY, | |
| (LPWSTR)&certPolicy, 0); | |
| policyIdLen = LoadStringW(hInstance, IDS_POLICY_ID, (LPWSTR)&policyId, | |
| 0); | |
| policyQualifierInfoLen = LoadStringW(hInstance, | |
| IDS_POLICY_QUALIFIER_INFO, (LPWSTR)&policyQualifierInfo, 0); | |
| policyQualifierIdLen = LoadStringW(hInstance, IDS_POLICY_QUALIFIER_ID, | |
| (LPWSTR)&policyQualifierId, 0); | |
| cpsLen = LoadStringW(hInstance, IDS_CPS, (LPWSTR)&cps, 0); | |
| userNoticeLen = LoadStringW(hInstance, IDS_USER_NOTICE, | |
| (LPWSTR)&userNotice, 0); | |
| qualifierLen = LoadStringW(hInstance, IDS_QUALIFIER, | |
| (LPWSTR)&qualifier, 0); | |
| if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE) | |
| { | |
| headingSep = colonCrlf; | |
| sep = crlf; | |
| } | |
| else | |
| { | |
| headingSep = colonSpace; | |
| sep = commaSep; | |
| } | |
| sepLen = strlenW(sep); | |
| headingSepLen = strlenW(headingSep); | |
| for (i = 0; ret && i < policies->cPolicyInfo; i++) | |
| { | |
| CERT_POLICY_INFO *policy = &policies->rgPolicyInfo[i]; | |
| DWORD j; | |
| LPCSTR src; | |
| charsNeeded += 1; /* '['*/ | |
| if (str && *pcbFormat >= charsNeeded * sizeof(WCHAR)) | |
| *str++ = '['; | |
| sprintfW(policyNum, numFmt, i + 1); | |
| charsNeeded += strlenW(policyNum); | |
| if (str && *pcbFormat >= charsNeeded * sizeof(WCHAR)) | |
| { | |
| strcpyW(str, policyNum); | |
| str += strlenW(policyNum); | |
| } | |
| charsNeeded += 1; /* ']'*/ | |
| if (str && *pcbFormat >= charsNeeded * sizeof(WCHAR)) | |
| *str++ = ']'; | |
| charsNeeded += certPolicyLen; | |
| if (str && *pcbFormat >= charsNeeded * sizeof(WCHAR)) | |
| { | |
| memcpy(str, certPolicy, certPolicyLen * sizeof(WCHAR)); | |
| str += certPolicyLen; | |
| } | |
| charsNeeded += headingSepLen; | |
| if (str && *pcbFormat >= charsNeeded * sizeof(WCHAR)) | |
| { | |
| strcpyW(str, headingSep); | |
| str += headingSepLen; | |
| } | |
| if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE) | |
| { | |
| charsNeeded += strlenW(indent); | |
| if (str && *pcbFormat >= charsNeeded * sizeof(WCHAR)) | |
| { | |
| strcpyW(str, indent); | |
| str += strlenW(indent); | |
| } | |
| } | |
| charsNeeded += policyIdLen; | |
| if (str && *pcbFormat >= charsNeeded * sizeof(WCHAR)) | |
| { | |
| memcpy(str, policyId, policyIdLen * sizeof(WCHAR)); | |
| str += policyIdLen; | |
| } | |
| charsNeeded += strlen(policy->pszPolicyIdentifier); | |
| if (str && *pcbFormat >= charsNeeded * sizeof(WCHAR)) | |
| { | |
| for (src = policy->pszPolicyIdentifier; src && *src; | |
| src++, str++) | |
| *str = *src; | |
| } | |
| charsNeeded += sepLen; | |
| if (str && *pcbFormat >= charsNeeded * sizeof(WCHAR)) | |
| { | |
| strcpyW(str, sep); | |
| str += sepLen; | |
| } | |
| for (j = 0; j < policy->cPolicyQualifier; j++) | |
| { | |
| CERT_POLICY_QUALIFIER_INFO *qualifierInfo = | |
| &policy->rgPolicyQualifier[j]; | |
| DWORD sizeRemaining; | |
| if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE) | |
| { | |
| charsNeeded += strlenW(indent); | |
| if (str && *pcbFormat >= charsNeeded * sizeof(WCHAR)) | |
| { | |
| strcpyW(str, indent); | |
| str += strlenW(indent); | |
| } | |
| } | |
| charsNeeded += 1; /* '['*/ | |
| if (str && *pcbFormat >= charsNeeded * sizeof(WCHAR)) | |
| *str++ = '['; | |
| charsNeeded += strlenW(policyNum); | |
| if (str && *pcbFormat >= charsNeeded * sizeof(WCHAR)) | |
| { | |
| strcpyW(str, policyNum); | |
| str += strlenW(policyNum); | |
| } | |
| charsNeeded += 1; /* ','*/ | |
| if (str && *pcbFormat >= charsNeeded * sizeof(WCHAR)) | |
| *str++ = ','; | |
| sprintfW(policyQualifierNum, numFmt, j + 1); | |
| charsNeeded += strlenW(policyQualifierNum); | |
| if (str && *pcbFormat >= charsNeeded * sizeof(WCHAR)) | |
| { | |
| strcpyW(str, policyQualifierNum); | |
| str += strlenW(policyQualifierNum); | |
| } | |
| charsNeeded += 1; /* ']'*/ | |
| if (str && *pcbFormat >= charsNeeded * sizeof(WCHAR)) | |
| *str++ = ']'; | |
| charsNeeded += policyQualifierInfoLen; | |
| if (str && *pcbFormat >= charsNeeded * sizeof(WCHAR)) | |
| { | |
| memcpy(str, policyQualifierInfo, | |
| policyQualifierInfoLen * sizeof(WCHAR)); | |
| str += policyQualifierInfoLen; | |
| } | |
| charsNeeded += headingSepLen; | |
| if (str && *pcbFormat >= charsNeeded * sizeof(WCHAR)) | |
| { | |
| strcpyW(str, headingSep); | |
| str += headingSepLen; | |
| } | |
| if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE) | |
| { | |
| charsNeeded += 2 * strlenW(indent); | |
| if (str && *pcbFormat >= charsNeeded * sizeof(WCHAR)) | |
| { | |
| strcpyW(str, indent); | |
| str += strlenW(indent); | |
| strcpyW(str, indent); | |
| str += strlenW(indent); | |
| } | |
| } | |
| charsNeeded += policyQualifierIdLen; | |
| if (str && *pcbFormat >= charsNeeded * sizeof(WCHAR)) | |
| { | |
| memcpy(str, policyQualifierId, | |
| policyQualifierIdLen * sizeof(WCHAR)); | |
| str += policyQualifierIdLen; | |
| } | |
| if (!strcmp(qualifierInfo->pszPolicyQualifierId, | |
| szOID_PKIX_POLICY_QUALIFIER_CPS)) | |
| { | |
| charsNeeded += cpsLen; | |
| if (str && *pcbFormat >= charsNeeded * sizeof(WCHAR)) | |
| { | |
| memcpy(str, cps, cpsLen * sizeof(WCHAR)); | |
| str += cpsLen; | |
| } | |
| } | |
| else if (!strcmp(qualifierInfo->pszPolicyQualifierId, | |
| szOID_PKIX_POLICY_QUALIFIER_USERNOTICE)) | |
| { | |
| charsNeeded += userNoticeLen; | |
| if (str && *pcbFormat >= charsNeeded * sizeof(WCHAR)) | |
| { | |
| memcpy(str, userNotice, userNoticeLen * sizeof(WCHAR)); | |
| str += userNoticeLen; | |
| } | |
| } | |
| else | |
| { | |
| charsNeeded += strlen(qualifierInfo->pszPolicyQualifierId); | |
| if (str && *pcbFormat >= charsNeeded * sizeof(WCHAR)) | |
| { | |
| for (src = qualifierInfo->pszPolicyQualifierId; | |
| src && *src; src++, str++) | |
| *str = *src; | |
| } | |
| } | |
| charsNeeded += sepLen; | |
| if (str && *pcbFormat >= charsNeeded * sizeof(WCHAR)) | |
| { | |
| strcpyW(str, sep); | |
| str += sepLen; | |
| } | |
| if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE) | |
| { | |
| charsNeeded += 2 * strlenW(indent); | |
| if (str && *pcbFormat >= charsNeeded * sizeof(WCHAR)) | |
| { | |
| strcpyW(str, indent); | |
| str += strlenW(indent); | |
| strcpyW(str, indent); | |
| str += strlenW(indent); | |
| } | |
| } | |
| charsNeeded += qualifierLen; | |
| if (str && *pcbFormat >= charsNeeded * sizeof(WCHAR)) | |
| { | |
| memcpy(str, qualifier, qualifierLen * sizeof(WCHAR)); | |
| str += qualifierLen; | |
| } | |
| charsNeeded += headingSepLen; | |
| if (str && *pcbFormat >= charsNeeded * sizeof(WCHAR)) | |
| { | |
| strcpyW(str, headingSep); | |
| str += headingSepLen; | |
| } | |
| /* This if block is deliberately redundant with the same if | |
| * block above, in order to keep the code more readable (the | |
| * code flow follows the order in which the strings are output.) | |
| */ | |
| if (!strcmp(qualifierInfo->pszPolicyQualifierId, | |
| szOID_PKIX_POLICY_QUALIFIER_CPS)) | |
| { | |
| if (!str || *pcbFormat < charsNeeded * sizeof(WCHAR)) | |
| { | |
| /* Insufficient space, determine how much is needed. */ | |
| ret = CRYPT_FormatCPS(dwCertEncodingType, | |
| dwFormatStrType, qualifierInfo->Qualifier.pbData, | |
| qualifierInfo->Qualifier.cbData, NULL, &size); | |
| if (ret) | |
| charsNeeded += size - 1; | |
| } | |
| else | |
| { | |
| sizeRemaining = *pcbFormat / sizeof(WCHAR); | |
| sizeRemaining -= str - (LPWSTR)pbFormat; | |
| ret = CRYPT_FormatCPS(dwCertEncodingType, | |
| dwFormatStrType, qualifierInfo->Qualifier.pbData, | |
| qualifierInfo->Qualifier.cbData, str, &sizeRemaining); | |
| if (ret || GetLastError() == ERROR_MORE_DATA) | |
| { | |
| charsNeeded += sizeRemaining - 1; | |
| str += sizeRemaining - 1; | |
| } | |
| } | |
| } | |
| else if (!strcmp(qualifierInfo->pszPolicyQualifierId, | |
| szOID_PKIX_POLICY_QUALIFIER_USERNOTICE)) | |
| { | |
| if (!str || *pcbFormat < charsNeeded * sizeof(WCHAR)) | |
| { | |
| /* Insufficient space, determine how much is needed. */ | |
| ret = CRYPT_FormatUserNotice(dwCertEncodingType, | |
| dwFormatStrType, qualifierInfo->Qualifier.pbData, | |
| qualifierInfo->Qualifier.cbData, NULL, &size); | |
| if (ret) | |
| charsNeeded += size - 1; | |
| } | |
| else | |
| { | |
| sizeRemaining = *pcbFormat / sizeof(WCHAR); | |
| sizeRemaining -= str - (LPWSTR)pbFormat; | |
| ret = CRYPT_FormatUserNotice(dwCertEncodingType, | |
| dwFormatStrType, qualifierInfo->Qualifier.pbData, | |
| qualifierInfo->Qualifier.cbData, str, &sizeRemaining); | |
| if (ret || GetLastError() == ERROR_MORE_DATA) | |
| { | |
| charsNeeded += sizeRemaining - 1; | |
| str += sizeRemaining - 1; | |
| } | |
| } | |
| } | |
| else | |
| { | |
| if (!str || *pcbFormat < charsNeeded * sizeof(WCHAR)) | |
| { | |
| /* Insufficient space, determine how much is needed. */ | |
| ret = CRYPT_FormatHexString( | |
| qualifierInfo->Qualifier.pbData, | |
| qualifierInfo->Qualifier.cbData, NULL, &size); | |
| if (ret) | |
| charsNeeded += size - 1; | |
| } | |
| else | |
| { | |
| sizeRemaining = *pcbFormat / sizeof(WCHAR); | |
| sizeRemaining -= str - (LPWSTR)pbFormat; | |
| ret = CRYPT_FormatHexString( | |
| qualifierInfo->Qualifier.pbData, | |
| qualifierInfo->Qualifier.cbData, str, &sizeRemaining); | |
| if (ret || GetLastError() == ERROR_MORE_DATA) | |
| { | |
| charsNeeded += sizeRemaining - 1; | |
| str += sizeRemaining - 1; | |
| } | |
| } | |
| } | |
| } | |
| } | |
| LocalFree(policies); | |
| if (ret) | |
| { | |
| if (!pbFormat) | |
| *pcbFormat = charsNeeded * sizeof(WCHAR); | |
| else if (*pcbFormat < charsNeeded * sizeof(WCHAR)) | |
| { | |
| *pcbFormat = charsNeeded * sizeof(WCHAR); | |
| SetLastError(ERROR_MORE_DATA); | |
| ret = FALSE; | |
| } | |
| else | |
| *pcbFormat = charsNeeded * sizeof(WCHAR); | |
| } | |
| } | |
| return ret; | |
| } | |
| #define szOID_MICROSOFT_Encryption_Key_Preference "1.3.6.1.4.1.311.16.4" | |
| /*********************************************************************** | |
| * DllRegisterServer (CRYPTDLG.@) | |
| */ | |
| HRESULT WINAPI DllRegisterServer(void) | |
| { | |
| static WCHAR cryptdlg[] = { 'c','r','y','p','t','d','l','g','.', | |
| 'd','l','l',0 }; | |
| static WCHAR wintrust[] = { 'w','i','n','t','r','u','s','t','.', | |
| 'd','l','l',0 }; | |
| static WCHAR certTrustInit[] = { 'C','e','r','t','T','r','u','s','t', | |
| 'I','n','i','t',0 }; | |
| static WCHAR wintrustCertificateTrust[] = { 'W','i','n','t','r','u','s','t', | |
| 'C','e','r','t','i','f','i','c','a','t','e','T','r','u','s','t',0 }; | |
| static WCHAR certTrustCertPolicy[] = { 'C','e','r','t','T','r','u','s','t', | |
| 'C','e','r','t','P','o','l','i','c','y',0 }; | |
| static WCHAR certTrustFinalPolicy[] = { 'C','e','r','t','T','r','u','s','t', | |
| 'F','i','n','a','l','P','o','l','i','c','y',0 }; | |
| static WCHAR certTrustCleanup[] = { 'C','e','r','t','T','r','u','s','t', | |
| 'C','l','e','a','n','u','p',0 }; | |
| static const WCHAR cryptDlg[] = { 'c','r','y','p','t','d','l','g','.', | |
| 'd','l','l',0 }; | |
| CRYPT_REGISTER_ACTIONID reg; | |
| GUID guid = CERT_CERTIFICATE_ACTION_VERIFY; | |
| HRESULT hr = S_OK; | |
| memset(®, 0, sizeof(reg)); | |
| reg.cbStruct = sizeof(reg); | |
| reg.sInitProvider.cbStruct = sizeof(CRYPT_TRUST_REG_ENTRY); | |
| reg.sInitProvider.pwszDLLName = cryptdlg; | |
| reg.sInitProvider.pwszFunctionName = certTrustInit; | |
| reg.sCertificateProvider.cbStruct = sizeof(CRYPT_TRUST_REG_ENTRY); | |
| reg.sCertificateProvider.pwszDLLName = wintrust; | |
| reg.sCertificateProvider.pwszFunctionName = wintrustCertificateTrust; | |
| reg.sCertificatePolicyProvider.cbStruct = sizeof(CRYPT_TRUST_REG_ENTRY); | |
| reg.sCertificatePolicyProvider.pwszDLLName = cryptdlg; | |
| reg.sCertificatePolicyProvider.pwszFunctionName = certTrustCertPolicy; | |
| reg.sFinalPolicyProvider.cbStruct = sizeof(CRYPT_TRUST_REG_ENTRY); | |
| reg.sFinalPolicyProvider.pwszDLLName = cryptdlg; | |
| reg.sFinalPolicyProvider.pwszFunctionName = certTrustFinalPolicy; | |
| reg.sCleanupProvider.cbStruct = sizeof(CRYPT_TRUST_REG_ENTRY); | |
| reg.sCleanupProvider.pwszDLLName = cryptdlg; | |
| reg.sCleanupProvider.pwszFunctionName = certTrustCleanup; | |
| if (!WintrustAddActionID(&guid, WT_ADD_ACTION_ID_RET_RESULT_FLAG, ®)) | |
| hr = GetLastError(); | |
| CryptRegisterOIDFunction(X509_ASN_ENCODING, CRYPT_OID_ENCODE_OBJECT_FUNC, | |
| "1.3.6.1.4.1.311.16.1.1", cryptDlg, "EncodeAttrSequence"); | |
| CryptRegisterOIDFunction(X509_ASN_ENCODING, CRYPT_OID_ENCODE_OBJECT_FUNC, | |
| szOID_MICROSOFT_Encryption_Key_Preference, cryptDlg, "EncodeRecipientID"); | |
| CryptRegisterOIDFunction(X509_ASN_ENCODING, CRYPT_OID_DECODE_OBJECT_FUNC, | |
| "1.3.6.1.4.1.311.16.1.1", cryptDlg, "DecodeAttrSequence"); | |
| CryptRegisterOIDFunction(X509_ASN_ENCODING, CRYPT_OID_DECODE_OBJECT_FUNC, | |
| szOID_MICROSOFT_Encryption_Key_Preference, cryptDlg, "DecodeRecipientID"); | |
| CryptRegisterOIDFunction(X509_ASN_ENCODING, CRYPT_OID_FORMAT_OBJECT_FUNC, | |
| szOID_PKIX_KP_EMAIL_PROTECTION, cryptDlg, "FormatPKIXEmailProtection"); | |
| CryptRegisterOIDFunction(X509_ASN_ENCODING, CRYPT_OID_FORMAT_OBJECT_FUNC, | |
| szOID_CERT_POLICIES, cryptDlg, "FormatVerisignExtension"); | |
| return hr; | |
| } | |
| /*********************************************************************** | |
| * DllUnregisterServer (CRYPTDLG.@) | |
| */ | |
| HRESULT WINAPI DllUnregisterServer(void) | |
| { | |
| GUID guid = CERT_CERTIFICATE_ACTION_VERIFY; | |
| WintrustRemoveActionID(&guid); | |
| CryptUnregisterOIDFunction(X509_ASN_ENCODING, CRYPT_OID_ENCODE_OBJECT_FUNC, | |
| "1.3.6.1.4.1.311.16.1.1"); | |
| CryptUnregisterOIDFunction(X509_ASN_ENCODING, CRYPT_OID_ENCODE_OBJECT_FUNC, | |
| szOID_MICROSOFT_Encryption_Key_Preference); | |
| CryptUnregisterOIDFunction(X509_ASN_ENCODING, CRYPT_OID_DECODE_OBJECT_FUNC, | |
| "1.3.6.1.4.1.311.16.1.1"); | |
| CryptUnregisterOIDFunction(X509_ASN_ENCODING, CRYPT_OID_DECODE_OBJECT_FUNC, | |
| szOID_MICROSOFT_Encryption_Key_Preference); | |
| CryptUnregisterOIDFunction(X509_ASN_ENCODING, CRYPT_OID_FORMAT_OBJECT_FUNC, | |
| szOID_PKIX_KP_EMAIL_PROTECTION); | |
| CryptUnregisterOIDFunction(X509_ASN_ENCODING, CRYPT_OID_FORMAT_OBJECT_FUNC, | |
| szOID_CERT_POLICIES); | |
| return S_OK; | |
| } |