2 * Copyright 2008 Maarten Lankhorst
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.
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.
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
19 #define NONAMELESSUNION
32 #include "cryptuiapi.h"
34 #include "wine/debug.h"
36 WINE_DEFAULT_DEBUG_CHANNEL(cryptdlg
);
38 static HINSTANCE hInstance
;
40 BOOL WINAPI
DllMain(HINSTANCE hinstDLL
, DWORD fdwReason
, LPVOID lpvReserved
)
42 TRACE("(0x%p, %ld, %p)\n", hinstDLL
, fdwReason
, lpvReserved
);
46 case DLL_PROCESS_ATTACH
:
47 DisableThreadLibraryCalls(hinstDLL
);
54 /***********************************************************************
55 * GetFriendlyNameOfCertA (CRYPTDLG.@)
57 DWORD WINAPI
GetFriendlyNameOfCertA(PCCERT_CONTEXT pccert
, LPSTR pchBuffer
,
60 return CertGetNameStringA(pccert
, CERT_NAME_FRIENDLY_DISPLAY_TYPE
, 0, NULL
,
61 pchBuffer
, cchBuffer
);
64 /***********************************************************************
65 * GetFriendlyNameOfCertW (CRYPTDLG.@)
67 DWORD WINAPI
GetFriendlyNameOfCertW(PCCERT_CONTEXT pccert
, LPWSTR pchBuffer
,
70 return CertGetNameStringW(pccert
, CERT_NAME_FRIENDLY_DISPLAY_TYPE
, 0, NULL
,
71 pchBuffer
, cchBuffer
);
74 /***********************************************************************
75 * CertTrustInit (CRYPTDLG.@)
77 HRESULT WINAPI
CertTrustInit(CRYPT_PROVIDER_DATA
*pProvData
)
79 HRESULT ret
= S_FALSE
;
81 TRACE("(%p)\n", pProvData
);
83 if (pProvData
->padwTrustStepErrors
&&
84 !pProvData
->padwTrustStepErrors
[TRUSTERROR_STEP_FINAL_WVTINIT
])
86 TRACE("returning %08lx\n", ret
);
90 /***********************************************************************
91 * CertTrustCertPolicy (CRYPTDLG.@)
93 BOOL WINAPI
CertTrustCertPolicy(CRYPT_PROVIDER_DATA
*pProvData
, DWORD idxSigner
, BOOL fCounterSignerChain
, DWORD idxCounterSigner
)
95 FIXME("(%p, %ld, %s, %ld)\n", pProvData
, idxSigner
, fCounterSignerChain
? "TRUE" : "FALSE", idxCounterSigner
);
99 /***********************************************************************
100 * CertTrustCleanup (CRYPTDLG.@)
102 HRESULT WINAPI
CertTrustCleanup(CRYPT_PROVIDER_DATA
*pProvData
)
104 FIXME("(%p)\n", pProvData
);
108 static BOOL
CRYPTDLG_CheckOnlineCRL(void)
113 if (!RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
114 L
"Software\\Microsoft\\Cryptography\\{7801ebd0-cf4b-11d0-851f-0060979387ea}", 0, KEY_READ
, &key
))
116 DWORD type
, flags
, size
= sizeof(flags
);
118 if (!RegQueryValueExW(key
, L
"PolicyFlags", NULL
, &type
, (BYTE
*)&flags
,
119 &size
) && type
== REG_DWORD
)
121 /* The flag values aren't defined in any header I'm aware of, but
122 * this value is well documented on the net.
124 if (flags
& 0x00010000)
132 /* Returns TRUE if pCert is not in the Disallowed system store, or FALSE if it
135 static BOOL
CRYPTDLG_IsCertAllowed(PCCERT_CONTEXT pCert
)
139 DWORD size
= sizeof(hash
);
141 if ((ret
= CertGetCertificateContextProperty(pCert
,
142 CERT_SIGNATURE_HASH_PROP_ID
, hash
, &size
)))
144 HCERTSTORE disallowed
= CertOpenStore(CERT_STORE_PROV_SYSTEM_W
,
145 X509_ASN_ENCODING
, 0, CERT_SYSTEM_STORE_CURRENT_USER
, L
"Disallowed");
149 PCCERT_CONTEXT found
= CertFindCertificateInStore(disallowed
,
150 X509_ASN_ENCODING
, 0, CERT_FIND_SIGNATURE_HASH
, hash
, NULL
);
155 CertFreeCertificateContext(found
);
157 CertCloseStore(disallowed
, 0);
163 static DWORD
CRYPTDLG_TrustStatusToConfidence(DWORD errorStatus
)
165 DWORD confidence
= 0;
168 if (!(errorStatus
& CERT_TRUST_IS_NOT_SIGNATURE_VALID
))
169 confidence
|= CERT_CONFIDENCE_SIG
;
170 if (!(errorStatus
& CERT_TRUST_IS_NOT_TIME_VALID
))
171 confidence
|= CERT_CONFIDENCE_TIME
;
172 if (!(errorStatus
& CERT_TRUST_IS_NOT_TIME_NESTED
))
173 confidence
|= CERT_CONFIDENCE_TIMENEST
;
177 static BOOL
CRYPTDLG_CopyChain(CRYPT_PROVIDER_DATA
*data
,
178 PCCERT_CHAIN_CONTEXT chain
)
181 CRYPT_PROVIDER_SGNR signer
;
182 PCERT_SIMPLE_CHAIN simpleChain
= chain
->rgpChain
[0];
185 memset(&signer
, 0, sizeof(signer
));
186 signer
.cbStruct
= sizeof(signer
);
187 ret
= data
->psPfns
->pfnAddSgnr2Chain(data
, FALSE
, 0, &signer
);
190 CRYPT_PROVIDER_SGNR
*sgnr
= WTHelperGetProvSignerFromChain(data
, 0,
195 sgnr
->dwError
= simpleChain
->TrustStatus
.dwErrorStatus
;
196 sgnr
->pChainContext
= CertDuplicateCertificateChain(chain
);
200 for (i
= 0; ret
&& i
< simpleChain
->cElement
; i
++)
202 ret
= data
->psPfns
->pfnAddCert2Chain(data
, 0, FALSE
, 0,
203 simpleChain
->rgpElement
[i
]->pCertContext
);
206 CRYPT_PROVIDER_CERT
*cert
;
208 if ((cert
= WTHelperGetProvCertFromChain(sgnr
, i
)))
210 CERT_CHAIN_ELEMENT
*element
= simpleChain
->rgpElement
[i
];
212 cert
->dwConfidence
= CRYPTDLG_TrustStatusToConfidence(
213 element
->TrustStatus
.dwErrorStatus
);
214 cert
->dwError
= element
->TrustStatus
.dwErrorStatus
;
215 cert
->pChainElement
= element
;
225 static CERT_VERIFY_CERTIFICATE_TRUST
*CRYPTDLG_GetVerifyData(
226 CRYPT_PROVIDER_DATA
*data
)
228 CERT_VERIFY_CERTIFICATE_TRUST
*pCert
= NULL
;
230 /* This should always be true, but just in case the calling function is
233 if (data
->pWintrustData
->dwUnionChoice
== WTD_CHOICE_BLOB
&&
234 data
->pWintrustData
->u
.pBlob
&& data
->pWintrustData
->u
.pBlob
->cbMemObject
==
235 sizeof(CERT_VERIFY_CERTIFICATE_TRUST
) &&
236 data
->pWintrustData
->u
.pBlob
->pbMemObject
)
237 pCert
= (CERT_VERIFY_CERTIFICATE_TRUST
*)
238 data
->pWintrustData
->u
.pBlob
->pbMemObject
;
242 static HCERTCHAINENGINE
CRYPTDLG_MakeEngine(CERT_VERIFY_CERTIFICATE_TRUST
*cert
)
244 HCERTCHAINENGINE engine
= NULL
;
245 HCERTSTORE root
= NULL
, trust
= NULL
;
248 if (cert
->cRootStores
)
250 root
= CertOpenStore(CERT_STORE_PROV_COLLECTION
, 0, 0,
251 CERT_STORE_CREATE_NEW_FLAG
, NULL
);
254 for (i
= 0; i
< cert
->cRootStores
; i
++)
255 CertAddStoreToCollection(root
, cert
->rghstoreRoots
[i
], 0, 0);
258 if (cert
->cTrustStores
)
260 trust
= CertOpenStore(CERT_STORE_PROV_COLLECTION
, 0, 0,
261 CERT_STORE_CREATE_NEW_FLAG
, NULL
);
264 for (i
= 0; i
< cert
->cTrustStores
; i
++)
265 CertAddStoreToCollection(trust
, cert
->rghstoreTrust
[i
], 0, 0);
268 if (cert
->cRootStores
|| cert
->cStores
|| cert
->cTrustStores
)
270 CERT_CHAIN_ENGINE_CONFIG config
;
272 memset(&config
, 0, sizeof(config
));
273 config
.cbSize
= sizeof(config
);
274 config
.hRestrictedRoot
= root
;
275 config
.hRestrictedTrust
= trust
;
276 config
.cAdditionalStore
= cert
->cStores
;
277 config
.rghAdditionalStore
= cert
->rghstoreCAs
;
278 config
.hRestrictedRoot
= root
;
279 CertCreateCertificateChainEngine(&config
, &engine
);
280 CertCloseStore(root
, 0);
281 CertCloseStore(trust
, 0);
286 /***********************************************************************
287 * CertTrustFinalPolicy (CRYPTDLG.@)
289 HRESULT WINAPI
CertTrustFinalPolicy(CRYPT_PROVIDER_DATA
*data
)
293 CERT_VERIFY_CERTIFICATE_TRUST
*pCert
= CRYPTDLG_GetVerifyData(data
);
295 TRACE("(%p)\n", data
);
297 if (data
->pWintrustData
->dwUIChoice
!= WTD_UI_NONE
)
298 FIXME("unimplemented for UI choice %ld\n",
299 data
->pWintrustData
->dwUIChoice
);
303 CERT_CHAIN_PARA chainPara
;
304 HCERTCHAINENGINE engine
;
306 memset(&chainPara
, 0, sizeof(chainPara
));
307 chainPara
.cbSize
= sizeof(chainPara
);
308 if (CRYPTDLG_CheckOnlineCRL())
309 flags
|= CERT_CHAIN_REVOCATION_CHECK_END_CERT
;
310 engine
= CRYPTDLG_MakeEngine(pCert
);
311 GetSystemTimeAsFileTime(&data
->sftSystemTime
);
312 ret
= CRYPTDLG_IsCertAllowed(pCert
->pccert
);
315 PCCERT_CHAIN_CONTEXT chain
;
317 ret
= CertGetCertificateChain(engine
, pCert
->pccert
,
318 &data
->sftSystemTime
, NULL
, &chainPara
, flags
, NULL
, &chain
);
321 if (chain
->cChain
!= 1)
323 FIXME("unimplemented for more than 1 simple chain\n");
324 err
= TRUST_E_SUBJECT_FORM_UNKNOWN
;
327 else if ((ret
= CRYPTDLG_CopyChain(data
, chain
)))
329 if (CertVerifyTimeValidity(&data
->sftSystemTime
,
330 pCert
->pccert
->pCertInfo
))
333 err
= CERT_E_EXPIRED
;
337 err
= TRUST_E_SYSTEM_ERROR
;
338 CertFreeCertificateChain(chain
);
341 err
= TRUST_E_SUBJECT_NOT_TRUSTED
;
343 CertFreeCertificateChainEngine(engine
);
348 err
= TRUST_E_NOSIGNATURE
;
350 /* Oddly, native doesn't set the error in the trust step error location,
351 * probably because this action is more advisory than anything else.
352 * Instead it stores it as the final error, but the function "succeeds" in
356 data
->dwFinalError
= err
;
357 TRACE("returning %ld (%08lx)\n", S_OK
, data
->dwFinalError
);
361 /***********************************************************************
362 * CertViewPropertiesA (CRYPTDLG.@)
364 BOOL WINAPI
CertViewPropertiesA(CERT_VIEWPROPERTIES_STRUCT_A
*info
)
366 CERT_VIEWPROPERTIES_STRUCT_W infoW
;
370 TRACE("(%p)\n", info
);
372 memcpy(&infoW
, info
, sizeof(infoW
));
375 int len
= MultiByteToWideChar(CP_ACP
, 0, info
->szTitle
, -1, NULL
, 0);
377 title
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
380 MultiByteToWideChar(CP_ACP
, 0, info
->szTitle
, -1, title
, len
);
381 infoW
.szTitle
= title
;
389 ret
= CertViewPropertiesW(&infoW
);
390 HeapFree(GetProcessHeap(), 0, title
);
395 /***********************************************************************
396 * CertViewPropertiesW (CRYPTDLG.@)
398 BOOL WINAPI
CertViewPropertiesW(CERT_VIEWPROPERTIES_STRUCT_W
*info
)
400 static GUID cert_action_verify
= CERT_CERTIFICATE_ACTION_VERIFY
;
401 CERT_VERIFY_CERTIFICATE_TRUST trust
;
402 WINTRUST_BLOB_INFO blob
;
407 TRACE("(%p)\n", info
);
409 memset(&trust
, 0, sizeof(trust
));
410 trust
.cbSize
= sizeof(trust
);
411 trust
.pccert
= info
->pCertContext
;
412 trust
.cRootStores
= info
->cRootStores
;
413 trust
.rghstoreRoots
= info
->rghstoreRoots
;
414 trust
.cStores
= info
->cStores
;
415 trust
.rghstoreCAs
= info
->rghstoreCAs
;
416 trust
.cTrustStores
= info
->cTrustStores
;
417 trust
.rghstoreTrust
= info
->rghstoreTrust
;
418 memset(&blob
, 0, sizeof(blob
));
419 blob
.cbStruct
= sizeof(blob
);
420 blob
.cbMemObject
= sizeof(trust
);
421 blob
.pbMemObject
= (BYTE
*)&trust
;
422 memset(&wtd
, 0, sizeof(wtd
));
423 wtd
.cbStruct
= sizeof(wtd
);
424 wtd
.dwUIChoice
= WTD_UI_NONE
;
425 wtd
.dwUnionChoice
= WTD_CHOICE_BLOB
;
427 wtd
.dwStateAction
= WTD_STATEACTION_VERIFY
;
428 err
= WinVerifyTrust(NULL
, &cert_action_verify
, &wtd
);
429 if (err
== ERROR_SUCCESS
)
431 CRYPTUI_VIEWCERTIFICATE_STRUCTW uiInfo
;
432 BOOL propsChanged
= FALSE
;
434 memset(&uiInfo
, 0, sizeof(uiInfo
));
435 uiInfo
.dwSize
= sizeof(uiInfo
);
436 uiInfo
.hwndParent
= info
->hwndParent
;
438 CRYPTUI_DISABLE_ADDTOSTORE
| CRYPTUI_ENABLE_EDITPROPERTIES
;
439 uiInfo
.szTitle
= info
->szTitle
;
440 uiInfo
.pCertContext
= info
->pCertContext
;
441 uiInfo
.cPurposes
= info
->cArrayPurposes
;
442 uiInfo
.rgszPurposes
= (LPCSTR
*)info
->arrayPurposes
;
443 uiInfo
.u
.hWVTStateData
= wtd
.hWVTStateData
;
444 uiInfo
.fpCryptProviderDataTrustedUsage
= TRUE
;
445 uiInfo
.cPropSheetPages
= info
->cArrayPropSheetPages
;
446 uiInfo
.rgPropSheetPages
= info
->arrayPropSheetPages
;
447 uiInfo
.nStartPage
= info
->nStartPage
;
448 ret
= CryptUIDlgViewCertificateW(&uiInfo
, &propsChanged
);
449 wtd
.dwStateAction
= WTD_STATEACTION_CLOSE
;
450 WinVerifyTrust(NULL
, &cert_action_verify
, &wtd
);
457 static BOOL
CRYPT_FormatHexString(const BYTE
*pbEncoded
, DWORD cbEncoded
,
458 WCHAR
*str
, DWORD
*pcchStr
)
464 charsNeeded
= (cbEncoded
* 3);
469 *pcchStr
= charsNeeded
;
472 else if (*pcchStr
< charsNeeded
)
474 *pcchStr
= charsNeeded
;
475 SetLastError(ERROR_MORE_DATA
);
483 *pcchStr
= charsNeeded
;
486 for (i
= 0; i
< cbEncoded
; i
++)
488 if (i
< cbEncoded
- 1)
489 ptr
+= swprintf(ptr
, 4, L
"%02x ", pbEncoded
[i
]);
491 ptr
+= swprintf(ptr
, 3, L
"%02x", pbEncoded
[i
]);
501 static const WCHAR indent
[] = L
" ";
503 static BOOL
CRYPT_FormatCPS(DWORD dwCertEncodingType
,
504 DWORD dwFormatStrType
, const BYTE
*pbEncoded
, DWORD cbEncoded
,
505 WCHAR
*str
, DWORD
*pcchStr
)
508 DWORD size
, charsNeeded
= 1;
509 CERT_NAME_VALUE
*cpsValue
;
511 if ((ret
= CryptDecodeObjectEx(dwCertEncodingType
, X509_UNICODE_ANY_STRING
,
512 pbEncoded
, cbEncoded
, CRYPT_DECODE_ALLOC_FLAG
, NULL
, &cpsValue
, &size
)))
517 if (dwFormatStrType
& CRYPT_FORMAT_STR_MULTI_LINE
)
522 sepLen
= lstrlenW(sep
);
524 if (dwFormatStrType
& CRYPT_FORMAT_STR_MULTI_LINE
)
526 charsNeeded
+= 3 * lstrlenW(indent
);
527 if (str
&& *pcchStr
>= charsNeeded
)
529 lstrcpyW(str
, indent
);
530 str
+= lstrlenW(indent
);
531 lstrcpyW(str
, indent
);
532 str
+= lstrlenW(indent
);
533 lstrcpyW(str
, indent
);
534 str
+= lstrlenW(indent
);
537 charsNeeded
+= cpsValue
->Value
.cbData
/ sizeof(WCHAR
);
538 if (str
&& *pcchStr
>= charsNeeded
)
540 lstrcpyW(str
, (LPWSTR
)cpsValue
->Value
.pbData
);
541 str
+= cpsValue
->Value
.cbData
/ sizeof(WCHAR
);
543 charsNeeded
+= sepLen
;
544 if (str
&& *pcchStr
>= charsNeeded
)
551 *pcchStr
= charsNeeded
;
552 else if (*pcchStr
< charsNeeded
)
554 *pcchStr
= charsNeeded
;
555 SetLastError(ERROR_MORE_DATA
);
559 *pcchStr
= charsNeeded
;
564 static BOOL
CRYPT_FormatUserNotice(DWORD dwCertEncodingType
,
565 DWORD dwFormatStrType
, const BYTE
*pbEncoded
, DWORD cbEncoded
,
566 WCHAR
*str
, DWORD
*pcchStr
)
569 DWORD size
, charsNeeded
= 1;
570 CERT_POLICY_QUALIFIER_USER_NOTICE
*notice
;
572 if ((ret
= CryptDecodeObjectEx(dwCertEncodingType
,
573 X509_PKIX_POLICY_QUALIFIER_USERNOTICE
, pbEncoded
, cbEncoded
,
574 CRYPT_DECODE_ALLOC_FLAG
, NULL
, ¬ice
, &size
)))
576 CERT_POLICY_QUALIFIER_NOTICE_REFERENCE
*pNoticeRef
=
577 notice
->pNoticeReference
;
578 LPCWSTR headingSep
, sep
;
579 DWORD headingSepLen
, sepLen
;
580 LPWSTR noticeRef
, organization
, noticeNum
, noticeText
;
581 DWORD noticeRefLen
, organizationLen
, noticeNumLen
, noticeTextLen
;
582 WCHAR noticeNumStr
[11];
584 noticeRefLen
= LoadStringW(hInstance
, IDS_NOTICE_REF
,
585 (LPWSTR
)¬iceRef
, 0);
586 organizationLen
= LoadStringW(hInstance
, IDS_ORGANIZATION
,
587 (LPWSTR
)&organization
, 0);
588 noticeNumLen
= LoadStringW(hInstance
, IDS_NOTICE_NUM
,
589 (LPWSTR
)¬iceNum
, 0);
590 noticeTextLen
= LoadStringW(hInstance
, IDS_NOTICE_TEXT
,
591 (LPWSTR
)¬iceText
, 0);
592 if (dwFormatStrType
& CRYPT_FORMAT_STR_MULTI_LINE
)
594 headingSep
= L
":\r\n";
602 sepLen
= lstrlenW(sep
);
603 headingSepLen
= lstrlenW(headingSep
);
610 if (dwFormatStrType
& CRYPT_FORMAT_STR_MULTI_LINE
)
612 charsNeeded
+= 3 * lstrlenW(indent
);
613 if (str
&& *pcchStr
>= charsNeeded
)
615 lstrcpyW(str
, indent
);
616 str
+= lstrlenW(indent
);
617 lstrcpyW(str
, indent
);
618 str
+= lstrlenW(indent
);
619 lstrcpyW(str
, indent
);
620 str
+= lstrlenW(indent
);
623 charsNeeded
+= noticeRefLen
;
624 if (str
&& *pcchStr
>= charsNeeded
)
626 memcpy(str
, noticeRef
, noticeRefLen
* sizeof(WCHAR
));
629 charsNeeded
+= headingSepLen
;
630 if (str
&& *pcchStr
>= charsNeeded
)
632 lstrcpyW(str
, headingSep
);
633 str
+= headingSepLen
;
635 if (dwFormatStrType
& CRYPT_FORMAT_STR_MULTI_LINE
)
637 charsNeeded
+= 4 * lstrlenW(indent
);
638 if (str
&& *pcchStr
>= charsNeeded
)
640 lstrcpyW(str
, indent
);
641 str
+= lstrlenW(indent
);
642 lstrcpyW(str
, indent
);
643 str
+= lstrlenW(indent
);
644 lstrcpyW(str
, indent
);
645 str
+= lstrlenW(indent
);
646 lstrcpyW(str
, indent
);
647 str
+= lstrlenW(indent
);
650 charsNeeded
+= organizationLen
;
651 if (str
&& *pcchStr
>= charsNeeded
)
653 memcpy(str
, organization
, organizationLen
* sizeof(WCHAR
));
654 str
+= organizationLen
;
656 charsNeeded
+= strlen(pNoticeRef
->pszOrganization
);
657 if (str
&& *pcchStr
>= charsNeeded
)
658 for (src
= pNoticeRef
->pszOrganization
; src
&& *src
;
661 charsNeeded
+= sepLen
;
662 if (str
&& *pcchStr
>= charsNeeded
)
667 for (k
= 0; k
< pNoticeRef
->cNoticeNumbers
; k
++)
669 if (dwFormatStrType
& CRYPT_FORMAT_STR_MULTI_LINE
)
671 charsNeeded
+= 4 * lstrlenW(indent
);
672 if (str
&& *pcchStr
>= charsNeeded
)
674 lstrcpyW(str
, indent
);
675 str
+= lstrlenW(indent
);
676 lstrcpyW(str
, indent
);
677 str
+= lstrlenW(indent
);
678 lstrcpyW(str
, indent
);
679 str
+= lstrlenW(indent
);
680 lstrcpyW(str
, indent
);
681 str
+= lstrlenW(indent
);
684 charsNeeded
+= noticeNumLen
;
685 if (str
&& *pcchStr
>= charsNeeded
)
687 memcpy(str
, noticeNum
, noticeNumLen
* sizeof(WCHAR
));
690 swprintf(noticeNumStr
, ARRAY_SIZE(noticeNumStr
), L
"%d", k
+ 1);
691 charsNeeded
+= lstrlenW(noticeNumStr
);
692 if (str
&& *pcchStr
>= charsNeeded
)
694 lstrcpyW(str
, noticeNumStr
);
695 str
+= lstrlenW(noticeNumStr
);
697 charsNeeded
+= sepLen
;
698 if (str
&& *pcchStr
>= charsNeeded
)
705 if (notice
->pszDisplayText
)
707 if (dwFormatStrType
& CRYPT_FORMAT_STR_MULTI_LINE
)
709 charsNeeded
+= 3 * lstrlenW(indent
);
710 if (str
&& *pcchStr
>= charsNeeded
)
712 lstrcpyW(str
, indent
);
713 str
+= lstrlenW(indent
);
714 lstrcpyW(str
, indent
);
715 str
+= lstrlenW(indent
);
716 lstrcpyW(str
, indent
);
717 str
+= lstrlenW(indent
);
720 charsNeeded
+= noticeTextLen
;
721 if (str
&& *pcchStr
>= charsNeeded
)
723 memcpy(str
, noticeText
, noticeTextLen
* sizeof(WCHAR
));
724 str
+= noticeTextLen
;
726 charsNeeded
+= lstrlenW(notice
->pszDisplayText
);
727 if (str
&& *pcchStr
>= charsNeeded
)
729 lstrcpyW(str
, notice
->pszDisplayText
);
730 str
+= lstrlenW(notice
->pszDisplayText
);
732 charsNeeded
+= sepLen
;
733 if (str
&& *pcchStr
>= charsNeeded
)
741 *pcchStr
= charsNeeded
;
742 else if (*pcchStr
< charsNeeded
)
744 *pcchStr
= charsNeeded
;
745 SetLastError(ERROR_MORE_DATA
);
749 *pcchStr
= charsNeeded
;
754 /***********************************************************************
755 * FormatVerisignExtension (CRYPTDLG.@)
757 BOOL WINAPI
FormatVerisignExtension(DWORD dwCertEncodingType
,
758 DWORD dwFormatType
, DWORD dwFormatStrType
, void *pFormatStruct
,
759 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, void *pbFormat
,
762 CERT_POLICIES_INFO
*policies
;
768 SetLastError(E_INVALIDARG
);
771 if ((ret
= CryptDecodeObjectEx(dwCertEncodingType
, X509_CERT_POLICIES
,
772 pbEncoded
, cbEncoded
, CRYPT_DECODE_ALLOC_FLAG
, NULL
, &policies
, &size
)))
774 DWORD charsNeeded
= 1; /* space for NULL terminator */
775 LPCWSTR headingSep
, sep
;
776 DWORD headingSepLen
, sepLen
;
777 WCHAR policyNum
[11], policyQualifierNum
[11];
778 LPWSTR certPolicy
, policyId
, policyQualifierInfo
, policyQualifierId
;
779 LPWSTR cps
, userNotice
, qualifier
;
780 DWORD certPolicyLen
, policyIdLen
, policyQualifierInfoLen
;
781 DWORD policyQualifierIdLen
, cpsLen
, userNoticeLen
, qualifierLen
;
783 LPWSTR str
= pbFormat
;
785 certPolicyLen
= LoadStringW(hInstance
, IDS_CERT_POLICY
,
786 (LPWSTR
)&certPolicy
, 0);
787 policyIdLen
= LoadStringW(hInstance
, IDS_POLICY_ID
, (LPWSTR
)&policyId
,
789 policyQualifierInfoLen
= LoadStringW(hInstance
,
790 IDS_POLICY_QUALIFIER_INFO
, (LPWSTR
)&policyQualifierInfo
, 0);
791 policyQualifierIdLen
= LoadStringW(hInstance
, IDS_POLICY_QUALIFIER_ID
,
792 (LPWSTR
)&policyQualifierId
, 0);
793 cpsLen
= LoadStringW(hInstance
, IDS_CPS
, (LPWSTR
)&cps
, 0);
794 userNoticeLen
= LoadStringW(hInstance
, IDS_USER_NOTICE
,
795 (LPWSTR
)&userNotice
, 0);
796 qualifierLen
= LoadStringW(hInstance
, IDS_QUALIFIER
,
797 (LPWSTR
)&qualifier
, 0);
798 if (dwFormatStrType
& CRYPT_FORMAT_STR_MULTI_LINE
)
800 headingSep
= L
":\r\n";
808 sepLen
= lstrlenW(sep
);
809 headingSepLen
= lstrlenW(headingSep
);
811 for (i
= 0; ret
&& i
< policies
->cPolicyInfo
; i
++)
813 CERT_POLICY_INFO
*policy
= &policies
->rgPolicyInfo
[i
];
817 charsNeeded
+= 1; /* '['*/
818 if (str
&& *pcbFormat
>= charsNeeded
* sizeof(WCHAR
))
820 swprintf(policyNum
, ARRAY_SIZE(policyNum
), L
"%d", i
+ 1);
821 charsNeeded
+= lstrlenW(policyNum
);
822 if (str
&& *pcbFormat
>= charsNeeded
* sizeof(WCHAR
))
824 lstrcpyW(str
, policyNum
);
825 str
+= lstrlenW(policyNum
);
827 charsNeeded
+= 1; /* ']'*/
828 if (str
&& *pcbFormat
>= charsNeeded
* sizeof(WCHAR
))
830 charsNeeded
+= certPolicyLen
;
831 if (str
&& *pcbFormat
>= charsNeeded
* sizeof(WCHAR
))
833 memcpy(str
, certPolicy
, certPolicyLen
* sizeof(WCHAR
));
834 str
+= certPolicyLen
;
836 charsNeeded
+= headingSepLen
;
837 if (str
&& *pcbFormat
>= charsNeeded
* sizeof(WCHAR
))
839 lstrcpyW(str
, headingSep
);
840 str
+= headingSepLen
;
842 if (dwFormatStrType
& CRYPT_FORMAT_STR_MULTI_LINE
)
844 charsNeeded
+= lstrlenW(indent
);
845 if (str
&& *pcbFormat
>= charsNeeded
* sizeof(WCHAR
))
847 lstrcpyW(str
, indent
);
848 str
+= lstrlenW(indent
);
851 charsNeeded
+= policyIdLen
;
852 if (str
&& *pcbFormat
>= charsNeeded
* sizeof(WCHAR
))
854 memcpy(str
, policyId
, policyIdLen
* sizeof(WCHAR
));
857 charsNeeded
+= strlen(policy
->pszPolicyIdentifier
);
858 if (str
&& *pcbFormat
>= charsNeeded
* sizeof(WCHAR
))
860 for (src
= policy
->pszPolicyIdentifier
; src
&& *src
;
864 charsNeeded
+= sepLen
;
865 if (str
&& *pcbFormat
>= charsNeeded
* sizeof(WCHAR
))
870 for (j
= 0; j
< policy
->cPolicyQualifier
; j
++)
872 CERT_POLICY_QUALIFIER_INFO
*qualifierInfo
=
873 &policy
->rgPolicyQualifier
[j
];
876 if (dwFormatStrType
& CRYPT_FORMAT_STR_MULTI_LINE
)
878 charsNeeded
+= lstrlenW(indent
);
879 if (str
&& *pcbFormat
>= charsNeeded
* sizeof(WCHAR
))
881 lstrcpyW(str
, indent
);
882 str
+= lstrlenW(indent
);
885 charsNeeded
+= 1; /* '['*/
886 if (str
&& *pcbFormat
>= charsNeeded
* sizeof(WCHAR
))
888 charsNeeded
+= lstrlenW(policyNum
);
889 if (str
&& *pcbFormat
>= charsNeeded
* sizeof(WCHAR
))
891 lstrcpyW(str
, policyNum
);
892 str
+= lstrlenW(policyNum
);
894 charsNeeded
+= 1; /* ','*/
895 if (str
&& *pcbFormat
>= charsNeeded
* sizeof(WCHAR
))
897 swprintf(policyQualifierNum
, ARRAY_SIZE(policyQualifierNum
), L
"%d", j
+ 1);
898 charsNeeded
+= lstrlenW(policyQualifierNum
);
899 if (str
&& *pcbFormat
>= charsNeeded
* sizeof(WCHAR
))
901 lstrcpyW(str
, policyQualifierNum
);
902 str
+= lstrlenW(policyQualifierNum
);
904 charsNeeded
+= 1; /* ']'*/
905 if (str
&& *pcbFormat
>= charsNeeded
* sizeof(WCHAR
))
907 charsNeeded
+= policyQualifierInfoLen
;
908 if (str
&& *pcbFormat
>= charsNeeded
* sizeof(WCHAR
))
910 memcpy(str
, policyQualifierInfo
,
911 policyQualifierInfoLen
* sizeof(WCHAR
));
912 str
+= policyQualifierInfoLen
;
914 charsNeeded
+= headingSepLen
;
915 if (str
&& *pcbFormat
>= charsNeeded
* sizeof(WCHAR
))
917 lstrcpyW(str
, headingSep
);
918 str
+= headingSepLen
;
920 if (dwFormatStrType
& CRYPT_FORMAT_STR_MULTI_LINE
)
922 charsNeeded
+= 2 * lstrlenW(indent
);
923 if (str
&& *pcbFormat
>= charsNeeded
* sizeof(WCHAR
))
925 lstrcpyW(str
, indent
);
926 str
+= lstrlenW(indent
);
927 lstrcpyW(str
, indent
);
928 str
+= lstrlenW(indent
);
931 charsNeeded
+= policyQualifierIdLen
;
932 if (str
&& *pcbFormat
>= charsNeeded
* sizeof(WCHAR
))
934 memcpy(str
, policyQualifierId
,
935 policyQualifierIdLen
* sizeof(WCHAR
));
936 str
+= policyQualifierIdLen
;
938 if (!strcmp(qualifierInfo
->pszPolicyQualifierId
,
939 szOID_PKIX_POLICY_QUALIFIER_CPS
))
941 charsNeeded
+= cpsLen
;
942 if (str
&& *pcbFormat
>= charsNeeded
* sizeof(WCHAR
))
944 memcpy(str
, cps
, cpsLen
* sizeof(WCHAR
));
948 else if (!strcmp(qualifierInfo
->pszPolicyQualifierId
,
949 szOID_PKIX_POLICY_QUALIFIER_USERNOTICE
))
951 charsNeeded
+= userNoticeLen
;
952 if (str
&& *pcbFormat
>= charsNeeded
* sizeof(WCHAR
))
954 memcpy(str
, userNotice
, userNoticeLen
* sizeof(WCHAR
));
955 str
+= userNoticeLen
;
960 charsNeeded
+= strlen(qualifierInfo
->pszPolicyQualifierId
);
961 if (str
&& *pcbFormat
>= charsNeeded
* sizeof(WCHAR
))
963 for (src
= qualifierInfo
->pszPolicyQualifierId
;
964 src
&& *src
; src
++, str
++)
968 charsNeeded
+= sepLen
;
969 if (str
&& *pcbFormat
>= charsNeeded
* sizeof(WCHAR
))
974 if (dwFormatStrType
& CRYPT_FORMAT_STR_MULTI_LINE
)
976 charsNeeded
+= 2 * lstrlenW(indent
);
977 if (str
&& *pcbFormat
>= charsNeeded
* sizeof(WCHAR
))
979 lstrcpyW(str
, indent
);
980 str
+= lstrlenW(indent
);
981 lstrcpyW(str
, indent
);
982 str
+= lstrlenW(indent
);
985 charsNeeded
+= qualifierLen
;
986 if (str
&& *pcbFormat
>= charsNeeded
* sizeof(WCHAR
))
988 memcpy(str
, qualifier
, qualifierLen
* sizeof(WCHAR
));
991 charsNeeded
+= headingSepLen
;
992 if (str
&& *pcbFormat
>= charsNeeded
* sizeof(WCHAR
))
994 lstrcpyW(str
, headingSep
);
995 str
+= headingSepLen
;
997 /* This if block is deliberately redundant with the same if
998 * block above, in order to keep the code more readable (the
999 * code flow follows the order in which the strings are output.)
1001 if (!strcmp(qualifierInfo
->pszPolicyQualifierId
,
1002 szOID_PKIX_POLICY_QUALIFIER_CPS
))
1004 if (!str
|| *pcbFormat
< charsNeeded
* sizeof(WCHAR
))
1006 /* Insufficient space, determine how much is needed. */
1007 ret
= CRYPT_FormatCPS(dwCertEncodingType
,
1008 dwFormatStrType
, qualifierInfo
->Qualifier
.pbData
,
1009 qualifierInfo
->Qualifier
.cbData
, NULL
, &size
);
1011 charsNeeded
+= size
- 1;
1015 sizeRemaining
= *pcbFormat
/ sizeof(WCHAR
);
1016 sizeRemaining
-= str
- (LPWSTR
)pbFormat
;
1017 ret
= CRYPT_FormatCPS(dwCertEncodingType
,
1018 dwFormatStrType
, qualifierInfo
->Qualifier
.pbData
,
1019 qualifierInfo
->Qualifier
.cbData
, str
, &sizeRemaining
);
1020 if (ret
|| GetLastError() == ERROR_MORE_DATA
)
1022 charsNeeded
+= sizeRemaining
- 1;
1023 str
+= sizeRemaining
- 1;
1027 else if (!strcmp(qualifierInfo
->pszPolicyQualifierId
,
1028 szOID_PKIX_POLICY_QUALIFIER_USERNOTICE
))
1030 if (!str
|| *pcbFormat
< charsNeeded
* sizeof(WCHAR
))
1032 /* Insufficient space, determine how much is needed. */
1033 ret
= CRYPT_FormatUserNotice(dwCertEncodingType
,
1034 dwFormatStrType
, qualifierInfo
->Qualifier
.pbData
,
1035 qualifierInfo
->Qualifier
.cbData
, NULL
, &size
);
1037 charsNeeded
+= size
- 1;
1041 sizeRemaining
= *pcbFormat
/ sizeof(WCHAR
);
1042 sizeRemaining
-= str
- (LPWSTR
)pbFormat
;
1043 ret
= CRYPT_FormatUserNotice(dwCertEncodingType
,
1044 dwFormatStrType
, qualifierInfo
->Qualifier
.pbData
,
1045 qualifierInfo
->Qualifier
.cbData
, str
, &sizeRemaining
);
1046 if (ret
|| GetLastError() == ERROR_MORE_DATA
)
1048 charsNeeded
+= sizeRemaining
- 1;
1049 str
+= sizeRemaining
- 1;
1055 if (!str
|| *pcbFormat
< charsNeeded
* sizeof(WCHAR
))
1057 /* Insufficient space, determine how much is needed. */
1058 ret
= CRYPT_FormatHexString(
1059 qualifierInfo
->Qualifier
.pbData
,
1060 qualifierInfo
->Qualifier
.cbData
, NULL
, &size
);
1062 charsNeeded
+= size
- 1;
1066 sizeRemaining
= *pcbFormat
/ sizeof(WCHAR
);
1067 sizeRemaining
-= str
- (LPWSTR
)pbFormat
;
1068 ret
= CRYPT_FormatHexString(
1069 qualifierInfo
->Qualifier
.pbData
,
1070 qualifierInfo
->Qualifier
.cbData
, str
, &sizeRemaining
);
1071 if (ret
|| GetLastError() == ERROR_MORE_DATA
)
1073 charsNeeded
+= sizeRemaining
- 1;
1074 str
+= sizeRemaining
- 1;
1080 LocalFree(policies
);
1084 *pcbFormat
= charsNeeded
* sizeof(WCHAR
);
1085 else if (*pcbFormat
< charsNeeded
* sizeof(WCHAR
))
1087 *pcbFormat
= charsNeeded
* sizeof(WCHAR
);
1088 SetLastError(ERROR_MORE_DATA
);
1092 *pcbFormat
= charsNeeded
* sizeof(WCHAR
);
1098 #define szOID_MICROSOFT_Encryption_Key_Preference "1.3.6.1.4.1.311.16.4"
1100 /***********************************************************************
1101 * DllRegisterServer (CRYPTDLG.@)
1103 HRESULT WINAPI
DllRegisterServer(void)
1105 static WCHAR cryptdlg
[] = L
"cryptdlg.dll";
1106 static WCHAR wintrust
[] = L
"wintrust.dll";
1107 static WCHAR certTrustInit
[] = L
"CertTrustInit";
1108 static WCHAR wintrustCertificateTrust
[] = L
"WintrustCertificateTrust";
1109 static WCHAR certTrustCertPolicy
[] = L
"CertTrustCertPolicy";
1110 static WCHAR certTrustFinalPolicy
[] = L
"CertTrustFinalPolicy";
1111 static WCHAR certTrustCleanup
[] = L
"CertTrustCleanup";
1112 CRYPT_REGISTER_ACTIONID reg
;
1113 GUID guid
= CERT_CERTIFICATE_ACTION_VERIFY
;
1116 memset(®
, 0, sizeof(reg
));
1117 reg
.cbStruct
= sizeof(reg
);
1118 reg
.sInitProvider
.cbStruct
= sizeof(CRYPT_TRUST_REG_ENTRY
);
1119 reg
.sInitProvider
.pwszDLLName
= cryptdlg
;
1120 reg
.sInitProvider
.pwszFunctionName
= certTrustInit
;
1121 reg
.sCertificateProvider
.cbStruct
= sizeof(CRYPT_TRUST_REG_ENTRY
);
1122 reg
.sCertificateProvider
.pwszDLLName
= wintrust
;
1123 reg
.sCertificateProvider
.pwszFunctionName
= wintrustCertificateTrust
;
1124 reg
.sCertificatePolicyProvider
.cbStruct
= sizeof(CRYPT_TRUST_REG_ENTRY
);
1125 reg
.sCertificatePolicyProvider
.pwszDLLName
= cryptdlg
;
1126 reg
.sCertificatePolicyProvider
.pwszFunctionName
= certTrustCertPolicy
;
1127 reg
.sFinalPolicyProvider
.cbStruct
= sizeof(CRYPT_TRUST_REG_ENTRY
);
1128 reg
.sFinalPolicyProvider
.pwszDLLName
= cryptdlg
;
1129 reg
.sFinalPolicyProvider
.pwszFunctionName
= certTrustFinalPolicy
;
1130 reg
.sCleanupProvider
.cbStruct
= sizeof(CRYPT_TRUST_REG_ENTRY
);
1131 reg
.sCleanupProvider
.pwszDLLName
= cryptdlg
;
1132 reg
.sCleanupProvider
.pwszFunctionName
= certTrustCleanup
;
1133 if (!WintrustAddActionID(&guid
, WT_ADD_ACTION_ID_RET_RESULT_FLAG
, ®
))
1134 hr
= GetLastError();
1135 CryptRegisterOIDFunction(X509_ASN_ENCODING
, CRYPT_OID_ENCODE_OBJECT_FUNC
,
1136 "1.3.6.1.4.1.311.16.1.1", L
"cryptdlg.dll", "EncodeAttrSequence");
1137 CryptRegisterOIDFunction(X509_ASN_ENCODING
, CRYPT_OID_ENCODE_OBJECT_FUNC
,
1138 szOID_MICROSOFT_Encryption_Key_Preference
, L
"cryptdlg.dll", "EncodeRecipientID");
1139 CryptRegisterOIDFunction(X509_ASN_ENCODING
, CRYPT_OID_DECODE_OBJECT_FUNC
,
1140 "1.3.6.1.4.1.311.16.1.1", L
"cryptdlg.dll", "DecodeAttrSequence");
1141 CryptRegisterOIDFunction(X509_ASN_ENCODING
, CRYPT_OID_DECODE_OBJECT_FUNC
,
1142 szOID_MICROSOFT_Encryption_Key_Preference
, L
"cryptdlg.dll", "DecodeRecipientID");
1143 CryptRegisterOIDFunction(X509_ASN_ENCODING
, CRYPT_OID_FORMAT_OBJECT_FUNC
,
1144 szOID_PKIX_KP_EMAIL_PROTECTION
, L
"cryptdlg.dll", "FormatPKIXEmailProtection");
1145 CryptRegisterOIDFunction(X509_ASN_ENCODING
, CRYPT_OID_FORMAT_OBJECT_FUNC
,
1146 szOID_CERT_POLICIES
, L
"cryptdlg.dll", "FormatVerisignExtension");
1150 /***********************************************************************
1151 * DllUnregisterServer (CRYPTDLG.@)
1153 HRESULT WINAPI
DllUnregisterServer(void)
1155 GUID guid
= CERT_CERTIFICATE_ACTION_VERIFY
;
1157 WintrustRemoveActionID(&guid
);
1158 CryptUnregisterOIDFunction(X509_ASN_ENCODING
, CRYPT_OID_ENCODE_OBJECT_FUNC
,
1159 "1.3.6.1.4.1.311.16.1.1");
1160 CryptUnregisterOIDFunction(X509_ASN_ENCODING
, CRYPT_OID_ENCODE_OBJECT_FUNC
,
1161 szOID_MICROSOFT_Encryption_Key_Preference
);
1162 CryptUnregisterOIDFunction(X509_ASN_ENCODING
, CRYPT_OID_DECODE_OBJECT_FUNC
,
1163 "1.3.6.1.4.1.311.16.1.1");
1164 CryptUnregisterOIDFunction(X509_ASN_ENCODING
, CRYPT_OID_DECODE_OBJECT_FUNC
,
1165 szOID_MICROSOFT_Encryption_Key_Preference
);
1166 CryptUnregisterOIDFunction(X509_ASN_ENCODING
, CRYPT_OID_FORMAT_OBJECT_FUNC
,
1167 szOID_PKIX_KP_EMAIL_PROTECTION
);
1168 CryptUnregisterOIDFunction(X509_ASN_ENCODING
, CRYPT_OID_FORMAT_OBJECT_FUNC
,
1169 szOID_CERT_POLICIES
);