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
34 #include "cryptuiapi.h"
35 #include "cryptuires.h"
39 #include "wine/debug.h"
41 WINE_DEFAULT_DEBUG_CHANNEL(cryptui
);
43 static HINSTANCE hInstance
;
45 static const WCHAR empty
[] = {0};
47 BOOL WINAPI
DllMain(HINSTANCE hinstDLL
, DWORD fdwReason
, LPVOID lpvReserved
)
49 TRACE("(0x%p, %ld, %p)\n", hinstDLL
, fdwReason
, lpvReserved
);
53 case DLL_PROCESS_ATTACH
:
55 DisableThreadLibraryCalls(hinstDLL
);
61 static WCHAR
*strdupAtoW( const char *str
)
63 DWORD len
= MultiByteToWideChar( CP_ACP
, 0, str
, -1, NULL
, 0 );
64 WCHAR
*ret
= malloc( len
* sizeof(WCHAR
) );
65 if (ret
) MultiByteToWideChar( CP_ACP
, 0, str
, -1, ret
, len
);
69 #define MAX_STRING_LEN 512
71 static void add_cert_columns(HWND hwnd
)
73 HWND lv
= GetDlgItem(hwnd
, IDC_MGR_CERTS
);
75 WCHAR buf
[MAX_STRING_LEN
];
78 SendMessageW(lv
, LVM_SETEXTENDEDLISTVIEWSTYLE
, 0, LVS_EX_FULLROWSELECT
);
79 GetWindowRect(lv
, &rc
);
80 LoadStringW(hInstance
, IDS_SUBJECT_COLUMN
, buf
, ARRAY_SIZE(buf
));
81 column
.mask
= LVCF_WIDTH
| LVCF_TEXT
;
82 column
.cx
= (rc
.right
- rc
.left
) * 29 / 100 - 2;
84 SendMessageW(lv
, LVM_INSERTCOLUMNW
, 0, (LPARAM
)&column
);
85 LoadStringW(hInstance
, IDS_ISSUER_COLUMN
, buf
, ARRAY_SIZE(buf
));
86 SendMessageW(lv
, LVM_INSERTCOLUMNW
, 1, (LPARAM
)&column
);
87 column
.cx
= (rc
.right
- rc
.left
) * 16 / 100 - 2;
88 LoadStringW(hInstance
, IDS_EXPIRATION_COLUMN
, buf
, ARRAY_SIZE(buf
));
89 SendMessageW(lv
, LVM_INSERTCOLUMNW
, 2, (LPARAM
)&column
);
90 column
.cx
= (rc
.right
- rc
.left
) * 23 / 100 - 1;
91 LoadStringW(hInstance
, IDS_FRIENDLY_NAME_COLUMN
, buf
, ARRAY_SIZE(buf
));
92 SendMessageW(lv
, LVM_INSERTCOLUMNW
, 3, (LPARAM
)&column
);
95 static void add_cert_to_view(HWND lv
, PCCERT_CONTEXT cert
, DWORD
*allocatedLen
,
100 WCHAR dateFmt
[80]; /* sufficient for LOCALE_SSHORTDATE */
105 item
.mask
= LVIF_IMAGE
| LVIF_PARAM
| LVIF_TEXT
;
106 item
.iItem
= SendMessageW(lv
, LVM_GETITEMCOUNT
, 0, 0);
109 item
.lParam
= (LPARAM
)CertDuplicateCertificateContext(cert
);
110 len
= CertGetNameStringW(cert
, CERT_NAME_SIMPLE_DISPLAY_TYPE
, 0, NULL
,
112 if (len
> *allocatedLen
)
115 *str
= malloc(len
* sizeof(WCHAR
));
121 CertGetNameStringW(cert
, CERT_NAME_SIMPLE_DISPLAY_TYPE
, 0, NULL
,
124 SendMessageW(lv
, LVM_INSERTITEMW
, 0, (LPARAM
)&item
);
127 item
.mask
= LVIF_TEXT
;
128 len
= CertGetNameStringW(cert
, CERT_NAME_SIMPLE_DISPLAY_TYPE
,
129 CERT_NAME_ISSUER_FLAG
, NULL
, NULL
, 0);
130 if (len
> *allocatedLen
)
133 *str
= malloc(len
* sizeof(WCHAR
));
139 CertGetNameStringW(cert
, CERT_NAME_SIMPLE_DISPLAY_TYPE
,
140 CERT_NAME_ISSUER_FLAG
, NULL
, *str
, len
);
143 SendMessageW(lv
, LVM_SETITEMTEXTW
, item
.iItem
, (LPARAM
)&item
);
146 GetLocaleInfoW(LOCALE_SYSTEM_DEFAULT
, LOCALE_SSHORTDATE
, dateFmt
, ARRAY_SIZE(dateFmt
));
147 FileTimeToSystemTime(&cert
->pCertInfo
->NotAfter
, &sysTime
);
148 GetDateFormatW(LOCALE_SYSTEM_DEFAULT
, 0, &sysTime
, dateFmt
, date
, ARRAY_SIZE(date
));
151 SendMessageW(lv
, LVM_SETITEMTEXTW
, item
.iItem
, (LPARAM
)&item
);
153 if (!CertGetCertificateContextProperty(cert
, CERT_FRIENDLY_NAME_PROP_ID
,
155 len
= LoadStringW(hInstance
, IDS_FRIENDLY_NAME_NONE
, (LPWSTR
)&none
, 0);
156 if (len
> *allocatedLen
)
159 *str
= malloc(len
* sizeof(WCHAR
));
165 if (!CertGetCertificateContextProperty(cert
, CERT_FRIENDLY_NAME_PROP_ID
,
171 SendMessageW(lv
, LVM_SETITEMTEXTW
, item
.iItem
, (LPARAM
)&item
);
175 static LPSTR
get_cert_mgr_usages(void)
177 static const WCHAR keyName
[] = { 'S','o','f','t','w','a','r','e','\\','M',
178 'i','c','r','o','s','o','f','t','\\','C','r','y','p','t','o','g','r','a',
179 'p','h','y','\\','U','I','\\','C','e','r','t','m','g','r','\\','P','u',
180 'r','p','o','s','e',0 };
184 if (!RegCreateKeyExW(HKEY_CURRENT_USER
, keyName
, 0, NULL
, 0, KEY_READ
,
190 rc
= RegQueryValueExA(key
, "Purpose", NULL
, &type
, NULL
, &size
);
191 if ((!rc
|| rc
== ERROR_MORE_DATA
) && type
== REG_SZ
)
196 rc
= RegQueryValueExA(key
, "Purpose", NULL
, NULL
, (LPBYTE
)str
,
211 PurposeFilterShowAll
= 0,
212 PurposeFilterShowAdvanced
= 1,
213 PurposeFilterShowOID
= 2
216 static void initialize_purpose_selection(HWND hwnd
)
218 HWND cb
= GetDlgItem(hwnd
, IDC_MGR_PURPOSE_SELECTION
);
219 WCHAR buf
[MAX_STRING_LEN
];
223 LoadStringW(hInstance
, IDS_PURPOSE_ALL
, buf
, ARRAY_SIZE(buf
));
224 index
= SendMessageW(cb
, CB_INSERTSTRING
, -1, (LPARAM
)buf
);
225 SendMessageW(cb
, CB_SETITEMDATA
, index
, (LPARAM
)PurposeFilterShowAll
);
226 LoadStringW(hInstance
, IDS_PURPOSE_ADVANCED
, buf
, ARRAY_SIZE(buf
));
227 index
= SendMessageW(cb
, CB_INSERTSTRING
, -1, (LPARAM
)buf
);
228 SendMessageW(cb
, CB_SETITEMDATA
, index
, (LPARAM
)PurposeFilterShowAdvanced
);
229 SendMessageW(cb
, CB_SETCURSEL
, 0, 0);
230 if ((usages
= get_cert_mgr_usages()))
234 for (ptr
= usages
, comma
= strchr(ptr
, ','); ptr
&& *ptr
;
235 ptr
= comma
? comma
+ 1 : NULL
,
236 comma
= ptr
? strchr(ptr
, ',') : NULL
)
238 PCCRYPT_OID_INFO info
;
242 if ((info
= CryptFindOIDInfo(CRYPT_OID_INFO_OID_KEY
, ptr
, 0)))
244 index
= SendMessageW(cb
, CB_INSERTSTRING
, 0,
245 (LPARAM
)info
->pwszName
);
246 SendMessageW(cb
, CB_SETITEMDATA
, index
, (LPARAM
)info
);
253 extern BOOL WINAPI
WTHelperGetKnownUsages(DWORD action
,
254 PCCRYPT_OID_INFO
**usages
);
256 static CERT_ENHKEY_USAGE
*add_oid_to_usage(CERT_ENHKEY_USAGE
*usage
, LPSTR oid
)
258 usage
->rgpszUsageIdentifier
= realloc(usage
->rgpszUsageIdentifier
,
259 (usage
->cUsageIdentifier
+ 1) * sizeof(char *));
260 if (usage
->rgpszUsageIdentifier
)
261 usage
->rgpszUsageIdentifier
[usage
->cUsageIdentifier
++] = oid
;
270 static CERT_ENHKEY_USAGE
*convert_usages_str_to_usage(LPSTR usageStr
)
272 CERT_ENHKEY_USAGE
*usage
= calloc(1, sizeof(CERT_ENHKEY_USAGE
));
278 for (ptr
= usageStr
, comma
= strchr(ptr
, ','); usage
&& ptr
&& *ptr
;
279 ptr
= comma
? comma
+ 1 : NULL
,
280 comma
= ptr
? strchr(ptr
, ',') : NULL
)
284 usage
= add_oid_to_usage(usage
, ptr
);
290 static CERT_ENHKEY_USAGE
*create_advanced_filter(void)
292 CERT_ENHKEY_USAGE
*advancedUsage
= calloc(1, sizeof(CERT_ENHKEY_USAGE
));
296 PCCRYPT_OID_INFO
*usages
;
298 if (WTHelperGetKnownUsages(1, &usages
))
300 LPSTR disabledUsagesStr
;
302 if ((disabledUsagesStr
= get_cert_mgr_usages()))
304 CERT_ENHKEY_USAGE
*disabledUsages
=
305 convert_usages_str_to_usage(disabledUsagesStr
);
309 PCCRYPT_OID_INFO
*ptr
;
311 for (ptr
= usages
; advancedUsage
&& *ptr
; ptr
++)
314 BOOL disabled
= FALSE
;
316 for (i
= 0; !disabled
&&
317 i
< disabledUsages
->cUsageIdentifier
; i
++)
318 if (!strcmp(disabledUsages
->rgpszUsageIdentifier
[i
],
322 advancedUsage
= add_oid_to_usage(advancedUsage
,
323 (LPSTR
)(*ptr
)->pszOID
);
325 /* The individual strings are pointers to disabledUsagesStr,
326 * so they're freed when it is.
328 free(disabledUsages
->rgpszUsageIdentifier
);
329 free(disabledUsages
);
331 free(disabledUsagesStr
);
333 WTHelperGetKnownUsages(2, &usages
);
336 return advancedUsage
;
339 static int CALLBACK
cert_mgr_sort_by_subject(LPARAM lp1
, LPARAM lp2
, LPARAM lp
);
341 static void show_store_certs(HWND hwnd
, HCERTSTORE store
)
343 HWND lv
= GetDlgItem(hwnd
, IDC_MGR_CERTS
);
344 HWND cb
= GetDlgItem(hwnd
, IDC_MGR_PURPOSE_SELECTION
);
345 PCCERT_CONTEXT cert
= NULL
;
346 DWORD allocatedLen
= 0;
349 PurposeFilter filter
= PurposeFilterShowAll
;
351 CERT_ENHKEY_USAGE
*advanced
= NULL
;
353 index
= SendMessageW(cb
, CB_GETCURSEL
, 0, 0);
356 INT_PTR data
= SendMessageW(cb
, CB_GETITEMDATA
, index
, 0);
362 PCCRYPT_OID_INFO info
= (PCCRYPT_OID_INFO
)data
;
364 filter
= PurposeFilterShowOID
;
368 if (filter
== PurposeFilterShowAdvanced
)
369 advanced
= create_advanced_filter();
371 cert
= CertEnumCertificatesInStore(store
, cert
);
376 if (filter
== PurposeFilterShowAll
)
383 if (CertGetValidUsages(1, &cert
, &numOIDs
, NULL
, &cbOIDs
))
387 /* -1 implies all usages are valid */
392 char **oids
= malloc(cbOIDs
);
396 if (CertGetValidUsages(1, &cert
, &numOIDs
, oids
,
401 if (filter
== PurposeFilterShowOID
)
403 for (i
= 0; !show
&& i
< numOIDs
; i
++)
404 if (!strcmp(oids
[i
], oid
))
409 for (i
= 0; !show
&& i
< numOIDs
; i
++)
414 j
< advanced
->cUsageIdentifier
; j
++)
416 advanced
->rgpszUsageIdentifier
[j
]))
427 add_cert_to_view(lv
, cert
, &allocatedLen
, &str
);
433 free(advanced
->rgpszUsageIdentifier
);
436 SendMessageW(lv
, LVM_SORTITEMSEX
, (WPARAM
)lv
,
437 (LPARAM
)cert_mgr_sort_by_subject
);
440 static const WCHAR my
[] = { 'M','y',0 };
441 static const WCHAR addressBook
[] = {
442 'A','d','d','r','e','s','s','B','o','o','k',0 };
443 static const WCHAR ca
[] = { 'C','A',0 };
444 static const WCHAR root
[] = { 'R','o','o','t',0 };
445 static const WCHAR trustedPublisher
[] = {
446 'T','r','u','s','t','e','d','P','u','b','l','i','s','h','e','r',0 };
447 static const WCHAR disallowed
[] = { 'D','i','s','a','l','l','o','w','e','d',0 };
449 struct CertMgrStoreInfo
453 int removePluralWarning
;
456 static const struct CertMgrStoreInfo defaultStoreList
[] = {
457 { my
, IDS_WARN_REMOVE_MY
, IDS_WARN_REMOVE_PLURAL_MY
},
458 { addressBook
, IDS_WARN_REMOVE_ADDRESSBOOK
,
459 IDS_WARN_REMOVE_PLURAL_ADDRESSBOOK
},
460 { ca
, IDS_WARN_REMOVE_CA
, IDS_WARN_REMOVE_PLURAL_CA
},
461 { root
, IDS_WARN_REMOVE_ROOT
, IDS_WARN_REMOVE_PLURAL_ROOT
},
462 { trustedPublisher
, IDS_WARN_REMOVE_TRUSTEDPUBLISHER
,
463 IDS_WARN_REMOVE_PLURAL_TRUSTEDPUBLISHER
},
464 { disallowed
, IDS_WARN_REMOVE_DEFAULT
},
467 static const struct CertMgrStoreInfo publisherStoreList
[] = {
468 { root
, IDS_WARN_REMOVE_ROOT
, IDS_WARN_REMOVE_PLURAL_ROOT
},
469 { trustedPublisher
, IDS_WARN_REMOVE_TRUSTEDPUBLISHER
,
470 IDS_WARN_REMOVE_PLURAL_TRUSTEDPUBLISHER
},
471 { disallowed
, IDS_WARN_REMOVE_PLURAL_DEFAULT
},
476 HIMAGELIST imageList
;
479 const struct CertMgrStoreInfo
*stores
;
482 static void show_cert_stores(HWND hwnd
, DWORD dwFlags
, struct CertMgrData
*data
)
484 const struct CertMgrStoreInfo
*storeList
;
486 HWND tab
= GetDlgItem(hwnd
, IDC_MGR_STORES
);
488 if (dwFlags
& CRYPTUI_CERT_MGR_PUBLISHER_TAB
)
490 storeList
= publisherStoreList
;
491 cStores
= ARRAY_SIZE(publisherStoreList
);
495 storeList
= defaultStoreList
;
496 cStores
= ARRAY_SIZE(defaultStoreList
);
498 if (dwFlags
& CRYPTUI_CERT_MGR_SINGLE_TAB_FLAG
)
500 data
->nStores
= cStores
;
501 data
->stores
= storeList
;
502 for (i
= 0; i
< cStores
; i
++)
508 if (!(name
= CryptFindLocalizedName(storeList
[i
].name
)))
509 name
= storeList
[i
].name
;
510 store
= CertOpenStore(CERT_STORE_PROV_SYSTEM_W
, 0, 0,
511 CERT_SYSTEM_STORE_CURRENT_USER
, storeList
[i
].name
);
512 item
.mask
= TCIF_TEXT
| TCIF_PARAM
;
513 item
.pszText
= (LPWSTR
)name
;
514 item
.lParam
= (LPARAM
)store
;
515 SendMessageW(tab
, TCM_INSERTITEMW
, i
, (LPARAM
)&item
);
519 static void free_certs(HWND lv
)
522 int items
= SendMessageW(lv
, LVM_GETITEMCOUNT
, 0, 0), i
;
524 for (i
= 0; i
< items
; i
++)
526 item
.mask
= LVIF_PARAM
;
529 SendMessageW(lv
, LVM_GETITEMW
, 0, (LPARAM
)&item
);
530 CertFreeCertificateContext((PCCERT_CONTEXT
)item
.lParam
);
534 static HCERTSTORE
cert_mgr_index_to_store(HWND tab
, int index
)
538 item
.mask
= TCIF_PARAM
;
539 SendMessageW(tab
, TCM_GETITEMW
, index
, (LPARAM
)&item
);
540 return (HCERTSTORE
)item
.lParam
;
543 static HCERTSTORE
cert_mgr_current_store(HWND hwnd
)
545 HWND tab
= GetDlgItem(hwnd
, IDC_MGR_STORES
);
547 return cert_mgr_index_to_store(tab
, SendMessageW(tab
, TCM_GETCURSEL
, 0, 0));
550 static void close_stores(HWND tab
)
552 int i
, tabs
= SendMessageW(tab
, TCM_GETITEMCOUNT
, 0, 0);
554 for (i
= 0; i
< tabs
; i
++)
555 CertCloseStore(cert_mgr_index_to_store(tab
, i
), 0);
558 static void refresh_store_certs(HWND hwnd
)
560 HWND lv
= GetDlgItem(hwnd
, IDC_MGR_CERTS
);
563 SendMessageW(lv
, LVM_DELETEALLITEMS
, 0, 0);
564 show_store_certs(hwnd
, cert_mgr_current_store(hwnd
));
568 CheckBitmapIndexUnchecked
= 1,
569 CheckBitmapIndexChecked
= 2,
570 CheckBitmapIndexDisabledUnchecked
= 3,
571 CheckBitmapIndexDisabledChecked
= 4
574 static void add_known_usage(HWND lv
, PCCRYPT_OID_INFO info
,
575 CheckBitmapIndex state
)
579 item
.mask
= LVIF_TEXT
| LVIF_STATE
| LVIF_PARAM
;
580 item
.state
= INDEXTOSTATEIMAGEMASK(state
);
581 item
.stateMask
= LVIS_STATEIMAGEMASK
;
582 item
.iItem
= SendMessageW(lv
, LVM_GETITEMCOUNT
, 0, 0);
584 item
.lParam
= (LPARAM
)info
;
585 item
.pszText
= (LPWSTR
)info
->pwszName
;
586 SendMessageW(lv
, LVM_INSERTITEMW
, 0, (LPARAM
)&item
);
589 static void add_known_usages_to_list(HWND lv
, CheckBitmapIndex state
)
591 PCCRYPT_OID_INFO
*usages
;
593 if (WTHelperGetKnownUsages(1, &usages
))
595 PCCRYPT_OID_INFO
*ptr
;
597 for (ptr
= usages
; *ptr
; ptr
++)
598 add_known_usage(lv
, *ptr
, state
);
599 WTHelperGetKnownUsages(2, &usages
);
603 static void toggle_usage(HWND hwnd
, int iItem
)
607 HWND lv
= GetDlgItem(hwnd
, IDC_CERTIFICATE_USAGES
);
609 item
.mask
= LVIF_STATE
;
612 item
.stateMask
= LVIS_STATEIMAGEMASK
;
613 res
= SendMessageW(lv
, LVM_GETITEMW
, 0, (LPARAM
)&item
);
616 int state
= item
.state
>> 12;
618 item
.state
= INDEXTOSTATEIMAGEMASK(
619 state
== CheckBitmapIndexChecked
? CheckBitmapIndexUnchecked
:
620 CheckBitmapIndexChecked
);
621 SendMessageW(lv
, LVM_SETITEMSTATE
, iItem
, (LPARAM
)&item
);
625 static LONG_PTR
find_oid_in_list(HWND lv
, LPCSTR oid
)
627 PCCRYPT_OID_INFO oidInfo
= CryptFindOIDInfo(CRYPT_OID_INFO_OID_KEY
,
628 (void *)oid
, CRYPT_ENHKEY_USAGE_OID_GROUP_ID
);
633 LVFINDINFOW findInfo
;
635 findInfo
.flags
= LVFI_PARAM
;
636 findInfo
.lParam
= (LPARAM
)oidInfo
;
637 ret
= SendMessageW(lv
, LVM_FINDITEMW
, -1, (LPARAM
)&findInfo
);
641 LVFINDINFOA findInfo
;
643 findInfo
.flags
= LVFI_STRING
;
645 ret
= SendMessageW(lv
, LVM_FINDITEMA
, -1, (LPARAM
)&findInfo
);
650 static void save_cert_mgr_usages(HWND hwnd
)
652 static const WCHAR keyName
[] = { 'S','o','f','t','w','a','r','e','\\','M',
653 'i','c','r','o','s','o','f','t','\\','C','r','y','p','t','o','g','r','a',
654 'p','h','y','\\','U','I','\\','C','e','r','t','m','g','r','\\','P','u',
655 'r','p','o','s','e',0 };
657 HWND lv
= GetDlgItem(hwnd
, IDC_CERTIFICATE_USAGES
);
658 int purposes
= SendMessageW(lv
, LVM_GETITEMCOUNT
, 0, 0), i
;
662 item
.mask
= LVIF_STATE
| LVIF_PARAM
;
664 item
.stateMask
= LVIS_STATEIMAGEMASK
;
665 for (i
= 0; i
< purposes
; i
++)
668 if (SendMessageW(lv
, LVM_GETITEMW
, 0, (LPARAM
)&item
))
670 int state
= item
.state
>> 12;
672 if (state
== CheckBitmapIndexUnchecked
)
674 CRYPT_OID_INFO
*info
= (CRYPT_OID_INFO
*)item
.lParam
;
675 BOOL firstString
= TRUE
;
678 str
= malloc(strlen(info
->pszOID
) + 1);
681 str
= realloc(str
, strlen(str
) + 1 + strlen(info
->pszOID
) + 1);
686 LPSTR ptr
= firstString
? str
: str
+ strlen(str
);
690 strcpy(ptr
, info
->pszOID
);
695 if (!RegCreateKeyExW(HKEY_CURRENT_USER
, keyName
, 0, NULL
, 0, KEY_ALL_ACCESS
,
699 RegSetValueExA(key
, "Purpose", 0, REG_SZ
, (const BYTE
*)str
,
702 RegDeleteValueA(key
, "Purpose");
708 static INT_PTR CALLBACK
cert_mgr_advanced_dlg_proc(HWND hwnd
, UINT msg
,
709 WPARAM wp
, LPARAM lp
)
717 HWND lv
= GetDlgItem(hwnd
, IDC_CERTIFICATE_USAGES
);
718 HIMAGELIST imageList
;
719 LPSTR disabledUsages
;
721 GetWindowRect(lv
, &rc
);
722 column
.mask
= LVCF_WIDTH
;
723 column
.cx
= rc
.right
- rc
.left
;
724 SendMessageW(lv
, LVM_INSERTCOLUMNW
, 0, (LPARAM
)&column
);
725 imageList
= ImageList_Create(16, 16, ILC_COLOR4
| ILC_MASK
, 4, 0);
729 COLORREF backColor
= RGB(255, 0, 255);
731 bmp
= LoadBitmapW(hInstance
, MAKEINTRESOURCEW(IDB_CHECKS
));
732 ImageList_AddMasked(imageList
, bmp
, backColor
);
734 ImageList_SetBkColor(imageList
, CLR_NONE
);
735 SendMessageW(lv
, LVM_SETIMAGELIST
, LVSIL_STATE
, (LPARAM
)imageList
);
736 SetWindowLongPtrW(hwnd
, DWLP_USER
, (LPARAM
)imageList
);
738 add_known_usages_to_list(lv
, CheckBitmapIndexChecked
);
739 if ((disabledUsages
= get_cert_mgr_usages()))
743 for (ptr
= disabledUsages
, comma
= strchr(ptr
, ','); ptr
&& *ptr
;
744 ptr
= comma
? comma
+ 1 : NULL
,
745 comma
= ptr
? strchr(ptr
, ',') : NULL
)
751 if ((index
= find_oid_in_list(lv
, ptr
)) != -1)
752 toggle_usage(hwnd
, index
);
754 free(disabledUsages
);
760 NMHDR
*hdr
= (NMHDR
*)lp
;
766 nm
= (NMITEMACTIVATE
*)lp
;
767 toggle_usage(hwnd
, nm
->iItem
);
768 SendMessageW(GetParent(hwnd
), PSM_CHANGED
, (WPARAM
)hwnd
, 0);
777 save_cert_mgr_usages(hwnd
);
778 ImageList_Destroy((HIMAGELIST
)GetWindowLongPtrW(hwnd
, DWLP_USER
));
779 EndDialog(hwnd
, IDOK
);
782 ImageList_Destroy((HIMAGELIST
)GetWindowLongPtrW(hwnd
, DWLP_USER
));
783 EndDialog(hwnd
, IDCANCEL
);
791 static void cert_mgr_clear_cert_selection(HWND hwnd
)
793 EnableWindow(GetDlgItem(hwnd
, IDC_MGR_EXPORT
), FALSE
);
794 EnableWindow(GetDlgItem(hwnd
, IDC_MGR_REMOVE
), FALSE
);
795 EnableWindow(GetDlgItem(hwnd
, IDC_MGR_VIEW
), FALSE
);
796 SendMessageW(GetDlgItem(hwnd
, IDC_MGR_PURPOSES
), WM_SETTEXT
, 0,
798 refresh_store_certs(hwnd
);
801 static PCCERT_CONTEXT
cert_mgr_index_to_cert(HWND hwnd
, int index
)
803 PCCERT_CONTEXT cert
= NULL
;
806 item
.mask
= LVIF_PARAM
;
809 if (SendMessageW(GetDlgItem(hwnd
, IDC_MGR_CERTS
), LVM_GETITEMW
, 0,
811 cert
= (PCCERT_CONTEXT
)item
.lParam
;
815 static void show_selected_cert(HWND hwnd
, int index
)
817 PCCERT_CONTEXT cert
= cert_mgr_index_to_cert(hwnd
, index
);
821 CRYPTUI_VIEWCERTIFICATE_STRUCTW viewInfo
;
823 memset(&viewInfo
, 0, sizeof(viewInfo
));
824 viewInfo
.dwSize
= sizeof(viewInfo
);
825 viewInfo
.hwndParent
= hwnd
;
826 viewInfo
.pCertContext
= cert
;
827 /* FIXME: this should be modal */
828 CryptUIDlgViewCertificateW(&viewInfo
, NULL
);
832 static void get_cert_usages(PCCERT_CONTEXT cert
, LPWSTR
*str
)
834 PCERT_ENHKEY_USAGE usage
;
837 /* Get enhanced key usage. Have to check for a property and an extension
838 * separately, because CertGetEnhancedKeyUsage will succeed and return an
839 * empty usage if neither is set. Unfortunately an empty usage implies
840 * no usage is allowed, so we have to distinguish between the two cases.
842 if (CertGetEnhancedKeyUsage(cert
, CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG
,
845 usage
= malloc(size
);
846 if (!CertGetEnhancedKeyUsage(cert
,
847 CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG
, usage
, &size
))
853 else if (CertGetEnhancedKeyUsage(cert
, CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG
,
856 usage
= malloc(size
);
857 if (!CertGetEnhancedKeyUsage(cert
,
858 CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG
, usage
, &size
))
868 if (usage
->cUsageIdentifier
)
870 static const WCHAR commaSpace
[] = { ',',' ',0 };
874 for (i
= 0; i
< usage
->cUsageIdentifier
; i
++)
876 PCCRYPT_OID_INFO info
=
877 CryptFindOIDInfo(CRYPT_OID_INFO_OID_KEY
,
878 usage
->rgpszUsageIdentifier
[i
],
879 CRYPT_ENHKEY_USAGE_OID_GROUP_ID
);
882 len
+= lstrlenW(info
->pwszName
);
884 len
+= strlen(usage
->rgpszUsageIdentifier
[i
]);
885 if (i
< usage
->cUsageIdentifier
- 1)
886 len
+= lstrlenW(commaSpace
);
888 *str
= malloc(len
* sizeof(WCHAR
));
891 for (i
= 0, ptr
= *str
; i
< usage
->cUsageIdentifier
; i
++)
893 PCCRYPT_OID_INFO info
=
894 CryptFindOIDInfo(CRYPT_OID_INFO_OID_KEY
,
895 usage
->rgpszUsageIdentifier
[i
],
896 CRYPT_ENHKEY_USAGE_OID_GROUP_ID
);
900 lstrcpyW(ptr
, info
->pwszName
);
901 ptr
+= lstrlenW(info
->pwszName
);
905 LPCSTR src
= usage
->rgpszUsageIdentifier
[i
];
907 for (; *src
; ptr
++, src
++)
911 if (i
< usage
->cUsageIdentifier
- 1)
913 lstrcpyW(ptr
, commaSpace
);
914 ptr
+= lstrlenW(commaSpace
);
923 size
= MAX_STRING_LEN
* sizeof(WCHAR
);
926 LoadStringW(hInstance
, IDS_ALLOWED_PURPOSE_NONE
, *str
, MAX_STRING_LEN
);
931 size
= MAX_STRING_LEN
* sizeof(WCHAR
);
934 LoadStringW(hInstance
, IDS_ALLOWED_PURPOSE_ALL
, *str
, MAX_STRING_LEN
);
938 static void cert_mgr_show_cert_usages(HWND hwnd
, int index
)
940 HWND text
= GetDlgItem(hwnd
, IDC_MGR_PURPOSES
);
941 PCCERT_CONTEXT cert
= cert_mgr_index_to_cert(hwnd
, index
);
944 get_cert_usages(cert
, &str
);
947 SendMessageW(text
, WM_SETTEXT
, 0, (LPARAM
)str
);
952 static void cert_mgr_do_remove(HWND hwnd
)
954 int tabIndex
= SendMessageW(GetDlgItem(hwnd
, IDC_MGR_STORES
),
955 TCM_GETCURSEL
, 0, 0);
956 struct CertMgrData
*data
=
957 (struct CertMgrData
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
959 if (tabIndex
< data
->nStores
)
961 HWND lv
= GetDlgItem(hwnd
, IDC_MGR_CERTS
);
962 WCHAR warning
[MAX_STRING_LEN
], title
[MAX_STRING_LEN
];
966 if (SendMessageW(lv
, LVM_GETSELECTEDCOUNT
, 0, 0) > 1)
967 warningID
= data
->stores
[tabIndex
].removePluralWarning
;
969 warningID
= data
->stores
[tabIndex
].removeWarning
;
971 pTitle
= data
->title
;
974 LoadStringW(hInstance
, IDS_CERT_MGR
, title
, ARRAY_SIZE(title
));
977 LoadStringW(hInstance
, warningID
, warning
, ARRAY_SIZE(warning
));
978 if (MessageBoxW(hwnd
, warning
, pTitle
, MB_YESNO
) == IDYES
)
983 selection
= SendMessageW(lv
, LVM_GETNEXTITEM
, selection
,
987 PCCERT_CONTEXT cert
= cert_mgr_index_to_cert(hwnd
,
990 CertDeleteCertificateFromStore(cert
);
992 } while (selection
>= 0);
993 cert_mgr_clear_cert_selection(hwnd
);
998 static void cert_mgr_do_export(HWND hwnd
)
1000 HWND lv
= GetDlgItem(hwnd
, IDC_MGR_CERTS
);
1001 int selectionCount
= SendMessageW(lv
, LVM_GETSELECTEDCOUNT
, 0, 0);
1003 if (selectionCount
== 1)
1005 int selection
= SendMessageW(lv
, LVM_GETNEXTITEM
, -1,
1010 PCCERT_CONTEXT cert
= cert_mgr_index_to_cert(hwnd
, selection
);
1014 CRYPTUI_WIZ_EXPORT_INFO info
;
1016 info
.dwSize
= sizeof(info
);
1017 info
.pwszExportFileName
= NULL
;
1018 info
.dwSubjectChoice
= CRYPTUI_WIZ_EXPORT_CERT_CONTEXT
;
1019 info
.pCertContext
= cert
;
1021 CryptUIWizExport(0, hwnd
, NULL
, &info
, NULL
);
1025 else if (selectionCount
> 1)
1027 HCERTSTORE store
= CertOpenStore(CERT_STORE_PROV_MEMORY
, 0, 0,
1028 CERT_STORE_CREATE_NEW_FLAG
, NULL
);
1032 CRYPTUI_WIZ_EXPORT_INFO info
;
1035 info
.dwSize
= sizeof(info
);
1036 info
.pwszExportFileName
= NULL
;
1037 info
.dwSubjectChoice
=
1038 CRYPTUI_WIZ_EXPORT_CERT_STORE_CERTIFICATES_ONLY
;
1039 info
.hCertStore
= store
;
1042 selection
= SendMessageW(lv
, LVM_GETNEXTITEM
, selection
,
1046 PCCERT_CONTEXT cert
= cert_mgr_index_to_cert(hwnd
,
1049 CertAddCertificateContextToStore(store
, cert
,
1050 CERT_STORE_ADD_ALWAYS
, NULL
);
1052 } while (selection
>= 0);
1053 CryptUIWizExport(0, hwnd
, NULL
, &info
, NULL
);
1054 CertCloseStore(store
, 0);
1059 static int cert_mgr_sort_by_text(HWND lv
, int col
, int index1
, int index2
)
1062 WCHAR buf1
[MAX_STRING_LEN
];
1063 WCHAR buf2
[MAX_STRING_LEN
];
1065 item
.cchTextMax
= ARRAY_SIZE(buf1
);
1066 item
.mask
= LVIF_TEXT
;
1067 item
.pszText
= buf1
;
1068 item
.iItem
= index1
;
1069 item
.iSubItem
= col
;
1070 SendMessageW(lv
, LVM_GETITEMW
, 0, (LPARAM
)&item
);
1071 item
.pszText
= buf2
;
1072 item
.iItem
= index2
;
1073 SendMessageW(lv
, LVM_GETITEMW
, 0, (LPARAM
)&item
);
1074 return lstrcmpW(buf1
, buf2
);
1077 static int CALLBACK
cert_mgr_sort_by_subject(LPARAM lp1
, LPARAM lp2
, LPARAM lp
)
1079 return cert_mgr_sort_by_text((HWND
)lp
, 0, lp1
, lp2
);
1082 static int CALLBACK
cert_mgr_sort_by_issuer(LPARAM lp1
, LPARAM lp2
, LPARAM lp
)
1084 return cert_mgr_sort_by_text((HWND
)lp
, 1, lp1
, lp2
);
1087 static int CALLBACK
cert_mgr_sort_by_date(LPARAM lp1
, LPARAM lp2
, LPARAM lp
)
1089 PCCERT_CONTEXT cert1
= (PCCERT_CONTEXT
)lp1
;
1090 PCCERT_CONTEXT cert2
= (PCCERT_CONTEXT
)lp2
;
1091 return CompareFileTime(&cert1
->pCertInfo
->NotAfter
,
1092 &cert2
->pCertInfo
->NotAfter
);
1095 static int CALLBACK
cert_mgr_sort_by_friendly_name(LPARAM lp1
, LPARAM lp2
,
1098 return cert_mgr_sort_by_text((HWND
)lp
, 3, lp1
, lp2
);
1101 static INT_PTR CALLBACK
cert_mgr_dlg_proc(HWND hwnd
, UINT msg
, WPARAM wp
,
1104 struct CertMgrData
*data
;
1110 PCCRYPTUI_CERT_MGR_STRUCT pCryptUICertMgr
=
1111 (PCCRYPTUI_CERT_MGR_STRUCT
)lp
;
1112 HWND tab
= GetDlgItem(hwnd
, IDC_MGR_STORES
);
1114 data
= malloc(sizeof(struct CertMgrData
));
1117 data
->imageList
= ImageList_Create(16, 16, ILC_COLOR4
| ILC_MASK
, 2, 0);
1118 if (data
->imageList
)
1121 COLORREF backColor
= RGB(255, 0, 255);
1123 bmp
= LoadBitmapW(hInstance
, MAKEINTRESOURCEW(IDB_SMALL_ICONS
));
1124 ImageList_AddMasked(data
->imageList
, bmp
, backColor
);
1126 ImageList_SetBkColor(data
->imageList
, CLR_NONE
);
1127 SendMessageW(GetDlgItem(hwnd
, IDC_MGR_CERTS
), LVM_SETIMAGELIST
,
1128 LVSIL_SMALL
, (LPARAM
)data
->imageList
);
1130 SetWindowLongPtrW(hwnd
, DWLP_USER
, (LPARAM
)data
);
1131 data
->title
= pCryptUICertMgr
->pwszTitle
;
1133 initialize_purpose_selection(hwnd
);
1134 add_cert_columns(hwnd
);
1135 if (pCryptUICertMgr
->pwszTitle
)
1136 SendMessageW(hwnd
, WM_SETTEXT
, 0,
1137 (LPARAM
)pCryptUICertMgr
->pwszTitle
);
1138 show_cert_stores(hwnd
, pCryptUICertMgr
->dwFlags
, data
);
1139 show_store_certs(hwnd
, cert_mgr_index_to_store(tab
, 0));
1144 NMHDR
*hdr
= (NMHDR
*)lp
;
1149 cert_mgr_clear_cert_selection(hwnd
);
1151 case LVN_ITEMCHANGED
:
1153 NMITEMACTIVATE
*nm
= (NMITEMACTIVATE
*)lp
;
1154 HWND lv
= GetDlgItem(hwnd
, IDC_MGR_CERTS
);
1155 int numSelected
= SendMessageW(lv
, LVM_GETSELECTEDCOUNT
, 0, 0);
1157 EnableWindow(GetDlgItem(hwnd
, IDC_MGR_EXPORT
), numSelected
> 0);
1158 EnableWindow(GetDlgItem(hwnd
, IDC_MGR_REMOVE
), numSelected
> 0);
1159 EnableWindow(GetDlgItem(hwnd
, IDC_MGR_VIEW
), numSelected
== 1);
1160 if (numSelected
== 1)
1161 cert_mgr_show_cert_usages(hwnd
, nm
->iItem
);
1163 SendMessageW(GetDlgItem(hwnd
, IDC_MGR_PURPOSES
), WM_SETTEXT
, 0,
1168 show_selected_cert(hwnd
, ((NMITEMACTIVATE
*)lp
)->iItem
);
1172 NMLVKEYDOWN
*lvk
= (NMLVKEYDOWN
*)lp
;
1174 if (lvk
->wVKey
== VK_DELETE
)
1175 cert_mgr_do_remove(hwnd
);
1178 case LVN_COLUMNCLICK
:
1180 NMLISTVIEW
*nmlv
= (NMLISTVIEW
*)lp
;
1181 HWND lv
= GetDlgItem(hwnd
, IDC_MGR_CERTS
);
1183 /* FIXME: doesn't support swapping sort order between ascending
1186 switch (nmlv
->iSubItem
)
1189 SendMessageW(lv
, LVM_SORTITEMSEX
, (WPARAM
)lv
,
1190 (LPARAM
)cert_mgr_sort_by_subject
);
1193 SendMessageW(lv
, LVM_SORTITEMSEX
, (WPARAM
)lv
,
1194 (LPARAM
)cert_mgr_sort_by_issuer
);
1197 SendMessageW(lv
, LVM_SORTITEMS
, 0,
1198 (LPARAM
)cert_mgr_sort_by_date
);
1201 SendMessageW(lv
, LVM_SORTITEMSEX
, (WPARAM
)lv
,
1202 (LPARAM
)cert_mgr_sort_by_friendly_name
);
1213 case ((CBN_SELCHANGE
<< 16) | IDC_MGR_PURPOSE_SELECTION
):
1214 cert_mgr_clear_cert_selection(hwnd
);
1216 case IDC_MGR_IMPORT
:
1217 if (CryptUIWizImport(0, hwnd
, NULL
, NULL
,
1218 cert_mgr_current_store(hwnd
)))
1219 refresh_store_certs(hwnd
);
1221 case IDC_MGR_ADVANCED
:
1222 if (DialogBoxW(hInstance
, MAKEINTRESOURCEW(IDD_CERT_MGR_ADVANCED
),
1223 hwnd
, cert_mgr_advanced_dlg_proc
) == IDOK
)
1225 HWND cb
= GetDlgItem(hwnd
, IDC_MGR_PURPOSE_SELECTION
);
1227 LPWSTR curString
= NULL
;
1229 index
= SendMessageW(cb
, CB_GETCURSEL
, 0, 0);
1232 len
= SendMessageW(cb
, CB_GETLBTEXTLEN
, index
, 0);
1233 curString
= malloc((len
+ 1) * sizeof(WCHAR
));
1234 SendMessageW(cb
, CB_GETLBTEXT
, index
, (LPARAM
)curString
);
1236 SendMessageW(cb
, CB_RESETCONTENT
, 0, 0);
1237 initialize_purpose_selection(hwnd
);
1240 index
= SendMessageW(cb
, CB_FINDSTRINGEXACT
, -1,
1243 SendMessageW(cb
, CB_SETCURSEL
, index
, 0);
1246 refresh_store_certs(hwnd
);
1251 HWND lv
= GetDlgItem(hwnd
, IDC_MGR_CERTS
);
1252 int selection
= SendMessageW(lv
, LVM_GETNEXTITEM
, -1,
1256 show_selected_cert(hwnd
, selection
);
1259 case IDC_MGR_EXPORT
:
1260 cert_mgr_do_export(hwnd
);
1262 case IDC_MGR_REMOVE
:
1263 cert_mgr_do_remove(hwnd
);
1266 free_certs(GetDlgItem(hwnd
, IDC_MGR_CERTS
));
1267 close_stores(GetDlgItem(hwnd
, IDC_MGR_STORES
));
1268 data
= (struct CertMgrData
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
1269 ImageList_Destroy(data
->imageList
);
1271 EndDialog(hwnd
, IDCANCEL
);
1279 /***********************************************************************
1280 * CryptUIDlgCertMgr (CRYPTUI.@)
1282 BOOL WINAPI
CryptUIDlgCertMgr(PCCRYPTUI_CERT_MGR_STRUCT pCryptUICertMgr
)
1284 TRACE("(%p)\n", pCryptUICertMgr
);
1286 if (pCryptUICertMgr
->dwSize
!= sizeof(CRYPTUI_CERT_MGR_STRUCT
))
1288 WARN("unexpected size %ld\n", pCryptUICertMgr
->dwSize
);
1289 SetLastError(E_INVALIDARG
);
1292 DialogBoxParamW(hInstance
, MAKEINTRESOURCEW(IDD_CERT_MGR
),
1293 pCryptUICertMgr
->hwndParent
, cert_mgr_dlg_proc
, (LPARAM
)pCryptUICertMgr
);
1297 /* FIXME: real names are unknown, functions are undocumented */
1298 typedef struct _CRYPTUI_ENUM_SYSTEM_STORE_ARGS
1301 void *pvSystemStoreLocationPara
;
1302 } CRYPTUI_ENUM_SYSTEM_STORE_ARGS
, *PCRYPTUI_ENUM_SYSTEM_STORE_ARGS
;
1304 typedef struct _CRYPTUI_ENUM_DATA
1307 HCERTSTORE
*rghStore
;
1309 PCRYPTUI_ENUM_SYSTEM_STORE_ARGS rgEnumArgs
;
1310 } CRYPTUI_ENUM_DATA
, *PCRYPTUI_ENUM_DATA
;
1312 typedef BOOL (WINAPI
*PFN_SELECTED_STORE_CB
)(HCERTSTORE store
, HWND hwnd
,
1315 /* Values for dwFlags */
1316 #define CRYPTUI_ENABLE_SHOW_PHYSICAL_STORE 0x00000001
1318 typedef struct _CRYPTUI_SELECTSTORE_INFO_A
1325 CRYPTUI_ENUM_DATA
*pEnumData
;
1326 PFN_SELECTED_STORE_CB pfnSelectedStoreCallback
;
1328 } CRYPTUI_SELECTSTORE_INFO_A
, *PCRYPTUI_SELECTSTORE_INFO_A
;
1330 typedef struct _CRYPTUI_SELECTSTORE_INFO_W
1337 CRYPTUI_ENUM_DATA
*pEnumData
;
1338 PFN_SELECTED_STORE_CB pfnSelectedStoreCallback
;
1340 } CRYPTUI_SELECTSTORE_INFO_W
, *PCRYPTUI_SELECTSTORE_INFO_W
;
1354 static BOOL WINAPI
enum_store_callback(const void *pvSystemStore
,
1355 DWORD dwFlags
, PCERT_SYSTEM_STORE_INFO pStoreInfo
, void *pvReserved
,
1358 HWND tree
= GetDlgItem(pvArg
, IDC_STORE_LIST
);
1359 TVINSERTSTRUCTW tvis
;
1360 LPCWSTR localizedName
;
1363 tvis
.hParent
= NULL
;
1364 tvis
.hInsertAfter
= TVI_LAST
;
1365 tvis
.item
.mask
= TVIF_TEXT
;
1366 if ((localizedName
= CryptFindLocalizedName(pvSystemStore
)))
1368 struct StoreInfo
*storeInfo
= malloc(sizeof(struct StoreInfo
));
1372 storeInfo
->type
= SystemStore
;
1373 storeInfo
->name
= wcsdup(pvSystemStore
);
1374 if (storeInfo
->name
)
1376 tvis
.item
.mask
|= TVIF_PARAM
;
1377 tvis
.item
.lParam
= (LPARAM
)storeInfo
;
1387 tvis
.item
.pszText
= (LPWSTR
)localizedName
;
1390 tvis
.item
.pszText
= (LPWSTR
)pvSystemStore
;
1391 /* FIXME: need a folder icon for the store too */
1393 SendMessageW(tree
, TVM_INSERTITEMW
, 0, (LPARAM
)&tvis
);
1397 static void enumerate_stores(HWND hwnd
, CRYPTUI_ENUM_DATA
*pEnumData
)
1400 HWND tree
= GetDlgItem(hwnd
, IDC_STORE_LIST
);
1402 for (i
= 0; i
< pEnumData
->cEnumArgs
; i
++)
1403 CertEnumSystemStore(pEnumData
->rgEnumArgs
[i
].dwFlags
,
1404 pEnumData
->rgEnumArgs
[i
].pvSystemStoreLocationPara
,
1405 hwnd
, enum_store_callback
);
1406 for (i
= 0; i
< pEnumData
->cStores
; i
++)
1410 if (CertGetStoreProperty(pEnumData
->rghStore
[i
],
1411 CERT_STORE_LOCALIZED_NAME_PROP_ID
, NULL
, &size
))
1413 WCHAR
*name
= malloc(size
);
1417 if (CertGetStoreProperty(pEnumData
->rghStore
[i
],
1418 CERT_STORE_LOCALIZED_NAME_PROP_ID
, name
, &size
))
1420 struct StoreInfo
*storeInfo
= malloc(sizeof(struct StoreInfo
));
1424 TVINSERTSTRUCTW tvis
;
1426 storeInfo
->type
= StoreHandle
;
1427 storeInfo
->store
= pEnumData
->rghStore
[i
];
1428 tvis
.hParent
= NULL
;
1429 tvis
.hInsertAfter
= TVI_LAST
;
1430 tvis
.item
.mask
= TVIF_TEXT
| TVIF_PARAM
;
1431 tvis
.item
.pszText
= name
;
1432 tvis
.item
.lParam
= (LPARAM
)storeInfo
;
1433 SendMessageW(tree
, TVM_INSERTITEMW
, 0, (LPARAM
)&tvis
);
1442 static void free_store_info(HWND tree
)
1444 HTREEITEM next
= (HTREEITEM
)SendMessageW(tree
, TVM_GETNEXTITEM
, TVGN_CHILD
,
1451 memset(&item
, 0, sizeof(item
));
1452 item
.mask
= TVIF_HANDLE
| TVIF_PARAM
;
1454 SendMessageW(tree
, TVM_GETITEMW
, 0, (LPARAM
)&item
);
1457 struct StoreInfo
*storeInfo
= (struct StoreInfo
*)item
.lParam
;
1459 if (storeInfo
->type
== SystemStore
)
1460 free(storeInfo
->name
);
1463 next
= (HTREEITEM
)SendMessageW(tree
, TVM_GETNEXTITEM
, TVGN_NEXT
,
1468 static HCERTSTORE
selected_item_to_store(HWND tree
, HTREEITEM hItem
)
1470 WCHAR buf
[MAX_STRING_LEN
];
1474 memset(&item
, 0, sizeof(item
));
1475 item
.mask
= TVIF_HANDLE
| TVIF_PARAM
| TVIF_TEXT
;
1477 item
.cchTextMax
= ARRAY_SIZE(buf
);
1479 SendMessageW(tree
, TVM_GETITEMW
, 0, (LPARAM
)&item
);
1482 struct StoreInfo
*storeInfo
= (struct StoreInfo
*)item
.lParam
;
1484 if (storeInfo
->type
== StoreHandle
)
1485 store
= storeInfo
->store
;
1487 store
= CertOpenSystemStoreW(0, storeInfo
->name
);
1491 /* It's implicitly a system store */
1492 store
= CertOpenSystemStoreW(0, buf
);
1497 struct SelectStoreInfo
1499 PCRYPTUI_SELECTSTORE_INFO_W info
;
1503 static INT_PTR CALLBACK
select_store_dlg_proc(HWND hwnd
, UINT msg
, WPARAM wp
,
1506 struct SelectStoreInfo
*selectInfo
;
1513 selectInfo
= (struct SelectStoreInfo
*)lp
;
1514 SetWindowLongPtrW(hwnd
, DWLP_USER
, lp
);
1515 if (selectInfo
->info
->pwszTitle
)
1516 SendMessageW(hwnd
, WM_SETTEXT
, 0,
1517 (LPARAM
)selectInfo
->info
->pwszTitle
);
1518 if (selectInfo
->info
->pwszText
)
1519 SendMessageW(GetDlgItem(hwnd
, IDC_STORE_TEXT
), WM_SETTEXT
, 0,
1520 (LPARAM
)selectInfo
->info
->pwszText
);
1521 if (!(selectInfo
->info
->dwFlags
& CRYPTUI_ENABLE_SHOW_PHYSICAL_STORE
))
1522 ShowWindow(GetDlgItem(hwnd
, IDC_SHOW_PHYSICAL_STORES
), FALSE
);
1523 enumerate_stores(hwnd
, selectInfo
->info
->pEnumData
);
1531 HWND tree
= GetDlgItem(hwnd
, IDC_STORE_LIST
);
1532 HTREEITEM selection
= (HTREEITEM
)SendMessageW(tree
,
1533 TVM_GETNEXTITEM
, TVGN_CARET
, 0);
1535 selectInfo
= (struct SelectStoreInfo
*)GetWindowLongPtrW(hwnd
,
1539 WCHAR title
[MAX_STRING_LEN
], error
[MAX_STRING_LEN
], *pTitle
;
1541 if (selectInfo
->info
->pwszTitle
)
1542 pTitle
= selectInfo
->info
->pwszTitle
;
1545 LoadStringW(hInstance
, IDS_SELECT_STORE_TITLE
, title
, ARRAY_SIZE(title
));
1548 LoadStringW(hInstance
, IDS_SELECT_STORE
, error
, ARRAY_SIZE(error
));
1549 MessageBoxW(hwnd
, error
, pTitle
, MB_ICONEXCLAMATION
| MB_OK
);
1553 HCERTSTORE store
= selected_item_to_store(tree
, selection
);
1555 if (!selectInfo
->info
->pfnSelectedStoreCallback
||
1556 selectInfo
->info
->pfnSelectedStoreCallback(store
, hwnd
,
1557 selectInfo
->info
->pvArg
))
1559 selectInfo
->store
= store
;
1560 free_store_info(tree
);
1561 EndDialog(hwnd
, IDOK
);
1564 CertCloseStore(store
, 0);
1570 free_store_info(GetDlgItem(hwnd
, IDC_STORE_LIST
));
1571 EndDialog(hwnd
, IDCANCEL
);
1580 /***********************************************************************
1581 * CryptUIDlgSelectStoreW (CRYPTUI.@)
1583 HCERTSTORE WINAPI
CryptUIDlgSelectStoreW(PCRYPTUI_SELECTSTORE_INFO_W info
)
1585 struct SelectStoreInfo selectInfo
= { info
, NULL
};
1587 TRACE("(%p)\n", info
);
1589 if (info
->dwSize
!= sizeof(CRYPTUI_SELECTSTORE_INFO_W
))
1591 WARN("unexpected size %ld\n", info
->dwSize
);
1592 SetLastError(E_INVALIDARG
);
1595 DialogBoxParamW(hInstance
, MAKEINTRESOURCEW(IDD_SELECT_STORE
), info
->parent
,
1596 select_store_dlg_proc
, (LPARAM
)&selectInfo
);
1597 return selectInfo
.store
;
1600 /***********************************************************************
1601 * CryptUIDlgSelectStoreA (CRYPTUI.@)
1603 HCERTSTORE WINAPI
CryptUIDlgSelectStoreA(PCRYPTUI_SELECTSTORE_INFO_A info
)
1605 CRYPTUI_SELECTSTORE_INFO_W infoW
;
1609 TRACE("(%p)\n", info
);
1611 if (info
->dwSize
!= sizeof(CRYPTUI_SELECTSTORE_INFO_A
))
1613 WARN("unexpected size %ld\n", info
->dwSize
);
1614 SetLastError(E_INVALIDARG
);
1617 memcpy(&infoW
, info
, sizeof(*info
));
1620 len
= MultiByteToWideChar(CP_ACP
, 0, info
->pszTitle
, -1, NULL
, 0);
1621 infoW
.pwszTitle
= malloc(len
* sizeof(WCHAR
));
1622 MultiByteToWideChar(CP_ACP
, 0, info
->pszTitle
, -1, infoW
.pwszTitle
,
1627 len
= MultiByteToWideChar(CP_ACP
, 0, info
->pszText
, -1, NULL
, 0);
1628 infoW
.pwszText
= malloc(len
* sizeof(WCHAR
));
1629 MultiByteToWideChar(CP_ACP
, 0, info
->pszText
, -1, infoW
.pwszText
, len
);
1631 ret
= CryptUIDlgSelectStoreW(&infoW
);
1632 free(infoW
.pwszText
);
1633 free(infoW
.pwszTitle
);
1637 /***********************************************************************
1638 * CryptUIDlgViewCertificateA (CRYPTUI.@)
1640 BOOL WINAPI
CryptUIDlgViewCertificateA(
1641 PCCRYPTUI_VIEWCERTIFICATE_STRUCTA pCertViewInfo
, BOOL
*pfPropertiesChanged
)
1643 CRYPTUI_VIEWCERTIFICATE_STRUCTW viewInfo
;
1644 LPWSTR title
= NULL
;
1647 TRACE("(%p, %p)\n", pCertViewInfo
, pfPropertiesChanged
);
1649 memcpy(&viewInfo
, pCertViewInfo
, sizeof(viewInfo
));
1650 if (pCertViewInfo
->szTitle
)
1652 int len
= MultiByteToWideChar(CP_ACP
, 0, pCertViewInfo
->szTitle
, -1,
1655 title
= malloc(len
* sizeof(WCHAR
));
1658 MultiByteToWideChar(CP_ACP
, 0, pCertViewInfo
->szTitle
, -1, title
,
1660 viewInfo
.szTitle
= title
;
1668 if (pCertViewInfo
->cPropSheetPages
)
1670 FIXME("ignoring additional prop sheet pages\n");
1671 viewInfo
.cPropSheetPages
= 0;
1673 ret
= CryptUIDlgViewCertificateW(&viewInfo
, pfPropertiesChanged
);
1679 struct ReadStringStruct
1686 static DWORD CALLBACK
read_text_callback(DWORD_PTR dwCookie
, LPBYTE buf
,
1689 struct ReadStringStruct
*string
= (struct ReadStringStruct
*)dwCookie
;
1690 LONG cch
= min(cb
/ sizeof(WCHAR
), string
->len
- string
->pos
);
1692 TRACE("(%p, %p, %ld, %p)\n", string
, buf
, cb
, pcb
);
1694 memmove(buf
, string
->buf
+ string
->pos
, cch
* sizeof(WCHAR
));
1696 *pcb
= cch
* sizeof(WCHAR
);
1700 static void add_unformatted_text_to_control(HWND hwnd
, LPCWSTR text
, LONG len
)
1702 struct ReadStringStruct string
;
1703 EDITSTREAM editstream
;
1705 TRACE("(%p, %s)\n", hwnd
, debugstr_wn(text
, len
));
1710 editstream
.dwCookie
= (DWORD_PTR
)&string
;
1711 editstream
.dwError
= 0;
1712 editstream
.pfnCallback
= read_text_callback
;
1713 SendMessageW(hwnd
, EM_STREAMIN
, SF_TEXT
| SFF_SELECTION
| SF_UNICODE
,
1714 (LPARAM
)&editstream
);
1717 static void add_string_resource_to_control(HWND hwnd
, int id
)
1722 len
= LoadStringW(hInstance
, id
, (LPWSTR
)&str
, 0);
1723 add_unformatted_text_to_control(hwnd
, str
, len
);
1726 static void add_text_with_paraformat_to_control(HWND hwnd
, LPCWSTR text
,
1727 LONG len
, const PARAFORMAT2
*fmt
)
1729 add_unformatted_text_to_control(hwnd
, text
, len
);
1730 SendMessageW(hwnd
, EM_SETPARAFORMAT
, 0, (LPARAM
)fmt
);
1733 static void add_string_resource_with_paraformat_to_control(HWND hwnd
, int id
,
1734 const PARAFORMAT2
*fmt
)
1739 len
= LoadStringW(hInstance
, id
, (LPWSTR
)&str
, 0);
1740 add_text_with_paraformat_to_control(hwnd
, str
, len
, fmt
);
1743 static LPWSTR
get_cert_name_string(PCCERT_CONTEXT pCertContext
, DWORD dwType
,
1749 len
= CertGetNameStringW(pCertContext
, dwType
, dwFlags
, NULL
, NULL
, 0);
1752 buf
= malloc(len
* sizeof(WCHAR
));
1754 CertGetNameStringW(pCertContext
, dwType
, dwFlags
, NULL
, buf
, len
);
1759 static void add_cert_string_to_control(HWND hwnd
, PCCERT_CONTEXT pCertContext
,
1760 DWORD dwType
, DWORD dwFlags
)
1762 LPWSTR name
= get_cert_name_string(pCertContext
, dwType
, dwFlags
);
1766 /* Don't include NULL-terminator in output */
1767 DWORD len
= lstrlenW(name
);
1769 add_unformatted_text_to_control(hwnd
, name
, len
);
1774 static void add_icon_to_control(HWND hwnd
, int id
)
1777 IRichEditOle
*richEditOle
= NULL
;
1778 IOleObject
*object
= NULL
;
1780 LPOLECACHE oleCache
= NULL
;
1781 FORMATETC formatEtc
;
1783 IDataObject
*dataObject
= NULL
;
1784 HBITMAP bitmap
= NULL
;
1786 IOleClientSite
*clientSite
= NULL
;
1789 TRACE("(%p, %d)\n", hwnd
, id
);
1791 SendMessageW(hwnd
, EM_GETOLEINTERFACE
, 0, (LPARAM
)&richEditOle
);
1794 hr
= OleCreateDefaultHandler(&CLSID_NULL
, NULL
, &IID_IOleObject
,
1798 hr
= IOleObject_GetUserClassID(object
, &clsid
);
1801 hr
= IOleObject_QueryInterface(object
, &IID_IOleCache
, (void**)&oleCache
);
1804 formatEtc
.cfFormat
= CF_BITMAP
;
1805 formatEtc
.ptd
= NULL
;
1806 formatEtc
.dwAspect
= DVASPECT_CONTENT
;
1807 formatEtc
.lindex
= -1;
1808 formatEtc
.tymed
= TYMED_GDI
;
1809 hr
= IOleCache_Cache(oleCache
, &formatEtc
, 0, &conn
);
1812 hr
= IOleObject_QueryInterface(object
, &IID_IDataObject
,
1813 (void**)&dataObject
);
1816 hr
= IRichEditOle_GetClientSite(richEditOle
, &clientSite
);
1819 bitmap
= LoadImageW(hInstance
, MAKEINTRESOURCEW(id
), IMAGE_BITMAP
, 0, 0,
1820 LR_DEFAULTSIZE
| LR_LOADTRANSPARENT
);
1823 stgm
.tymed
= TYMED_GDI
;
1824 stgm
.hBitmap
= bitmap
;
1825 stgm
.pUnkForRelease
= NULL
;
1826 hr
= IDataObject_SetData(dataObject
, &formatEtc
, &stgm
, TRUE
);
1830 reObject
.cbStruct
= sizeof(reObject
);
1831 reObject
.cp
= REO_CP_SELECTION
;
1832 reObject
.clsid
= clsid
;
1833 reObject
.poleobj
= object
;
1834 reObject
.pstg
= NULL
;
1835 reObject
.polesite
= clientSite
;
1836 reObject
.sizel
.cx
= reObject
.sizel
.cy
= 0;
1837 reObject
.dvaspect
= DVASPECT_CONTENT
;
1838 reObject
.dwFlags
= 0;
1839 reObject
.dwUser
= 0;
1841 IRichEditOle_InsertObject(richEditOle
, &reObject
);
1845 IOleClientSite_Release(clientSite
);
1847 IDataObject_Release(dataObject
);
1849 IOleCache_Release(oleCache
);
1851 IOleObject_Release(object
);
1853 IRichEditOle_Release(richEditOle
);
1856 #define MY_INDENT 200
1858 static void add_oid_text_to_control(HWND hwnd
, char *oid
)
1861 PCCRYPT_OID_INFO oidInfo
= CryptFindOIDInfo(CRYPT_OID_INFO_OID_KEY
, oid
, 0);
1864 parFmt
.cbSize
= sizeof(parFmt
);
1865 parFmt
.dwMask
= PFM_STARTINDENT
;
1866 parFmt
.dxStartIndent
= MY_INDENT
* 3;
1869 add_text_with_paraformat_to_control(hwnd
, oidInfo
->pwszName
,
1870 lstrlenW(oidInfo
->pwszName
), &parFmt
);
1871 add_unformatted_text_to_control(hwnd
, &nl
, 1);
1881 /* The following list MUST be lexicographically sorted by OID */
1882 static struct OIDToString oidMap
[] = {
1883 /* 1.3.6.1.4.1.311.10.3.1 */
1884 { szOID_KP_CTL_USAGE_SIGNING
, IDS_PURPOSE_CTL_USAGE_SIGNING
},
1885 /* 1.3.6.1.4.1.311.10.3.4 */
1886 { szOID_KP_EFS
, IDS_PURPOSE_EFS
},
1887 /* 1.3.6.1.4.1.311.10.3.4.1 */
1888 { szOID_EFS_RECOVERY
, IDS_PURPOSE_EFS_RECOVERY
},
1889 /* 1.3.6.1.4.1.311.10.3.5 */
1890 { szOID_WHQL_CRYPTO
, IDS_PURPOSE_WHQL
},
1891 /* 1.3.6.1.4.1.311.10.3.6 */
1892 { szOID_NT5_CRYPTO
, IDS_PURPOSE_NT5
},
1893 /* 1.3.6.1.4.1.311.10.3.7 */
1894 { szOID_OEM_WHQL_CRYPTO
, IDS_PURPOSE_OEM_WHQL
},
1895 /* 1.3.6.1.4.1.311.10.3.8 */
1896 { szOID_EMBEDDED_NT_CRYPTO
, IDS_PURPOSE_EMBEDDED_NT
},
1897 /* 1.3.6.1.4.1.311.10.3.9 */
1898 { szOID_ROOT_LIST_SIGNER
, IDS_PURPOSE_ROOT_LIST_SIGNER
},
1899 /* 1.3.6.1.4.1.311.10.3.10 */
1900 { szOID_KP_QUALIFIED_SUBORDINATION
, IDS_PURPOSE_QUALIFIED_SUBORDINATION
},
1901 /* 1.3.6.1.4.1.311.10.3.11 */
1902 { szOID_KP_KEY_RECOVERY
, IDS_PURPOSE_KEY_RECOVERY
},
1903 /* 1.3.6.1.4.1.311.10.3.12 */
1904 { szOID_KP_DOCUMENT_SIGNING
, IDS_PURPOSE_DOCUMENT_SIGNING
},
1905 /* 1.3.6.1.4.1.311.10.3.13 */
1906 { szOID_KP_LIFETIME_SIGNING
, IDS_PURPOSE_LIFETIME_SIGNING
},
1907 /* 1.3.6.1.4.1.311.10.5.1 */
1908 { szOID_DRM
, IDS_PURPOSE_DRM
},
1909 /* 1.3.6.1.4.1.311.10.6.1 */
1910 { szOID_LICENSES
, IDS_PURPOSE_LICENSES
},
1911 /* 1.3.6.1.4.1.311.10.6.2 */
1912 { szOID_LICENSE_SERVER
, IDS_PURPOSE_LICENSE_SERVER
},
1913 /* 1.3.6.1.4.1.311.20.2.1 */
1914 { szOID_ENROLLMENT_AGENT
, IDS_PURPOSE_ENROLLMENT_AGENT
},
1915 /* 1.3.6.1.4.1.311.20.2.2 */
1916 { szOID_KP_SMARTCARD_LOGON
, IDS_PURPOSE_SMARTCARD_LOGON
},
1917 /* 1.3.6.1.4.1.311.21.5 */
1918 { szOID_KP_CA_EXCHANGE
, IDS_PURPOSE_CA_EXCHANGE
},
1919 /* 1.3.6.1.4.1.311.21.6 */
1920 { szOID_KP_KEY_RECOVERY_AGENT
, IDS_PURPOSE_KEY_RECOVERY_AGENT
},
1921 /* 1.3.6.1.4.1.311.21.19 */
1922 { szOID_DS_EMAIL_REPLICATION
, IDS_PURPOSE_DS_EMAIL_REPLICATION
},
1923 /* 1.3.6.1.5.5.7.3.1 */
1924 { szOID_PKIX_KP_SERVER_AUTH
, IDS_PURPOSE_SERVER_AUTH
},
1925 /* 1.3.6.1.5.5.7.3.2 */
1926 { szOID_PKIX_KP_CLIENT_AUTH
, IDS_PURPOSE_CLIENT_AUTH
},
1927 /* 1.3.6.1.5.5.7.3.3 */
1928 { szOID_PKIX_KP_CODE_SIGNING
, IDS_PURPOSE_CODE_SIGNING
},
1929 /* 1.3.6.1.5.5.7.3.4 */
1930 { szOID_PKIX_KP_EMAIL_PROTECTION
, IDS_PURPOSE_EMAIL_PROTECTION
},
1931 /* 1.3.6.1.5.5.7.3.5 */
1932 { szOID_PKIX_KP_IPSEC_END_SYSTEM
, IDS_PURPOSE_IPSEC
},
1933 /* 1.3.6.1.5.5.7.3.6 */
1934 { szOID_PKIX_KP_IPSEC_TUNNEL
, IDS_PURPOSE_IPSEC
},
1935 /* 1.3.6.1.5.5.7.3.7 */
1936 { szOID_PKIX_KP_IPSEC_USER
, IDS_PURPOSE_IPSEC
},
1937 /* 1.3.6.1.5.5.7.3.8 */
1938 { szOID_PKIX_KP_TIMESTAMP_SIGNING
, IDS_PURPOSE_TIMESTAMP_SIGNING
},
1941 static struct OIDToString
*findSupportedOID(LPCSTR oid
)
1943 int indexHigh
= ARRAY_SIZE(oidMap
) - 1, indexLow
= 0;
1945 while (indexLow
<= indexHigh
)
1947 int cmp
, i
= (indexLow
+ indexHigh
) / 2;
1948 if (!(cmp
= strcmp(oid
, oidMap
[i
].oid
)))
1958 static void add_local_oid_text_to_control(HWND text
, LPCSTR oid
)
1960 struct OIDToString
*entry
;
1964 parFmt
.cbSize
= sizeof(parFmt
);
1965 parFmt
.dwMask
= PFM_STARTINDENT
;
1966 parFmt
.dxStartIndent
= MY_INDENT
* 3;
1967 if ((entry
= findSupportedOID(oid
)))
1969 WCHAR
*str
, *linebreak
, *ptr
;
1970 BOOL multiline
= FALSE
;
1973 len
= LoadStringW(hInstance
, entry
->id
, (LPWSTR
)&str
, 0);
1976 if ((linebreak
= wmemchr(ptr
, '\n', len
)))
1978 WCHAR copy
[MAX_STRING_LEN
];
1981 /* The source string contains a newline, which the richedit
1982 * control won't find since it's interpreted as a paragraph
1983 * break. Therefore copy up to the newline. lstrcpynW always
1984 * NULL-terminates, so pass one more than the length of the
1985 * source line so the copy includes the entire line and the
1988 lstrcpynW(copy
, ptr
, linebreak
- ptr
+ 1);
1989 add_text_with_paraformat_to_control(text
, copy
,
1990 linebreak
- ptr
, &parFmt
);
1991 ptr
= linebreak
+ 1;
1992 add_unformatted_text_to_control(text
, &nl
, 1);
1994 else if (multiline
&& *ptr
)
1996 /* Add the last line */
1997 add_text_with_paraformat_to_control(text
, ptr
,
1998 len
- (ptr
- str
), &parFmt
);
1999 add_unformatted_text_to_control(text
, &nl
, 1);
2001 } while (linebreak
);
2004 add_text_with_paraformat_to_control(text
, str
, len
, &parFmt
);
2005 add_unformatted_text_to_control(text
, &nl
, 1);
2010 WCHAR
*oidW
= malloc((strlen(oid
) + 1) * sizeof(WCHAR
));
2017 for (src
= oid
, dst
= oidW
; *src
; src
++, dst
++)
2020 add_text_with_paraformat_to_control(text
, oidW
, lstrlenW(oidW
),
2022 add_unformatted_text_to_control(text
, &nl
, 1);
2028 static void display_app_usages(HWND text
, PCCERT_CONTEXT cert
,
2029 BOOL
*anyUsageAdded
)
2031 static char any_app_policy
[] = szOID_ANY_APPLICATION_POLICY
;
2033 CHARFORMATW charFmt
;
2034 PCERT_EXTENSION policyExt
;
2035 if (!*anyUsageAdded
)
2039 parFmt
.cbSize
= sizeof(parFmt
);
2040 parFmt
.dwMask
= PFM_STARTINDENT
;
2041 parFmt
.dxStartIndent
= MY_INDENT
;
2042 add_string_resource_with_paraformat_to_control(text
,
2043 IDS_CERT_INFO_PURPOSES
, &parFmt
);
2044 add_unformatted_text_to_control(text
, &nl
, 1);
2045 *anyUsageAdded
= TRUE
;
2047 memset(&charFmt
, 0, sizeof(charFmt
));
2048 charFmt
.cbSize
= sizeof(charFmt
);
2049 charFmt
.dwMask
= CFM_BOLD
;
2050 charFmt
.dwEffects
= 0;
2051 SendMessageW(text
, EM_SETCHARFORMAT
, SCF_SELECTION
, (LPARAM
)&charFmt
);
2052 if ((policyExt
= CertFindExtension(szOID_APPLICATION_CERT_POLICIES
,
2053 cert
->pCertInfo
->cExtension
, cert
->pCertInfo
->rgExtension
)))
2055 CERT_POLICIES_INFO
*policies
;
2058 if (CryptDecodeObjectEx(X509_ASN_ENCODING
, X509_CERT_POLICIES
,
2059 policyExt
->Value
.pbData
, policyExt
->Value
.cbData
,
2060 CRYPT_DECODE_ALLOC_FLAG
, NULL
, &policies
, &size
))
2064 for (i
= 0; i
< policies
->cPolicyInfo
; i
++)
2068 for (j
= 0; j
< policies
->rgPolicyInfo
[i
].cPolicyQualifier
; j
++)
2069 add_local_oid_text_to_control(text
,
2070 policies
->rgPolicyInfo
[i
].rgPolicyQualifier
[j
].
2071 pszPolicyQualifierId
);
2073 LocalFree(policies
);
2077 add_oid_text_to_control(text
, any_app_policy
);
2080 static BOOL
display_cert_usages(HWND text
, PCCERT_CONTEXT cert
,
2081 BOOL
*anyUsageAdded
)
2085 BOOL badUsages
= FALSE
;
2087 if (CertGetEnhancedKeyUsage(cert
, 0, NULL
, &size
))
2089 CHARFORMATW charFmt
;
2090 static char any_cert_policy
[] = szOID_ANY_CERT_POLICY
;
2091 CERT_ENHKEY_USAGE
*usage
= malloc(size
);
2095 if (CertGetEnhancedKeyUsage(cert
, 0, usage
, &size
))
2099 if (!*anyUsageAdded
)
2103 parFmt
.cbSize
= sizeof(parFmt
);
2104 parFmt
.dwMask
= PFM_STARTINDENT
;
2105 parFmt
.dxStartIndent
= MY_INDENT
;
2106 add_string_resource_with_paraformat_to_control(text
,
2107 IDS_CERT_INFO_PURPOSES
, &parFmt
);
2108 add_unformatted_text_to_control(text
, &nl
, 1);
2109 *anyUsageAdded
= TRUE
;
2111 memset(&charFmt
, 0, sizeof(charFmt
));
2112 charFmt
.cbSize
= sizeof(charFmt
);
2113 charFmt
.dwMask
= CFM_BOLD
;
2114 charFmt
.dwEffects
= 0;
2115 SendMessageW(text
, EM_SETCHARFORMAT
, SCF_SELECTION
,
2117 if (!usage
->cUsageIdentifier
)
2118 add_oid_text_to_control(text
, any_cert_policy
);
2120 for (i
= 0; i
< usage
->cUsageIdentifier
; i
++)
2121 add_local_oid_text_to_control(text
,
2122 usage
->rgpszUsageIdentifier
[i
]);
2136 static void set_policy_text(HWND text
,
2137 PCCRYPTUI_VIEWCERTIFICATE_STRUCTW pCertViewInfo
)
2139 BOOL includeCertUsages
= FALSE
, includeAppUsages
= FALSE
;
2140 BOOL badUsages
= FALSE
, anyUsageAdded
= FALSE
;
2142 if (pCertViewInfo
->cPurposes
)
2146 for (i
= 0; i
< pCertViewInfo
->cPurposes
; i
++)
2148 if (!strcmp(pCertViewInfo
->rgszPurposes
[i
], szOID_ANY_CERT_POLICY
))
2149 includeCertUsages
= TRUE
;
2150 else if (!strcmp(pCertViewInfo
->rgszPurposes
[i
],
2151 szOID_ANY_APPLICATION_POLICY
))
2152 includeAppUsages
= TRUE
;
2158 includeAppUsages
= includeCertUsages
= TRUE
;
2159 if (includeAppUsages
)
2160 display_app_usages(text
, pCertViewInfo
->pCertContext
, &anyUsageAdded
);
2161 if (includeCertUsages
)
2162 badUsages
= display_cert_usages(text
, pCertViewInfo
->pCertContext
,
2168 parFmt
.cbSize
= sizeof(parFmt
);
2169 parFmt
.dwMask
= PFM_STARTINDENT
;
2170 parFmt
.dxStartIndent
= MY_INDENT
;
2171 add_string_resource_with_paraformat_to_control(text
,
2172 IDS_CERT_INFO_BAD_PURPOSES
, &parFmt
);
2176 static CRYPT_OBJID_BLOB
*find_policy_qualifier(CERT_POLICIES_INFO
*policies
,
2179 CRYPT_OBJID_BLOB
*ret
= NULL
;
2182 for (i
= 0; !ret
&& i
< policies
->cPolicyInfo
; i
++)
2186 for (j
= 0; !ret
&& j
< policies
->rgPolicyInfo
[i
].cPolicyQualifier
; j
++)
2187 if (!strcmp(policies
->rgPolicyInfo
[i
].rgPolicyQualifier
[j
].
2188 pszPolicyQualifierId
, policyOid
))
2189 ret
= &policies
->rgPolicyInfo
[i
].rgPolicyQualifier
[j
].
2195 static WCHAR
*get_cps_str_from_qualifier(const CRYPT_OBJID_BLOB
*qualifier
)
2197 LPWSTR qualifierStr
= NULL
;
2198 CERT_NAME_VALUE
*qualifierValue
;
2201 if (CryptDecodeObjectEx(X509_ASN_ENCODING
, X509_NAME_VALUE
,
2202 qualifier
->pbData
, qualifier
->cbData
, CRYPT_DECODE_ALLOC_FLAG
, NULL
,
2203 &qualifierValue
, &size
))
2205 size
= CertRDNValueToStrW(qualifierValue
->dwValueType
,
2206 &qualifierValue
->Value
, NULL
, 0);
2207 qualifierStr
= malloc(size
* sizeof(WCHAR
));
2209 CertRDNValueToStrW(qualifierValue
->dwValueType
,
2210 &qualifierValue
->Value
, qualifierStr
, size
);
2211 LocalFree(qualifierValue
);
2213 return qualifierStr
;
2216 static WCHAR
*get_user_notice_from_qualifier(const CRYPT_OBJID_BLOB
*qualifier
)
2219 CERT_POLICY_QUALIFIER_USER_NOTICE
*qualifierValue
;
2222 if (CryptDecodeObjectEx(X509_ASN_ENCODING
,
2223 X509_PKIX_POLICY_QUALIFIER_USERNOTICE
,
2224 qualifier
->pbData
, qualifier
->cbData
, CRYPT_DECODE_ALLOC_FLAG
, NULL
,
2225 &qualifierValue
, &size
))
2227 str
= wcsdup(qualifierValue
->pszDisplayText
);
2228 LocalFree(qualifierValue
);
2233 struct IssuerStatement
2239 static void set_issuer_statement(HWND hwnd
,
2240 PCCRYPTUI_VIEWCERTIFICATE_STRUCTW pCertViewInfo
)
2242 PCERT_EXTENSION policyExt
;
2244 if (!(pCertViewInfo
->dwFlags
& CRYPTUI_DISABLE_ISSUERSTATEMENT
) &&
2245 (policyExt
= CertFindExtension(szOID_CERT_POLICIES
,
2246 pCertViewInfo
->pCertContext
->pCertInfo
->cExtension
,
2247 pCertViewInfo
->pCertContext
->pCertInfo
->rgExtension
)))
2249 CERT_POLICIES_INFO
*policies
;
2252 if (CryptDecodeObjectEx(X509_ASN_ENCODING
, policyExt
->pszObjId
,
2253 policyExt
->Value
.pbData
, policyExt
->Value
.cbData
,
2254 CRYPT_DECODE_ALLOC_FLAG
, NULL
, &policies
, &size
))
2256 CRYPT_OBJID_BLOB
*qualifier
;
2257 LPWSTR cps
= NULL
, userNotice
= NULL
;
2259 if ((qualifier
= find_policy_qualifier(policies
,
2260 szOID_PKIX_POLICY_QUALIFIER_CPS
)))
2261 cps
= get_cps_str_from_qualifier(qualifier
);
2262 if ((qualifier
= find_policy_qualifier(policies
,
2263 szOID_PKIX_POLICY_QUALIFIER_USERNOTICE
)))
2264 userNotice
= get_user_notice_from_qualifier(qualifier
);
2265 if (cps
|| userNotice
)
2267 struct IssuerStatement
*issuerStatement
= malloc(sizeof(struct IssuerStatement
));
2269 if (issuerStatement
)
2271 issuerStatement
->cps
= cps
;
2272 issuerStatement
->userNotice
= userNotice
;
2273 EnableWindow(GetDlgItem(hwnd
, IDC_ISSUERSTATEMENT
), TRUE
);
2274 SetWindowLongPtrW(hwnd
, DWLP_USER
,
2275 (ULONG_PTR
)issuerStatement
);
2278 LocalFree(policies
);
2283 static void set_cert_info(HWND hwnd
,
2284 PCCRYPTUI_VIEWCERTIFICATE_STRUCTW pCertViewInfo
)
2286 CHARFORMATW charFmt
;
2288 HWND icon
= GetDlgItem(hwnd
, IDC_CERTIFICATE_ICON
);
2289 HWND text
= GetDlgItem(hwnd
, IDC_CERTIFICATE_INFO
);
2290 CRYPT_PROVIDER_SGNR
*provSigner
= WTHelperGetProvSignerFromChain(
2291 (CRYPT_PROVIDER_DATA
*)pCertViewInfo
->pCryptProviderData
,
2292 pCertViewInfo
->idxSigner
, pCertViewInfo
->fCounterSigner
,
2293 pCertViewInfo
->idxCounterSigner
);
2294 CRYPT_PROVIDER_CERT
*root
=
2295 &provSigner
->pasCertChain
[provSigner
->csCertChain
- 1];
2297 if (!provSigner
->pChainContext
||
2298 (provSigner
->pChainContext
->TrustStatus
.dwErrorStatus
&
2299 CERT_TRUST_IS_PARTIAL_CHAIN
))
2300 add_icon_to_control(icon
, IDB_CERT_WARNING
);
2301 else if (!root
->fTrustedRoot
)
2302 add_icon_to_control(icon
, IDB_CERT_ERROR
);
2304 add_icon_to_control(icon
, IDB_CERT
);
2306 memset(&charFmt
, 0, sizeof(charFmt
));
2307 charFmt
.cbSize
= sizeof(charFmt
);
2308 charFmt
.dwMask
= CFM_BOLD
;
2309 charFmt
.dwEffects
= CFE_BOLD
;
2310 SendMessageW(text
, EM_SETCHARFORMAT
, SCF_SELECTION
, (LPARAM
)&charFmt
);
2311 /* FIXME: vertically center text */
2312 parFmt
.cbSize
= sizeof(parFmt
);
2313 parFmt
.dwMask
= PFM_STARTINDENT
;
2314 parFmt
.dxStartIndent
= MY_INDENT
;
2315 add_string_resource_with_paraformat_to_control(text
,
2316 IDS_CERTIFICATEINFORMATION
, &parFmt
);
2318 text
= GetDlgItem(hwnd
, IDC_CERTIFICATE_STATUS
);
2319 SendMessageW(text
, EM_SETCHARFORMAT
, SCF_SELECTION
, (LPARAM
)&charFmt
);
2320 if (provSigner
->dwError
== TRUST_E_CERT_SIGNATURE
)
2321 add_string_resource_with_paraformat_to_control(text
,
2322 IDS_CERT_INFO_BAD_SIG
, &parFmt
);
2323 else if (!provSigner
->pChainContext
||
2324 (provSigner
->pChainContext
->TrustStatus
.dwErrorStatus
&
2325 CERT_TRUST_IS_PARTIAL_CHAIN
))
2326 add_string_resource_with_paraformat_to_control(text
,
2327 IDS_CERT_INFO_PARTIAL_CHAIN
, &parFmt
);
2328 else if (!root
->fTrustedRoot
)
2330 if (provSigner
->csCertChain
== 1 && root
->fSelfSigned
)
2331 add_string_resource_with_paraformat_to_control(text
,
2332 IDS_CERT_INFO_UNTRUSTED_CA
, &parFmt
);
2334 add_string_resource_with_paraformat_to_control(text
,
2335 IDS_CERT_INFO_UNTRUSTED_ROOT
, &parFmt
);
2339 set_policy_text(text
, pCertViewInfo
);
2340 set_issuer_statement(hwnd
, pCertViewInfo
);
2344 static void set_cert_name_string(HWND hwnd
, PCCERT_CONTEXT cert
,
2345 DWORD nameFlags
, int heading
)
2348 HWND text
= GetDlgItem(hwnd
, IDC_CERTIFICATE_NAMES
);
2349 CHARFORMATW charFmt
;
2352 memset(&charFmt
, 0, sizeof(charFmt
));
2353 charFmt
.cbSize
= sizeof(charFmt
);
2354 charFmt
.dwMask
= CFM_BOLD
;
2355 charFmt
.dwEffects
= CFE_BOLD
;
2356 SendMessageW(text
, EM_SETCHARFORMAT
, SCF_SELECTION
, (LPARAM
)&charFmt
);
2357 parFmt
.cbSize
= sizeof(parFmt
);
2358 parFmt
.dwMask
= PFM_STARTINDENT
;
2359 parFmt
.dxStartIndent
= MY_INDENT
* 3;
2360 add_string_resource_with_paraformat_to_control(text
, heading
, &parFmt
);
2361 charFmt
.dwEffects
= 0;
2362 SendMessageW(text
, EM_SETCHARFORMAT
, SCF_SELECTION
, (LPARAM
)&charFmt
);
2363 add_cert_string_to_control(text
, cert
, CERT_NAME_SIMPLE_DISPLAY_TYPE
,
2365 add_unformatted_text_to_control(text
, &nl
, 1);
2366 add_unformatted_text_to_control(text
, &nl
, 1);
2367 add_unformatted_text_to_control(text
, &nl
, 1);
2371 static void add_date_string_to_control(HWND hwnd
, const FILETIME
*fileTime
)
2373 WCHAR dateFmt
[80]; /* sufficient for all versions of LOCALE_SSHORTDATE */
2377 GetLocaleInfoW(LOCALE_SYSTEM_DEFAULT
, LOCALE_SSHORTDATE
, dateFmt
, ARRAY_SIZE(dateFmt
));
2378 FileTimeToSystemTime(fileTime
, &sysTime
);
2379 GetDateFormatW(LOCALE_SYSTEM_DEFAULT
, 0, &sysTime
, dateFmt
, date
, ARRAY_SIZE(date
));
2380 add_unformatted_text_to_control(hwnd
, date
, lstrlenW(date
));
2383 static void set_cert_validity_period(HWND hwnd
, PCCERT_CONTEXT cert
)
2386 HWND text
= GetDlgItem(hwnd
, IDC_CERTIFICATE_NAMES
);
2387 CHARFORMATW charFmt
;
2390 memset(&charFmt
, 0, sizeof(charFmt
));
2391 charFmt
.cbSize
= sizeof(charFmt
);
2392 charFmt
.dwMask
= CFM_BOLD
;
2393 charFmt
.dwEffects
= CFE_BOLD
;
2394 SendMessageW(text
, EM_SETCHARFORMAT
, SCF_SELECTION
, (LPARAM
)&charFmt
);
2395 parFmt
.cbSize
= sizeof(parFmt
);
2396 parFmt
.dwMask
= PFM_STARTINDENT
;
2397 parFmt
.dxStartIndent
= MY_INDENT
* 3;
2398 add_string_resource_with_paraformat_to_control(text
, IDS_VALID_FROM
,
2400 charFmt
.dwEffects
= 0;
2401 SendMessageW(text
, EM_SETCHARFORMAT
, SCF_SELECTION
, (LPARAM
)&charFmt
);
2402 add_date_string_to_control(text
, &cert
->pCertInfo
->NotBefore
);
2403 charFmt
.dwEffects
= CFE_BOLD
;
2404 SendMessageW(text
, EM_SETCHARFORMAT
, SCF_SELECTION
, (LPARAM
)&charFmt
);
2405 add_string_resource_to_control(text
, IDS_VALID_TO
);
2406 charFmt
.dwEffects
= 0;
2407 SendMessageW(text
, EM_SETCHARFORMAT
, SCF_SELECTION
, (LPARAM
)&charFmt
);
2408 add_date_string_to_control(text
, &cert
->pCertInfo
->NotAfter
);
2409 add_unformatted_text_to_control(text
, &nl
, 1);
2412 static void set_general_info(HWND hwnd
,
2413 PCCRYPTUI_VIEWCERTIFICATE_STRUCTW pCertViewInfo
)
2415 set_cert_info(hwnd
, pCertViewInfo
);
2416 set_cert_name_string(hwnd
, pCertViewInfo
->pCertContext
, 0,
2417 IDS_SUBJECT_HEADING
);
2418 set_cert_name_string(hwnd
, pCertViewInfo
->pCertContext
,
2419 CERT_NAME_ISSUER_FLAG
, IDS_ISSUER_HEADING
);
2420 set_cert_validity_period(hwnd
, pCertViewInfo
->pCertContext
);
2423 static INT_PTR CALLBACK
user_notice_dlg_proc(HWND hwnd
, UINT msg
, WPARAM wp
,
2428 struct IssuerStatement
*issuerStatement
;
2433 text
= GetDlgItem(hwnd
, IDC_USERNOTICE
);
2434 issuerStatement
= (struct IssuerStatement
*)lp
;
2435 add_unformatted_text_to_control(text
, issuerStatement
->userNotice
,
2436 lstrlenW(issuerStatement
->userNotice
));
2437 if (issuerStatement
->cps
)
2438 SetWindowLongPtrW(hwnd
, DWLP_USER
, (LPARAM
)issuerStatement
->cps
);
2440 EnableWindow(GetDlgItem(hwnd
, IDC_CPS
), FALSE
);
2446 EndDialog(hwnd
, IDOK
);
2451 IBindCtx
*bctx
= NULL
;
2454 CreateBindCtx(0, &bctx
);
2455 cps
= (LPWSTR
)GetWindowLongPtrW(hwnd
, DWLP_USER
);
2456 HlinkSimpleNavigateToString(cps
, NULL
, NULL
, NULL
, bctx
, NULL
,
2457 HLNF_OPENINNEWWINDOW
, 0);
2458 IBindCtx_Release(bctx
);
2466 static void show_user_notice(HWND hwnd
, struct IssuerStatement
*issuerStatement
)
2468 DialogBoxParamW(hInstance
, MAKEINTRESOURCEW(IDD_USERNOTICE
), hwnd
,
2469 user_notice_dlg_proc
, (LPARAM
)issuerStatement
);
2472 static INT_PTR CALLBACK
general_dlg_proc(HWND hwnd
, UINT msg
, WPARAM wp
,
2475 PROPSHEETPAGEW
*page
;
2476 PCCRYPTUI_VIEWCERTIFICATE_STRUCTW pCertViewInfo
;
2478 TRACE("(%p, %08x, %08Ix, %08Ix)\n", hwnd
, msg
, wp
, lp
);
2483 page
= (PROPSHEETPAGEW
*)lp
;
2484 pCertViewInfo
= (PCCRYPTUI_VIEWCERTIFICATE_STRUCTW
)page
->lParam
;
2485 if (pCertViewInfo
->dwFlags
& CRYPTUI_DISABLE_ADDTOSTORE
)
2486 ShowWindow(GetDlgItem(hwnd
, IDC_ADDTOSTORE
), FALSE
);
2487 EnableWindow(GetDlgItem(hwnd
, IDC_ISSUERSTATEMENT
), FALSE
);
2488 set_general_info(hwnd
, pCertViewInfo
);
2493 case IDC_ADDTOSTORE
:
2494 CryptUIWizImport(0, hwnd
, NULL
, NULL
, NULL
);
2496 case IDC_ISSUERSTATEMENT
:
2498 struct IssuerStatement
*issuerStatement
=
2499 (struct IssuerStatement
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
2501 if (issuerStatement
)
2503 if (issuerStatement
->userNotice
)
2504 show_user_notice(hwnd
, issuerStatement
);
2505 else if (issuerStatement
->cps
)
2507 IBindCtx
*bctx
= NULL
;
2509 CreateBindCtx(0, &bctx
);
2510 HlinkSimpleNavigateToString(issuerStatement
->cps
, NULL
,
2511 NULL
, NULL
, bctx
, NULL
, HLNF_OPENINNEWWINDOW
, 0);
2512 IBindCtx_Release(bctx
);
2523 static UINT CALLBACK
general_callback_proc(HWND hwnd
, UINT msg
,
2524 PROPSHEETPAGEW
*page
)
2526 struct IssuerStatement
*issuerStatement
;
2532 (struct IssuerStatement
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
2533 if (issuerStatement
)
2535 free(issuerStatement
->cps
);
2536 free(issuerStatement
->userNotice
);
2537 free(issuerStatement
);
2544 static void init_general_page(PCCRYPTUI_VIEWCERTIFICATE_STRUCTW pCertViewInfo
,
2545 PROPSHEETPAGEW
*page
)
2547 memset(page
, 0, sizeof(PROPSHEETPAGEW
));
2548 page
->dwSize
= sizeof(PROPSHEETPAGEW
);
2549 page
->dwFlags
= PSP_USECALLBACK
;
2550 page
->pfnCallback
= general_callback_proc
;
2551 page
->hInstance
= hInstance
;
2552 page
->pszTemplate
= MAKEINTRESOURCEW(IDD_GENERAL
);
2553 page
->pfnDlgProc
= general_dlg_proc
;
2554 page
->lParam
= (LPARAM
)pCertViewInfo
;
2557 typedef WCHAR
* (*field_format_func
)(PCCERT_CONTEXT cert
);
2559 static WCHAR
*field_format_version(PCCERT_CONTEXT cert
)
2561 static const WCHAR fmt
[] = { 'V','%','d',0 };
2562 WCHAR
*buf
= malloc(12 * sizeof(WCHAR
));
2565 swprintf(buf
, 12, fmt
, cert
->pCertInfo
->dwVersion
);
2569 static WCHAR
*format_hex_string(void *pb
, DWORD cb
)
2571 WCHAR
*buf
= malloc((cb
* 3 + 1) * sizeof(WCHAR
));
2575 static const WCHAR fmt
[] = { '%','0','2','x',' ',0 };
2579 for (i
= 0, ptr
= buf
; i
< cb
; i
++, ptr
+= 3)
2580 swprintf(ptr
, 4, fmt
, ((BYTE
*)pb
)[i
]);
2585 static WCHAR
*field_format_serial_number(PCCERT_CONTEXT cert
)
2587 return format_hex_string(cert
->pCertInfo
->SerialNumber
.pbData
,
2588 cert
->pCertInfo
->SerialNumber
.cbData
);
2591 static WCHAR
*field_format_issuer(PCCERT_CONTEXT cert
)
2593 return get_cert_name_string(cert
, CERT_NAME_SIMPLE_DISPLAY_TYPE
,
2594 CERT_NAME_ISSUER_FLAG
);
2597 static WCHAR
*field_format_detailed_cert_name(PCERT_NAME_BLOB name
)
2600 DWORD len
= CertNameToStrW(X509_ASN_ENCODING
, name
,
2601 CERT_X500_NAME_STR
| CERT_NAME_STR_CRLF_FLAG
| CERT_NAME_STR_NO_QUOTING_FLAG
, NULL
, 0);
2605 str
= malloc(len
* sizeof(WCHAR
));
2607 CertNameToStrW(X509_ASN_ENCODING
, name
,
2608 CERT_X500_NAME_STR
| CERT_NAME_STR_CRLF_FLAG
| CERT_NAME_STR_NO_QUOTING_FLAG
, str
, len
);
2613 static WCHAR
*field_format_detailed_issuer(PCCERT_CONTEXT cert
, void *param
)
2615 return field_format_detailed_cert_name(&cert
->pCertInfo
->Issuer
);
2618 static WCHAR
*field_format_subject(PCCERT_CONTEXT cert
)
2620 return get_cert_name_string(cert
, CERT_NAME_SIMPLE_DISPLAY_TYPE
, 0);
2623 static WCHAR
*field_format_detailed_subject(PCCERT_CONTEXT cert
, void *param
)
2625 return field_format_detailed_cert_name(&cert
->pCertInfo
->Subject
);
2628 static WCHAR
*format_long_date(const FILETIME
*fileTime
)
2630 WCHAR dateFmt
[80]; /* long enough for LOCALE_SLONGDATE */
2635 /* FIXME: format isn't quite right, want time too */
2636 GetLocaleInfoW(LOCALE_SYSTEM_DEFAULT
, LOCALE_SLONGDATE
, dateFmt
, ARRAY_SIZE(dateFmt
));
2637 FileTimeToSystemTime(fileTime
, &sysTime
);
2638 len
= GetDateFormatW(LOCALE_SYSTEM_DEFAULT
, 0, &sysTime
, dateFmt
, NULL
, 0);
2641 buf
= malloc(len
* sizeof(WCHAR
));
2643 GetDateFormatW(LOCALE_SYSTEM_DEFAULT
, 0, &sysTime
, dateFmt
, buf
,
2649 static WCHAR
*field_format_from_date(PCCERT_CONTEXT cert
)
2651 return format_long_date(&cert
->pCertInfo
->NotBefore
);
2654 static WCHAR
*field_format_to_date(PCCERT_CONTEXT cert
)
2656 return format_long_date(&cert
->pCertInfo
->NotAfter
);
2659 static WCHAR
*field_format_public_key(PCCERT_CONTEXT cert
)
2661 PCCRYPT_OID_INFO oidInfo
;
2664 oidInfo
= CryptFindOIDInfo(CRYPT_OID_INFO_OID_KEY
,
2665 cert
->pCertInfo
->SubjectPublicKeyInfo
.Algorithm
.pszObjId
, 0);
2668 WCHAR fmt
[MAX_STRING_LEN
];
2670 if (LoadStringW(hInstance
, IDS_FIELD_PUBLIC_KEY_FORMAT
, fmt
, ARRAY_SIZE(fmt
)))
2674 /* Allocate the output buffer. Use the number of bytes in the
2675 * public key as a conservative (high) estimate for the number of
2676 * digits in its output.
2677 * The output is of the form (in English)
2678 * "<public key algorithm> (<public key bit length> bits)".
2679 * Ordinarily having two positional parameters in a string is not a
2680 * good idea, but as this isn't a sentence fragment, it shouldn't
2681 * be word-order dependent.
2683 len
= lstrlenW(fmt
) + lstrlenW(oidInfo
->pwszName
) +
2684 cert
->pCertInfo
->SubjectPublicKeyInfo
.PublicKey
.cbData
* 8;
2685 buf
= malloc(len
* sizeof(*buf
));
2689 args
[0] = (DWORD_PTR
)oidInfo
->pwszName
;
2690 args
[1] = CertGetPublicKeyLength(X509_ASN_ENCODING
,
2691 &cert
->pCertInfo
->SubjectPublicKeyInfo
);
2692 FormatMessageW(FORMAT_MESSAGE_FROM_STRING
|FORMAT_MESSAGE_ARGUMENT_ARRAY
,
2693 fmt
, 0, 0, buf
, len
, (va_list *)args
);
2700 static WCHAR
*field_format_detailed_public_key(PCCERT_CONTEXT cert
, void *param
)
2702 return format_hex_string(
2703 cert
->pCertInfo
->SubjectPublicKeyInfo
.PublicKey
.pbData
,
2704 cert
->pCertInfo
->SubjectPublicKeyInfo
.PublicKey
.cbData
);
2707 struct field_value_data
;
2710 PCCRYPTUI_VIEWCERTIFICATE_STRUCTW pCertViewInfo
;
2711 BOOL
*pfPropertiesChanged
;
2713 struct field_value_data
*fields
;
2716 typedef void (*add_fields_func
)(HWND hwnd
, struct detail_data
*data
);
2718 typedef WCHAR
*(*create_detailed_value_func
)(PCCERT_CONTEXT cert
, void *param
);
2720 struct field_value_data
2722 create_detailed_value_func create
;
2723 LPWSTR detailed_value
;
2727 static void add_field_value_data(struct detail_data
*data
,
2728 create_detailed_value_func create
, void *param
)
2730 data
->fields
= realloc(data
->fields
, (data
->cFields
+ 1) * sizeof(struct field_value_data
));
2733 data
->fields
[data
->cFields
].create
= create
;
2734 data
->fields
[data
->cFields
].detailed_value
= NULL
;
2735 data
->fields
[data
->cFields
].param
= param
;
2740 static void add_field_and_value_to_list(HWND hwnd
, struct detail_data
*data
,
2741 LPWSTR field
, LPWSTR value
, create_detailed_value_func create
, void *param
)
2744 int iItem
= SendMessageW(hwnd
, LVM_GETITEMCOUNT
, 0, 0);
2746 item
.mask
= LVIF_TEXT
| LVIF_PARAM
;
2749 item
.pszText
= field
;
2750 item
.lParam
= (LPARAM
)data
;
2751 SendMessageW(hwnd
, LVM_INSERTITEMW
, 0, (LPARAM
)&item
);
2754 item
.pszText
= value
;
2756 SendMessageW(hwnd
, LVM_SETITEMTEXTW
, iItem
, (LPARAM
)&item
);
2758 add_field_value_data(data
, create
, param
);
2761 static void add_string_id_and_value_to_list(HWND hwnd
, struct detail_data
*data
,
2762 int id
, LPWSTR value
, create_detailed_value_func create
, void *param
)
2764 WCHAR buf
[MAX_STRING_LEN
];
2766 LoadStringW(hInstance
, id
, buf
, ARRAY_SIZE(buf
));
2767 add_field_and_value_to_list(hwnd
, data
, buf
, value
, create
, param
);
2773 field_format_func format
;
2774 create_detailed_value_func create_detailed_value
;
2777 static void add_v1_field(HWND hwnd
, struct detail_data
*data
,
2778 const struct v1_field
*field
)
2780 WCHAR
*val
= field
->format(data
->pCertViewInfo
->pCertContext
);
2784 add_string_id_and_value_to_list(hwnd
, data
, field
->id
, val
,
2785 field
->create_detailed_value
, NULL
);
2790 static const struct v1_field v1_fields
[] = {
2791 { IDS_FIELD_VERSION
, field_format_version
, NULL
},
2792 { IDS_FIELD_SERIAL_NUMBER
, field_format_serial_number
, NULL
},
2793 { IDS_FIELD_ISSUER
, field_format_issuer
, field_format_detailed_issuer
},
2794 { IDS_FIELD_VALID_FROM
, field_format_from_date
, NULL
},
2795 { IDS_FIELD_VALID_TO
, field_format_to_date
, NULL
},
2796 { IDS_FIELD_SUBJECT
, field_format_subject
, field_format_detailed_subject
},
2797 { IDS_FIELD_PUBLIC_KEY
, field_format_public_key
,
2798 field_format_detailed_public_key
}
2801 static void add_v1_fields(HWND hwnd
, struct detail_data
*data
)
2804 PCCERT_CONTEXT cert
= data
->pCertViewInfo
->pCertContext
;
2806 /* The last item in v1_fields is the public key, which is not in the loop
2807 * because it's a special case.
2809 for (i
= 0; i
< ARRAY_SIZE(v1_fields
) - 1; i
++)
2810 add_v1_field(hwnd
, data
, &v1_fields
[i
]);
2811 if (cert
->pCertInfo
->SubjectPublicKeyInfo
.PublicKey
.cbData
)
2812 add_v1_field(hwnd
, data
, &v1_fields
[i
]);
2815 static WCHAR
*crypt_format_extension(const CERT_EXTENSION
*ext
, DWORD formatStrType
)
2820 if (CryptFormatObject(X509_ASN_ENCODING
, 0, formatStrType
, NULL
,
2821 ext
->pszObjId
, ext
->Value
.pbData
, ext
->Value
.cbData
, NULL
, &size
))
2824 CryptFormatObject(X509_ASN_ENCODING
, 0, formatStrType
, NULL
,
2825 ext
->pszObjId
, ext
->Value
.pbData
, ext
->Value
.cbData
, str
, &size
);
2830 static WCHAR
*field_format_extension_hex_with_ascii(const CERT_EXTENSION
*ext
)
2834 if (ext
->Value
.cbData
)
2836 /* The output is formatted as:
2837 * <hex bytes> <ascii bytes>\n
2838 * where <hex bytes> is a string of up to 8 bytes, output as %02x,
2839 * and <ascii bytes> is the ASCII equivalent of each byte, or '.' if
2840 * the byte is not printable.
2841 * So, for example, the extension value consisting of the following
2843 * 0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,0x55,0x04,0x03,
2844 * 0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67
2846 * 30 14 31 12 30 10 06 03 0.1.0...
2847 * 55 04 03 13 09 4a 75 61 U....Jua
2848 * 6e 20 4c 61 6e 67 n Lang
2849 * The allocation size therefore requires:
2850 * - 4 characters per character in an 8-byte line
2851 * (2 for the hex format, one for the space, one for the ASCII value)
2852 * - 3 more characters per 8-byte line (two spaces and a newline)
2853 * - 1 character for the terminating nul
2854 * FIXME: should use a fixed-width font for this
2856 DWORD lines
= (ext
->Value
.cbData
+ 7) / 8;
2858 str
= malloc((lines
* 8 * 4 + lines
* 3 + 1) * sizeof(WCHAR
));
2861 static const WCHAR fmt
[] = { '%','0','2','x',' ',0 };
2865 for (i
= 0, ptr
= str
; i
< ext
->Value
.cbData
; i
+= 8)
2867 /* Output as hex bytes first */
2868 for (j
= i
; j
< min(i
+ 8, ext
->Value
.cbData
); j
++, ptr
+= 3)
2869 swprintf(ptr
, 4, fmt
, ext
->Value
.pbData
[j
]);
2870 /* Pad the hex output with spaces for alignment */
2871 if (j
== ext
->Value
.cbData
&& j
% 8)
2873 static const WCHAR pad
[] = { ' ',' ',' ' };
2875 for (; j
% 8; j
++, ptr
+= ARRAY_SIZE(pad
))
2876 memcpy(ptr
, pad
, sizeof(pad
));
2878 /* The last swprintf included a space, so just insert one
2879 * more space between the hex bytes and the ASCII output
2882 /* Output as ASCII bytes */
2883 for (j
= i
; j
< min(i
+ 8, ext
->Value
.cbData
); j
++, ptr
++)
2885 if (iswprint(ext
->Value
.pbData
[j
]) &&
2886 !iswspace(ext
->Value
.pbData
[j
]))
2887 *ptr
= ext
->Value
.pbData
[j
];
2899 static WCHAR
*field_format_detailed_extension(PCCERT_CONTEXT cert
, void *param
)
2901 PCERT_EXTENSION ext
= param
;
2902 LPWSTR str
= crypt_format_extension(ext
,
2903 CRYPT_FORMAT_STR_MULTI_LINE
| CRYPT_FORMAT_STR_NO_HEX
);
2906 str
= field_format_extension_hex_with_ascii(ext
);
2910 static void add_cert_extension_detail(HWND hwnd
, struct detail_data
*data
,
2911 PCERT_EXTENSION ext
)
2913 PCCRYPT_OID_INFO oidInfo
= CryptFindOIDInfo(CRYPT_OID_INFO_OID_KEY
,
2915 LPWSTR val
= crypt_format_extension(ext
, 0);
2918 add_field_and_value_to_list(hwnd
, data
, (LPWSTR
)oidInfo
->pwszName
,
2919 val
, field_format_detailed_extension
, ext
);
2922 DWORD len
= strlen(ext
->pszObjId
);
2923 WCHAR
*oidW
= malloc((len
+ 1) * sizeof(WCHAR
));
2929 for (i
= 0; i
<= len
; i
++)
2930 oidW
[i
] = ext
->pszObjId
[i
];
2931 add_field_and_value_to_list(hwnd
, data
, oidW
, val
,
2932 field_format_detailed_extension
, ext
);
2939 static void add_all_extensions(HWND hwnd
, struct detail_data
*data
)
2942 PCCERT_CONTEXT cert
= data
->pCertViewInfo
->pCertContext
;
2944 for (i
= 0; i
< cert
->pCertInfo
->cExtension
; i
++)
2945 add_cert_extension_detail(hwnd
, data
, &cert
->pCertInfo
->rgExtension
[i
]);
2948 static void add_critical_extensions(HWND hwnd
, struct detail_data
*data
)
2951 PCCERT_CONTEXT cert
= data
->pCertViewInfo
->pCertContext
;
2953 for (i
= 0; i
< cert
->pCertInfo
->cExtension
; i
++)
2954 if (cert
->pCertInfo
->rgExtension
[i
].fCritical
)
2955 add_cert_extension_detail(hwnd
, data
,
2956 &cert
->pCertInfo
->rgExtension
[i
]);
2959 typedef WCHAR
* (*prop_to_value_func
)(void *pb
, DWORD cb
);
2961 struct prop_id_to_string_id
2965 BOOL prop_is_string
;
2966 prop_to_value_func prop_to_value
;
2969 static WCHAR
*format_enhanced_key_usage_value(void *pb
, DWORD cb
)
2973 ext
.pszObjId
= (LPSTR
)X509_ENHANCED_KEY_USAGE
;
2974 ext
.fCritical
= FALSE
;
2975 ext
.Value
.pbData
= pb
;
2976 ext
.Value
.cbData
= cb
;
2977 return crypt_format_extension(&ext
, 0);
2980 /* Logically the access state should also be checked, and IDC_EDITPROPERTIES
2981 * disabled for read-only certificates, but native doesn't appear to do that.
2983 static const struct prop_id_to_string_id prop_id_map
[] = {
2984 { CERT_HASH_PROP_ID
, IDS_PROP_HASH
, FALSE
, format_hex_string
},
2985 { CERT_FRIENDLY_NAME_PROP_ID
, IDS_PROP_FRIENDLY_NAME
, TRUE
, NULL
},
2986 { CERT_DESCRIPTION_PROP_ID
, IDS_PROP_DESCRIPTION
, TRUE
, NULL
},
2987 { CERT_ENHKEY_USAGE_PROP_ID
, IDS_PROP_ENHKEY_USAGE
, FALSE
,
2988 format_enhanced_key_usage_value
},
2991 static void add_properties(HWND hwnd
, struct detail_data
*data
)
2994 PCCERT_CONTEXT cert
= data
->pCertViewInfo
->pCertContext
;
2996 for (i
= 0; i
< ARRAY_SIZE(prop_id_map
); i
++)
3000 if (CertGetCertificateContextProperty(cert
, prop_id_map
[i
].prop
, NULL
,
3006 /* FIXME: MS adds a separate value for the signature hash
3012 if (CertGetCertificateContextProperty(cert
,
3013 prop_id_map
[i
].prop
, pb
, &cb
))
3015 if (prop_id_map
[i
].prop_is_string
)
3018 /* Don't double-free pb */
3022 val
= prop_id_map
[i
].prop_to_value(pb
, cb
);
3026 add_string_id_and_value_to_list(hwnd
, data
, prop_id_map
[i
].id
, val
,
3032 static void add_all_fields(HWND hwnd
, struct detail_data
*data
)
3034 add_v1_fields(hwnd
, data
);
3035 add_all_extensions(hwnd
, data
);
3036 add_properties(hwnd
, data
);
3039 struct selection_list_item
3042 add_fields_func add
;
3045 static const struct selection_list_item listItems
[] = {
3046 { IDS_FIELDS_ALL
, add_all_fields
},
3047 { IDS_FIELDS_V1
, add_v1_fields
},
3048 { IDS_FIELDS_EXTENSIONS
, add_all_extensions
},
3049 { IDS_FIELDS_CRITICAL_EXTENSIONS
, add_critical_extensions
},
3050 { IDS_FIELDS_PROPERTIES
, add_properties
},
3053 static void create_show_list(HWND hwnd
, struct detail_data
*data
)
3055 HWND cb
= GetDlgItem(hwnd
, IDC_DETAIL_SELECT
);
3056 WCHAR buf
[MAX_STRING_LEN
];
3059 for (i
= 0; i
< ARRAY_SIZE(listItems
); i
++)
3063 LoadStringW(hInstance
, listItems
[i
].id
, buf
, ARRAY_SIZE(buf
));
3064 index
= SendMessageW(cb
, CB_INSERTSTRING
, -1, (LPARAM
)buf
);
3065 SendMessageW(cb
, CB_SETITEMDATA
, index
, (LPARAM
)data
);
3067 SendMessageW(cb
, CB_SETCURSEL
, 0, 0);
3070 static void create_listview_columns(HWND hwnd
)
3072 HWND lv
= GetDlgItem(hwnd
, IDC_DETAIL_LIST
);
3074 WCHAR buf
[MAX_STRING_LEN
];
3077 SendMessageW(lv
, LVM_SETEXTENDEDLISTVIEWSTYLE
, 0, LVS_EX_FULLROWSELECT
);
3078 GetWindowRect(lv
, &rc
);
3079 LoadStringW(hInstance
, IDS_FIELD
, buf
, ARRAY_SIZE(buf
));
3080 column
.mask
= LVCF_WIDTH
| LVCF_TEXT
;
3081 column
.cx
= (rc
.right
- rc
.left
) / 2 - 2;
3082 column
.pszText
= buf
;
3083 SendMessageW(lv
, LVM_INSERTCOLUMNW
, 0, (LPARAM
)&column
);
3084 LoadStringW(hInstance
, IDS_VALUE
, buf
, ARRAY_SIZE(buf
));
3085 SendMessageW(lv
, LVM_INSERTCOLUMNW
, 1, (LPARAM
)&column
);
3088 static void set_fields_selection(HWND hwnd
, struct detail_data
*data
, int sel
)
3090 HWND list
= GetDlgItem(hwnd
, IDC_DETAIL_LIST
);
3092 if (sel
>= 0 && sel
< ARRAY_SIZE(listItems
))
3094 SendMessageW(list
, LVM_DELETEALLITEMS
, 0, 0);
3095 listItems
[sel
].add(list
, data
);
3099 static void create_cert_details_list(HWND hwnd
, struct detail_data
*data
)
3101 create_show_list(hwnd
, data
);
3102 create_listview_columns(hwnd
);
3103 set_fields_selection(hwnd
, data
, 0);
3106 static void add_purpose(HWND hwnd
, LPCSTR oid
)
3108 HWND lv
= GetDlgItem(hwnd
, IDC_CERTIFICATE_USAGES
);
3109 CRYPT_OID_INFO
*info
= calloc(1, sizeof(CRYPT_OID_INFO
));
3113 char *oidCopy
= strdup(oid
);
3119 info
->cbSize
= sizeof(CRYPT_OID_INFO
);
3120 info
->pszOID
= oidCopy
;
3121 item
.mask
= LVIF_TEXT
| LVIF_STATE
| LVIF_PARAM
;
3122 item
.state
= INDEXTOSTATEIMAGEMASK(CheckBitmapIndexChecked
);
3123 item
.stateMask
= LVIS_STATEIMAGEMASK
;
3124 item
.iItem
= SendMessageW(lv
, LVM_GETITEMCOUNT
, 0, 0);
3126 item
.lParam
= (LPARAM
)info
;
3127 item
.pszText
= oidCopy
;
3128 SendMessageA(lv
, LVM_INSERTITEMA
, 0, (LPARAM
)&item
);
3135 static BOOL
is_valid_oid(LPCSTR oid
)
3139 if (oid
[0] != '0' && oid
[0] != '1' && oid
[0] != '2')
3141 else if (oid
[1] != '.')
3148 BOOL expectNum
= TRUE
;
3150 for (ptr
= oid
+ 2, ret
= TRUE
; ret
&& *ptr
; ptr
++)
3156 else if (*(ptr
+ 1) == '.')
3163 else if (!(*(ptr
+ 1)))
3173 static BOOL
is_oid_in_list(HWND hwnd
, LPCSTR oid
)
3175 return find_oid_in_list(GetDlgItem(hwnd
, IDC_CERTIFICATE_USAGES
), oid
)
3179 #define MAX_PURPOSE 255
3181 static INT_PTR CALLBACK
add_purpose_dlg_proc(HWND hwnd
, UINT msg
,
3182 WPARAM wp
, LPARAM lp
)
3185 char buf
[MAX_PURPOSE
+ 1];
3190 SendMessageW(GetDlgItem(hwnd
, IDC_NEW_PURPOSE
), EM_SETLIMITTEXT
,
3192 ShowScrollBar(GetDlgItem(hwnd
, IDC_NEW_PURPOSE
), SB_VERT
, FALSE
);
3193 SetWindowLongPtrW(hwnd
, DWLP_USER
, lp
);
3199 if (LOWORD(wp
) == IDC_NEW_PURPOSE
)
3201 /* Show/hide scroll bar on description depending on how much
3204 HWND description
= GetDlgItem(hwnd
, IDC_NEW_PURPOSE
);
3205 int lines
= SendMessageW(description
, EM_GETLINECOUNT
, 0, 0);
3207 ShowScrollBar(description
, SB_VERT
, lines
> 1);
3214 SendMessageA(GetDlgItem(hwnd
, IDC_NEW_PURPOSE
), WM_GETTEXT
, ARRAY_SIZE(buf
),
3218 /* An empty purpose is the same as cancelling */
3219 EndDialog(hwnd
, IDCANCEL
);
3222 else if (!is_valid_oid(buf
))
3224 WCHAR title
[MAX_STRING_LEN
], error
[MAX_STRING_LEN
];
3226 LoadStringW(hInstance
, IDS_CERTIFICATE_PURPOSE_ERROR
, error
, ARRAY_SIZE(error
));
3227 LoadStringW(hInstance
, IDS_CERTIFICATE_PROPERTIES
, title
, ARRAY_SIZE(title
));
3228 MessageBoxW(hwnd
, error
, title
, MB_ICONERROR
| MB_OK
);
3230 else if (is_oid_in_list(
3231 (HWND
)GetWindowLongPtrW(hwnd
, DWLP_USER
), buf
))
3233 WCHAR title
[MAX_STRING_LEN
], error
[MAX_STRING_LEN
];
3235 LoadStringW(hInstance
, IDS_CERTIFICATE_PURPOSE_EXISTS
, error
,
3237 LoadStringW(hInstance
, IDS_CERTIFICATE_PROPERTIES
, title
, ARRAY_SIZE(title
));
3238 MessageBoxW(hwnd
, error
, title
, MB_ICONEXCLAMATION
| MB_OK
);
3242 HWND parent
= (HWND
)GetWindowLongPtrW(hwnd
, DWLP_USER
);
3244 add_purpose(parent
, buf
);
3245 EndDialog(hwnd
, wp
);
3250 EndDialog(hwnd
, wp
);
3261 static WCHAR
*get_cert_property_as_string(PCCERT_CONTEXT cert
, DWORD prop
)
3266 if (CertGetCertificateContextProperty(cert
, prop
, NULL
, &cb
))
3271 if (!CertGetCertificateContextProperty(cert
, prop
, name
, &cb
))
3281 static void redraw_states(HWND list
, BOOL enabled
)
3283 int items
= SendMessageW(list
, LVM_GETITEMCOUNT
, 0, 0), i
;
3285 for (i
= 0; i
< items
; i
++)
3287 BOOL change
= FALSE
;
3290 state
= SendMessageW(list
, LVM_GETITEMSTATE
, i
, LVIS_STATEIMAGEMASK
);
3291 /* This reverses the INDEXTOSTATEIMAGEMASK shift. There doesn't appear
3292 * to be a handy macro for it.
3297 if (state
== CheckBitmapIndexDisabledChecked
)
3299 state
= CheckBitmapIndexChecked
;
3302 if (state
== CheckBitmapIndexDisabledUnchecked
)
3304 state
= CheckBitmapIndexUnchecked
;
3310 if (state
== CheckBitmapIndexChecked
)
3312 state
= CheckBitmapIndexDisabledChecked
;
3315 if (state
== CheckBitmapIndexUnchecked
)
3317 state
= CheckBitmapIndexDisabledUnchecked
;
3325 item
.state
= INDEXTOSTATEIMAGEMASK(state
);
3326 item
.stateMask
= LVIS_STATEIMAGEMASK
;
3327 SendMessageW(list
, LVM_SETITEMSTATE
, i
, (LPARAM
)&item
);
3333 PurposeEnableAll
= 0,
3335 PurposeEnableSelected
3338 static void select_purposes(HWND hwnd
, PurposeSelection selection
)
3340 HWND lv
= GetDlgItem(hwnd
, IDC_CERTIFICATE_USAGES
);
3344 case PurposeEnableAll
:
3345 case PurposeDisableAll
:
3346 EnableWindow(lv
, FALSE
);
3347 redraw_states(lv
, FALSE
);
3348 EnableWindow(GetDlgItem(hwnd
, IDC_ADD_PURPOSE
), FALSE
);
3350 case PurposeEnableSelected
:
3351 EnableWindow(lv
, TRUE
);
3352 redraw_states(lv
, TRUE
);
3353 EnableWindow(GetDlgItem(hwnd
, IDC_ADD_PURPOSE
), TRUE
);
3357 struct edit_cert_data
3359 PCCERT_CONTEXT cert
;
3360 BOOL
*pfPropertiesChanged
;
3361 HIMAGELIST imageList
;
3364 static void show_cert_usages(HWND hwnd
, struct edit_cert_data
*data
)
3366 PCCERT_CONTEXT cert
= data
->cert
;
3367 HWND lv
= GetDlgItem(hwnd
, IDC_CERTIFICATE_USAGES
);
3368 PCERT_ENHKEY_USAGE usage
;
3372 PurposeSelection purposeSelection
= PurposeEnableAll
;
3374 GetWindowRect(lv
, &rc
);
3375 column
.mask
= LVCF_WIDTH
;
3376 column
.cx
= rc
.right
- rc
.left
;
3377 SendMessageW(lv
, LVM_INSERTCOLUMNW
, 0, (LPARAM
)&column
);
3378 SendMessageW(lv
, LVM_SETIMAGELIST
, LVSIL_STATE
, (LPARAM
)data
->imageList
);
3380 /* Get enhanced key usage. Have to check for a property and an extension
3381 * separately, because CertGetEnhancedKeyUsage will succeed and return an
3382 * empty usage if neither is set. Unfortunately an empty usage implies
3383 * no usage is allowed, so we have to distinguish between the two cases.
3385 if (CertGetEnhancedKeyUsage(cert
, CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG
,
3388 usage
= malloc(size
);
3389 if (!CertGetEnhancedKeyUsage(cert
,
3390 CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG
, usage
, &size
))
3395 else if (usage
->cUsageIdentifier
)
3396 purposeSelection
= PurposeEnableSelected
;
3398 purposeSelection
= PurposeDisableAll
;
3400 else if (CertGetEnhancedKeyUsage(cert
, CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG
,
3403 usage
= malloc(size
);
3404 if (!CertGetEnhancedKeyUsage(cert
,
3405 CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG
, usage
, &size
))
3410 else if (usage
->cUsageIdentifier
)
3411 purposeSelection
= PurposeEnableAll
;
3413 purposeSelection
= PurposeDisableAll
;
3417 purposeSelection
= PurposeEnableAll
;
3424 for (i
= 0; i
< usage
->cUsageIdentifier
; i
++)
3426 PCCRYPT_OID_INFO info
= CryptFindOIDInfo(CRYPT_OID_INFO_OID_KEY
,
3427 usage
->rgpszUsageIdentifier
[i
], CRYPT_ENHKEY_USAGE_OID_GROUP_ID
);
3430 add_known_usage(lv
, info
, CheckBitmapIndexDisabledChecked
);
3432 add_purpose(hwnd
, usage
->rgpszUsageIdentifier
[i
]);
3437 add_known_usages_to_list(lv
, CheckBitmapIndexDisabledChecked
);
3438 select_purposes(hwnd
, purposeSelection
);
3439 SendMessageW(GetDlgItem(hwnd
, IDC_ENABLE_ALL_PURPOSES
+ purposeSelection
),
3443 static void set_general_cert_properties(HWND hwnd
, struct edit_cert_data
*data
)
3445 PCCERT_CONTEXT cert
= data
->cert
;
3448 if ((str
= get_cert_property_as_string(cert
, CERT_FRIENDLY_NAME_PROP_ID
)))
3450 SendMessageW(GetDlgItem(hwnd
, IDC_FRIENDLY_NAME
), WM_SETTEXT
, 0,
3454 if ((str
= get_cert_property_as_string(cert
, CERT_DESCRIPTION_PROP_ID
)))
3456 SendMessageW(GetDlgItem(hwnd
, IDC_DESCRIPTION
), WM_SETTEXT
, 0,
3460 show_cert_usages(hwnd
, data
);
3463 static void set_cert_string_property(PCCERT_CONTEXT cert
, DWORD prop
,
3468 CRYPT_DATA_BLOB blob
;
3470 blob
.pbData
= (BYTE
*)str
;
3471 blob
.cbData
= (lstrlenW(str
) + 1) * sizeof(WCHAR
);
3472 CertSetCertificateContextProperty(cert
, prop
, 0, &blob
);
3475 CertSetCertificateContextProperty(cert
, prop
, 0, NULL
);
3478 #define WM_REFRESH_VIEW WM_USER + 0
3480 static BOOL CALLBACK
refresh_propsheet_pages(HWND hwnd
, LPARAM lParam
)
3482 if ((GetClassLongW(hwnd
, GCW_ATOM
) == WC_DIALOG
))
3483 SendMessageW(hwnd
, WM_REFRESH_VIEW
, 0, 0);
3487 #define MAX_FRIENDLY_NAME 40
3488 #define MAX_DESCRIPTION 255
3490 static void apply_general_changes(HWND hwnd
)
3492 WCHAR buf
[MAX_DESCRIPTION
+ 1];
3493 struct edit_cert_data
*data
=
3494 (struct edit_cert_data
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
3496 SendMessageW(GetDlgItem(hwnd
, IDC_FRIENDLY_NAME
), WM_GETTEXT
, ARRAY_SIZE(buf
), (LPARAM
)buf
);
3497 set_cert_string_property(data
->cert
, CERT_FRIENDLY_NAME_PROP_ID
, buf
);
3498 SendMessageW(GetDlgItem(hwnd
, IDC_DESCRIPTION
), WM_GETTEXT
, ARRAY_SIZE(buf
), (LPARAM
)buf
);
3499 set_cert_string_property(data
->cert
, CERT_DESCRIPTION_PROP_ID
, buf
);
3500 if (IsDlgButtonChecked(hwnd
, IDC_ENABLE_ALL_PURPOSES
))
3502 /* Setting a NULL usage removes the enhanced key usage property. */
3503 CertSetEnhancedKeyUsage(data
->cert
, NULL
);
3505 else if (IsDlgButtonChecked(hwnd
, IDC_DISABLE_ALL_PURPOSES
))
3507 CERT_ENHKEY_USAGE usage
= { 0, NULL
};
3509 CertSetEnhancedKeyUsage(data
->cert
, &usage
);
3511 else if (IsDlgButtonChecked(hwnd
, IDC_ENABLE_SELECTED_PURPOSES
))
3513 HWND lv
= GetDlgItem(hwnd
, IDC_CERTIFICATE_USAGES
);
3514 CERT_ENHKEY_USAGE usage
= { 0, NULL
};
3515 int purposes
= SendMessageW(lv
, LVM_GETITEMCOUNT
, 0, 0), i
;
3518 item
.mask
= LVIF_STATE
| LVIF_PARAM
;
3520 item
.stateMask
= LVIS_STATEIMAGEMASK
;
3521 for (i
= 0; i
< purposes
; i
++)
3524 if (SendMessageW(lv
, LVM_GETITEMW
, 0, (LPARAM
)&item
))
3526 int state
= item
.state
>> 12;
3528 if (state
== CheckBitmapIndexChecked
)
3530 CRYPT_OID_INFO
*info
= (CRYPT_OID_INFO
*)item
.lParam
;
3532 usage
.rgpszUsageIdentifier
= realloc(usage
.rgpszUsageIdentifier
,
3533 (usage
.cUsageIdentifier
+ 1) * sizeof(char *));
3534 if (usage
.rgpszUsageIdentifier
)
3535 usage
.rgpszUsageIdentifier
[usage
.cUsageIdentifier
++] =
3536 (LPSTR
)info
->pszOID
;
3540 CertSetEnhancedKeyUsage(data
->cert
, &usage
);
3541 free(usage
.rgpszUsageIdentifier
);
3543 EnumChildWindows(GetParent(GetParent(hwnd
)), refresh_propsheet_pages
, 0);
3544 if (data
->pfPropertiesChanged
)
3545 *data
->pfPropertiesChanged
= TRUE
;
3548 static INT_PTR CALLBACK
cert_properties_general_dlg_proc(HWND hwnd
, UINT msg
,
3549 WPARAM wp
, LPARAM lp
)
3551 PROPSHEETPAGEW
*page
;
3553 TRACE("(%p, %08x, %08Ix, %08Ix)\n", hwnd
, msg
, wp
, lp
);
3559 HWND description
= GetDlgItem(hwnd
, IDC_DESCRIPTION
);
3560 struct detail_data
*detailData
;
3561 struct edit_cert_data
*editData
;
3563 page
= (PROPSHEETPAGEW
*)lp
;
3564 detailData
= (struct detail_data
*)page
->lParam
;
3565 SendMessageW(GetDlgItem(hwnd
, IDC_FRIENDLY_NAME
), EM_SETLIMITTEXT
,
3566 MAX_FRIENDLY_NAME
, 0);
3567 SendMessageW(description
, EM_SETLIMITTEXT
, MAX_DESCRIPTION
, 0);
3568 ShowScrollBar(description
, SB_VERT
, FALSE
);
3569 editData
= malloc(sizeof(struct edit_cert_data
));
3572 editData
->imageList
= ImageList_Create(16, 16,
3573 ILC_COLOR4
| ILC_MASK
, 4, 0);
3574 if (editData
->imageList
)
3577 COLORREF backColor
= RGB(255, 0, 255);
3579 bmp
= LoadBitmapW(hInstance
, MAKEINTRESOURCEW(IDB_CHECKS
));
3580 ImageList_AddMasked(editData
->imageList
, bmp
, backColor
);
3582 ImageList_SetBkColor(editData
->imageList
, CLR_NONE
);
3584 editData
->cert
= detailData
->pCertViewInfo
->pCertContext
;
3585 editData
->pfPropertiesChanged
= detailData
->pfPropertiesChanged
;
3586 SetWindowLongPtrW(hwnd
, DWLP_USER
, (LPARAM
)editData
);
3587 set_general_cert_properties(hwnd
, editData
);
3593 NMHDR
*hdr
= (NMHDR
*)lp
;
3599 nm
= (NMITEMACTIVATE
*)lp
;
3600 toggle_usage(hwnd
, nm
->iItem
);
3601 SendMessageW(GetParent(hwnd
), PSM_CHANGED
, (WPARAM
)hwnd
, 0);
3604 apply_general_changes(hwnd
);
3613 SendMessageW(GetParent(hwnd
), PSM_CHANGED
, (WPARAM
)hwnd
, 0);
3614 if (LOWORD(wp
) == IDC_DESCRIPTION
)
3616 /* Show/hide scroll bar on description depending on how much
3619 HWND description
= GetDlgItem(hwnd
, IDC_DESCRIPTION
);
3620 int lines
= SendMessageW(description
, EM_GETLINECOUNT
, 0, 0);
3622 ShowScrollBar(description
, SB_VERT
, lines
> 1);
3628 case IDC_ADD_PURPOSE
:
3629 if (DialogBoxParamW(hInstance
,
3630 MAKEINTRESOURCEW(IDD_ADD_CERT_PURPOSE
), hwnd
,
3631 add_purpose_dlg_proc
, (LPARAM
)hwnd
) == IDOK
)
3632 SendMessageW(GetParent(hwnd
), PSM_CHANGED
, (WPARAM
)hwnd
, 0);
3634 case IDC_ENABLE_ALL_PURPOSES
:
3635 case IDC_DISABLE_ALL_PURPOSES
:
3636 case IDC_ENABLE_SELECTED_PURPOSES
:
3637 SendMessageW(GetParent(hwnd
), PSM_CHANGED
, (WPARAM
)hwnd
, 0);
3638 select_purposes(hwnd
, LOWORD(wp
) - IDC_ENABLE_ALL_PURPOSES
);
3648 static UINT CALLBACK
cert_properties_general_callback(HWND hwnd
, UINT msg
,
3649 PROPSHEETPAGEW
*page
)
3653 struct edit_cert_data
*data
;
3658 lv
= GetDlgItem(hwnd
, IDC_CERTIFICATE_USAGES
);
3659 cItem
= SendMessageW(lv
, LVM_GETITEMCOUNT
, 0, 0);
3660 for (i
= 0; i
< cItem
; i
++)
3664 item
.mask
= LVIF_PARAM
;
3667 if (SendMessageW(lv
, LVM_GETITEMW
, 0, (LPARAM
)&item
) && item
.lParam
)
3669 PCRYPT_OID_INFO info
= (PCRYPT_OID_INFO
)item
.lParam
;
3671 if (info
->cbSize
== sizeof(CRYPT_OID_INFO
) && !info
->dwGroupId
)
3673 free((char *)info
->pszOID
);
3678 data
= (struct edit_cert_data
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
3681 ImageList_Destroy(data
->imageList
);
3689 static void show_edit_cert_properties_dialog(HWND parent
,
3690 struct detail_data
*data
)
3692 PROPSHEETHEADERW hdr
;
3693 PROPSHEETPAGEW page
; /* FIXME: need to add a cross-certificate page */
3695 TRACE("(%p)\n", data
);
3697 memset(&page
, 0, sizeof(PROPSHEETPAGEW
));
3698 page
.dwSize
= sizeof(page
);
3699 page
.dwFlags
= PSP_USECALLBACK
;
3700 page
.pfnCallback
= cert_properties_general_callback
;
3701 page
.hInstance
= hInstance
;
3702 page
.pszTemplate
= MAKEINTRESOURCEW(IDD_CERT_PROPERTIES_GENERAL
);
3703 page
.pfnDlgProc
= cert_properties_general_dlg_proc
;
3704 page
.lParam
= (LPARAM
)data
;
3706 memset(&hdr
, 0, sizeof(hdr
));
3707 hdr
.dwSize
= sizeof(hdr
);
3708 hdr
.hwndParent
= parent
;
3709 hdr
.dwFlags
= PSH_PROPSHEETPAGE
;
3710 hdr
.hInstance
= hInstance
;
3711 hdr
.pszCaption
= MAKEINTRESOURCEW(IDS_CERTIFICATE_PROPERTIES
);
3714 PropertySheetW(&hdr
);
3717 static void free_detail_fields(struct detail_data
*data
)
3721 for (i
= 0; i
< data
->cFields
; i
++)
3722 free(data
->fields
[i
].detailed_value
);
3724 data
->fields
= NULL
;
3728 static void refresh_details_view(HWND hwnd
)
3730 HWND cb
= GetDlgItem(hwnd
, IDC_DETAIL_SELECT
);
3732 struct detail_data
*data
;
3734 curSel
= SendMessageW(cb
, CB_GETCURSEL
, 0, 0);
3735 /* Actually, any index will do, since they all store the same data value */
3736 data
= (struct detail_data
*)SendMessageW(cb
, CB_GETITEMDATA
, curSel
, 0);
3737 free_detail_fields(data
);
3738 set_fields_selection(hwnd
, data
, curSel
);
3741 static INT_PTR CALLBACK
detail_dlg_proc(HWND hwnd
, UINT msg
, WPARAM wp
,
3744 PROPSHEETPAGEW
*page
;
3745 struct detail_data
*data
;
3747 TRACE("(%p, %08x, %08Ix, %08Ix)\n", hwnd
, msg
, wp
, lp
);
3752 page
= (PROPSHEETPAGEW
*)lp
;
3753 data
= (struct detail_data
*)page
->lParam
;
3754 create_cert_details_list(hwnd
, data
);
3755 if (!(data
->pCertViewInfo
->dwFlags
& CRYPTUI_ENABLE_EDITPROPERTIES
))
3756 EnableWindow(GetDlgItem(hwnd
, IDC_EDITPROPERTIES
), FALSE
);
3757 if (data
->pCertViewInfo
->dwFlags
& CRYPTUI_DISABLE_EXPORT
)
3758 EnableWindow(GetDlgItem(hwnd
, IDC_EXPORT
), FALSE
);
3763 HWND list
= GetDlgItem(hwnd
, IDC_DETAIL_LIST
);
3765 nm
= (NMITEMACTIVATE
*)lp
;
3766 if (nm
->hdr
.hwndFrom
== list
&& nm
->uNewState
& LVN_ITEMACTIVATE
3767 && nm
->hdr
.code
== LVN_ITEMCHANGED
)
3769 data
= (struct detail_data
*)nm
->lParam
;
3770 if (nm
->iItem
>= 0 && data
&& nm
->iItem
< data
->cFields
)
3772 WCHAR buf
[MAX_STRING_LEN
], *val
= NULL
;
3773 HWND valueCtl
= GetDlgItem(hwnd
, IDC_DETAIL_VALUE
);
3775 if (data
->fields
[nm
->iItem
].create
)
3776 val
= data
->fields
[nm
->iItem
].create(
3777 data
->pCertViewInfo
->pCertContext
,
3778 data
->fields
[nm
->iItem
].param
);
3784 item
.cchTextMax
= ARRAY_SIZE(buf
);
3785 item
.mask
= LVIF_TEXT
;
3787 item
.iItem
= nm
->iItem
;
3789 res
= SendMessageW(list
, LVM_GETITEMW
, 0, (LPARAM
)&item
);
3793 /* Select all the text in the control, the next update will
3796 SendMessageW(valueCtl
, EM_SETSEL
, 0, -1);
3797 add_unformatted_text_to_control(valueCtl
, val
,
3798 val
? lstrlenW(val
) : 0);
3810 HWND cb
= GetDlgItem(hwnd
, IDC_DETAIL_SELECT
);
3811 CRYPTUI_WIZ_EXPORT_INFO info
;
3813 data
= (struct detail_data
*)SendMessageW(cb
, CB_GETITEMDATA
, 0, 0);
3814 info
.dwSize
= sizeof(info
);
3815 info
.pwszExportFileName
= NULL
;
3816 info
.dwSubjectChoice
= CRYPTUI_WIZ_EXPORT_CERT_CONTEXT
;
3817 info
.pCertContext
= data
->pCertViewInfo
->pCertContext
;
3819 CryptUIWizExport(0, hwnd
, NULL
, &info
, NULL
);
3822 case IDC_EDITPROPERTIES
:
3824 HWND cb
= GetDlgItem(hwnd
, IDC_DETAIL_SELECT
);
3827 curSel
= SendMessageW(cb
, CB_GETCURSEL
, 0, 0);
3828 /* Actually, any index will do, since they all store the same
3831 data
= (struct detail_data
*)SendMessageW(cb
, CB_GETITEMDATA
,
3833 show_edit_cert_properties_dialog(GetParent(hwnd
), data
);
3836 case ((CBN_SELCHANGE
<< 16) | IDC_DETAIL_SELECT
):
3837 refresh_details_view(hwnd
);
3841 case WM_REFRESH_VIEW
:
3842 refresh_details_view(hwnd
);
3848 static UINT CALLBACK
detail_callback(HWND hwnd
, UINT msg
,
3849 PROPSHEETPAGEW
*page
)
3851 struct detail_data
*data
;
3856 data
= (struct detail_data
*)page
->lParam
;
3857 free_detail_fields(data
);
3864 static BOOL
init_detail_page(PCCRYPTUI_VIEWCERTIFICATE_STRUCTW pCertViewInfo
,
3865 BOOL
*pfPropertiesChanged
, PROPSHEETPAGEW
*page
)
3868 struct detail_data
*data
= malloc(sizeof(struct detail_data
));
3872 data
->pCertViewInfo
= pCertViewInfo
;
3873 data
->pfPropertiesChanged
= pfPropertiesChanged
;
3875 data
->fields
= NULL
;
3876 memset(page
, 0, sizeof(PROPSHEETPAGEW
));
3877 page
->dwSize
= sizeof(PROPSHEETPAGEW
);
3878 page
->dwFlags
= PSP_USECALLBACK
;
3879 page
->pfnCallback
= detail_callback
;
3880 page
->hInstance
= hInstance
;
3881 page
->pszTemplate
= MAKEINTRESOURCEW(IDD_DETAIL
);
3882 page
->pfnDlgProc
= detail_dlg_proc
;
3883 page
->lParam
= (LPARAM
)data
;
3891 struct hierarchy_data
3893 PCCRYPTUI_VIEWCERTIFICATE_STRUCTW pCertViewInfo
;
3894 HIMAGELIST imageList
;
3898 static LPARAM
index_to_lparam(struct hierarchy_data
*data
, DWORD index
)
3900 CRYPT_PROVIDER_SGNR
*provSigner
= WTHelperGetProvSignerFromChain(
3901 (CRYPT_PROVIDER_DATA
*)data
->pCertViewInfo
->pCryptProviderData
,
3902 data
->pCertViewInfo
->idxSigner
, data
->pCertViewInfo
->fCounterSigner
,
3903 data
->pCertViewInfo
->idxCounterSigner
);
3905 /* Takes advantage of the fact that a pointer is 32-bit aligned, and
3906 * therefore always even.
3908 if (index
== provSigner
->csCertChain
- 1)
3909 return (LPARAM
)data
;
3910 return index
<< 1 | 1;
3913 static inline DWORD
lparam_to_index(struct hierarchy_data
*data
, LPARAM lp
)
3915 CRYPT_PROVIDER_SGNR
*provSigner
= WTHelperGetProvSignerFromChain(
3916 (CRYPT_PROVIDER_DATA
*)data
->pCertViewInfo
->pCryptProviderData
,
3917 data
->pCertViewInfo
->idxSigner
, data
->pCertViewInfo
->fCounterSigner
,
3918 data
->pCertViewInfo
->idxCounterSigner
);
3921 return provSigner
->csCertChain
- 1;
3925 static struct hierarchy_data
*get_hierarchy_data_from_tree_item(HWND tree
,
3928 struct hierarchy_data
*data
= NULL
;
3929 HTREEITEM root
= NULL
;
3932 HTREEITEM parent
= (HTREEITEM
)SendMessageW(tree
, TVM_GETNEXTITEM
,
3933 TVGN_PARENT
, (LPARAM
)hItem
);
3943 item
.mask
= TVIF_PARAM
;
3945 SendMessageW(tree
, TVM_GETITEMW
, 0, (LPARAM
)&item
);
3946 data
= (struct hierarchy_data
*)item
.lParam
;
3951 static WCHAR
*get_cert_display_name(PCCERT_CONTEXT cert
)
3953 WCHAR
*name
= get_cert_property_as_string(cert
, CERT_FRIENDLY_NAME_PROP_ID
);
3956 name
= get_cert_name_string(cert
, CERT_NAME_SIMPLE_DISPLAY_TYPE
, 0);
3960 static void show_cert_chain(HWND hwnd
, struct hierarchy_data
*data
)
3962 HWND tree
= GetDlgItem(hwnd
, IDC_CERTPATH
);
3963 CRYPT_PROVIDER_SGNR
*provSigner
= WTHelperGetProvSignerFromChain(
3964 (CRYPT_PROVIDER_DATA
*)data
->pCertViewInfo
->pCryptProviderData
,
3965 data
->pCertViewInfo
->idxSigner
, data
->pCertViewInfo
->fCounterSigner
,
3966 data
->pCertViewInfo
->idxCounterSigner
);
3968 HTREEITEM parent
= NULL
;
3970 SendMessageW(tree
, TVM_SETIMAGELIST
, TVSIL_NORMAL
, (LPARAM
)data
->imageList
);
3971 for (i
= provSigner
->csCertChain
; i
; i
--)
3975 name
= get_cert_display_name(provSigner
->pasCertChain
[i
- 1].pCert
);
3978 TVINSERTSTRUCTW tvis
;
3980 tvis
.hParent
= parent
;
3981 tvis
.hInsertAfter
= TVI_LAST
;
3982 tvis
.item
.mask
= TVIF_TEXT
| TVIF_STATE
| TVIF_IMAGE
|
3983 TVIF_SELECTEDIMAGE
| TVIF_PARAM
;
3984 tvis
.item
.pszText
= name
;
3985 tvis
.item
.state
= TVIS_EXPANDED
;
3986 tvis
.item
.stateMask
= TVIS_EXPANDED
;
3987 if (i
== 1 && (!provSigner
->pChainContext
||
3988 provSigner
->pChainContext
->TrustStatus
.dwErrorStatus
&
3989 CERT_TRUST_IS_PARTIAL_CHAIN
))
3991 /* The root of the chain has a special case: if the chain is
3992 * a partial chain, the icon is a warning icon rather than an
3995 tvis
.item
.iImage
= 2;
3997 else if (provSigner
->pasCertChain
[i
- 1].pChainElement
->TrustStatus
.
3999 tvis
.item
.iImage
= 0;
4001 tvis
.item
.iImage
= 1;
4002 tvis
.item
.iSelectedImage
= tvis
.item
.iImage
;
4003 tvis
.item
.lParam
= index_to_lparam(data
, i
- 1);
4004 parent
= (HTREEITEM
)SendMessageW(tree
, TVM_INSERTITEMW
, 0,
4011 static void set_certificate_status(HWND hwnd
, const CRYPT_PROVIDER_CERT
*cert
)
4013 /* Select all the text in the control, the next update will replace it */
4014 SendMessageW(hwnd
, EM_SETSEL
, 0, -1);
4015 /* Set the highest priority error messages first. */
4016 if (!(cert
->dwConfidence
& CERT_CONFIDENCE_SIG
))
4017 add_string_resource_to_control(hwnd
, IDS_CERTIFICATE_BAD_SIGNATURE
);
4018 else if (!(cert
->dwConfidence
& CERT_CONFIDENCE_TIME
))
4019 add_string_resource_to_control(hwnd
, IDS_CERTIFICATE_BAD_TIME
);
4020 else if (!(cert
->dwConfidence
& CERT_CONFIDENCE_TIMENEST
))
4021 add_string_resource_to_control(hwnd
, IDS_CERTIFICATE_BAD_TIMENEST
);
4022 else if (cert
->dwRevokedReason
)
4023 add_string_resource_to_control(hwnd
, IDS_CERTIFICATE_REVOKED
);
4025 add_string_resource_to_control(hwnd
, IDS_CERTIFICATE_VALID
);
4028 static void set_certificate_status_for_end_cert(HWND hwnd
,
4029 PCCRYPTUI_VIEWCERTIFICATE_STRUCTW pCertViewInfo
)
4031 HWND status
= GetDlgItem(hwnd
, IDC_CERTIFICATESTATUSTEXT
);
4032 CRYPT_PROVIDER_SGNR
*provSigner
= WTHelperGetProvSignerFromChain(
4033 (CRYPT_PROVIDER_DATA
*)pCertViewInfo
->pCryptProviderData
,
4034 pCertViewInfo
->idxSigner
, pCertViewInfo
->fCounterSigner
,
4035 pCertViewInfo
->idxCounterSigner
);
4036 CRYPT_PROVIDER_CERT
*provCert
= WTHelperGetProvCertFromChain(provSigner
,
4037 pCertViewInfo
->idxCert
);
4039 set_certificate_status(status
, provCert
);
4042 static void show_cert_hierarchy(HWND hwnd
, struct hierarchy_data
*data
)
4044 /* Disable view certificate button until a certificate is selected */
4045 EnableWindow(GetDlgItem(hwnd
, IDC_VIEWCERTIFICATE
), FALSE
);
4046 show_cert_chain(hwnd
, data
);
4047 set_certificate_status_for_end_cert(hwnd
, data
->pCertViewInfo
);
4050 static void show_dialog_for_selected_cert(HWND hwnd
)
4052 HWND tree
= GetDlgItem(hwnd
, IDC_CERTPATH
);
4054 struct hierarchy_data
*data
;
4057 memset(&item
, 0, sizeof(item
));
4058 item
.mask
= TVIF_HANDLE
| TVIF_PARAM
;
4059 item
.hItem
= (HTREEITEM
)SendMessageW(tree
, TVM_GETNEXTITEM
, TVGN_CARET
, 0);
4060 SendMessageW(tree
, TVM_GETITEMW
, 0, (LPARAM
)&item
);
4061 data
= get_hierarchy_data_from_tree_item(tree
, item
.hItem
);
4062 selection
= lparam_to_index(data
, item
.lParam
);
4065 CRYPT_PROVIDER_SGNR
*provSigner
;
4066 CRYPTUI_VIEWCERTIFICATE_STRUCTW viewInfo
;
4067 BOOL changed
= FALSE
;
4069 provSigner
= WTHelperGetProvSignerFromChain(
4070 (CRYPT_PROVIDER_DATA
*)data
->pCertViewInfo
->pCryptProviderData
,
4071 data
->pCertViewInfo
->idxSigner
,
4072 data
->pCertViewInfo
->fCounterSigner
,
4073 data
->pCertViewInfo
->idxCounterSigner
);
4074 memset(&viewInfo
, 0, sizeof(viewInfo
));
4075 viewInfo
.dwSize
= sizeof(viewInfo
);
4076 viewInfo
.dwFlags
= data
->pCertViewInfo
->dwFlags
;
4077 viewInfo
.szTitle
= data
->pCertViewInfo
->szTitle
;
4078 viewInfo
.pCertContext
= provSigner
->pasCertChain
[selection
].pCert
;
4079 viewInfo
.cStores
= data
->pCertViewInfo
->cStores
;
4080 viewInfo
.rghStores
= data
->pCertViewInfo
->rghStores
;
4081 viewInfo
.cPropSheetPages
= data
->pCertViewInfo
->cPropSheetPages
;
4082 viewInfo
.rgPropSheetPages
= data
->pCertViewInfo
->rgPropSheetPages
;
4083 viewInfo
.nStartPage
= data
->pCertViewInfo
->nStartPage
;
4084 CryptUIDlgViewCertificateW(&viewInfo
, &changed
);
4087 /* Delete the contents of the tree */
4088 SendMessageW(tree
, TVM_DELETEITEM
, 0, (LPARAM
)TVI_ROOT
);
4089 /* Reinitialize the tree */
4090 show_cert_hierarchy(hwnd
, data
);
4095 static INT_PTR CALLBACK
hierarchy_dlg_proc(HWND hwnd
, UINT msg
, WPARAM wp
,
4098 PROPSHEETPAGEW
*page
;
4099 struct hierarchy_data
*data
;
4101 HWND tree
= GetDlgItem(hwnd
, IDC_CERTPATH
);
4103 TRACE("(%p, %08x, %08Ix, %08Ix)\n", hwnd
, msg
, wp
, lp
);
4108 page
= (PROPSHEETPAGEW
*)lp
;
4109 data
= (struct hierarchy_data
*)page
->lParam
;
4110 show_cert_hierarchy(hwnd
, data
);
4119 case TVN_SELCHANGEDW
:
4121 NMTREEVIEWW
*nm
= (NMTREEVIEWW
*)lp
;
4123 CRYPT_PROVIDER_SGNR
*provSigner
;
4125 data
= get_hierarchy_data_from_tree_item(tree
, nm
->itemNew
.hItem
);
4126 selection
= lparam_to_index(data
, nm
->itemNew
.lParam
);
4127 provSigner
= WTHelperGetProvSignerFromChain(
4128 (CRYPT_PROVIDER_DATA
*)data
->pCertViewInfo
->pCryptProviderData
,
4129 data
->pCertViewInfo
->idxSigner
,
4130 data
->pCertViewInfo
->fCounterSigner
,
4131 data
->pCertViewInfo
->idxCounterSigner
);
4132 EnableWindow(GetDlgItem(hwnd
, IDC_VIEWCERTIFICATE
), selection
!= 0);
4133 set_certificate_status(GetDlgItem(hwnd
, IDC_CERTIFICATESTATUSTEXT
),
4134 &provSigner
->pasCertChain
[selection
]);
4138 show_dialog_for_selected_cert(hwnd
);
4139 SetWindowLongPtrW(hwnd
, DWLP_MSGRESULT
, 1);
4148 case IDC_VIEWCERTIFICATE
:
4149 show_dialog_for_selected_cert(hwnd
);
4153 case WM_REFRESH_VIEW
:
4157 /* Get hierarchy data */
4158 memset(&item
, 0, sizeof(item
));
4159 item
.mask
= TVIF_HANDLE
| TVIF_PARAM
;
4160 item
.hItem
= (HTREEITEM
)SendMessageW(tree
, TVM_GETNEXTITEM
, TVGN_ROOT
,
4162 data
= get_hierarchy_data_from_tree_item(tree
, item
.hItem
);
4163 /* Delete the contents of the tree */
4164 SendMessageW(tree
, TVM_DELETEITEM
, 0, (LPARAM
)TVI_ROOT
);
4165 /* Reinitialize the tree */
4166 show_cert_hierarchy(hwnd
, data
);
4173 static UINT CALLBACK
hierarchy_callback(HWND hwnd
, UINT msg
,
4174 PROPSHEETPAGEW
*page
)
4176 struct hierarchy_data
*data
;
4181 data
= (struct hierarchy_data
*)page
->lParam
;
4182 ImageList_Destroy(data
->imageList
);
4189 static BOOL
init_hierarchy_page(PCCRYPTUI_VIEWCERTIFICATE_STRUCTW pCertViewInfo
,
4190 PROPSHEETPAGEW
*page
)
4192 struct hierarchy_data
*data
= malloc(sizeof(struct hierarchy_data
));
4197 data
->imageList
= ImageList_Create(16, 16, ILC_COLOR4
| ILC_MASK
, 2, 0);
4198 if (data
->imageList
)
4201 COLORREF backColor
= RGB(255, 0, 255);
4203 data
->pCertViewInfo
= pCertViewInfo
;
4204 data
->selectedCert
= 0xffffffff;
4206 bmp
= LoadBitmapW(hInstance
, MAKEINTRESOURCEW(IDB_SMALL_ICONS
));
4207 ImageList_AddMasked(data
->imageList
, bmp
, backColor
);
4209 ImageList_SetBkColor(data
->imageList
, CLR_NONE
);
4211 memset(page
, 0, sizeof(PROPSHEETPAGEW
));
4212 page
->dwSize
= sizeof(PROPSHEETPAGEW
);
4213 page
->dwFlags
= PSP_USECALLBACK
;
4214 page
->hInstance
= hInstance
;
4215 page
->pszTemplate
= MAKEINTRESOURCEW(IDD_HIERARCHY
);
4216 page
->pfnDlgProc
= hierarchy_dlg_proc
;
4217 page
->lParam
= (LPARAM
)data
;
4218 page
->pfnCallback
= hierarchy_callback
;
4227 static int CALLBACK
cert_prop_sheet_proc(HWND hwnd
, UINT msg
, LPARAM lp
)
4231 TRACE("(%p, %08x, %08Ix)\n", hwnd
, msg
, lp
);
4235 case PSCB_INITIALIZED
:
4236 /* Get cancel button's position.. */
4237 GetWindowRect(GetDlgItem(hwnd
, IDCANCEL
), &rc
);
4238 MapWindowPoints( 0, hwnd
, (POINT
*)&rc
, 2 );
4239 /* hide the cancel button.. */
4240 ShowWindow(GetDlgItem(hwnd
, IDCANCEL
), FALSE
);
4241 /* and move the OK button to the cancel button's original position. */
4242 SetWindowPos(GetDlgItem(hwnd
, IDOK
), 0, rc
.left
, rc
.top
, 0, 0,
4243 SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
| SWP_NOREDRAW
);
4249 static BOOL
show_cert_dialog(PCCRYPTUI_VIEWCERTIFICATE_STRUCTW pCertViewInfo
,
4250 CRYPT_PROVIDER_CERT
*provCert
, BOOL
*pfPropertiesChanged
)
4252 static const WCHAR riched
[] = { 'r','i','c','h','e','d','2','0',0 };
4254 PROPSHEETPAGEW
*pages
;
4256 HMODULE lib
= LoadLibraryW(riched
);
4258 nPages
= pCertViewInfo
->cPropSheetPages
+ 1; /* one for the General tab */
4259 if (!(pCertViewInfo
->dwFlags
& CRYPTUI_HIDE_DETAILPAGE
))
4261 if (!(pCertViewInfo
->dwFlags
& CRYPTUI_HIDE_HIERARCHYPAGE
))
4263 pages
= malloc(nPages
* sizeof(PROPSHEETPAGEW
));
4266 PROPSHEETHEADERW hdr
;
4267 CRYPTUI_INITDIALOG_STRUCT
*init
= NULL
;
4270 memset(&hdr
, 0, sizeof(hdr
));
4271 hdr
.dwSize
= sizeof(hdr
);
4272 hdr
.dwFlags
= PSH_NOAPPLYNOW
| PSH_PROPSHEETPAGE
| PSH_USECALLBACK
;
4273 hdr
.hInstance
= hInstance
;
4274 if (pCertViewInfo
->szTitle
)
4275 hdr
.pszCaption
= pCertViewInfo
->szTitle
;
4277 hdr
.pszCaption
= MAKEINTRESOURCEW(IDS_CERTIFICATE
);
4278 init_general_page(pCertViewInfo
, &pages
[hdr
.nPages
++]);
4279 if (!(pCertViewInfo
->dwFlags
& CRYPTUI_HIDE_DETAILPAGE
))
4281 if (init_detail_page(pCertViewInfo
, pfPropertiesChanged
,
4282 &pages
[hdr
.nPages
]))
4285 if (!(pCertViewInfo
->dwFlags
& CRYPTUI_HIDE_HIERARCHYPAGE
))
4287 if (init_hierarchy_page(pCertViewInfo
, &pages
[hdr
.nPages
]))
4290 /* Copy each additional page, and create the init dialog struct for it
4292 if (pCertViewInfo
->cPropSheetPages
)
4294 init
= malloc(pCertViewInfo
->cPropSheetPages
* sizeof(CRYPTUI_INITDIALOG_STRUCT
));
4297 for (i
= 0; i
< pCertViewInfo
->cPropSheetPages
; i
++)
4299 memcpy(&pages
[hdr
.nPages
+ i
],
4300 &pCertViewInfo
->rgPropSheetPages
[i
],
4301 sizeof(PROPSHEETPAGEW
));
4302 init
[i
].lParam
= pCertViewInfo
->rgPropSheetPages
[i
].lParam
;
4303 init
[i
].pCertContext
= pCertViewInfo
->pCertContext
;
4304 pages
[hdr
.nPages
+ i
].lParam
= (LPARAM
)&init
[i
];
4306 if (pCertViewInfo
->nStartPage
& 0x8000)
4308 /* Start page index is relative to the number of default
4311 hdr
.nStartPage
= pCertViewInfo
->nStartPage
+ hdr
.nPages
;
4314 hdr
.nStartPage
= pCertViewInfo
->nStartPage
;
4315 hdr
.nPages
= nPages
;
4319 SetLastError(ERROR_OUTOFMEMORY
);
4323 /* Ignore the relative flag if there aren't any additional pages */
4324 hdr
.nStartPage
= pCertViewInfo
->nStartPage
& 0x7fff;
4332 hdr
.pfnCallback
= cert_prop_sheet_proc
;
4333 l
= PropertySheetW(&hdr
);
4336 SetLastError(ERROR_CANCELLED
);
4344 SetLastError(ERROR_OUTOFMEMORY
);
4349 /***********************************************************************
4350 * CryptUIDlgViewCertificateW (CRYPTUI.@)
4352 BOOL WINAPI
CryptUIDlgViewCertificateW(
4353 PCCRYPTUI_VIEWCERTIFICATE_STRUCTW pCertViewInfo
, BOOL
*pfPropertiesChanged
)
4355 static GUID generic_cert_verify
= WINTRUST_ACTION_GENERIC_CERT_VERIFY
;
4356 CRYPTUI_VIEWCERTIFICATE_STRUCTW viewInfo
;
4358 WINTRUST_CERT_INFO cert
;
4360 CRYPT_PROVIDER_SGNR
*signer
;
4361 CRYPT_PROVIDER_CERT
*provCert
= NULL
;
4363 TRACE("(%p, %p)\n", pCertViewInfo
, pfPropertiesChanged
);
4365 if (pCertViewInfo
->dwSize
!= sizeof(CRYPTUI_VIEWCERTIFICATE_STRUCTW
))
4367 SetLastError(ERROR_INVALID_PARAMETER
);
4370 /* Make a local copy in case we have to call WinVerifyTrust ourselves */
4371 memcpy(&viewInfo
, pCertViewInfo
, sizeof(viewInfo
));
4372 if (!pCertViewInfo
->hWVTStateData
)
4374 memset(&wvt
, 0, sizeof(wvt
));
4375 wvt
.cbStruct
= sizeof(wvt
);
4376 wvt
.dwUIChoice
= WTD_UI_NONE
;
4377 if (viewInfo
.dwFlags
&
4378 CRYPTUI_ENABLE_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT
)
4379 wvt
.fdwRevocationChecks
|= WTD_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT
;
4380 if (viewInfo
.dwFlags
& CRYPTUI_ENABLE_REVOCATION_CHECK_END_CERT
)
4381 wvt
.fdwRevocationChecks
|= WTD_REVOCATION_CHECK_END_CERT
;
4382 if (viewInfo
.dwFlags
& CRYPTUI_ENABLE_REVOCATION_CHECK_CHAIN
)
4383 wvt
.fdwRevocationChecks
|= WTD_REVOCATION_CHECK_CHAIN
;
4384 wvt
.dwUnionChoice
= WTD_CHOICE_CERT
;
4385 memset(&cert
, 0, sizeof(cert
));
4386 cert
.cbStruct
= sizeof(cert
);
4387 cert
.psCertContext
= (CERT_CONTEXT
*)viewInfo
.pCertContext
;
4388 cert
.chStores
= viewInfo
.cStores
;
4389 cert
.pahStores
= viewInfo
.rghStores
;
4391 wvt
.dwStateAction
= WTD_STATEACTION_VERIFY
;
4392 WinVerifyTrust(NULL
, &generic_cert_verify
, &wvt
);
4393 viewInfo
.pCryptProviderData
=
4394 WTHelperProvDataFromStateData(wvt
.hWVTStateData
);
4395 signer
= WTHelperGetProvSignerFromChain(
4396 (CRYPT_PROVIDER_DATA
*)viewInfo
.pCryptProviderData
, 0, FALSE
, 0);
4397 provCert
= WTHelperGetProvCertFromChain(signer
, 0);
4402 viewInfo
.pCryptProviderData
=
4403 WTHelperProvDataFromStateData(viewInfo
.hWVTStateData
);
4404 signer
= WTHelperGetProvSignerFromChain(
4405 (CRYPT_PROVIDER_DATA
*)viewInfo
.pCryptProviderData
,
4406 viewInfo
.idxSigner
, viewInfo
.fCounterSigner
,
4407 viewInfo
.idxCounterSigner
);
4408 provCert
= WTHelperGetProvCertFromChain(signer
, viewInfo
.idxCert
);
4413 ret
= show_cert_dialog(&viewInfo
, provCert
, pfPropertiesChanged
);
4414 if (!pCertViewInfo
->hWVTStateData
)
4416 wvt
.dwStateAction
= WTD_STATEACTION_CLOSE
;
4417 WinVerifyTrust(NULL
, &generic_cert_verify
, &wvt
);
4423 /***********************************************************************
4424 * CryptUIDlgViewContext (CRYPTUI.@)
4426 BOOL WINAPI
CryptUIDlgViewContext(DWORD dwContextType
, LPVOID pvContext
,
4427 HWND hwnd
, LPCWSTR pwszTitle
, DWORD dwFlags
, LPVOID pvReserved
)
4431 TRACE("(%ld, %p, %p, %s, %08lx, %p)\n", dwContextType
, pvContext
, hwnd
,
4432 debugstr_w(pwszTitle
), dwFlags
, pvReserved
);
4434 switch (dwContextType
)
4436 case CERT_STORE_CERTIFICATE_CONTEXT
:
4438 CRYPTUI_VIEWCERTIFICATE_STRUCTW viewInfo
;
4440 memset(&viewInfo
, 0, sizeof(viewInfo
));
4441 viewInfo
.dwSize
= sizeof(viewInfo
);
4442 viewInfo
.hwndParent
= hwnd
;
4443 viewInfo
.szTitle
= pwszTitle
;
4444 viewInfo
.pCertContext
= pvContext
;
4445 ret
= CryptUIDlgViewCertificateW(&viewInfo
, NULL
);
4449 FIXME("unimplemented for context type %ld\n", dwContextType
);
4450 SetLastError(E_INVALIDARG
);
4456 /* Decodes a cert's basic constraints extension (either szOID_BASIC_CONSTRAINTS
4457 * or szOID_BASIC_CONSTRAINTS2, whichever is present) to determine if it
4458 * should be a CA. If neither extension is present, returns
4459 * defaultIfNotSpecified.
4461 static BOOL
is_ca_cert(PCCERT_CONTEXT cert
, BOOL defaultIfNotSpecified
)
4463 BOOL isCA
= defaultIfNotSpecified
;
4464 PCERT_EXTENSION ext
= CertFindExtension(szOID_BASIC_CONSTRAINTS
,
4465 cert
->pCertInfo
->cExtension
, cert
->pCertInfo
->rgExtension
);
4469 CERT_BASIC_CONSTRAINTS_INFO
*info
;
4472 if (CryptDecodeObjectEx(X509_ASN_ENCODING
, szOID_BASIC_CONSTRAINTS
,
4473 ext
->Value
.pbData
, ext
->Value
.cbData
, CRYPT_DECODE_ALLOC_FLAG
,
4474 NULL
, &info
, &size
))
4476 if (info
->SubjectType
.cbData
== 1)
4477 isCA
= info
->SubjectType
.pbData
[0] & CERT_CA_SUBJECT_FLAG
;
4483 ext
= CertFindExtension(szOID_BASIC_CONSTRAINTS2
,
4484 cert
->pCertInfo
->cExtension
, cert
->pCertInfo
->rgExtension
);
4487 CERT_BASIC_CONSTRAINTS2_INFO info
;
4488 DWORD size
= sizeof(CERT_BASIC_CONSTRAINTS2_INFO
);
4490 if (CryptDecodeObjectEx(X509_ASN_ENCODING
,
4491 szOID_BASIC_CONSTRAINTS2
, ext
->Value
.pbData
, ext
->Value
.cbData
,
4492 0, NULL
, &info
, &size
))
4499 static HCERTSTORE
choose_store_for_cert(PCCERT_CONTEXT cert
)
4503 if (is_ca_cert(cert
, TRUE
))
4506 storeName
= addressBook
;
4507 return CertOpenStore(CERT_STORE_PROV_SYSTEM_W
, 0, 0,
4508 CERT_SYSTEM_STORE_CURRENT_USER
, storeName
);
4511 static BOOL
import_cert(PCCERT_CONTEXT cert
, HCERTSTORE hDestCertStore
)
4518 SetLastError(E_INVALIDARG
);
4521 if (hDestCertStore
) store
= hDestCertStore
;
4524 if (!(store
= choose_store_for_cert(cert
)))
4526 WARN("unable to open certificate store\n");
4530 ret
= CertAddCertificateContextToStore(store
, cert
,
4531 CERT_STORE_ADD_REPLACE_EXISTING_INHERIT_PROPERTIES
, NULL
);
4532 if (!hDestCertStore
) CertCloseStore(store
, 0);
4536 static BOOL
import_crl(PCCRL_CONTEXT crl
, HCERTSTORE hDestCertStore
)
4543 SetLastError(E_INVALIDARG
);
4546 if (hDestCertStore
) store
= hDestCertStore
;
4549 if (!(store
= CertOpenStore(CERT_STORE_PROV_SYSTEM_W
, 0, 0,
4550 CERT_SYSTEM_STORE_CURRENT_USER
, ca
)))
4552 WARN("unable to open certificate store\n");
4556 ret
= CertAddCRLContextToStore(store
, crl
,
4557 CERT_STORE_ADD_REPLACE_EXISTING_INHERIT_PROPERTIES
, NULL
);
4558 if (!hDestCertStore
) CertCloseStore(store
, 0);
4562 static BOOL
import_ctl(PCCTL_CONTEXT ctl
, HCERTSTORE hDestCertStore
)
4569 SetLastError(E_INVALIDARG
);
4572 if (hDestCertStore
) store
= hDestCertStore
;
4575 static const WCHAR trust
[] = { 'T','r','u','s','t',0 };
4577 if (!(store
= CertOpenStore(CERT_STORE_PROV_SYSTEM_W
, 0, 0,
4578 CERT_SYSTEM_STORE_CURRENT_USER
, trust
)))
4580 WARN("unable to open certificate store\n");
4584 ret
= CertAddCTLContextToStore(store
, ctl
,
4585 CERT_STORE_ADD_REPLACE_EXISTING_INHERIT_PROPERTIES
, NULL
);
4586 if (!hDestCertStore
) CertCloseStore(store
, 0);
4590 /* Checks type, a type such as CERT_QUERY_CONTENT_CERT returned by
4591 * CryptQueryObject, against the allowed types. Returns TRUE if the
4592 * type is allowed, FALSE otherwise.
4594 static BOOL
check_context_type(DWORD dwFlags
, DWORD type
)
4599 (CRYPTUI_WIZ_IMPORT_ALLOW_CERT
| CRYPTUI_WIZ_IMPORT_ALLOW_CRL
|
4600 CRYPTUI_WIZ_IMPORT_ALLOW_CTL
))
4604 case CERT_QUERY_CONTENT_CERT
:
4605 case CERT_QUERY_CONTENT_SERIALIZED_CERT
:
4606 ret
= dwFlags
& CRYPTUI_WIZ_IMPORT_ALLOW_CERT
;
4608 case CERT_QUERY_CONTENT_CRL
:
4609 case CERT_QUERY_CONTENT_SERIALIZED_CRL
:
4610 ret
= dwFlags
& CRYPTUI_WIZ_IMPORT_ALLOW_CRL
;
4612 case CERT_QUERY_CONTENT_CTL
:
4613 case CERT_QUERY_CONTENT_SERIALIZED_CTL
:
4614 ret
= dwFlags
& CRYPTUI_WIZ_IMPORT_ALLOW_CTL
;
4617 /* The remaining types contain more than one type, so allow
4625 /* No allowed types specified, so any type is allowed */
4629 SetLastError(E_INVALIDARG
);
4634 static void import_warning(DWORD dwFlags
, HWND hwnd
, LPCWSTR szTitle
,
4637 if (!(dwFlags
& CRYPTUI_WIZ_NO_UI
))
4639 WCHAR title
[MAX_STRING_LEN
], error
[MAX_STRING_LEN
];
4646 LoadStringW(hInstance
, IDS_IMPORT_WIZARD
, title
, ARRAY_SIZE(title
));
4649 LoadStringW(hInstance
, warningID
, error
, ARRAY_SIZE(error
));
4650 MessageBoxW(hwnd
, error
, pTitle
, MB_ICONERROR
| MB_OK
);
4654 static void import_warn_type_mismatch(DWORD dwFlags
, HWND hwnd
, LPCWSTR szTitle
)
4656 import_warning(dwFlags
, hwnd
, szTitle
, IDS_IMPORT_TYPE_MISMATCH
);
4659 static BOOL
check_store_context_type(DWORD dwFlags
, HCERTSTORE store
)
4664 (CRYPTUI_WIZ_IMPORT_ALLOW_CERT
| CRYPTUI_WIZ_IMPORT_ALLOW_CRL
|
4665 CRYPTUI_WIZ_IMPORT_ALLOW_CTL
))
4667 PCCERT_CONTEXT cert
;
4672 if ((cert
= CertEnumCertificatesInStore(store
, NULL
)))
4674 CertFreeCertificateContext(cert
);
4675 if (!(dwFlags
& CRYPTUI_WIZ_IMPORT_ALLOW_CERT
))
4678 if (ret
&& (crl
= CertEnumCRLsInStore(store
, NULL
)))
4680 CertFreeCRLContext(crl
);
4681 if (!(dwFlags
& CRYPTUI_WIZ_IMPORT_ALLOW_CRL
))
4684 if (ret
&& (ctl
= CertEnumCTLsInStore(store
, NULL
)))
4686 CertFreeCTLContext(ctl
);
4687 if (!(dwFlags
& CRYPTUI_WIZ_IMPORT_ALLOW_CTL
))
4694 SetLastError(E_INVALIDARG
);
4698 static BOOL
import_store(DWORD dwFlags
, HWND hwnd
, LPCWSTR szTitle
,
4699 HCERTSTORE source
, HCERTSTORE dest
)
4703 if ((ret
= check_store_context_type(dwFlags
, source
)))
4705 PCCERT_CONTEXT cert
= NULL
;
4706 PCCRL_CONTEXT crl
= NULL
;
4707 PCCTL_CONTEXT ctl
= NULL
;
4710 cert
= CertEnumCertificatesInStore(source
, cert
);
4712 ret
= import_cert(cert
, dest
);
4713 } while (ret
&& cert
);
4715 crl
= CertEnumCRLsInStore(source
, crl
);
4717 ret
= import_crl(crl
, dest
);
4718 } while (ret
&& crl
);
4720 ctl
= CertEnumCTLsInStore(source
, ctl
);
4722 ret
= import_ctl(ctl
, dest
);
4723 } while (ret
&& ctl
);
4726 import_warn_type_mismatch(dwFlags
, hwnd
, szTitle
);
4730 static HCERTSTORE
open_store_from_file(DWORD dwFlags
, LPCWSTR fileName
,
4731 DWORD
*pContentType
)
4733 HCERTSTORE store
= NULL
;
4734 DWORD contentType
= 0, expectedContentTypeFlags
;
4737 (CRYPTUI_WIZ_IMPORT_ALLOW_CERT
| CRYPTUI_WIZ_IMPORT_ALLOW_CRL
|
4738 CRYPTUI_WIZ_IMPORT_ALLOW_CTL
))
4740 expectedContentTypeFlags
=
4741 CERT_QUERY_CONTENT_FLAG_SERIALIZED_STORE
|
4742 CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED
|
4743 CERT_QUERY_CONTENT_FLAG_PFX
;
4744 if (dwFlags
& CRYPTUI_WIZ_IMPORT_ALLOW_CERT
)
4745 expectedContentTypeFlags
|=
4746 CERT_QUERY_CONTENT_FLAG_CERT
|
4747 CERT_QUERY_CONTENT_FLAG_SERIALIZED_CERT
;
4748 if (dwFlags
& CRYPTUI_WIZ_IMPORT_ALLOW_CRL
)
4749 expectedContentTypeFlags
|=
4750 CERT_QUERY_CONTENT_FLAG_SERIALIZED_CRL
|
4751 CERT_QUERY_CONTENT_FLAG_CRL
;
4752 if (dwFlags
& CRYPTUI_WIZ_IMPORT_ALLOW_CTL
)
4753 expectedContentTypeFlags
|=
4754 CERT_QUERY_CONTENT_FLAG_CTL
|
4755 CERT_QUERY_CONTENT_FLAG_SERIALIZED_CTL
;
4758 expectedContentTypeFlags
=
4759 CERT_QUERY_CONTENT_FLAG_CERT
|
4760 CERT_QUERY_CONTENT_FLAG_CTL
|
4761 CERT_QUERY_CONTENT_FLAG_CRL
|
4762 CERT_QUERY_CONTENT_FLAG_SERIALIZED_STORE
|
4763 CERT_QUERY_CONTENT_FLAG_SERIALIZED_CERT
|
4764 CERT_QUERY_CONTENT_FLAG_SERIALIZED_CTL
|
4765 CERT_QUERY_CONTENT_FLAG_SERIALIZED_CRL
|
4766 CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED
|
4767 CERT_QUERY_CONTENT_FLAG_PFX
;
4769 CryptQueryObject(CERT_QUERY_OBJECT_FILE
, fileName
,
4770 expectedContentTypeFlags
, CERT_QUERY_FORMAT_FLAG_ALL
, 0, NULL
,
4771 &contentType
, NULL
, &store
, NULL
, NULL
);
4773 *pContentType
= contentType
;
4777 static BOOL
import_file(DWORD dwFlags
, HWND hwnd
, LPCWSTR szTitle
,
4778 LPCWSTR fileName
, HCERTSTORE dest
)
4783 if ((source
= open_store_from_file(dwFlags
, fileName
, NULL
)))
4785 ret
= import_store(dwFlags
, hwnd
, szTitle
, source
, dest
);
4786 CertCloseStore(source
, 0);
4793 struct ImportWizData
4797 LPCWSTR pwszWizardTitle
;
4798 CRYPTUI_WIZ_IMPORT_SRC_INFO importSrc
;
4802 HCERTSTORE hDestCertStore
;
4808 static INT_PTR CALLBACK
import_welcome_dlg_proc(HWND hwnd
, UINT msg
, WPARAM wp
,
4817 struct ImportWizData
*data
;
4818 PROPSHEETPAGEW
*page
= (PROPSHEETPAGEW
*)lp
;
4819 WCHAR fontFace
[MAX_STRING_LEN
];
4820 HDC hDC
= GetDC(hwnd
);
4823 data
= (struct ImportWizData
*)page
->lParam
;
4824 LoadStringW(hInstance
, IDS_WIZARD_TITLE_FONT
, fontFace
, ARRAY_SIZE(fontFace
));
4825 height
= -MulDiv(12, GetDeviceCaps(hDC
, LOGPIXELSY
), 72);
4826 data
->titleFont
= CreateFontW(height
, 0, 0, 0, FW_BOLD
, 0, 0, 0,
4827 DEFAULT_CHARSET
, OUT_DEFAULT_PRECIS
, CLIP_DEFAULT_PRECIS
,
4828 DEFAULT_QUALITY
, DEFAULT_PITCH
| FF_DONTCARE
, fontFace
);
4829 SendMessageW(GetDlgItem(hwnd
, IDC_IMPORT_TITLE
), WM_SETFONT
,
4830 (WPARAM
)data
->titleFont
, TRUE
);
4831 ReleaseDC(hwnd
, hDC
);
4836 NMHDR
*hdr
= (NMHDR
*)lp
;
4841 PostMessageW(GetParent(hwnd
), PSM_SETWIZBUTTONS
, 0, PSWIZB_NEXT
);
4851 static const WCHAR filter_cert
[] = { '*','.','c','e','r',';','*','.',
4853 static const WCHAR filter_pfx
[] = { '*','.','p','f','x',';','*','.',
4855 static const WCHAR filter_crl
[] = { '*','.','c','r','l',0 };
4856 static const WCHAR filter_ctl
[] = { '*','.','s','t','l',0 };
4857 static const WCHAR filter_serialized_store
[] = { '*','.','s','s','t',0 };
4858 static const WCHAR filter_cms
[] = { '*','.','s','p','c',';','*','.',
4860 static const WCHAR filter_all
[] = { '*','.','*',0 };
4867 } import_filters
[] = {
4868 { IDS_IMPORT_FILTER_CERT
, CRYPTUI_WIZ_IMPORT_ALLOW_CERT
, filter_cert
},
4869 { IDS_IMPORT_FILTER_PFX
, 0, filter_pfx
},
4870 { IDS_IMPORT_FILTER_CRL
, CRYPTUI_WIZ_IMPORT_ALLOW_CRL
, filter_crl
},
4871 { IDS_IMPORT_FILTER_CTL
, CRYPTUI_WIZ_IMPORT_ALLOW_CTL
, filter_ctl
},
4872 { IDS_IMPORT_FILTER_SERIALIZED_STORE
, 0, filter_serialized_store
},
4873 { IDS_IMPORT_FILTER_CMS
, 0, filter_cms
},
4874 { IDS_IMPORT_FILTER_ALL
, 0, filter_all
},
4877 static WCHAR
*make_import_file_filter(DWORD dwFlags
)
4880 int len
, totalLen
= 2;
4881 LPWSTR filter
= NULL
, str
;
4883 for (i
= 0; i
< ARRAY_SIZE(import_filters
); i
++)
4885 if (!import_filters
[i
].allowFlags
|| !dwFlags
||
4886 (dwFlags
& import_filters
[i
].allowFlags
))
4888 len
= LoadStringW(hInstance
, import_filters
[i
].id
, (LPWSTR
)&str
, 0);
4889 totalLen
+= len
+ lstrlenW(import_filters
[i
].filter
) + 2;
4892 filter
= malloc(totalLen
* sizeof(WCHAR
));
4898 for (i
= 0; i
< ARRAY_SIZE(import_filters
); i
++)
4900 if (!import_filters
[i
].allowFlags
|| !dwFlags
||
4901 (dwFlags
& import_filters
[i
].allowFlags
))
4903 len
= LoadStringW(hInstance
, import_filters
[i
].id
,
4905 memcpy(ptr
, str
, len
* sizeof(WCHAR
));
4908 lstrcpyW(ptr
, import_filters
[i
].filter
);
4909 ptr
+= lstrlenW(import_filters
[i
].filter
) + 1;
4917 static BOOL
import_validate_filename(HWND hwnd
, struct ImportWizData
*data
,
4923 file
= CreateFileW(fileName
, GENERIC_READ
, FILE_SHARE_READ
, NULL
,
4924 OPEN_EXISTING
, 0, NULL
);
4925 if (file
!= INVALID_HANDLE_VALUE
)
4927 HCERTSTORE source
= open_store_from_file(data
->dwFlags
, fileName
,
4928 &data
->contentType
);
4932 warningID
= IDS_IMPORT_BAD_FORMAT
;
4933 else if (!check_store_context_type(data
->dwFlags
, source
))
4934 warningID
= IDS_IMPORT_TYPE_MISMATCH
;
4937 data
->importSrc
.dwSubjectChoice
=
4938 CRYPTUI_WIZ_IMPORT_SUBJECT_CERT_STORE
;
4939 data
->importSrc
.hCertStore
= source
;
4940 data
->freeSource
= TRUE
;
4945 import_warning(data
->dwFlags
, hwnd
, data
->pwszWizardTitle
,
4952 WCHAR title
[MAX_STRING_LEN
], error
[MAX_STRING_LEN
];
4954 LPWSTR msgBuf
, fullError
;
4956 if (data
->pwszWizardTitle
)
4957 pTitle
= data
->pwszWizardTitle
;
4960 LoadStringW(hInstance
, IDS_IMPORT_WIZARD
, title
, ARRAY_SIZE(title
));
4963 LoadStringW(hInstance
, IDS_IMPORT_OPEN_FAILED
, error
, ARRAY_SIZE(error
));
4965 FORMAT_MESSAGE_ALLOCATE_BUFFER
| FORMAT_MESSAGE_FROM_SYSTEM
, NULL
,
4966 GetLastError(), 0, (LPWSTR
) &msgBuf
, 0, NULL
);
4967 fullError
= malloc((wcslen(error
) + wcslen(fileName
) + wcslen(msgBuf
) + 3) * sizeof(WCHAR
));
4970 LPWSTR ptr
= fullError
;
4972 lstrcpyW(ptr
, error
);
4973 ptr
+= lstrlenW(error
);
4974 lstrcpyW(ptr
, fileName
);
4975 ptr
+= lstrlenW(fileName
);
4978 lstrcpyW(ptr
, msgBuf
);
4979 MessageBoxW(hwnd
, fullError
, pTitle
, MB_ICONERROR
| MB_OK
);
4987 static INT_PTR CALLBACK
import_file_dlg_proc(HWND hwnd
, UINT msg
, WPARAM wp
,
4991 struct ImportWizData
*data
;
4997 PROPSHEETPAGEW
*page
= (PROPSHEETPAGEW
*)lp
;
4999 data
= (struct ImportWizData
*)page
->lParam
;
5000 SetWindowLongPtrW(hwnd
, DWLP_USER
, (LPARAM
)data
);
5003 HWND fileNameEdit
= GetDlgItem(hwnd
, IDC_IMPORT_FILENAME
);
5005 SendMessageW(fileNameEdit
, WM_SETTEXT
, 0, (LPARAM
)data
->fileName
);
5011 NMHDR
*hdr
= (NMHDR
*)lp
;
5016 PostMessageW(GetParent(hwnd
), PSM_SETWIZBUTTONS
, 0,
5017 PSWIZB_BACK
| PSWIZB_NEXT
);
5022 HWND fileNameEdit
= GetDlgItem(hwnd
, IDC_IMPORT_FILENAME
);
5023 DWORD len
= SendMessageW(fileNameEdit
, WM_GETTEXTLENGTH
, 0, 0);
5025 data
= (struct ImportWizData
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
5028 import_warning(data
->dwFlags
, hwnd
, data
->pwszWizardTitle
,
5029 IDS_IMPORT_EMPTY_FILE
);
5030 SetWindowLongPtrW(hwnd
, DWLP_MSGRESULT
, 1);
5035 WCHAR
*fileName
= malloc((len
+ 1) * sizeof(WCHAR
));
5039 SendMessageW(fileNameEdit
, WM_GETTEXT
, len
+ 1,
5041 if (!import_validate_filename(hwnd
, data
, fileName
))
5044 SetWindowLongPtrW(hwnd
, DWLP_MSGRESULT
, 1);
5048 data
->fileName
= fileName
;
5059 case IDC_IMPORT_BROWSE_FILE
:
5062 WCHAR fileBuf
[MAX_PATH
];
5064 data
= (struct ImportWizData
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
5065 memset(&ofn
, 0, sizeof(ofn
));
5066 ofn
.lStructSize
= sizeof(ofn
);
5067 ofn
.hwndOwner
= hwnd
;
5068 ofn
.lpstrFilter
= make_import_file_filter(data
->dwFlags
);
5069 ofn
.lpstrFile
= fileBuf
;
5070 ofn
.nMaxFile
= ARRAY_SIZE(fileBuf
);
5072 if (GetOpenFileNameW(&ofn
))
5073 SendMessageW(GetDlgItem(hwnd
, IDC_IMPORT_FILENAME
), WM_SETTEXT
,
5074 0, (LPARAM
)ofn
.lpstrFile
);
5075 free((WCHAR
*)ofn
.lpstrFilter
);
5084 static INT_PTR CALLBACK
import_store_dlg_proc(HWND hwnd
, UINT msg
, WPARAM wp
,
5088 struct ImportWizData
*data
;
5094 PROPSHEETPAGEW
*page
= (PROPSHEETPAGEW
*)lp
;
5096 data
= (struct ImportWizData
*)page
->lParam
;
5097 SetWindowLongPtrW(hwnd
, DWLP_USER
, (LPARAM
)data
);
5098 if (!data
->hDestCertStore
)
5100 SendMessageW(GetDlgItem(hwnd
, IDC_IMPORT_AUTO_STORE
), BM_CLICK
,
5102 EnableWindow(GetDlgItem(hwnd
, IDC_IMPORT_STORE
), FALSE
);
5103 EnableWindow(GetDlgItem(hwnd
, IDC_IMPORT_BROWSE_STORE
), FALSE
);
5104 EnableWindow(GetDlgItem(hwnd
, IDC_IMPORT_SPECIFY_STORE
), FALSE
);
5108 WCHAR storeTitle
[MAX_STRING_LEN
];
5110 SendMessageW(GetDlgItem(hwnd
, IDC_IMPORT_SPECIFY_STORE
), BM_CLICK
,
5112 EnableWindow(GetDlgItem(hwnd
, IDC_IMPORT_STORE
), TRUE
);
5113 EnableWindow(GetDlgItem(hwnd
, IDC_IMPORT_BROWSE_STORE
), TRUE
);
5114 EnableWindow(GetDlgItem(hwnd
, IDC_IMPORT_SPECIFY_STORE
),
5115 !(data
->dwFlags
& CRYPTUI_WIZ_IMPORT_NO_CHANGE_DEST_STORE
));
5116 LoadStringW(hInstance
, IDS_IMPORT_DEST_DETERMINED
, storeTitle
, ARRAY_SIZE(storeTitle
));
5117 SendMessageW(GetDlgItem(hwnd
, IDC_IMPORT_STORE
), WM_SETTEXT
,
5118 0, (LPARAM
)storeTitle
);
5124 NMHDR
*hdr
= (NMHDR
*)lp
;
5129 PostMessageW(GetParent(hwnd
), PSM_SETWIZBUTTONS
, 0,
5130 PSWIZB_BACK
| PSWIZB_NEXT
);
5135 data
= (struct ImportWizData
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
5136 if (IsDlgButtonChecked(hwnd
, IDC_IMPORT_SPECIFY_STORE
) &&
5137 !data
->hDestCertStore
)
5139 import_warning(data
->dwFlags
, hwnd
, data
->pwszWizardTitle
,
5140 IDS_IMPORT_SELECT_STORE
);
5141 SetWindowLongPtrW(hwnd
, DWLP_MSGRESULT
, 1);
5152 case IDC_IMPORT_AUTO_STORE
:
5153 data
= (struct ImportWizData
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
5154 data
->autoDest
= TRUE
;
5155 EnableWindow(GetDlgItem(hwnd
, IDC_IMPORT_STORE
), FALSE
);
5156 EnableWindow(GetDlgItem(hwnd
, IDC_IMPORT_BROWSE_STORE
), FALSE
);
5158 case IDC_IMPORT_SPECIFY_STORE
:
5159 data
= (struct ImportWizData
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
5160 data
->autoDest
= FALSE
;
5161 EnableWindow(GetDlgItem(hwnd
, IDC_IMPORT_STORE
), TRUE
);
5162 EnableWindow(GetDlgItem(hwnd
, IDC_IMPORT_BROWSE_STORE
), TRUE
);
5164 case IDC_IMPORT_BROWSE_STORE
:
5166 CRYPTUI_ENUM_SYSTEM_STORE_ARGS enumArgs
= {
5167 CERT_SYSTEM_STORE_CURRENT_USER
, NULL
};
5168 CRYPTUI_ENUM_DATA enumData
= { 0, NULL
, 1, &enumArgs
};
5169 CRYPTUI_SELECTSTORE_INFO_W selectInfo
;
5172 data
= (struct ImportWizData
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
5173 selectInfo
.dwSize
= sizeof(selectInfo
);
5174 selectInfo
.parent
= hwnd
;
5175 selectInfo
.dwFlags
= CRYPTUI_ENABLE_SHOW_PHYSICAL_STORE
;
5176 selectInfo
.pwszTitle
= NULL
;
5177 selectInfo
.pwszText
= NULL
;
5178 selectInfo
.pEnumData
= &enumData
;
5179 selectInfo
.pfnSelectedStoreCallback
= NULL
;
5180 if ((store
= CryptUIDlgSelectStoreW(&selectInfo
)))
5182 WCHAR storeTitle
[MAX_STRING_LEN
];
5184 LoadStringW(hInstance
, IDS_IMPORT_DEST_DETERMINED
, storeTitle
,
5185 ARRAY_SIZE(storeTitle
));
5186 SendMessageW(GetDlgItem(hwnd
, IDC_IMPORT_STORE
), WM_SETTEXT
,
5187 0, (LPARAM
)storeTitle
);
5188 data
->hDestCertStore
= store
;
5189 data
->freeDest
= TRUE
;
5199 static void show_import_details(HWND lv
, struct ImportWizData
*data
)
5201 WCHAR text
[MAX_STRING_LEN
];
5205 item
.mask
= LVIF_TEXT
;
5206 item
.iItem
= SendMessageW(lv
, LVM_GETITEMCOUNT
, 0, 0);
5208 LoadStringW(hInstance
, IDS_IMPORT_STORE_SELECTION
, text
, ARRAY_SIZE(text
));
5209 item
.pszText
= text
;
5210 SendMessageW(lv
, LVM_INSERTITEMW
, 0, (LPARAM
)&item
);
5213 LoadStringW(hInstance
, IDS_IMPORT_DEST_AUTOMATIC
, text
, ARRAY_SIZE(text
));
5215 LoadStringW(hInstance
, IDS_IMPORT_DEST_DETERMINED
, text
, ARRAY_SIZE(text
));
5216 SendMessageW(lv
, LVM_SETITEMTEXTW
, item
.iItem
, (LPARAM
)&item
);
5217 item
.iItem
= SendMessageW(lv
, LVM_GETITEMCOUNT
, 0, 0);
5219 LoadStringW(hInstance
, IDS_IMPORT_CONTENT
, text
, ARRAY_SIZE(text
));
5220 SendMessageW(lv
, LVM_INSERTITEMW
, 0, (LPARAM
)&item
);
5221 switch (data
->contentType
)
5223 case CERT_QUERY_CONTENT_CERT
:
5224 case CERT_QUERY_CONTENT_SERIALIZED_CERT
:
5225 contentID
= IDS_IMPORT_CONTENT_CERT
;
5227 case CERT_QUERY_CONTENT_CRL
:
5228 case CERT_QUERY_CONTENT_SERIALIZED_CRL
:
5229 contentID
= IDS_IMPORT_CONTENT_CRL
;
5231 case CERT_QUERY_CONTENT_CTL
:
5232 case CERT_QUERY_CONTENT_SERIALIZED_CTL
:
5233 contentID
= IDS_IMPORT_CONTENT_CTL
;
5235 case CERT_QUERY_CONTENT_PKCS7_SIGNED
:
5236 contentID
= IDS_IMPORT_CONTENT_CMS
;
5238 case CERT_QUERY_CONTENT_FLAG_PFX
:
5239 contentID
= IDS_IMPORT_CONTENT_PFX
;
5242 contentID
= IDS_IMPORT_CONTENT_STORE
;
5245 LoadStringW(hInstance
, contentID
, text
, ARRAY_SIZE(text
));
5247 SendMessageW(lv
, LVM_SETITEMTEXTW
, item
.iItem
, (LPARAM
)&item
);
5250 item
.iItem
= SendMessageW(lv
, LVM_GETITEMCOUNT
, 0, 0);
5252 LoadStringW(hInstance
, IDS_IMPORT_FILE
, text
, ARRAY_SIZE(text
));
5253 SendMessageW(lv
, LVM_INSERTITEMW
, 0, (LPARAM
)&item
);
5255 item
.pszText
= data
->fileName
;
5256 SendMessageW(lv
, LVM_SETITEMTEXTW
, item
.iItem
, (LPARAM
)&item
);
5260 static BOOL
do_import(DWORD dwFlags
, HWND hwndParent
, LPCWSTR pwszWizardTitle
,
5261 PCCRYPTUI_WIZ_IMPORT_SRC_INFO pImportSrc
, HCERTSTORE hDestCertStore
)
5265 switch (pImportSrc
->dwSubjectChoice
)
5267 case CRYPTUI_WIZ_IMPORT_SUBJECT_FILE
:
5268 ret
= import_file(dwFlags
, hwndParent
, pwszWizardTitle
,
5269 pImportSrc
->pwszFileName
, hDestCertStore
);
5271 case CRYPTUI_WIZ_IMPORT_SUBJECT_CERT_CONTEXT
:
5272 if ((ret
= check_context_type(dwFlags
, CERT_QUERY_CONTENT_CERT
)))
5273 ret
= import_cert(pImportSrc
->pCertContext
, hDestCertStore
);
5275 import_warn_type_mismatch(dwFlags
, hwndParent
, pwszWizardTitle
);
5277 case CRYPTUI_WIZ_IMPORT_SUBJECT_CRL_CONTEXT
:
5278 if ((ret
= check_context_type(dwFlags
, CERT_QUERY_CONTENT_CRL
)))
5279 ret
= import_crl(pImportSrc
->pCRLContext
, hDestCertStore
);
5281 import_warn_type_mismatch(dwFlags
, hwndParent
, pwszWizardTitle
);
5283 case CRYPTUI_WIZ_IMPORT_SUBJECT_CTL_CONTEXT
:
5284 if ((ret
= check_context_type(dwFlags
, CERT_QUERY_CONTENT_CTL
)))
5285 ret
= import_ctl(pImportSrc
->pCTLContext
, hDestCertStore
);
5287 import_warn_type_mismatch(dwFlags
, hwndParent
, pwszWizardTitle
);
5289 case CRYPTUI_WIZ_IMPORT_SUBJECT_CERT_STORE
:
5290 ret
= import_store(dwFlags
, hwndParent
, pwszWizardTitle
,
5291 pImportSrc
->hCertStore
, hDestCertStore
);
5294 WARN("unknown source type: %lu\n", pImportSrc
->dwSubjectChoice
);
5295 SetLastError(E_INVALIDARG
);
5301 static INT_PTR CALLBACK
import_finish_dlg_proc(HWND hwnd
, UINT msg
, WPARAM wp
,
5305 struct ImportWizData
*data
;
5311 PROPSHEETPAGEW
*page
= (PROPSHEETPAGEW
*)lp
;
5312 HWND lv
= GetDlgItem(hwnd
, IDC_IMPORT_SETTINGS
);
5316 data
= (struct ImportWizData
*)page
->lParam
;
5317 SetWindowLongPtrW(hwnd
, DWLP_USER
, (LPARAM
)data
);
5318 SendMessageW(GetDlgItem(hwnd
, IDC_IMPORT_TITLE
), WM_SETFONT
,
5319 (WPARAM
)data
->titleFont
, TRUE
);
5320 GetWindowRect(lv
, &rc
);
5321 column
.mask
= LVCF_WIDTH
;
5322 column
.cx
= (rc
.right
- rc
.left
) / 2 - 2;
5323 SendMessageW(lv
, LVM_INSERTCOLUMNW
, 0, (LPARAM
)&column
);
5324 SendMessageW(lv
, LVM_INSERTCOLUMNW
, 1, (LPARAM
)&column
);
5325 show_import_details(lv
, data
);
5330 NMHDR
*hdr
= (NMHDR
*)lp
;
5336 HWND lv
= GetDlgItem(hwnd
, IDC_IMPORT_SETTINGS
);
5338 data
= (struct ImportWizData
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
5339 SendMessageW(lv
, LVM_DELETEALLITEMS
, 0, 0);
5340 show_import_details(lv
, data
);
5341 PostMessageW(GetParent(hwnd
), PSM_SETWIZBUTTONS
, 0,
5342 PSWIZB_BACK
| PSWIZB_FINISH
);
5348 data
= (struct ImportWizData
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
5349 if ((data
->success
= do_import(data
->dwFlags
, hwnd
,
5350 data
->pwszWizardTitle
, &data
->importSrc
, data
->hDestCertStore
)))
5352 WCHAR title
[MAX_STRING_LEN
], message
[MAX_STRING_LEN
];
5355 if (data
->pwszWizardTitle
)
5356 pTitle
= data
->pwszWizardTitle
;
5359 LoadStringW(hInstance
, IDS_IMPORT_WIZARD
, title
, ARRAY_SIZE(title
));
5362 LoadStringW(hInstance
, IDS_IMPORT_SUCCEEDED
, message
, ARRAY_SIZE(message
));
5363 MessageBoxW(hwnd
, message
, pTitle
, MB_OK
);
5366 import_warning(data
->dwFlags
, hwnd
, data
->pwszWizardTitle
,
5377 static BOOL
show_import_ui(DWORD dwFlags
, HWND hwndParent
,
5378 LPCWSTR pwszWizardTitle
, PCCRYPTUI_WIZ_IMPORT_SRC_INFO pImportSrc
,
5379 HCERTSTORE hDestCertStore
)
5381 PROPSHEETHEADERW hdr
;
5382 PROPSHEETPAGEW pages
[4];
5383 struct ImportWizData data
;
5386 data
.dwFlags
= dwFlags
;
5387 data
.pwszWizardTitle
= pwszWizardTitle
;
5390 memcpy(&data
.importSrc
, pImportSrc
, sizeof(data
.importSrc
));
5391 data
.fileName
= (LPWSTR
)pImportSrc
->pwszFileName
;
5395 memset(&data
.importSrc
, 0, sizeof(data
.importSrc
));
5396 data
.fileName
= NULL
;
5398 data
.freeSource
= FALSE
;
5399 data
.hDestCertStore
= hDestCertStore
;
5400 data
.freeDest
= FALSE
;
5401 data
.autoDest
= TRUE
;
5402 data
.success
= TRUE
;
5404 memset(pages
, 0, sizeof(pages
));
5406 pages
[nPages
].dwSize
= sizeof(pages
[0]);
5407 pages
[nPages
].hInstance
= hInstance
;
5408 pages
[nPages
].pszTemplate
= MAKEINTRESOURCEW(IDD_IMPORT_WELCOME
);
5409 pages
[nPages
].pfnDlgProc
= import_welcome_dlg_proc
;
5410 pages
[nPages
].dwFlags
= PSP_HIDEHEADER
;
5411 pages
[nPages
].lParam
= (LPARAM
)&data
;
5415 pImportSrc
->dwSubjectChoice
== CRYPTUI_WIZ_IMPORT_SUBJECT_FILE
)
5417 pages
[nPages
].dwSize
= sizeof(pages
[0]);
5418 pages
[nPages
].hInstance
= hInstance
;
5419 pages
[nPages
].pszTemplate
= MAKEINTRESOURCEW(IDD_IMPORT_FILE
);
5420 pages
[nPages
].pfnDlgProc
= import_file_dlg_proc
;
5421 pages
[nPages
].dwFlags
= PSP_USEHEADERTITLE
| PSP_USEHEADERSUBTITLE
;
5422 pages
[nPages
].pszHeaderTitle
= MAKEINTRESOURCEW(IDS_IMPORT_FILE_TITLE
);
5423 pages
[nPages
].pszHeaderSubTitle
=
5424 MAKEINTRESOURCEW(IDS_IMPORT_FILE_SUBTITLE
);
5425 pages
[nPages
].lParam
= (LPARAM
)&data
;
5430 switch (pImportSrc
->dwSubjectChoice
)
5432 case CRYPTUI_WIZ_IMPORT_SUBJECT_CERT_CONTEXT
:
5433 data
.contentType
= CERT_QUERY_CONTENT_CERT
;
5435 case CRYPTUI_WIZ_IMPORT_SUBJECT_CRL_CONTEXT
:
5436 data
.contentType
= CERT_QUERY_CONTENT_CRL
;
5438 case CRYPTUI_WIZ_IMPORT_SUBJECT_CTL_CONTEXT
:
5439 data
.contentType
= CERT_QUERY_CONTENT_CTL
;
5441 case CRYPTUI_WIZ_IMPORT_SUBJECT_CERT_STORE
:
5442 data
.contentType
= CERT_QUERY_CONTENT_SERIALIZED_STORE
;
5447 pages
[nPages
].dwSize
= sizeof(pages
[0]);
5448 pages
[nPages
].hInstance
= hInstance
;
5449 pages
[nPages
].pszTemplate
= MAKEINTRESOURCEW(IDD_IMPORT_STORE
);
5450 pages
[nPages
].pfnDlgProc
= import_store_dlg_proc
;
5451 pages
[nPages
].dwFlags
= PSP_USEHEADERTITLE
| PSP_USEHEADERSUBTITLE
;
5452 pages
[nPages
].pszHeaderTitle
= MAKEINTRESOURCEW(IDS_IMPORT_STORE_TITLE
);
5453 pages
[nPages
].pszHeaderSubTitle
=
5454 MAKEINTRESOURCEW(IDS_IMPORT_STORE_SUBTITLE
);
5455 pages
[nPages
].lParam
= (LPARAM
)&data
;
5458 pages
[nPages
].dwSize
= sizeof(pages
[0]);
5459 pages
[nPages
].hInstance
= hInstance
;
5460 pages
[nPages
].pszTemplate
= MAKEINTRESOURCEW(IDD_IMPORT_FINISH
);
5461 pages
[nPages
].pfnDlgProc
= import_finish_dlg_proc
;
5462 pages
[nPages
].dwFlags
= PSP_HIDEHEADER
;
5463 pages
[nPages
].lParam
= (LPARAM
)&data
;
5466 memset(&hdr
, 0, sizeof(hdr
));
5467 hdr
.dwSize
= sizeof(hdr
);
5468 hdr
.hwndParent
= hwndParent
;
5469 hdr
.dwFlags
= PSH_PROPSHEETPAGE
| PSH_WIZARD97_NEW
| PSH_HEADER
|
5471 hdr
.hInstance
= hInstance
;
5472 if (pwszWizardTitle
)
5473 hdr
.pszCaption
= pwszWizardTitle
;
5475 hdr
.pszCaption
= MAKEINTRESOURCEW(IDS_IMPORT_WIZARD
);
5477 hdr
.nPages
= nPages
;
5478 hdr
.pszbmWatermark
= MAKEINTRESOURCEW(IDB_CERT_WATERMARK
);
5479 hdr
.pszbmHeader
= MAKEINTRESOURCEW(IDB_CERT_HEADER
);
5480 PropertySheetW(&hdr
);
5481 if (data
.fileName
!= data
.importSrc
.pwszFileName
)
5482 free(data
.fileName
);
5483 if (data
.freeSource
&&
5484 data
.importSrc
.dwSubjectChoice
== CRYPTUI_WIZ_IMPORT_SUBJECT_CERT_STORE
)
5485 CertCloseStore(data
.importSrc
.hCertStore
, 0);
5486 DeleteObject(data
.titleFont
);
5487 return data
.success
;
5490 BOOL WINAPI
CryptUIWizImport(DWORD dwFlags
, HWND hwndParent
, LPCWSTR pwszWizardTitle
,
5491 PCCRYPTUI_WIZ_IMPORT_SRC_INFO pImportSrc
, HCERTSTORE hDestCertStore
)
5495 TRACE("(0x%08lx, %p, %s, %p, %p)\n", dwFlags
, hwndParent
, debugstr_w(pwszWizardTitle
),
5496 pImportSrc
, hDestCertStore
);
5499 pImportSrc
->dwSize
!= sizeof(CRYPTUI_WIZ_IMPORT_SRC_INFO
))
5501 SetLastError(E_INVALIDARG
);
5505 if (!(dwFlags
& CRYPTUI_WIZ_NO_UI
))
5506 ret
= show_import_ui(dwFlags
, hwndParent
, pwszWizardTitle
, pImportSrc
,
5508 else if (pImportSrc
)
5509 ret
= do_import(dwFlags
, hwndParent
, pwszWizardTitle
, pImportSrc
,
5513 /* Can't have no UI without specifying source */
5514 SetLastError(E_INVALIDARG
);
5521 struct ExportWizData
5525 LPCWSTR pwszWizardTitle
;
5526 CRYPTUI_WIZ_EXPORT_INFO exportInfo
;
5527 CRYPTUI_WIZ_EXPORT_CERTCONTEXT_INFO contextInfo
;
5529 PCRYPT_KEY_PROV_INFO keyProvInfo
;
5536 static INT_PTR CALLBACK
export_welcome_dlg_proc(HWND hwnd
, UINT msg
, WPARAM wp
,
5545 struct ExportWizData
*data
;
5546 PROPSHEETPAGEW
*page
= (PROPSHEETPAGEW
*)lp
;
5547 WCHAR fontFace
[MAX_STRING_LEN
];
5548 HDC hDC
= GetDC(hwnd
);
5551 data
= (struct ExportWizData
*)page
->lParam
;
5552 LoadStringW(hInstance
, IDS_WIZARD_TITLE_FONT
, fontFace
, ARRAY_SIZE(fontFace
));
5553 height
= -MulDiv(12, GetDeviceCaps(hDC
, LOGPIXELSY
), 72);
5554 data
->titleFont
= CreateFontW(height
, 0, 0, 0, FW_BOLD
, 0, 0, 0,
5555 DEFAULT_CHARSET
, OUT_DEFAULT_PRECIS
, CLIP_DEFAULT_PRECIS
,
5556 DEFAULT_QUALITY
, DEFAULT_PITCH
| FF_DONTCARE
, fontFace
);
5557 SendMessageW(GetDlgItem(hwnd
, IDC_EXPORT_TITLE
), WM_SETFONT
,
5558 (WPARAM
)data
->titleFont
, TRUE
);
5559 ReleaseDC(hwnd
, hDC
);
5564 NMHDR
*hdr
= (NMHDR
*)lp
;
5569 PostMessageW(GetParent(hwnd
), PSM_SETWIZBUTTONS
, 0, PSWIZB_NEXT
);
5579 static PCRYPT_KEY_PROV_INFO
export_get_private_key_info(PCCERT_CONTEXT cert
)
5581 PCRYPT_KEY_PROV_INFO info
= NULL
;
5584 if (CertGetCertificateContextProperty(cert
, CERT_KEY_PROV_INFO_PROP_ID
,
5587 info
= malloc(size
);
5590 if (!CertGetCertificateContextProperty(cert
,
5591 CERT_KEY_PROV_INFO_PROP_ID
, info
, &size
))
5601 static BOOL
export_acquire_private_key(const CRYPT_KEY_PROV_INFO
*info
,
5606 ret
= CryptAcquireContextW(phProv
, info
->pwszContainerName
,
5607 info
->pwszProvName
, info
->dwProvType
, 0);
5612 for (i
= 0; i
< info
->cProvParam
; i
++)
5613 CryptSetProvParam(*phProv
, info
->rgProvParam
[i
].dwParam
,
5614 info
->rgProvParam
[i
].pbData
, info
->rgProvParam
[i
].dwFlags
);
5619 static BOOL
export_is_key_exportable(HCRYPTPROV hProv
, DWORD keySpec
)
5624 if ((ret
= CryptGetUserKey(hProv
, keySpec
, &key
)))
5626 DWORD permissions
, size
= sizeof(permissions
);
5628 if ((ret
= CryptGetKeyParam(key
, KP_PERMISSIONS
, (BYTE
*)&permissions
,
5629 &size
, 0)) && !(permissions
& CRYPT_EXPORT
))
5631 CryptDestroyKey(key
);
5636 static INT_PTR CALLBACK
export_private_key_dlg_proc(HWND hwnd
, UINT msg
,
5637 WPARAM wp
, LPARAM lp
)
5640 struct ExportWizData
*data
;
5646 PROPSHEETPAGEW
*page
= (PROPSHEETPAGEW
*)lp
;
5647 PCRYPT_KEY_PROV_INFO info
;
5648 HCRYPTPROV hProv
= 0;
5651 data
= (struct ExportWizData
*)page
->lParam
;
5652 SetWindowLongPtrW(hwnd
, DWLP_USER
, (LPARAM
)data
);
5653 /* Get enough information about a key to see whether it's exportable.
5655 if (!(info
= export_get_private_key_info(
5656 data
->exportInfo
.pCertContext
)))
5657 errorID
= IDS_EXPORT_PRIVATE_KEY_UNAVAILABLE
;
5658 else if (!export_acquire_private_key(info
, &hProv
))
5659 errorID
= IDS_EXPORT_PRIVATE_KEY_UNAVAILABLE
;
5660 else if (!export_is_key_exportable(hProv
, info
->dwKeySpec
))
5661 errorID
= IDS_EXPORT_PRIVATE_KEY_NON_EXPORTABLE
;
5665 WCHAR error
[MAX_STRING_LEN
];
5667 LoadStringW(hInstance
, errorID
, error
, ARRAY_SIZE(error
));
5668 SendMessageW(GetDlgItem(hwnd
, IDC_EXPORT_PRIVATE_KEY_UNAVAILABLE
),
5669 WM_SETTEXT
, 0, (LPARAM
)error
);
5670 EnableWindow(GetDlgItem(hwnd
, IDC_EXPORT_PRIVATE_KEY_YES
), FALSE
);
5673 data
->keyProvInfo
= info
;
5675 CryptReleaseContext(hProv
, 0);
5676 SendMessageW(GetDlgItem(hwnd
, IDC_EXPORT_PRIVATE_KEY_NO
), BM_CLICK
,
5682 NMHDR
*hdr
= (NMHDR
*)lp
;
5687 PostMessageW(GetParent(hwnd
), PSM_SETWIZBUTTONS
, 0,
5688 PSWIZB_BACK
| PSWIZB_NEXT
);
5692 data
= (struct ExportWizData
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
5693 if (IsDlgButtonChecked(hwnd
, IDC_EXPORT_PRIVATE_KEY_NO
))
5695 data
->contextInfo
.dwExportFormat
=
5696 CRYPTUI_WIZ_EXPORT_FORMAT_DER
;
5697 data
->contextInfo
.fExportPrivateKeys
= FALSE
;
5701 data
->contextInfo
.dwExportFormat
=
5702 CRYPTUI_WIZ_EXPORT_FORMAT_PFX
;
5703 data
->contextInfo
.fExportPrivateKeys
= TRUE
;
5713 static BOOL
export_info_has_private_key(PCCRYPTUI_WIZ_EXPORT_INFO pExportInfo
)
5717 if (pExportInfo
->dwSubjectChoice
== CRYPTUI_WIZ_EXPORT_CERT_CONTEXT
)
5721 /* If there's a CRYPT_KEY_PROV_INFO set for this cert, assume the
5722 * cert has a private key.
5724 if (CertGetCertificateContextProperty(pExportInfo
->pCertContext
,
5725 CERT_KEY_PROV_INFO_PROP_ID
, NULL
, &size
))
5731 static void export_format_enable_controls(HWND hwnd
, const struct ExportWizData
*data
)
5733 int defaultFormatID
;
5735 switch (data
->contextInfo
.dwExportFormat
)
5737 case CRYPTUI_WIZ_EXPORT_FORMAT_BASE64
:
5738 defaultFormatID
= IDC_EXPORT_FORMAT_BASE64
;
5740 case CRYPTUI_WIZ_EXPORT_FORMAT_PKCS7
:
5741 defaultFormatID
= IDC_EXPORT_FORMAT_CMS
;
5743 case CRYPTUI_WIZ_EXPORT_FORMAT_PFX
:
5744 defaultFormatID
= IDC_EXPORT_FORMAT_PFX
;
5747 defaultFormatID
= IDC_EXPORT_FORMAT_DER
;
5749 SendMessageW(GetDlgItem(hwnd
, defaultFormatID
), BM_CLICK
, 0, 0);
5750 if (defaultFormatID
== IDC_EXPORT_FORMAT_PFX
)
5752 EnableWindow(GetDlgItem(hwnd
, IDC_EXPORT_FORMAT_DER
), FALSE
);
5753 EnableWindow(GetDlgItem(hwnd
, IDC_EXPORT_FORMAT_BASE64
), FALSE
);
5754 EnableWindow(GetDlgItem(hwnd
, IDC_EXPORT_FORMAT_CMS
), FALSE
);
5755 EnableWindow(GetDlgItem(hwnd
, IDC_EXPORT_FORMAT_PFX
), TRUE
);
5759 EnableWindow(GetDlgItem(hwnd
, IDC_EXPORT_FORMAT_DER
), TRUE
);
5760 EnableWindow(GetDlgItem(hwnd
, IDC_EXPORT_FORMAT_BASE64
), TRUE
);
5761 EnableWindow(GetDlgItem(hwnd
, IDC_EXPORT_FORMAT_CMS
), TRUE
);
5762 EnableWindow(GetDlgItem(hwnd
, IDC_EXPORT_FORMAT_PFX
), FALSE
);
5766 static INT_PTR CALLBACK
export_format_dlg_proc(HWND hwnd
, UINT msg
, WPARAM wp
,
5770 struct ExportWizData
*data
;
5776 PROPSHEETPAGEW
*page
= (PROPSHEETPAGEW
*)lp
;
5778 data
= (struct ExportWizData
*)page
->lParam
;
5779 SetWindowLongPtrW(hwnd
, DWLP_USER
, (LPARAM
)data
);
5780 export_format_enable_controls(hwnd
, data
);
5785 NMHDR
*hdr
= (NMHDR
*)lp
;
5790 PostMessageW(GetParent(hwnd
), PSM_SETWIZBUTTONS
, 0,
5791 PSWIZB_BACK
| PSWIZB_NEXT
);
5792 data
= (struct ExportWizData
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
5793 export_format_enable_controls(hwnd
, data
);
5798 BOOL skipPasswordPage
= TRUE
;
5800 data
= (struct ExportWizData
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
5801 if (IsDlgButtonChecked(hwnd
, IDC_EXPORT_FORMAT_DER
))
5802 data
->contextInfo
.dwExportFormat
=
5803 CRYPTUI_WIZ_EXPORT_FORMAT_DER
;
5804 else if (IsDlgButtonChecked(hwnd
, IDC_EXPORT_FORMAT_BASE64
))
5805 data
->contextInfo
.dwExportFormat
=
5806 CRYPTUI_WIZ_EXPORT_FORMAT_BASE64
;
5807 else if (IsDlgButtonChecked(hwnd
, IDC_EXPORT_FORMAT_CMS
))
5809 data
->contextInfo
.dwExportFormat
=
5810 CRYPTUI_WIZ_EXPORT_FORMAT_PKCS7
;
5811 if (IsDlgButtonChecked(hwnd
, IDC_EXPORT_CMS_INCLUDE_CHAIN
))
5812 data
->contextInfo
.fExportChain
=
5813 CRYPTUI_WIZ_EXPORT_FORMAT_PKCS7
;
5817 data
->contextInfo
.dwExportFormat
=
5818 CRYPTUI_WIZ_EXPORT_FORMAT_PFX
;
5819 if (IsDlgButtonChecked(hwnd
, IDC_EXPORT_PFX_INCLUDE_CHAIN
))
5820 data
->contextInfo
.fExportChain
= TRUE
;
5821 if (IsDlgButtonChecked(hwnd
, IDC_EXPORT_PFX_STRONG_ENCRYPTION
))
5822 data
->contextInfo
.fStrongEncryption
= TRUE
;
5823 if (IsDlgButtonChecked(hwnd
, IDC_EXPORT_PFX_DELETE_PRIVATE_KEY
))
5824 data
->deleteKeys
= TRUE
;
5825 skipPasswordPage
= FALSE
;
5827 SetWindowLongPtrW(hwnd
, DWLP_MSGRESULT
,
5828 skipPasswordPage
? IDD_EXPORT_FILE
: 0);
5841 case IDC_EXPORT_FORMAT_DER
:
5842 case IDC_EXPORT_FORMAT_BASE64
:
5843 EnableWindow(GetDlgItem(hwnd
, IDC_EXPORT_CMS_INCLUDE_CHAIN
),
5845 EnableWindow(GetDlgItem(hwnd
, IDC_EXPORT_PFX_INCLUDE_CHAIN
),
5847 EnableWindow(GetDlgItem(hwnd
, IDC_EXPORT_PFX_STRONG_ENCRYPTION
),
5849 EnableWindow(GetDlgItem(hwnd
,
5850 IDC_EXPORT_PFX_DELETE_PRIVATE_KEY
), FALSE
);
5852 case IDC_EXPORT_FORMAT_CMS
:
5853 EnableWindow(GetDlgItem(hwnd
, IDC_EXPORT_CMS_INCLUDE_CHAIN
),
5856 case IDC_EXPORT_FORMAT_PFX
:
5857 EnableWindow(GetDlgItem(hwnd
, IDC_EXPORT_PFX_INCLUDE_CHAIN
),
5859 EnableWindow(GetDlgItem(hwnd
, IDC_EXPORT_PFX_STRONG_ENCRYPTION
),
5861 EnableWindow(GetDlgItem(hwnd
,
5862 IDC_EXPORT_PFX_DELETE_PRIVATE_KEY
), TRUE
);
5872 static void export_password_mismatch(HWND hwnd
, const struct ExportWizData
*data
)
5874 WCHAR title
[MAX_STRING_LEN
], error
[MAX_STRING_LEN
];
5877 if (data
->pwszWizardTitle
)
5878 pTitle
= data
->pwszWizardTitle
;
5881 LoadStringW(hInstance
, IDS_EXPORT_WIZARD
, title
, ARRAY_SIZE(title
));
5884 LoadStringW(hInstance
, IDS_EXPORT_PASSWORD_MISMATCH
, error
, ARRAY_SIZE(error
));
5885 MessageBoxW(hwnd
, error
, pTitle
, MB_ICONERROR
| MB_OK
);
5886 SetFocus(GetDlgItem(hwnd
, IDC_EXPORT_PASSWORD
));
5889 static INT_PTR CALLBACK
export_password_dlg_proc(HWND hwnd
, UINT msg
,
5890 WPARAM wp
, LPARAM lp
)
5893 struct ExportWizData
*data
;
5899 PROPSHEETPAGEW
*page
= (PROPSHEETPAGEW
*)lp
;
5901 data
= (struct ExportWizData
*)page
->lParam
;
5902 SetWindowLongPtrW(hwnd
, DWLP_USER
, (LPARAM
)data
);
5907 NMHDR
*hdr
= (NMHDR
*)lp
;
5912 PostMessageW(GetParent(hwnd
), PSM_SETWIZBUTTONS
, 0,
5913 PSWIZB_BACK
| PSWIZB_NEXT
);
5918 HWND passwordEdit
= GetDlgItem(hwnd
, IDC_EXPORT_PASSWORD
);
5919 HWND passwordConfirmEdit
= GetDlgItem(hwnd
,
5920 IDC_EXPORT_PASSWORD_CONFIRM
);
5921 DWORD passwordLen
= SendMessageW(passwordEdit
, WM_GETTEXTLENGTH
,
5923 DWORD passwordConfirmLen
= SendMessageW(passwordConfirmEdit
,
5924 WM_GETTEXTLENGTH
, 0, 0);
5926 data
= (struct ExportWizData
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
5927 if (!passwordLen
&& !passwordConfirmLen
)
5928 data
->contextInfo
.pwszPassword
= NULL
;
5929 else if (passwordLen
!= passwordConfirmLen
)
5931 export_password_mismatch(hwnd
, data
);
5932 SetWindowLongPtrW(hwnd
, DWLP_MSGRESULT
, 1);
5937 WCHAR
*password
= malloc((passwordLen
+ 1) * sizeof(WCHAR
));
5938 WCHAR
*passwordConfirm
= malloc((passwordConfirmLen
+ 1) * sizeof(WCHAR
));
5939 BOOL freePassword
= TRUE
;
5941 if (password
&& passwordConfirm
)
5943 SendMessageW(passwordEdit
, WM_GETTEXT
, passwordLen
+ 1,
5945 SendMessageW(passwordConfirmEdit
, WM_GETTEXT
,
5946 passwordConfirmLen
+ 1, (LPARAM
)passwordConfirm
);
5947 if (lstrcmpW(password
, passwordConfirm
))
5949 export_password_mismatch(hwnd
, data
);
5950 SetWindowLongPtrW(hwnd
, DWLP_MSGRESULT
, 1);
5955 data
->contextInfo
.pwszPassword
= password
;
5956 freePassword
= FALSE
;
5957 data
->freePassword
= TRUE
;
5962 free(passwordConfirm
);
5973 static LPWSTR
export_append_extension(const struct ExportWizData
*data
,
5976 static const WCHAR cer
[] = { '.','c','e','r',0 };
5977 static const WCHAR crl
[] = { '.','c','r','l',0 };
5978 static const WCHAR ctl
[] = { '.','c','t','l',0 };
5979 static const WCHAR p7b
[] = { '.','p','7','b',0 };
5980 static const WCHAR pfx
[] = { '.','p','f','x',0 };
5981 static const WCHAR sst
[] = { '.','s','s','t',0 };
5984 BOOL appendExtension
;
5986 switch (data
->contextInfo
.dwExportFormat
)
5988 case CRYPTUI_WIZ_EXPORT_FORMAT_PKCS7
:
5991 case CRYPTUI_WIZ_EXPORT_FORMAT_PFX
:
5995 switch (data
->exportInfo
.dwSubjectChoice
)
5997 case CRYPTUI_WIZ_EXPORT_CRL_CONTEXT
:
6000 case CRYPTUI_WIZ_EXPORT_CTL_CONTEXT
:
6003 case CRYPTUI_WIZ_EXPORT_CERT_STORE
:
6010 dot
= wcsrchr(fileName
, '.');
6012 appendExtension
= wcsicmp(dot
, extension
) != 0;
6014 appendExtension
= TRUE
;
6015 if (appendExtension
)
6017 fileName
= realloc(fileName
, (wcslen(fileName
) + wcslen(extension
) + 1) * sizeof(WCHAR
));
6019 lstrcatW(fileName
, extension
);
6024 static BOOL
export_validate_filename(HWND hwnd
, struct ExportWizData
*data
,
6028 BOOL tryCreate
= TRUE
, forceCreate
= FALSE
, ret
= FALSE
;
6030 file
= CreateFileW(fileName
, GENERIC_WRITE
,
6031 FILE_SHARE_READ
| FILE_SHARE_WRITE
, NULL
, OPEN_EXISTING
, 0, NULL
);
6032 if (file
!= INVALID_HANDLE_VALUE
)
6034 WCHAR warning
[MAX_STRING_LEN
], title
[MAX_STRING_LEN
];
6037 if (data
->pwszWizardTitle
)
6038 pTitle
= data
->pwszWizardTitle
;
6041 LoadStringW(hInstance
, IDS_EXPORT_WIZARD
, title
, ARRAY_SIZE(title
));
6044 LoadStringW(hInstance
, IDS_EXPORT_FILE_EXISTS
, warning
, ARRAY_SIZE(warning
));
6045 if (MessageBoxW(hwnd
, warning
, pTitle
, MB_YESNO
) == IDYES
)
6053 file
= CreateFileW(fileName
, GENERIC_WRITE
,
6054 FILE_SHARE_READ
| FILE_SHARE_WRITE
, NULL
,
6055 forceCreate
? CREATE_ALWAYS
: CREATE_NEW
,
6057 if (file
!= INVALID_HANDLE_VALUE
)
6064 WCHAR title
[MAX_STRING_LEN
], error
[MAX_STRING_LEN
];
6066 LPWSTR msgBuf
, fullError
;
6068 if (data
->pwszWizardTitle
)
6069 pTitle
= data
->pwszWizardTitle
;
6072 LoadStringW(hInstance
, IDS_EXPORT_WIZARD
, title
, ARRAY_SIZE(title
));
6075 LoadStringW(hInstance
, IDS_IMPORT_OPEN_FAILED
, error
, ARRAY_SIZE(error
));
6077 FORMAT_MESSAGE_ALLOCATE_BUFFER
| FORMAT_MESSAGE_FROM_SYSTEM
, NULL
,
6078 GetLastError(), 0, (LPWSTR
) &msgBuf
, 0, NULL
);
6079 fullError
= malloc((wcslen(error
) + wcslen(fileName
) + wcslen(msgBuf
) + 3) * sizeof(WCHAR
));
6082 LPWSTR ptr
= fullError
;
6084 lstrcpyW(ptr
, error
);
6085 ptr
+= lstrlenW(error
);
6086 lstrcpyW(ptr
, fileName
);
6087 ptr
+= lstrlenW(fileName
);
6090 lstrcpyW(ptr
, msgBuf
);
6091 MessageBoxW(hwnd
, fullError
, pTitle
, MB_ICONERROR
| MB_OK
);
6100 static const WCHAR export_filter_cert
[] = { '*','.','c','e','r',0 };
6101 static const WCHAR export_filter_crl
[] = { '*','.','c','r','l',0 };
6102 static const WCHAR export_filter_ctl
[] = { '*','.','s','t','l',0 };
6103 static const WCHAR export_filter_cms
[] = { '*','.','p','7','b',0 };
6104 static const WCHAR export_filter_pfx
[] = { '*','.','p','f','x',0 };
6105 static const WCHAR export_filter_sst
[] = { '*','.','s','s','t',0 };
6107 static WCHAR
*make_export_file_filter(DWORD exportFormat
, DWORD subjectChoice
)
6109 int baseLen
, allLen
, totalLen
= 2, baseID
;
6110 LPWSTR filter
= NULL
, baseFilter
, all
;
6113 switch (exportFormat
)
6115 case CRYPTUI_WIZ_EXPORT_FORMAT_BASE64
:
6116 baseID
= IDS_EXPORT_FILTER_BASE64_CERT
;
6117 filterStr
= export_filter_cert
;
6119 case CRYPTUI_WIZ_EXPORT_FORMAT_PFX
:
6120 baseID
= IDS_EXPORT_FILTER_PFX
;
6121 filterStr
= export_filter_pfx
;
6123 case CRYPTUI_WIZ_EXPORT_FORMAT_PKCS7
:
6124 baseID
= IDS_EXPORT_FILTER_CMS
;
6125 filterStr
= export_filter_cms
;
6128 switch (subjectChoice
)
6130 case CRYPTUI_WIZ_EXPORT_CRL_CONTEXT
:
6131 baseID
= IDS_EXPORT_FILTER_CRL
;
6132 filterStr
= export_filter_crl
;
6134 case CRYPTUI_WIZ_EXPORT_CTL_CONTEXT
:
6135 baseID
= IDS_EXPORT_FILTER_CTL
;
6136 filterStr
= export_filter_ctl
;
6138 case CRYPTUI_WIZ_EXPORT_CERT_STORE
:
6139 baseID
= IDS_EXPORT_FILTER_SERIALIZED_CERT_STORE
;
6140 filterStr
= export_filter_sst
;
6143 baseID
= IDS_EXPORT_FILTER_CERT
;
6144 filterStr
= export_filter_cert
;
6148 baseLen
= LoadStringW(hInstance
, baseID
, (LPWSTR
)&baseFilter
, 0);
6149 totalLen
+= baseLen
+ lstrlenW(filterStr
) + 2;
6150 allLen
= LoadStringW(hInstance
, IDS_IMPORT_FILTER_ALL
, (LPWSTR
)&all
, 0);
6151 totalLen
+= allLen
+ lstrlenW(filter_all
) + 2;
6152 filter
= malloc(totalLen
* sizeof(WCHAR
));
6158 memcpy(ptr
, baseFilter
, baseLen
* sizeof(WCHAR
));
6161 lstrcpyW(ptr
, filterStr
);
6162 ptr
+= lstrlenW(filterStr
) + 1;
6163 memcpy(ptr
, all
, allLen
* sizeof(WCHAR
));
6166 lstrcpyW(ptr
, filter_all
);
6167 ptr
+= lstrlenW(filter_all
) + 1;
6173 static INT_PTR CALLBACK
export_file_dlg_proc(HWND hwnd
, UINT msg
, WPARAM wp
,
6177 struct ExportWizData
*data
;
6183 PROPSHEETPAGEW
*page
= (PROPSHEETPAGEW
*)lp
;
6185 data
= (struct ExportWizData
*)page
->lParam
;
6186 SetWindowLongPtrW(hwnd
, DWLP_USER
, (LPARAM
)data
);
6187 if (data
->exportInfo
.pwszExportFileName
)
6188 SendMessageW(GetDlgItem(hwnd
, IDC_EXPORT_FILENAME
), WM_SETTEXT
, 0,
6189 (LPARAM
)data
->exportInfo
.pwszExportFileName
);
6194 NMHDR
*hdr
= (NMHDR
*)lp
;
6199 data
= (struct ExportWizData
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
6200 if (data
->contextInfo
.dwExportFormat
!=
6201 CRYPTUI_WIZ_EXPORT_FORMAT_PFX
)
6203 SetWindowLongPtrW(hwnd
, DWLP_MSGRESULT
, IDD_EXPORT_FORMAT
);
6209 HWND fileNameEdit
= GetDlgItem(hwnd
, IDC_EXPORT_FILENAME
);
6210 DWORD len
= SendMessageW(fileNameEdit
, WM_GETTEXTLENGTH
, 0, 0);
6212 data
= (struct ExportWizData
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
6215 WCHAR title
[MAX_STRING_LEN
], error
[MAX_STRING_LEN
];
6218 if (data
->pwszWizardTitle
)
6219 pTitle
= data
->pwszWizardTitle
;
6222 LoadStringW(hInstance
, IDS_EXPORT_WIZARD
, title
, ARRAY_SIZE(title
));
6225 LoadStringW(hInstance
, IDS_IMPORT_EMPTY_FILE
, error
, ARRAY_SIZE(error
));
6226 MessageBoxW(hwnd
, error
, pTitle
, MB_ICONERROR
| MB_OK
);
6227 SetWindowLongPtrW(hwnd
, DWLP_MSGRESULT
, 1);
6232 WCHAR
*fileName
= malloc((len
+ 1) * sizeof(WCHAR
));
6236 SendMessageW(fileNameEdit
, WM_GETTEXT
, len
+ 1,
6238 fileName
= export_append_extension(data
, fileName
);
6239 if (!export_validate_filename(hwnd
, data
, fileName
))
6242 SetWindowLongPtrW(hwnd
, DWLP_MSGRESULT
, 1);
6246 data
->fileName
= fileName
;
6252 PostMessageW(GetParent(hwnd
), PSM_SETWIZBUTTONS
, 0,
6253 PSWIZB_BACK
| PSWIZB_NEXT
);
6262 case IDC_EXPORT_BROWSE_FILE
:
6265 WCHAR fileBuf
[MAX_PATH
];
6267 data
= (struct ExportWizData
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
6268 memset(&ofn
, 0, sizeof(ofn
));
6269 ofn
.lStructSize
= sizeof(ofn
);
6270 ofn
.hwndOwner
= hwnd
;
6271 ofn
.lpstrFilter
= make_export_file_filter(
6272 data
->contextInfo
.dwExportFormat
,
6273 data
->exportInfo
.dwSubjectChoice
);
6274 ofn
.lpstrFile
= fileBuf
;
6275 ofn
.nMaxFile
= ARRAY_SIZE(fileBuf
);
6277 if (GetSaveFileNameW(&ofn
))
6278 SendMessageW(GetDlgItem(hwnd
, IDC_EXPORT_FILENAME
), WM_SETTEXT
,
6279 0, (LPARAM
)ofn
.lpstrFile
);
6280 free((WCHAR
*)ofn
.lpstrFilter
);
6289 static void show_export_details(HWND lv
, const struct ExportWizData
*data
)
6291 WCHAR text
[MAX_STRING_LEN
];
6295 item
.mask
= LVIF_TEXT
;
6298 item
.iItem
= SendMessageW(lv
, LVM_GETITEMCOUNT
, 0, 0);
6300 LoadStringW(hInstance
, IDS_IMPORT_FILE
, text
, ARRAY_SIZE(text
));
6301 item
.pszText
= text
;
6302 SendMessageW(lv
, LVM_INSERTITEMW
, 0, (LPARAM
)&item
);
6304 item
.pszText
= data
->fileName
;
6305 SendMessageW(lv
, LVM_SETITEMTEXTW
, item
.iItem
, (LPARAM
)&item
);
6308 item
.pszText
= text
;
6309 switch (data
->exportInfo
.dwSubjectChoice
)
6311 case CRYPTUI_WIZ_EXPORT_CRL_CONTEXT
:
6312 case CRYPTUI_WIZ_EXPORT_CTL_CONTEXT
:
6313 case CRYPTUI_WIZ_EXPORT_CERT_STORE
:
6314 case CRYPTUI_WIZ_EXPORT_CERT_STORE_CERTIFICATES_ONLY
:
6319 item
.iItem
= SendMessageW(lv
, LVM_GETITEMCOUNT
, 0, 0);
6321 LoadStringW(hInstance
, IDS_EXPORT_INCLUDE_CHAIN
, text
, ARRAY_SIZE(text
));
6322 SendMessageW(lv
, LVM_INSERTITEMW
, item
.iItem
, (LPARAM
)&item
);
6324 LoadStringW(hInstance
, data
->contextInfo
.fExportChain
? IDS_YES
: IDS_NO
, text
,
6326 SendMessageW(lv
, LVM_SETITEMTEXTW
, item
.iItem
, (LPARAM
)&item
);
6328 item
.iItem
= SendMessageW(lv
, LVM_GETITEMCOUNT
, 0, 0);
6330 LoadStringW(hInstance
, IDS_EXPORT_KEYS
, text
, ARRAY_SIZE(text
));
6331 SendMessageW(lv
, LVM_INSERTITEMW
, item
.iItem
, (LPARAM
)&item
);
6333 LoadStringW(hInstance
, data
->contextInfo
.fExportPrivateKeys
? IDS_YES
: IDS_NO
, text
,
6335 SendMessageW(lv
, LVM_SETITEMTEXTW
, item
.iItem
, (LPARAM
)&item
);
6339 item
.iItem
= SendMessageW(lv
, LVM_GETITEMCOUNT
, 0, 0);
6341 LoadStringW(hInstance
, IDS_EXPORT_FORMAT
, text
, ARRAY_SIZE(text
));
6342 SendMessageW(lv
, LVM_INSERTITEMW
, 0, (LPARAM
)&item
);
6345 switch (data
->exportInfo
.dwSubjectChoice
)
6347 case CRYPTUI_WIZ_EXPORT_CRL_CONTEXT
:
6348 contentID
= IDS_EXPORT_FILTER_CRL
;
6350 case CRYPTUI_WIZ_EXPORT_CTL_CONTEXT
:
6351 contentID
= IDS_EXPORT_FILTER_CTL
;
6353 case CRYPTUI_WIZ_EXPORT_CERT_STORE
:
6354 contentID
= IDS_EXPORT_FILTER_SERIALIZED_CERT_STORE
;
6357 switch (data
->contextInfo
.dwExportFormat
)
6359 case CRYPTUI_WIZ_EXPORT_FORMAT_BASE64
:
6360 contentID
= IDS_EXPORT_FILTER_BASE64_CERT
;
6362 case CRYPTUI_WIZ_EXPORT_FORMAT_PKCS7
:
6363 contentID
= IDS_EXPORT_FILTER_CMS
;
6365 case CRYPTUI_WIZ_EXPORT_FORMAT_PFX
:
6366 contentID
= IDS_EXPORT_FILTER_PFX
;
6369 contentID
= IDS_EXPORT_FILTER_CERT
;
6372 LoadStringW(hInstance
, contentID
, text
, ARRAY_SIZE(text
));
6373 SendMessageW(lv
, LVM_SETITEMTEXTW
, item
.iItem
, (LPARAM
)&item
);
6376 static inline BOOL
save_der(HANDLE file
, const BYTE
*pb
, DWORD cb
)
6380 return WriteFile(file
, pb
, cb
, &bytesWritten
, NULL
);
6383 static BOOL
save_base64(HANDLE file
, const BYTE
*pb
, DWORD cb
)
6388 if ((ret
= CryptBinaryToStringA(pb
, cb
, CRYPT_STRING_BASE64
, NULL
, &size
)))
6390 char *buf
= malloc(size
);
6394 if ((ret
= CryptBinaryToStringA(pb
, cb
, CRYPT_STRING_BASE64
, buf
,
6396 ret
= WriteFile(file
, buf
, size
, &size
, NULL
);
6401 SetLastError(ERROR_OUTOFMEMORY
);
6408 static inline BOOL
save_store_as_cms(HANDLE file
, HCERTSTORE store
)
6410 return CertSaveStore(store
, PKCS_7_ASN_ENCODING
| X509_ASN_ENCODING
,
6411 CERT_STORE_SAVE_AS_PKCS7
, CERT_STORE_SAVE_TO_FILE
, file
, 0);
6414 static BOOL
save_cert_as_cms(HANDLE file
, PCCRYPTUI_WIZ_EXPORT_INFO pExportInfo
,
6418 HCERTSTORE store
= CertOpenStore(CERT_STORE_PROV_MEMORY
, 0, 0,
6419 CERT_STORE_CREATE_NEW_FLAG
, NULL
);
6425 HCERTSTORE addlStore
= CertOpenStore(CERT_STORE_PROV_COLLECTION
,
6426 0, 0, CERT_STORE_CREATE_NEW_FLAG
, NULL
);
6433 for (i
= 0; ret
&& i
< pExportInfo
->cStores
; i
++)
6434 ret
= CertAddStoreToCollection(addlStore
,
6435 pExportInfo
->rghStores
, 0, 0);
6438 PCCERT_CHAIN_CONTEXT chain
;
6440 ret
= CertGetCertificateChain(NULL
,
6441 pExportInfo
->pCertContext
, NULL
, addlStore
, NULL
, 0,
6447 for (i
= 0; ret
&& i
< chain
->cChain
; i
++)
6448 for (j
= 0; ret
&& j
< chain
->rgpChain
[i
]->cElement
;
6450 ret
= CertAddCertificateContextToStore(store
,
6451 chain
->rgpChain
[i
]->rgpElement
[j
]->pCertContext
,
6452 CERT_STORE_ADD_ALWAYS
, NULL
);
6453 CertFreeCertificateChain(chain
);
6457 /* No chain could be created, just add the individual
6458 * cert to the message.
6460 ret
= CertAddCertificateContextToStore(store
,
6461 pExportInfo
->pCertContext
, CERT_STORE_ADD_ALWAYS
,
6465 CertCloseStore(addlStore
, 0);
6471 ret
= CertAddCertificateContextToStore(store
,
6472 pExportInfo
->pCertContext
, CERT_STORE_ADD_ALWAYS
, NULL
);
6474 ret
= save_store_as_cms(file
, store
);
6475 CertCloseStore(store
, 0);
6482 static BOOL
save_serialized_store(HANDLE file
, HCERTSTORE store
)
6484 return CertSaveStore(store
, PKCS_7_ASN_ENCODING
| X509_ASN_ENCODING
,
6485 CERT_STORE_SAVE_AS_STORE
, CERT_STORE_SAVE_TO_FILE
, file
, 0);
6488 static BOOL
save_pfx(HANDLE file
, PCCRYPTUI_WIZ_EXPORT_INFO pExportInfo
,
6489 PCCRYPTUI_WIZ_EXPORT_CERTCONTEXT_INFO pContextInfo
,
6490 PCRYPT_KEY_PROV_INFO keyProvInfo
, BOOL deleteKeys
)
6492 HCERTSTORE store
= CertOpenStore(CERT_STORE_PROV_MEMORY
, X509_ASN_ENCODING
,
6493 0, CERT_STORE_CREATE_NEW_FLAG
, NULL
);
6498 CRYPT_DATA_BLOB pfxBlob
= { 0, NULL
};
6499 PCCERT_CONTEXT cert
= NULL
;
6500 BOOL freeKeyProvInfo
= FALSE
;
6502 if (pContextInfo
->fExportChain
)
6504 HCERTCHAINENGINE engine
= NULL
;
6506 if (pExportInfo
->cStores
)
6508 CERT_CHAIN_ENGINE_CONFIG config
;
6510 memset(&config
, 0, sizeof(config
));
6511 config
.cbSize
= sizeof(config
);
6512 config
.cAdditionalStore
= pExportInfo
->cStores
;
6513 config
.rghAdditionalStore
= pExportInfo
->rghStores
;
6514 ret
= CertCreateCertificateChainEngine(&config
, &engine
);
6520 CERT_CHAIN_PARA chainPara
;
6521 PCCERT_CHAIN_CONTEXT chain
;
6523 memset(&chainPara
, 0, sizeof(chainPara
));
6524 chainPara
.cbSize
= sizeof(chainPara
);
6525 ret
= CertGetCertificateChain(engine
,
6526 pExportInfo
->pCertContext
, NULL
, NULL
, &chainPara
, 0, NULL
,
6532 for (i
= 0; ret
&& i
< chain
->cChain
; i
++)
6533 for (j
= 0; ret
&& j
< chain
->rgpChain
[i
]->cElement
;
6536 if (i
== 0 && j
== 0)
6537 ret
= CertAddCertificateContextToStore(store
,
6538 chain
->rgpChain
[i
]->rgpElement
[j
]->pCertContext
,
6539 CERT_STORE_ADD_ALWAYS
, &cert
);
6541 ret
= CertAddCertificateContextToStore(store
,
6542 chain
->rgpChain
[i
]->rgpElement
[j
]->pCertContext
,
6543 CERT_STORE_ADD_ALWAYS
, NULL
);
6545 CertFreeCertificateChain(chain
);
6549 CertFreeCertificateChainEngine(engine
);
6552 ret
= CertAddCertificateContextToStore(store
,
6553 pExportInfo
->pCertContext
, CERT_STORE_ADD_ALWAYS
, &cert
);
6554 /* Copy private key info to newly created cert, so it'll get exported
6555 * along with the cert.
6557 if (ret
&& pContextInfo
->fExportPrivateKeys
)
6560 ret
= CertSetCertificateContextProperty(cert
,
6561 CERT_KEY_PROV_INFO_PROP_ID
, 0, keyProvInfo
);
6564 if (!(keyProvInfo
= export_get_private_key_info(cert
)))
6568 ret
= CertSetCertificateContextProperty(cert
,
6569 CERT_KEY_PROV_INFO_PROP_ID
, 0, keyProvInfo
);
6570 freeKeyProvInfo
= TRUE
;
6577 REPORT_NOT_ABLE_TO_EXPORT_PRIVATE_KEY
| EXPORT_PRIVATE_KEYS
;
6579 ret
= PFXExportCertStore(store
, &pfxBlob
,
6580 pContextInfo
->pwszPassword
, exportFlags
);
6583 pfxBlob
.pbData
= malloc(pfxBlob
.cbData
);
6586 ret
= PFXExportCertStore(store
, &pfxBlob
,
6587 pContextInfo
->pwszPassword
, exportFlags
);
6592 ret
= WriteFile(file
, pfxBlob
.pbData
, pfxBlob
.cbData
,
6593 &bytesWritten
, NULL
);
6598 SetLastError(ERROR_OUTOFMEMORY
);
6603 if (ret
&& deleteKeys
)
6607 CryptAcquireContextW(&prov
, keyProvInfo
->pwszContainerName
,
6608 keyProvInfo
->pwszProvName
, keyProvInfo
->dwProvType
,
6609 CRYPT_DELETEKEYSET
);
6611 if (freeKeyProvInfo
)
6613 CertFreeCertificateContext(cert
);
6614 CertCloseStore(store
, 0);
6619 static BOOL
do_export(HANDLE file
, PCCRYPTUI_WIZ_EXPORT_INFO pExportInfo
,
6620 PCCRYPTUI_WIZ_EXPORT_CERTCONTEXT_INFO pContextInfo
,
6621 PCRYPT_KEY_PROV_INFO keyProvInfo
, BOOL deleteKeys
)
6625 if (pContextInfo
->dwSize
!= sizeof(CRYPTUI_WIZ_EXPORT_CERTCONTEXT_INFO
))
6627 SetLastError(E_INVALIDARG
);
6630 switch (pExportInfo
->dwSubjectChoice
)
6632 case CRYPTUI_WIZ_EXPORT_CRL_CONTEXT
:
6633 ret
= save_der(file
,
6634 pExportInfo
->pCRLContext
->pbCrlEncoded
,
6635 pExportInfo
->pCRLContext
->cbCrlEncoded
);
6637 case CRYPTUI_WIZ_EXPORT_CTL_CONTEXT
:
6638 ret
= save_der(file
,
6639 pExportInfo
->pCTLContext
->pbCtlEncoded
,
6640 pExportInfo
->pCTLContext
->cbCtlEncoded
);
6642 case CRYPTUI_WIZ_EXPORT_CERT_STORE
:
6643 ret
= save_serialized_store(file
, pExportInfo
->hCertStore
);
6645 case CRYPTUI_WIZ_EXPORT_CERT_STORE_CERTIFICATES_ONLY
:
6646 ret
= save_store_as_cms(file
, pExportInfo
->hCertStore
);
6649 switch (pContextInfo
->dwExportFormat
)
6651 case CRYPTUI_WIZ_EXPORT_FORMAT_DER
:
6652 ret
= save_der(file
, pExportInfo
->pCertContext
->pbCertEncoded
,
6653 pExportInfo
->pCertContext
->cbCertEncoded
);
6655 case CRYPTUI_WIZ_EXPORT_FORMAT_BASE64
:
6656 ret
= save_base64(file
,
6657 pExportInfo
->pCertContext
->pbCertEncoded
,
6658 pExportInfo
->pCertContext
->cbCertEncoded
);
6660 case CRYPTUI_WIZ_EXPORT_FORMAT_PKCS7
:
6661 ret
= save_cert_as_cms(file
, pExportInfo
,
6662 pContextInfo
->fExportChain
);
6664 case CRYPTUI_WIZ_EXPORT_FORMAT_PFX
:
6665 ret
= save_pfx(file
, pExportInfo
, pContextInfo
, keyProvInfo
,
6669 SetLastError(E_FAIL
);
6676 static INT_PTR CALLBACK
export_finish_dlg_proc(HWND hwnd
, UINT msg
, WPARAM wp
,
6680 struct ExportWizData
*data
;
6686 PROPSHEETPAGEW
*page
= (PROPSHEETPAGEW
*)lp
;
6687 HWND lv
= GetDlgItem(hwnd
, IDC_EXPORT_SETTINGS
);
6691 data
= (struct ExportWizData
*)page
->lParam
;
6692 SetWindowLongPtrW(hwnd
, DWLP_USER
, (LPARAM
)data
);
6693 SendMessageW(GetDlgItem(hwnd
, IDC_EXPORT_TITLE
), WM_SETFONT
,
6694 (WPARAM
)data
->titleFont
, TRUE
);
6695 GetWindowRect(lv
, &rc
);
6696 column
.mask
= LVCF_WIDTH
;
6697 column
.cx
= (rc
.right
- rc
.left
) / 2 - 2;
6698 SendMessageW(lv
, LVM_INSERTCOLUMNW
, 0, (LPARAM
)&column
);
6699 SendMessageW(lv
, LVM_INSERTCOLUMNW
, 1, (LPARAM
)&column
);
6700 show_export_details(lv
, data
);
6705 NMHDR
*hdr
= (NMHDR
*)lp
;
6711 HWND lv
= GetDlgItem(hwnd
, IDC_EXPORT_SETTINGS
);
6713 data
= (struct ExportWizData
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
6714 SendMessageW(lv
, LVM_DELETEALLITEMS
, 0, 0);
6715 show_export_details(lv
, data
);
6716 PostMessageW(GetParent(hwnd
), PSM_SETWIZBUTTONS
, 0,
6717 PSWIZB_BACK
| PSWIZB_FINISH
);
6724 WCHAR title
[MAX_STRING_LEN
], message
[MAX_STRING_LEN
];
6728 data
= (struct ExportWizData
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
6729 if ((data
->success
= do_export(data
->file
, &data
->exportInfo
,
6730 &data
->contextInfo
, data
->keyProvInfo
, data
->deleteKeys
)))
6732 messageID
= IDS_EXPORT_SUCCEEDED
;
6737 messageID
= IDS_EXPORT_FAILED
;
6738 mbFlags
= MB_OK
| MB_ICONERROR
;
6740 if (data
->pwszWizardTitle
)
6741 pTitle
= data
->pwszWizardTitle
;
6744 LoadStringW(hInstance
, IDS_EXPORT_WIZARD
, title
, ARRAY_SIZE(title
));
6747 LoadStringW(hInstance
, messageID
, message
, ARRAY_SIZE(message
));
6748 MessageBoxW(hwnd
, message
, pTitle
, mbFlags
);
6758 static BOOL
show_export_ui(DWORD dwFlags
, HWND hwndParent
,
6759 LPCWSTR pwszWizardTitle
, PCCRYPTUI_WIZ_EXPORT_INFO pExportInfo
, const void *pvoid
)
6761 PROPSHEETHEADERW hdr
;
6762 PROPSHEETPAGEW pages
[6];
6763 struct ExportWizData data
;
6765 BOOL hasPrivateKey
, showFormatPage
= TRUE
;
6768 data
.dwFlags
= dwFlags
;
6769 data
.pwszWizardTitle
= pwszWizardTitle
;
6770 memset(&data
.exportInfo
, 0, sizeof(data
.exportInfo
));
6771 memcpy(&data
.exportInfo
, pExportInfo
,
6772 min(sizeof(data
.exportInfo
), pExportInfo
->dwSize
));
6773 if (pExportInfo
->dwSize
> sizeof(data
.exportInfo
))
6774 data
.exportInfo
.dwSize
= sizeof(data
.exportInfo
);
6775 data
.contextInfo
.dwSize
= sizeof(data
.contextInfo
);
6776 data
.contextInfo
.dwExportFormat
= CRYPTUI_WIZ_EXPORT_FORMAT_DER
;
6777 data
.contextInfo
.fExportChain
= FALSE
;
6778 data
.contextInfo
.fStrongEncryption
= FALSE
;
6779 data
.contextInfo
.fExportPrivateKeys
= FALSE
;
6780 data
.contextInfo
.pwszPassword
= NULL
;
6781 data
.freePassword
= FALSE
;
6782 if (pExportInfo
->dwSubjectChoice
== CRYPTUI_WIZ_EXPORT_CERT_CONTEXT
&&
6784 memcpy(&data
.contextInfo
, pvoid
,
6785 min(((PCCRYPTUI_WIZ_EXPORT_CERTCONTEXT_INFO
)pvoid
)->dwSize
,
6786 sizeof(data
.contextInfo
)));
6787 data
.keyProvInfo
= NULL
;
6788 data
.deleteKeys
= FALSE
;
6789 data
.fileName
= NULL
;
6790 data
.file
= INVALID_HANDLE_VALUE
;
6791 data
.success
= FALSE
;
6793 memset(pages
, 0, sizeof(pages
));
6795 pages
[nPages
].dwSize
= sizeof(pages
[0]);
6796 pages
[nPages
].hInstance
= hInstance
;
6797 pages
[nPages
].pszTemplate
= MAKEINTRESOURCEW(IDD_EXPORT_WELCOME
);
6798 pages
[nPages
].pfnDlgProc
= export_welcome_dlg_proc
;
6799 pages
[nPages
].dwFlags
= PSP_HIDEHEADER
;
6800 pages
[nPages
].lParam
= (LPARAM
)&data
;
6803 hasPrivateKey
= export_info_has_private_key(pExportInfo
);
6804 switch (pExportInfo
->dwSubjectChoice
)
6806 case CRYPTUI_WIZ_EXPORT_CRL_CONTEXT
:
6807 case CRYPTUI_WIZ_EXPORT_CTL_CONTEXT
:
6808 showFormatPage
= FALSE
;
6809 data
.contextInfo
.dwExportFormat
= CRYPTUI_WIZ_EXPORT_FORMAT_DER
;
6811 case CRYPTUI_WIZ_EXPORT_CERT_STORE
:
6812 showFormatPage
= FALSE
;
6813 data
.contextInfo
.dwExportFormat
=
6814 CRYPTUI_WIZ_EXPORT_FORMAT_SERIALIZED_CERT_STORE
;
6816 case CRYPTUI_WIZ_EXPORT_CERT_STORE_CERTIFICATES_ONLY
:
6817 showFormatPage
= FALSE
;
6818 data
.contextInfo
.dwExportFormat
= CRYPTUI_WIZ_EXPORT_FORMAT_PKCS7
;
6822 if (hasPrivateKey
&& showFormatPage
)
6824 pages
[nPages
].dwSize
= sizeof(pages
[0]);
6825 pages
[nPages
].hInstance
= hInstance
;
6826 pages
[nPages
].pszTemplate
= MAKEINTRESOURCEW(IDD_EXPORT_PRIVATE_KEY
);
6827 pages
[nPages
].pfnDlgProc
= export_private_key_dlg_proc
;
6828 pages
[nPages
].dwFlags
= PSP_USEHEADERTITLE
| PSP_USEHEADERSUBTITLE
;
6829 pages
[nPages
].pszHeaderTitle
=
6830 MAKEINTRESOURCEW(IDS_EXPORT_PRIVATE_KEY_TITLE
);
6831 pages
[nPages
].pszHeaderSubTitle
=
6832 MAKEINTRESOURCEW(IDS_EXPORT_PRIVATE_KEY_SUBTITLE
);
6833 pages
[nPages
].lParam
= (LPARAM
)&data
;
6838 pages
[nPages
].dwSize
= sizeof(pages
[0]);
6839 pages
[nPages
].hInstance
= hInstance
;
6840 pages
[nPages
].pszTemplate
= MAKEINTRESOURCEW(IDD_EXPORT_FORMAT
);
6841 pages
[nPages
].pfnDlgProc
= export_format_dlg_proc
;
6842 pages
[nPages
].dwFlags
= PSP_USEHEADERTITLE
| PSP_USEHEADERSUBTITLE
;
6843 pages
[nPages
].pszHeaderTitle
=
6844 MAKEINTRESOURCEW(IDS_EXPORT_FORMAT_TITLE
);
6845 pages
[nPages
].pszHeaderSubTitle
=
6846 MAKEINTRESOURCEW(IDS_EXPORT_FORMAT_SUBTITLE
);
6847 pages
[nPages
].lParam
= (LPARAM
)&data
;
6850 if (hasPrivateKey
&& showFormatPage
)
6852 pages
[nPages
].dwSize
= sizeof(pages
[0]);
6853 pages
[nPages
].hInstance
= hInstance
;
6854 pages
[nPages
].pszTemplate
= MAKEINTRESOURCEW(IDD_EXPORT_PASSWORD
);
6855 pages
[nPages
].pfnDlgProc
= export_password_dlg_proc
;
6856 pages
[nPages
].dwFlags
= PSP_USEHEADERTITLE
| PSP_USEHEADERSUBTITLE
;
6857 pages
[nPages
].pszHeaderTitle
=
6858 MAKEINTRESOURCEW(IDS_EXPORT_PASSWORD_TITLE
);
6859 pages
[nPages
].pszHeaderSubTitle
=
6860 MAKEINTRESOURCEW(IDS_EXPORT_PASSWORD_SUBTITLE
);
6861 pages
[nPages
].lParam
= (LPARAM
)&data
;
6865 pages
[nPages
].dwSize
= sizeof(pages
[0]);
6866 pages
[nPages
].hInstance
= hInstance
;
6867 pages
[nPages
].pszTemplate
= MAKEINTRESOURCEW(IDD_EXPORT_FILE
);
6868 pages
[nPages
].pfnDlgProc
= export_file_dlg_proc
;
6869 pages
[nPages
].dwFlags
= PSP_USEHEADERTITLE
| PSP_USEHEADERSUBTITLE
;
6870 pages
[nPages
].pszHeaderTitle
= MAKEINTRESOURCEW(IDS_EXPORT_FILE_TITLE
);
6871 pages
[nPages
].pszHeaderSubTitle
=
6872 MAKEINTRESOURCEW(IDS_EXPORT_FILE_SUBTITLE
);
6873 pages
[nPages
].lParam
= (LPARAM
)&data
;
6876 pages
[nPages
].dwSize
= sizeof(pages
[0]);
6877 pages
[nPages
].hInstance
= hInstance
;
6878 pages
[nPages
].pszTemplate
= MAKEINTRESOURCEW(IDD_EXPORT_FINISH
);
6879 pages
[nPages
].pfnDlgProc
= export_finish_dlg_proc
;
6880 pages
[nPages
].dwFlags
= PSP_HIDEHEADER
;
6881 pages
[nPages
].lParam
= (LPARAM
)&data
;
6884 memset(&hdr
, 0, sizeof(hdr
));
6885 hdr
.dwSize
= sizeof(hdr
);
6886 hdr
.hwndParent
= hwndParent
;
6887 hdr
.dwFlags
= PSH_PROPSHEETPAGE
| PSH_WIZARD97_NEW
| PSH_HEADER
|
6889 hdr
.hInstance
= hInstance
;
6890 if (pwszWizardTitle
)
6891 hdr
.pszCaption
= pwszWizardTitle
;
6893 hdr
.pszCaption
= MAKEINTRESOURCEW(IDS_EXPORT_WIZARD
);
6895 hdr
.nPages
= nPages
;
6896 hdr
.pszbmWatermark
= MAKEINTRESOURCEW(IDB_CERT_WATERMARK
);
6897 hdr
.pszbmHeader
= MAKEINTRESOURCEW(IDB_CERT_HEADER
);
6898 l
= PropertySheetW(&hdr
);
6899 DeleteObject(data
.titleFont
);
6900 if (data
.freePassword
)
6901 free((WCHAR
*)data
.contextInfo
.pwszPassword
);
6902 free(data
.keyProvInfo
);
6903 CloseHandle(data
.file
);
6904 free(data
.fileName
);
6907 SetLastError(ERROR_CANCELLED
);
6911 return data
.success
;
6914 BOOL WINAPI
CryptUIWizExport(DWORD dwFlags
, HWND hwndParent
,
6915 LPCWSTR pwszWizardTitle
, PCCRYPTUI_WIZ_EXPORT_INFO pExportInfo
, void *pvoid
)
6919 TRACE("(%08lx, %p, %s, %p, %p)\n", dwFlags
, hwndParent
,
6920 debugstr_w(pwszWizardTitle
), pExportInfo
, pvoid
);
6922 if (!(dwFlags
& CRYPTUI_WIZ_NO_UI
))
6923 ret
= show_export_ui(dwFlags
, hwndParent
, pwszWizardTitle
, pExportInfo
,
6927 HANDLE file
= CreateFileW(pExportInfo
->pwszExportFileName
,
6928 GENERIC_WRITE
, FILE_SHARE_READ
| FILE_SHARE_WRITE
, NULL
,
6929 CREATE_ALWAYS
, 0, NULL
);
6931 if (file
!= INVALID_HANDLE_VALUE
)
6933 ret
= do_export(file
, pExportInfo
, pvoid
, NULL
, FALSE
);
6942 BOOL WINAPI
CryptUIDlgViewSignerInfoA(CRYPTUI_VIEWSIGNERINFO_STRUCTA
*pcvsi
)
6944 FIXME("%p: stub\n", pcvsi
);
6948 static void init_columns(HWND lv
, DWORD flags
)
6950 WCHAR buf
[MAX_STRING_LEN
];
6954 SendMessageW(lv
, LVM_SETEXTENDEDLISTVIEWSTYLE
, 0, LVS_EX_FULLROWSELECT
);
6955 column
.mask
= LVCF_WIDTH
| LVCF_TEXT
;
6957 column
.pszText
= buf
;
6958 if (!(flags
& CRYPTUI_SELECT_ISSUEDTO_COLUMN
))
6960 LoadStringW(hInstance
, IDS_SUBJECT_COLUMN
, buf
, ARRAY_SIZE(buf
));
6961 SendMessageW(lv
, LVM_INSERTCOLUMNW
, i
++, (LPARAM
)&column
);
6963 if (!(flags
& CRYPTUI_SELECT_ISSUEDBY_COLUMN
))
6965 LoadStringW(hInstance
, IDS_ISSUER_COLUMN
, buf
, ARRAY_SIZE(buf
));
6966 SendMessageW(lv
, LVM_INSERTCOLUMNW
, i
++, (LPARAM
)&column
);
6968 if (!(flags
& CRYPTUI_SELECT_INTENDEDUSE_COLUMN
))
6970 LoadStringW(hInstance
, IDS_INTENDED_USE_COLUMN
, buf
, ARRAY_SIZE(buf
));
6971 SendMessageW(lv
, LVM_INSERTCOLUMNW
, i
++, (LPARAM
)&column
);
6973 if (!(flags
& CRYPTUI_SELECT_FRIENDLYNAME_COLUMN
))
6975 LoadStringW(hInstance
, IDS_FRIENDLY_NAME_COLUMN
, buf
, ARRAY_SIZE(buf
));
6976 SendMessageW(lv
, LVM_INSERTCOLUMNW
, i
++, (LPARAM
)&column
);
6978 if (!(flags
& CRYPTUI_SELECT_EXPIRATION_COLUMN
))
6980 LoadStringW(hInstance
, IDS_EXPIRATION_COLUMN
, buf
, ARRAY_SIZE(buf
));
6981 SendMessageW(lv
, LVM_INSERTCOLUMNW
, i
++, (LPARAM
)&column
);
6983 if (!(flags
& CRYPTUI_SELECT_LOCATION_COLUMN
))
6985 LoadStringW(hInstance
, IDS_LOCATION_COLUMN
, buf
, ARRAY_SIZE(buf
));
6986 SendMessageW(lv
, LVM_INSERTCOLUMNW
, i
++, (LPARAM
)&column
);
6990 static void add_cert_to_list(HWND lv
, PCCERT_CONTEXT cert
, DWORD flags
, DWORD
*allocatedLen
,
6995 WCHAR dateFmt
[80]; /* sufficient for LOCALE_SSHORTDATE */
6998 LPWSTR none
, usages
;
7000 item
.mask
= LVIF_IMAGE
| LVIF_PARAM
| LVIF_TEXT
;
7001 item
.iItem
= SendMessageW(lv
, LVM_GETITEMCOUNT
, 0, 0);
7004 item
.lParam
= (LPARAM
)CertDuplicateCertificateContext(cert
);
7007 item
.mask
|= LVIF_STATE
;
7008 item
.state
= LVIS_SELECTED
;
7009 item
.stateMask
= -1;
7011 if (!(flags
& CRYPTUI_SELECT_ISSUEDTO_COLUMN
))
7013 len
= CertGetNameStringW(cert
, CERT_NAME_SIMPLE_DISPLAY_TYPE
, 0, NULL
, NULL
, 0);
7014 if (len
> *allocatedLen
)
7017 *str
= malloc(len
* sizeof(WCHAR
));
7019 *allocatedLen
= len
;
7023 CertGetNameStringW(cert
, CERT_NAME_SIMPLE_DISPLAY_TYPE
, 0, NULL
, *str
, len
);
7024 item
.pszText
= *str
;
7025 SendMessageW(lv
, LVM_INSERTITEMW
, 0, (LPARAM
)&item
);
7027 item
.mask
= LVIF_TEXT
;
7030 if (!(flags
& CRYPTUI_SELECT_ISSUEDBY_COLUMN
))
7032 len
= CertGetNameStringW(cert
, CERT_NAME_SIMPLE_DISPLAY_TYPE
, CERT_NAME_ISSUER_FLAG
, NULL
,
7034 if (len
> *allocatedLen
)
7037 *str
= malloc(len
* sizeof(WCHAR
));
7039 *allocatedLen
= len
;
7043 CertGetNameStringW(cert
, CERT_NAME_SIMPLE_DISPLAY_TYPE
, CERT_NAME_ISSUER_FLAG
, NULL
,
7045 item
.pszText
= *str
;
7047 SendMessageW(lv
, LVM_INSERTITEMW
, 0, (LPARAM
)&item
);
7049 SendMessageW(lv
, LVM_SETITEMTEXTW
, item
.iItem
, (LPARAM
)&item
);
7051 item
.mask
= LVIF_TEXT
;
7054 if (!(flags
& CRYPTUI_SELECT_INTENDEDUSE_COLUMN
))
7056 get_cert_usages(cert
, &usages
);
7059 item
.pszText
= usages
;
7061 SendMessageW(lv
, LVM_INSERTITEMW
, 0, (LPARAM
)&item
);
7063 SendMessageW(lv
, LVM_SETITEMTEXTW
, item
.iItem
, (LPARAM
)&item
);
7066 item
.mask
= LVIF_TEXT
;
7069 if (!(flags
& CRYPTUI_SELECT_FRIENDLYNAME_COLUMN
))
7071 if (!CertGetCertificateContextProperty(cert
, CERT_FRIENDLY_NAME_PROP_ID
, NULL
, &len
))
7072 len
= LoadStringW(hInstance
, IDS_FRIENDLY_NAME_NONE
, (LPWSTR
)&none
, 0);
7073 if (len
> *allocatedLen
)
7076 *str
= malloc(len
* sizeof(WCHAR
));
7078 *allocatedLen
= len
;
7082 if (!CertGetCertificateContextProperty(cert
, CERT_FRIENDLY_NAME_PROP_ID
, *str
, &len
))
7083 item
.pszText
= none
;
7085 item
.pszText
= *str
;
7087 SendMessageW(lv
, LVM_INSERTITEMW
, 0, (LPARAM
)&item
);
7089 SendMessageW(lv
, LVM_SETITEMTEXTW
, item
.iItem
, (LPARAM
)&item
);
7091 item
.mask
= LVIF_TEXT
;
7094 if (!(flags
& CRYPTUI_SELECT_EXPIRATION_COLUMN
))
7096 GetLocaleInfoW(LOCALE_SYSTEM_DEFAULT
, LOCALE_SSHORTDATE
, dateFmt
, ARRAY_SIZE(dateFmt
));
7097 FileTimeToSystemTime(&cert
->pCertInfo
->NotAfter
, &sysTime
);
7098 GetDateFormatW(LOCALE_SYSTEM_DEFAULT
, 0, &sysTime
, dateFmt
, buf
, ARRAY_SIZE(buf
));
7101 SendMessageW(lv
, LVM_INSERTITEMW
, 0, (LPARAM
)&item
);
7103 SendMessageW(lv
, LVM_SETITEMTEXTW
, item
.iItem
, (LPARAM
)&item
);
7104 item
.mask
= LVIF_TEXT
;
7107 if (!(flags
& CRYPTUI_SELECT_LOCATION_COLUMN
))
7109 static int show_fixme
;
7111 FIXME("showing location is not implemented\n");
7112 LoadStringW(hInstance
, IDS_NO_IMPL
, buf
, ARRAY_SIZE(buf
));
7114 SendMessageW(lv
, LVM_INSERTITEMW
, 0, (LPARAM
)&item
);
7116 SendMessageW(lv
, LVM_SETITEMTEXTW
, item
.iItem
, (LPARAM
)&item
);
7120 static void add_store_certs(HWND lv
, HCERTSTORE store
, DWORD flags
, PFNCFILTERPROC filter
,
7121 void *callback_data
)
7123 PCCERT_CONTEXT cert
= NULL
;
7124 BOOL select
= FALSE
;
7125 DWORD allocatedLen
= 0;
7129 cert
= CertEnumCertificatesInStore(store
, cert
);
7130 if (cert
&& (!filter
|| filter(cert
, &select
, callback_data
)))
7131 add_cert_to_list(lv
, cert
, flags
, &allocatedLen
, &str
);
7136 static PCCERT_CONTEXT
select_cert_get_selected(HWND hwnd
, int selection
)
7138 HWND lv
= GetDlgItem(hwnd
, IDC_SELECT_CERTS
);
7139 PCCERT_CONTEXT cert
= NULL
;
7143 selection
= SendMessageW(lv
, LVM_GETNEXTITEM
, -1, LVNI_SELECTED
);
7146 item
.mask
= LVIF_PARAM
;
7147 item
.iItem
= selection
;
7149 if (SendMessageW(lv
, LVM_GETITEMW
, 0, (LPARAM
)&item
))
7150 cert
= (PCCERT_CONTEXT
)item
.lParam
;
7154 static void select_cert_update_view_button(HWND hwnd
)
7156 HWND lv
= GetDlgItem(hwnd
, IDC_SELECT_CERTS
);
7157 int numSelected
= SendMessageW(lv
, LVM_GETSELECTEDCOUNT
, 0, 0);
7159 EnableWindow(GetDlgItem(hwnd
, IDC_SELECT_VIEW_CERT
), numSelected
== 1);
7162 struct SelectCertData
7164 PCCERT_CONTEXT
*cert
;
7166 HIMAGELIST imageList
;
7169 HCERTSTORE
*rghStores
;
7170 DWORD cPropSheetPages
;
7171 LPCPROPSHEETPAGEW rgPropSheetPages
;
7172 PFNCCERTDISPLAYPROC displayProc
;
7176 static void select_cert_view(HWND hwnd
, PCCERT_CONTEXT cert
, struct SelectCertData
*data
)
7178 CRYPTUI_VIEWCERTIFICATE_STRUCTW viewInfo
;
7180 if (data
->displayProc
&& data
->displayProc(cert
, hwnd
, data
->callbackData
))
7182 memset(&viewInfo
, 0, sizeof(viewInfo
));
7183 viewInfo
.dwSize
= sizeof(viewInfo
);
7184 viewInfo
.hwndParent
= hwnd
;
7185 viewInfo
.pCertContext
= cert
;
7186 viewInfo
.cStores
= data
->cStores
;
7187 viewInfo
.rghStores
= data
->rghStores
;
7188 viewInfo
.cPropSheetPages
= data
->cPropSheetPages
;
7189 viewInfo
.rgPropSheetPages
= data
->rgPropSheetPages
;
7190 /* FIXME: this should be modal */
7191 CryptUIDlgViewCertificateW(&viewInfo
, NULL
);
7200 static int CALLBACK
select_cert_sort_by_text(LPARAM lp1
, LPARAM lp2
, LPARAM lp
)
7202 struct SortData
*data
= (struct SortData
*)lp
;
7203 return cert_mgr_sort_by_text(data
->hwnd
, data
->column
, lp1
, lp2
);
7206 struct SelectCertParam
7208 PCCRYPTUI_SELECTCERTIFICATE_STRUCTW pcsc
;
7209 PCCERT_CONTEXT cert
;
7212 static INT_PTR CALLBACK
select_cert_dlg_proc(HWND hwnd
, UINT msg
, WPARAM wp
, LPARAM lp
)
7214 struct SelectCertData
*data
;
7220 struct SelectCertParam
*param
= (struct SelectCertParam
*)lp
;
7221 PCCRYPTUI_SELECTCERTIFICATE_STRUCTW pcsc
= param
->pcsc
;
7222 HWND lv
= GetDlgItem(hwnd
, IDC_SELECT_CERTS
);
7225 data
= malloc(sizeof(*data
));
7228 data
->cert
= ¶m
->cert
;
7229 data
->dateColumn
= 4 -
7230 ((pcsc
->dwDontUseColumn
& CRYPTUI_SELECT_ISSUEDTO_COLUMN
) ? 1 : 0) -
7231 ((pcsc
->dwDontUseColumn
& CRYPTUI_SELECT_ISSUEDBY_COLUMN
) ? 1 : 0) -
7232 ((pcsc
->dwDontUseColumn
& CRYPTUI_SELECT_INTENDEDUSE_COLUMN
) ? 1 : 0) -
7233 ((pcsc
->dwDontUseColumn
& CRYPTUI_SELECT_FRIENDLYNAME_COLUMN
) ? 1 : 0);
7234 data
->imageList
= ImageList_Create(16, 16, ILC_COLOR4
| ILC_MASK
, 2, 0);
7235 if (data
->imageList
)
7238 COLORREF backColor
= RGB(255, 0, 255);
7240 bmp
= LoadBitmapW(hInstance
, MAKEINTRESOURCEW(IDB_SMALL_ICONS
));
7241 ImageList_AddMasked(data
->imageList
, bmp
, backColor
);
7243 ImageList_SetBkColor(data
->imageList
, CLR_NONE
);
7244 SendMessageW(GetDlgItem(hwnd
, IDC_SELECT_CERTS
), LVM_SETIMAGELIST
, LVSIL_SMALL
,
7245 (LPARAM
)data
->imageList
);
7247 data
->title
= pcsc
->szTitle
;
7248 data
->cStores
= pcsc
->cStores
;
7249 data
->rghStores
= pcsc
->rghStores
;
7250 data
->cPropSheetPages
= pcsc
->cPropSheetPages
;
7251 data
->rgPropSheetPages
= pcsc
->rgPropSheetPages
;
7252 data
->displayProc
= pcsc
->pDisplayCallback
;
7253 data
->callbackData
= pcsc
->pvCallbackData
;
7254 SetWindowLongPtrW(hwnd
, DWLP_USER
, (LPARAM
)data
);
7257 SendMessageW(hwnd
, WM_SETTEXT
, 0, (LPARAM
)pcsc
->szTitle
);
7258 if (pcsc
->szDisplayString
)
7259 SendMessageW(GetDlgItem(hwnd
, IDC_SELECT_DISPLAY_STRING
), WM_SETTEXT
, 0,
7260 (LPARAM
)pcsc
->szDisplayString
);
7261 init_columns(lv
, pcsc
->dwDontUseColumn
);
7262 while (i
< pcsc
->cDisplayStores
)
7263 add_store_certs(lv
, pcsc
->rghDisplayStores
[i
++], pcsc
->dwDontUseColumn
,
7264 pcsc
->pFilterCallback
, pcsc
->pvCallbackData
);
7265 select_cert_update_view_button(hwnd
);
7270 NMHDR
*hdr
= (NMHDR
*)lp
;
7276 PCCERT_CONTEXT cert
= select_cert_get_selected(hwnd
, ((NMITEMACTIVATE
*)lp
)->iItem
);
7278 data
= (struct SelectCertData
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
7280 select_cert_view(hwnd
, cert
, data
);
7283 case LVN_COLUMNCLICK
:
7285 NMLISTVIEW
*nmlv
= (NMLISTVIEW
*)lp
;
7286 HWND lv
= GetDlgItem(hwnd
, IDC_SELECT_CERTS
);
7288 /* FIXME: doesn't support swapping sort order between ascending and descending. */
7289 data
= (struct SelectCertData
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
7290 if (nmlv
->iSubItem
== data
->dateColumn
)
7291 SendMessageW(lv
, LVM_SORTITEMS
, 0, (LPARAM
)cert_mgr_sort_by_date
);
7294 struct SortData sortData
;
7297 sortData
.column
= nmlv
->iSubItem
;
7298 SendMessageW(lv
, LVM_SORTITEMSEX
, (WPARAM
)&sortData
,
7299 (LPARAM
)select_cert_sort_by_text
);
7311 PCCERT_CONTEXT cert
= select_cert_get_selected(hwnd
, -1);
7313 data
= (struct SelectCertData
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
7316 WCHAR buf
[40], title
[40];
7318 LoadStringW(hInstance
, IDS_SELECT_CERT
, buf
, ARRAY_SIZE(buf
));
7320 LoadStringW(hInstance
, IDS_SELECT_CERT_TITLE
, title
, ARRAY_SIZE(title
));
7321 MessageBoxW(hwnd
, buf
, data
->title
? data
->title
: title
, MB_OK
| MB_ICONWARNING
);
7324 *data
->cert
= CertDuplicateCertificateContext(cert
);
7325 free_certs(GetDlgItem(hwnd
, IDC_SELECT_CERTS
));
7326 ImageList_Destroy(data
->imageList
);
7328 EndDialog(hwnd
, IDOK
);
7332 data
= (struct SelectCertData
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
7333 free_certs(GetDlgItem(hwnd
, IDC_SELECT_CERTS
));
7334 ImageList_Destroy(data
->imageList
);
7336 EndDialog(hwnd
, IDCANCEL
);
7338 case IDC_SELECT_VIEW_CERT
:
7340 PCCERT_CONTEXT cert
= select_cert_get_selected(hwnd
, -1);
7342 data
= (struct SelectCertData
*)GetWindowLongPtrW(hwnd
, DWLP_USER
);
7344 select_cert_view(hwnd
, cert
, data
);
7353 PCCERT_CONTEXT WINAPI
CryptUIDlgSelectCertificateW(PCCRYPTUI_SELECTCERTIFICATE_STRUCTW pcsc
)
7355 struct SelectCertParam param
;
7357 TRACE("%p\n", pcsc
);
7359 if (pcsc
->dwSize
!= sizeof(*pcsc
) && pcsc
->dwSize
!= sizeof(*pcsc
) - sizeof(HCERTSTORE
))
7361 WARN("unexpected size %ld\n", pcsc
->dwSize
);
7362 SetLastError(E_INVALIDARG
);
7365 if (pcsc
->dwFlags
& CRYPTUI_SELECTCERT_MULTISELECT
)
7366 FIXME("ignoring CRYPTUI_SELECTCERT_MULTISELECT\n");
7369 DialogBoxParamW(hInstance
, MAKEINTRESOURCEW(IDD_SELECT_CERT
), pcsc
->hwndParent
,
7370 select_cert_dlg_proc
, (LPARAM
)¶m
);
7374 static void free_prop_sheet_pages(PROPSHEETPAGEW
*pages
, DWORD num
)
7378 for (i
= 0; i
< num
; i
++)
7380 if (!(pages
[i
].dwFlags
& PSP_DLGINDIRECT
) && !IS_INTRESOURCE(pages
[i
].pszTemplate
))
7381 free((void *)pages
[i
].pszTemplate
);
7382 if ((pages
[i
].dwFlags
& PSP_USEICONID
) && !IS_INTRESOURCE(pages
[i
].pszIcon
))
7383 free((void *)pages
[i
].pszIcon
);
7384 if ((pages
[i
].dwFlags
& PSP_USETITLE
) && !IS_INTRESOURCE(pages
[i
].pszTitle
))
7385 free((void *)pages
[i
].pszTitle
);
7386 if ((pages
[i
].dwFlags
& PSP_USEHEADERTITLE
) && !IS_INTRESOURCE(pages
[i
].pszHeaderTitle
))
7387 free((void *)pages
[i
].pszHeaderTitle
);
7388 if ((pages
[i
].dwFlags
& PSP_USEHEADERSUBTITLE
) &&
7389 !IS_INTRESOURCE(pages
[i
].pszHeaderSubTitle
))
7390 free((void *)pages
[i
].pszHeaderSubTitle
);
7395 static PROPSHEETPAGEW
*prop_sheet_pages_AtoW(LPCPROPSHEETPAGEA pages
, DWORD num
)
7397 PROPSHEETPAGEW
*psp
;
7398 DWORD i
, size
= sizeof(*psp
) * num
;
7403 memcpy(psp
, pages
, size
);
7404 for (i
= 0; i
< num
; i
++)
7406 if (!(pages
[i
].dwFlags
& PSP_DLGINDIRECT
) && !IS_INTRESOURCE(pages
[i
].pszTemplate
))
7407 psp
[i
].pszTemplate
= NULL
;
7408 if ((pages
[i
].dwFlags
& PSP_USEICONID
) && !IS_INTRESOURCE(pages
[i
].pszIcon
))
7409 psp
[i
].pszIcon
= NULL
;
7410 if ((pages
[i
].dwFlags
& PSP_USETITLE
) && !IS_INTRESOURCE(pages
[i
].pszTitle
))
7411 psp
[i
].pszTitle
= NULL
;
7412 if (pages
[i
].dwFlags
& PSP_USECALLBACK
)
7413 psp
[i
].pfnCallback
= NULL
;
7414 if ((pages
[i
].dwFlags
& PSP_USEHEADERTITLE
) && !IS_INTRESOURCE(pages
[i
].pszHeaderTitle
))
7415 psp
[i
].pszHeaderTitle
= NULL
;
7416 if ((pages
[i
].dwFlags
& PSP_USEHEADERSUBTITLE
) &&
7417 !IS_INTRESOURCE(pages
[i
].pszHeaderSubTitle
))
7418 psp
[i
].pszHeaderSubTitle
= NULL
;
7420 for (i
= 0; i
< num
; i
++)
7422 if (!(pages
[i
].dwFlags
& PSP_DLGINDIRECT
) && !IS_INTRESOURCE(pages
[i
].pszTemplate
))
7424 if (!(psp
[i
].pszTemplate
= strdupAtoW( pages
[i
].pszTemplate
))) goto error
;
7426 if ((pages
[i
].dwFlags
& PSP_USEICONID
) && !IS_INTRESOURCE(pages
[i
].pszIcon
))
7428 if (!(psp
[i
].pszIcon
= strdupAtoW( pages
[i
].pszIcon
))) goto error
;
7430 if ((pages
[i
].dwFlags
& PSP_USETITLE
) && !IS_INTRESOURCE(pages
[i
].pszTitle
))
7432 if (!(psp
[i
].pszTitle
= strdupAtoW( pages
[i
].pszTitle
))) goto error
;
7434 if (pages
[i
].dwFlags
& PSP_USECALLBACK
)
7435 FIXME("ignoring pfnCallback\n");
7436 if ((pages
[i
].dwFlags
& PSP_USEHEADERTITLE
) && !IS_INTRESOURCE(pages
[i
].pszHeaderTitle
))
7438 if (!(psp
[i
].pszHeaderTitle
= strdupAtoW( pages
[i
].pszHeaderTitle
))) goto error
;
7440 if ((pages
[i
].dwFlags
& PSP_USEHEADERSUBTITLE
) &&
7441 !IS_INTRESOURCE(pages
[i
].pszHeaderSubTitle
))
7443 if (!(psp
[i
].pszHeaderSubTitle
= strdupAtoW( pages
[i
].pszHeaderSubTitle
))) goto error
;
7448 free_prop_sheet_pages(psp
, num
);
7452 PCCERT_CONTEXT WINAPI
CryptUIDlgSelectCertificateA(PCCRYPTUI_SELECTCERTIFICATE_STRUCTA pcsc
)
7454 PCCERT_CONTEXT cert
= NULL
;
7455 CRYPTUI_SELECTCERTIFICATE_STRUCTW selCertInfo
;
7456 LPWSTR title
= NULL
, display_str
= NULL
;
7457 PROPSHEETPAGEW
*pages
= NULL
;
7459 TRACE("%p\n", pcsc
);
7461 if (pcsc
->dwSize
!= sizeof(*pcsc
) && pcsc
->dwSize
!= sizeof(*pcsc
) - sizeof(HCERTSTORE
))
7463 WARN("unexpected size %ld\n", pcsc
->dwSize
);
7464 SetLastError(E_INVALIDARG
);
7467 memcpy(&selCertInfo
, pcsc
, pcsc
->dwSize
);
7470 if (!(title
= strdupAtoW( pcsc
->szTitle
))) goto error
;
7471 selCertInfo
.szTitle
= title
;
7473 if (pcsc
->szDisplayString
)
7475 if (!(display_str
= strdupAtoW( pcsc
->szDisplayString
))) goto error
;
7476 selCertInfo
.szDisplayString
= display_str
;
7478 if (pcsc
->cPropSheetPages
)
7480 pages
= prop_sheet_pages_AtoW(pcsc
->rgPropSheetPages
, pcsc
->cPropSheetPages
);
7483 selCertInfo
.rgPropSheetPages
= pages
;
7485 cert
= CryptUIDlgSelectCertificateW(&selCertInfo
);
7489 if (pcsc
->cPropSheetPages
)
7490 free_prop_sheet_pages(pages
, pcsc
->cPropSheetPages
);
7494 PCCERT_CONTEXT WINAPI
CryptUIDlgSelectCertificateFromStore(HCERTSTORE hCertStore
, HWND hwnd
, LPCWSTR pwszTitle
,
7495 LPCWSTR pwszDisplayString
, DWORD dwDontUseColumn
,
7496 DWORD dwFlags
, void *pvReserved
)
7498 CRYPTUI_SELECTCERTIFICATE_STRUCTW sc
;
7500 TRACE("%p %p %s %s %lx %lx %p\n", hCertStore
, hwnd
, debugstr_w(pwszTitle
), debugstr_w(pwszDisplayString
), dwDontUseColumn
, dwFlags
, pvReserved
);
7502 memset(&sc
, 0, sizeof(sc
));
7504 sc
.dwSize
= sizeof(sc
);
7505 sc
.hwndParent
= hwnd
;
7506 sc
.dwFlags
= dwFlags
;
7507 sc
.szTitle
= pwszTitle
;
7508 sc
.szDisplayString
= pwszDisplayString
;
7509 sc
.dwDontUseColumn
= dwDontUseColumn
;
7510 sc
.cDisplayStores
= 1;
7511 sc
.rghDisplayStores
= &hCertStore
;
7512 return CryptUIDlgSelectCertificateW(&sc
);
7515 BOOL WINAPI
CryptUIWizDigitalSign(DWORD flags
, HWND parent
, LPCWSTR title
, PCCRYPTUI_WIZ_DIGITAL_SIGN_INFO info
,
7516 PCCRYPTUI_WIZ_DIGITAL_SIGN_CONTEXT
*context
)
7518 FIXME("%ld %p %s %p %p: stub\n", flags
, parent
, debugstr_w(title
), info
, context
);