2 * Copyright 2008 Juan Lang
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
24 #define NONAMELESSUNION
35 #include "cryptuiapi.h"
36 #include "cryptuires.h"
37 #include "wine/debug.h"
38 #include "wine/unicode.h"
40 WINE_DEFAULT_DEBUG_CHANNEL(cryptui
);
42 static HINSTANCE hInstance
;
44 BOOL WINAPI
DllMain(HINSTANCE hinstDLL
, DWORD fdwReason
, LPVOID lpvReserved
)
46 TRACE("(0x%p, %d, %p)\n", hinstDLL
, fdwReason
, lpvReserved
);
50 case DLL_WINE_PREATTACH
:
51 return FALSE
; /* prefer native version */
52 case DLL_PROCESS_ATTACH
:
54 DisableThreadLibraryCalls(hinstDLL
);
56 case DLL_PROCESS_DETACH
:
64 /***********************************************************************
65 * CryptUIDlgCertMgr (CRYPTUI.@)
67 BOOL WINAPI
CryptUIDlgCertMgr(PCCRYPTUI_CERT_MGR_STRUCT pCryptUICertMgr
)
69 FIXME("(%p): stub\n", pCryptUICertMgr
);
73 /***********************************************************************
74 * CryptUIDlgViewCertificateA (CRYPTUI.@)
76 BOOL WINAPI
CryptUIDlgViewCertificateA(
77 PCCRYPTUI_VIEWCERTIFICATE_STRUCTA pCertViewInfo
, BOOL
*pfPropertiesChanged
)
79 CRYPTUI_VIEWCERTIFICATE_STRUCTW viewInfo
;
83 TRACE("(%p, %p)\n", pCertViewInfo
, pfPropertiesChanged
);
85 memcpy(&viewInfo
, pCertViewInfo
, sizeof(viewInfo
));
86 if (pCertViewInfo
->szTitle
)
88 int len
= MultiByteToWideChar(CP_ACP
, 0, pCertViewInfo
->szTitle
, -1,
91 title
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
94 MultiByteToWideChar(CP_ACP
, 0, pCertViewInfo
->szTitle
, -1, title
,
96 viewInfo
.szTitle
= title
;
104 if (pCertViewInfo
->cPropSheetPages
)
106 FIXME("ignoring additional prop sheet pages\n");
107 viewInfo
.cPropSheetPages
= 0;
109 ret
= CryptUIDlgViewCertificateW(&viewInfo
, pfPropertiesChanged
);
110 HeapFree(GetProcessHeap(), 0, title
);
115 struct ReadStringStruct
122 static DWORD CALLBACK
read_text_callback(DWORD_PTR dwCookie
, LPBYTE buf
,
125 struct ReadStringStruct
*string
= (struct ReadStringStruct
*)dwCookie
;
126 LONG cch
= min(cb
/ sizeof(WCHAR
), string
->len
- string
->pos
);
128 TRACE("(%p, %p, %d, %p)\n", string
, buf
, cb
, pcb
);
130 memmove(buf
, string
->buf
+ string
->pos
, cch
* sizeof(WCHAR
));
132 *pcb
= cch
* sizeof(WCHAR
);
136 static void add_unformatted_text_to_control(HWND hwnd
, LPCWSTR text
, LONG len
)
138 struct ReadStringStruct string
;
139 EDITSTREAM editstream
;
141 TRACE("(%p, %s)\n", hwnd
, debugstr_wn(text
, len
));
146 editstream
.dwCookie
= (DWORD_PTR
)&string
;
147 editstream
.dwError
= 0;
148 editstream
.pfnCallback
= read_text_callback
;
149 SendMessageW(hwnd
, EM_STREAMIN
, SF_TEXT
| SFF_SELECTION
| SF_UNICODE
,
150 (LPARAM
)&editstream
);
153 static void add_string_resource_to_control(HWND hwnd
, int id
)
158 len
= LoadStringW(hInstance
, id
, (LPWSTR
)&str
, 0);
159 add_unformatted_text_to_control(hwnd
, str
, len
);
162 static void add_text_with_paraformat_to_control(HWND hwnd
, LPCWSTR text
,
163 LONG len
, const PARAFORMAT2
*fmt
)
165 add_unformatted_text_to_control(hwnd
, text
, len
);
166 SendMessageW(hwnd
, EM_SETPARAFORMAT
, 0, (LPARAM
)fmt
);
169 static void add_string_resource_with_paraformat_to_control(HWND hwnd
, int id
,
170 const PARAFORMAT2
*fmt
)
175 len
= LoadStringW(hInstance
, id
, (LPWSTR
)&str
, 0);
176 add_text_with_paraformat_to_control(hwnd
, str
, len
, fmt
);
179 static LPWSTR
get_cert_name_string(PCCERT_CONTEXT pCertContext
, DWORD dwType
,
185 len
= CertGetNameStringW(pCertContext
, dwType
, dwFlags
, NULL
, NULL
, 0);
188 buf
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
190 CertGetNameStringW(pCertContext
, dwType
, dwFlags
, NULL
, buf
, len
);
195 static void add_cert_string_to_control(HWND hwnd
, PCCERT_CONTEXT pCertContext
,
196 DWORD dwType
, DWORD dwFlags
)
198 LPWSTR name
= get_cert_name_string(pCertContext
, dwType
, dwFlags
);
202 /* Don't include NULL-terminator in output */
203 DWORD len
= lstrlenW(name
);
205 add_unformatted_text_to_control(hwnd
, name
, len
);
206 HeapFree(GetProcessHeap(), 0, name
);
210 static void add_icon_to_control(HWND hwnd
, int id
)
213 LPRICHEDITOLE richEditOle
= NULL
;
214 LPOLEOBJECT object
= NULL
;
216 LPOLECACHE oleCache
= NULL
;
219 LPDATAOBJECT dataObject
= NULL
;
220 HBITMAP bitmap
= NULL
;
225 TRACE("(%p, %d)\n", hwnd
, id
);
227 SendMessageW(hwnd
, EM_GETOLEINTERFACE
, 0, (LPARAM
)&richEditOle
);
230 hr
= OleCreateDefaultHandler(&CLSID_NULL
, NULL
, &IID_IOleObject
,
234 hr
= IOleObject_GetUserClassID(object
, &clsid
);
237 hr
= IOleObject_QueryInterface(object
, &IID_IOleCache
, (void**)&oleCache
);
240 formatEtc
.cfFormat
= CF_BITMAP
;
241 formatEtc
.ptd
= NULL
;
242 formatEtc
.dwAspect
= DVASPECT_CONTENT
;
243 formatEtc
.lindex
= -1;
244 formatEtc
.tymed
= TYMED_GDI
;
245 hr
= IOleCache_Cache(oleCache
, &formatEtc
, 0, &conn
);
248 hr
= IOleObject_QueryInterface(object
, &IID_IDataObject
,
249 (void**)&dataObject
);
252 bitmap
= LoadImageW(hInstance
, MAKEINTRESOURCEW(id
), IMAGE_BITMAP
, 0, 0,
253 LR_DEFAULTSIZE
| LR_LOADTRANSPARENT
);
256 rect
.left
= rect
.top
= 0;
257 rect
.right
= GetSystemMetrics(SM_CXICON
);
258 rect
.bottom
= GetSystemMetrics(SM_CYICON
);
259 stgm
.tymed
= TYMED_GDI
;
260 stgm
.u
.hBitmap
= bitmap
;
261 stgm
.pUnkForRelease
= NULL
;
262 hr
= IDataObject_SetData(dataObject
, &formatEtc
, &stgm
, TRUE
);
266 reObject
.cbStruct
= sizeof(reObject
);
267 reObject
.cp
= REO_CP_SELECTION
;
268 reObject
.clsid
= clsid
;
269 reObject
.poleobj
= object
;
270 reObject
.pstg
= NULL
;
271 reObject
.polesite
= NULL
;
272 reObject
.sizel
.cx
= reObject
.sizel
.cy
= 0;
273 reObject
.dvaspect
= DVASPECT_CONTENT
;
274 reObject
.dwFlags
= 0;
277 IRichEditOle_InsertObject(richEditOle
, &reObject
);
281 IDataObject_Release(dataObject
);
283 IOleCache_Release(oleCache
);
285 IOleObject_Release(object
);
287 IRichEditOle_Release(richEditOle
);
290 #define MY_INDENT 200
292 static void add_oid_text_to_control(HWND hwnd
, char *oid
)
295 PCCRYPT_OID_INFO oidInfo
= CryptFindOIDInfo(CRYPT_OID_INFO_OID_KEY
, oid
, 0);
298 parFmt
.cbSize
= sizeof(parFmt
);
299 parFmt
.dwMask
= PFM_STARTINDENT
;
300 parFmt
.dxStartIndent
= MY_INDENT
* 3;
303 add_text_with_paraformat_to_control(hwnd
, oidInfo
->pwszName
,
304 lstrlenW(oidInfo
->pwszName
), &parFmt
);
305 add_unformatted_text_to_control(hwnd
, &nl
, 1);
309 #define MAX_STRING_LEN 512
317 /* The following list MUST be lexicographically sorted by OID */
318 static struct OIDToString oidMap
[] = {
319 /* 1.3.6.1.4.1.311.10.3.1 */
320 { szOID_KP_CTL_USAGE_SIGNING
, IDS_PURPOSE_CTL_USAGE_SIGNING
},
321 /* 1.3.6.1.4.1.311.10.3.4 */
322 { szOID_KP_EFS
, IDS_PURPOSE_EFS
},
323 /* 1.3.6.1.4.1.311.10.3.4.1 */
324 { szOID_EFS_RECOVERY
, IDS_PURPOSE_EFS_RECOVERY
},
325 /* 1.3.6.1.4.1.311.10.3.5 */
326 { szOID_WHQL_CRYPTO
, IDS_PURPOSE_WHQL
},
327 /* 1.3.6.1.4.1.311.10.3.6 */
328 { szOID_NT5_CRYPTO
, IDS_PURPOSE_NT5
},
329 /* 1.3.6.1.4.1.311.10.3.7 */
330 { szOID_OEM_WHQL_CRYPTO
, IDS_PURPOSE_OEM_WHQL
},
331 /* 1.3.6.1.4.1.311.10.3.8 */
332 { szOID_EMBEDDED_NT_CRYPTO
, IDS_PURPOSE_EMBEDDED_NT
},
333 /* 1.3.6.1.4.1.311.10.3.9 */
334 { szOID_ROOT_LIST_SIGNER
, IDS_PURPOSE_ROOT_LIST_SIGNER
},
335 /* 1.3.6.1.4.1.311.10.3.10 */
336 { szOID_KP_QUALIFIED_SUBORDINATION
, IDS_PURPOSE_QUALIFIED_SUBORDINATION
},
337 /* 1.3.6.1.4.1.311.10.3.11 */
338 { szOID_KP_KEY_RECOVERY
, IDS_PURPOSE_KEY_RECOVERY
},
339 /* 1.3.6.1.4.1.311.10.3.12 */
340 { szOID_KP_DOCUMENT_SIGNING
, IDS_PURPOSE_DOCUMENT_SIGNING
},
341 /* 1.3.6.1.4.1.311.10.3.13 */
342 { szOID_KP_LIFETIME_SIGNING
, IDS_PURPOSE_LIFETIME_SIGNING
},
343 /* 1.3.6.1.4.1.311.10.5.1 */
344 { szOID_DRM
, IDS_PURPOSE_DRM
},
345 /* 1.3.6.1.4.1.311.10.6.1 */
346 { szOID_LICENSES
, IDS_PURPOSE_LICENSES
},
347 /* 1.3.6.1.4.1.311.10.6.2 */
348 { szOID_LICENSE_SERVER
, IDS_PURPOSE_LICENSE_SERVER
},
349 /* 1.3.6.1.4.1.311.20.2.1 */
350 { szOID_ENROLLMENT_AGENT
, IDS_PURPOSE_ENROLLMENT_AGENT
},
351 /* 1.3.6.1.4.1.311.20.2.2 */
352 { szOID_KP_SMARTCARD_LOGON
, IDS_PURPOSE_SMARTCARD_LOGON
},
353 /* 1.3.6.1.4.1.311.21.5 */
354 { szOID_KP_CA_EXCHANGE
, IDS_PURPOSE_CA_EXCHANGE
},
355 /* 1.3.6.1.4.1.311.21.6 */
356 { szOID_KP_KEY_RECOVERY_AGENT
, IDS_PURPOSE_KEY_RECOVERY_AGENT
},
357 /* 1.3.6.1.4.1.311.21.19 */
358 { szOID_DS_EMAIL_REPLICATION
, IDS_PURPOSE_DS_EMAIL_REPLICATION
},
359 /* 1.3.6.1.5.5.7.3.1 */
360 { szOID_PKIX_KP_SERVER_AUTH
, IDS_PURPOSE_SERVER_AUTH
},
361 /* 1.3.6.1.5.5.7.3.2 */
362 { szOID_PKIX_KP_CLIENT_AUTH
, IDS_PURPOSE_CLIENT_AUTH
},
363 /* 1.3.6.1.5.5.7.3.3 */
364 { szOID_PKIX_KP_CODE_SIGNING
, IDS_PURPOSE_CODE_SIGNING
},
365 /* 1.3.6.1.5.5.7.3.4 */
366 { szOID_PKIX_KP_EMAIL_PROTECTION
, IDS_PURPOSE_EMAIL_PROTECTION
},
367 /* 1.3.6.1.5.5.7.3.5 */
368 { szOID_PKIX_KP_IPSEC_END_SYSTEM
, IDS_PURPOSE_IPSEC
},
369 /* 1.3.6.1.5.5.7.3.6 */
370 { szOID_PKIX_KP_IPSEC_TUNNEL
, IDS_PURPOSE_IPSEC
},
371 /* 1.3.6.1.5.5.7.3.7 */
372 { szOID_PKIX_KP_IPSEC_USER
, IDS_PURPOSE_IPSEC
},
373 /* 1.3.6.1.5.5.7.3.8 */
374 { szOID_PKIX_KP_TIMESTAMP_SIGNING
, IDS_PURPOSE_TIMESTAMP_SIGNING
},
377 static struct OIDToString
*findSupportedOID(LPCSTR oid
)
379 int indexHigh
= sizeof(oidMap
) / sizeof(oidMap
[0]) - 1, indexLow
= 0, i
;
380 struct OIDToString
*ret
= NULL
;
382 for (i
= (indexLow
+ indexHigh
) / 2; !ret
&& indexLow
<= indexHigh
;
383 i
= (indexLow
+ indexHigh
) / 2)
387 cmp
= strcmp(oid
, oidMap
[i
].oid
);
398 static void add_local_oid_text_to_control(HWND text
, LPCSTR oid
)
400 struct OIDToString
*entry
;
404 parFmt
.cbSize
= sizeof(parFmt
);
405 parFmt
.dwMask
= PFM_STARTINDENT
;
406 parFmt
.dxStartIndent
= MY_INDENT
* 3;
407 if ((entry
= findSupportedOID(oid
)))
409 WCHAR
*str
, *linebreak
, *ptr
;
410 BOOL multiline
= FALSE
;
413 len
= LoadStringW(hInstance
, entry
->id
, (LPWSTR
)&str
, 0);
416 if ((linebreak
= memchrW(ptr
, '\n', len
)))
418 WCHAR copy
[MAX_STRING_LEN
];
421 /* The source string contains a newline, which the richedit
422 * control won't find since it's interpreted as a paragraph
423 * break. Therefore copy up to the newline. lstrcpynW always
424 * NULL-terminates, so pass one more than the length of the
425 * source line so the copy includes the entire line and the
428 lstrcpynW(copy
, ptr
, linebreak
- ptr
+ 1);
429 add_text_with_paraformat_to_control(text
, copy
,
430 linebreak
- ptr
, &parFmt
);
432 add_unformatted_text_to_control(text
, &nl
, 1);
434 else if (multiline
&& *ptr
)
436 /* Add the last line */
437 add_text_with_paraformat_to_control(text
, ptr
,
438 len
- (ptr
- str
), &parFmt
);
439 add_unformatted_text_to_control(text
, &nl
, 1);
444 add_text_with_paraformat_to_control(text
, str
, len
, &parFmt
);
445 add_unformatted_text_to_control(text
, &nl
, 1);
450 WCHAR
*oidW
= HeapAlloc(GetProcessHeap(), 0,
451 (strlen(oid
) + 1) * sizeof(WCHAR
));
458 for (src
= oid
, dst
= oidW
; *src
; src
++, dst
++)
461 add_text_with_paraformat_to_control(text
, oidW
, lstrlenW(oidW
),
463 add_unformatted_text_to_control(text
, &nl
, 1);
464 HeapFree(GetProcessHeap(), 0, oidW
);
469 static void display_app_usages(HWND text
, PCCERT_CONTEXT cert
,
472 static char any_app_policy
[] = szOID_ANY_APPLICATION_POLICY
;
475 PCERT_EXTENSION policyExt
;
480 parFmt
.cbSize
= sizeof(parFmt
);
481 parFmt
.dwMask
= PFM_STARTINDENT
;
482 parFmt
.dxStartIndent
= MY_INDENT
;
483 add_string_resource_with_paraformat_to_control(text
,
484 IDS_CERT_INFO_PURPOSES
, &parFmt
);
485 add_unformatted_text_to_control(text
, &nl
, 1);
486 *anyUsageAdded
= TRUE
;
488 memset(&charFmt
, 0, sizeof(charFmt
));
489 charFmt
.cbSize
= sizeof(charFmt
);
490 charFmt
.dwMask
= CFM_BOLD
;
491 charFmt
.dwEffects
= 0;
492 SendMessageW(text
, EM_SETCHARFORMAT
, SCF_SELECTION
, (LPARAM
)&charFmt
);
493 if ((policyExt
= CertFindExtension(szOID_APPLICATION_CERT_POLICIES
,
494 cert
->pCertInfo
->cExtension
, cert
->pCertInfo
->rgExtension
)))
496 CERT_POLICIES_INFO
*policies
;
499 if (CryptDecodeObjectEx(X509_ASN_ENCODING
, X509_CERT_POLICIES
,
500 policyExt
->Value
.pbData
, policyExt
->Value
.cbData
,
501 CRYPT_DECODE_ALLOC_FLAG
, NULL
, &policies
, &size
))
505 for (i
= 0; i
< policies
->cPolicyInfo
; i
++)
509 for (j
= 0; j
< policies
->rgPolicyInfo
[i
].cPolicyQualifier
; j
++)
510 add_local_oid_text_to_control(text
,
511 policies
->rgPolicyInfo
[i
].rgPolicyQualifier
[j
].
512 pszPolicyQualifierId
);
518 add_oid_text_to_control(text
, any_app_policy
);
521 static BOOL
display_cert_usages(HWND text
, PCCERT_CONTEXT cert
,
526 BOOL badUsages
= FALSE
;
528 if (CertGetEnhancedKeyUsage(cert
, 0, NULL
, &size
))
531 static char any_cert_policy
[] = szOID_ANY_CERT_POLICY
;
532 PCERT_ENHKEY_USAGE usage
= HeapAlloc(GetProcessHeap(), 0, size
);
536 if (CertGetEnhancedKeyUsage(cert
, 0, usage
, &size
))
544 parFmt
.cbSize
= sizeof(parFmt
);
545 parFmt
.dwMask
= PFM_STARTINDENT
;
546 parFmt
.dxStartIndent
= MY_INDENT
;
547 add_string_resource_with_paraformat_to_control(text
,
548 IDS_CERT_INFO_PURPOSES
, &parFmt
);
549 add_unformatted_text_to_control(text
, &nl
, 1);
550 *anyUsageAdded
= TRUE
;
552 memset(&charFmt
, 0, sizeof(charFmt
));
553 charFmt
.cbSize
= sizeof(charFmt
);
554 charFmt
.dwMask
= CFM_BOLD
;
555 charFmt
.dwEffects
= 0;
556 SendMessageW(text
, EM_SETCHARFORMAT
, SCF_SELECTION
,
558 if (!usage
->cUsageIdentifier
)
559 add_oid_text_to_control(text
, any_cert_policy
);
561 for (i
= 0; i
< usage
->cUsageIdentifier
; i
++)
562 add_local_oid_text_to_control(text
,
563 usage
->rgpszUsageIdentifier
[i
]);
567 HeapFree(GetProcessHeap(), 0, usage
);
577 static void set_policy_text(HWND text
,
578 PCCRYPTUI_VIEWCERTIFICATE_STRUCTW pCertViewInfo
)
580 BOOL includeCertUsages
= FALSE
, includeAppUsages
= FALSE
;
581 BOOL badUsages
= FALSE
, anyUsageAdded
= FALSE
;
583 if (pCertViewInfo
->cPurposes
)
587 for (i
= 0; i
< pCertViewInfo
->cPurposes
; i
++)
589 if (!strcmp(pCertViewInfo
->rgszPurposes
[i
], szOID_ANY_CERT_POLICY
))
590 includeCertUsages
= TRUE
;
591 else if (!strcmp(pCertViewInfo
->rgszPurposes
[i
],
592 szOID_ANY_APPLICATION_POLICY
))
593 includeAppUsages
= TRUE
;
599 includeAppUsages
= includeCertUsages
= TRUE
;
600 if (includeAppUsages
)
601 display_app_usages(text
, pCertViewInfo
->pCertContext
, &anyUsageAdded
);
602 if (includeCertUsages
)
603 badUsages
= display_cert_usages(text
, pCertViewInfo
->pCertContext
,
609 parFmt
.cbSize
= sizeof(parFmt
);
610 parFmt
.dwMask
= PFM_STARTINDENT
;
611 parFmt
.dxStartIndent
= MY_INDENT
;
612 add_string_resource_with_paraformat_to_control(text
,
613 IDS_CERT_INFO_BAD_PURPOSES
, &parFmt
);
617 static void set_cert_info(HWND hwnd
,
618 PCCRYPTUI_VIEWCERTIFICATE_STRUCTW pCertViewInfo
)
622 HWND icon
= GetDlgItem(hwnd
, IDC_CERTIFICATE_ICON
);
623 HWND text
= GetDlgItem(hwnd
, IDC_CERTIFICATE_INFO
);
624 CRYPT_PROVIDER_SGNR
*provSigner
= WTHelperGetProvSignerFromChain(
625 (CRYPT_PROVIDER_DATA
*)pCertViewInfo
->u
.pCryptProviderData
,
626 pCertViewInfo
->idxSigner
, pCertViewInfo
->fCounterSigner
,
627 pCertViewInfo
->idxCounterSigner
);
628 CRYPT_PROVIDER_CERT
*root
=
629 &provSigner
->pasCertChain
[provSigner
->csCertChain
- 1];
631 if (provSigner
->pChainContext
->TrustStatus
.dwErrorStatus
&
632 CERT_TRUST_IS_PARTIAL_CHAIN
)
633 add_icon_to_control(icon
, IDB_CERT_WARNING
);
634 else if (!root
->fTrustedRoot
)
635 add_icon_to_control(icon
, IDB_CERT_ERROR
);
637 add_icon_to_control(icon
, IDB_CERT
);
639 memset(&charFmt
, 0, sizeof(charFmt
));
640 charFmt
.cbSize
= sizeof(charFmt
);
641 charFmt
.dwMask
= CFM_BOLD
;
642 charFmt
.dwEffects
= CFE_BOLD
;
643 SendMessageW(text
, EM_SETCHARFORMAT
, SCF_SELECTION
, (LPARAM
)&charFmt
);
644 /* FIXME: vertically center text */
645 parFmt
.cbSize
= sizeof(parFmt
);
646 parFmt
.dwMask
= PFM_STARTINDENT
;
647 parFmt
.dxStartIndent
= MY_INDENT
;
648 add_string_resource_with_paraformat_to_control(text
,
649 IDS_CERTIFICATEINFORMATION
, &parFmt
);
651 text
= GetDlgItem(hwnd
, IDC_CERTIFICATE_STATUS
);
652 SendMessageW(text
, EM_SETCHARFORMAT
, SCF_SELECTION
, (LPARAM
)&charFmt
);
653 if (provSigner
->dwError
== TRUST_E_CERT_SIGNATURE
)
654 add_string_resource_with_paraformat_to_control(text
,
655 IDS_CERT_INFO_BAD_SIG
, &parFmt
);
656 else if (provSigner
->pChainContext
->TrustStatus
.dwErrorStatus
&
657 CERT_TRUST_IS_PARTIAL_CHAIN
)
658 add_string_resource_with_paraformat_to_control(text
,
659 IDS_CERT_INFO_PARTIAL_CHAIN
, &parFmt
);
660 else if (!root
->fTrustedRoot
)
662 if (provSigner
->csCertChain
== 1 && root
->fSelfSigned
)
663 add_string_resource_with_paraformat_to_control(text
,
664 IDS_CERT_INFO_UNTRUSTED_CA
, &parFmt
);
666 add_string_resource_with_paraformat_to_control(text
,
667 IDS_CERT_INFO_UNTRUSTED_ROOT
, &parFmt
);
671 set_policy_text(text
, pCertViewInfo
);
672 FIXME("show issuer statement\n");
676 static void set_cert_name_string(HWND hwnd
, PCCERT_CONTEXT cert
,
677 DWORD nameFlags
, int heading
)
680 HWND text
= GetDlgItem(hwnd
, IDC_CERTIFICATE_NAMES
);
684 memset(&charFmt
, 0, sizeof(charFmt
));
685 charFmt
.cbSize
= sizeof(charFmt
);
686 charFmt
.dwMask
= CFM_BOLD
;
687 charFmt
.dwEffects
= CFE_BOLD
;
688 SendMessageW(text
, EM_SETCHARFORMAT
, SCF_SELECTION
, (LPARAM
)&charFmt
);
689 parFmt
.cbSize
= sizeof(parFmt
);
690 parFmt
.dwMask
= PFM_STARTINDENT
;
691 parFmt
.dxStartIndent
= MY_INDENT
* 3;
692 add_string_resource_with_paraformat_to_control(text
, heading
, &parFmt
);
693 charFmt
.dwEffects
= 0;
694 SendMessageW(text
, EM_SETCHARFORMAT
, SCF_SELECTION
, (LPARAM
)&charFmt
);
695 add_cert_string_to_control(text
, cert
, CERT_NAME_SIMPLE_DISPLAY_TYPE
,
697 add_unformatted_text_to_control(text
, &nl
, 1);
698 add_unformatted_text_to_control(text
, &nl
, 1);
699 add_unformatted_text_to_control(text
, &nl
, 1);
703 static void add_date_string_to_control(HWND hwnd
, const FILETIME
*fileTime
)
705 WCHAR dateFmt
[80]; /* sufficient for all versions of LOCALE_SSHORTDATE */
709 GetLocaleInfoW(LOCALE_SYSTEM_DEFAULT
, LOCALE_SSHORTDATE
, dateFmt
,
710 sizeof(dateFmt
) / sizeof(dateFmt
[0]));
711 FileTimeToSystemTime(fileTime
, &sysTime
);
712 GetDateFormatW(LOCALE_SYSTEM_DEFAULT
, 0, &sysTime
, dateFmt
, date
,
713 sizeof(date
) / sizeof(date
[0]));
714 add_unformatted_text_to_control(hwnd
, date
, lstrlenW(date
));
717 static void set_cert_validity_period(HWND hwnd
, PCCERT_CONTEXT cert
)
720 HWND text
= GetDlgItem(hwnd
, IDC_CERTIFICATE_NAMES
);
724 memset(&charFmt
, 0, sizeof(charFmt
));
725 charFmt
.cbSize
= sizeof(charFmt
);
726 charFmt
.dwMask
= CFM_BOLD
;
727 charFmt
.dwEffects
= CFE_BOLD
;
728 SendMessageW(text
, EM_SETCHARFORMAT
, SCF_SELECTION
, (LPARAM
)&charFmt
);
729 parFmt
.cbSize
= sizeof(parFmt
);
730 parFmt
.dwMask
= PFM_STARTINDENT
;
731 parFmt
.dxStartIndent
= MY_INDENT
* 3;
732 add_string_resource_with_paraformat_to_control(text
, IDS_VALID_FROM
,
734 charFmt
.dwEffects
= 0;
735 SendMessageW(text
, EM_SETCHARFORMAT
, SCF_SELECTION
, (LPARAM
)&charFmt
);
736 add_date_string_to_control(text
, &cert
->pCertInfo
->NotBefore
);
737 charFmt
.dwEffects
= CFE_BOLD
;
738 SendMessageW(text
, EM_SETCHARFORMAT
, SCF_SELECTION
, (LPARAM
)&charFmt
);
739 add_string_resource_to_control(text
, IDS_VALID_TO
);
740 charFmt
.dwEffects
= 0;
741 SendMessageW(text
, EM_SETCHARFORMAT
, SCF_SELECTION
, (LPARAM
)&charFmt
);
742 add_date_string_to_control(text
, &cert
->pCertInfo
->NotAfter
);
743 add_unformatted_text_to_control(text
, &nl
, 1);
746 static void set_general_info(HWND hwnd
,
747 PCCRYPTUI_VIEWCERTIFICATE_STRUCTW pCertViewInfo
)
749 set_cert_info(hwnd
, pCertViewInfo
);
750 set_cert_name_string(hwnd
, pCertViewInfo
->pCertContext
, 0,
751 IDS_SUBJECT_HEADING
);
752 set_cert_name_string(hwnd
, pCertViewInfo
->pCertContext
,
753 CERT_NAME_ISSUER_FLAG
, IDS_ISSUER_HEADING
);
754 set_cert_validity_period(hwnd
, pCertViewInfo
->pCertContext
);
757 static LRESULT CALLBACK
general_dlg_proc(HWND hwnd
, UINT msg
, WPARAM wp
,
760 PROPSHEETPAGEW
*page
;
761 PCCRYPTUI_VIEWCERTIFICATE_STRUCTW pCertViewInfo
;
763 TRACE("(%p, %08x, %08lx, %08lx)\n", hwnd
, msg
, wp
, lp
);
768 page
= (PROPSHEETPAGEW
*)lp
;
769 pCertViewInfo
= (PCCRYPTUI_VIEWCERTIFICATE_STRUCTW
)page
->lParam
;
770 if (pCertViewInfo
->dwFlags
& CRYPTUI_DISABLE_ADDTOSTORE
)
771 ShowWindow(GetDlgItem(hwnd
, IDC_ADDTOSTORE
), FALSE
);
772 EnableWindow(GetDlgItem(hwnd
, IDC_ISSUERSTATEMENT
), FALSE
);
773 set_general_info(hwnd
, pCertViewInfo
);
779 FIXME("call CryptUIWizImport\n");
787 static void init_general_page(PCCRYPTUI_VIEWCERTIFICATE_STRUCTW pCertViewInfo
,
788 PROPSHEETPAGEW
*page
)
790 memset(page
, 0, sizeof(PROPSHEETPAGEW
));
791 page
->dwSize
= sizeof(PROPSHEETPAGEW
);
792 page
->hInstance
= hInstance
;
793 page
->u
.pszTemplate
= MAKEINTRESOURCEW(IDD_GENERAL
);
794 page
->pfnDlgProc
= general_dlg_proc
;
795 page
->lParam
= (LPARAM
)pCertViewInfo
;
798 static int CALLBACK
cert_prop_sheet_proc(HWND hwnd
, UINT msg
, LPARAM lp
)
803 TRACE("(%p, %08x, %08lx)\n", hwnd
, msg
, lp
);
807 case PSCB_INITIALIZED
:
808 /* Get cancel button's position.. */
809 GetWindowRect(GetDlgItem(hwnd
, IDCANCEL
), &rc
);
812 ScreenToClient(hwnd
, &topLeft
);
813 /* hide the cancel button.. */
814 ShowWindow(GetDlgItem(hwnd
, IDCANCEL
), FALSE
);
815 /* get the OK button's size.. */
816 GetWindowRect(GetDlgItem(hwnd
, IDOK
), &rc
);
817 /* and move the OK button to the cancel button's original position. */
818 MoveWindow(GetDlgItem(hwnd
, IDOK
), topLeft
.x
, topLeft
.y
,
819 rc
.right
- rc
.left
, rc
.bottom
- rc
.top
, FALSE
);
820 GetWindowRect(GetDlgItem(hwnd
, IDOK
), &rc
);
826 static BOOL
show_cert_dialog(PCCRYPTUI_VIEWCERTIFICATE_STRUCTW pCertViewInfo
,
827 CRYPT_PROVIDER_CERT
*provCert
, BOOL
*pfPropertiesChanged
)
829 static const WCHAR riched
[] = { 'r','i','c','h','e','d','2','0',0 };
831 PROPSHEETPAGEW
*pages
;
833 HMODULE lib
= LoadLibraryW(riched
);
835 nPages
= pCertViewInfo
->cPropSheetPages
+ 1; /* one for the General tab */
836 if (!(pCertViewInfo
->dwFlags
& CRYPTUI_HIDE_DETAILPAGE
))
837 FIXME("show detail page\n");
838 if (!(pCertViewInfo
->dwFlags
& CRYPTUI_HIDE_HIERARCHYPAGE
))
839 FIXME("show hierarchy page\n");
840 pages
= HeapAlloc(GetProcessHeap(), 0, nPages
* sizeof(PROPSHEETPAGEW
));
843 PROPSHEETHEADERW hdr
;
844 CRYPTUI_INITDIALOG_STRUCT
*init
= NULL
;
847 memset(&hdr
, 0, sizeof(hdr
));
848 hdr
.dwSize
= sizeof(hdr
);
849 hdr
.dwFlags
= PSH_NOAPPLYNOW
| PSH_PROPSHEETPAGE
| PSH_USECALLBACK
;
850 hdr
.hInstance
= hInstance
;
851 if (pCertViewInfo
->szTitle
)
852 hdr
.pszCaption
= pCertViewInfo
->szTitle
;
854 hdr
.pszCaption
= MAKEINTRESOURCEW(IDS_CERTIFICATE
);
855 init_general_page(pCertViewInfo
, &pages
[hdr
.nPages
++]);
856 /* Copy each additional page, and create the init dialog struct for it
858 if (pCertViewInfo
->cPropSheetPages
)
860 init
= HeapAlloc(GetProcessHeap(), 0,
861 pCertViewInfo
->cPropSheetPages
*
862 sizeof(CRYPTUI_INITDIALOG_STRUCT
));
865 for (i
= 0; i
< pCertViewInfo
->cPropSheetPages
; i
++)
867 memcpy(&pages
[hdr
.nPages
+ i
],
868 &pCertViewInfo
->rgPropSheetPages
[i
],
869 sizeof(PROPSHEETPAGEW
));
870 init
[i
].lParam
= pCertViewInfo
->rgPropSheetPages
[i
].lParam
;
871 init
[i
].pCertContext
= pCertViewInfo
->pCertContext
;
872 pages
[hdr
.nPages
+ i
].lParam
= (LPARAM
)&init
[i
];
874 if (pCertViewInfo
->nStartPage
& 0x8000)
876 /* Start page index is relative to the number of default
879 hdr
.u2
.nStartPage
= pCertViewInfo
->nStartPage
+ hdr
.nPages
;
882 hdr
.u2
.nStartPage
= pCertViewInfo
->nStartPage
;
887 SetLastError(ERROR_OUTOFMEMORY
);
891 /* Ignore the relative flag if there aren't any additional pages */
892 hdr
.u2
.nStartPage
= pCertViewInfo
->nStartPage
& 0x7fff;
900 hdr
.pfnCallback
= cert_prop_sheet_proc
;
901 l
= PropertySheetW(&hdr
);
904 SetLastError(ERROR_CANCELLED
);
908 HeapFree(GetProcessHeap(), 0, init
);
909 HeapFree(GetProcessHeap(), 0, pages
);
912 SetLastError(ERROR_OUTOFMEMORY
);
917 /***********************************************************************
918 * CryptUIDlgViewCertificateW (CRYPTUI.@)
920 BOOL WINAPI
CryptUIDlgViewCertificateW(
921 PCCRYPTUI_VIEWCERTIFICATE_STRUCTW pCertViewInfo
, BOOL
*pfPropertiesChanged
)
923 static GUID generic_cert_verify
= WINTRUST_ACTION_GENERIC_CERT_VERIFY
;
924 CRYPTUI_VIEWCERTIFICATE_STRUCTW viewInfo
;
926 WINTRUST_CERT_INFO cert
;
928 CRYPT_PROVIDER_SGNR
*signer
;
929 CRYPT_PROVIDER_CERT
*provCert
= NULL
;
931 TRACE("(%p, %p)\n", pCertViewInfo
, pfPropertiesChanged
);
933 if (pCertViewInfo
->dwSize
!= sizeof(CRYPTUI_VIEWCERTIFICATE_STRUCTW
))
935 SetLastError(ERROR_INVALID_PARAMETER
);
938 /* Make a local copy in case we have to call WinVerifyTrust ourselves */
939 memcpy(&viewInfo
, pCertViewInfo
, sizeof(viewInfo
));
940 if (!viewInfo
.u
.hWVTStateData
)
942 memset(&wvt
, 0, sizeof(wvt
));
943 wvt
.cbStruct
= sizeof(wvt
);
944 wvt
.dwUIChoice
= WTD_UI_NONE
;
945 if (viewInfo
.dwFlags
&
946 CRYPTUI_ENABLE_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT
)
947 wvt
.fdwRevocationChecks
|= WTD_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT
;
948 if (viewInfo
.dwFlags
& CRYPTUI_ENABLE_REVOCATION_CHECK_END_CERT
)
949 wvt
.fdwRevocationChecks
|= WTD_REVOCATION_CHECK_END_CERT
;
950 if (viewInfo
.dwFlags
& CRYPTUI_ENABLE_REVOCATION_CHECK_CHAIN
)
951 wvt
.fdwRevocationChecks
|= WTD_REVOCATION_CHECK_CHAIN
;
952 wvt
.dwUnionChoice
= WTD_CHOICE_CERT
;
953 memset(&cert
, 0, sizeof(cert
));
954 cert
.cbStruct
= sizeof(cert
);
955 cert
.psCertContext
= (CERT_CONTEXT
*)viewInfo
.pCertContext
;
956 cert
.chStores
= viewInfo
.cStores
;
957 cert
.pahStores
= viewInfo
.rghStores
;
959 wvt
.dwStateAction
= WTD_STATEACTION_VERIFY
;
960 WinVerifyTrust(NULL
, &generic_cert_verify
, &wvt
);
961 viewInfo
.u
.pCryptProviderData
=
962 WTHelperProvDataFromStateData(wvt
.hWVTStateData
);
963 signer
= WTHelperGetProvSignerFromChain(
964 (CRYPT_PROVIDER_DATA
*)viewInfo
.u
.pCryptProviderData
, 0, FALSE
, 0);
965 provCert
= WTHelperGetProvCertFromChain(signer
, 0);
970 viewInfo
.u
.pCryptProviderData
=
971 WTHelperProvDataFromStateData(viewInfo
.u
.hWVTStateData
);
972 signer
= WTHelperGetProvSignerFromChain(
973 (CRYPT_PROVIDER_DATA
*)viewInfo
.u
.pCryptProviderData
,
974 viewInfo
.idxSigner
, viewInfo
.fCounterSigner
,
975 viewInfo
.idxCounterSigner
);
976 provCert
= WTHelperGetProvCertFromChain(signer
, viewInfo
.idxCert
);
981 ret
= show_cert_dialog(&viewInfo
, provCert
, pfPropertiesChanged
);
982 if (!viewInfo
.u
.hWVTStateData
)
984 wvt
.dwStateAction
= WTD_STATEACTION_CLOSE
;
985 WinVerifyTrust(NULL
, &generic_cert_verify
, &wvt
);
991 static PCCERT_CONTEXT
make_cert_from_file(LPCWSTR fileName
)
994 DWORD size
, encoding
= X509_ASN_ENCODING
| PKCS_7_ASN_ENCODING
;
998 file
= CreateFileW(fileName
, GENERIC_READ
, FILE_SHARE_READ
, NULL
,
999 OPEN_EXISTING
, 0, NULL
);
1000 if (file
== INVALID_HANDLE_VALUE
)
1002 WARN("can't open certificate file %s\n", debugstr_w(fileName
));
1005 if ((size
= GetFileSize(file
, NULL
)))
1007 if ((buffer
= HeapAlloc(GetProcessHeap(), 0, size
)))
1010 if (!ReadFile(file
, buffer
, size
, &read
, NULL
) || read
!= size
)
1012 WARN("can't read certificate file %s\n", debugstr_w(fileName
));
1013 HeapFree(GetProcessHeap(), 0, buffer
);
1021 WARN("empty file %s\n", debugstr_w(fileName
));
1026 cert
= CertCreateCertificateContext(encoding
, buffer
, size
);
1027 HeapFree(GetProcessHeap(), 0, buffer
);
1031 /* Decodes a cert's basic constraints extension (either szOID_BASIC_CONSTRAINTS
1032 * or szOID_BASIC_CONSTRAINTS2, whichever is present) to determine if it
1033 * should be a CA. If neither extension is present, returns
1034 * defaultIfNotSpecified.
1036 static BOOL
is_ca_cert(PCCERT_CONTEXT cert
, BOOL defaultIfNotSpecified
)
1038 BOOL isCA
= defaultIfNotSpecified
;
1039 PCERT_EXTENSION ext
= CertFindExtension(szOID_BASIC_CONSTRAINTS
,
1040 cert
->pCertInfo
->cExtension
, cert
->pCertInfo
->rgExtension
);
1044 CERT_BASIC_CONSTRAINTS_INFO
*info
;
1047 if (CryptDecodeObjectEx(X509_ASN_ENCODING
, szOID_BASIC_CONSTRAINTS
,
1048 ext
->Value
.pbData
, ext
->Value
.cbData
, CRYPT_DECODE_ALLOC_FLAG
,
1049 NULL
, (LPBYTE
)&info
, &size
))
1051 if (info
->SubjectType
.cbData
== 1)
1052 isCA
= info
->SubjectType
.pbData
[0] & CERT_CA_SUBJECT_FLAG
;
1058 ext
= CertFindExtension(szOID_BASIC_CONSTRAINTS2
,
1059 cert
->pCertInfo
->cExtension
, cert
->pCertInfo
->rgExtension
);
1062 CERT_BASIC_CONSTRAINTS2_INFO info
;
1063 DWORD size
= sizeof(CERT_BASIC_CONSTRAINTS2_INFO
);
1065 if (CryptDecodeObjectEx(X509_ASN_ENCODING
,
1066 szOID_BASIC_CONSTRAINTS2
, ext
->Value
.pbData
, ext
->Value
.cbData
,
1067 0, NULL
, &info
, &size
))
1074 static HCERTSTORE
choose_store_for_cert(PCCERT_CONTEXT cert
)
1076 static const WCHAR AddressBook
[] = { 'A','d','d','r','e','s','s',
1077 'B','o','o','k',0 };
1078 static const WCHAR CA
[] = { 'C','A',0 };
1081 if (is_ca_cert(cert
, TRUE
))
1084 storeName
= AddressBook
;
1085 return CertOpenStore(CERT_STORE_PROV_SYSTEM_W
, 0, 0,
1086 CERT_SYSTEM_STORE_CURRENT_USER
, storeName
);
1089 BOOL WINAPI
CryptUIWizImport(DWORD dwFlags
, HWND hwndParent
, LPCWSTR pwszWizardTitle
,
1090 PCCRYPTUI_WIZ_IMPORT_SRC_INFO pImportSrc
, HCERTSTORE hDestCertStore
)
1094 const CERT_CONTEXT
*cert
;
1095 BOOL freeCert
= FALSE
;
1097 TRACE("(0x%08x, %p, %s, %p, %p)\n", dwFlags
, hwndParent
, debugstr_w(pwszWizardTitle
),
1098 pImportSrc
, hDestCertStore
);
1100 if (!(dwFlags
& CRYPTUI_WIZ_NO_UI
)) FIXME("UI not implemented\n");
1103 pImportSrc
->dwSize
!= sizeof(CRYPTUI_WIZ_IMPORT_SRC_INFO
))
1105 SetLastError(E_INVALIDARG
);
1109 switch (pImportSrc
->dwSubjectChoice
)
1111 case CRYPTUI_WIZ_IMPORT_SUBJECT_FILE
:
1112 if (!(cert
= make_cert_from_file(pImportSrc
->u
.pwszFileName
)))
1114 WARN("unable to create certificate context\n");
1120 case CRYPTUI_WIZ_IMPORT_SUBJECT_CERT_CONTEXT
:
1121 cert
= pImportSrc
->u
.pCertContext
;
1124 SetLastError(E_INVALIDARG
);
1129 FIXME("source type not implemented: %u\n", pImportSrc
->dwSubjectChoice
);
1130 SetLastError(E_INVALIDARG
);
1133 if (hDestCertStore
) store
= hDestCertStore
;
1136 if (!(store
= choose_store_for_cert(cert
)))
1138 WARN("unable to open certificate store\n");
1139 CertFreeCertificateContext(cert
);
1143 ret
= CertAddCertificateContextToStore(store
, cert
, CERT_STORE_ADD_REPLACE_EXISTING
, NULL
);
1145 if (!hDestCertStore
) CertCloseStore(store
, 0);
1147 CertFreeCertificateContext(cert
);