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
34 #include "cryptuiapi.h"
36 #include "wine/unicode.h"
37 #include "wine/debug.h"
39 WINE_DEFAULT_DEBUG_CHANNEL(cryptdlg
);
41 static HINSTANCE hInstance
;
43 BOOL WINAPI
DllMain(HINSTANCE hinstDLL
, DWORD fdwReason
, LPVOID lpvReserved
)
45 TRACE("(0x%p, %d, %p)\n", hinstDLL
, fdwReason
, lpvReserved
);
49 case DLL_WINE_PREATTACH
:
50 return FALSE
; /* prefer native version */
51 case DLL_PROCESS_ATTACH
:
52 DisableThreadLibraryCalls(hinstDLL
);
55 case DLL_PROCESS_DETACH
:
63 /***********************************************************************
64 * GetFriendlyNameOfCertA (CRYPTDLG.@)
66 DWORD WINAPI
GetFriendlyNameOfCertA(PCCERT_CONTEXT pccert
, LPSTR pchBuffer
,
69 return CertGetNameStringA(pccert
, CERT_NAME_FRIENDLY_DISPLAY_TYPE
, 0, NULL
,
70 pchBuffer
, cchBuffer
);
73 /***********************************************************************
74 * GetFriendlyNameOfCertW (CRYPTDLG.@)
76 DWORD WINAPI
GetFriendlyNameOfCertW(PCCERT_CONTEXT pccert
, LPWSTR pchBuffer
,
79 return CertGetNameStringW(pccert
, CERT_NAME_FRIENDLY_DISPLAY_TYPE
, 0, NULL
,
80 pchBuffer
, cchBuffer
);
83 /***********************************************************************
84 * CertTrustInit (CRYPTDLG.@)
86 HRESULT WINAPI
CertTrustInit(CRYPT_PROVIDER_DATA
*pProvData
)
88 HRESULT ret
= S_FALSE
;
90 TRACE("(%p)\n", pProvData
);
92 if (pProvData
->padwTrustStepErrors
&&
93 !pProvData
->padwTrustStepErrors
[TRUSTERROR_STEP_FINAL_WVTINIT
])
95 TRACE("returning %08x\n", ret
);
99 /***********************************************************************
100 * CertTrustCertPolicy (CRYPTDLG.@)
102 BOOL WINAPI
CertTrustCertPolicy(CRYPT_PROVIDER_DATA
*pProvData
, DWORD idxSigner
, BOOL fCounterSignerChain
, DWORD idxCounterSigner
)
104 FIXME("(%p, %d, %s, %d)\n", pProvData
, idxSigner
, fCounterSignerChain
? "TRUE" : "FALSE", idxCounterSigner
);
108 /***********************************************************************
109 * CertTrustCleanup (CRYPTDLG.@)
111 HRESULT WINAPI
CertTrustCleanup(CRYPT_PROVIDER_DATA
*pProvData
)
113 FIXME("(%p)\n", pProvData
);
117 static BOOL
CRYPTDLG_CheckOnlineCRL(void)
119 static const WCHAR policyFlagsKey
[] = { 'S','o','f','t','w','a','r','e',
120 '\\','M','i','c','r','o','s','o','f','t','\\','C','r','y','p','t','o','g',
121 'r','a','p','h','y','\\','{','7','8','0','1','e','b','d','0','-','c','f',
122 '4','b','-','1','1','d','0','-','8','5','1','f','-','0','0','6','0','9',
123 '7','9','3','8','7','e','a','}',0 };
124 static const WCHAR policyFlags
[] = { 'P','o','l','i','c','y','F','l','a',
129 if (!RegOpenKeyExW(HKEY_LOCAL_MACHINE
, policyFlagsKey
, 0, KEY_READ
, &key
))
131 DWORD type
, flags
, size
= sizeof(flags
);
133 if (!RegQueryValueExW(key
, policyFlags
, NULL
, &type
, (BYTE
*)&flags
,
134 &size
) && type
== REG_DWORD
)
136 /* The flag values aren't defined in any header I'm aware of, but
137 * this value is well documented on the net.
139 if (flags
& 0x00010000)
147 /* Returns TRUE if pCert is not in the Disallowed system store, or FALSE if it
150 static BOOL
CRYPTDLG_IsCertAllowed(PCCERT_CONTEXT pCert
)
154 DWORD size
= sizeof(hash
);
156 if ((ret
= CertGetCertificateContextProperty(pCert
,
157 CERT_SIGNATURE_HASH_PROP_ID
, hash
, &size
)))
159 static const WCHAR disallowedW
[] =
160 { 'D','i','s','a','l','l','o','w','e','d',0 };
161 HCERTSTORE disallowed
= CertOpenStore(CERT_STORE_PROV_SYSTEM_W
,
162 X509_ASN_ENCODING
, 0, CERT_SYSTEM_STORE_CURRENT_USER
, disallowedW
);
166 PCCERT_CONTEXT found
= CertFindCertificateInStore(disallowed
,
167 X509_ASN_ENCODING
, 0, CERT_FIND_SIGNATURE_HASH
, hash
, NULL
);
172 CertFreeCertificateContext(found
);
174 CertCloseStore(disallowed
, 0);
180 static DWORD
CRYPTDLG_TrustStatusToConfidence(DWORD errorStatus
)
182 DWORD confidence
= 0;
185 if (!(errorStatus
& CERT_TRUST_IS_NOT_SIGNATURE_VALID
))
186 confidence
|= CERT_CONFIDENCE_SIG
;
187 if (!(errorStatus
& CERT_TRUST_IS_NOT_TIME_VALID
))
188 confidence
|= CERT_CONFIDENCE_TIME
;
189 if (!(errorStatus
& CERT_TRUST_IS_NOT_TIME_NESTED
))
190 confidence
|= CERT_CONFIDENCE_TIMENEST
;
194 static BOOL
CRYPTDLG_CopyChain(CRYPT_PROVIDER_DATA
*data
,
195 PCCERT_CHAIN_CONTEXT chain
)
198 CRYPT_PROVIDER_SGNR signer
;
199 PCERT_SIMPLE_CHAIN simpleChain
= chain
->rgpChain
[0];
202 memset(&signer
, 0, sizeof(signer
));
203 signer
.cbStruct
= sizeof(signer
);
204 ret
= data
->psPfns
->pfnAddSgnr2Chain(data
, FALSE
, 0, &signer
);
207 CRYPT_PROVIDER_SGNR
*sgnr
= WTHelperGetProvSignerFromChain(data
, 0,
212 sgnr
->dwError
= simpleChain
->TrustStatus
.dwErrorStatus
;
213 sgnr
->pChainContext
= CertDuplicateCertificateChain(chain
);
217 for (i
= 0; ret
&& i
< simpleChain
->cElement
; i
++)
219 ret
= data
->psPfns
->pfnAddCert2Chain(data
, 0, FALSE
, 0,
220 simpleChain
->rgpElement
[i
]->pCertContext
);
223 CRYPT_PROVIDER_CERT
*cert
;
225 if ((cert
= WTHelperGetProvCertFromChain(sgnr
, i
)))
227 CERT_CHAIN_ELEMENT
*element
= simpleChain
->rgpElement
[i
];
229 cert
->dwConfidence
= CRYPTDLG_TrustStatusToConfidence(
230 element
->TrustStatus
.dwErrorStatus
);
231 cert
->dwError
= element
->TrustStatus
.dwErrorStatus
;
232 cert
->pChainElement
= element
;
242 static CERT_VERIFY_CERTIFICATE_TRUST
*CRYPTDLG_GetVerifyData(
243 CRYPT_PROVIDER_DATA
*data
)
245 CERT_VERIFY_CERTIFICATE_TRUST
*pCert
= NULL
;
247 /* This should always be true, but just in case the calling function is
250 if (data
->pWintrustData
->dwUnionChoice
== WTD_CHOICE_BLOB
&&
251 data
->pWintrustData
->u
.pBlob
&& data
->pWintrustData
->u
.pBlob
->cbMemObject
==
252 sizeof(CERT_VERIFY_CERTIFICATE_TRUST
) &&
253 data
->pWintrustData
->u
.pBlob
->pbMemObject
)
254 pCert
= (CERT_VERIFY_CERTIFICATE_TRUST
*)
255 data
->pWintrustData
->u
.pBlob
->pbMemObject
;
259 static HCERTCHAINENGINE
CRYPTDLG_MakeEngine(CERT_VERIFY_CERTIFICATE_TRUST
*cert
)
261 HCERTCHAINENGINE engine
= NULL
;
262 HCERTSTORE root
= NULL
, trust
= NULL
;
265 if (cert
->cRootStores
)
267 root
= CertOpenStore(CERT_STORE_PROV_COLLECTION
, 0, 0,
268 CERT_STORE_CREATE_NEW_FLAG
, NULL
);
271 for (i
= 0; i
< cert
->cRootStores
; i
++)
272 CertAddStoreToCollection(root
, cert
->rghstoreRoots
[i
], 0, 0);
275 if (cert
->cTrustStores
)
277 trust
= CertOpenStore(CERT_STORE_PROV_COLLECTION
, 0, 0,
278 CERT_STORE_CREATE_NEW_FLAG
, NULL
);
281 for (i
= 0; i
< cert
->cTrustStores
; i
++)
282 CertAddStoreToCollection(trust
, cert
->rghstoreTrust
[i
], 0, 0);
285 if (cert
->cRootStores
|| cert
->cStores
|| cert
->cTrustStores
)
287 CERT_CHAIN_ENGINE_CONFIG config
;
289 memset(&config
, 0, sizeof(config
));
290 config
.cbSize
= sizeof(config
);
291 config
.hRestrictedRoot
= root
;
292 config
.hRestrictedTrust
= trust
;
293 config
.cAdditionalStore
= cert
->cStores
;
294 config
.rghAdditionalStore
= cert
->rghstoreCAs
;
295 config
.hRestrictedRoot
= root
;
296 CertCreateCertificateChainEngine(&config
, &engine
);
297 CertCloseStore(root
, 0);
298 CertCloseStore(trust
, 0);
303 /***********************************************************************
304 * CertTrustFinalPolicy (CRYPTDLG.@)
306 HRESULT WINAPI
CertTrustFinalPolicy(CRYPT_PROVIDER_DATA
*data
)
310 CERT_VERIFY_CERTIFICATE_TRUST
*pCert
= CRYPTDLG_GetVerifyData(data
);
312 TRACE("(%p)\n", data
);
314 if (data
->pWintrustData
->dwUIChoice
!= WTD_UI_NONE
)
315 FIXME("unimplemented for UI choice %d\n",
316 data
->pWintrustData
->dwUIChoice
);
320 CERT_CHAIN_PARA chainPara
;
321 HCERTCHAINENGINE engine
;
323 memset(&chainPara
, 0, sizeof(chainPara
));
324 chainPara
.cbSize
= sizeof(chainPara
);
325 if (CRYPTDLG_CheckOnlineCRL())
326 flags
|= CERT_CHAIN_REVOCATION_CHECK_END_CERT
;
327 engine
= CRYPTDLG_MakeEngine(pCert
);
328 GetSystemTimeAsFileTime(&data
->sftSystemTime
);
329 ret
= CRYPTDLG_IsCertAllowed(pCert
->pccert
);
332 PCCERT_CHAIN_CONTEXT chain
;
334 ret
= CertGetCertificateChain(engine
, pCert
->pccert
,
335 &data
->sftSystemTime
, NULL
, &chainPara
, flags
, NULL
, &chain
);
338 if (chain
->cChain
!= 1)
340 FIXME("unimplemented for more than 1 simple chain\n");
341 err
= TRUST_E_SUBJECT_FORM_UNKNOWN
;
344 else if ((ret
= CRYPTDLG_CopyChain(data
, chain
)))
346 if (CertVerifyTimeValidity(&data
->sftSystemTime
,
347 pCert
->pccert
->pCertInfo
))
350 err
= CERT_E_EXPIRED
;
354 err
= TRUST_E_SYSTEM_ERROR
;
355 CertFreeCertificateChain(chain
);
358 err
= TRUST_E_SUBJECT_NOT_TRUSTED
;
360 CertFreeCertificateChainEngine(engine
);
365 err
= TRUST_E_NOSIGNATURE
;
367 /* Oddly, native doesn't set the error in the trust step error location,
368 * probably because this action is more advisory than anything else.
369 * Instead it stores it as the final error, but the function "succeeds" in
373 data
->dwFinalError
= err
;
374 TRACE("returning %d (%08x)\n", S_OK
, data
->dwFinalError
);
378 /***********************************************************************
379 * CertViewPropertiesA (CRYPTDLG.@)
381 BOOL WINAPI
CertViewPropertiesA(CERT_VIEWPROPERTIES_STRUCT_A
*info
)
383 CERT_VIEWPROPERTIES_STRUCT_W infoW
;
387 TRACE("(%p)\n", info
);
389 memcpy(&infoW
, info
, sizeof(infoW
));
392 int len
= MultiByteToWideChar(CP_ACP
, 0, info
->szTitle
, -1, NULL
, 0);
394 title
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
397 MultiByteToWideChar(CP_ACP
, 0, info
->szTitle
, -1, title
, len
);
398 infoW
.szTitle
= title
;
406 ret
= CertViewPropertiesW(&infoW
);
407 HeapFree(GetProcessHeap(), 0, title
);
412 /***********************************************************************
413 * CertViewPropertiesW (CRYPTDLG.@)
415 BOOL WINAPI
CertViewPropertiesW(CERT_VIEWPROPERTIES_STRUCT_W
*info
)
417 static GUID cert_action_verify
= CERT_CERTIFICATE_ACTION_VERIFY
;
418 CERT_VERIFY_CERTIFICATE_TRUST trust
;
419 WINTRUST_BLOB_INFO blob
;
424 TRACE("(%p)\n", info
);
426 memset(&trust
, 0, sizeof(trust
));
427 trust
.cbSize
= sizeof(trust
);
428 trust
.pccert
= info
->pCertContext
;
429 trust
.cRootStores
= info
->cRootStores
;
430 trust
.rghstoreRoots
= info
->rghstoreRoots
;
431 trust
.cStores
= info
->cStores
;
432 trust
.rghstoreCAs
= info
->rghstoreCAs
;
433 trust
.cTrustStores
= info
->cTrustStores
;
434 trust
.rghstoreTrust
= info
->rghstoreTrust
;
435 memset(&blob
, 0, sizeof(blob
));
436 blob
.cbStruct
= sizeof(blob
);
437 blob
.cbMemObject
= sizeof(trust
);
438 blob
.pbMemObject
= (BYTE
*)&trust
;
439 memset(&wtd
, 0, sizeof(wtd
));
440 wtd
.cbStruct
= sizeof(wtd
);
441 wtd
.dwUIChoice
= WTD_UI_NONE
;
442 wtd
.dwUnionChoice
= WTD_CHOICE_BLOB
;
444 wtd
.dwStateAction
= WTD_STATEACTION_VERIFY
;
445 err
= WinVerifyTrust(NULL
, &cert_action_verify
, &wtd
);
446 if (err
== ERROR_SUCCESS
)
448 CRYPTUI_VIEWCERTIFICATE_STRUCTW uiInfo
;
449 BOOL propsChanged
= FALSE
;
451 memset(&uiInfo
, 0, sizeof(uiInfo
));
452 uiInfo
.dwSize
= sizeof(uiInfo
);
453 uiInfo
.hwndParent
= info
->hwndParent
;
455 CRYPTUI_DISABLE_ADDTOSTORE
| CRYPTUI_ENABLE_EDITPROPERTIES
;
456 uiInfo
.szTitle
= info
->szTitle
;
457 uiInfo
.pCertContext
= info
->pCertContext
;
458 uiInfo
.cPurposes
= info
->cArrayPurposes
;
459 uiInfo
.rgszPurposes
= (LPCSTR
*)info
->arrayPurposes
;
460 uiInfo
.u
.hWVTStateData
= wtd
.hWVTStateData
;
461 uiInfo
.fpCryptProviderDataTrustedUsage
= TRUE
;
462 uiInfo
.cPropSheetPages
= info
->cArrayPropSheetPages
;
463 uiInfo
.rgPropSheetPages
= info
->arrayPropSheetPages
;
464 uiInfo
.nStartPage
= info
->nStartPage
;
465 ret
= CryptUIDlgViewCertificateW(&uiInfo
, &propsChanged
);
466 wtd
.dwStateAction
= WTD_STATEACTION_CLOSE
;
467 WinVerifyTrust(NULL
, &cert_action_verify
, &wtd
);
474 static BOOL
CRYPT_FormatHexString(const BYTE
*pbEncoded
, DWORD cbEncoded
,
475 WCHAR
*str
, DWORD
*pcchStr
)
481 charsNeeded
= (cbEncoded
* 3);
486 *pcchStr
= charsNeeded
;
489 else if (*pcchStr
< charsNeeded
)
491 *pcchStr
= charsNeeded
;
492 SetLastError(ERROR_MORE_DATA
);
497 static const WCHAR fmt
[] = { '%','0','2','x',' ',0 };
498 static const WCHAR endFmt
[] = { '%','0','2','x',0 };
502 *pcchStr
= charsNeeded
;
505 for (i
= 0; i
< cbEncoded
; i
++)
507 if (i
< cbEncoded
- 1)
508 ptr
+= sprintfW(ptr
, fmt
, pbEncoded
[i
]);
510 ptr
+= sprintfW(ptr
, endFmt
, pbEncoded
[i
]);
520 static const WCHAR indent
[] = { ' ',' ',' ',' ',' ',0 };
521 static const WCHAR colonCrlf
[] = { ':','\r','\n',0 };
522 static const WCHAR colonSpace
[] = { ':',' ',0 };
523 static const WCHAR crlf
[] = { '\r','\n',0 };
524 static const WCHAR commaSep
[] = { ',',' ',0 };
526 static BOOL
CRYPT_FormatCPS(DWORD dwCertEncodingType
,
527 DWORD dwFormatStrType
, const BYTE
*pbEncoded
, DWORD cbEncoded
,
528 WCHAR
*str
, DWORD
*pcchStr
)
531 DWORD size
, charsNeeded
= 1;
532 CERT_NAME_VALUE
*cpsValue
;
534 if ((ret
= CryptDecodeObjectEx(dwCertEncodingType
, X509_UNICODE_ANY_STRING
,
535 pbEncoded
, cbEncoded
, CRYPT_DECODE_ALLOC_FLAG
, NULL
, &cpsValue
, &size
)))
537 LPCWSTR headingSep
, sep
;
538 DWORD headingSepLen
, sepLen
;
540 if (dwFormatStrType
& CRYPT_FORMAT_STR_MULTI_LINE
)
542 headingSep
= colonCrlf
;
547 headingSep
= colonSpace
;
550 sepLen
= strlenW(sep
);
551 headingSepLen
= strlenW(headingSep
);
553 if (dwFormatStrType
& CRYPT_FORMAT_STR_MULTI_LINE
)
555 charsNeeded
+= 3 * strlenW(indent
);
556 if (str
&& *pcchStr
>= charsNeeded
)
558 strcpyW(str
, indent
);
559 str
+= strlenW(indent
);
560 strcpyW(str
, indent
);
561 str
+= strlenW(indent
);
562 strcpyW(str
, indent
);
563 str
+= strlenW(indent
);
566 charsNeeded
+= cpsValue
->Value
.cbData
/ sizeof(WCHAR
);
567 if (str
&& *pcchStr
>= charsNeeded
)
569 strcpyW(str
, (LPWSTR
)cpsValue
->Value
.pbData
);
570 str
+= cpsValue
->Value
.cbData
/ sizeof(WCHAR
);
572 charsNeeded
+= sepLen
;
573 if (str
&& *pcchStr
>= charsNeeded
)
580 *pcchStr
= charsNeeded
;
581 else if (*pcchStr
< charsNeeded
)
583 *pcchStr
= charsNeeded
;
584 SetLastError(ERROR_MORE_DATA
);
588 *pcchStr
= charsNeeded
;
593 static BOOL
CRYPT_FormatUserNotice(DWORD dwCertEncodingType
,
594 DWORD dwFormatStrType
, const BYTE
*pbEncoded
, DWORD cbEncoded
,
595 WCHAR
*str
, DWORD
*pcchStr
)
598 DWORD size
, charsNeeded
= 1;
599 CERT_POLICY_QUALIFIER_USER_NOTICE
*notice
;
601 if ((ret
= CryptDecodeObjectEx(dwCertEncodingType
,
602 X509_PKIX_POLICY_QUALIFIER_USERNOTICE
, pbEncoded
, cbEncoded
,
603 CRYPT_DECODE_ALLOC_FLAG
, NULL
, ¬ice
, &size
)))
605 static const WCHAR numFmt
[] = { '%','d',0 };
606 CERT_POLICY_QUALIFIER_NOTICE_REFERENCE
*pNoticeRef
=
607 notice
->pNoticeReference
;
608 LPCWSTR headingSep
, sep
;
609 DWORD headingSepLen
, sepLen
;
610 LPWSTR noticeRef
, organization
, noticeNum
, noticeText
;
611 DWORD noticeRefLen
, organizationLen
, noticeNumLen
, noticeTextLen
;
612 WCHAR noticeNumStr
[11];
614 noticeRefLen
= LoadStringW(hInstance
, IDS_NOTICE_REF
,
615 (LPWSTR
)¬iceRef
, 0);
616 organizationLen
= LoadStringW(hInstance
, IDS_ORGANIZATION
,
617 (LPWSTR
)&organization
, 0);
618 noticeNumLen
= LoadStringW(hInstance
, IDS_NOTICE_NUM
,
619 (LPWSTR
)¬iceNum
, 0);
620 noticeTextLen
= LoadStringW(hInstance
, IDS_NOTICE_TEXT
,
621 (LPWSTR
)¬iceText
, 0);
622 if (dwFormatStrType
& CRYPT_FORMAT_STR_MULTI_LINE
)
624 headingSep
= colonCrlf
;
629 headingSep
= colonSpace
;
632 sepLen
= strlenW(sep
);
633 headingSepLen
= strlenW(headingSep
);
640 if (dwFormatStrType
& CRYPT_FORMAT_STR_MULTI_LINE
)
642 charsNeeded
+= 3 * strlenW(indent
);
643 if (str
&& *pcchStr
>= charsNeeded
)
645 strcpyW(str
, indent
);
646 str
+= strlenW(indent
);
647 strcpyW(str
, indent
);
648 str
+= strlenW(indent
);
649 strcpyW(str
, indent
);
650 str
+= strlenW(indent
);
653 charsNeeded
+= noticeRefLen
;
654 if (str
&& *pcchStr
>= charsNeeded
)
656 memcpy(str
, noticeRef
, noticeRefLen
* sizeof(WCHAR
));
659 charsNeeded
+= headingSepLen
;
660 if (str
&& *pcchStr
>= charsNeeded
)
662 strcpyW(str
, headingSep
);
663 str
+= headingSepLen
;
665 if (dwFormatStrType
& CRYPT_FORMAT_STR_MULTI_LINE
)
667 charsNeeded
+= 4 * strlenW(indent
);
668 if (str
&& *pcchStr
>= charsNeeded
)
670 strcpyW(str
, indent
);
671 str
+= strlenW(indent
);
672 strcpyW(str
, indent
);
673 str
+= strlenW(indent
);
674 strcpyW(str
, indent
);
675 str
+= strlenW(indent
);
676 strcpyW(str
, indent
);
677 str
+= strlenW(indent
);
680 charsNeeded
+= organizationLen
;
681 if (str
&& *pcchStr
>= charsNeeded
)
683 memcpy(str
, organization
, organizationLen
* sizeof(WCHAR
));
684 str
+= organizationLen
;
686 charsNeeded
+= strlen(pNoticeRef
->pszOrganization
);
687 if (str
&& *pcchStr
>= charsNeeded
)
688 for (src
= pNoticeRef
->pszOrganization
; src
&& *src
;
691 charsNeeded
+= sepLen
;
692 if (str
&& *pcchStr
>= charsNeeded
)
697 for (k
= 0; k
< pNoticeRef
->cNoticeNumbers
; k
++)
699 if (dwFormatStrType
& CRYPT_FORMAT_STR_MULTI_LINE
)
701 charsNeeded
+= 4 * strlenW(indent
);
702 if (str
&& *pcchStr
>= charsNeeded
)
704 strcpyW(str
, indent
);
705 str
+= strlenW(indent
);
706 strcpyW(str
, indent
);
707 str
+= strlenW(indent
);
708 strcpyW(str
, indent
);
709 str
+= strlenW(indent
);
710 strcpyW(str
, indent
);
711 str
+= strlenW(indent
);
714 charsNeeded
+= noticeNumLen
;
715 if (str
&& *pcchStr
>= charsNeeded
)
717 memcpy(str
, noticeNum
, noticeNumLen
* sizeof(WCHAR
));
720 sprintfW(noticeNumStr
, numFmt
, k
+ 1);
721 charsNeeded
+= strlenW(noticeNumStr
);
722 if (str
&& *pcchStr
>= charsNeeded
)
724 strcpyW(str
, noticeNumStr
);
725 str
+= strlenW(noticeNumStr
);
727 charsNeeded
+= sepLen
;
728 if (str
&& *pcchStr
>= charsNeeded
)
735 if (notice
->pszDisplayText
)
737 if (dwFormatStrType
& CRYPT_FORMAT_STR_MULTI_LINE
)
739 charsNeeded
+= 3 * strlenW(indent
);
740 if (str
&& *pcchStr
>= charsNeeded
)
742 strcpyW(str
, indent
);
743 str
+= strlenW(indent
);
744 strcpyW(str
, indent
);
745 str
+= strlenW(indent
);
746 strcpyW(str
, indent
);
747 str
+= strlenW(indent
);
750 charsNeeded
+= noticeTextLen
;
751 if (str
&& *pcchStr
>= charsNeeded
)
753 memcpy(str
, noticeText
, noticeTextLen
* sizeof(WCHAR
));
754 str
+= noticeTextLen
;
756 charsNeeded
+= strlenW(notice
->pszDisplayText
);
757 if (str
&& *pcchStr
>= charsNeeded
)
759 strcpyW(str
, notice
->pszDisplayText
);
760 str
+= strlenW(notice
->pszDisplayText
);
762 charsNeeded
+= sepLen
;
763 if (str
&& *pcchStr
>= charsNeeded
)
771 *pcchStr
= charsNeeded
;
772 else if (*pcchStr
< charsNeeded
)
774 *pcchStr
= charsNeeded
;
775 SetLastError(ERROR_MORE_DATA
);
779 *pcchStr
= charsNeeded
;
784 /***********************************************************************
785 * FormatVerisignExtension (CRYPTDLG.@)
787 BOOL WINAPI
FormatVerisignExtension(DWORD dwCertEncodingType
,
788 DWORD dwFormatType
, DWORD dwFormatStrType
, void *pFormatStruct
,
789 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, void *pbFormat
,
792 CERT_POLICIES_INFO
*policies
;
798 SetLastError(E_INVALIDARG
);
801 if ((ret
= CryptDecodeObjectEx(dwCertEncodingType
, X509_CERT_POLICIES
,
802 pbEncoded
, cbEncoded
, CRYPT_DECODE_ALLOC_FLAG
, NULL
, &policies
, &size
)))
804 static const WCHAR numFmt
[] = { '%','d',0 };
805 DWORD charsNeeded
= 1; /* space for NULL terminator */
806 LPCWSTR headingSep
, sep
;
807 DWORD headingSepLen
, sepLen
;
808 WCHAR policyNum
[11], policyQualifierNum
[11];
809 LPWSTR certPolicy
, policyId
, policyQualifierInfo
, policyQualifierId
;
810 LPWSTR cps
, userNotice
, qualifier
;
811 DWORD certPolicyLen
, policyIdLen
, policyQualifierInfoLen
;
812 DWORD policyQualifierIdLen
, cpsLen
, userNoticeLen
, qualifierLen
;
814 LPWSTR str
= pbFormat
;
816 certPolicyLen
= LoadStringW(hInstance
, IDS_CERT_POLICY
,
817 (LPWSTR
)&certPolicy
, 0);
818 policyIdLen
= LoadStringW(hInstance
, IDS_POLICY_ID
, (LPWSTR
)&policyId
,
820 policyQualifierInfoLen
= LoadStringW(hInstance
,
821 IDS_POLICY_QUALIFIER_INFO
, (LPWSTR
)&policyQualifierInfo
, 0);
822 policyQualifierIdLen
= LoadStringW(hInstance
, IDS_POLICY_QUALIFIER_ID
,
823 (LPWSTR
)&policyQualifierId
, 0);
824 cpsLen
= LoadStringW(hInstance
, IDS_CPS
, (LPWSTR
)&cps
, 0);
825 userNoticeLen
= LoadStringW(hInstance
, IDS_USER_NOTICE
,
826 (LPWSTR
)&userNotice
, 0);
827 qualifierLen
= LoadStringW(hInstance
, IDS_QUALIFIER
,
828 (LPWSTR
)&qualifier
, 0);
829 if (dwFormatStrType
& CRYPT_FORMAT_STR_MULTI_LINE
)
831 headingSep
= colonCrlf
;
836 headingSep
= colonSpace
;
839 sepLen
= strlenW(sep
);
840 headingSepLen
= strlenW(headingSep
);
842 for (i
= 0; ret
&& i
< policies
->cPolicyInfo
; i
++)
844 CERT_POLICY_INFO
*policy
= &policies
->rgPolicyInfo
[i
];
848 charsNeeded
+= 1; /* '['*/
849 if (str
&& *pcbFormat
>= charsNeeded
* sizeof(WCHAR
))
851 sprintfW(policyNum
, numFmt
, i
+ 1);
852 charsNeeded
+= strlenW(policyNum
);
853 if (str
&& *pcbFormat
>= charsNeeded
* sizeof(WCHAR
))
855 strcpyW(str
, policyNum
);
856 str
+= strlenW(policyNum
);
858 charsNeeded
+= 1; /* ']'*/
859 if (str
&& *pcbFormat
>= charsNeeded
* sizeof(WCHAR
))
861 charsNeeded
+= certPolicyLen
;
862 if (str
&& *pcbFormat
>= charsNeeded
* sizeof(WCHAR
))
864 memcpy(str
, certPolicy
, certPolicyLen
* sizeof(WCHAR
));
865 str
+= certPolicyLen
;
867 charsNeeded
+= headingSepLen
;
868 if (str
&& *pcbFormat
>= charsNeeded
* sizeof(WCHAR
))
870 strcpyW(str
, headingSep
);
871 str
+= headingSepLen
;
873 if (dwFormatStrType
& CRYPT_FORMAT_STR_MULTI_LINE
)
875 charsNeeded
+= strlenW(indent
);
876 if (str
&& *pcbFormat
>= charsNeeded
* sizeof(WCHAR
))
878 strcpyW(str
, indent
);
879 str
+= strlenW(indent
);
882 charsNeeded
+= policyIdLen
;
883 if (str
&& *pcbFormat
>= charsNeeded
* sizeof(WCHAR
))
885 memcpy(str
, policyId
, policyIdLen
* sizeof(WCHAR
));
888 charsNeeded
+= strlen(policy
->pszPolicyIdentifier
);
889 if (str
&& *pcbFormat
>= charsNeeded
* sizeof(WCHAR
))
891 for (src
= policy
->pszPolicyIdentifier
; src
&& *src
;
895 charsNeeded
+= sepLen
;
896 if (str
&& *pcbFormat
>= charsNeeded
* sizeof(WCHAR
))
901 for (j
= 0; j
< policy
->cPolicyQualifier
; j
++)
903 CERT_POLICY_QUALIFIER_INFO
*qualifierInfo
=
904 &policy
->rgPolicyQualifier
[j
];
907 if (dwFormatStrType
& CRYPT_FORMAT_STR_MULTI_LINE
)
909 charsNeeded
+= strlenW(indent
);
910 if (str
&& *pcbFormat
>= charsNeeded
* sizeof(WCHAR
))
912 strcpyW(str
, indent
);
913 str
+= strlenW(indent
);
916 charsNeeded
+= 1; /* '['*/
917 if (str
&& *pcbFormat
>= charsNeeded
* sizeof(WCHAR
))
919 charsNeeded
+= strlenW(policyNum
);
920 if (str
&& *pcbFormat
>= charsNeeded
* sizeof(WCHAR
))
922 strcpyW(str
, policyNum
);
923 str
+= strlenW(policyNum
);
925 charsNeeded
+= 1; /* ','*/
926 if (str
&& *pcbFormat
>= charsNeeded
* sizeof(WCHAR
))
928 sprintfW(policyQualifierNum
, numFmt
, j
+ 1);
929 charsNeeded
+= strlenW(policyQualifierNum
);
930 if (str
&& *pcbFormat
>= charsNeeded
* sizeof(WCHAR
))
932 strcpyW(str
, policyQualifierNum
);
933 str
+= strlenW(policyQualifierNum
);
935 charsNeeded
+= 1; /* ']'*/
936 if (str
&& *pcbFormat
>= charsNeeded
* sizeof(WCHAR
))
938 charsNeeded
+= policyQualifierInfoLen
;
939 if (str
&& *pcbFormat
>= charsNeeded
* sizeof(WCHAR
))
941 memcpy(str
, policyQualifierInfo
,
942 policyQualifierInfoLen
* sizeof(WCHAR
));
943 str
+= policyQualifierInfoLen
;
945 charsNeeded
+= headingSepLen
;
946 if (str
&& *pcbFormat
>= charsNeeded
* sizeof(WCHAR
))
948 strcpyW(str
, headingSep
);
949 str
+= headingSepLen
;
951 if (dwFormatStrType
& CRYPT_FORMAT_STR_MULTI_LINE
)
953 charsNeeded
+= 2 * strlenW(indent
);
954 if (str
&& *pcbFormat
>= charsNeeded
* sizeof(WCHAR
))
956 strcpyW(str
, indent
);
957 str
+= strlenW(indent
);
958 strcpyW(str
, indent
);
959 str
+= strlenW(indent
);
962 charsNeeded
+= policyQualifierIdLen
;
963 if (str
&& *pcbFormat
>= charsNeeded
* sizeof(WCHAR
))
965 memcpy(str
, policyQualifierId
,
966 policyQualifierIdLen
* sizeof(WCHAR
));
967 str
+= policyQualifierIdLen
;
969 if (!strcmp(qualifierInfo
->pszPolicyQualifierId
,
970 szOID_PKIX_POLICY_QUALIFIER_CPS
))
972 charsNeeded
+= cpsLen
;
973 if (str
&& *pcbFormat
>= charsNeeded
* sizeof(WCHAR
))
975 memcpy(str
, cps
, cpsLen
* sizeof(WCHAR
));
979 else if (!strcmp(qualifierInfo
->pszPolicyQualifierId
,
980 szOID_PKIX_POLICY_QUALIFIER_USERNOTICE
))
982 charsNeeded
+= userNoticeLen
;
983 if (str
&& *pcbFormat
>= charsNeeded
* sizeof(WCHAR
))
985 memcpy(str
, userNotice
, userNoticeLen
* sizeof(WCHAR
));
986 str
+= userNoticeLen
;
991 charsNeeded
+= strlen(qualifierInfo
->pszPolicyQualifierId
);
992 if (str
&& *pcbFormat
>= charsNeeded
* sizeof(WCHAR
))
994 for (src
= qualifierInfo
->pszPolicyQualifierId
;
995 src
&& *src
; src
++, str
++)
999 charsNeeded
+= sepLen
;
1000 if (str
&& *pcbFormat
>= charsNeeded
* sizeof(WCHAR
))
1005 if (dwFormatStrType
& CRYPT_FORMAT_STR_MULTI_LINE
)
1007 charsNeeded
+= 2 * strlenW(indent
);
1008 if (str
&& *pcbFormat
>= charsNeeded
* sizeof(WCHAR
))
1010 strcpyW(str
, indent
);
1011 str
+= strlenW(indent
);
1012 strcpyW(str
, indent
);
1013 str
+= strlenW(indent
);
1016 charsNeeded
+= qualifierLen
;
1017 if (str
&& *pcbFormat
>= charsNeeded
* sizeof(WCHAR
))
1019 memcpy(str
, qualifier
, qualifierLen
* sizeof(WCHAR
));
1020 str
+= qualifierLen
;
1022 charsNeeded
+= headingSepLen
;
1023 if (str
&& *pcbFormat
>= charsNeeded
* sizeof(WCHAR
))
1025 strcpyW(str
, headingSep
);
1026 str
+= headingSepLen
;
1028 /* This if block is deliberately redundant with the same if
1029 * block above, in order to keep the code more readable (the
1030 * code flow follows the order in which the strings are output.)
1032 if (!strcmp(qualifierInfo
->pszPolicyQualifierId
,
1033 szOID_PKIX_POLICY_QUALIFIER_CPS
))
1035 if (!str
|| *pcbFormat
< charsNeeded
* sizeof(WCHAR
))
1037 /* Insufficient space, determine how much is needed. */
1038 ret
= CRYPT_FormatCPS(dwCertEncodingType
,
1039 dwFormatStrType
, qualifierInfo
->Qualifier
.pbData
,
1040 qualifierInfo
->Qualifier
.cbData
, NULL
, &size
);
1042 charsNeeded
+= size
- 1;
1046 sizeRemaining
= *pcbFormat
/ sizeof(WCHAR
);
1047 sizeRemaining
-= str
- (LPWSTR
)pbFormat
;
1048 ret
= CRYPT_FormatCPS(dwCertEncodingType
,
1049 dwFormatStrType
, qualifierInfo
->Qualifier
.pbData
,
1050 qualifierInfo
->Qualifier
.cbData
, str
, &sizeRemaining
);
1051 if (ret
|| GetLastError() == ERROR_MORE_DATA
)
1053 charsNeeded
+= sizeRemaining
- 1;
1054 str
+= sizeRemaining
- 1;
1058 else if (!strcmp(qualifierInfo
->pszPolicyQualifierId
,
1059 szOID_PKIX_POLICY_QUALIFIER_USERNOTICE
))
1061 if (!str
|| *pcbFormat
< charsNeeded
* sizeof(WCHAR
))
1063 /* Insufficient space, determine how much is needed. */
1064 ret
= CRYPT_FormatUserNotice(dwCertEncodingType
,
1065 dwFormatStrType
, qualifierInfo
->Qualifier
.pbData
,
1066 qualifierInfo
->Qualifier
.cbData
, NULL
, &size
);
1068 charsNeeded
+= size
- 1;
1072 sizeRemaining
= *pcbFormat
/ sizeof(WCHAR
);
1073 sizeRemaining
-= str
- (LPWSTR
)pbFormat
;
1074 ret
= CRYPT_FormatUserNotice(dwCertEncodingType
,
1075 dwFormatStrType
, qualifierInfo
->Qualifier
.pbData
,
1076 qualifierInfo
->Qualifier
.cbData
, str
, &sizeRemaining
);
1077 if (ret
|| GetLastError() == ERROR_MORE_DATA
)
1079 charsNeeded
+= sizeRemaining
- 1;
1080 str
+= sizeRemaining
- 1;
1086 if (!str
|| *pcbFormat
< charsNeeded
* sizeof(WCHAR
))
1088 /* Insufficient space, determine how much is needed. */
1089 ret
= CRYPT_FormatHexString(
1090 qualifierInfo
->Qualifier
.pbData
,
1091 qualifierInfo
->Qualifier
.cbData
, NULL
, &size
);
1093 charsNeeded
+= size
- 1;
1097 sizeRemaining
= *pcbFormat
/ sizeof(WCHAR
);
1098 sizeRemaining
-= str
- (LPWSTR
)pbFormat
;
1099 ret
= CRYPT_FormatHexString(
1100 qualifierInfo
->Qualifier
.pbData
,
1101 qualifierInfo
->Qualifier
.cbData
, str
, &sizeRemaining
);
1102 if (ret
|| GetLastError() == ERROR_MORE_DATA
)
1104 charsNeeded
+= sizeRemaining
- 1;
1105 str
+= sizeRemaining
- 1;
1111 LocalFree(policies
);
1115 *pcbFormat
= charsNeeded
* sizeof(WCHAR
);
1116 else if (*pcbFormat
< charsNeeded
* sizeof(WCHAR
))
1118 *pcbFormat
= charsNeeded
* sizeof(WCHAR
);
1119 SetLastError(ERROR_MORE_DATA
);
1123 *pcbFormat
= charsNeeded
* sizeof(WCHAR
);
1129 #define szOID_MICROSOFT_Encryption_Key_Preference "1.3.6.1.4.1.311.16.4"
1131 /***********************************************************************
1132 * DllRegisterServer (CRYPTDLG.@)
1134 HRESULT WINAPI
DllRegisterServer(void)
1136 static WCHAR cryptdlg
[] = { 'c','r','y','p','t','d','l','g','.',
1138 static WCHAR wintrust
[] = { 'w','i','n','t','r','u','s','t','.',
1140 static WCHAR certTrustInit
[] = { 'C','e','r','t','T','r','u','s','t',
1141 'I','n','i','t',0 };
1142 static WCHAR wintrustCertificateTrust
[] = { 'W','i','n','t','r','u','s','t',
1143 'C','e','r','t','i','f','i','c','a','t','e','T','r','u','s','t',0 };
1144 static WCHAR certTrustCertPolicy
[] = { 'C','e','r','t','T','r','u','s','t',
1145 'C','e','r','t','P','o','l','i','c','y',0 };
1146 static WCHAR certTrustFinalPolicy
[] = { 'C','e','r','t','T','r','u','s','t',
1147 'F','i','n','a','l','P','o','l','i','c','y',0 };
1148 static WCHAR certTrustCleanup
[] = { 'C','e','r','t','T','r','u','s','t',
1149 'C','l','e','a','n','u','p',0 };
1150 static const WCHAR cryptDlg
[] = { 'c','r','y','p','t','d','l','g','.',
1152 CRYPT_REGISTER_ACTIONID reg
;
1153 GUID guid
= CERT_CERTIFICATE_ACTION_VERIFY
;
1156 memset(®
, 0, sizeof(reg
));
1157 reg
.cbStruct
= sizeof(reg
);
1158 reg
.sInitProvider
.cbStruct
= sizeof(CRYPT_TRUST_REG_ENTRY
);
1159 reg
.sInitProvider
.pwszDLLName
= cryptdlg
;
1160 reg
.sInitProvider
.pwszFunctionName
= certTrustInit
;
1161 reg
.sCertificateProvider
.cbStruct
= sizeof(CRYPT_TRUST_REG_ENTRY
);
1162 reg
.sCertificateProvider
.pwszDLLName
= wintrust
;
1163 reg
.sCertificateProvider
.pwszFunctionName
= wintrustCertificateTrust
;
1164 reg
.sCertificatePolicyProvider
.cbStruct
= sizeof(CRYPT_TRUST_REG_ENTRY
);
1165 reg
.sCertificatePolicyProvider
.pwszDLLName
= cryptdlg
;
1166 reg
.sCertificatePolicyProvider
.pwszFunctionName
= certTrustCertPolicy
;
1167 reg
.sFinalPolicyProvider
.cbStruct
= sizeof(CRYPT_TRUST_REG_ENTRY
);
1168 reg
.sFinalPolicyProvider
.pwszDLLName
= cryptdlg
;
1169 reg
.sFinalPolicyProvider
.pwszFunctionName
= certTrustFinalPolicy
;
1170 reg
.sCleanupProvider
.cbStruct
= sizeof(CRYPT_TRUST_REG_ENTRY
);
1171 reg
.sCleanupProvider
.pwszDLLName
= cryptdlg
;
1172 reg
.sCleanupProvider
.pwszFunctionName
= certTrustCleanup
;
1173 if (!WintrustAddActionID(&guid
, WT_ADD_ACTION_ID_RET_RESULT_FLAG
, ®
))
1174 hr
= GetLastError();
1175 CryptRegisterOIDFunction(X509_ASN_ENCODING
, CRYPT_OID_ENCODE_OBJECT_FUNC
,
1176 "1.3.6.1.4.1.311.16.1.1", cryptDlg
, "EncodeAttrSequence");
1177 CryptRegisterOIDFunction(X509_ASN_ENCODING
, CRYPT_OID_ENCODE_OBJECT_FUNC
,
1178 szOID_MICROSOFT_Encryption_Key_Preference
, cryptDlg
, "EncodeRecipientID");
1179 CryptRegisterOIDFunction(X509_ASN_ENCODING
, CRYPT_OID_DECODE_OBJECT_FUNC
,
1180 "1.3.6.1.4.1.311.16.1.1", cryptDlg
, "DecodeAttrSequence");
1181 CryptRegisterOIDFunction(X509_ASN_ENCODING
, CRYPT_OID_DECODE_OBJECT_FUNC
,
1182 szOID_MICROSOFT_Encryption_Key_Preference
, cryptDlg
, "DecodeRecipientID");
1183 CryptRegisterOIDFunction(X509_ASN_ENCODING
, CRYPT_OID_FORMAT_OBJECT_FUNC
,
1184 szOID_PKIX_KP_EMAIL_PROTECTION
, cryptDlg
, "FormatPKIXEmailProtection");
1185 CryptRegisterOIDFunction(X509_ASN_ENCODING
, CRYPT_OID_FORMAT_OBJECT_FUNC
,
1186 szOID_CERT_POLICIES
, cryptDlg
, "FormatVerisignExtension");
1190 /***********************************************************************
1191 * DllUnregisterServer (CRYPTDLG.@)
1193 HRESULT WINAPI
DllUnregisterServer(void)
1195 GUID guid
= CERT_CERTIFICATE_ACTION_VERIFY
;
1197 WintrustRemoveActionID(&guid
);
1198 CryptUnregisterOIDFunction(X509_ASN_ENCODING
, CRYPT_OID_ENCODE_OBJECT_FUNC
,
1199 "1.3.6.1.4.1.311.16.1.1");
1200 CryptUnregisterOIDFunction(X509_ASN_ENCODING
, CRYPT_OID_ENCODE_OBJECT_FUNC
,
1201 szOID_MICROSOFT_Encryption_Key_Preference
);
1202 CryptUnregisterOIDFunction(X509_ASN_ENCODING
, CRYPT_OID_DECODE_OBJECT_FUNC
,
1203 "1.3.6.1.4.1.311.16.1.1");
1204 CryptUnregisterOIDFunction(X509_ASN_ENCODING
, CRYPT_OID_DECODE_OBJECT_FUNC
,
1205 szOID_MICROSOFT_Encryption_Key_Preference
);
1206 CryptUnregisterOIDFunction(X509_ASN_ENCODING
, CRYPT_OID_FORMAT_OBJECT_FUNC
,
1207 szOID_PKIX_KP_EMAIL_PROTECTION
);
1208 CryptUnregisterOIDFunction(X509_ASN_ENCODING
, CRYPT_OID_FORMAT_OBJECT_FUNC
,
1209 szOID_CERT_POLICIES
);