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, %d, %p)\n", hinstDLL
, fdwReason
, lpvReserved
);
46 case DLL_WINE_PREATTACH
:
47 return FALSE
; /* prefer native version */
48 case DLL_PROCESS_ATTACH
:
49 DisableThreadLibraryCalls(hinstDLL
);
56 /***********************************************************************
57 * GetFriendlyNameOfCertA (CRYPTDLG.@)
59 DWORD WINAPI
GetFriendlyNameOfCertA(PCCERT_CONTEXT pccert
, LPSTR pchBuffer
,
62 return CertGetNameStringA(pccert
, CERT_NAME_FRIENDLY_DISPLAY_TYPE
, 0, NULL
,
63 pchBuffer
, cchBuffer
);
66 /***********************************************************************
67 * GetFriendlyNameOfCertW (CRYPTDLG.@)
69 DWORD WINAPI
GetFriendlyNameOfCertW(PCCERT_CONTEXT pccert
, LPWSTR pchBuffer
,
72 return CertGetNameStringW(pccert
, CERT_NAME_FRIENDLY_DISPLAY_TYPE
, 0, NULL
,
73 pchBuffer
, cchBuffer
);
76 /***********************************************************************
77 * CertTrustInit (CRYPTDLG.@)
79 HRESULT WINAPI
CertTrustInit(CRYPT_PROVIDER_DATA
*pProvData
)
81 HRESULT ret
= S_FALSE
;
83 TRACE("(%p)\n", pProvData
);
85 if (pProvData
->padwTrustStepErrors
&&
86 !pProvData
->padwTrustStepErrors
[TRUSTERROR_STEP_FINAL_WVTINIT
])
88 TRACE("returning %08x\n", ret
);
92 /***********************************************************************
93 * CertTrustCertPolicy (CRYPTDLG.@)
95 BOOL WINAPI
CertTrustCertPolicy(CRYPT_PROVIDER_DATA
*pProvData
, DWORD idxSigner
, BOOL fCounterSignerChain
, DWORD idxCounterSigner
)
97 FIXME("(%p, %d, %s, %d)\n", pProvData
, idxSigner
, fCounterSignerChain
? "TRUE" : "FALSE", idxCounterSigner
);
101 /***********************************************************************
102 * CertTrustCleanup (CRYPTDLG.@)
104 HRESULT WINAPI
CertTrustCleanup(CRYPT_PROVIDER_DATA
*pProvData
)
106 FIXME("(%p)\n", pProvData
);
110 static BOOL
CRYPTDLG_CheckOnlineCRL(void)
112 static const WCHAR policyFlagsKey
[] = { 'S','o','f','t','w','a','r','e',
113 '\\','M','i','c','r','o','s','o','f','t','\\','C','r','y','p','t','o','g',
114 'r','a','p','h','y','\\','{','7','8','0','1','e','b','d','0','-','c','f',
115 '4','b','-','1','1','d','0','-','8','5','1','f','-','0','0','6','0','9',
116 '7','9','3','8','7','e','a','}',0 };
117 static const WCHAR policyFlags
[] = { 'P','o','l','i','c','y','F','l','a',
122 if (!RegOpenKeyExW(HKEY_LOCAL_MACHINE
, policyFlagsKey
, 0, KEY_READ
, &key
))
124 DWORD type
, flags
, size
= sizeof(flags
);
126 if (!RegQueryValueExW(key
, policyFlags
, NULL
, &type
, (BYTE
*)&flags
,
127 &size
) && type
== REG_DWORD
)
129 /* The flag values aren't defined in any header I'm aware of, but
130 * this value is well documented on the net.
132 if (flags
& 0x00010000)
140 /* Returns TRUE if pCert is not in the Disallowed system store, or FALSE if it
143 static BOOL
CRYPTDLG_IsCertAllowed(PCCERT_CONTEXT pCert
)
147 DWORD size
= sizeof(hash
);
149 if ((ret
= CertGetCertificateContextProperty(pCert
,
150 CERT_SIGNATURE_HASH_PROP_ID
, hash
, &size
)))
152 static const WCHAR disallowedW
[] =
153 { 'D','i','s','a','l','l','o','w','e','d',0 };
154 HCERTSTORE disallowed
= CertOpenStore(CERT_STORE_PROV_SYSTEM_W
,
155 X509_ASN_ENCODING
, 0, CERT_SYSTEM_STORE_CURRENT_USER
, disallowedW
);
159 PCCERT_CONTEXT found
= CertFindCertificateInStore(disallowed
,
160 X509_ASN_ENCODING
, 0, CERT_FIND_SIGNATURE_HASH
, hash
, NULL
);
165 CertFreeCertificateContext(found
);
167 CertCloseStore(disallowed
, 0);
173 static DWORD
CRYPTDLG_TrustStatusToConfidence(DWORD errorStatus
)
175 DWORD confidence
= 0;
178 if (!(errorStatus
& CERT_TRUST_IS_NOT_SIGNATURE_VALID
))
179 confidence
|= CERT_CONFIDENCE_SIG
;
180 if (!(errorStatus
& CERT_TRUST_IS_NOT_TIME_VALID
))
181 confidence
|= CERT_CONFIDENCE_TIME
;
182 if (!(errorStatus
& CERT_TRUST_IS_NOT_TIME_NESTED
))
183 confidence
|= CERT_CONFIDENCE_TIMENEST
;
187 static BOOL
CRYPTDLG_CopyChain(CRYPT_PROVIDER_DATA
*data
,
188 PCCERT_CHAIN_CONTEXT chain
)
191 CRYPT_PROVIDER_SGNR signer
;
192 PCERT_SIMPLE_CHAIN simpleChain
= chain
->rgpChain
[0];
195 memset(&signer
, 0, sizeof(signer
));
196 signer
.cbStruct
= sizeof(signer
);
197 ret
= data
->psPfns
->pfnAddSgnr2Chain(data
, FALSE
, 0, &signer
);
200 CRYPT_PROVIDER_SGNR
*sgnr
= WTHelperGetProvSignerFromChain(data
, 0,
205 sgnr
->dwError
= simpleChain
->TrustStatus
.dwErrorStatus
;
206 sgnr
->pChainContext
= CertDuplicateCertificateChain(chain
);
210 for (i
= 0; ret
&& i
< simpleChain
->cElement
; i
++)
212 ret
= data
->psPfns
->pfnAddCert2Chain(data
, 0, FALSE
, 0,
213 simpleChain
->rgpElement
[i
]->pCertContext
);
216 CRYPT_PROVIDER_CERT
*cert
;
218 if ((cert
= WTHelperGetProvCertFromChain(sgnr
, i
)))
220 CERT_CHAIN_ELEMENT
*element
= simpleChain
->rgpElement
[i
];
222 cert
->dwConfidence
= CRYPTDLG_TrustStatusToConfidence(
223 element
->TrustStatus
.dwErrorStatus
);
224 cert
->dwError
= element
->TrustStatus
.dwErrorStatus
;
225 cert
->pChainElement
= element
;
235 static CERT_VERIFY_CERTIFICATE_TRUST
*CRYPTDLG_GetVerifyData(
236 CRYPT_PROVIDER_DATA
*data
)
238 CERT_VERIFY_CERTIFICATE_TRUST
*pCert
= NULL
;
240 /* This should always be true, but just in case the calling function is
243 if (data
->pWintrustData
->dwUnionChoice
== WTD_CHOICE_BLOB
&&
244 data
->pWintrustData
->u
.pBlob
&& data
->pWintrustData
->u
.pBlob
->cbMemObject
==
245 sizeof(CERT_VERIFY_CERTIFICATE_TRUST
) &&
246 data
->pWintrustData
->u
.pBlob
->pbMemObject
)
247 pCert
= (CERT_VERIFY_CERTIFICATE_TRUST
*)
248 data
->pWintrustData
->u
.pBlob
->pbMemObject
;
252 static HCERTCHAINENGINE
CRYPTDLG_MakeEngine(CERT_VERIFY_CERTIFICATE_TRUST
*cert
)
254 HCERTCHAINENGINE engine
= NULL
;
255 HCERTSTORE root
= NULL
, trust
= NULL
;
258 if (cert
->cRootStores
)
260 root
= CertOpenStore(CERT_STORE_PROV_COLLECTION
, 0, 0,
261 CERT_STORE_CREATE_NEW_FLAG
, NULL
);
264 for (i
= 0; i
< cert
->cRootStores
; i
++)
265 CertAddStoreToCollection(root
, cert
->rghstoreRoots
[i
], 0, 0);
268 if (cert
->cTrustStores
)
270 trust
= CertOpenStore(CERT_STORE_PROV_COLLECTION
, 0, 0,
271 CERT_STORE_CREATE_NEW_FLAG
, NULL
);
274 for (i
= 0; i
< cert
->cTrustStores
; i
++)
275 CertAddStoreToCollection(trust
, cert
->rghstoreTrust
[i
], 0, 0);
278 if (cert
->cRootStores
|| cert
->cStores
|| cert
->cTrustStores
)
280 CERT_CHAIN_ENGINE_CONFIG config
;
282 memset(&config
, 0, sizeof(config
));
283 config
.cbSize
= sizeof(config
);
284 config
.hRestrictedRoot
= root
;
285 config
.hRestrictedTrust
= trust
;
286 config
.cAdditionalStore
= cert
->cStores
;
287 config
.rghAdditionalStore
= cert
->rghstoreCAs
;
288 config
.hRestrictedRoot
= root
;
289 CertCreateCertificateChainEngine(&config
, &engine
);
290 CertCloseStore(root
, 0);
291 CertCloseStore(trust
, 0);
296 /***********************************************************************
297 * CertTrustFinalPolicy (CRYPTDLG.@)
299 HRESULT WINAPI
CertTrustFinalPolicy(CRYPT_PROVIDER_DATA
*data
)
303 CERT_VERIFY_CERTIFICATE_TRUST
*pCert
= CRYPTDLG_GetVerifyData(data
);
305 TRACE("(%p)\n", data
);
307 if (data
->pWintrustData
->dwUIChoice
!= WTD_UI_NONE
)
308 FIXME("unimplemented for UI choice %d\n",
309 data
->pWintrustData
->dwUIChoice
);
313 CERT_CHAIN_PARA chainPara
;
314 HCERTCHAINENGINE engine
;
316 memset(&chainPara
, 0, sizeof(chainPara
));
317 chainPara
.cbSize
= sizeof(chainPara
);
318 if (CRYPTDLG_CheckOnlineCRL())
319 flags
|= CERT_CHAIN_REVOCATION_CHECK_END_CERT
;
320 engine
= CRYPTDLG_MakeEngine(pCert
);
321 GetSystemTimeAsFileTime(&data
->sftSystemTime
);
322 ret
= CRYPTDLG_IsCertAllowed(pCert
->pccert
);
325 PCCERT_CHAIN_CONTEXT chain
;
327 ret
= CertGetCertificateChain(engine
, pCert
->pccert
,
328 &data
->sftSystemTime
, NULL
, &chainPara
, flags
, NULL
, &chain
);
331 if (chain
->cChain
!= 1)
333 FIXME("unimplemented for more than 1 simple chain\n");
334 err
= TRUST_E_SUBJECT_FORM_UNKNOWN
;
337 else if ((ret
= CRYPTDLG_CopyChain(data
, chain
)))
339 if (CertVerifyTimeValidity(&data
->sftSystemTime
,
340 pCert
->pccert
->pCertInfo
))
343 err
= CERT_E_EXPIRED
;
347 err
= TRUST_E_SYSTEM_ERROR
;
348 CertFreeCertificateChain(chain
);
351 err
= TRUST_E_SUBJECT_NOT_TRUSTED
;
353 CertFreeCertificateChainEngine(engine
);
358 err
= TRUST_E_NOSIGNATURE
;
360 /* Oddly, native doesn't set the error in the trust step error location,
361 * probably because this action is more advisory than anything else.
362 * Instead it stores it as the final error, but the function "succeeds" in
366 data
->dwFinalError
= err
;
367 TRACE("returning %d (%08x)\n", S_OK
, data
->dwFinalError
);
371 /***********************************************************************
372 * CertViewPropertiesA (CRYPTDLG.@)
374 BOOL WINAPI
CertViewPropertiesA(CERT_VIEWPROPERTIES_STRUCT_A
*info
)
376 CERT_VIEWPROPERTIES_STRUCT_W infoW
;
380 TRACE("(%p)\n", info
);
382 memcpy(&infoW
, info
, sizeof(infoW
));
385 int len
= MultiByteToWideChar(CP_ACP
, 0, info
->szTitle
, -1, NULL
, 0);
387 title
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
390 MultiByteToWideChar(CP_ACP
, 0, info
->szTitle
, -1, title
, len
);
391 infoW
.szTitle
= title
;
399 ret
= CertViewPropertiesW(&infoW
);
400 HeapFree(GetProcessHeap(), 0, title
);
405 /***********************************************************************
406 * CertViewPropertiesW (CRYPTDLG.@)
408 BOOL WINAPI
CertViewPropertiesW(CERT_VIEWPROPERTIES_STRUCT_W
*info
)
410 static GUID cert_action_verify
= CERT_CERTIFICATE_ACTION_VERIFY
;
411 CERT_VERIFY_CERTIFICATE_TRUST trust
;
412 WINTRUST_BLOB_INFO blob
;
417 TRACE("(%p)\n", info
);
419 memset(&trust
, 0, sizeof(trust
));
420 trust
.cbSize
= sizeof(trust
);
421 trust
.pccert
= info
->pCertContext
;
422 trust
.cRootStores
= info
->cRootStores
;
423 trust
.rghstoreRoots
= info
->rghstoreRoots
;
424 trust
.cStores
= info
->cStores
;
425 trust
.rghstoreCAs
= info
->rghstoreCAs
;
426 trust
.cTrustStores
= info
->cTrustStores
;
427 trust
.rghstoreTrust
= info
->rghstoreTrust
;
428 memset(&blob
, 0, sizeof(blob
));
429 blob
.cbStruct
= sizeof(blob
);
430 blob
.cbMemObject
= sizeof(trust
);
431 blob
.pbMemObject
= (BYTE
*)&trust
;
432 memset(&wtd
, 0, sizeof(wtd
));
433 wtd
.cbStruct
= sizeof(wtd
);
434 wtd
.dwUIChoice
= WTD_UI_NONE
;
435 wtd
.dwUnionChoice
= WTD_CHOICE_BLOB
;
437 wtd
.dwStateAction
= WTD_STATEACTION_VERIFY
;
438 err
= WinVerifyTrust(NULL
, &cert_action_verify
, &wtd
);
439 if (err
== ERROR_SUCCESS
)
441 CRYPTUI_VIEWCERTIFICATE_STRUCTW uiInfo
;
442 BOOL propsChanged
= FALSE
;
444 memset(&uiInfo
, 0, sizeof(uiInfo
));
445 uiInfo
.dwSize
= sizeof(uiInfo
);
446 uiInfo
.hwndParent
= info
->hwndParent
;
448 CRYPTUI_DISABLE_ADDTOSTORE
| CRYPTUI_ENABLE_EDITPROPERTIES
;
449 uiInfo
.szTitle
= info
->szTitle
;
450 uiInfo
.pCertContext
= info
->pCertContext
;
451 uiInfo
.cPurposes
= info
->cArrayPurposes
;
452 uiInfo
.rgszPurposes
= (LPCSTR
*)info
->arrayPurposes
;
453 uiInfo
.u
.hWVTStateData
= wtd
.hWVTStateData
;
454 uiInfo
.fpCryptProviderDataTrustedUsage
= TRUE
;
455 uiInfo
.cPropSheetPages
= info
->cArrayPropSheetPages
;
456 uiInfo
.rgPropSheetPages
= info
->arrayPropSheetPages
;
457 uiInfo
.nStartPage
= info
->nStartPage
;
458 ret
= CryptUIDlgViewCertificateW(&uiInfo
, &propsChanged
);
459 wtd
.dwStateAction
= WTD_STATEACTION_CLOSE
;
460 WinVerifyTrust(NULL
, &cert_action_verify
, &wtd
);
467 static BOOL
CRYPT_FormatHexString(const BYTE
*pbEncoded
, DWORD cbEncoded
,
468 WCHAR
*str
, DWORD
*pcchStr
)
474 charsNeeded
= (cbEncoded
* 3);
479 *pcchStr
= charsNeeded
;
482 else if (*pcchStr
< charsNeeded
)
484 *pcchStr
= charsNeeded
;
485 SetLastError(ERROR_MORE_DATA
);
490 static const WCHAR fmt
[] = { '%','0','2','x',' ',0 };
491 static const WCHAR endFmt
[] = { '%','0','2','x',0 };
495 *pcchStr
= charsNeeded
;
498 for (i
= 0; i
< cbEncoded
; i
++)
500 if (i
< cbEncoded
- 1)
501 ptr
+= swprintf(ptr
, 4, fmt
, pbEncoded
[i
]);
503 ptr
+= swprintf(ptr
, 3, endFmt
, pbEncoded
[i
]);
513 static const WCHAR indent
[] = { ' ',' ',' ',' ',' ',0 };
514 static const WCHAR colonCrlf
[] = { ':','\r','\n',0 };
515 static const WCHAR colonSpace
[] = { ':',' ',0 };
516 static const WCHAR crlf
[] = { '\r','\n',0 };
517 static const WCHAR commaSep
[] = { ',',' ',0 };
519 static BOOL
CRYPT_FormatCPS(DWORD dwCertEncodingType
,
520 DWORD dwFormatStrType
, const BYTE
*pbEncoded
, DWORD cbEncoded
,
521 WCHAR
*str
, DWORD
*pcchStr
)
524 DWORD size
, charsNeeded
= 1;
525 CERT_NAME_VALUE
*cpsValue
;
527 if ((ret
= CryptDecodeObjectEx(dwCertEncodingType
, X509_UNICODE_ANY_STRING
,
528 pbEncoded
, cbEncoded
, CRYPT_DECODE_ALLOC_FLAG
, NULL
, &cpsValue
, &size
)))
533 if (dwFormatStrType
& CRYPT_FORMAT_STR_MULTI_LINE
)
538 sepLen
= lstrlenW(sep
);
540 if (dwFormatStrType
& CRYPT_FORMAT_STR_MULTI_LINE
)
542 charsNeeded
+= 3 * lstrlenW(indent
);
543 if (str
&& *pcchStr
>= charsNeeded
)
545 lstrcpyW(str
, indent
);
546 str
+= lstrlenW(indent
);
547 lstrcpyW(str
, indent
);
548 str
+= lstrlenW(indent
);
549 lstrcpyW(str
, indent
);
550 str
+= lstrlenW(indent
);
553 charsNeeded
+= cpsValue
->Value
.cbData
/ sizeof(WCHAR
);
554 if (str
&& *pcchStr
>= charsNeeded
)
556 lstrcpyW(str
, (LPWSTR
)cpsValue
->Value
.pbData
);
557 str
+= cpsValue
->Value
.cbData
/ sizeof(WCHAR
);
559 charsNeeded
+= sepLen
;
560 if (str
&& *pcchStr
>= charsNeeded
)
567 *pcchStr
= charsNeeded
;
568 else if (*pcchStr
< charsNeeded
)
570 *pcchStr
= charsNeeded
;
571 SetLastError(ERROR_MORE_DATA
);
575 *pcchStr
= charsNeeded
;
580 static BOOL
CRYPT_FormatUserNotice(DWORD dwCertEncodingType
,
581 DWORD dwFormatStrType
, const BYTE
*pbEncoded
, DWORD cbEncoded
,
582 WCHAR
*str
, DWORD
*pcchStr
)
585 DWORD size
, charsNeeded
= 1;
586 CERT_POLICY_QUALIFIER_USER_NOTICE
*notice
;
588 if ((ret
= CryptDecodeObjectEx(dwCertEncodingType
,
589 X509_PKIX_POLICY_QUALIFIER_USERNOTICE
, pbEncoded
, cbEncoded
,
590 CRYPT_DECODE_ALLOC_FLAG
, NULL
, ¬ice
, &size
)))
592 static const WCHAR numFmt
[] = { '%','d',0 };
593 CERT_POLICY_QUALIFIER_NOTICE_REFERENCE
*pNoticeRef
=
594 notice
->pNoticeReference
;
595 LPCWSTR headingSep
, sep
;
596 DWORD headingSepLen
, sepLen
;
597 LPWSTR noticeRef
, organization
, noticeNum
, noticeText
;
598 DWORD noticeRefLen
, organizationLen
, noticeNumLen
, noticeTextLen
;
599 WCHAR noticeNumStr
[11];
601 noticeRefLen
= LoadStringW(hInstance
, IDS_NOTICE_REF
,
602 (LPWSTR
)¬iceRef
, 0);
603 organizationLen
= LoadStringW(hInstance
, IDS_ORGANIZATION
,
604 (LPWSTR
)&organization
, 0);
605 noticeNumLen
= LoadStringW(hInstance
, IDS_NOTICE_NUM
,
606 (LPWSTR
)¬iceNum
, 0);
607 noticeTextLen
= LoadStringW(hInstance
, IDS_NOTICE_TEXT
,
608 (LPWSTR
)¬iceText
, 0);
609 if (dwFormatStrType
& CRYPT_FORMAT_STR_MULTI_LINE
)
611 headingSep
= colonCrlf
;
616 headingSep
= colonSpace
;
619 sepLen
= lstrlenW(sep
);
620 headingSepLen
= lstrlenW(headingSep
);
627 if (dwFormatStrType
& CRYPT_FORMAT_STR_MULTI_LINE
)
629 charsNeeded
+= 3 * lstrlenW(indent
);
630 if (str
&& *pcchStr
>= charsNeeded
)
632 lstrcpyW(str
, indent
);
633 str
+= lstrlenW(indent
);
634 lstrcpyW(str
, indent
);
635 str
+= lstrlenW(indent
);
636 lstrcpyW(str
, indent
);
637 str
+= lstrlenW(indent
);
640 charsNeeded
+= noticeRefLen
;
641 if (str
&& *pcchStr
>= charsNeeded
)
643 memcpy(str
, noticeRef
, noticeRefLen
* sizeof(WCHAR
));
646 charsNeeded
+= headingSepLen
;
647 if (str
&& *pcchStr
>= charsNeeded
)
649 lstrcpyW(str
, headingSep
);
650 str
+= headingSepLen
;
652 if (dwFormatStrType
& CRYPT_FORMAT_STR_MULTI_LINE
)
654 charsNeeded
+= 4 * lstrlenW(indent
);
655 if (str
&& *pcchStr
>= charsNeeded
)
657 lstrcpyW(str
, indent
);
658 str
+= lstrlenW(indent
);
659 lstrcpyW(str
, indent
);
660 str
+= lstrlenW(indent
);
661 lstrcpyW(str
, indent
);
662 str
+= lstrlenW(indent
);
663 lstrcpyW(str
, indent
);
664 str
+= lstrlenW(indent
);
667 charsNeeded
+= organizationLen
;
668 if (str
&& *pcchStr
>= charsNeeded
)
670 memcpy(str
, organization
, organizationLen
* sizeof(WCHAR
));
671 str
+= organizationLen
;
673 charsNeeded
+= strlen(pNoticeRef
->pszOrganization
);
674 if (str
&& *pcchStr
>= charsNeeded
)
675 for (src
= pNoticeRef
->pszOrganization
; src
&& *src
;
678 charsNeeded
+= sepLen
;
679 if (str
&& *pcchStr
>= charsNeeded
)
684 for (k
= 0; k
< pNoticeRef
->cNoticeNumbers
; k
++)
686 if (dwFormatStrType
& CRYPT_FORMAT_STR_MULTI_LINE
)
688 charsNeeded
+= 4 * lstrlenW(indent
);
689 if (str
&& *pcchStr
>= charsNeeded
)
691 lstrcpyW(str
, indent
);
692 str
+= lstrlenW(indent
);
693 lstrcpyW(str
, indent
);
694 str
+= lstrlenW(indent
);
695 lstrcpyW(str
, indent
);
696 str
+= lstrlenW(indent
);
697 lstrcpyW(str
, indent
);
698 str
+= lstrlenW(indent
);
701 charsNeeded
+= noticeNumLen
;
702 if (str
&& *pcchStr
>= charsNeeded
)
704 memcpy(str
, noticeNum
, noticeNumLen
* sizeof(WCHAR
));
707 swprintf(noticeNumStr
, ARRAY_SIZE(noticeNumStr
), numFmt
, k
+ 1);
708 charsNeeded
+= lstrlenW(noticeNumStr
);
709 if (str
&& *pcchStr
>= charsNeeded
)
711 lstrcpyW(str
, noticeNumStr
);
712 str
+= lstrlenW(noticeNumStr
);
714 charsNeeded
+= sepLen
;
715 if (str
&& *pcchStr
>= charsNeeded
)
722 if (notice
->pszDisplayText
)
724 if (dwFormatStrType
& CRYPT_FORMAT_STR_MULTI_LINE
)
726 charsNeeded
+= 3 * lstrlenW(indent
);
727 if (str
&& *pcchStr
>= charsNeeded
)
729 lstrcpyW(str
, indent
);
730 str
+= lstrlenW(indent
);
731 lstrcpyW(str
, indent
);
732 str
+= lstrlenW(indent
);
733 lstrcpyW(str
, indent
);
734 str
+= lstrlenW(indent
);
737 charsNeeded
+= noticeTextLen
;
738 if (str
&& *pcchStr
>= charsNeeded
)
740 memcpy(str
, noticeText
, noticeTextLen
* sizeof(WCHAR
));
741 str
+= noticeTextLen
;
743 charsNeeded
+= lstrlenW(notice
->pszDisplayText
);
744 if (str
&& *pcchStr
>= charsNeeded
)
746 lstrcpyW(str
, notice
->pszDisplayText
);
747 str
+= lstrlenW(notice
->pszDisplayText
);
749 charsNeeded
+= sepLen
;
750 if (str
&& *pcchStr
>= charsNeeded
)
758 *pcchStr
= charsNeeded
;
759 else if (*pcchStr
< charsNeeded
)
761 *pcchStr
= charsNeeded
;
762 SetLastError(ERROR_MORE_DATA
);
766 *pcchStr
= charsNeeded
;
771 /***********************************************************************
772 * FormatVerisignExtension (CRYPTDLG.@)
774 BOOL WINAPI
FormatVerisignExtension(DWORD dwCertEncodingType
,
775 DWORD dwFormatType
, DWORD dwFormatStrType
, void *pFormatStruct
,
776 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, void *pbFormat
,
779 CERT_POLICIES_INFO
*policies
;
785 SetLastError(E_INVALIDARG
);
788 if ((ret
= CryptDecodeObjectEx(dwCertEncodingType
, X509_CERT_POLICIES
,
789 pbEncoded
, cbEncoded
, CRYPT_DECODE_ALLOC_FLAG
, NULL
, &policies
, &size
)))
791 static const WCHAR numFmt
[] = { '%','d',0 };
792 DWORD charsNeeded
= 1; /* space for NULL terminator */
793 LPCWSTR headingSep
, sep
;
794 DWORD headingSepLen
, sepLen
;
795 WCHAR policyNum
[11], policyQualifierNum
[11];
796 LPWSTR certPolicy
, policyId
, policyQualifierInfo
, policyQualifierId
;
797 LPWSTR cps
, userNotice
, qualifier
;
798 DWORD certPolicyLen
, policyIdLen
, policyQualifierInfoLen
;
799 DWORD policyQualifierIdLen
, cpsLen
, userNoticeLen
, qualifierLen
;
801 LPWSTR str
= pbFormat
;
803 certPolicyLen
= LoadStringW(hInstance
, IDS_CERT_POLICY
,
804 (LPWSTR
)&certPolicy
, 0);
805 policyIdLen
= LoadStringW(hInstance
, IDS_POLICY_ID
, (LPWSTR
)&policyId
,
807 policyQualifierInfoLen
= LoadStringW(hInstance
,
808 IDS_POLICY_QUALIFIER_INFO
, (LPWSTR
)&policyQualifierInfo
, 0);
809 policyQualifierIdLen
= LoadStringW(hInstance
, IDS_POLICY_QUALIFIER_ID
,
810 (LPWSTR
)&policyQualifierId
, 0);
811 cpsLen
= LoadStringW(hInstance
, IDS_CPS
, (LPWSTR
)&cps
, 0);
812 userNoticeLen
= LoadStringW(hInstance
, IDS_USER_NOTICE
,
813 (LPWSTR
)&userNotice
, 0);
814 qualifierLen
= LoadStringW(hInstance
, IDS_QUALIFIER
,
815 (LPWSTR
)&qualifier
, 0);
816 if (dwFormatStrType
& CRYPT_FORMAT_STR_MULTI_LINE
)
818 headingSep
= colonCrlf
;
823 headingSep
= colonSpace
;
826 sepLen
= lstrlenW(sep
);
827 headingSepLen
= lstrlenW(headingSep
);
829 for (i
= 0; ret
&& i
< policies
->cPolicyInfo
; i
++)
831 CERT_POLICY_INFO
*policy
= &policies
->rgPolicyInfo
[i
];
835 charsNeeded
+= 1; /* '['*/
836 if (str
&& *pcbFormat
>= charsNeeded
* sizeof(WCHAR
))
838 swprintf(policyNum
, ARRAY_SIZE(policyNum
), numFmt
, i
+ 1);
839 charsNeeded
+= lstrlenW(policyNum
);
840 if (str
&& *pcbFormat
>= charsNeeded
* sizeof(WCHAR
))
842 lstrcpyW(str
, policyNum
);
843 str
+= lstrlenW(policyNum
);
845 charsNeeded
+= 1; /* ']'*/
846 if (str
&& *pcbFormat
>= charsNeeded
* sizeof(WCHAR
))
848 charsNeeded
+= certPolicyLen
;
849 if (str
&& *pcbFormat
>= charsNeeded
* sizeof(WCHAR
))
851 memcpy(str
, certPolicy
, certPolicyLen
* sizeof(WCHAR
));
852 str
+= certPolicyLen
;
854 charsNeeded
+= headingSepLen
;
855 if (str
&& *pcbFormat
>= charsNeeded
* sizeof(WCHAR
))
857 lstrcpyW(str
, headingSep
);
858 str
+= headingSepLen
;
860 if (dwFormatStrType
& CRYPT_FORMAT_STR_MULTI_LINE
)
862 charsNeeded
+= lstrlenW(indent
);
863 if (str
&& *pcbFormat
>= charsNeeded
* sizeof(WCHAR
))
865 lstrcpyW(str
, indent
);
866 str
+= lstrlenW(indent
);
869 charsNeeded
+= policyIdLen
;
870 if (str
&& *pcbFormat
>= charsNeeded
* sizeof(WCHAR
))
872 memcpy(str
, policyId
, policyIdLen
* sizeof(WCHAR
));
875 charsNeeded
+= strlen(policy
->pszPolicyIdentifier
);
876 if (str
&& *pcbFormat
>= charsNeeded
* sizeof(WCHAR
))
878 for (src
= policy
->pszPolicyIdentifier
; src
&& *src
;
882 charsNeeded
+= sepLen
;
883 if (str
&& *pcbFormat
>= charsNeeded
* sizeof(WCHAR
))
888 for (j
= 0; j
< policy
->cPolicyQualifier
; j
++)
890 CERT_POLICY_QUALIFIER_INFO
*qualifierInfo
=
891 &policy
->rgPolicyQualifier
[j
];
894 if (dwFormatStrType
& CRYPT_FORMAT_STR_MULTI_LINE
)
896 charsNeeded
+= lstrlenW(indent
);
897 if (str
&& *pcbFormat
>= charsNeeded
* sizeof(WCHAR
))
899 lstrcpyW(str
, indent
);
900 str
+= lstrlenW(indent
);
903 charsNeeded
+= 1; /* '['*/
904 if (str
&& *pcbFormat
>= charsNeeded
* sizeof(WCHAR
))
906 charsNeeded
+= lstrlenW(policyNum
);
907 if (str
&& *pcbFormat
>= charsNeeded
* sizeof(WCHAR
))
909 lstrcpyW(str
, policyNum
);
910 str
+= lstrlenW(policyNum
);
912 charsNeeded
+= 1; /* ','*/
913 if (str
&& *pcbFormat
>= charsNeeded
* sizeof(WCHAR
))
915 swprintf(policyQualifierNum
, ARRAY_SIZE(policyQualifierNum
), numFmt
, j
+ 1);
916 charsNeeded
+= lstrlenW(policyQualifierNum
);
917 if (str
&& *pcbFormat
>= charsNeeded
* sizeof(WCHAR
))
919 lstrcpyW(str
, policyQualifierNum
);
920 str
+= lstrlenW(policyQualifierNum
);
922 charsNeeded
+= 1; /* ']'*/
923 if (str
&& *pcbFormat
>= charsNeeded
* sizeof(WCHAR
))
925 charsNeeded
+= policyQualifierInfoLen
;
926 if (str
&& *pcbFormat
>= charsNeeded
* sizeof(WCHAR
))
928 memcpy(str
, policyQualifierInfo
,
929 policyQualifierInfoLen
* sizeof(WCHAR
));
930 str
+= policyQualifierInfoLen
;
932 charsNeeded
+= headingSepLen
;
933 if (str
&& *pcbFormat
>= charsNeeded
* sizeof(WCHAR
))
935 lstrcpyW(str
, headingSep
);
936 str
+= headingSepLen
;
938 if (dwFormatStrType
& CRYPT_FORMAT_STR_MULTI_LINE
)
940 charsNeeded
+= 2 * lstrlenW(indent
);
941 if (str
&& *pcbFormat
>= charsNeeded
* sizeof(WCHAR
))
943 lstrcpyW(str
, indent
);
944 str
+= lstrlenW(indent
);
945 lstrcpyW(str
, indent
);
946 str
+= lstrlenW(indent
);
949 charsNeeded
+= policyQualifierIdLen
;
950 if (str
&& *pcbFormat
>= charsNeeded
* sizeof(WCHAR
))
952 memcpy(str
, policyQualifierId
,
953 policyQualifierIdLen
* sizeof(WCHAR
));
954 str
+= policyQualifierIdLen
;
956 if (!strcmp(qualifierInfo
->pszPolicyQualifierId
,
957 szOID_PKIX_POLICY_QUALIFIER_CPS
))
959 charsNeeded
+= cpsLen
;
960 if (str
&& *pcbFormat
>= charsNeeded
* sizeof(WCHAR
))
962 memcpy(str
, cps
, cpsLen
* sizeof(WCHAR
));
966 else if (!strcmp(qualifierInfo
->pszPolicyQualifierId
,
967 szOID_PKIX_POLICY_QUALIFIER_USERNOTICE
))
969 charsNeeded
+= userNoticeLen
;
970 if (str
&& *pcbFormat
>= charsNeeded
* sizeof(WCHAR
))
972 memcpy(str
, userNotice
, userNoticeLen
* sizeof(WCHAR
));
973 str
+= userNoticeLen
;
978 charsNeeded
+= strlen(qualifierInfo
->pszPolicyQualifierId
);
979 if (str
&& *pcbFormat
>= charsNeeded
* sizeof(WCHAR
))
981 for (src
= qualifierInfo
->pszPolicyQualifierId
;
982 src
&& *src
; src
++, str
++)
986 charsNeeded
+= sepLen
;
987 if (str
&& *pcbFormat
>= charsNeeded
* sizeof(WCHAR
))
992 if (dwFormatStrType
& CRYPT_FORMAT_STR_MULTI_LINE
)
994 charsNeeded
+= 2 * lstrlenW(indent
);
995 if (str
&& *pcbFormat
>= charsNeeded
* sizeof(WCHAR
))
997 lstrcpyW(str
, indent
);
998 str
+= lstrlenW(indent
);
999 lstrcpyW(str
, indent
);
1000 str
+= lstrlenW(indent
);
1003 charsNeeded
+= qualifierLen
;
1004 if (str
&& *pcbFormat
>= charsNeeded
* sizeof(WCHAR
))
1006 memcpy(str
, qualifier
, qualifierLen
* sizeof(WCHAR
));
1007 str
+= qualifierLen
;
1009 charsNeeded
+= headingSepLen
;
1010 if (str
&& *pcbFormat
>= charsNeeded
* sizeof(WCHAR
))
1012 lstrcpyW(str
, headingSep
);
1013 str
+= headingSepLen
;
1015 /* This if block is deliberately redundant with the same if
1016 * block above, in order to keep the code more readable (the
1017 * code flow follows the order in which the strings are output.)
1019 if (!strcmp(qualifierInfo
->pszPolicyQualifierId
,
1020 szOID_PKIX_POLICY_QUALIFIER_CPS
))
1022 if (!str
|| *pcbFormat
< charsNeeded
* sizeof(WCHAR
))
1024 /* Insufficient space, determine how much is needed. */
1025 ret
= CRYPT_FormatCPS(dwCertEncodingType
,
1026 dwFormatStrType
, qualifierInfo
->Qualifier
.pbData
,
1027 qualifierInfo
->Qualifier
.cbData
, NULL
, &size
);
1029 charsNeeded
+= size
- 1;
1033 sizeRemaining
= *pcbFormat
/ sizeof(WCHAR
);
1034 sizeRemaining
-= str
- (LPWSTR
)pbFormat
;
1035 ret
= CRYPT_FormatCPS(dwCertEncodingType
,
1036 dwFormatStrType
, qualifierInfo
->Qualifier
.pbData
,
1037 qualifierInfo
->Qualifier
.cbData
, str
, &sizeRemaining
);
1038 if (ret
|| GetLastError() == ERROR_MORE_DATA
)
1040 charsNeeded
+= sizeRemaining
- 1;
1041 str
+= sizeRemaining
- 1;
1045 else if (!strcmp(qualifierInfo
->pszPolicyQualifierId
,
1046 szOID_PKIX_POLICY_QUALIFIER_USERNOTICE
))
1048 if (!str
|| *pcbFormat
< charsNeeded
* sizeof(WCHAR
))
1050 /* Insufficient space, determine how much is needed. */
1051 ret
= CRYPT_FormatUserNotice(dwCertEncodingType
,
1052 dwFormatStrType
, qualifierInfo
->Qualifier
.pbData
,
1053 qualifierInfo
->Qualifier
.cbData
, NULL
, &size
);
1055 charsNeeded
+= size
- 1;
1059 sizeRemaining
= *pcbFormat
/ sizeof(WCHAR
);
1060 sizeRemaining
-= str
- (LPWSTR
)pbFormat
;
1061 ret
= CRYPT_FormatUserNotice(dwCertEncodingType
,
1062 dwFormatStrType
, qualifierInfo
->Qualifier
.pbData
,
1063 qualifierInfo
->Qualifier
.cbData
, str
, &sizeRemaining
);
1064 if (ret
|| GetLastError() == ERROR_MORE_DATA
)
1066 charsNeeded
+= sizeRemaining
- 1;
1067 str
+= sizeRemaining
- 1;
1073 if (!str
|| *pcbFormat
< charsNeeded
* sizeof(WCHAR
))
1075 /* Insufficient space, determine how much is needed. */
1076 ret
= CRYPT_FormatHexString(
1077 qualifierInfo
->Qualifier
.pbData
,
1078 qualifierInfo
->Qualifier
.cbData
, NULL
, &size
);
1080 charsNeeded
+= size
- 1;
1084 sizeRemaining
= *pcbFormat
/ sizeof(WCHAR
);
1085 sizeRemaining
-= str
- (LPWSTR
)pbFormat
;
1086 ret
= CRYPT_FormatHexString(
1087 qualifierInfo
->Qualifier
.pbData
,
1088 qualifierInfo
->Qualifier
.cbData
, str
, &sizeRemaining
);
1089 if (ret
|| GetLastError() == ERROR_MORE_DATA
)
1091 charsNeeded
+= sizeRemaining
- 1;
1092 str
+= sizeRemaining
- 1;
1098 LocalFree(policies
);
1102 *pcbFormat
= charsNeeded
* sizeof(WCHAR
);
1103 else if (*pcbFormat
< charsNeeded
* sizeof(WCHAR
))
1105 *pcbFormat
= charsNeeded
* sizeof(WCHAR
);
1106 SetLastError(ERROR_MORE_DATA
);
1110 *pcbFormat
= charsNeeded
* sizeof(WCHAR
);
1116 #define szOID_MICROSOFT_Encryption_Key_Preference "1.3.6.1.4.1.311.16.4"
1118 /***********************************************************************
1119 * DllRegisterServer (CRYPTDLG.@)
1121 HRESULT WINAPI
DllRegisterServer(void)
1123 static WCHAR cryptdlg
[] = { 'c','r','y','p','t','d','l','g','.',
1125 static WCHAR wintrust
[] = { 'w','i','n','t','r','u','s','t','.',
1127 static WCHAR certTrustInit
[] = { 'C','e','r','t','T','r','u','s','t',
1128 'I','n','i','t',0 };
1129 static WCHAR wintrustCertificateTrust
[] = { 'W','i','n','t','r','u','s','t',
1130 'C','e','r','t','i','f','i','c','a','t','e','T','r','u','s','t',0 };
1131 static WCHAR certTrustCertPolicy
[] = { 'C','e','r','t','T','r','u','s','t',
1132 'C','e','r','t','P','o','l','i','c','y',0 };
1133 static WCHAR certTrustFinalPolicy
[] = { 'C','e','r','t','T','r','u','s','t',
1134 'F','i','n','a','l','P','o','l','i','c','y',0 };
1135 static WCHAR certTrustCleanup
[] = { 'C','e','r','t','T','r','u','s','t',
1136 'C','l','e','a','n','u','p',0 };
1137 static const WCHAR cryptDlg
[] = { 'c','r','y','p','t','d','l','g','.',
1139 CRYPT_REGISTER_ACTIONID reg
;
1140 GUID guid
= CERT_CERTIFICATE_ACTION_VERIFY
;
1143 memset(®
, 0, sizeof(reg
));
1144 reg
.cbStruct
= sizeof(reg
);
1145 reg
.sInitProvider
.cbStruct
= sizeof(CRYPT_TRUST_REG_ENTRY
);
1146 reg
.sInitProvider
.pwszDLLName
= cryptdlg
;
1147 reg
.sInitProvider
.pwszFunctionName
= certTrustInit
;
1148 reg
.sCertificateProvider
.cbStruct
= sizeof(CRYPT_TRUST_REG_ENTRY
);
1149 reg
.sCertificateProvider
.pwszDLLName
= wintrust
;
1150 reg
.sCertificateProvider
.pwszFunctionName
= wintrustCertificateTrust
;
1151 reg
.sCertificatePolicyProvider
.cbStruct
= sizeof(CRYPT_TRUST_REG_ENTRY
);
1152 reg
.sCertificatePolicyProvider
.pwszDLLName
= cryptdlg
;
1153 reg
.sCertificatePolicyProvider
.pwszFunctionName
= certTrustCertPolicy
;
1154 reg
.sFinalPolicyProvider
.cbStruct
= sizeof(CRYPT_TRUST_REG_ENTRY
);
1155 reg
.sFinalPolicyProvider
.pwszDLLName
= cryptdlg
;
1156 reg
.sFinalPolicyProvider
.pwszFunctionName
= certTrustFinalPolicy
;
1157 reg
.sCleanupProvider
.cbStruct
= sizeof(CRYPT_TRUST_REG_ENTRY
);
1158 reg
.sCleanupProvider
.pwszDLLName
= cryptdlg
;
1159 reg
.sCleanupProvider
.pwszFunctionName
= certTrustCleanup
;
1160 if (!WintrustAddActionID(&guid
, WT_ADD_ACTION_ID_RET_RESULT_FLAG
, ®
))
1161 hr
= GetLastError();
1162 CryptRegisterOIDFunction(X509_ASN_ENCODING
, CRYPT_OID_ENCODE_OBJECT_FUNC
,
1163 "1.3.6.1.4.1.311.16.1.1", cryptDlg
, "EncodeAttrSequence");
1164 CryptRegisterOIDFunction(X509_ASN_ENCODING
, CRYPT_OID_ENCODE_OBJECT_FUNC
,
1165 szOID_MICROSOFT_Encryption_Key_Preference
, cryptDlg
, "EncodeRecipientID");
1166 CryptRegisterOIDFunction(X509_ASN_ENCODING
, CRYPT_OID_DECODE_OBJECT_FUNC
,
1167 "1.3.6.1.4.1.311.16.1.1", cryptDlg
, "DecodeAttrSequence");
1168 CryptRegisterOIDFunction(X509_ASN_ENCODING
, CRYPT_OID_DECODE_OBJECT_FUNC
,
1169 szOID_MICROSOFT_Encryption_Key_Preference
, cryptDlg
, "DecodeRecipientID");
1170 CryptRegisterOIDFunction(X509_ASN_ENCODING
, CRYPT_OID_FORMAT_OBJECT_FUNC
,
1171 szOID_PKIX_KP_EMAIL_PROTECTION
, cryptDlg
, "FormatPKIXEmailProtection");
1172 CryptRegisterOIDFunction(X509_ASN_ENCODING
, CRYPT_OID_FORMAT_OBJECT_FUNC
,
1173 szOID_CERT_POLICIES
, cryptDlg
, "FormatVerisignExtension");
1177 /***********************************************************************
1178 * DllUnregisterServer (CRYPTDLG.@)
1180 HRESULT WINAPI
DllUnregisterServer(void)
1182 GUID guid
= CERT_CERTIFICATE_ACTION_VERIFY
;
1184 WintrustRemoveActionID(&guid
);
1185 CryptUnregisterOIDFunction(X509_ASN_ENCODING
, CRYPT_OID_ENCODE_OBJECT_FUNC
,
1186 "1.3.6.1.4.1.311.16.1.1");
1187 CryptUnregisterOIDFunction(X509_ASN_ENCODING
, CRYPT_OID_ENCODE_OBJECT_FUNC
,
1188 szOID_MICROSOFT_Encryption_Key_Preference
);
1189 CryptUnregisterOIDFunction(X509_ASN_ENCODING
, CRYPT_OID_DECODE_OBJECT_FUNC
,
1190 "1.3.6.1.4.1.311.16.1.1");
1191 CryptUnregisterOIDFunction(X509_ASN_ENCODING
, CRYPT_OID_DECODE_OBJECT_FUNC
,
1192 szOID_MICROSOFT_Encryption_Key_Preference
);
1193 CryptUnregisterOIDFunction(X509_ASN_ENCODING
, CRYPT_OID_FORMAT_OBJECT_FUNC
,
1194 szOID_PKIX_KP_EMAIL_PROTECTION
);
1195 CryptUnregisterOIDFunction(X509_ASN_ENCODING
, CRYPT_OID_FORMAT_OBJECT_FUNC
,
1196 szOID_CERT_POLICIES
);